@namzu/sdk 51.1.0 → 52.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +100 -0
- package/dist/agents/QueryAgent.d.ts.map +1 -1
- package/dist/agents/QueryAgent.js +2 -0
- package/dist/agents/QueryAgent.js.map +1 -1
- package/dist/agents/SupervisorAgent.d.ts +1 -1
- package/dist/agents/SupervisorAgent.d.ts.map +1 -1
- package/dist/agents/SupervisorAgent.js.map +1 -1
- package/dist/agents/examples/SupervisorAgent.d.ts +42 -0
- package/dist/agents/examples/SupervisorAgent.d.ts.map +1 -1
- package/dist/agents/examples/SupervisorAgent.js +80 -4
- package/dist/agents/examples/SupervisorAgent.js.map +1 -1
- package/dist/agents/index.d.ts +1 -1
- package/dist/agents/index.d.ts.map +1 -1
- package/dist/agents/index.js.map +1 -1
- package/dist/authorization/protected-paths.d.ts +36 -0
- package/dist/authorization/protected-paths.d.ts.map +1 -0
- package/dist/authorization/protected-paths.js +107 -0
- package/dist/authorization/protected-paths.js.map +1 -0
- package/dist/authorization/readonly-commands.d.ts +39 -0
- package/dist/authorization/readonly-commands.d.ts.map +1 -0
- package/dist/authorization/readonly-commands.js +797 -0
- package/dist/authorization/readonly-commands.js.map +1 -0
- package/dist/authorization/readonly-flags.d.ts +19 -0
- package/dist/authorization/readonly-flags.d.ts.map +1 -0
- package/dist/authorization/readonly-flags.js +178 -0
- package/dist/authorization/readonly-flags.js.map +1 -0
- package/dist/authorization/removal.d.ts +52 -0
- package/dist/authorization/removal.d.ts.map +1 -0
- package/dist/authorization/removal.js +283 -0
- package/dist/authorization/removal.js.map +1 -0
- package/dist/authorization/shell-paths.d.ts +66 -0
- package/dist/authorization/shell-paths.d.ts.map +1 -0
- package/dist/authorization/shell-paths.js +697 -0
- package/dist/authorization/shell-paths.js.map +1 -0
- package/dist/bridge/acp/update.d.ts.map +1 -1
- package/dist/bridge/acp/update.js +1 -0
- package/dist/bridge/acp/update.js.map +1 -1
- package/dist/compaction/context-window.d.ts +24 -0
- package/dist/compaction/context-window.d.ts.map +1 -1
- package/dist/compaction/context-window.js +34 -0
- package/dist/compaction/context-window.js.map +1 -1
- package/dist/compaction/manual.d.ts.map +1 -1
- package/dist/compaction/manual.js +10 -2
- package/dist/compaction/manual.js.map +1 -1
- package/dist/compaction/plan.d.ts +4 -0
- package/dist/compaction/plan.d.ts.map +1 -1
- package/dist/compaction/plan.js +6 -2
- package/dist/compaction/plan.js.map +1 -1
- package/dist/compaction/verifier.d.ts +11 -1
- package/dist/compaction/verifier.d.ts.map +1 -1
- package/dist/compaction/verifier.js +19 -7
- package/dist/compaction/verifier.js.map +1 -1
- package/dist/config/runtime.d.ts +55 -7
- package/dist/config/runtime.d.ts.map +1 -1
- package/dist/config/runtime.js +23 -2
- package/dist/config/runtime.js.map +1 -1
- package/dist/connector/web/guarded-fetch.d.ts.map +1 -1
- package/dist/connector/web/guarded-fetch.js +24 -0
- package/dist/connector/web/guarded-fetch.js.map +1 -1
- package/dist/connector/web/index.d.ts +1 -1
- package/dist/connector/web/index.d.ts.map +1 -1
- package/dist/connector/web/page.d.ts +59 -0
- package/dist/connector/web/page.d.ts.map +1 -0
- package/dist/connector/web/page.js +112 -0
- package/dist/connector/web/page.js.map +1 -0
- package/dist/connector/web/types.d.ts +47 -0
- package/dist/connector/web/types.d.ts.map +1 -1
- package/dist/connector/web/types.js.map +1 -1
- package/dist/constants/continuation.d.ts +8 -0
- package/dist/constants/continuation.d.ts.map +1 -1
- package/dist/constants/continuation.js +8 -0
- package/dist/constants/continuation.js.map +1 -1
- package/dist/constants/plugin/index.d.ts +1 -1
- package/dist/constants/plugin/index.d.ts.map +1 -1
- package/dist/constants/plugin/index.js +1 -1
- package/dist/constants/plugin/index.js.map +1 -1
- package/dist/manager/agent/lifecycle.d.ts +7 -0
- package/dist/manager/agent/lifecycle.d.ts.map +1 -1
- package/dist/manager/agent/lifecycle.js +11 -2
- package/dist/manager/agent/lifecycle.js.map +1 -1
- package/dist/manager/session/turn-recorder.d.ts.map +1 -1
- package/dist/manager/session/turn-recorder.js +4 -2
- package/dist/manager/session/turn-recorder.js.map +1 -1
- package/dist/plugin/index.d.ts +1 -1
- package/dist/plugin/index.d.ts.map +1 -1
- package/dist/plugin/index.js +1 -1
- package/dist/plugin/index.js.map +1 -1
- package/dist/plugin/lifecycle.d.ts +6 -0
- package/dist/plugin/lifecycle.d.ts.map +1 -1
- package/dist/plugin/lifecycle.js +98 -114
- package/dist/plugin/lifecycle.js.map +1 -1
- package/dist/plugin/shell-hook.d.ts +90 -22
- package/dist/plugin/shell-hook.d.ts.map +1 -1
- package/dist/plugin/shell-hook.js +434 -41
- package/dist/plugin/shell-hook.js.map +1 -1
- package/dist/public-runtime.d.ts +4 -1
- package/dist/public-runtime.d.ts.map +1 -1
- package/dist/public-runtime.js +4 -1
- package/dist/public-runtime.js.map +1 -1
- package/dist/public-types.d.ts +2 -2
- package/dist/public-types.d.ts.map +1 -1
- package/dist/runtime/jobs/registry.d.ts +21 -0
- package/dist/runtime/jobs/registry.d.ts.map +1 -1
- package/dist/runtime/jobs/registry.js +15 -2
- package/dist/runtime/jobs/registry.js.map +1 -1
- package/dist/runtime/query/executor/tool-call-admission.d.ts +10 -0
- package/dist/runtime/query/executor/tool-call-admission.d.ts.map +1 -1
- package/dist/runtime/query/executor/tool-call-admission.js +74 -13
- package/dist/runtime/query/executor/tool-call-admission.js.map +1 -1
- package/dist/runtime/query/executor.d.ts +41 -2
- package/dist/runtime/query/executor.d.ts.map +1 -1
- package/dist/runtime/query/executor.js +190 -6
- package/dist/runtime/query/executor.js.map +1 -1
- package/dist/runtime/query/finalize-turn.d.ts +6 -0
- package/dist/runtime/query/finalize-turn.d.ts.map +1 -1
- package/dist/runtime/query/finalize-turn.js +1 -1
- package/dist/runtime/query/finalize-turn.js.map +1 -1
- package/dist/runtime/query/index.d.ts +29 -0
- package/dist/runtime/query/index.d.ts.map +1 -1
- package/dist/runtime/query/index.js +15 -3
- package/dist/runtime/query/index.js.map +1 -1
- package/dist/runtime/query/iteration/index.d.ts +31 -0
- package/dist/runtime/query/iteration/index.d.ts.map +1 -1
- package/dist/runtime/query/iteration/index.js +216 -7
- package/dist/runtime/query/iteration/index.js.map +1 -1
- package/dist/runtime/query/iteration/phases/compaction-breaker.d.ts +58 -0
- package/dist/runtime/query/iteration/phases/compaction-breaker.d.ts.map +1 -0
- package/dist/runtime/query/iteration/phases/compaction-breaker.js +91 -0
- package/dist/runtime/query/iteration/phases/compaction-breaker.js.map +1 -0
- package/dist/runtime/query/iteration/phases/compaction.d.ts.map +1 -1
- package/dist/runtime/query/iteration/phases/compaction.js +89 -7
- package/dist/runtime/query/iteration/phases/compaction.js.map +1 -1
- package/dist/runtime/query/iteration/phases/context.d.ts +10 -0
- package/dist/runtime/query/iteration/phases/context.d.ts.map +1 -1
- package/dist/runtime/query/iteration/phases/context.js.map +1 -1
- package/dist/runtime/query/iteration/phases/tool-review.d.ts.map +1 -1
- package/dist/runtime/query/iteration/phases/tool-review.js +165 -2
- package/dist/runtime/query/iteration/phases/tool-review.js.map +1 -1
- package/dist/runtime/query/path-escalation.d.ts +36 -0
- package/dist/runtime/query/path-escalation.d.ts.map +1 -0
- package/dist/runtime/query/path-escalation.js +184 -0
- package/dist/runtime/query/path-escalation.js.map +1 -0
- package/dist/runtime/query/plugin-hooks.d.ts.map +1 -1
- package/dist/runtime/query/plugin-hooks.js +8 -0
- package/dist/runtime/query/plugin-hooks.js.map +1 -1
- package/dist/runtime/query/reminders.d.ts +35 -0
- package/dist/runtime/query/reminders.d.ts.map +1 -0
- package/dist/runtime/query/reminders.js +7 -0
- package/dist/runtime/query/reminders.js.map +1 -0
- package/dist/runtime/query/resume-pending.d.ts.map +1 -1
- package/dist/runtime/query/resume-pending.js +26 -0
- package/dist/runtime/query/resume-pending.js.map +1 -1
- package/dist/runtime/query/review-policy.d.ts +26 -0
- package/dist/runtime/query/review-policy.d.ts.map +1 -1
- package/dist/runtime/query/review-policy.js +79 -5
- package/dist/runtime/query/review-policy.js.map +1 -1
- package/dist/runtime/query/tool-output-budget.d.ts +46 -0
- package/dist/runtime/query/tool-output-budget.d.ts.map +1 -1
- package/dist/runtime/query/tool-output-budget.js +85 -1
- package/dist/runtime/query/tool-output-budget.js.map +1 -1
- package/dist/runtime/query/tooling.d.ts +1 -0
- package/dist/runtime/query/tooling.d.ts.map +1 -1
- package/dist/runtime/query/tooling.js +5 -0
- package/dist/runtime/query/tooling.js.map +1 -1
- package/dist/session/paths.d.ts +5 -1
- package/dist/session/paths.d.ts.map +1 -1
- package/dist/session/paths.js +8 -0
- package/dist/session/paths.js.map +1 -1
- package/dist/store/memory/disk.d.ts.map +1 -1
- package/dist/store/memory/disk.js +2 -2
- package/dist/store/memory/disk.js.map +1 -1
- package/dist/store/memory/markdown.d.ts.map +1 -1
- package/dist/store/memory/markdown.js +2 -2
- package/dist/store/memory/markdown.js.map +1 -1
- package/dist/store/memory/naming.d.ts +9 -0
- package/dist/store/memory/naming.d.ts.map +1 -1
- package/dist/store/memory/naming.js +12 -0
- package/dist/store/memory/naming.js.map +1 -1
- package/dist/tools/builtins/bash.d.ts +30 -1
- package/dist/tools/builtins/bash.d.ts.map +1 -1
- package/dist/tools/builtins/bash.js +170 -26
- package/dist/tools/builtins/bash.js.map +1 -1
- package/dist/tools/builtins/content-fingerprint.d.ts +2 -0
- package/dist/tools/builtins/content-fingerprint.d.ts.map +1 -1
- package/dist/tools/builtins/content-fingerprint.js +4 -0
- package/dist/tools/builtins/content-fingerprint.js.map +1 -1
- package/dist/tools/builtins/edit.d.ts.map +1 -1
- package/dist/tools/builtins/edit.js +60 -18
- package/dist/tools/builtins/edit.js.map +1 -1
- package/dist/tools/builtins/grep.d.ts +8 -1
- package/dist/tools/builtins/grep.d.ts.map +1 -1
- package/dist/tools/builtins/grep.js +152 -33
- package/dist/tools/builtins/grep.js.map +1 -1
- package/dist/tools/builtins/read-file.d.ts +1 -0
- package/dist/tools/builtins/read-file.d.ts.map +1 -1
- package/dist/tools/builtins/read-file.js +44 -5
- package/dist/tools/builtins/read-file.js.map +1 -1
- package/dist/tools/builtins/read-render.d.ts +52 -0
- package/dist/tools/builtins/read-render.d.ts.map +1 -1
- package/dist/tools/builtins/read-render.js +143 -0
- package/dist/tools/builtins/read-render.js.map +1 -1
- package/dist/tools/builtins/web.d.ts +13 -2
- package/dist/tools/builtins/web.d.ts.map +1 -1
- package/dist/tools/builtins/web.js +225 -32
- package/dist/tools/builtins/web.js.map +1 -1
- package/dist/tools/coordinator/ask-user-question.d.ts +2 -0
- package/dist/tools/coordinator/ask-user-question.d.ts.map +1 -1
- package/dist/tools/coordinator/ask-user-question.js +256 -92
- package/dist/tools/coordinator/ask-user-question.js.map +1 -1
- package/dist/tools/coordinator/question-options.d.ts +1 -0
- package/dist/tools/coordinator/question-options.d.ts.map +1 -1
- package/dist/tools/coordinator/question-options.js +6 -1
- package/dist/tools/coordinator/question-options.js.map +1 -1
- package/dist/tools/defineTool.d.ts +4 -1
- package/dist/tools/defineTool.d.ts.map +1 -1
- package/dist/tools/defineTool.js +6 -1
- package/dist/tools/defineTool.js.map +1 -1
- package/dist/tools/paths.d.ts +6 -0
- package/dist/tools/paths.d.ts.map +1 -1
- package/dist/tools/paths.js +1 -1
- package/dist/tools/paths.js.map +1 -1
- package/dist/types/agent/query.d.ts +3 -0
- package/dist/types/agent/query.d.ts.map +1 -1
- package/dist/types/errors/catalog.js +1 -1
- package/dist/types/errors/catalog.js.map +1 -1
- package/dist/types/hitl/index.d.ts +104 -0
- package/dist/types/hitl/index.d.ts.map +1 -1
- package/dist/types/hitl/index.js.map +1 -1
- package/dist/types/message/index.d.ts +1 -1
- package/dist/types/message/index.d.ts.map +1 -1
- package/dist/types/message/index.js +2 -0
- package/dist/types/message/index.js.map +1 -1
- package/dist/types/plugin/index.d.ts +93 -19
- package/dist/types/plugin/index.d.ts.map +1 -1
- package/dist/types/plugin/index.js +3 -0
- package/dist/types/plugin/index.js.map +1 -1
- package/dist/types/provider/errors.d.ts +19 -0
- package/dist/types/provider/errors.d.ts.map +1 -1
- package/dist/types/provider/errors.js +24 -0
- package/dist/types/provider/errors.js.map +1 -1
- package/dist/types/session/events.d.ts +10 -2
- package/dist/types/session/events.d.ts.map +1 -1
- package/dist/types/session/events.js.map +1 -1
- package/dist/types/session/records.d.ts +9 -9
- package/dist/types/session/records.d.ts.map +1 -1
- package/dist/types/session/records.js +1 -0
- package/dist/types/session/records.js.map +1 -1
- package/dist/types/session/stop-reason.d.ts +5 -0
- package/dist/types/session/stop-reason.d.ts.map +1 -1
- package/dist/types/tool/index.d.ts +52 -0
- package/dist/types/tool/index.d.ts.map +1 -1
- package/dist/types/tool/index.js.map +1 -1
- package/package.json +4 -2
- package/src/agents/QueryAgent.ts +5 -1
- package/src/agents/SupervisorAgent.ts +1 -1
- package/src/agents/examples/SupervisorAgent.ts +217 -106
- package/src/agents/index.ts +1 -1
- package/src/authorization/protected-paths.ts +110 -0
- package/src/authorization/readonly-commands.ts +771 -0
- package/src/authorization/readonly-flags.ts +196 -0
- package/src/authorization/removal.ts +326 -0
- package/src/authorization/shell-paths.ts +927 -0
- package/src/bridge/acp/update.ts +1 -0
- package/src/compaction/context-window.ts +41 -0
- package/src/compaction/manual.ts +10 -2
- package/src/compaction/plan.ts +11 -2
- package/src/compaction/verifier.ts +28 -3
- package/src/config/runtime.ts +23 -2
- package/src/connector/web/guarded-fetch.ts +26 -0
- package/src/connector/web/index.ts +3 -0
- package/src/connector/web/page.ts +130 -0
- package/src/connector/web/types.ts +47 -0
- package/src/constants/continuation.ts +10 -0
- package/src/constants/plugin/index.ts +1 -1
- package/src/manager/agent/lifecycle.ts +12 -4
- package/src/manager/session/turn-recorder.ts +10 -2
- package/src/plugin/index.ts +1 -0
- package/src/plugin/lifecycle.ts +107 -119
- package/src/plugin/shell-hook.ts +477 -43
- package/src/public-runtime.ts +8 -0
- package/src/public-types.ts +4 -0
- package/src/runtime/jobs/registry.ts +39 -2
- package/src/runtime/query/executor/tool-call-admission.ts +79 -13
- package/src/runtime/query/executor.ts +242 -8
- package/src/runtime/query/finalize-turn.ts +7 -1
- package/src/runtime/query/index.ts +45 -3
- package/src/runtime/query/iteration/index.ts +251 -12
- package/src/runtime/query/iteration/phases/compaction-breaker.ts +106 -0
- package/src/runtime/query/iteration/phases/compaction.ts +99 -12
- package/src/runtime/query/iteration/phases/context.ts +11 -0
- package/src/runtime/query/iteration/phases/tool-review.ts +177 -2
- package/src/runtime/query/path-escalation.ts +204 -0
- package/src/runtime/query/plugin-hooks.ts +8 -0
- package/src/runtime/query/reminders.ts +45 -0
- package/src/runtime/query/resume-pending.ts +27 -0
- package/src/runtime/query/review-policy.ts +106 -5
- package/src/runtime/query/tool-output-budget.ts +115 -1
- package/src/runtime/query/tooling.ts +6 -0
- package/src/session/paths.ts +11 -1
- package/src/store/memory/disk.ts +2 -1
- package/src/store/memory/markdown.ts +2 -1
- package/src/store/memory/naming.ts +13 -0
- package/src/tools/builtins/bash.ts +203 -34
- package/src/tools/builtins/content-fingerprint.ts +5 -0
- package/src/tools/builtins/edit.ts +69 -19
- package/src/tools/builtins/grep.ts +159 -38
- package/src/tools/builtins/read-file.ts +48 -5
- package/src/tools/builtins/read-render.ts +193 -0
- package/src/tools/builtins/web.ts +258 -33
- package/src/tools/coordinator/ask-user-question.ts +309 -103
- package/src/tools/coordinator/question-options.ts +8 -1
- package/src/tools/defineTool.ts +11 -2
- package/src/tools/paths.ts +1 -1
- package/src/types/agent/query.ts +3 -0
- package/src/types/errors/catalog.ts +1 -1
- package/src/types/hitl/index.ts +104 -0
- package/src/types/message/index.ts +2 -0
- package/src/types/plugin/index.ts +101 -18
- package/src/types/provider/errors.ts +33 -0
- package/src/types/session/events.ts +10 -2
- package/src/types/session/records.ts +1 -0
- package/src/types/session/stop-reason.ts +5 -0
- package/src/types/tool/index.ts +53 -2
|
@@ -32,7 +32,7 @@ import {
|
|
|
32
32
|
createToolMessage,
|
|
33
33
|
} from '../../types/message/index.js'
|
|
34
34
|
import type { PermissionMode } from '../../types/permission/index.js'
|
|
35
|
-
import type { PluginHookResult } from '../../types/plugin/index.js'
|
|
35
|
+
import type { PluginHookPermission, PluginHookResult } from '../../types/plugin/index.js'
|
|
36
36
|
import type { ChatCompletionResponse } from '../../types/provider/index.js'
|
|
37
37
|
import type { Sandbox } from '../../types/sandbox/index.js'
|
|
38
38
|
import type { AuditEventInput } from '../../types/session/audit.js'
|
|
@@ -65,6 +65,7 @@ import { type BackgroundJobRegistry, type JobProcess, bindOwner } from '../jobs/
|
|
|
65
65
|
import {
|
|
66
66
|
type ToolAdmissionHost,
|
|
67
67
|
formatFailedToolOutput,
|
|
68
|
+
hookNote,
|
|
68
69
|
isUnregistered,
|
|
69
70
|
prepareDirectCall,
|
|
70
71
|
runPreToolHook,
|
|
@@ -73,14 +74,17 @@ import {
|
|
|
73
74
|
import { describeVisibleFileEvidence } from './file-evidence-context.js'
|
|
74
75
|
import { seedObservationLedger } from './file-evidence-seed.js'
|
|
75
76
|
import { DEFAULT_TOOL_RESULT_GUARDRAILS } from './guardrail-presets.js'
|
|
77
|
+
import { declaredWriteEscalation, shellEscalations } from './path-escalation.js'
|
|
76
78
|
import type { ToolResultObservation } from './project-instructions.js'
|
|
77
79
|
import { savedPresentation } from './saved-presentation.js'
|
|
78
80
|
import { ToolCallBudget, assertMaxToolCalls } from './tool-call-budget.js'
|
|
79
81
|
import {
|
|
80
82
|
DEFAULT_MAX_TOOL_OUTPUT_CHARS,
|
|
83
|
+
DEFAULT_MAX_TOOL_OUTPUT_CHARS_PER_MESSAGE,
|
|
81
84
|
type ToolOutputBudgetResult,
|
|
82
85
|
applyToolOutputBudget,
|
|
83
86
|
describeDroppedContent,
|
|
87
|
+
fitResultsToMessageBudget,
|
|
84
88
|
measureContentBytes,
|
|
85
89
|
} from './tool-output-budget.js'
|
|
86
90
|
|
|
@@ -94,6 +98,7 @@ export type PreparedDirectCall =
|
|
|
94
98
|
readonly toolName: string
|
|
95
99
|
readonly input: unknown
|
|
96
100
|
readonly prepared: PreparedToolExecution
|
|
101
|
+
readonly hook?: PreToolHookNotes
|
|
97
102
|
}
|
|
98
103
|
| {
|
|
99
104
|
readonly kind: 'legacy'
|
|
@@ -101,6 +106,7 @@ export type PreparedDirectCall =
|
|
|
101
106
|
readonly toolName: string
|
|
102
107
|
readonly input: unknown
|
|
103
108
|
readonly inputFailure?: CompletedToolRecord['inputFailure']
|
|
109
|
+
readonly hook?: PreToolHookNotes
|
|
104
110
|
}
|
|
105
111
|
| {
|
|
106
112
|
readonly kind: 'synthetic'
|
|
@@ -129,6 +135,8 @@ export interface PreparedToolBatch {
|
|
|
129
135
|
readonly input: unknown
|
|
130
136
|
/** What the prepared value reaches past the turn's boundary; see `ToolCallSummary.escalation`. */
|
|
131
137
|
readonly escalation?: ToolCallEscalation
|
|
138
|
+
/** What a `pre_tool_use` hook asked for this call's approval; see `ToolCallSummary.hookPermission`. */
|
|
139
|
+
readonly hookPermission?: PluginHookPermission
|
|
132
140
|
}[]
|
|
133
141
|
}
|
|
134
142
|
|
|
@@ -137,6 +145,16 @@ interface OwnedPreparedToolBatch extends PreparedToolBatch {
|
|
|
137
145
|
readonly escalations: ReadonlyMap<string, ToolCallEscalation>
|
|
138
146
|
}
|
|
139
147
|
|
|
148
|
+
/**
|
|
149
|
+
* A nested call cannot open a review from inside the tool that issued it, so
|
|
150
|
+
* a hook that asked for a person to approve it can only be answered with a
|
|
151
|
+
* refusal. Silence would run the call the hook wanted a person to see.
|
|
152
|
+
*/
|
|
153
|
+
function askedNestedMessage(toolName: string, outcome: PreToolHookOutcome): string | undefined {
|
|
154
|
+
if (outcome.kind !== 'continue' || outcome.permission?.decision !== 'ask') return undefined
|
|
155
|
+
return `Blocked: a hook asked that a person approve "${toolName}", and an approval cannot be requested from inside another tool. Call it directly.`
|
|
156
|
+
}
|
|
157
|
+
|
|
140
158
|
function assertUniqueToolCallIds(toolCalls: readonly ToolCall[]): void {
|
|
141
159
|
const seen = new Set<string>()
|
|
142
160
|
for (const [index, toolCall] of toolCalls.entries()) {
|
|
@@ -420,6 +438,8 @@ export interface ToolExecutorConfig {
|
|
|
420
438
|
* {@link DEFAULT_MAX_TOOL_OUTPUT_CHARS}; set `0` to disable.
|
|
421
439
|
*/
|
|
422
440
|
maxToolOutputChars?: number
|
|
441
|
+
/** See QueryParams.maxToolOutputCharsPerMessage. */
|
|
442
|
+
maxToolOutputCharsPerMessage?: number
|
|
423
443
|
/** See QueryParams.retainedToolPreviewChars; applies to the recorded host output. */
|
|
424
444
|
retainedToolPreviewChars?: number
|
|
425
445
|
|
|
@@ -493,8 +513,16 @@ interface PostToolOverride {
|
|
|
493
513
|
readonly content?: ToolResultContent
|
|
494
514
|
}
|
|
495
515
|
|
|
516
|
+
/** What `pre_tool_use` hooks said about a call beyond running it or not. */
|
|
517
|
+
export interface PreToolHookNotes {
|
|
518
|
+
/** The strictest permission answer among the hooks: `ask` outranks `allow`. */
|
|
519
|
+
readonly permission?: PluginHookPermission
|
|
520
|
+
/** Hook text for the model, appended to what it reads of this call. */
|
|
521
|
+
readonly context?: string
|
|
522
|
+
}
|
|
523
|
+
|
|
496
524
|
export type PreToolHookOutcome =
|
|
497
|
-
| { kind: 'continue'; input: unknown; modified: boolean }
|
|
525
|
+
| ({ kind: 'continue'; input: unknown; modified: boolean } & PreToolHookNotes)
|
|
498
526
|
| { kind: 'skip'; input: unknown; output: string }
|
|
499
527
|
| { kind: 'error'; input: unknown; output: string }
|
|
500
528
|
|
|
@@ -1003,11 +1031,80 @@ export class ToolExecutor {
|
|
|
1003
1031
|
tool.sandboxEscapeArgument !== undefined &&
|
|
1004
1032
|
input[tool.sandboxEscapeArgument] === true
|
|
1005
1033
|
const unknownProgram = this.unknownProgramOf(tool, input, sandboxed)
|
|
1006
|
-
|
|
1034
|
+
const reaches = await this.pathEscalationsOf(tool, input, sandboxed)
|
|
1035
|
+
if (reaches.outsidePaths.length > 0) {
|
|
1036
|
+
outsidePaths = [...new Set([...(outsidePaths ?? []), ...reaches.outsidePaths])]
|
|
1037
|
+
}
|
|
1038
|
+
const protectedPaths = reaches.protectedPaths
|
|
1039
|
+
const removal = reaches.dangerousRemoval
|
|
1040
|
+
if (
|
|
1041
|
+
!outsidePaths &&
|
|
1042
|
+
!sandboxEscape &&
|
|
1043
|
+
unknownProgram === undefined &&
|
|
1044
|
+
protectedPaths.length === 0 &&
|
|
1045
|
+
removal === undefined
|
|
1046
|
+
) {
|
|
1047
|
+
return undefined
|
|
1048
|
+
}
|
|
1007
1049
|
return {
|
|
1008
1050
|
...(outsidePaths ? { outsidePaths } : {}),
|
|
1009
1051
|
...(sandboxEscape ? { sandboxEscape: true as const } : {}),
|
|
1010
1052
|
...(unknownProgram !== undefined ? { unknownProgram } : {}),
|
|
1053
|
+
...(protectedPaths.length > 0 ? { protectedPaths } : {}),
|
|
1054
|
+
...(removal !== undefined ? { dangerousRemoval: removal } : {}),
|
|
1055
|
+
}
|
|
1056
|
+
}
|
|
1057
|
+
|
|
1058
|
+
/**
|
|
1059
|
+
* What the call's own arguments write or remove that no mode may approve in
|
|
1060
|
+
* advance, and, for a shell line, the paths outside the roots it names.
|
|
1061
|
+
*
|
|
1062
|
+
* The protected-path and removal floors hold whether or not the turn reviews
|
|
1063
|
+
* outside paths and whether or not it is sandboxed: they are about what the
|
|
1064
|
+
* write plants and what the removal destroys, not about where the turn is
|
|
1065
|
+
* allowed to look. The outside-path half follows `outsideRootAccess`, as the
|
|
1066
|
+
* file tools' own does.
|
|
1067
|
+
*/
|
|
1068
|
+
private async pathEscalationsOf(
|
|
1069
|
+
tool: Pick<
|
|
1070
|
+
ToolDefinition,
|
|
1071
|
+
'pathArgument' | 'commandArgument' | 'commandDialect' | 'isReadOnly'
|
|
1072
|
+
>,
|
|
1073
|
+
input: Record<string, unknown>,
|
|
1074
|
+
sandboxed: boolean,
|
|
1075
|
+
): Promise<{
|
|
1076
|
+
outsidePaths: readonly string[]
|
|
1077
|
+
protectedPaths: readonly string[]
|
|
1078
|
+
dangerousRemoval?: string
|
|
1079
|
+
}> {
|
|
1080
|
+
const roots = toolRoots(this.config)
|
|
1081
|
+
const protectedPaths: string[] = []
|
|
1082
|
+
let outsidePaths: readonly string[] = []
|
|
1083
|
+
let removal: string | undefined
|
|
1084
|
+
if (tool.pathArgument !== undefined && tool.isReadOnly?.(input) !== true) {
|
|
1085
|
+
const value = input[tool.pathArgument]
|
|
1086
|
+
if (typeof value === 'string') {
|
|
1087
|
+
const hit = await declaredWriteEscalation(roots, value)
|
|
1088
|
+
if (hit !== undefined) protectedPaths.push(hit)
|
|
1089
|
+
}
|
|
1090
|
+
}
|
|
1091
|
+
if (tool.commandArgument !== undefined) {
|
|
1092
|
+
const line = input[tool.commandArgument]
|
|
1093
|
+
if (typeof line === 'string') {
|
|
1094
|
+
const dialect = tool.commandDialect?.({ sandboxed }) ?? 'sh'
|
|
1095
|
+
const found = await shellEscalations(line, dialect, {
|
|
1096
|
+
roots,
|
|
1097
|
+
reviewOutside: this.config.outsideRootAccess === 'review' && !sandboxed,
|
|
1098
|
+
})
|
|
1099
|
+
protectedPaths.push(...found.protectedPaths)
|
|
1100
|
+
outsidePaths = found.outsidePaths
|
|
1101
|
+
removal = found.dangerousRemoval
|
|
1102
|
+
}
|
|
1103
|
+
}
|
|
1104
|
+
return {
|
|
1105
|
+
outsidePaths,
|
|
1106
|
+
protectedPaths: [...new Set(protectedPaths)],
|
|
1107
|
+
...(removal !== undefined ? { dangerousRemoval: removal } : {}),
|
|
1011
1108
|
}
|
|
1012
1109
|
}
|
|
1013
1110
|
|
|
@@ -1022,7 +1119,10 @@ export class ToolExecutor {
|
|
|
1022
1119
|
* outside one.
|
|
1023
1120
|
*/
|
|
1024
1121
|
private unknownProgramOf(
|
|
1025
|
-
tool: {
|
|
1122
|
+
tool: {
|
|
1123
|
+
commandArgument?: string
|
|
1124
|
+
commandDialect?: ToolDefinition['commandDialect']
|
|
1125
|
+
},
|
|
1026
1126
|
input: Record<string, unknown>,
|
|
1027
1127
|
sandboxed: boolean,
|
|
1028
1128
|
): string | undefined {
|
|
@@ -1069,11 +1169,13 @@ export class ToolExecutor {
|
|
|
1069
1169
|
)
|
|
1070
1170
|
.map((call) => {
|
|
1071
1171
|
const escalation = escalations.get(call.toolCall.id)
|
|
1172
|
+
const hookPermission = call.hook?.permission
|
|
1072
1173
|
return {
|
|
1073
1174
|
id: call.toolCall.id,
|
|
1074
1175
|
name: call.toolName,
|
|
1075
1176
|
input: call.input,
|
|
1076
1177
|
...(escalation ? { escalation } : {}),
|
|
1178
|
+
...(hookPermission ? { hookPermission } : {}),
|
|
1077
1179
|
}
|
|
1078
1180
|
})
|
|
1079
1181
|
const batch: OwnedPreparedToolBatch = Object.freeze({
|
|
@@ -1327,6 +1429,8 @@ export class ToolExecutor {
|
|
|
1327
1429
|
})
|
|
1328
1430
|
}
|
|
1329
1431
|
|
|
1432
|
+
this.fitBatchToMessageBudget(results)
|
|
1433
|
+
|
|
1330
1434
|
// isError and rich content were computed and then discarded here: the
|
|
1331
1435
|
// tuple narrowed to {toolCallId, output} BEFORE the message was built,
|
|
1332
1436
|
// so the failure signal and any image block were structurally lost at
|
|
@@ -1338,6 +1442,51 @@ export class ToolExecutor {
|
|
|
1338
1442
|
return { messages, results, observations }
|
|
1339
1443
|
}
|
|
1340
1444
|
|
|
1445
|
+
/**
|
|
1446
|
+
* Hold the batch's combined result text under the per-message cap.
|
|
1447
|
+
*
|
|
1448
|
+
* Runs once, on the settled batch and before the results become history
|
|
1449
|
+
* messages, so what it writes is what every later request replays.
|
|
1450
|
+
*/
|
|
1451
|
+
private fitBatchToMessageBudget(results: ToolCallOutcome[]): void {
|
|
1452
|
+
const maxChars =
|
|
1453
|
+
this.config.maxToolOutputCharsPerMessage ?? DEFAULT_MAX_TOOL_OUTPUT_CHARS_PER_MESSAGE
|
|
1454
|
+
const replacements = fitResultsToMessageBudget(
|
|
1455
|
+
results.map((r) => ({
|
|
1456
|
+
toolCallId: r.toolCallId,
|
|
1457
|
+
toolName: r.toolName,
|
|
1458
|
+
output: r.output,
|
|
1459
|
+
// A result carrying rich content or a structured-output copy is
|
|
1460
|
+
// not text the model reads alone, and a self-limiting tool has
|
|
1461
|
+
// already decided its own size.
|
|
1462
|
+
replaceable:
|
|
1463
|
+
r.content === undefined &&
|
|
1464
|
+
r.structuredResultJson === undefined &&
|
|
1465
|
+
this.config.tools.get(r.toolName)?.selfLimitingOutput !== true,
|
|
1466
|
+
})),
|
|
1467
|
+
{
|
|
1468
|
+
maxChars,
|
|
1469
|
+
spillDir: this.outputDirectory(),
|
|
1470
|
+
onError: (message) =>
|
|
1471
|
+
this.log.warn('Failed to retain a tool output replaced for the message budget', {
|
|
1472
|
+
[NAMZU.TURN_ID]: this.config.turnId,
|
|
1473
|
+
'exception.message': message,
|
|
1474
|
+
}),
|
|
1475
|
+
},
|
|
1476
|
+
)
|
|
1477
|
+
if (replacements.size === 0) return
|
|
1478
|
+
for (const [i, r] of results.entries()) {
|
|
1479
|
+
const replacement = replacements.get(r.toolCallId)
|
|
1480
|
+
if (replacement === undefined) continue
|
|
1481
|
+
results[i] = { ...r, output: replacement.output }
|
|
1482
|
+
}
|
|
1483
|
+
this.log.warn("Tool results exceeded the message's combined budget", {
|
|
1484
|
+
[NAMZU.TURN_ID]: this.config.turnId,
|
|
1485
|
+
'namzu.runtime.replaced_count': replacements.size,
|
|
1486
|
+
'namzu.runtime.message_budget_chars': maxChars,
|
|
1487
|
+
})
|
|
1488
|
+
}
|
|
1489
|
+
|
|
1341
1490
|
/**
|
|
1342
1491
|
* Run a tool on behalf of another tool, and put it on the record.
|
|
1343
1492
|
*
|
|
@@ -1802,8 +1951,10 @@ export class ToolExecutor {
|
|
|
1802
1951
|
let input: unknown
|
|
1803
1952
|
let prepared: PreparedToolExecution | undefined
|
|
1804
1953
|
let inputFailure: ToolCallOutcome['inputFailure']
|
|
1954
|
+
let preparedHookContext: string | undefined
|
|
1805
1955
|
|
|
1806
1956
|
if (preparedCall?.kind === 'ready' || preparedCall?.kind === 'legacy') {
|
|
1957
|
+
preparedHookContext = preparedCall.hook?.context
|
|
1807
1958
|
input = preparedCall.input
|
|
1808
1959
|
prepared = preparedCall.kind === 'ready' ? preparedCall.prepared : undefined
|
|
1809
1960
|
if (preparedCall.kind === 'legacy') inputFailure = preparedCall.inputFailure
|
|
@@ -1824,6 +1975,7 @@ export class ToolExecutor {
|
|
|
1824
1975
|
if (admitted.kind === 'synthetic') return this.recordSyntheticPreparation(admitted)
|
|
1825
1976
|
toolName = admitted.toolName
|
|
1826
1977
|
input = admitted.input
|
|
1978
|
+
preparedHookContext = admitted.hook?.context
|
|
1827
1979
|
prepared = admitted.kind === 'ready' ? admitted.prepared : undefined
|
|
1828
1980
|
if (admitted.kind === 'legacy') inputFailure = admitted.inputFailure
|
|
1829
1981
|
}
|
|
@@ -2029,7 +2181,11 @@ export class ToolExecutor {
|
|
|
2029
2181
|
]
|
|
2030
2182
|
}
|
|
2031
2183
|
}
|
|
2032
|
-
|
|
2184
|
+
// A tool that bounds its own output is exempt from the DEFAULT per-result
|
|
2185
|
+
// cap only; a host that set the cap explicitly still gets it.
|
|
2186
|
+
const maxToolOutputChars =
|
|
2187
|
+
this.config.maxToolOutputChars ??
|
|
2188
|
+
(executedDefinition?.selfLimitingOutput === true ? 0 : DEFAULT_MAX_TOOL_OUTPUT_CHARS)
|
|
2033
2189
|
const sourceOutput = output
|
|
2034
2190
|
// This owner-bound channel follows the selected receipt after both result
|
|
2035
2191
|
// screening and post-tool replacement. ToolResult.data and raw input can
|
|
@@ -2085,13 +2241,26 @@ export class ToolExecutor {
|
|
|
2085
2241
|
})
|
|
2086
2242
|
}
|
|
2087
2243
|
output = budgeted.output
|
|
2088
|
-
|
|
2244
|
+
let modelContent =
|
|
2089
2245
|
selectedContent === undefined
|
|
2090
2246
|
? undefined
|
|
2091
2247
|
: this.budgetContent(selectedContent, toolName, toolCall.id, {
|
|
2092
2248
|
sourceOutput,
|
|
2093
2249
|
budgeted,
|
|
2094
2250
|
})
|
|
2251
|
+
// What hooks said about this call rides with its result, in the model's
|
|
2252
|
+
// receipt and the host's alike, framed as a hook's words. Added after
|
|
2253
|
+
// the output budget so a bounded result is never trimmed to make room
|
|
2254
|
+
// for it; the note has its own bound (`hookNote`).
|
|
2255
|
+
const hookTexts = [preparedHookContext, post.context].filter(
|
|
2256
|
+
(text): text is string => text !== undefined && text.length > 0,
|
|
2257
|
+
)
|
|
2258
|
+
if (hookTexts.length > 0) {
|
|
2259
|
+
const note = hookNote(hookTexts)
|
|
2260
|
+
output = `${output}\n\n${note}`
|
|
2261
|
+
if (typeof modelContent === 'string') modelContent = `${modelContent}\n\n${note}`
|
|
2262
|
+
else if (modelContent) modelContent = [...modelContent, { type: 'text', text: note }]
|
|
2263
|
+
}
|
|
2095
2264
|
|
|
2096
2265
|
// A failed call, or an override that says the call failed. A `replace`
|
|
2097
2266
|
// says the opposite, and reading it as a failure is what made redaction
|
|
@@ -2438,9 +2607,25 @@ export class ToolExecutor {
|
|
|
2438
2607
|
emitEvent: this.emitEvent,
|
|
2439
2608
|
log: this.log,
|
|
2440
2609
|
allowedTools: this.effectiveAllowedTools(),
|
|
2610
|
+
requestHalt: (reason) => this.requestHalt(reason),
|
|
2441
2611
|
}
|
|
2442
2612
|
}
|
|
2443
2613
|
|
|
2614
|
+
/** Why a hook asked for the turn to stop, until the iteration loop reads it. */
|
|
2615
|
+
private haltReason: string | undefined
|
|
2616
|
+
|
|
2617
|
+
/** The first request wins: a later hook does not rewrite why the turn stopped. */
|
|
2618
|
+
requestHalt(reason: string): void {
|
|
2619
|
+
this.haltReason ??= reason
|
|
2620
|
+
}
|
|
2621
|
+
|
|
2622
|
+
/** Read and clear a hook's request to stop the turn. */
|
|
2623
|
+
takeHalt(): string | undefined {
|
|
2624
|
+
const reason = this.haltReason
|
|
2625
|
+
this.haltReason = undefined
|
|
2626
|
+
return reason
|
|
2627
|
+
}
|
|
2628
|
+
|
|
2444
2629
|
private async prepareNestedCall(
|
|
2445
2630
|
toolName: string,
|
|
2446
2631
|
input: unknown,
|
|
@@ -2468,6 +2653,14 @@ export class ToolExecutor {
|
|
|
2468
2653
|
...(preOutcome.kind === 'skip' ? { skipped: true as const } : {}),
|
|
2469
2654
|
}
|
|
2470
2655
|
}
|
|
2656
|
+
const nestedAsk = askedNestedMessage(toolName, preOutcome)
|
|
2657
|
+
if (nestedAsk)
|
|
2658
|
+
return {
|
|
2659
|
+
kind: 'synthetic',
|
|
2660
|
+
input: preOutcome.input,
|
|
2661
|
+
message: nestedAsk,
|
|
2662
|
+
isError: true,
|
|
2663
|
+
}
|
|
2471
2664
|
return { kind: 'legacy', input: preOutcome.input }
|
|
2472
2665
|
}
|
|
2473
2666
|
|
|
@@ -2513,6 +2706,15 @@ export class ToolExecutor {
|
|
|
2513
2706
|
...(preOutcome.kind === 'skip' ? { skipped: true as const } : {}),
|
|
2514
2707
|
}
|
|
2515
2708
|
}
|
|
2709
|
+
const nestedAsk = askedNestedMessage(toolName, preOutcome)
|
|
2710
|
+
if (nestedAsk) {
|
|
2711
|
+
return {
|
|
2712
|
+
kind: 'synthetic',
|
|
2713
|
+
input: preOutcome.input,
|
|
2714
|
+
message: nestedAsk,
|
|
2715
|
+
isError: true,
|
|
2716
|
+
}
|
|
2717
|
+
}
|
|
2516
2718
|
if (!preOutcome.modified) {
|
|
2517
2719
|
return {
|
|
2518
2720
|
kind: 'ready',
|
|
@@ -2571,12 +2773,17 @@ export class ToolExecutor {
|
|
|
2571
2773
|
/**
|
|
2572
2774
|
* @returns `override` — text replacing the tool's output, or `null`.
|
|
2573
2775
|
* `retry` — the hook asked for the tool to run again.
|
|
2776
|
+
* `context` — what the hooks want the model to read beside the result.
|
|
2574
2777
|
*/
|
|
2575
2778
|
private async runPostToolHook(
|
|
2576
2779
|
toolName: string,
|
|
2577
2780
|
input: unknown,
|
|
2578
2781
|
toolResult: ToolResult,
|
|
2579
|
-
): Promise<{
|
|
2782
|
+
): Promise<{
|
|
2783
|
+
override: PostToolOverride | null
|
|
2784
|
+
retry: boolean
|
|
2785
|
+
context?: string
|
|
2786
|
+
}> {
|
|
2580
2787
|
if (!this.config.pluginManager) return { override: null, retry: false }
|
|
2581
2788
|
let results: PluginHookResult[]
|
|
2582
2789
|
try {
|
|
@@ -2592,6 +2799,26 @@ export class ToolExecutor {
|
|
|
2592
2799
|
},
|
|
2593
2800
|
this.emitEvent,
|
|
2594
2801
|
)
|
|
2802
|
+
// A failed call is announced a second time, by name, so a hook that
|
|
2803
|
+
// only cares about failures need not read every result. After
|
|
2804
|
+
// `post_tool_use`, so the existing hooks see exactly what they saw.
|
|
2805
|
+
if (!toolResult.success) {
|
|
2806
|
+
results = [
|
|
2807
|
+
...results,
|
|
2808
|
+
...(await this.config.pluginManager.executeHooks(
|
|
2809
|
+
'post_tool_use_failure',
|
|
2810
|
+
{
|
|
2811
|
+
sessionId: this.config.sessionId,
|
|
2812
|
+
turnId: this.config.turnId,
|
|
2813
|
+
toolName,
|
|
2814
|
+
toolInput: input,
|
|
2815
|
+
toolResult,
|
|
2816
|
+
signal: this.config.abortSignal,
|
|
2817
|
+
},
|
|
2818
|
+
this.emitEvent,
|
|
2819
|
+
)),
|
|
2820
|
+
]
|
|
2821
|
+
}
|
|
2595
2822
|
} catch (error) {
|
|
2596
2823
|
if (!this.config.abortSignal.aborted) throw error
|
|
2597
2824
|
// The tool has already returned. Cancellation of a later redaction
|
|
@@ -2608,9 +2835,12 @@ export class ToolExecutor {
|
|
|
2608
2835
|
}
|
|
2609
2836
|
let override: PostToolOverride | null = null
|
|
2610
2837
|
let retry = false
|
|
2838
|
+
const contexts: string[] = []
|
|
2611
2839
|
for (const result of results) {
|
|
2612
2840
|
switch (result.action) {
|
|
2613
2841
|
case 'continue':
|
|
2842
|
+
if (result.context) contexts.push(result.context)
|
|
2843
|
+
if (result.halt) this.requestHalt(result.halt.reason)
|
|
2614
2844
|
continue
|
|
2615
2845
|
case 'error':
|
|
2616
2846
|
override = { output: `Error: ${result.message}`, isError: true }
|
|
@@ -2646,7 +2876,11 @@ export class ToolExecutor {
|
|
|
2646
2876
|
}
|
|
2647
2877
|
}
|
|
2648
2878
|
}
|
|
2649
|
-
return {
|
|
2879
|
+
return {
|
|
2880
|
+
override,
|
|
2881
|
+
retry,
|
|
2882
|
+
...(contexts.length > 0 ? { context: contexts.join('\n') } : {}),
|
|
2883
|
+
}
|
|
2650
2884
|
}
|
|
2651
2885
|
|
|
2652
2886
|
/**
|
|
@@ -53,6 +53,12 @@ export interface TurnFinalization {
|
|
|
53
53
|
* immediately before the record is written.
|
|
54
54
|
*/
|
|
55
55
|
readonly takeSteps: () => readonly StepResult[]
|
|
56
|
+
/**
|
|
57
|
+
* Whether the loop already fired `turn_end` (and `subagent_stop`) when the
|
|
58
|
+
* model finished, so a hook could keep the turn going. Fired there, it is
|
|
59
|
+
* not fired again here.
|
|
60
|
+
*/
|
|
61
|
+
readonly turnEndHooksFired?: () => boolean
|
|
56
62
|
readonly workingStateManager: WorkingStateManager | undefined
|
|
57
63
|
readonly resultAssembler: ResultAssembler
|
|
58
64
|
readonly rootSpan: Span
|
|
@@ -71,7 +77,7 @@ export async function* finalizeTurn(
|
|
|
71
77
|
rootSpan,
|
|
72
78
|
} = finalization
|
|
73
79
|
|
|
74
|
-
if (params.pluginManager) {
|
|
80
|
+
if (params.pluginManager && finalization.turnEndHooksFired?.() !== true) {
|
|
75
81
|
const hookResults = await params.pluginManager.executeHooks(
|
|
76
82
|
'turn_end',
|
|
77
83
|
{ sessionId: ctx.sessionId, turnId: ctx.turnId, signal: ctx.abortController.signal },
|
|
@@ -331,6 +331,17 @@ export interface QueryParams {
|
|
|
331
331
|
maxToolConcurrency?: number
|
|
332
332
|
/** Per-turn cumulative tool attempt limit, including nested calls and retries. Unset is unlimited. Re-supply on resume; durable reservations are never refunded. */
|
|
333
333
|
maxToolCalls?: number
|
|
334
|
+
/**
|
|
335
|
+
* How many times in a row the loop nudges the model to carry on after a
|
|
336
|
+
* reply was cut off at its output limit, before the turn stops with an
|
|
337
|
+
* error naming the limit. The count restarts after any call that finishes
|
|
338
|
+
* on its own.
|
|
339
|
+
*
|
|
340
|
+
* Unset keeps the earlier behaviour: nudge every time, bounded only by
|
|
341
|
+
* `maxIterations`. Opt-in because a cap is a stop a host did not have
|
|
342
|
+
* before; `0` stops at the first cut-off.
|
|
343
|
+
*/
|
|
344
|
+
maxOutputContinuations?: number
|
|
334
345
|
|
|
335
346
|
/**
|
|
336
347
|
* Model-visible size cap for a single tool result. Over-budget output is
|
|
@@ -339,6 +350,18 @@ export interface QueryParams {
|
|
|
339
350
|
* agent decides the rest is worth re-reading. Set `0` to disable.
|
|
340
351
|
*/
|
|
341
352
|
maxToolOutputChars?: number
|
|
353
|
+
/**
|
|
354
|
+
* Cap on the COMBINED model-visible text of every tool result one assistant
|
|
355
|
+
* message produced. Defaults to {@link DEFAULT_MAX_TOOL_OUTPUT_CHARS_PER_MESSAGE}
|
|
356
|
+
* (200,000 characters); `0` disables it. When a batch exceeds it, the
|
|
357
|
+
* largest results are replaced, largest first, by a short preview that
|
|
358
|
+
* names where the full text was kept, until the batch fits. The
|
|
359
|
+
* replacement is written into the result before it reaches the history, so
|
|
360
|
+
* it never changes afterwards and the prompt-cache prefix stays stable.
|
|
361
|
+
* Tools that bound their own output (`selfLimitingOutput`) are never
|
|
362
|
+
* replaced.
|
|
363
|
+
*/
|
|
364
|
+
maxToolOutputCharsPerMessage?: number
|
|
342
365
|
/**
|
|
343
366
|
* Screens to run against every tool result. The turn builds its manager
|
|
344
367
|
* from `toolsets` and gives it this policy.
|
|
@@ -726,6 +749,13 @@ export interface QueryParams {
|
|
|
726
749
|
* started. See `BaseAgentConfig.inboundMessages` for what it closes.
|
|
727
750
|
*/
|
|
728
751
|
inboundMessages?: () => import('../../types/message/index.js').Message[]
|
|
752
|
+
/**
|
|
753
|
+
* Hidden reminders a host feeds into the conversation, asked for before
|
|
754
|
+
* every model request of the turn. Opt-in: omitted, a turn carries none.
|
|
755
|
+
* See {@link ReminderSource}.
|
|
756
|
+
*/
|
|
757
|
+
reminders?: import('./reminders.js').ReminderSource
|
|
758
|
+
|
|
729
759
|
/**
|
|
730
760
|
* Wake a background-task hold when operator input is available, without draining it.
|
|
731
761
|
* Resolve immediately if input is already pending. Otherwise wait for its arrival;
|
|
@@ -1407,6 +1437,11 @@ export async function* query(params: QueryParams): AsyncGenerator<SessionEvent,
|
|
|
1407
1437
|
...(params.maxToolOutputChars !== undefined
|
|
1408
1438
|
? { maxToolOutputChars: params.maxToolOutputChars }
|
|
1409
1439
|
: {}),
|
|
1440
|
+
...(params.maxToolOutputCharsPerMessage !== undefined
|
|
1441
|
+
? {
|
|
1442
|
+
maxToolOutputCharsPerMessage: params.maxToolOutputCharsPerMessage,
|
|
1443
|
+
}
|
|
1444
|
+
: {}),
|
|
1410
1445
|
...(params.toolResultGuardrails !== undefined
|
|
1411
1446
|
? { toolResultGuardrails: params.toolResultGuardrails }
|
|
1412
1447
|
: {}),
|
|
@@ -1474,9 +1509,9 @@ export async function* query(params: QueryParams): AsyncGenerator<SessionEvent,
|
|
|
1474
1509
|
// Normalised once, defaults applied. A host that passes a partial
|
|
1475
1510
|
// object — a strategy and a window, nothing else — used to reach the
|
|
1476
1511
|
// phase with `triggerThreshold` undefined, and `usage < undefined` is
|
|
1477
|
-
// false: the pass ran on every iteration
|
|
1478
|
-
//
|
|
1479
|
-
//
|
|
1512
|
+
// false: the pass ran on every iteration. An absent threshold now means
|
|
1513
|
+
// the derived trigger (`resolveTriggerThreshold`), resolved where it is
|
|
1514
|
+
// compared.
|
|
1480
1515
|
const compactionConfig = params.compactionConfig
|
|
1481
1516
|
? CompactionConfigSchema.parse(params.compactionConfig)
|
|
1482
1517
|
: undefined
|
|
@@ -1635,7 +1670,11 @@ export async function* query(params: QueryParams): AsyncGenerator<SessionEvent,
|
|
|
1635
1670
|
// would leak exactly that way.
|
|
1636
1671
|
...(params.repeatCallAdvisory === false ? {} : { repeatCalls: new RepeatCallTracker() }),
|
|
1637
1672
|
compactionConfig,
|
|
1673
|
+
...(params.maxOutputContinuations !== undefined
|
|
1674
|
+
? { maxOutputContinuations: params.maxOutputContinuations }
|
|
1675
|
+
: {}),
|
|
1638
1676
|
...(params.inboundMessages ? { inboundMessages: params.inboundMessages } : {}),
|
|
1677
|
+
...(params.reminders ? { reminders: params.reminders } : {}),
|
|
1639
1678
|
...(params.durableInbound ? { durableInbound: params.durableInbound } : {}),
|
|
1640
1679
|
...(params.resumeFromCheckpoint ? { resumedInput: queuedForThisRun } : {}),
|
|
1641
1680
|
...(params.waitForInbound ? { waitForInbound: params.waitForInbound } : {}),
|
|
@@ -1666,6 +1705,8 @@ export async function* query(params: QueryParams): AsyncGenerator<SessionEvent,
|
|
|
1666
1705
|
agentBus: params.agentBus,
|
|
1667
1706
|
verificationGate,
|
|
1668
1707
|
pluginManager: params.pluginManager,
|
|
1708
|
+
...(params.parentSessionId !== undefined ? { parentSessionId: params.parentSessionId } : {}),
|
|
1709
|
+
...(params.parentTurnId !== undefined ? { parentTurnId: params.parentTurnId } : {}),
|
|
1669
1710
|
})
|
|
1670
1711
|
|
|
1671
1712
|
const tracer = getTracer()
|
|
@@ -2489,6 +2530,7 @@ export async function* query(params: QueryParams): AsyncGenerator<SessionEvent,
|
|
|
2489
2530
|
params,
|
|
2490
2531
|
eventTranslator,
|
|
2491
2532
|
takeSteps: () => iterationOrchestrator.getSteps(),
|
|
2533
|
+
turnEndHooksFired: () => iterationOrchestrator.turnEndHooksFired,
|
|
2492
2534
|
workingStateManager,
|
|
2493
2535
|
resultAssembler,
|
|
2494
2536
|
rootSpan,
|