npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

tinkerdesk-types

v0.2.2

Published

TinkerDesk 开发者类型定义包——工具/提供者/应用/应用 SDK 对外扩展类型约束(纯类型声明)

Readme

tinkerdesk-types

TinkerDesk 开发者类型定义包 —— 所有对外扩展面的类型约束唯一定义处(纯类型声明,零运行时)。

| 扩展面 | 包名前缀 | 入口类型 | |---|---|---| | 工具 | tinkerdesk-tool-* / 应用包内 tools/<name>/ | IAgentTool | | 能力提供者 | tinkerdesk-provider-* | TinkerProvider | | 应用 | tinkerdesk-app-* | AppManifest | | 应用 SDK(运行时能力) | 应用内的工具与前端页面 | AppSdk(工具侧 ctx.app)/ TinkerAppSdk(window.tinkerApp) |

安装

npm i -D tinkerdesk-types

TypeScript 项目直接 import type { … } from 'tinkerdesk-types'。 纯 JS 应用把类型写到 JSDoc 里,并在文件头加一行引用即可吃到补全:

// @ts-check
/// <reference types="tinkerdesk-types" />

工具

工具实现侧自包含(只用 Node 标准库即可)。入口模块导出默认实例,或导出 tool 字段。

import type { IAgentTool, ToolSchema, ToolResult, ToolContext } from 'tinkerdesk-types';

class MyTool implements IAgentTool {
  getSchema(): ToolSchema {
    return {
      name: 'my_tool',
      description: '一句话说明这个工具做什么',
      parameters: { type: 'object', properties: { node: { type: 'string' } } },
      toFunctionCallingFormat() {
        return { type: 'function', function: { name: 'my_tool', description: '…', parameters: {} } };
      },
    };
  }

  async execute(ctx: ToolContext): Promise<ToolResult> {
    const { node } = ctx.toolCall.arguments;   // LLM 传入的参数
    return { async: false, result: `done: ${String(node)}` };
  }
}

export default new MyTool();

包内 manifest.json(type: "tool"):

{
  "id": "my-tool",
  "entry": "dist/index.js",
  "apiVersion": 1,
  "type": "tool",
  "tool": { "name": "my_tool", "displayName": "我的工具", "description": "…", "categories": ["utility"] }
}

能力提供者

一个类 = 一个扩展的完整生命体:静态声明走包内 manifest.json,运行时走 init / check / start / stop / dispose。

import type { TinkerProvider, ProviderContext, ProviderCheckResult } from 'tinkerdesk-types';

export default class MyProvider implements TinkerProvider {
  async init(ctx: ProviderContext): Promise<void> {
    ctx.registerIpc('run', (payload) => ({ ok: true, payload }));
  }
  async check(): Promise<ProviderCheckResult> {
    return { ok: true, checks: [{ name: '依赖可用', ok: true }] };
  }
  async start(): Promise<void> {}
  async stop(): Promise<void> {}
  async dispose(): Promise<void> {}
}

应用

manifest.json 是平台对该应用的唯一静态声明(type: "app")。

{
  "id": "my-app",
  "name": "我的工作台",
  "version": "0.1.0",
  "apiVersion": 1,
  "type": "app",
  "ui": { "entry": "ui/index.html" },
  "configSchema": {
    "required": ["baseUrl"],
    "properties": {
      "baseUrl": { "type": "string", "title": "后端基址", "default": "http://127.0.0.1:4399" },
      "apiToken": { "type": "secret", "title": "访问令牌" },
      "greeting": { "type": "string", "title": "默认问候语", "default": "你好" }
    }
  },
  "vocation": { "displayName": "问候", "prompt": "prompts/vocation.hbs" },
  "skills": [{ "name": "style", "path": "skills/style.md" }],
  "prompts": [{ "name": "tone", "path": "prompts/tone.hbs" }]
}

应用 SDK(运行时能力)

应用不直连自己的后端:能力由平台在主进程执行(拼基址 + 注入 X-TinkerDesk-App / X-TinkerDesk-Token); 应用只允许打自己的基址,令牌永远拿不到——配置里的 secret 对应用一律掩码为 '***'。

两条腿同一形状:能力名 = 属性名,方法 = 命名方法。

工具侧(ctx.app,仅 app_<appId>_* 工具带):

import type { ToolContext, HttpResponse } from 'tinkerdesk-types';

export async function execute(ctx: ToolContext) {
  const res: HttpResponse = await ctx.app!.http.request({
    path: `/nodes/${String(ctx.toolCall.arguments.node)}`,
    method: 'PATCH',
    body: { text: '改短的正文' },
  });
  return { async: false, result: res.body };
}

webview 侧(window.tinkerApp,类型由包里的 declare global 自动带上):

const res = await window.tinkerApp.http.request({ path: '/hello' });

失败时抛出的错误对象带 code(CapabilityErrorCode):UNKNOWN_CAPABILITY / SURFACE_DENIED / MISSING_CONFIG / BAD_REQUEST / UPSTREAM_ERROR。MISSING_CONFIG 表示所需配置项还没在应用设置里填。

版本

| 版本 | 变更 | |---|---| | 0.2.2 | 去掉 "type": "module"(纯类型包无需 ESM 标记;CJS 消费者 import type 不再报 TS1541) | | 0.2.1 | 应用 manifest 去掉 backend(默认基址写进 configSchema 的 default);令牌字段统一为 apiToken,与 baseUrl 一起列为系统预留配置键(必须在 configSchema 里声明) | | 0.2.0 | 包类型字段统一为 type(原 kind);应用 manifest 对齐现模型(ui.entry / backend.baseUrl / vocation 单数 / configSchema);新增 sdk(AppSdk / TinkerAppSdk / HttpRequest / HttpResponse / CapabilityErrorCode);provider 补 dispose()、ProviderCheckResult.checks;tool 的 check 允许 boolean、ToolContext 补 app | | 0.1.1 | provider 只保留根契约(去掉业务封装类型) | | 0.1.0 | 首版(tool / provider / app) |