fix(tools): add collapses() method and fix createExecution collapse logic
This commit is contained in:
@@ -1250,6 +1250,19 @@ export class ToolRegistry extends Service {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether the `code` mode collapse denies a model-direct call: only the
|
||||||
|
* reserved `run_code` transport may be named. Nested sub-dispatches (a
|
||||||
|
* `parent` token set) bypass the collapse. One home for the
|
||||||
|
* security-relevant predicate, shared by {@link resolveExecution} and
|
||||||
|
* {@link createExecution} so the two can never drift apart.
|
||||||
|
* @param name - the tool name as registered.
|
||||||
|
* @param nested - whether the call is a transport sub-dispatch, not a model-direct call.
|
||||||
|
*/
|
||||||
|
private collapses(name: string, nested: boolean): boolean {
|
||||||
|
return !nested && this.defaultMode === 'code' && name !== RUN_CODE_NAME
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Execute through pre-policy, guards, around-dispatch, post-policy,
|
* Execute through pre-policy, guards, around-dispatch, post-policy,
|
||||||
* definition-owned content finalization, and final notification. Tool and
|
* definition-owned content finalization, and final notification. Tool and
|
||||||
@@ -1295,8 +1308,15 @@ export class ToolRegistry extends Service {
|
|||||||
const agent = exec.agent
|
const agent = exec.agent
|
||||||
const parent = exec.parent
|
const parent = exec.parent
|
||||||
const signal = exec.signal
|
const signal = exec.signal
|
||||||
const definition = this.get(name, agent)
|
// Distinguish a mode-collapsed call (visible in the scope, denied only by
|
||||||
const finalizeContent = definition?.finalizeContent?.bind(definition)
|
// the `code` collapse) from a genuinely unknown tool. A collapsed call is
|
||||||
|
// deterministically denied, so it terminates BEFORE the extensible policy
|
||||||
|
// pipeline: pre-execute listeners, approval `ask`, and guards must never
|
||||||
|
// observe — or worse, approve — a call that can only fail. An unknown tool
|
||||||
|
// keeps the historical dispatch-stage `UNKNOWN_TOOL` path so policy
|
||||||
|
// listeners still see every name that reaches the registry.
|
||||||
|
const visible = this.get(name, agent)
|
||||||
|
const collapsed = visible !== undefined && this.collapses(name, parent !== undefined)
|
||||||
const concludingExecutions = this.concludingExecutions
|
const concludingExecutions = this.concludingExecutions
|
||||||
const base = {
|
const base = {
|
||||||
token,
|
token,
|
||||||
@@ -1333,7 +1353,7 @@ export class ToolRegistry extends Service {
|
|||||||
}
|
}
|
||||||
const execution: MutableToolRunContext = { ...base, arguments: deepFreeze(detached) }
|
const execution: MutableToolRunContext = { ...base, arguments: deepFreeze(detached) }
|
||||||
this.deferredContexts.set(execution, deferredContexts)
|
this.deferredContexts.set(execution, deferredContexts)
|
||||||
this.contentFinalizers.set(execution, finalizeContent)
|
this.contentFinalizers.set(execution, finalizerFor())
|
||||||
this.cancellationStates.set(execution, {
|
this.cancellationStates.set(execution, {
|
||||||
callerSignal: signal,
|
callerSignal: signal,
|
||||||
bodyInvoked: false,
|
bodyInvoked: false,
|
||||||
|
|||||||
Reference in New Issue
Block a user