mirror of
https://github.com/deepseek-ai/deepseek-harness.git
synced 2026-10-26 16:55:08 +00:00
ctx.tools.register(definition, { when }) adds a synchronous or asynchronous
condition. AgentLoop resolves conditions once per proposed step with the
agent, the model selection that step preparation captured, and the turn
signal, before prompt assembly and agent/pre-step. The resulting
ResolvedToolSet governs tool declarations, Native dispatch, PTC bindings,
and nested calls for that step and its retries, and the turn disposes it
when the proposal is rejected or fails, when no step opens, and after the
step. A false condition removes the tool everywhere; a thrown condition
ends the turn with TOOL_ACTIVATION_FAILED. Calls whose registration was
replaced or removed during the step return UNKNOWN_TOOL.
system-prompt/assemble now transforms PromptPresentation without a tool
array, so tool declarations stay provider-owned. exit_plan_mode is declared
only for steps whose selected plan state is active, the same state that
renders plan guidance; it still rejects a call before the selection is
logged.
Model selection stays as master defines it; this change adds no model
selection event or Agent field.
29 lines
1.1 KiB
JavaScript
29 lines
1.1 KiB
JavaScript
/** Activate a native tool after a file read and disable it after its first execution. */
|
|
export const name = 'python-sdk-dynamic-tools'
|
|
export const inject = ['tools']
|
|
|
|
/** @param {import('@deepseek-ai/cordis').Context} ctx - Scenario-owned tool registry. */
|
|
export function apply(ctx) {
|
|
let active = false
|
|
ctx.tools.register({
|
|
name: 'snapshot_ping',
|
|
description: 'Return pong once.',
|
|
parameters: { type: 'object', properties: {}, additionalProperties: false },
|
|
output: {
|
|
schema: { type: 'string' },
|
|
render(_args, value) { return [{ type: 'text', text: value }] },
|
|
},
|
|
async execute() { return 'pong' },
|
|
}, { when: async ({ modelSelection }) => active && modelSelection.provider === 'deepseek-official' })
|
|
ctx.on('tools/post-execute', async (exec, result, next) => {
|
|
const downstream = await next()
|
|
if (result.isError) return downstream
|
|
if (exec.name === 'read' && exec.arguments.file_path === 'dynamic-tool-task.txt') {
|
|
active = true
|
|
} else if (exec.name === 'snapshot_ping') {
|
|
active = false
|
|
}
|
|
return downstream
|
|
})
|
|
}
|