refactor(tools): pin the two language tables to one union, and name python at the seam
`SDK_RENDERERS` and `RUN_CODE_FLAVORS` had to stay in step by review alone: the `Object.hasOwn` guards catch drift only once a runtime reporting the half-added language exists, which is the one case that cannot arise. Both tables are now `satisfies`-checked against a shared `CodeSdkLanguage` union, so a missing or extra entry fails `typecheck`. The declared `Record<string, …>` type stays, since `CodeRuntime.language` is an unconstrained `string`. The code-runtime seam's own README row and `CodeRuntime.language` JSDoc still named `'typescript'` as the sole well-known value; both now name `'python'` too and say only `'typescript'` has a published backend.
This commit is contained in:
@@ -100,11 +100,22 @@ const PYTHON_FLAVOR: RunCodeFlavor = {
|
||||
codeDescription: 'The program: the body of an async Python function.',
|
||||
}
|
||||
|
||||
/** Per-language `run_code` schema flavors (see {@link RunCodeFlavor}); one entry per `SDK_RENDERERS` language. */
|
||||
/**
|
||||
* The languages Code Mode ships a presentation for. Both per-language tables —
|
||||
* {@link RUN_CODE_FLAVORS} here and `SDK_RENDERERS` in {@link ./index.ts} — are
|
||||
* checked against this union with `satisfies`, so a language added to one and
|
||||
* not the other fails `typecheck` instead of waiting for a runtime that reports
|
||||
* it. The tables stay declared `Record<string, …>` because `CodeRuntime.language`
|
||||
* is an unconstrained `string`: this union pins what the harness ships, while the
|
||||
* `Object.hasOwn` guards reject what a mounted runtime may report.
|
||||
*/
|
||||
export type CodeSdkLanguage = 'typescript' | 'python'
|
||||
|
||||
/** Per-language `run_code` schema flavors (see {@link RunCodeFlavor}); one entry per {@link CodeSdkLanguage}. */
|
||||
const RUN_CODE_FLAVORS: Record<string, RunCodeFlavor> = {
|
||||
typescript: TYPESCRIPT_FLAVOR,
|
||||
python: PYTHON_FLAVOR,
|
||||
}
|
||||
} satisfies Record<CodeSdkLanguage, RunCodeFlavor>
|
||||
|
||||
/**
|
||||
* The `description` parameter's model-facing description: language-independent
|
||||
|
||||
@@ -22,6 +22,7 @@ import type { ToolCallView, ToolResultView } from './presentation.ts'
|
||||
import { assertSupportedJsonSchema, validateJsonSchemaValue } from './json-schema.ts'
|
||||
import type { JsonSchemaNode } from './json-schema.ts'
|
||||
import { createRunCodeTool, RUN_CODE_NAME, SDK_SECTION_ORDER } from './code-mode.ts'
|
||||
import type { CodeSdkLanguage } from './code-mode.ts'
|
||||
import { renderToolsSdk } from './ts-types.ts'
|
||||
import type { ToolSdkSchema } from './ts-types.ts'
|
||||
import { renderToolsSdkPy } from './py-types.ts'
|
||||
@@ -33,12 +34,15 @@ import { renderToolsSdkPy } from './py-types.ts'
|
||||
* fails the assembly loudly (same idiom as `toolOrder` violations). Adding a
|
||||
* new backend language is two table entries — an entry here and a
|
||||
* `RUN_CODE_FLAVORS` entry in `code-mode.ts` for its `run_code` schema strings
|
||||
* — plus the renderer function this table points at.
|
||||
* — plus the renderer function this table points at. The `satisfies` clause
|
||||
* pins this table's key set to {@link CodeSdkLanguage}, the same union the
|
||||
* flavor table is checked against, so adding one entry without the other is a
|
||||
* typecheck failure.
|
||||
*/
|
||||
const SDK_RENDERERS: Record<string, (schemas: ToolSdkSchema[]) => string> = {
|
||||
typescript: renderToolsSdk,
|
||||
python: renderToolsSdkPy,
|
||||
}
|
||||
} satisfies Record<CodeSdkLanguage, (schemas: ToolSdkSchema[]) => string>
|
||||
|
||||
export {
|
||||
defineTool,
|
||||
|
||||
Reference in New Issue
Block a user