@pella-labs/pinakes 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/README.md +208 -0
- package/dist/cli/audit.d.ts +30 -0
- package/dist/cli/audit.d.ts.map +1 -0
- package/dist/cli/audit.js +49 -0
- package/dist/cli/audit.js.map +1 -0
- package/dist/cli/export.d.ts +32 -0
- package/dist/cli/export.d.ts.map +1 -0
- package/dist/cli/export.js +73 -0
- package/dist/cli/export.js.map +1 -0
- package/dist/cli/import.d.ts +24 -0
- package/dist/cli/import.d.ts.map +1 -0
- package/dist/cli/import.js +96 -0
- package/dist/cli/import.js.map +1 -0
- package/dist/cli/index.d.ts +3 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +172 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/purge.d.ts +23 -0
- package/dist/cli/purge.d.ts.map +1 -0
- package/dist/cli/purge.js +57 -0
- package/dist/cli/purge.js.map +1 -0
- package/dist/cli/rebuild.d.ts +54 -0
- package/dist/cli/rebuild.d.ts.map +1 -0
- package/dist/cli/rebuild.js +113 -0
- package/dist/cli/rebuild.js.map +1 -0
- package/dist/cli/serve.d.ts +49 -0
- package/dist/cli/serve.d.ts.map +1 -0
- package/dist/cli/serve.js +296 -0
- package/dist/cli/serve.js.map +1 -0
- package/dist/cli/status.d.ts +39 -0
- package/dist/cli/status.d.ts.map +1 -0
- package/dist/cli/status.js +108 -0
- package/dist/cli/status.js.map +1 -0
- package/dist/db/client.d.ts +109 -0
- package/dist/db/client.d.ts.map +1 -0
- package/dist/db/client.js +175 -0
- package/dist/db/client.js.map +1 -0
- package/dist/db/repository.d.ts +82 -0
- package/dist/db/repository.d.ts.map +1 -0
- package/dist/db/repository.js +173 -0
- package/dist/db/repository.js.map +1 -0
- package/dist/db/schema.d.ts +990 -0
- package/dist/db/schema.d.ts.map +1 -0
- package/dist/db/schema.js +259 -0
- package/dist/db/schema.js.map +1 -0
- package/dist/db/types.d.ts +28 -0
- package/dist/db/types.d.ts.map +1 -0
- package/dist/db/types.js +11 -0
- package/dist/db/types.js.map +1 -0
- package/dist/gaps/detector.d.ts +67 -0
- package/dist/gaps/detector.d.ts.map +1 -0
- package/dist/gaps/detector.js +160 -0
- package/dist/gaps/detector.js.map +1 -0
- package/dist/gate/budget.d.ts +90 -0
- package/dist/gate/budget.d.ts.map +1 -0
- package/dist/gate/budget.js +145 -0
- package/dist/gate/budget.js.map +1 -0
- package/dist/ingest/chokidar.d.ts +33 -0
- package/dist/ingest/chokidar.d.ts.map +1 -0
- package/dist/ingest/chokidar.js +152 -0
- package/dist/ingest/chokidar.js.map +1 -0
- package/dist/ingest/ingester.d.ts +117 -0
- package/dist/ingest/ingester.d.ts.map +1 -0
- package/dist/ingest/ingester.js +312 -0
- package/dist/ingest/ingester.js.map +1 -0
- package/dist/ingest/manifest.d.ts +87 -0
- package/dist/ingest/manifest.d.ts.map +1 -0
- package/dist/ingest/manifest.js +223 -0
- package/dist/ingest/manifest.js.map +1 -0
- package/dist/ingest/memory-store.d.ts +55 -0
- package/dist/ingest/memory-store.d.ts.map +1 -0
- package/dist/ingest/memory-store.js +94 -0
- package/dist/ingest/memory-store.js.map +1 -0
- package/dist/ingest/parse/chunk.d.ts +15 -0
- package/dist/ingest/parse/chunk.d.ts.map +1 -0
- package/dist/ingest/parse/chunk.js +88 -0
- package/dist/ingest/parse/chunk.js.map +1 -0
- package/dist/ingest/parse/markdown.d.ts +64 -0
- package/dist/ingest/parse/markdown.d.ts.map +1 -0
- package/dist/ingest/parse/markdown.js +152 -0
- package/dist/ingest/parse/markdown.js.map +1 -0
- package/dist/ingest/queue.d.ts +21 -0
- package/dist/ingest/queue.d.ts.map +1 -0
- package/dist/ingest/queue.js +24 -0
- package/dist/ingest/queue.js.map +1 -0
- package/dist/ingest/source.d.ts +42 -0
- package/dist/ingest/source.d.ts.map +1 -0
- package/dist/ingest/source.js +19 -0
- package/dist/ingest/source.js.map +1 -0
- package/dist/mcp/envelope.d.ts +73 -0
- package/dist/mcp/envelope.d.ts.map +1 -0
- package/dist/mcp/envelope.js +46 -0
- package/dist/mcp/envelope.js.map +1 -0
- package/dist/mcp/tools/execute.d.ts +55 -0
- package/dist/mcp/tools/execute.d.ts.map +1 -0
- package/dist/mcp/tools/execute.js +232 -0
- package/dist/mcp/tools/execute.js.map +1 -0
- package/dist/mcp/tools/search.d.ts +53 -0
- package/dist/mcp/tools/search.d.ts.map +1 -0
- package/dist/mcp/tools/search.js +114 -0
- package/dist/mcp/tools/search.js.map +1 -0
- package/dist/observability/audit.d.ts +25 -0
- package/dist/observability/audit.d.ts.map +1 -0
- package/dist/observability/audit.js +38 -0
- package/dist/observability/audit.js.map +1 -0
- package/dist/observability/logger.d.ts +4 -0
- package/dist/observability/logger.d.ts.map +1 -0
- package/dist/observability/logger.js +56 -0
- package/dist/observability/logger.js.map +1 -0
- package/dist/observability/metrics.d.ts +38 -0
- package/dist/observability/metrics.d.ts.map +1 -0
- package/dist/observability/metrics.js +64 -0
- package/dist/observability/metrics.js.map +1 -0
- package/dist/retrieval/embedder.d.ts +130 -0
- package/dist/retrieval/embedder.d.ts.map +1 -0
- package/dist/retrieval/embedder.js +278 -0
- package/dist/retrieval/embedder.js.map +1 -0
- package/dist/retrieval/fts.d.ts +42 -0
- package/dist/retrieval/fts.d.ts.map +1 -0
- package/dist/retrieval/fts.js +46 -0
- package/dist/retrieval/fts.js.map +1 -0
- package/dist/retrieval/hybrid.d.ts +43 -0
- package/dist/retrieval/hybrid.d.ts.map +1 -0
- package/dist/retrieval/hybrid.js +120 -0
- package/dist/retrieval/hybrid.js.map +1 -0
- package/dist/retrieval/vec.d.ts +39 -0
- package/dist/retrieval/vec.d.ts.map +1 -0
- package/dist/retrieval/vec.js +50 -0
- package/dist/retrieval/vec.js.map +1 -0
- package/dist/sandbox/bindings/budget.d.ts +10 -0
- package/dist/sandbox/bindings/budget.d.ts.map +1 -0
- package/dist/sandbox/bindings/budget.js +44 -0
- package/dist/sandbox/bindings/budget.js.map +1 -0
- package/dist/sandbox/bindings/install.d.ts +23 -0
- package/dist/sandbox/bindings/install.d.ts.map +1 -0
- package/dist/sandbox/bindings/install.js +15 -0
- package/dist/sandbox/bindings/install.js.map +1 -0
- package/dist/sandbox/bindings/kg.d.ts +29 -0
- package/dist/sandbox/bindings/kg.d.ts.map +1 -0
- package/dist/sandbox/bindings/kg.js +323 -0
- package/dist/sandbox/bindings/kg.js.map +1 -0
- package/dist/sandbox/bindings/logger.d.ts +11 -0
- package/dist/sandbox/bindings/logger.d.ts.map +1 -0
- package/dist/sandbox/bindings/logger.js +33 -0
- package/dist/sandbox/bindings/logger.js.map +1 -0
- package/dist/sandbox/bindings/write.d.ts +34 -0
- package/dist/sandbox/bindings/write.d.ts.map +1 -0
- package/dist/sandbox/bindings/write.js +195 -0
- package/dist/sandbox/bindings/write.js.map +1 -0
- package/dist/sandbox/executor.d.ts +68 -0
- package/dist/sandbox/executor.d.ts.map +1 -0
- package/dist/sandbox/executor.js +280 -0
- package/dist/sandbox/executor.js.map +1 -0
- package/dist/sandbox/helpers.d.ts +26 -0
- package/dist/sandbox/helpers.d.ts.map +1 -0
- package/dist/sandbox/helpers.js +131 -0
- package/dist/sandbox/helpers.js.map +1 -0
- package/dist/sandbox/pool.d.ts +63 -0
- package/dist/sandbox/pool.d.ts.map +1 -0
- package/dist/sandbox/pool.js +98 -0
- package/dist/sandbox/pool.js.map +1 -0
- package/dist/sandbox/vendored-codemode.d.ts +99 -0
- package/dist/sandbox/vendored-codemode.d.ts.map +1 -0
- package/dist/sandbox/vendored-codemode.js +471 -0
- package/dist/sandbox/vendored-codemode.js.map +1 -0
- package/dist/server.d.ts +3 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +74 -0
- package/dist/server.js.map +1 -0
- package/dist/spike.d.ts +15 -0
- package/dist/spike.d.ts.map +1 -0
- package/dist/spike.js +90 -0
- package/dist/spike.js.map +1 -0
- package/package.json +60 -0
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
export class SandboxPool {
|
|
2
|
+
wasmModule;
|
|
3
|
+
available = [];
|
|
4
|
+
maxSize;
|
|
5
|
+
memoryLimitBytes;
|
|
6
|
+
stats = {
|
|
7
|
+
warmHits: 0,
|
|
8
|
+
coldHits: 0,
|
|
9
|
+
crashes: 0,
|
|
10
|
+
currentSize: 0,
|
|
11
|
+
};
|
|
12
|
+
nextId = 0;
|
|
13
|
+
disposed = false;
|
|
14
|
+
constructor(wasmModule, opts) {
|
|
15
|
+
this.wasmModule = wasmModule;
|
|
16
|
+
this.maxSize = opts?.poolSize ?? 2;
|
|
17
|
+
this.memoryLimitBytes = opts?.memoryLimitBytes ?? 64 * 1024 * 1024;
|
|
18
|
+
// Pre-create warm runtimes.
|
|
19
|
+
for (let i = 0; i < this.maxSize; i++) {
|
|
20
|
+
this.available.push(this.spawnRuntime(true));
|
|
21
|
+
}
|
|
22
|
+
this.stats.currentSize = this.maxSize;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Acquire a runtime from the pool. If the pool has warm runtimes available,
|
|
26
|
+
* returns one immediately. Otherwise spawns a cold overflow runtime.
|
|
27
|
+
* Never blocks.
|
|
28
|
+
*/
|
|
29
|
+
acquire() {
|
|
30
|
+
if (this.disposed)
|
|
31
|
+
throw new Error('SandboxPool is disposed');
|
|
32
|
+
const warm = this.available.pop();
|
|
33
|
+
if (warm) {
|
|
34
|
+
this.stats.warmHits++;
|
|
35
|
+
return warm;
|
|
36
|
+
}
|
|
37
|
+
// Overflow — spawn cold runtime, don't grow the pool.
|
|
38
|
+
this.stats.coldHits++;
|
|
39
|
+
return this.spawnRuntime(false);
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Release a runtime back to the pool. If `crashed` is true, the runtime
|
|
43
|
+
* is disposed and replaced with a fresh one. Overflow runtimes (not from
|
|
44
|
+
* the warm pool) are always disposed on release.
|
|
45
|
+
*/
|
|
46
|
+
release(pr, crashed) {
|
|
47
|
+
if (this.disposed) {
|
|
48
|
+
// Pool is shutting down — just dispose.
|
|
49
|
+
try {
|
|
50
|
+
pr.runtime.dispose();
|
|
51
|
+
}
|
|
52
|
+
catch { /* best effort */ }
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
if (crashed) {
|
|
56
|
+
this.stats.crashes++;
|
|
57
|
+
try {
|
|
58
|
+
pr.runtime.dispose();
|
|
59
|
+
}
|
|
60
|
+
catch { /* already dead */ }
|
|
61
|
+
// Replace with a fresh runtime if this was a warm slot.
|
|
62
|
+
if (pr.isWarm && this.available.length < this.maxSize) {
|
|
63
|
+
this.available.push(this.spawnRuntime(true));
|
|
64
|
+
}
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
// Return warm runtimes to pool; dispose overflow runtimes.
|
|
68
|
+
if (pr.isWarm && this.available.length < this.maxSize) {
|
|
69
|
+
this.available.push(pr);
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
try {
|
|
73
|
+
pr.runtime.dispose();
|
|
74
|
+
}
|
|
75
|
+
catch { /* best effort */ }
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
getStats() {
|
|
79
|
+
return { ...this.stats, currentSize: this.available.length };
|
|
80
|
+
}
|
|
81
|
+
dispose() {
|
|
82
|
+
this.disposed = true;
|
|
83
|
+
for (const pr of this.available) {
|
|
84
|
+
try {
|
|
85
|
+
pr.runtime.dispose();
|
|
86
|
+
}
|
|
87
|
+
catch { /* best effort */ }
|
|
88
|
+
}
|
|
89
|
+
this.available.length = 0;
|
|
90
|
+
}
|
|
91
|
+
// --------------------------------------------------------------------------
|
|
92
|
+
spawnRuntime(isWarm) {
|
|
93
|
+
const runtime = this.wasmModule.newRuntime();
|
|
94
|
+
runtime.setMemoryLimit(this.memoryLimitBytes);
|
|
95
|
+
return { runtime, id: this.nextId++, isWarm };
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
//# sourceMappingURL=pool.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pool.js","sourceRoot":"","sources":["../../src/sandbox/pool.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Vendored utilities from @cloudflare/codemode v0.3.4
|
|
3
|
+
*
|
|
4
|
+
* Source: https://github.com/cloudflare/agents/tree/main/packages/codemode
|
|
5
|
+
* License: MIT (Cloudflare, Inc.)
|
|
6
|
+
*
|
|
7
|
+
* Why vendored, not imported:
|
|
8
|
+
* The main entry of @cloudflare/codemode imports `RpcTarget` from
|
|
9
|
+
* `cloudflare:workers`, which is a Workers-runtime-only module. The package
|
|
10
|
+
* is therefore unusable from a plain Node.js process (like our MCP stdio
|
|
11
|
+
* server). The four utility functions in this file are pure JS with no
|
|
12
|
+
* Workers dependency, so we copy them here instead of deep-importing from
|
|
13
|
+
* the package's internal chunk files (whose hashed names are not part of
|
|
14
|
+
* any public API and can change on any upstream rebuild).
|
|
15
|
+
*
|
|
16
|
+
* See `dev-docs/prior-art.md` §5 and `dev-docs/presearch.md` D30 for the
|
|
17
|
+
* full audit and decision.
|
|
18
|
+
*
|
|
19
|
+
* Exports:
|
|
20
|
+
* - normalizeCode(code) — strip markdown fences + AST-wrap
|
|
21
|
+
* LLM code into an async IIFE
|
|
22
|
+
* - sanitizeToolName(name) — tool name → valid JS identifier
|
|
23
|
+
* - jsonSchemaToType(schema, typeName) — JSON Schema → TS type alias
|
|
24
|
+
* - generateTypesFromJsonSchema(tools) — tool set → TS `declare const`
|
|
25
|
+
* block for LLM prompts
|
|
26
|
+
*
|
|
27
|
+
* Modifications from upstream:
|
|
28
|
+
* - Added explicit TypeScript types (upstream ships types via a separate
|
|
29
|
+
* `.d.ts` chunk).
|
|
30
|
+
* - Combined into a single file instead of upstream's two-chunk layout.
|
|
31
|
+
* - Reformatted to match our Prettier config (single quotes, semicolons).
|
|
32
|
+
* - No behavioral changes.
|
|
33
|
+
*
|
|
34
|
+
* Upstream copyright:
|
|
35
|
+
* MIT License
|
|
36
|
+
* Copyright (c) Cloudflare, Inc.
|
|
37
|
+
* https://github.com/cloudflare/agents/blob/main/LICENSE
|
|
38
|
+
*/
|
|
39
|
+
import type { JSONSchema7 } from 'json-schema';
|
|
40
|
+
/**
|
|
41
|
+
* Normalize LLM-generated code into an async IIFE suitable for sandbox
|
|
42
|
+
* execution. Strips markdown fences, parses with acorn, and wraps the
|
|
43
|
+
* code so the final expression is returned from an `async () => { ... }`.
|
|
44
|
+
*
|
|
45
|
+
* Graceful fallback: if acorn fails to parse, wraps the raw source as-is.
|
|
46
|
+
*/
|
|
47
|
+
export declare function normalizeCode(code: string): string;
|
|
48
|
+
/**
|
|
49
|
+
* Sanitize a tool name into a valid JavaScript identifier.
|
|
50
|
+
* Replaces hyphens, dots, and spaces with `_`, strips other invalid chars,
|
|
51
|
+
* prefixes digit-leading names with `_`, and appends `_` to JS reserved words.
|
|
52
|
+
*/
|
|
53
|
+
export declare function sanitizeToolName(name: string): string;
|
|
54
|
+
/**
|
|
55
|
+
* Convert a JSON Schema to a TypeScript type declaration.
|
|
56
|
+
*/
|
|
57
|
+
export declare function jsonSchemaToType(schema: JSONSchema7, typeName: string): string;
|
|
58
|
+
/**
|
|
59
|
+
* A tool descriptor using plain JSON Schema (no Zod or AI SDK dependency).
|
|
60
|
+
*/
|
|
61
|
+
export interface JsonSchemaToolDescriptor {
|
|
62
|
+
description?: string;
|
|
63
|
+
inputSchema: JSONSchema7;
|
|
64
|
+
outputSchema?: JSONSchema7;
|
|
65
|
+
}
|
|
66
|
+
export type JsonSchemaToolDescriptors = Record<string, JsonSchemaToolDescriptor>;
|
|
67
|
+
/**
|
|
68
|
+
* Generate TypeScript type definitions from tool descriptors with JSON Schema.
|
|
69
|
+
* These types can be included in tool descriptions to help LLMs write correct
|
|
70
|
+
* code against our `kg.*` bindings.
|
|
71
|
+
*
|
|
72
|
+
* This function has NO dependency on the AI SDK or Zod — it works purely with
|
|
73
|
+
* JSON Schema objects.
|
|
74
|
+
*/
|
|
75
|
+
export declare function generateTypesFromJsonSchema(tools: JsonSchemaToolDescriptors): string;
|
|
76
|
+
export interface ExecuteResult {
|
|
77
|
+
result: unknown;
|
|
78
|
+
error?: string;
|
|
79
|
+
logs?: string[];
|
|
80
|
+
}
|
|
81
|
+
export interface ResolvedProvider {
|
|
82
|
+
name: string;
|
|
83
|
+
fns: Record<string, (...args: unknown[]) => Promise<unknown>>;
|
|
84
|
+
positionalArgs?: boolean;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* An executor runs LLM-generated code in a sandbox, making the provided
|
|
88
|
+
* tool functions callable under their namespace inside the sandbox.
|
|
89
|
+
*
|
|
90
|
+
* Implementations should never throw — errors are returned in
|
|
91
|
+
* `ExecuteResult.error`.
|
|
92
|
+
*
|
|
93
|
+
* Our Phase 1+ implementation will be a QuickJS-backed class in
|
|
94
|
+
* `src/sandbox/executor.ts`.
|
|
95
|
+
*/
|
|
96
|
+
export interface Executor {
|
|
97
|
+
execute(code: string, providersOrFns: ResolvedProvider[] | Record<string, (...args: unknown[]) => Promise<unknown>>): Promise<ExecuteResult>;
|
|
98
|
+
}
|
|
99
|
+
//# sourceMappingURL=vendored-codemode.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vendored-codemode.d.ts","sourceRoot":"","sources":["../../src/sandbox/vendored-codemode.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AAGH,OAAO,KAAK,EAAE,WAAW,EAAyB,MAAM,aAAa,CAAC;AAiBtE;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAoDlD;AAkBD;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAQrD;AAoRD;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAO9E;AAqBD;;GAEG;AACH,MAAM,WAAW,wBAAwB;IACvC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,WAAW,CAAC;IACzB,YAAY,CAAC,EAAE,WAAW,CAAC;CAC5B;AAED,MAAM,MAAM,yBAAyB,GAAG,MAAM,CAAC,MAAM,EAAE,wBAAwB,CAAC,CAAC;AAEjF;;;;;;;GAOG;AACH,wBAAgB,2BAA2B,CAAC,KAAK,EAAE,yBAAyB,GAAG,MAAM,CA+CpF;AAOD,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,OAAO,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;CACjB;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC;IAC9D,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED;;;;;;;;;GASG;AACH,MAAM,WAAW,QAAQ;IACvB,OAAO,CACL,IAAI,EAAE,MAAM,EACZ,cAAc,EACV,gBAAgB,EAAE,GAClB,MAAM,CAAC,MAAM,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC,GAC3D,OAAO,CAAC,aAAa,CAAC,CAAC;CAC3B"}
|
|
@@ -0,0 +1,471 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Vendored utilities from @cloudflare/codemode v0.3.4
|
|
3
|
+
*
|
|
4
|
+
* Source: https://github.com/cloudflare/agents/tree/main/packages/codemode
|
|
5
|
+
* License: MIT (Cloudflare, Inc.)
|
|
6
|
+
*
|
|
7
|
+
* Why vendored, not imported:
|
|
8
|
+
* The main entry of @cloudflare/codemode imports `RpcTarget` from
|
|
9
|
+
* `cloudflare:workers`, which is a Workers-runtime-only module. The package
|
|
10
|
+
* is therefore unusable from a plain Node.js process (like our MCP stdio
|
|
11
|
+
* server). The four utility functions in this file are pure JS with no
|
|
12
|
+
* Workers dependency, so we copy them here instead of deep-importing from
|
|
13
|
+
* the package's internal chunk files (whose hashed names are not part of
|
|
14
|
+
* any public API and can change on any upstream rebuild).
|
|
15
|
+
*
|
|
16
|
+
* See `dev-docs/prior-art.md` §5 and `dev-docs/presearch.md` D30 for the
|
|
17
|
+
* full audit and decision.
|
|
18
|
+
*
|
|
19
|
+
* Exports:
|
|
20
|
+
* - normalizeCode(code) — strip markdown fences + AST-wrap
|
|
21
|
+
* LLM code into an async IIFE
|
|
22
|
+
* - sanitizeToolName(name) — tool name → valid JS identifier
|
|
23
|
+
* - jsonSchemaToType(schema, typeName) — JSON Schema → TS type alias
|
|
24
|
+
* - generateTypesFromJsonSchema(tools) — tool set → TS `declare const`
|
|
25
|
+
* block for LLM prompts
|
|
26
|
+
*
|
|
27
|
+
* Modifications from upstream:
|
|
28
|
+
* - Added explicit TypeScript types (upstream ships types via a separate
|
|
29
|
+
* `.d.ts` chunk).
|
|
30
|
+
* - Combined into a single file instead of upstream's two-chunk layout.
|
|
31
|
+
* - Reformatted to match our Prettier config (single quotes, semicolons).
|
|
32
|
+
* - No behavioral changes.
|
|
33
|
+
*
|
|
34
|
+
* Upstream copyright:
|
|
35
|
+
* MIT License
|
|
36
|
+
* Copyright (c) Cloudflare, Inc.
|
|
37
|
+
* https://github.com/cloudflare/agents/blob/main/LICENSE
|
|
38
|
+
*/
|
|
39
|
+
import * as acorn from 'acorn';
|
|
40
|
+
// ============================================================================
|
|
41
|
+
// normalize.ts — strip markdown fences + AST-wrap LLM code
|
|
42
|
+
// ============================================================================
|
|
43
|
+
/**
|
|
44
|
+
* Strip markdown code fences that LLMs commonly wrap code in.
|
|
45
|
+
* Handles ```js, ```javascript, ```typescript, ```ts, or bare ```.
|
|
46
|
+
*/
|
|
47
|
+
function stripCodeFences(code) {
|
|
48
|
+
const match = code.match(/^```(?:js|javascript|typescript|ts|tsx|jsx)?\s*\n([\s\S]*?)```\s*$/);
|
|
49
|
+
return match ? match[1] : code;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Normalize LLM-generated code into an async IIFE suitable for sandbox
|
|
53
|
+
* execution. Strips markdown fences, parses with acorn, and wraps the
|
|
54
|
+
* code so the final expression is returned from an `async () => { ... }`.
|
|
55
|
+
*
|
|
56
|
+
* Graceful fallback: if acorn fails to parse, wraps the raw source as-is.
|
|
57
|
+
*/
|
|
58
|
+
export function normalizeCode(code) {
|
|
59
|
+
const trimmed = stripCodeFences(code.trim());
|
|
60
|
+
if (!trimmed.trim())
|
|
61
|
+
return 'async () => {}';
|
|
62
|
+
const source = trimmed.trim();
|
|
63
|
+
try {
|
|
64
|
+
const ast = acorn.parse(source, {
|
|
65
|
+
ecmaVersion: 'latest',
|
|
66
|
+
sourceType: 'module',
|
|
67
|
+
});
|
|
68
|
+
if (ast.body.length === 1 && ast.body[0].type === 'ExpressionStatement') {
|
|
69
|
+
if (ast.body[0].expression.type === 'ArrowFunctionExpression')
|
|
70
|
+
return source;
|
|
71
|
+
}
|
|
72
|
+
if (ast.body.length === 1 && ast.body[0].type === 'ExportDefaultDeclaration') {
|
|
73
|
+
const decl = ast.body[0].declaration;
|
|
74
|
+
const inner = source.slice(decl.start, decl.end);
|
|
75
|
+
if (decl.type === 'FunctionDeclaration' && !decl.id) {
|
|
76
|
+
return `async () => {\nreturn (${inner})();\n}`;
|
|
77
|
+
}
|
|
78
|
+
if (decl.type === 'ClassDeclaration' && !decl.id) {
|
|
79
|
+
return `async () => {\nreturn (${inner});\n}`;
|
|
80
|
+
}
|
|
81
|
+
return normalizeCode(inner);
|
|
82
|
+
}
|
|
83
|
+
if (ast.body.length === 1 && ast.body[0].type === 'FunctionDeclaration') {
|
|
84
|
+
return `async () => {\n${source}\nreturn ${ast.body[0].id?.name ?? 'fn'}();\n}`;
|
|
85
|
+
}
|
|
86
|
+
const last = ast.body[ast.body.length - 1];
|
|
87
|
+
if (last?.type === 'ExpressionStatement') {
|
|
88
|
+
const exprStmt = last;
|
|
89
|
+
return `async () => {\n${source.slice(0, last.start)}return (${source.slice(exprStmt.expression.start, exprStmt.expression.end)})\n}`;
|
|
90
|
+
}
|
|
91
|
+
return `async () => {\n${source}\n}`;
|
|
92
|
+
}
|
|
93
|
+
catch {
|
|
94
|
+
return `async () => {\n${source}\n}`;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
// ============================================================================
|
|
98
|
+
// utils.ts — identifier sanitization + string escaping helpers
|
|
99
|
+
// ============================================================================
|
|
100
|
+
const JS_RESERVED = new Set([
|
|
101
|
+
'abstract', 'arguments', 'await', 'boolean', 'break', 'byte', 'case',
|
|
102
|
+
'catch', 'char', 'class', 'const', 'continue', 'debugger', 'default',
|
|
103
|
+
'delete', 'do', 'double', 'else', 'enum', 'eval', 'export', 'extends',
|
|
104
|
+
'false', 'final', 'finally', 'float', 'for', 'function', 'goto', 'if',
|
|
105
|
+
'implements', 'import', 'in', 'instanceof', 'int', 'interface', 'let',
|
|
106
|
+
'long', 'native', 'new', 'null', 'package', 'private', 'protected',
|
|
107
|
+
'public', 'return', 'short', 'static', 'super', 'switch', 'synchronized',
|
|
108
|
+
'this', 'throw', 'throws', 'transient', 'true', 'try', 'typeof',
|
|
109
|
+
'undefined', 'var', 'void', 'volatile', 'while', 'with', 'yield',
|
|
110
|
+
]);
|
|
111
|
+
/**
|
|
112
|
+
* Sanitize a tool name into a valid JavaScript identifier.
|
|
113
|
+
* Replaces hyphens, dots, and spaces with `_`, strips other invalid chars,
|
|
114
|
+
* prefixes digit-leading names with `_`, and appends `_` to JS reserved words.
|
|
115
|
+
*/
|
|
116
|
+
export function sanitizeToolName(name) {
|
|
117
|
+
if (!name)
|
|
118
|
+
return '_';
|
|
119
|
+
let sanitized = name.replace(/[-.\s]/g, '_');
|
|
120
|
+
sanitized = sanitized.replace(/[^a-zA-Z0-9_$]/g, '');
|
|
121
|
+
if (!sanitized)
|
|
122
|
+
return '_';
|
|
123
|
+
if (/^[0-9]/.test(sanitized))
|
|
124
|
+
sanitized = '_' + sanitized;
|
|
125
|
+
if (JS_RESERVED.has(sanitized))
|
|
126
|
+
sanitized = sanitized + '_';
|
|
127
|
+
return sanitized;
|
|
128
|
+
}
|
|
129
|
+
function toPascalCase(str) {
|
|
130
|
+
return str
|
|
131
|
+
.replace(/_([a-z])/g, (_, letter) => letter.toUpperCase())
|
|
132
|
+
.replace(/^[a-z]/, (letter) => letter.toUpperCase());
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Escape a character as a unicode escape sequence if it is a control character.
|
|
136
|
+
*/
|
|
137
|
+
function escapeControlChar(ch) {
|
|
138
|
+
const code = ch.charCodeAt(0);
|
|
139
|
+
if (code <= 31 || code === 127)
|
|
140
|
+
return '\\u' + code.toString(16).padStart(4, '0');
|
|
141
|
+
return ch;
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Quote a property name if needed.
|
|
145
|
+
* Escapes backslashes, quotes, and control characters.
|
|
146
|
+
*/
|
|
147
|
+
function quoteProp(name) {
|
|
148
|
+
if (!/^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(name)) {
|
|
149
|
+
let escaped = '';
|
|
150
|
+
for (const ch of name) {
|
|
151
|
+
if (ch === '\\')
|
|
152
|
+
escaped += '\\\\';
|
|
153
|
+
else if (ch === '"')
|
|
154
|
+
escaped += '\\"';
|
|
155
|
+
else if (ch === '\n')
|
|
156
|
+
escaped += '\\n';
|
|
157
|
+
else if (ch === '\r')
|
|
158
|
+
escaped += '\\r';
|
|
159
|
+
else if (ch === '\t')
|
|
160
|
+
escaped += '\\t';
|
|
161
|
+
else if (ch === '\u2028')
|
|
162
|
+
escaped += '\\u2028';
|
|
163
|
+
else if (ch === '\u2029')
|
|
164
|
+
escaped += '\\u2029';
|
|
165
|
+
else
|
|
166
|
+
escaped += escapeControlChar(ch);
|
|
167
|
+
}
|
|
168
|
+
return `"${escaped}"`;
|
|
169
|
+
}
|
|
170
|
+
return name;
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Escape a string for use inside a double-quoted TypeScript string literal.
|
|
174
|
+
*/
|
|
175
|
+
function escapeStringLiteral(s) {
|
|
176
|
+
let out = '';
|
|
177
|
+
for (const ch of s) {
|
|
178
|
+
if (ch === '\\')
|
|
179
|
+
out += '\\\\';
|
|
180
|
+
else if (ch === '"')
|
|
181
|
+
out += '\\"';
|
|
182
|
+
else if (ch === '\n')
|
|
183
|
+
out += '\\n';
|
|
184
|
+
else if (ch === '\r')
|
|
185
|
+
out += '\\r';
|
|
186
|
+
else if (ch === '\t')
|
|
187
|
+
out += '\\t';
|
|
188
|
+
else if (ch === '\u2028')
|
|
189
|
+
out += '\\u2028';
|
|
190
|
+
else if (ch === '\u2029')
|
|
191
|
+
out += '\\u2029';
|
|
192
|
+
else
|
|
193
|
+
out += escapeControlChar(ch);
|
|
194
|
+
}
|
|
195
|
+
return out;
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Escape a string for use inside a JSDoc comment.
|
|
199
|
+
* Prevents premature comment closure from star-slash sequences.
|
|
200
|
+
*/
|
|
201
|
+
function escapeJsDoc(text) {
|
|
202
|
+
return text.replace(/\*\//g, '*\\/');
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* Resolve an internal JSON Pointer $ref (e.g. #/definitions/Foo) against the
|
|
206
|
+
* root schema. Returns null for external URLs or unresolvable paths.
|
|
207
|
+
*/
|
|
208
|
+
function resolveRef(ref, root) {
|
|
209
|
+
if (ref === '#')
|
|
210
|
+
return root;
|
|
211
|
+
if (!ref.startsWith('#/'))
|
|
212
|
+
return null;
|
|
213
|
+
const segments = ref
|
|
214
|
+
.slice(2)
|
|
215
|
+
.split('/')
|
|
216
|
+
.map((s) => s.replace(/~1/g, '/').replace(/~0/g, '~'));
|
|
217
|
+
let current = root;
|
|
218
|
+
for (const seg of segments) {
|
|
219
|
+
if (current === null || typeof current !== 'object')
|
|
220
|
+
return null;
|
|
221
|
+
current = current[seg];
|
|
222
|
+
if (current === undefined)
|
|
223
|
+
return null;
|
|
224
|
+
}
|
|
225
|
+
if (typeof current === 'boolean')
|
|
226
|
+
return current;
|
|
227
|
+
if (current === null || typeof current !== 'object')
|
|
228
|
+
return null;
|
|
229
|
+
return current;
|
|
230
|
+
}
|
|
231
|
+
/**
|
|
232
|
+
* Apply OpenAPI 3.0 `nullable: true` to a type result.
|
|
233
|
+
*/
|
|
234
|
+
function applyNullable(result, schema) {
|
|
235
|
+
if (result !== 'unknown' && result !== 'never' && schema?.nullable === true) {
|
|
236
|
+
return `${result} | null`;
|
|
237
|
+
}
|
|
238
|
+
return result;
|
|
239
|
+
}
|
|
240
|
+
/**
|
|
241
|
+
* Convert a JSON Schema to a TypeScript type string.
|
|
242
|
+
* This is a direct conversion without going through Zod.
|
|
243
|
+
*/
|
|
244
|
+
function jsonSchemaToTypeString(schema, indent, ctx) {
|
|
245
|
+
if (typeof schema === 'boolean')
|
|
246
|
+
return schema ? 'unknown' : 'never';
|
|
247
|
+
if (ctx.depth >= ctx.maxDepth)
|
|
248
|
+
return 'unknown';
|
|
249
|
+
if (ctx.seen.has(schema))
|
|
250
|
+
return 'unknown';
|
|
251
|
+
ctx.seen.add(schema);
|
|
252
|
+
const nextCtx = { ...ctx, depth: ctx.depth + 1 };
|
|
253
|
+
try {
|
|
254
|
+
const s = schema;
|
|
255
|
+
if (s.$ref) {
|
|
256
|
+
const resolved = resolveRef(s.$ref, ctx.root);
|
|
257
|
+
if (!resolved)
|
|
258
|
+
return 'unknown';
|
|
259
|
+
return applyNullable(jsonSchemaToTypeString(resolved, indent, nextCtx), s);
|
|
260
|
+
}
|
|
261
|
+
if (s.anyOf) {
|
|
262
|
+
return applyNullable(s.anyOf.map((sub) => jsonSchemaToTypeString(sub, indent, nextCtx)).join(' | '), s);
|
|
263
|
+
}
|
|
264
|
+
if (s.oneOf) {
|
|
265
|
+
return applyNullable(s.oneOf.map((sub) => jsonSchemaToTypeString(sub, indent, nextCtx)).join(' | '), s);
|
|
266
|
+
}
|
|
267
|
+
if (s.allOf) {
|
|
268
|
+
return applyNullable(s.allOf.map((sub) => jsonSchemaToTypeString(sub, indent, nextCtx)).join(' & '), s);
|
|
269
|
+
}
|
|
270
|
+
if (s.enum) {
|
|
271
|
+
if (s.enum.length === 0)
|
|
272
|
+
return 'never';
|
|
273
|
+
return applyNullable(s.enum
|
|
274
|
+
.map((v) => {
|
|
275
|
+
if (v === null)
|
|
276
|
+
return 'null';
|
|
277
|
+
if (typeof v === 'string')
|
|
278
|
+
return '"' + escapeStringLiteral(v) + '"';
|
|
279
|
+
if (typeof v === 'object')
|
|
280
|
+
return JSON.stringify(v) ?? 'unknown';
|
|
281
|
+
return String(v);
|
|
282
|
+
})
|
|
283
|
+
.join(' | '), s);
|
|
284
|
+
}
|
|
285
|
+
if (s.const !== undefined) {
|
|
286
|
+
return applyNullable(s.const === null
|
|
287
|
+
? 'null'
|
|
288
|
+
: typeof s.const === 'string'
|
|
289
|
+
? '"' + escapeStringLiteral(s.const) + '"'
|
|
290
|
+
: typeof s.const === 'object'
|
|
291
|
+
? (JSON.stringify(s.const) ?? 'unknown')
|
|
292
|
+
: String(s.const), s);
|
|
293
|
+
}
|
|
294
|
+
const type = s.type;
|
|
295
|
+
if (type === 'string')
|
|
296
|
+
return applyNullable('string', s);
|
|
297
|
+
if (type === 'number' || type === 'integer')
|
|
298
|
+
return applyNullable('number', s);
|
|
299
|
+
if (type === 'boolean')
|
|
300
|
+
return applyNullable('boolean', s);
|
|
301
|
+
if (type === 'null')
|
|
302
|
+
return 'null';
|
|
303
|
+
if (type === 'array') {
|
|
304
|
+
const prefixItems = s.prefixItems;
|
|
305
|
+
if (Array.isArray(prefixItems)) {
|
|
306
|
+
return applyNullable(`[${prefixItems.map((sub) => jsonSchemaToTypeString(sub, indent, nextCtx)).join(', ')}]`, s);
|
|
307
|
+
}
|
|
308
|
+
if (Array.isArray(s.items)) {
|
|
309
|
+
return applyNullable(`[${s.items.map((sub) => jsonSchemaToTypeString(sub, indent, nextCtx)).join(', ')}]`, s);
|
|
310
|
+
}
|
|
311
|
+
if (s.items) {
|
|
312
|
+
return applyNullable(`${jsonSchemaToTypeString(s.items, indent, nextCtx)}[]`, s);
|
|
313
|
+
}
|
|
314
|
+
return applyNullable('unknown[]', s);
|
|
315
|
+
}
|
|
316
|
+
if (type === 'object' || s.properties) {
|
|
317
|
+
const props = s.properties || {};
|
|
318
|
+
const required = new Set(s.required || []);
|
|
319
|
+
const lines = [];
|
|
320
|
+
for (const [propName, propSchema] of Object.entries(props)) {
|
|
321
|
+
if (typeof propSchema === 'boolean') {
|
|
322
|
+
const boolType = propSchema ? 'unknown' : 'never';
|
|
323
|
+
const optionalMark = required.has(propName) ? '' : '?';
|
|
324
|
+
lines.push(`${indent} ${quoteProp(propName)}${optionalMark}: ${boolType};`);
|
|
325
|
+
continue;
|
|
326
|
+
}
|
|
327
|
+
const isRequired = required.has(propName);
|
|
328
|
+
const propType = jsonSchemaToTypeString(propSchema, indent + ' ', nextCtx);
|
|
329
|
+
const desc = propSchema.description;
|
|
330
|
+
const format = propSchema.format;
|
|
331
|
+
if (desc || format) {
|
|
332
|
+
const descText = desc ? escapeJsDoc(desc.replace(/\r?\n/g, ' ')) : undefined;
|
|
333
|
+
const formatTag = format ? `@format ${escapeJsDoc(format)}` : undefined;
|
|
334
|
+
if (descText && formatTag) {
|
|
335
|
+
lines.push(`${indent} /**`);
|
|
336
|
+
lines.push(`${indent} * ${descText}`);
|
|
337
|
+
lines.push(`${indent} * ${formatTag}`);
|
|
338
|
+
lines.push(`${indent} */`);
|
|
339
|
+
}
|
|
340
|
+
else {
|
|
341
|
+
lines.push(`${indent} /** ${descText ?? formatTag} */`);
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
const quotedName = quoteProp(propName);
|
|
345
|
+
const optionalMark = isRequired ? '' : '?';
|
|
346
|
+
lines.push(`${indent} ${quotedName}${optionalMark}: ${propType};`);
|
|
347
|
+
}
|
|
348
|
+
if (s.additionalProperties) {
|
|
349
|
+
const valueType = s.additionalProperties === true
|
|
350
|
+
? 'unknown'
|
|
351
|
+
: jsonSchemaToTypeString(s.additionalProperties, indent + ' ', nextCtx);
|
|
352
|
+
lines.push(`${indent} [key: string]: ${valueType};`);
|
|
353
|
+
}
|
|
354
|
+
if (lines.length === 0) {
|
|
355
|
+
if (s.additionalProperties === false)
|
|
356
|
+
return applyNullable('{}', s);
|
|
357
|
+
return applyNullable('Record<string, unknown>', s);
|
|
358
|
+
}
|
|
359
|
+
return applyNullable(`{\n${lines.join('\n')}\n${indent}}`, s);
|
|
360
|
+
}
|
|
361
|
+
if (Array.isArray(type)) {
|
|
362
|
+
return applyNullable(type
|
|
363
|
+
.map((t) => {
|
|
364
|
+
if (t === 'string')
|
|
365
|
+
return 'string';
|
|
366
|
+
if (t === 'number' || t === 'integer')
|
|
367
|
+
return 'number';
|
|
368
|
+
if (t === 'boolean')
|
|
369
|
+
return 'boolean';
|
|
370
|
+
if (t === 'null')
|
|
371
|
+
return 'null';
|
|
372
|
+
if (t === 'array')
|
|
373
|
+
return 'unknown[]';
|
|
374
|
+
if (t === 'object')
|
|
375
|
+
return 'Record<string, unknown>';
|
|
376
|
+
return 'unknown';
|
|
377
|
+
})
|
|
378
|
+
.join(' | '), s);
|
|
379
|
+
}
|
|
380
|
+
return 'unknown';
|
|
381
|
+
}
|
|
382
|
+
finally {
|
|
383
|
+
ctx.seen.delete(schema);
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
/**
|
|
387
|
+
* Convert a JSON Schema to a TypeScript type declaration.
|
|
388
|
+
*/
|
|
389
|
+
export function jsonSchemaToType(schema, typeName) {
|
|
390
|
+
return `type ${typeName} = ${jsonSchemaToTypeString(schema, '', {
|
|
391
|
+
root: schema,
|
|
392
|
+
depth: 0,
|
|
393
|
+
seen: new Set(),
|
|
394
|
+
maxDepth: 20,
|
|
395
|
+
})}`;
|
|
396
|
+
}
|
|
397
|
+
/**
|
|
398
|
+
* Extract field descriptions from a JSON Schema's properties.
|
|
399
|
+
*/
|
|
400
|
+
function extractJsonSchemaDescriptions(schema) {
|
|
401
|
+
const descriptions = {};
|
|
402
|
+
if (schema.properties) {
|
|
403
|
+
for (const [fieldName, propSchema] of Object.entries(schema.properties)) {
|
|
404
|
+
if (propSchema &&
|
|
405
|
+
typeof propSchema === 'object' &&
|
|
406
|
+
propSchema.description) {
|
|
407
|
+
descriptions[fieldName] = propSchema.description;
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
return descriptions;
|
|
412
|
+
}
|
|
413
|
+
/**
|
|
414
|
+
* Generate TypeScript type definitions from tool descriptors with JSON Schema.
|
|
415
|
+
* These types can be included in tool descriptions to help LLMs write correct
|
|
416
|
+
* code against our `kg.*` bindings.
|
|
417
|
+
*
|
|
418
|
+
* This function has NO dependency on the AI SDK or Zod — it works purely with
|
|
419
|
+
* JSON Schema objects.
|
|
420
|
+
*/
|
|
421
|
+
export function generateTypesFromJsonSchema(tools) {
|
|
422
|
+
let availableTools = '';
|
|
423
|
+
let availableTypes = '';
|
|
424
|
+
for (const [toolName, tool] of Object.entries(tools)) {
|
|
425
|
+
const safeName = sanitizeToolName(toolName);
|
|
426
|
+
const typeName = toPascalCase(safeName);
|
|
427
|
+
try {
|
|
428
|
+
const inputType = jsonSchemaToType(tool.inputSchema, `${typeName}Input`);
|
|
429
|
+
const outputType = tool.outputSchema
|
|
430
|
+
? jsonSchemaToType(tool.outputSchema, `${typeName}Output`)
|
|
431
|
+
: `type ${typeName}Output = unknown`;
|
|
432
|
+
availableTypes += `\n${inputType.trim()}`;
|
|
433
|
+
availableTypes += `\n${outputType.trim()}`;
|
|
434
|
+
const paramLines = (() => {
|
|
435
|
+
try {
|
|
436
|
+
const paramDescs = extractJsonSchemaDescriptions(tool.inputSchema);
|
|
437
|
+
return Object.entries(paramDescs).map(([fieldName, desc]) => `@param input.${fieldName} - ${desc}`);
|
|
438
|
+
}
|
|
439
|
+
catch {
|
|
440
|
+
return [];
|
|
441
|
+
}
|
|
442
|
+
})();
|
|
443
|
+
const jsdocLines = [];
|
|
444
|
+
if (tool.description?.trim()) {
|
|
445
|
+
jsdocLines.push(escapeJsDoc(tool.description.trim().replace(/\r?\n/g, ' ')));
|
|
446
|
+
}
|
|
447
|
+
else {
|
|
448
|
+
jsdocLines.push(escapeJsDoc(toolName));
|
|
449
|
+
}
|
|
450
|
+
for (const pd of paramLines)
|
|
451
|
+
jsdocLines.push(escapeJsDoc(pd.replace(/\r?\n/g, ' ')));
|
|
452
|
+
const jsdocBody = jsdocLines.map((l) => `\t * ${l}`).join('\n');
|
|
453
|
+
availableTools += `\n\t/**\n${jsdocBody}\n\t */`;
|
|
454
|
+
availableTools += `\n\t${safeName}: (input: ${typeName}Input) => Promise<${typeName}Output>;`;
|
|
455
|
+
availableTools += '\n';
|
|
456
|
+
}
|
|
457
|
+
catch {
|
|
458
|
+
availableTypes += `\ntype ${typeName}Input = unknown`;
|
|
459
|
+
availableTypes += `\ntype ${typeName}Output = unknown`;
|
|
460
|
+
availableTools += `\n\t/**\n\t * ${escapeJsDoc(toolName)}\n\t */`;
|
|
461
|
+
availableTools += `\n\t${safeName}: (input: ${typeName}Input) => Promise<${typeName}Output>;`;
|
|
462
|
+
availableTools += '\n';
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
availableTools = `\ndeclare const codemode: {${availableTools}}`;
|
|
466
|
+
return `
|
|
467
|
+
${availableTypes}
|
|
468
|
+
${availableTools}
|
|
469
|
+
`.trim();
|
|
470
|
+
}
|
|
471
|
+
//# sourceMappingURL=vendored-codemode.js.map
|