@anionex/dsh-tool-search 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -0
- package/LICENSE +21 -0
- package/README.md +160 -0
- package/README.zh.md +160 -0
- package/cordis.patch.yml +3 -0
- package/docs/benchmark-results.json +51 -0
- package/lib/bm25.js +83 -0
- package/lib/bm25.js.map +1 -0
- package/lib/catalog.js +53 -0
- package/lib/catalog.js.map +1 -0
- package/lib/client.js +388 -0
- package/lib/client.js.map +1 -0
- package/lib/index.js +24 -0
- package/lib/index.js.map +1 -0
- package/lib/runtime.js +286 -0
- package/lib/runtime.js.map +1 -0
- package/lib/settings.js +50 -0
- package/lib/settings.js.map +1 -0
- package/lib/shared.js +40 -0
- package/lib/shared.js.map +1 -0
- package/lib/types/bm25.d.ts +20 -0
- package/lib/types/bm25.d.ts.map +1 -0
- package/lib/types/catalog.d.ts +26 -0
- package/lib/types/catalog.d.ts.map +1 -0
- package/lib/types/client/index.d.ts +65 -0
- package/lib/types/client/index.d.ts.map +1 -0
- package/lib/types/index.d.ts +14 -0
- package/lib/types/index.d.ts.map +1 -0
- package/lib/types/runtime.d.ts +37 -0
- package/lib/types/runtime.d.ts.map +1 -0
- package/lib/types/settings.d.ts +16 -0
- package/lib/types/settings.d.ts.map +1 -0
- package/lib/types/shared.d.ts +31 -0
- package/lib/types/shared.d.ts.map +1 -0
- package/lib/types/web.d.ts +5 -0
- package/lib/types/web.d.ts.map +1 -0
- package/lib/web.js +28 -0
- package/lib/web.js.map +1 -0
- package/package.json +149 -0
- package/pnpm-workspace.yaml +11 -0
- package/scripts/benchmark.mjs +124 -0
- package/scripts/profile-e2e.mjs +366 -0
- package/scripts/validate.mjs +170 -0
- package/src/bm25.ts +104 -0
- package/src/catalog.ts +72 -0
- package/src/client/index.tsx +344 -0
- package/src/index.ts +32 -0
- package/src/runtime.ts +326 -0
- package/src/settings.ts +63 -0
- package/src/shared.ts +63 -0
- package/src/web.ts +34 -0
- package/src/wink-porter2-stemmer.d.ts +3 -0
- package/tests/bm25.spec.ts +75 -0
- package/tests/catalog.spec.ts +63 -0
- package/tests/client.spec.tsx +39 -0
- package/tests/execution-regression.spec.ts +200 -0
- package/tests/runtime.spec.ts +271 -0
- package/tests/settings.spec.ts +33 -0
- package/tsconfig.client.json +31 -0
- package/tsconfig.json +30 -0
- package/tsconfig.test.json +23 -0
- package/tsdown.config.mjs +37 -0
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/** Values shared by the Host runtime and Web settings client. */
|
|
2
|
+
export declare const TOOL_SEARCH_NAME = "tool_search";
|
|
3
|
+
export declare const TOOL_SEARCH_SETTINGS_NAMESPACE = "tool-search";
|
|
4
|
+
export declare const TOOL_SEARCH_CATALOG_ROUTE = "/_dsh/tool-search/catalog";
|
|
5
|
+
export declare const DEFAULT_RESULT_LIMIT = 5;
|
|
6
|
+
export declare const MAX_RESULT_LIMIT = 20;
|
|
7
|
+
/**
|
|
8
|
+
* Stable bootstrap surface for current DSH releases. Unknown future first-party
|
|
9
|
+
* names are deferred until this list or the user allowlist is updated because
|
|
10
|
+
* ToolDefinition does not expose package provenance.
|
|
11
|
+
*/
|
|
12
|
+
export declare const DEFAULT_CORE_TOOLS: readonly ["apply_patch", "ask_user_question", "bash", "create_goal", "dsh_im_return_file", "exit_plan_mode", "get_goal", "interrupt_agent", "job_kill", "job_list", "job_output", "list_agents", "ralph", "report", "send_message", "skill", "subagent", "subagent_fork", "todo_write", "update_goal", "workflow"];
|
|
13
|
+
export interface ToolSearchSettings {
|
|
14
|
+
defaultLimit: number;
|
|
15
|
+
alwaysVisible: string[];
|
|
16
|
+
neverSearch: string[];
|
|
17
|
+
}
|
|
18
|
+
export declare const DEFAULT_SETTINGS: Readonly<ToolSearchSettings>;
|
|
19
|
+
export type ToolPolicy = 'always' | 'deferred' | 'blocked';
|
|
20
|
+
export interface CatalogToolSummary {
|
|
21
|
+
name: string;
|
|
22
|
+
description: string;
|
|
23
|
+
policy: ToolPolicy;
|
|
24
|
+
selectedBy: string[];
|
|
25
|
+
}
|
|
26
|
+
export interface CatalogSnapshot {
|
|
27
|
+
schemaVersion: 1;
|
|
28
|
+
generation: number;
|
|
29
|
+
tools: CatalogToolSummary[];
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=shared.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shared.d.ts","sourceRoot":"","sources":["../../src/shared.ts"],"names":[],"mappings":"AAAA,iEAAiE;AAEjE,eAAO,MAAM,gBAAgB,gBAAgB,CAAA;AAC7C,eAAO,MAAM,8BAA8B,gBAAgB,CAAA;AAC3D,eAAO,MAAM,yBAAyB,8BAA8B,CAAA;AACpE,eAAO,MAAM,oBAAoB,IAAI,CAAA;AACrC,eAAO,MAAM,gBAAgB,KAAK,CAAA;AAElC;;;;GAIG;AACH,eAAO,MAAM,kBAAkB,oTAsBpB,CAAA;AAEX,MAAM,WAAW,kBAAkB;IACjC,YAAY,EAAE,MAAM,CAAA;IACpB,aAAa,EAAE,MAAM,EAAE,CAAA;IACvB,WAAW,EAAE,MAAM,EAAE,CAAA;CACtB;AAED,eAAO,MAAM,gBAAgB,EAAE,QAAQ,CAAC,kBAAkB,CAIxD,CAAA;AAEF,MAAM,MAAM,UAAU,GAAG,QAAQ,GAAG,UAAU,GAAG,SAAS,CAAA;AAE1D,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,EAAE,MAAM,CAAA;IACnB,MAAM,EAAE,UAAU,CAAA;IAClB,UAAU,EAAE,MAAM,EAAE,CAAA;CACrB;AAED,MAAM,WAAW,eAAe;IAC9B,aAAa,EAAE,CAAC,CAAA;IAChB,UAAU,EAAE,MAAM,CAAA;IAClB,KAAK,EAAE,kBAAkB,EAAE,CAAA;CAC5B"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
/** Read-only live catalog endpoint for the Web settings page. */
|
|
2
|
+
import type { Context } from '@deepseek-ai/cordis';
|
|
3
|
+
import type { ToolSearchRuntime } from './runtime.ts';
|
|
4
|
+
export declare function installCatalogRoute(ctx: Context, runtime: ToolSearchRuntime): void;
|
|
5
|
+
//# sourceMappingURL=web.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"web.d.ts","sourceRoot":"","sources":["../../src/web.ts"],"names":[],"mappings":"AAAA,iEAAiE;AAGjE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAGlD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAA;AAYrD,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,OAAO,EAAE,OAAO,EAAE,iBAAiB,GAAG,IAAI,CAelF"}
|
package/lib/web.js
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/** Read-only live catalog endpoint for the Web settings page. */
|
|
2
|
+
import { TOOL_SEARCH_CATALOG_ROUTE } from "./shared.js";
|
|
3
|
+
function sendJson(res, status, value) {
|
|
4
|
+
const body = Buffer.from(JSON.stringify(value));
|
|
5
|
+
res.setHeader('Content-Type', 'application/json; charset=utf-8');
|
|
6
|
+
res.setHeader('Content-Length', String(body.length));
|
|
7
|
+
res.setHeader('Cache-Control', 'no-store');
|
|
8
|
+
res.setHeader('X-Content-Type-Options', 'nosniff');
|
|
9
|
+
res.writeHead(status);
|
|
10
|
+
res.end(body);
|
|
11
|
+
}
|
|
12
|
+
export function installCatalogRoute(ctx, runtime) {
|
|
13
|
+
ctx.inject(['webServer'], webCtx => {
|
|
14
|
+
webCtx.effect(() => webCtx.webServer.register({
|
|
15
|
+
kind: 'exact',
|
|
16
|
+
path: TOOL_SEARCH_CATALOG_ROUTE,
|
|
17
|
+
handler: (req, res) => {
|
|
18
|
+
if (req.method !== 'GET') {
|
|
19
|
+
res.setHeader('Allow', 'GET');
|
|
20
|
+
sendJson(res, 405, { error: 'method-not-allowed' });
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
sendJson(res, 200, runtime.snapshot());
|
|
24
|
+
},
|
|
25
|
+
}), 'dsh-tool-search: Web catalog route');
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=web.js.map
|
package/lib/web.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"web.js","sourceRoot":"","sources":["../src/web.ts"],"names":[],"mappings":"AAAA,iEAAiE;AAKjE,OAAO,EAAE,yBAAyB,EAAE,MAAM,aAAa,CAAA;AAGvD,SAAS,QAAQ,CAAC,GAAmB,EAAE,MAAc,EAAE,KAAc;IACnE,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAA;IAC/C,GAAG,CAAC,SAAS,CAAC,cAAc,EAAE,iCAAiC,CAAC,CAAA;IAChE,GAAG,CAAC,SAAS,CAAC,gBAAgB,EAAE,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAA;IACpD,GAAG,CAAC,SAAS,CAAC,eAAe,EAAE,UAAU,CAAC,CAAA;IAC1C,GAAG,CAAC,SAAS,CAAC,wBAAwB,EAAE,SAAS,CAAC,CAAA;IAClD,GAAG,CAAC,SAAS,CAAC,MAAM,CAAC,CAAA;IACrB,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;AACf,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,GAAY,EAAE,OAA0B;IAC1E,GAAG,CAAC,MAAM,CAAC,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC,EAAE;QACjC,MAAM,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC;YAC5C,IAAI,EAAE,OAAO;YACb,IAAI,EAAE,yBAAyB;YAC/B,OAAO,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE;gBACpB,IAAI,GAAG,CAAC,MAAM,KAAK,KAAK,EAAE,CAAC;oBACzB,GAAG,CAAC,SAAS,CAAC,OAAO,EAAE,KAAK,CAAC,CAAA;oBAC7B,QAAQ,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,KAAK,EAAE,oBAAoB,EAAE,CAAC,CAAA;oBACnD,OAAM;gBACR,CAAC;gBACD,QAAQ,CAAC,GAAG,EAAE,GAAG,EAAE,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAA;YACxC,CAAC;SACF,CAAC,EAAE,oCAAoC,CAAC,CAAA;IAC3C,CAAC,CAAC,CAAA;AACJ,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@anionex/dsh-tool-search",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Codex-style deferred tool loading for DSH with deterministic local BM25 search",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"deepseek",
|
|
7
|
+
"deepseek-harness",
|
|
8
|
+
"tool-search",
|
|
9
|
+
"deferred-loading",
|
|
10
|
+
"bm25"
|
|
11
|
+
],
|
|
12
|
+
"repository": {
|
|
13
|
+
"type": "git",
|
|
14
|
+
"url": "git+https://github.com/Anionex/dsh-tool-search.git"
|
|
15
|
+
},
|
|
16
|
+
"bugs": {
|
|
17
|
+
"url": "https://github.com/Anionex/dsh-tool-search/issues"
|
|
18
|
+
},
|
|
19
|
+
"homepage": "https://github.com/Anionex/dsh-tool-search#readme",
|
|
20
|
+
"type": "module",
|
|
21
|
+
"packageManager": "pnpm@11.8.0",
|
|
22
|
+
"engines": {
|
|
23
|
+
"node": "^22.19.0 || >=24.0.0"
|
|
24
|
+
},
|
|
25
|
+
"main": "./lib/index.js",
|
|
26
|
+
"types": "./lib/types/index.d.ts",
|
|
27
|
+
"exports": {
|
|
28
|
+
".": {
|
|
29
|
+
"types": "./lib/types/index.d.ts",
|
|
30
|
+
"default": "./lib/index.js"
|
|
31
|
+
},
|
|
32
|
+
"./bm25": {
|
|
33
|
+
"types": "./lib/types/bm25.d.ts",
|
|
34
|
+
"default": "./lib/bm25.js"
|
|
35
|
+
},
|
|
36
|
+
"./catalog": {
|
|
37
|
+
"types": "./lib/types/catalog.d.ts",
|
|
38
|
+
"default": "./lib/catalog.js"
|
|
39
|
+
},
|
|
40
|
+
"./client": {
|
|
41
|
+
"types": "./lib/types/client/index.d.ts",
|
|
42
|
+
"default": "./lib/client.js"
|
|
43
|
+
},
|
|
44
|
+
"./package.json": "./package.json"
|
|
45
|
+
},
|
|
46
|
+
"files": [
|
|
47
|
+
"lib",
|
|
48
|
+
"src",
|
|
49
|
+
"scripts",
|
|
50
|
+
"tests",
|
|
51
|
+
"docs",
|
|
52
|
+
"cordis.patch.yml",
|
|
53
|
+
"pnpm-lock.yaml",
|
|
54
|
+
"pnpm-workspace.yaml",
|
|
55
|
+
"tsconfig.json",
|
|
56
|
+
"tsconfig.client.json",
|
|
57
|
+
"tsconfig.test.json",
|
|
58
|
+
"tsdown.config.mjs",
|
|
59
|
+
"README.md",
|
|
60
|
+
"README.zh.md",
|
|
61
|
+
"CHANGELOG.md",
|
|
62
|
+
"LICENSE"
|
|
63
|
+
],
|
|
64
|
+
"scripts": {
|
|
65
|
+
"build": "node --input-type=module -e \"import { rmSync } from 'node:fs'; for (const path of ['lib', '.client-build']) rmSync(path, { recursive: true, force: true })\" && tsc -p tsconfig.json && tsc -p tsconfig.client.json && tsdown -c tsdown.config.mjs",
|
|
66
|
+
"check": "tsc -p tsconfig.json --noEmit --pretty false && tsc -p tsconfig.client.json --noEmit --pretty false && tsc -p tsconfig.test.json --noEmit --pretty false",
|
|
67
|
+
"test": "pnpm run build && vitest run tests",
|
|
68
|
+
"benchmark": "node scripts/benchmark.mjs --write",
|
|
69
|
+
"e2e:profile": "node scripts/profile-e2e.mjs",
|
|
70
|
+
"validate": "pnpm run check && pnpm run test && pnpm run benchmark && node scripts/validate.mjs",
|
|
71
|
+
"prepack": "pnpm run build"
|
|
72
|
+
},
|
|
73
|
+
"dsh": {
|
|
74
|
+
"bundle": {
|
|
75
|
+
"patch": "./cordis.patch.yml"
|
|
76
|
+
},
|
|
77
|
+
"client": {
|
|
78
|
+
"platform": "web",
|
|
79
|
+
"inject": [
|
|
80
|
+
"@deepseek-ai/dsh-client-ui-renderer",
|
|
81
|
+
"@deepseek-ai/dsh-client-ui-settings",
|
|
82
|
+
"@deepseek-ai/dsh-client-locale"
|
|
83
|
+
]
|
|
84
|
+
},
|
|
85
|
+
"compatibility": {
|
|
86
|
+
"dsh": "^0.1.1-rc.1 || ^0.1.2-alpha.1",
|
|
87
|
+
"profiles": [
|
|
88
|
+
"web",
|
|
89
|
+
"headless"
|
|
90
|
+
]
|
|
91
|
+
}
|
|
92
|
+
},
|
|
93
|
+
"peerDependencies": {
|
|
94
|
+
"@deepseek-ai/cordis": "^4.0.1",
|
|
95
|
+
"@deepseek-ai/dsh-agent": "^0.1.0-rc.8 || ^0.1.1-rc.1 || ^0.1.2-alpha.1",
|
|
96
|
+
"@deepseek-ai/dsh-client-locale": "^0.1.0-rc.8 || ^0.1.1-rc.1 || ^0.1.2-alpha.1",
|
|
97
|
+
"@deepseek-ai/dsh-client-ui-renderer": "^0.1.0-rc.8 || ^0.1.1-rc.1 || ^0.1.2-alpha.1",
|
|
98
|
+
"@deepseek-ai/dsh-client-ui-settings": "^0.1.0-rc.8 || ^0.1.1-rc.1 || ^0.1.2-alpha.1",
|
|
99
|
+
"@deepseek-ai/dsh-host-webserver": "^0.1.0-rc.8 || ^0.1.1-rc.1 || ^0.1.2-alpha.1",
|
|
100
|
+
"@deepseek-ai/dsh-settings": "^0.1.0-rc.8 || ^0.1.1-rc.1 || ^0.1.2-alpha.1",
|
|
101
|
+
"@deepseek-ai/dsh-system-prompt": "^0.1.0-rc.8 || ^0.1.1-rc.1 || ^0.1.2-alpha.1",
|
|
102
|
+
"@deepseek-ai/dsh-tools": "^0.1.0-rc.8 || ^0.1.1-rc.1 || ^0.1.2-alpha.1",
|
|
103
|
+
"@deepseek-ai/schemastery": "^3.18.1",
|
|
104
|
+
"react": "^18.2.0"
|
|
105
|
+
},
|
|
106
|
+
"peerDependenciesMeta": {
|
|
107
|
+
"@deepseek-ai/dsh-host-webserver": {
|
|
108
|
+
"optional": true
|
|
109
|
+
}
|
|
110
|
+
},
|
|
111
|
+
"dependencies": {
|
|
112
|
+
"wink-porter2-stemmer": "^2.0.1"
|
|
113
|
+
},
|
|
114
|
+
"devDependencies": {
|
|
115
|
+
"@deepseek-ai/dsh": "0.1.2-rc.1",
|
|
116
|
+
"@deepseek-ai/dsh-agent": "0.1.2-rc.1",
|
|
117
|
+
"@deepseek-ai/dsh-attachment": "0.1.2-rc.1",
|
|
118
|
+
"@deepseek-ai/dsh-client-locale": "0.1.2-rc.1",
|
|
119
|
+
"@deepseek-ai/dsh-client-ui-renderer": "0.1.2-rc.1",
|
|
120
|
+
"@deepseek-ai/dsh-client-ui-settings": "0.1.2-rc.1",
|
|
121
|
+
"@deepseek-ai/dsh-code-runtime": "0.1.2-rc.1",
|
|
122
|
+
"@deepseek-ai/dsh-compaction": "0.1.2-rc.1",
|
|
123
|
+
"@deepseek-ai/dsh-host-webserver": "0.1.2-rc.1",
|
|
124
|
+
"@deepseek-ai/dsh-jobs": "0.1.2-rc.1",
|
|
125
|
+
"@deepseek-ai/dsh-output-retention": "0.1.2-rc.1",
|
|
126
|
+
"@deepseek-ai/dsh-sandbox": "0.1.2-rc.1",
|
|
127
|
+
"@deepseek-ai/dsh-session-persistence": "0.1.2-rc.1",
|
|
128
|
+
"@deepseek-ai/dsh-session-query": "0.1.2-rc.1",
|
|
129
|
+
"@deepseek-ai/dsh-settings": "0.1.2-rc.1",
|
|
130
|
+
"@deepseek-ai/dsh-system-prompt": "0.1.2-rc.1",
|
|
131
|
+
"@deepseek-ai/dsh-tools": "0.1.2-rc.1",
|
|
132
|
+
"@testing-library/react": "^16.3.2",
|
|
133
|
+
"@types/node": "^22.20.0",
|
|
134
|
+
"@types/react": "~18.3.1",
|
|
135
|
+
"@types/react-dom": "~18.3.0",
|
|
136
|
+
"gpt-tokenizer": "^4.0.0",
|
|
137
|
+
"jsdom": "^29.1.1",
|
|
138
|
+
"react": "^18.3.1",
|
|
139
|
+
"react-dom": "^18.3.1",
|
|
140
|
+
"tsdown": "^0.22.2",
|
|
141
|
+
"typescript": "^5.9.3",
|
|
142
|
+
"vitest": "^4.1.10"
|
|
143
|
+
},
|
|
144
|
+
"publishConfig": {
|
|
145
|
+
"access": "public",
|
|
146
|
+
"registry": "https://registry.npmjs.org/"
|
|
147
|
+
},
|
|
148
|
+
"license": "MIT"
|
|
149
|
+
}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto'
|
|
2
|
+
import { mkdir, readFile, writeFile } from 'node:fs/promises'
|
|
3
|
+
import { dirname, join } from 'node:path'
|
|
4
|
+
import { fileURLToPath } from 'node:url'
|
|
5
|
+
import { encode } from 'gpt-tokenizer'
|
|
6
|
+
|
|
7
|
+
const root = dirname(dirname(fileURLToPath(import.meta.url)))
|
|
8
|
+
const generator = 'scripts/benchmark.mjs'
|
|
9
|
+
const generatorSource = await readFile(fileURLToPath(import.meta.url))
|
|
10
|
+
const packageJson = JSON.parse(await readFile(join(root, 'package.json'), 'utf8'))
|
|
11
|
+
const sizes = [10, 30, 50, 100]
|
|
12
|
+
|
|
13
|
+
function generatedTool(index) {
|
|
14
|
+
const id = String(index + 1).padStart(3, '0')
|
|
15
|
+
return {
|
|
16
|
+
name: `integration_${id}_search_records`,
|
|
17
|
+
description: `Search integration ${id} records with account, date, status, ownership, and pagination filters.`,
|
|
18
|
+
parameters: {
|
|
19
|
+
type: 'object',
|
|
20
|
+
additionalProperties: false,
|
|
21
|
+
properties: {
|
|
22
|
+
account_id: {
|
|
23
|
+
type: 'string',
|
|
24
|
+
description: 'Exact customer account identifier.',
|
|
25
|
+
},
|
|
26
|
+
filters: {
|
|
27
|
+
type: 'object',
|
|
28
|
+
description: 'Optional structured record filters.',
|
|
29
|
+
additionalProperties: false,
|
|
30
|
+
properties: {
|
|
31
|
+
created_after: {
|
|
32
|
+
type: 'string',
|
|
33
|
+
description: 'ISO 8601 lower date boundary.',
|
|
34
|
+
},
|
|
35
|
+
owner: {
|
|
36
|
+
type: 'string',
|
|
37
|
+
description: 'Owner email address or stable identifier.',
|
|
38
|
+
},
|
|
39
|
+
statuses: {
|
|
40
|
+
type: 'array',
|
|
41
|
+
description: 'Accepted workflow states.',
|
|
42
|
+
items: {
|
|
43
|
+
type: 'string',
|
|
44
|
+
description: 'One workflow status.',
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
},
|
|
48
|
+
},
|
|
49
|
+
limit: {
|
|
50
|
+
type: 'integer',
|
|
51
|
+
description: 'Maximum records to return.',
|
|
52
|
+
},
|
|
53
|
+
cursor: {
|
|
54
|
+
type: 'string',
|
|
55
|
+
description: 'Opaque pagination cursor from the previous result.',
|
|
56
|
+
},
|
|
57
|
+
},
|
|
58
|
+
required: ['account_id'],
|
|
59
|
+
},
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const searchTool = {
|
|
64
|
+
name: 'tool_search',
|
|
65
|
+
description: 'Search deferred tool metadata with deterministic local BM25. Matching tools become available by their real names on the next model call. Results contain summaries, not full schemas.',
|
|
66
|
+
parameters: {
|
|
67
|
+
type: 'object',
|
|
68
|
+
additionalProperties: false,
|
|
69
|
+
properties: {
|
|
70
|
+
query: { type: 'string', description: 'Search query for deferred tools.' },
|
|
71
|
+
limit: { type: 'integer', description: 'Maximum number of tools to return. Defaults to 5.' },
|
|
72
|
+
},
|
|
73
|
+
required: ['query'],
|
|
74
|
+
},
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function wire(tools) {
|
|
78
|
+
return JSON.stringify(tools.map(tool => ({
|
|
79
|
+
type: 'function',
|
|
80
|
+
function: tool,
|
|
81
|
+
})))
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function tokenCount(tools) {
|
|
85
|
+
return encode(wire(tools)).length
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
const allTools = Array.from({ length: Math.max(...sizes) }, (_value, index) => generatedTool(index))
|
|
89
|
+
const rows = sizes.map(size => {
|
|
90
|
+
const corpus = allTools.slice(0, size)
|
|
91
|
+
const fullTokens = tokenCount(corpus)
|
|
92
|
+
const deferredInitialTokens = tokenCount([searchTool])
|
|
93
|
+
const afterTop5Tokens = tokenCount([searchTool, ...corpus.slice(0, 5)])
|
|
94
|
+
return {
|
|
95
|
+
tools: size,
|
|
96
|
+
fullTokens,
|
|
97
|
+
deferredInitialTokens,
|
|
98
|
+
initialTokensSaved: fullTokens - deferredInitialTokens,
|
|
99
|
+
initialReductionPercent: Number(((1 - deferredInitialTokens / fullTokens) * 100).toFixed(1)),
|
|
100
|
+
afterTop5Tokens,
|
|
101
|
+
}
|
|
102
|
+
})
|
|
103
|
+
|
|
104
|
+
const report = {
|
|
105
|
+
schemaVersion: 2,
|
|
106
|
+
packageVersion: packageJson.version,
|
|
107
|
+
tokenizer: 'gpt-tokenizer 4.0.0 (o200k_base default encode)',
|
|
108
|
+
fixture: {
|
|
109
|
+
description: 'Deterministic nested function schemas; full surface versus tool_search-only initial surface.',
|
|
110
|
+
generator,
|
|
111
|
+
generatorSha256: createHash('sha256').update(generatorSource).digest('hex'),
|
|
112
|
+
corpusSha256: createHash('sha256').update(wire(allTools)).digest('hex'),
|
|
113
|
+
sizes,
|
|
114
|
+
},
|
|
115
|
+
rows,
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
if (process.argv.includes('--write')) {
|
|
119
|
+
const output = join(root, 'docs', 'benchmark-results.json')
|
|
120
|
+
await mkdir(dirname(output), { recursive: true })
|
|
121
|
+
await writeFile(output, `${JSON.stringify(report, null, 2)}\n`)
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
process.stdout.write(`${JSON.stringify(report, null, 2)}\n`)
|