diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/util/js-template.ts | 17 | ||||
| -rw-r--r-- | src/util/mutex.ts | 5 | ||||
| -rw-r--r-- | src/util/sharp-shim.ts | 11 | ||||
| -rw-r--r-- | src/util/tool.ts | 14 |
4 files changed, 5 insertions, 42 deletions
diff --git a/src/util/js-template.ts b/src/util/js-template.ts index 392dbc0..75e0217 100644 --- a/src/util/js-template.ts +++ b/src/util/js-template.ts @@ -1,19 +1,4 @@ -/** - * Build a JavaScript source string with safely-interpolated values. - * Every interpolated value is JSON.stringify'd, so strings, numbers, - * objects, and special characters all become valid JS literals. - * - * This is the ONLY supported way to interpolate untrusted values into - * evaluation source — never use raw template literals for JS that - * crosses the CDP boundary. The static parts of the template (the - * `strings` array) must remain hard-coded; only the `${...}` slots - * are sanitized. - * - * Values must be JSON-serializable: BigInt and Symbol throw at runtime; - * functions and undefined serialize to `undefined`/omitted, which yields - * a ReferenceError when evaluated. Pass strings, numbers, booleans, - * plain objects, or arrays. - */ +// The ONLY supported way to interpolate untrusted values into evaluation source — never use raw template literals for JS crossing the CDP boundary. export const safeJs = ( strings: TemplateStringsArray, ...values: ReadonlyArray<unknown> diff --git a/src/util/mutex.ts b/src/util/mutex.ts index 08efe76..ad9e0c1 100644 --- a/src/util/mutex.ts +++ b/src/util/mutex.ts @@ -1,8 +1,3 @@ -/** - * Lightweight async mutex (~10 lines). Acquire returns a release function. - * When the mutex is free, acquire() resolves immediately. When held, - * callers are queued and execute serially in FIFO order. - */ export type Mutex = { acquire(): Promise<() => void>; }; diff --git a/src/util/sharp-shim.ts b/src/util/sharp-shim.ts index 36dd536..d7adb5f 100644 --- a/src/util/sharp-shim.ts +++ b/src/util/sharp-shim.ts @@ -1,10 +1,4 @@ -// Typed minimal shim for the optional `sharp` dependency. Sharp is a heavy -// native module not installed in every workspace; we import dynamically and -// distinguish "missing" (no install) from "error" (installed but threw). -// -// We declare only the surface we use. The dynamic import returns `unknown` -// at the boundary; the cast inside loadSharp() is the documented escape -// hatch — every other consumer sees the typed SharpFactory. +// `sharp` is an optional dependency not installed in every workspace, so the import must stay dynamic and unresolvable to tsc. export type SharpInstance = { metadata(): Promise<{ width?: number; height?: number }>; @@ -38,8 +32,7 @@ export const loadSharp = async (): Promise<SharpLoad> => { return { kind: "error", message: msg }; } if (mod === null || mod === undefined) return { kind: "missing" }; - // The CommonJS sharp module's default export IS the factory. ESM-wrapped - // sharp puts it on .default. Probe both. + // The CommonJS sharp module's default export IS the factory; ESM-wrapped sharp puts it on .default. const m = mod as { default?: unknown }; const candidate: unknown = typeof m.default === "function" ? m.default : mod; if (typeof candidate !== "function") { diff --git a/src/util/tool.ts b/src/util/tool.ts index 76087bc..155ab00 100644 --- a/src/util/tool.ts +++ b/src/util/tool.ts @@ -57,10 +57,7 @@ export type BrowserToolDefinition<S extends TSchema> = { readonly ensureAlive?: boolean; }; -// Type-erased entry for the registry's heterogeneous TOOLS array. -// renderCall accepts `never` so any concrete args type satisfies it via -// function-parameter contravariance (a handler that takes SpecificT is -// assignable to one that takes never, because never is a subtype of everything). +// renderCall accepts `never` so any concrete args type satisfies it via function-parameter contravariance. export type AnyBrowserToolDefinition = Omit<BrowserToolDefinition<TSchema>, "renderCall" | "renderResult"> & { readonly renderCall?: (args: never, theme: Theme) => Component; readonly renderResult?: (result: AgentToolResult<unknown>, expanded: boolean, theme: Theme) => Component; @@ -104,9 +101,6 @@ export const registerBrowserTool = ( client: BrowserClient, def: AnyBrowserToolDefinition, ): void => { - // AnyBrowserToolDefinition is type-erased; we recover the schema-typed surface - // by casting def to the generic form. The cast is safe because defineBrowserTool - // ensures the handler, parameters, and renderCall were all created with the same S. type S = TSchema; const defRenderCall = def.renderCall; const defRenderResult = def.renderResult; @@ -120,8 +114,7 @@ export const registerBrowserTool = ( ...(defRenderCall ? { renderCall: (args: Static<S>, theme: Theme, _ctx: Parameters<NonNullable<ToolDefinition<S>["renderCall"]>>[2]) => - // Cast from never->Component to unknown->Component: safe because at runtime - // args is always the concrete Static<S> value the tool was defined with. + // Sanctioned cast: at runtime args is always the concrete Static<S> value the tool was defined with. (defRenderCall as (args: unknown, theme: Theme) => Component)(args, theme), } : {}), @@ -137,9 +130,6 @@ export const registerBrowserTool = ( : {}), async execute(_toolCallId, args, signal, onUpdate, extensionCtx) { if (def.ensureAlive !== false) { - // Check daemon socket exists before attempting browser control. - // If missing, the user hasn't run /browser-setup yet. Return a clear - // error so the agent knows to direct the user to initialize. if (!(await daemonSocketMayExist())) { return toToolResult( { |
