# Conflicts: # docs/module-graph.md # docs/module-graph.zh.md # packages/ptc-runtime/ptc-runtime-node/package.json
85 lines
4.2 KiB
TypeScript
85 lines
4.2 KiB
TypeScript
/** PTC execution plugin for the mounting Agent, preset, or deployment scope. @module */
|
|
import type { Context } from '@deepseek-ai/cordis'
|
|
import type { PtcProgramFormat } from '@deepseek-ai/dsh-ptc-runtime'
|
|
import { RUN_CODE_NAME, ToolNotFoundError, projectToolSchema } from '@deepseek-ai/dsh-tools'
|
|
import type { ToolDefinition, ToolExecutor, ToolModelInput, ToolPromptSection, ToolBatchInput, ToolBatchResult } from '@deepseek-ai/dsh-tools'
|
|
import { ToolExecutionPipeline, executeToolBatch } from '@deepseek-ai/dsh-tools/pipeline'
|
|
import { createRunCodeTool, requirePtcRuntime, type PtcSdkLanguage } from './ptc.ts'
|
|
import { renderToolsSdk, type ToolSdkSchema } from './ts-types.ts'
|
|
import { renderToolsSdkPy } from './py-types.ts'
|
|
import { Config } from './config.ts'
|
|
|
|
const PTC_ONLY_INSTRUCTION = `\`${RUN_CODE_NAME}\` is the only tool you can call directly — a tool call naming any other tool fails. Reach every tool the SDK declares below from inside the program.`
|
|
|
|
const SDK_RENDERERS = {
|
|
typescript: renderToolsSdk,
|
|
python: renderToolsSdkPy,
|
|
} satisfies Record<PtcSdkLanguage, (schemas: readonly ToolSdkSchema[], programFormat: PtcProgramFormat) => string>
|
|
|
|
/** Runs programs whose nested tool calls use the shared guarded invocation pipeline. */
|
|
export class PtcExecutor implements ToolExecutor {
|
|
readonly sections: readonly ToolPromptSection[]
|
|
private readonly pipeline: ToolExecutionPipeline
|
|
private readonly maxParallelSubCalls: number
|
|
private ptcTransport: ToolDefinition | undefined
|
|
|
|
constructor(private readonly ctx: Context, config: Partial<Config> = {}, private readonly maxParallel: () => number = () => 10) {
|
|
this.maxParallelSubCalls = Config(config).maxParallelSubCalls
|
|
const tools = ctx.tools
|
|
this.sections = [
|
|
{ name: 'tools:ptc-only', order: ctx.systemPrompt.getSectionOrder('PTC_ONLY'), text: PTC_ONLY_INSTRUCTION, interpolate: false },
|
|
{ name: 'tools:sdk', order: ctx.systemPrompt.getSectionOrder('TOOLS_SDK'), text: tools => this.renderSdk(tools), interpolate: false },
|
|
]
|
|
this.pipeline = new ToolExecutionPipeline(ctx, {
|
|
get: (name, scope, toolSet) => name === RUN_CODE_NAME ? this.requirePtcTransport() : tools.executable(name, scope, toolSet),
|
|
reject: (name, nested) => !nested && name !== RUN_CODE_NAME
|
|
? new ToolNotFoundError(name, `only \`${RUN_CODE_NAME}\` is callable directly — call \`${name}\` from inside a \`${RUN_CODE_NAME}\` program instead`)
|
|
: undefined,
|
|
})
|
|
}
|
|
|
|
describe(_tools: readonly ToolDefinition[]): ToolModelInput {
|
|
return { schemas: [projectToolSchema(this.requirePtcTransport(), false)], knownNames: [RUN_CODE_NAME] }
|
|
}
|
|
|
|
private renderSdk(tools: readonly ToolDefinition[]): string {
|
|
const runtime = requirePtcRuntime(this.ctx)
|
|
const render = SDK_RENDERERS[runtime.language]
|
|
return render(tools.map(definition => ({
|
|
...projectToolSchema(definition, false),
|
|
output: definition.output.schema,
|
|
})), runtime.programFormat)
|
|
}
|
|
|
|
execute(input: ToolBatchInput): Promise<ToolBatchResult> {
|
|
return executeToolBatch(input, this.pipeline, this.maxParallel)
|
|
}
|
|
|
|
/** Keep the reserved transport outside registered capabilities and their restrictions. */
|
|
private requirePtcTransport(): ToolDefinition {
|
|
this.ptcTransport ??= createRunCodeTool(this.ctx, this.pipeline, this.maxParallelSubCalls)
|
|
return this.ptcTransport
|
|
}
|
|
}
|
|
|
|
export { Config } from './config.ts'
|
|
export { CodeRunFailedError } from './errors.ts'
|
|
export type { PtcDispatchLog } from './runtime-types.ts'
|
|
export type { PtcDispatchStartEventData, PtcDispatchEventData } from './types.ts'
|
|
export { jsonSchemaToTs, renderToolsSdk, type ToolSdkSchema } from './ts-types.ts'
|
|
export { jsonSchemaToPy, renderToolsSdkPy } from './py-types.ts'
|
|
|
|
/** Cordis plugin name. */
|
|
export const name = 'ptc-tool-executor'
|
|
/** Activate the executor only while its registry, prompt service, and runtime are available. */
|
|
export const inject = ['tools', 'systemPrompt', 'ptcRuntime']
|
|
|
|
/**
|
|
* Select PTC execution in the mounting scope.
|
|
* @param ctx - context owning this executor's selection and lifetime.
|
|
* @param config - program subcall concurrency limits.
|
|
*/
|
|
export function apply(ctx: Context, config: Config): void {
|
|
ctx.tools.setExecutor(new PtcExecutor(ctx, config))
|
|
}
|