diff --git a/packages/codemode/AGENTS.md b/packages/codemode/AGENTS.md index cbea866d4e..232665ccfb 100644 --- a/packages/codemode/AGENTS.md +++ b/packages/codemode/AGENTS.md @@ -4,6 +4,7 @@ - Do not add a speculative generic permission or approval policy. A host omits tools it does not expose and enforces domain authorization inside each provided tool. - Keep Code Mode unaware of host session, channel, and conversation models. The hosting application supplies trusted execution scope around it. - Tool schemas are the model-facing Interface. Keep arguments minimal and natural to the operation; never add unrelated IDs as ambient capability tokens. +- State model-visible diagnostics, logs, tool descriptions, and instructions directly. The execution context is already clear; do not repeat `Code Mode` or `CodeMode` unless the distinction is necessary. - When interpreter behavior or support changes, update `interpreter-support.md` and direct tests in the same PR. ## OpenAPI diff --git a/packages/codemode/src/interpreter/methods.ts b/packages/codemode/src/interpreter/methods.ts index dc2f6bb5c6..79a014ba4f 100644 --- a/packages/codemode/src/interpreter/methods.ts +++ b/packages/codemode/src/interpreter/methods.ts @@ -126,7 +126,7 @@ export const invokeIntrinsic = ( if (ref.receiver instanceof CodeModeURLSearchParams) { return invokeURLSearchParamsMethod(runner, ref.receiver, ref.name, args, node) } - throw new InterpreterRuntimeError(`Method '${ref.name}' is not available in CodeMode.`, node) + throw new InterpreterRuntimeError(`Method '${ref.name}' is not available.`, node) } const coerceNumericArgument = ( @@ -157,8 +157,7 @@ const coerceNumericArgument = ( } export const invokeGlobalMethod = (ref: GlobalMethodReference, args: Array, node: AstNode): unknown => { - if (ref.namespace === "console") - throw new InterpreterRuntimeError(`console.${ref.name} is not available in CodeMode.`, node) + if (ref.namespace === "console") throw new InterpreterRuntimeError(`console.${ref.name} is not available.`, node) if (ref.namespace === "Object") return invokeObjectMethod(ref.name, args, node) if (ref.namespace === "Math") return invokeMathMethod(ref.name, args, node) if (ref.namespace === "Array") return invokeArrayStatic(ref.name, args, node) @@ -168,9 +167,9 @@ export const invokeGlobalMethod = (ref: GlobalMethodReference, args: Array { @@ -348,7 +347,7 @@ const invokeStringMethod = (value: string, name: string, args: Array, n break } default: - throw new InterpreterRuntimeError(`String method '${name}' is not available in CodeMode.`, node) + throw new InterpreterRuntimeError(`String method '${name}' is not available.`, node) } return boundedData(result, `String.${name} result`) } @@ -364,7 +363,7 @@ const invokeArrayStatic = (name: string, args: Array, node: AstNode): u case "from": return arrayFromItems(args[0], node) default: - throw new InterpreterRuntimeError(`Array.${name} is not available in CodeMode.`, node) + throw new InterpreterRuntimeError(`Array.${name} is not available.`, node) } } @@ -449,7 +448,7 @@ export const invokeGroupBy = ( for (const item of items) { const key = yield* coerceGroupByPropertyKey(runner, yield* apply([item, index]), node) if (isBlockedMember(key)) { - throw new InterpreterRuntimeError(`Property '${key}' is not available in CodeMode.`, node) + throw new InterpreterRuntimeError(`Property '${key}' is not available.`, node) } const group = result[key] if (group === undefined) result[key] = [item] @@ -619,7 +618,7 @@ const invokeMapMethod = ( }) } default: - throw new InterpreterRuntimeError(`Map method '${name}' is not available in CodeMode.`, node) + throw new InterpreterRuntimeError(`Map method '${name}' is not available.`, node) } } @@ -666,7 +665,7 @@ const invokeSetMethod = ( case "isDisjointFrom": return invokeSetOperation(runner, target, name, args[0], node) default: - throw new InterpreterRuntimeError(`Set method '${name}' is not available in CodeMode.`, node) + throw new InterpreterRuntimeError(`Set method '${name}' is not available.`, node) } } @@ -861,7 +860,7 @@ const invokeURLSearchParamsMethod = ( }) } default: - throw new InterpreterRuntimeError(`URLSearchParams method '${name}' is not available in CodeMode.`, node) + throw new InterpreterRuntimeError(`URLSearchParams method '${name}' is not available.`, node) } } @@ -1104,7 +1103,7 @@ const invokeArrayMethod = ( } return -1 } - throw new InterpreterRuntimeError(`Array method '${name}' is not available in CodeMode.`, node) + throw new InterpreterRuntimeError(`Array method '${name}' is not available.`, node) }) } diff --git a/packages/codemode/src/interpreter/model.ts b/packages/codemode/src/interpreter/model.ts index 72e6de8be7..cc66f3b8a9 100644 --- a/packages/codemode/src/interpreter/model.ts +++ b/packages/codemode/src/interpreter/model.ts @@ -166,7 +166,7 @@ export class InterpreterRuntimeError extends Error { export const unsupportedSyntax = (kind: string, node: AstNode): InterpreterRuntimeError => new InterpreterRuntimeError( - `Syntax '${kind}' is not supported in CodeMode. ${supportedSyntaxMessage}`, + `Syntax '${kind}' is not supported. ${supportedSyntaxMessage}`, node, "UnsupportedSyntax", [supportedSyntaxMessage], diff --git a/packages/codemode/src/interpreter/runtime.ts b/packages/codemode/src/interpreter/runtime.ts index 2c90a4beb0..d290e817b5 100644 --- a/packages/codemode/src/interpreter/runtime.ts +++ b/packages/codemode/src/interpreter/runtime.ts @@ -166,7 +166,7 @@ const instanceofValue = (lhs: unknown, rhs: unknown, node: AstNode): boolean => return false } throw new InterpreterRuntimeError( - "The right-hand side of 'instanceof' must be a constructor CodeMode knows: Error (or a specific error type like TypeError), Date, RegExp, Map, Set, URL, URLSearchParams, Array, Object, or Promise.", + "The right-hand side of 'instanceof' must be a supported constructor: Error (or a specific error type like TypeError), Date, RegExp, Map, Set, URL, URLSearchParams, Array, Object, or Promise.", node, ) } @@ -393,12 +393,9 @@ export class Interpreter { private createFunction(node: AstNode): CodeModeFunction { if (node.generator === true) { - throw new InterpreterRuntimeError( - "Generator functions are not supported in CodeMode.", - node, - "UnsupportedSyntax", - [supportedSyntaxMessage], - ) + throw new InterpreterRuntimeError("Generator functions are not supported.", node, "UnsupportedSyntax", [ + supportedSyntaxMessage, + ]) } return new CodeModeFunction( getArray(node, "params").map((parameter, index) => asNode(parameter, `params[${index}]`)), @@ -454,11 +451,7 @@ export class Interpreter { return Effect.gen(function* () { const discriminant = yield* self.evaluateExpression(getNode(node, "discriminant")) if (containsOpaqueReference(discriminant)) { - throw new InterpreterRuntimeError( - "Switch discriminants must be data values in CodeMode.", - node, - "InvalidDataValue", - ) + throw new InterpreterRuntimeError("Switch discriminants must be data values.", node, "InvalidDataValue") } self.scopes.push() return yield* Effect.gen(function* () { @@ -474,11 +467,7 @@ export class Interpreter { } const candidate = yield* self.evaluateExpression(test) if (containsOpaqueReference(candidate)) { - throw new InterpreterRuntimeError( - "Switch case values must be data values in CodeMode.", - test, - "InvalidDataValue", - ) + throw new InterpreterRuntimeError("Switch case values must be data values.", test, "InvalidDataValue") } if (candidate === discriminant) { selected = index @@ -649,7 +638,7 @@ export class Interpreter { const iterable = spreadItems(right) if (iterable === undefined) { throw new InterpreterRuntimeError( - `${awaiting ? "for await...of" : "for...of"} requires an array, string, Map, Set, or URLSearchParams value in CodeMode.`, + `${awaiting ? "for await...of" : "for...of"} requires an array, string, Map, Set, or URLSearchParams value.`, node, ) } @@ -746,7 +735,7 @@ export class Interpreter { const keys = self.enumerableKeys(right) if (keys === undefined) { throw new InterpreterRuntimeError( - "for...in requires a plain object, array, or tools reference in CodeMode. Use for...of for arrays/strings/Maps/Sets, or Object.keys(value) for a key list.", + "for...in requires a plain object, array, or tools reference. Use for...of for arrays/strings/Maps/Sets, or Object.keys(value) for a key list.", node, ) } @@ -948,7 +937,7 @@ export class Interpreter { const key = yield* self.destructuringPropertyKey(property) if (isBlockedMember(String(key))) { - throw new InterpreterRuntimeError(`Property '${String(key)}' is not available in CodeMode.`, property) + throw new InterpreterRuntimeError(`Property '${String(key)}' is not available.`, property) } consumed.add(String(key)) yield* self.declarePattern( @@ -1026,7 +1015,7 @@ export class Interpreter { } const key = yield* self.destructuringPropertyKey(property) if (isBlockedMember(String(key))) { - throw new InterpreterRuntimeError(`Property '${String(key)}' is not available in CodeMode.`, property) + throw new InterpreterRuntimeError(`Property '${String(key)}' is not available.`, property) } consumed.add(String(key)) yield* self.assignPattern(getNode(property, "value"), self.destructuringPropertyValue(source, key), property) @@ -1202,7 +1191,7 @@ export class Interpreter { if (first === null || first === undefined) return {} if (typeof first === "object") return first throw new InterpreterRuntimeError( - `Object(${typeof first}) wrapper objects are not supported in CodeMode; use the primitive value directly.`, + `Object(${typeof first}) wrapper objects are not supported; use the primitive value directly.`, node, ) } @@ -1379,7 +1368,7 @@ export class Interpreter { private applyBinaryOperator(operator: string, lhs: unknown, rhs: unknown, node: AstNode): unknown { if (containsOpaqueReference(lhs) || containsOpaqueReference(rhs)) { - throw new InterpreterRuntimeError("Binary operators require data values in CodeMode.", node, "InvalidDataValue") + throw new InterpreterRuntimeError("Binary operators require data values.", node, "InvalidDataValue") } // Null-prototype data needs explicit primitive coercion; identity and `in` retain raw objects. // Dates use their default string hint for addition and loose equality, and epoch time elsewhere. @@ -1470,7 +1459,7 @@ export class Interpreter { if (operator === "!") return !value if (operator === "void") return undefined if (containsOpaqueReference(value)) { - throw new InterpreterRuntimeError("Unary operators require data values in CodeMode.", node, "InvalidDataValue") + throw new InterpreterRuntimeError("Unary operators require data values.", node, "InvalidDataValue") } const operand = value instanceof CodeModeDate @@ -1585,11 +1574,7 @@ export class Interpreter { // the host throw during ToPrimitive, and opaque runtime references must reject clearly. const operand = (current: unknown): number => { if (containsOpaqueReference(current)) { - throw new InterpreterRuntimeError( - `'${operator}' requires a data value in CodeMode.`, - argument, - "InvalidDataValue", - ) + throw new InterpreterRuntimeError(`'${operator}' requires a data value.`, argument, "InvalidDataValue") } return coerceToNumber(current) } @@ -1712,7 +1697,7 @@ export class Interpreter { if (callable === undefined || callable === null) { throw new InterpreterRuntimeError(`${calleeDescription(callee)} is not a function.`, callee).as("TypeError") } - throw new InterpreterRuntimeError("Only tools are callable in CodeMode.", callee) + throw new InterpreterRuntimeError("Only tools are callable here.", callee) }) } @@ -1728,8 +1713,7 @@ export class Interpreter { } private invokeConsole(name: string, args: Array, node: AstNode): undefined { - if (!consoleMethods.has(name)) - throw new InterpreterRuntimeError(`console.${name} is not available in CodeMode.`, node) + if (!consoleMethods.has(name)) throw new InterpreterRuntimeError(`console.${name} is not available.`, node) this.logs.push(formatConsoleMessage(name, args)) return undefined } @@ -1744,10 +1728,7 @@ export class Interpreter { const spread = yield* self.evaluateExpression(getNode(argNode, "argument")) const items = spreadItems(spread) if (items === undefined) - throw new InterpreterRuntimeError( - "Spread arguments require an array, string, Map, or Set in CodeMode.", - argNode, - ) + throw new InterpreterRuntimeError("Spread arguments require an array, string, Map, or Set.", argNode) args.push(...items) } else { args.push(yield* self.evaluateExpression(argNode)) @@ -1813,15 +1794,10 @@ export class Interpreter { const spread = yield* self.evaluateExpression(getNode(property, "argument")) if (spread === null || spread === undefined || isCodeModeValue(spread)) continue if (typeof spread !== "object" || Array.isArray(spread) || isRuntimeReference(spread)) { - throw new InterpreterRuntimeError( - "Object spread requires a data object in CodeMode.", - property, - "InvalidDataValue", - ) + throw new InterpreterRuntimeError("Object spread requires a data object.", property, "InvalidDataValue") } for (const [key, value] of Object.entries(spread)) { - if (isBlockedMember(key)) - throw new InterpreterRuntimeError(`Property '${key}' is not available in CodeMode.`, property) + if (isBlockedMember(key)) throw new InterpreterRuntimeError(`Property '${key}' is not available.`, property) objectValue[key] = value } continue @@ -1852,7 +1828,7 @@ export class Interpreter { } if (isBlockedMember(String(key))) { - throw new InterpreterRuntimeError(`Property '${String(key)}' is not available in CodeMode.`, keyNode) + throw new InterpreterRuntimeError(`Property '${String(key)}' is not available.`, keyNode) } objectValue[String(key)] = yield* self.evaluateExpression(valueNode) } @@ -1878,10 +1854,7 @@ export class Interpreter { const spread = yield* self.evaluateExpression(getNode(element, "argument")) const items = spreadItems(spread) if (items === undefined) - throw new InterpreterRuntimeError( - "Array spread requires an array, string, Map, or Set in CodeMode.", - element, - ) + throw new InterpreterRuntimeError("Array spread requires an array, string, Map, or Set.", element) values.push(...items) } else { values.push(yield* self.evaluateExpression(element)) @@ -1977,14 +1950,14 @@ export class Interpreter { return new PromiseMethodReference(key as PromiseMethodName) } throw new InterpreterRuntimeError( - `Promise.${String(key)} is not available in CodeMode. Available: Promise.all, Promise.allSettled, Promise.race, Promise.any, Promise.resolve, and Promise.reject; consume promises with await.`, + `Promise.${String(key)} is not available. Available: Promise.all, Promise.allSettled, Promise.race, Promise.any, Promise.resolve, and Promise.reject; consume promises with await.`, propertyNode, ) } if (objectValue instanceof GlobalNamespace) { if (typeof key === "string" && isBlockedMember(key)) { - throw new InterpreterRuntimeError(`${objectValue.name}.${key} is not available in CodeMode.`, propertyNode) + throw new InterpreterRuntimeError(`${objectValue.name}.${key} is not available.`, propertyNode) } if (typeof key !== "string") return new ComputedValue(undefined) if (objectValue.name === "Math" && mathConstants.has(key)) { @@ -2016,7 +1989,7 @@ export class Interpreter { if (objectValue instanceof CoercionFunction) { if (typeof key === "string" && isBlockedMember(key)) { - throw new InterpreterRuntimeError(`${objectValue.name}.${key} is not available in CodeMode.`, propertyNode) + throw new InterpreterRuntimeError(`${objectValue.name}.${key} is not available.`, propertyNode) } if (typeof key !== "string") return new ComputedValue(undefined) if (objectValue.name === "Number" && numberConstants.has(key)) { @@ -2083,7 +2056,7 @@ export class Interpreter { if (isRuntimeReference(objectValue)) { throw new InterpreterRuntimeError( - "CodeMode runtime references are opaque and do not expose properties.", + "Runtime references are opaque and do not expose properties.", objectNode, "InvalidDataValue", ) @@ -2094,7 +2067,7 @@ export class Interpreter { } if (typeof key === "string" && isBlockedMember(key)) { - throw new InterpreterRuntimeError(`Property '${key}' is not available in CodeMode.`, propertyNode) + throw new InterpreterRuntimeError(`Property '${key}' is not available.`, propertyNode) } if (Array.isArray(objectValue)) { @@ -2147,7 +2120,7 @@ export class Interpreter { private evaluateDeleteExpression(argument: AstNode): Effect.Effect { const target = argument.type === "ChainExpression" ? getNode(argument, "expression") : argument if (target.type !== "MemberExpression") { - throw new InterpreterRuntimeError("Only data fields may be deleted in CodeMode.", argument) + throw new InterpreterRuntimeError("Only data fields may be deleted.", argument) } return Effect.map(this.getMemberReference(target, "delete"), (reference) => { if (reference === OptionalShortCircuit) return true @@ -2162,7 +2135,7 @@ export class Interpreter { reference instanceof JsonMethodReference || reference.target instanceof CodeModeURL ) { - throw new InterpreterRuntimeError("Only data fields may be deleted in CodeMode.", target, "InvalidDataValue") + throw new InterpreterRuntimeError("Only data fields may be deleted.", target, "InvalidDataValue") } if (reference.target instanceof CodeModeRegExp) { return Reflect.deleteProperty(reference.target.regex, reference.key) @@ -2190,13 +2163,12 @@ export class Interpreter { reference instanceof GlobalMethodReference || reference instanceof JsonMethodReference ) { - throw new InterpreterRuntimeError("Only data fields may be assigned in CodeMode.", node) + throw new InterpreterRuntimeError("Only data fields may be assigned.", node) } if (Array.isArray(reference.target)) { - if (reference.key === "length") - throw new InterpreterRuntimeError("Array length cannot be assigned in CodeMode.", node) + if (reference.key === "length") throw new InterpreterRuntimeError("Array length cannot be assigned.", node) if (typeof reference.key === "string" && arrayMethods.has(reference.key)) { - throw new InterpreterRuntimeError("Array methods cannot be assigned in CodeMode.", node) + throw new InterpreterRuntimeError("Array methods cannot be assigned.", node) } } const key = Array.isArray(reference.target) ? reference.key : String(reference.key) diff --git a/packages/codemode/src/stdlib/console.ts b/packages/codemode/src/stdlib/console.ts index 1b7c3cbdb9..9ecca62c77 100644 --- a/packages/codemode/src/stdlib/console.ts +++ b/packages/codemode/src/stdlib/console.ts @@ -58,7 +58,7 @@ const formatConsoleValue = (value: unknown, seen: Set, depth: number): s seen.delete(value) } } - if (isRuntimeReference(value)) return "[CodeMode reference]" + if (isRuntimeReference(value)) return "[opaque reference]" seen.add(value) try { if (Array.isArray(value)) { @@ -74,7 +74,7 @@ const formatConsoleValue = (value: unknown, seen: Set, depth: number): s const formatConsoleTable = (value: unknown, columnsArgument: unknown): string => { if (value === undefined) return "undefined" - if (containsOpaqueReference(value)) return "[CodeMode reference]" + if (containsOpaqueReference(value)) return "[opaque reference]" const data = boundedData(value, "console.table argument") const columns = consoleTableColumns(columnsArgument) const rows = consoleTableRows(data, columns) diff --git a/packages/codemode/src/stdlib/date.ts b/packages/codemode/src/stdlib/date.ts index 5cec32bd04..bbae208eca 100644 --- a/packages/codemode/src/stdlib/date.ts +++ b/packages/codemode/src/stdlib/date.ts @@ -59,7 +59,7 @@ export const invokeDateStatic = (name: string, args: Array, node: AstNo case "UTC": return Date.UTC(...(args.map((arg) => coerceToNumber(arg)) as Parameters)) default: - throw new InterpreterRuntimeError(`Date.${name} is not available in CodeMode.`, node) + throw new InterpreterRuntimeError(`Date.${name} is not available.`, node) } } @@ -170,7 +170,7 @@ export const invokeDateMethod = ( if (args.length < 3) return updateDate(value, hosted.setUTCFullYear(args[0], args[1])) return updateDate(value, hosted.setUTCFullYear(args[0], args[1], args[2])) default: - throw new InterpreterRuntimeError(`Date method '${name}' is not available in CodeMode.`, node) + throw new InterpreterRuntimeError(`Date method '${name}' is not available.`, node) } } diff --git a/packages/codemode/src/stdlib/math.ts b/packages/codemode/src/stdlib/math.ts index 235b6083b5..040153b97e 100644 --- a/packages/codemode/src/stdlib/math.ts +++ b/packages/codemode/src/stdlib/math.ts @@ -51,7 +51,7 @@ export const mathMethods = new Set([ ]) export const invokeMathMethod = (name: string, args: Array, node: AstNode): number => { - if (!mathMethods.has(name)) throw new InterpreterRuntimeError(`Math.${name} is not available in CodeMode.`, node) + if (!mathMethods.has(name)) throw new InterpreterRuntimeError(`Math.${name} is not available.`, node) if (name === "random") return Math.random() if (name === "sumPrecise") { const items = spreadItems(args[0]) @@ -151,5 +151,5 @@ export const invokeMathMethod = (name: string, args: Array, node: AstNo case "imul": return Math.imul(a, b()) } - throw new InterpreterRuntimeError(`Math.${name} is not available in CodeMode.`, node) + throw new InterpreterRuntimeError(`Math.${name} is not available.`, node) } diff --git a/packages/codemode/src/stdlib/number.ts b/packages/codemode/src/stdlib/number.ts index 02dfa953b4..8055b046ea 100644 --- a/packages/codemode/src/stdlib/number.ts +++ b/packages/codemode/src/stdlib/number.ts @@ -45,7 +45,7 @@ export const invokeNumberMethod = (value: number, name: string, args: Array, node: Ast case "parseFloat": return parseFloat(coerceToString(value)) default: - throw new InterpreterRuntimeError(`Number.${name} is not available in CodeMode.`, node) + throw new InterpreterRuntimeError(`Number.${name} is not available.`, node) } } import { type AstNode, InterpreterRuntimeError } from "../interpreter/model.js" diff --git a/packages/codemode/src/stdlib/object.ts b/packages/codemode/src/stdlib/object.ts index d2930d81c7..7716ba8115 100644 --- a/packages/codemode/src/stdlib/object.ts +++ b/packages/codemode/src/stdlib/object.ts @@ -30,7 +30,7 @@ export const invokeObjectMethod = (name: string, args: Array, node: Ast return input as Record } const guardedSet = (out: Record, key: string, item: unknown): void => { - if (isBlockedMember(key)) throw new InterpreterRuntimeError(`Property '${key}' is not available in CodeMode.`, node) + if (isBlockedMember(key)) throw new InterpreterRuntimeError(`Property '${key}' is not available.`, node) out[key] = item } const addEntry = (out: Record, key: unknown, item: unknown): void => { @@ -49,7 +49,7 @@ export const invokeObjectMethod = (name: string, args: Array, node: Ast return Object.hasOwn(requireObject(), String(args[1])) case "is": if (containsOpaqueReference(args[0]) || containsOpaqueReference(args[1])) { - throw new InterpreterRuntimeError("Object.is requires data values in CodeMode.", node, "InvalidDataValue") + throw new InterpreterRuntimeError("Object.is requires data values.", node, "InvalidDataValue") } return Object.is(args[0], args[1]) case "assign": { @@ -94,5 +94,5 @@ export const invokeObjectMethod = (name: string, args: Array, node: Ast return out } } - throw new InterpreterRuntimeError(`Object.${name} is not available in CodeMode.`, node) + throw new InterpreterRuntimeError(`Object.${name} is not available.`, node) } diff --git a/packages/codemode/src/stdlib/regexp.ts b/packages/codemode/src/stdlib/regexp.ts index f737e1b993..c53a38fcd8 100644 --- a/packages/codemode/src/stdlib/regexp.ts +++ b/packages/codemode/src/stdlib/regexp.ts @@ -72,7 +72,7 @@ export const matchToValue = (match: RegExpMatchArray): Array => { } export const invokeRegExpStatic = (name: string, args: Array, node: AstNode): string => { - if (name !== "escape") throw new InterpreterRuntimeError(`RegExp.${name} is not available in CodeMode.`, node) + if (name !== "escape") throw new InterpreterRuntimeError(`RegExp.${name} is not available.`, node) if (typeof args[0] !== "string") { throw new InterpreterRuntimeError("RegExp.escape expects a string.", node).as("TypeError") } @@ -104,7 +104,7 @@ export const invokeRegExpMethod = ( case "toString": return coerceToString(value) default: - throw new InterpreterRuntimeError(`RegExp method '${name}' is not available in CodeMode.`, node) + throw new InterpreterRuntimeError(`RegExp method '${name}' is not available.`, node) } } diff --git a/packages/codemode/src/stdlib/string.ts b/packages/codemode/src/stdlib/string.ts index ffc33797dd..7070c645a4 100644 --- a/packages/codemode/src/stdlib/string.ts +++ b/packages/codemode/src/stdlib/string.ts @@ -43,7 +43,7 @@ export const invokeStringStatic = (name: string, args: Array, node: Ast case "fromCodePoint": return String.fromCodePoint(...codes) default: - throw new InterpreterRuntimeError(`String.${name} is not available in CodeMode.`, node) + throw new InterpreterRuntimeError(`String.${name} is not available.`, node) } } import { type AstNode, InterpreterRuntimeError } from "../interpreter/model.js" diff --git a/packages/codemode/src/stdlib/url.ts b/packages/codemode/src/stdlib/url.ts index 39e960539f..dfb203f1f2 100644 --- a/packages/codemode/src/stdlib/url.ts +++ b/packages/codemode/src/stdlib/url.ts @@ -69,7 +69,7 @@ export const urlArgument = (value: unknown, label: string): string => value instanceof CodeModeURL ? value.url.href : uriArgument(value, label) export const invokeURLStatic = (name: string, args: Array, node: AstNode): unknown => { - if (!urlStatics.has(name)) throw new InterpreterRuntimeError(`URL.${name} is not available in CodeMode.`, node) + if (!urlStatics.has(name)) throw new InterpreterRuntimeError(`URL.${name} is not available.`, node) if (args.length === 0) throw new InterpreterRuntimeError(`URL.${name} requires a URL argument.`, node).as("TypeError") const input = urlArgument(args[0], `URL.${name} input`) const base = args[1] === undefined ? undefined : urlArgument(args[1], `URL.${name} base`) @@ -83,7 +83,7 @@ export const invokeURLStatic = (name: string, args: Array, node: AstNod export const invokeURLMethod = (value: CodeModeURL, name: string, node: AstNode): string => { if (name === "toString" || name === "toJSON") return value.url.href - throw new InterpreterRuntimeError(`URL method '${name}' is not available in CodeMode.`, node) + throw new InterpreterRuntimeError(`URL method '${name}' is not available.`, node) } import { type AstNode, InterpreterRuntimeError, UriFunction } from "../interpreter/model.js" import { CodeModeURL } from "../values.js" diff --git a/packages/codemode/src/tool-runtime.ts b/packages/codemode/src/tool-runtime.ts index a518f37cc7..f64858aa35 100644 --- a/packages/codemode/src/tool-runtime.ts +++ b/packages/codemode/src/tool-runtime.ts @@ -363,7 +363,7 @@ const termForms = (term: string): Array => { const makeSearchTool = (searchIndex: ReadonlyArray): Definition => ({ _tag: "CodeModeTool", - description: "Search available Code Mode tools", + description: "Search available tools", input: SearchInput, output: SearchOutput, run: (input) => @@ -501,8 +501,8 @@ export const prepare = (tools: Tools, catalogBudget = defaultCatalogBudget empty ? "This is a restricted JavaScript language for calling tools, not a general-purpose runtime." : complete - ? "This is a restricted JavaScript language for calling tools, not a general-purpose runtime. Inside the confined interpreter, `tools` contains the Code Mode tools listed below; surrounding agent tools are not available." - : "This is a restricted JavaScript language for calling tools, not a general-purpose runtime. Inside the confined interpreter, `tools` contains the Code Mode tools listed or searchable below; surrounding agent tools are not available.", + ? "This is a restricted JavaScript language for calling tools, not a general-purpose runtime. Inside the confined interpreter, `tools` contains the tools listed below; surrounding agent tools are not available." + : "This is a restricted JavaScript language for calling tools, not a general-purpose runtime. Inside the confined interpreter, `tools` contains the tools listed or searchable below; surrounding agent tools are not available.", ...(empty ? [] : ["Do not infer or normalize tool names; use only exact signatures shown below or returned by search."]), @@ -533,8 +533,8 @@ export const prepare = (tools: Tools, catalogBudget = defaultCatalogBudget "## Rules", "", complete - ? "- Only Code Mode tools listed here are available; surrounding agent tools are not implicitly exposed." - : "- Only Code Mode tools listed here or returned by the built-in `search` function are available; surrounding agent tools are not implicitly exposed.", + ? "- Only tools listed here are available; surrounding agent tools are not implicitly exposed." + : "- Only tools listed here or returned by the built-in `search` function are available; surrounding agent tools are not implicitly exposed.", "- Filter, aggregate, and transform collections in code - never return them raw or call a tool per item across messages.", "- A result typed `Promise` may be structured data or text. Before reading fields, check that it is a non-null object and not an array; otherwise handle the returned text or primitive directly.", '- Run independent calls in parallel: `await Promise.all(items.map((item) => tools..(item)))`, or use `tools.["tool-name"](item)` when the listed signature uses bracket notation.', @@ -553,7 +553,7 @@ export const prepare = (tools: Tools, catalogBudget = defaultCatalogBudget "## Language", "", "Use common JavaScript data operations, functions, control flow, selected standard-library methods, and awaited tool calls. Built-ins include Date, RegExp, Map, Set, URL, URLSearchParams, and URI encoding helpers.", - "Modules/imports, classes, generators, timers, fetch, eval, prototype access, and unlisted methods are unavailable. Use Code Mode tools for external operations. Use await with try/catch.", + "Modules/imports, classes, generators, timers, fetch, eval, prototype access, and unlisted methods are unavailable. Use tools for external operations. Use await with try/catch.", "Prefer explicit `return`; otherwise only the final top-level expression becomes the result.", "Dates and URLs serialize to strings at data boundaries; Map/Set/RegExp/URLSearchParams serialize to `{}`.", ] diff --git a/packages/codemode/test/codemode.test.ts b/packages/codemode/test/codemode.test.ts index e2c91e7f4e..c017a0b971 100644 --- a/packages/codemode/test/codemode.test.ts +++ b/packages/codemode/test/codemode.test.ts @@ -308,7 +308,7 @@ describe("CodeMode console capture", () => { ) expect(result.ok).toBe(true) - expect(result.logs).toStrictEqual(['{"box":Map(1) [["self",[Circular]]]}', '{"fn":[CodeMode reference],"ok":1}']) + expect(result.logs).toStrictEqual(['{"box":Map(1) [["self",[Circular]]]}', '{"fn":[opaque reference],"ok":1}']) }) test("console.table renders CodeMode value cells", async () => { @@ -696,7 +696,7 @@ describe("CodeMode public contract", () => { expect(instructions).toContain("Do not infer or normalize tool names") expect(instructions).toContain("bracket notation and quotes are part of the path") expect(instructions).toContain("surrounding agent tools are not available") - expect(instructions).toContain("Only Code Mode tools listed here are available") + expect(instructions).toContain("Only tools listed here are available") // Placeholders use generic namespace/tool/field names only - no fabricated real tools // and no real catalog tools cherry-picked into example lines. expect(instructions).toContain("`const result = await tools..(input)`") @@ -718,7 +718,7 @@ describe("CodeMode public contract", () => { '1. If needed, discover tools with the built-in search function: `return search({ query: "" })`.', ) expect(partial).toContain("In the next execution, copy a returned path exactly") - expect(partial).toContain("Only Code Mode tools listed here or returned by the built-in `search` function") + expect(partial).toContain("Only tools listed here or returned by the built-in `search` function") expect(partial).toContain('- Browse one namespace: `search({ query: "", namespace: "" })`.') expect(partial).toContain("repeat the same search with `offset: next.offset`") expect(partial).toContain(" limit?: number,\n offset?: number,") @@ -739,7 +739,7 @@ describe("CodeMode public contract", () => { expect(instructions).not.toContain("promise chaining") expect(instructions).toContain("URL, URLSearchParams, and URI encoding helpers") expect(instructions).not.toContain("host globals") - expect(instructions).toContain("Use Code Mode tools for external operations") + expect(instructions).toContain("Use tools for external operations") expect(instructions).toContain( "Prefer explicit `return`; otherwise only the final top-level expression becomes the result.", )