@namzu/sdk 51.0.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 +110 -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/bridge/sse/mapper.d.ts.map +1 -1
- package/dist/bridge/sse/mapper.js +1 -0
- package/dist/bridge/sse/mapper.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/provider/errors.d.ts +10 -0
- package/dist/provider/errors.d.ts.map +1 -1
- package/dist/provider/errors.js +16 -0
- package/dist/provider/errors.js.map +1 -1
- package/dist/provider/retry.d.ts +27 -0
- package/dist/provider/retry.d.ts.map +1 -1
- package/dist/provider/retry.js +19 -3
- package/dist/provider/retry.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/iteration/stream-turn.d.ts.map +1 -1
- package/dist/runtime/query/iteration/stream-turn.js +24 -1
- package/dist/runtime/query/iteration/stream-turn.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/error.d.ts +6 -0
- package/dist/types/provider/error.d.ts.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 +39 -1
- package/dist/types/provider/errors.js.map +1 -1
- package/dist/types/provider/stream.d.ts +6 -0
- package/dist/types/provider/stream.d.ts.map +1 -1
- package/dist/types/session/events.d.ts +15 -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/dist/utils/backoff.d.ts +12 -0
- package/dist/utils/backoff.d.ts.map +1 -1
- package/dist/utils/backoff.js +15 -0
- package/dist/utils/backoff.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/bridge/sse/mapper.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/provider/errors.ts +18 -0
- package/src/provider/retry.ts +53 -3
- 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/iteration/stream-turn.ts +24 -1
- 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/error.ts +6 -0
- package/src/types/provider/errors.ts +49 -1
- package/src/types/provider/stream.ts +6 -0
- package/src/types/session/events.ts +15 -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
- package/src/utils/backoff.ts +21 -0
package/src/provider/errors.ts
CHANGED
|
@@ -76,6 +76,8 @@ export class ProviderRequestError extends Error {
|
|
|
76
76
|
* See {@link vendorDetail} for what is kept and what is scrubbed.
|
|
77
77
|
*/
|
|
78
78
|
public readonly detail?: string
|
|
79
|
+
/** The provider's `x-should-retry` verdict, when it sent one; see {@link ProviderRequestErrorInit.shouldRetry}. */
|
|
80
|
+
public readonly shouldRetry?: boolean
|
|
79
81
|
|
|
80
82
|
constructor(init: ProviderRequestErrorInit) {
|
|
81
83
|
super(buildProviderErrorMessage(init))
|
|
@@ -87,6 +89,7 @@ export class ProviderRequestError extends Error {
|
|
|
87
89
|
if (init.status !== undefined) this.status = init.status
|
|
88
90
|
if (init.retryAfterMs !== undefined) this.retryAfterMs = init.retryAfterMs
|
|
89
91
|
if (init.detail !== undefined) this.detail = init.detail
|
|
92
|
+
if (init.shouldRetry !== undefined) this.shouldRetry = init.shouldRetry
|
|
90
93
|
}
|
|
91
94
|
}
|
|
92
95
|
|
|
@@ -273,6 +276,15 @@ export function bodySaysContextOverflow(body: string | undefined | null): boolea
|
|
|
273
276
|
* a negative delay is worse than none, because a caller would treat it as
|
|
274
277
|
* "retry immediately" against a provider that just asked it to wait.
|
|
275
278
|
*/
|
|
279
|
+
/**
|
|
280
|
+
* `x-should-retry` is only read when it says `false`: that is the provider
|
|
281
|
+
* refusing a resend, and it outranks the status code. `true` changes nothing,
|
|
282
|
+
* because a retryable status is already retried.
|
|
283
|
+
*/
|
|
284
|
+
export function parseShouldRetry(value: string | null | undefined): false | undefined {
|
|
285
|
+
return value?.trim().toLowerCase() === 'false' ? false : undefined
|
|
286
|
+
}
|
|
287
|
+
|
|
276
288
|
export function parseRetryAfterMs(
|
|
277
289
|
headerValue: string | null | undefined,
|
|
278
290
|
now: number = Date.now(),
|
|
@@ -525,6 +537,7 @@ export function providerVendorError(input: {
|
|
|
525
537
|
input.retryAfter ?? vendorRetryAfter(error),
|
|
526
538
|
input.now ?? Date.now(),
|
|
527
539
|
)
|
|
540
|
+
const shouldRetry = parseShouldRetry(vendorHeader(error, ['x-should-retry']))
|
|
528
541
|
const fields = error as { type?: unknown; param?: unknown; requestID?: unknown } | null
|
|
529
542
|
// A message that already carries its body (Anthropic's) has the fields; one that is only the
|
|
530
543
|
// parsed sentence (OpenAI's) gets them from the SDK error's own properties.
|
|
@@ -544,6 +557,7 @@ export function providerVendorError(input: {
|
|
|
544
557
|
...(status !== undefined ? { status } : {}),
|
|
545
558
|
...(retryAfterMs !== undefined ? { retryAfterMs } : {}),
|
|
546
559
|
...(detail !== undefined ? { detail } : {}),
|
|
560
|
+
...(shouldRetry !== undefined ? { shouldRetry } : {}),
|
|
547
561
|
})
|
|
548
562
|
}
|
|
549
563
|
|
|
@@ -605,6 +619,8 @@ export function providerHttpError(input: {
|
|
|
605
619
|
readonly retryAfter?: string | null
|
|
606
620
|
/** The response's request ID header, when the driver read one. */
|
|
607
621
|
readonly requestId?: string | null
|
|
622
|
+
/** The response's `x-should-retry` header, when the driver read one. */
|
|
623
|
+
readonly shouldRetry?: string | null
|
|
608
624
|
readonly now?: number
|
|
609
625
|
}): ProviderRequestError {
|
|
610
626
|
const kind = classifyProviderHttpStatus(input.status, input.body)
|
|
@@ -621,6 +637,7 @@ export function providerHttpError(input: {
|
|
|
621
637
|
})
|
|
622
638
|
: vendorDetail(input.body)
|
|
623
639
|
const exactProviderCode = providerCode(input.body)
|
|
640
|
+
const shouldRetry = parseShouldRetry(input.shouldRetry)
|
|
624
641
|
return new ProviderRequestError({
|
|
625
642
|
kind,
|
|
626
643
|
providerId: input.providerId,
|
|
@@ -628,5 +645,6 @@ export function providerHttpError(input: {
|
|
|
628
645
|
status: input.status,
|
|
629
646
|
...(retryAfterMs !== undefined ? { retryAfterMs } : {}),
|
|
630
647
|
...(detail !== undefined ? { detail } : {}),
|
|
648
|
+
...(shouldRetry !== undefined ? { shouldRetry } : {}),
|
|
631
649
|
})
|
|
632
650
|
}
|
package/src/provider/retry.ts
CHANGED
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
import { GENAI } from '../constants/telemetry/index.js'
|
|
2
2
|
import { classifyProviderError, isAbortError } from '../types/provider/errors.js'
|
|
3
3
|
import type { ChatCompletionParams, LLMProvider, StreamChunk } from '../types/provider/index.js'
|
|
4
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
type BackoffPolicy,
|
|
6
|
+
backoffProportional,
|
|
7
|
+
backoffWithJitter,
|
|
8
|
+
sleep,
|
|
9
|
+
} from '../utils/backoff.js'
|
|
5
10
|
import type { Logger } from '../utils/logger.js'
|
|
6
11
|
import { isProviderRequestError } from './errors.js'
|
|
7
12
|
|
|
@@ -31,6 +36,33 @@ export interface ProviderRetryConfig extends BackoffPolicy {
|
|
|
31
36
|
* still slept exactly as instructed.
|
|
32
37
|
*/
|
|
33
38
|
readonly maxRetryAfterMs: number
|
|
39
|
+
/**
|
|
40
|
+
* Shape of the random part of a backoff.
|
|
41
|
+
*
|
|
42
|
+
* `'full'` (the default) sleeps a uniform amount in `[0, backoff]`.
|
|
43
|
+
* `'proportional'` sleeps the backoff plus up to a quarter of it, so a step
|
|
44
|
+
* is never shorter than its exponential value.
|
|
45
|
+
*/
|
|
46
|
+
readonly jitter?: 'full' | 'proportional'
|
|
47
|
+
/**
|
|
48
|
+
* What a server-named wait means.
|
|
49
|
+
*
|
|
50
|
+
* `'exact'` (the default) sleeps exactly what `Retry-After` said.
|
|
51
|
+
* `'floor'` sleeps the longer of that and the backoff for this attempt, so
|
|
52
|
+
* a server that says "1 second" on the seventh failure is still given the
|
|
53
|
+
* backoff's thirty. The ceiling above applies either way.
|
|
54
|
+
*/
|
|
55
|
+
readonly retryAfter?: 'exact' | 'floor'
|
|
56
|
+
/**
|
|
57
|
+
* Also retry a stream that failed AFTER it produced text or reasoning.
|
|
58
|
+
*
|
|
59
|
+
* Off by default, because the decorator cannot un-emit: the consumer has
|
|
60
|
+
* already seen those deltas. When on, the retry notice carries
|
|
61
|
+
* `restart: true` and the consumer must discard what the failed attempt
|
|
62
|
+
* produced; the runtime does this itself. A stream that has begun a tool
|
|
63
|
+
* call is never restarted, because the call may already be underway.
|
|
64
|
+
*/
|
|
65
|
+
readonly retryMidStream?: boolean
|
|
34
66
|
}
|
|
35
67
|
|
|
36
68
|
export const DEFAULT_PROVIDER_RETRY: ProviderRetryConfig = {
|
|
@@ -97,6 +129,9 @@ export function withProviderRetry(
|
|
|
97
129
|
async function* chatStream(params: ChatCompletionParams): AsyncIterable<StreamChunk> {
|
|
98
130
|
for (let attempt = 0; ; attempt++) {
|
|
99
131
|
let produced = false
|
|
132
|
+
// A tool call or hosted tool began: past this point a restart could
|
|
133
|
+
// repeat work that is already underway, so it is never offered.
|
|
134
|
+
let acted = false
|
|
100
135
|
try {
|
|
101
136
|
for await (const chunk of provider.chatStream(params)) {
|
|
102
137
|
// An error-only chunk is a failure report, not output: it
|
|
@@ -106,6 +141,9 @@ export function withProviderRetry(
|
|
|
106
141
|
chunk.error !== undefined && !chunk.delta.content && !chunk.delta.toolCalls?.length
|
|
107
142
|
|
|
108
143
|
if (!isErrorOnly) produced = true
|
|
144
|
+
if (chunk.delta.toolCalls?.length || chunk.delta.toolCallEnd || chunk.delta.hostedTool) {
|
|
145
|
+
acted = true
|
|
146
|
+
}
|
|
109
147
|
|
|
110
148
|
if (isErrorOnly && !produced && attempt < config.maxRetries) {
|
|
111
149
|
throw new Error(chunk.error)
|
|
@@ -132,7 +170,8 @@ export function withProviderRetry(
|
|
|
132
170
|
const classified = classifyProviderError(err, provider.id)
|
|
133
171
|
const exhausted = attempt >= config.maxRetries
|
|
134
172
|
|
|
135
|
-
|
|
173
|
+
const restartable = produced && config.retryMidStream === true && !acted
|
|
174
|
+
if ((produced && !restartable) || !classified.retryable || exhausted) {
|
|
136
175
|
log?.warn('Provider call failed', {
|
|
137
176
|
[GENAI.SYSTEM]: provider.id,
|
|
138
177
|
'namzu.provider.code': classified.code,
|
|
@@ -200,7 +239,16 @@ export function withProviderRetry(
|
|
|
200
239
|
throw isProviderRequestError(err) ? err : classified
|
|
201
240
|
}
|
|
202
241
|
|
|
203
|
-
const
|
|
242
|
+
const backoff =
|
|
243
|
+
config.jitter === 'proportional'
|
|
244
|
+
? backoffProportional(attempt, config, random)
|
|
245
|
+
: backoffWithJitter(attempt, config, random)
|
|
246
|
+
const delay =
|
|
247
|
+
serverDirected === undefined
|
|
248
|
+
? backoff
|
|
249
|
+
: config.retryAfter === 'floor'
|
|
250
|
+
? Math.max(serverDirected, backoff)
|
|
251
|
+
: serverDirected
|
|
204
252
|
|
|
205
253
|
log?.warn('Provider call failed — retrying', {
|
|
206
254
|
[GENAI.SYSTEM]: provider.id,
|
|
@@ -210,6 +258,7 @@ export function withProviderRetry(
|
|
|
210
258
|
'namzu.provider.max_retries': config.maxRetries,
|
|
211
259
|
'namzu.provider.delay_ms': delay,
|
|
212
260
|
'namzu.provider.server_directed': serverDirected !== undefined,
|
|
261
|
+
'namzu.provider.restart': restartable,
|
|
213
262
|
})
|
|
214
263
|
|
|
215
264
|
// Tell the consumer BEFORE sleeping. With the default policy a
|
|
@@ -231,6 +280,7 @@ export function withProviderRetry(
|
|
|
231
280
|
code: classified.code,
|
|
232
281
|
...(classified.status !== undefined ? { status: classified.status } : {}),
|
|
233
282
|
serverDirected: serverDirected !== undefined,
|
|
283
|
+
...(restartable ? { restart: true } : {}),
|
|
234
284
|
},
|
|
235
285
|
}
|
|
236
286
|
|
package/src/public-runtime.ts
CHANGED
|
@@ -318,6 +318,12 @@ export {
|
|
|
318
318
|
formatSteeringNote,
|
|
319
319
|
} from './runtime/query/steering.js'
|
|
320
320
|
export type { SteeringChannel } from './runtime/query/steering.js'
|
|
321
|
+
// Hidden mid-conversation reminders a host feeds per model request (opt-in).
|
|
322
|
+
export { isReminderMessage } from './runtime/query/reminders.js'
|
|
323
|
+
export type {
|
|
324
|
+
ReminderContext,
|
|
325
|
+
ReminderSource,
|
|
326
|
+
} from './runtime/query/reminders.js'
|
|
321
327
|
export {
|
|
322
328
|
BidiSessionCloseTimeoutError,
|
|
323
329
|
createMockBidiProvider,
|
|
@@ -628,6 +634,7 @@ export {
|
|
|
628
634
|
runShellHook,
|
|
629
635
|
SHELL_HOOK_EVENTS,
|
|
630
636
|
SHELL_HOOKS_PLUGIN_ID,
|
|
637
|
+
shellHookIfMatches,
|
|
631
638
|
shellHookMatches,
|
|
632
639
|
shellHookVerdict,
|
|
633
640
|
} from './plugin/index.js'
|
|
@@ -1505,6 +1512,7 @@ export {
|
|
|
1505
1512
|
// consumer (`SpanProcessorLike`, then `CompactNowInput` and `CompactionResult`).
|
|
1506
1513
|
// The gate is the reason this is a list rather than a fourth accident.
|
|
1507
1514
|
export type { ResolvedContextWindow } from './compaction/context-window.js'
|
|
1515
|
+
export { resolveTriggerThreshold } from './compaction/context-window.js'
|
|
1508
1516
|
export type { CompactRegionInput } from './compaction/manual.js'
|
|
1509
1517
|
export type {
|
|
1510
1518
|
CompactionVerificationOptions,
|
package/src/public-types.ts
CHANGED
|
@@ -204,6 +204,7 @@ export type {
|
|
|
204
204
|
Disposable,
|
|
205
205
|
RunAgentOptions,
|
|
206
206
|
RunAgentResult,
|
|
207
|
+
SupervisorResumeTarget,
|
|
207
208
|
} from './agents/index.js'
|
|
208
209
|
|
|
209
210
|
export type {
|
|
@@ -457,7 +458,10 @@ export type {
|
|
|
457
458
|
|
|
458
459
|
export type {
|
|
459
460
|
GuardedFetchConfig,
|
|
461
|
+
WebContentExtractor,
|
|
462
|
+
WebExtractRequest,
|
|
460
463
|
WebFetchProvider,
|
|
464
|
+
WebFetchRedirectPolicy,
|
|
461
465
|
WebFetchRefusalReason,
|
|
462
466
|
WebFetchRequest,
|
|
463
467
|
WebFetchResult,
|
|
@@ -99,6 +99,21 @@ export interface StartJobParams {
|
|
|
99
99
|
* expect stdin.
|
|
100
100
|
*/
|
|
101
101
|
readonly spawn?: () => JobProcess
|
|
102
|
+
/**
|
|
103
|
+
* Output the process already wrote before the registry took it over, in
|
|
104
|
+
* the order it was written. Used when a foreground command is moved to the
|
|
105
|
+
* background, so a later `read` starts with what the model was shown.
|
|
106
|
+
*/
|
|
107
|
+
readonly initialOutput?: readonly {
|
|
108
|
+
readonly stream: 'stdout' | 'stderr'
|
|
109
|
+
readonly text: string
|
|
110
|
+
}[]
|
|
111
|
+
/**
|
|
112
|
+
* `spawn` returned a process on THIS host that the host shell started (a
|
|
113
|
+
* foreground command being moved to the background), so its bytes are
|
|
114
|
+
* decoded the way a foreground command's are, not as a Linux guest's.
|
|
115
|
+
*/
|
|
116
|
+
readonly hostOutput?: boolean
|
|
102
117
|
}
|
|
103
118
|
|
|
104
119
|
export interface BackgroundJobRegistryConfig {
|
|
@@ -333,8 +348,12 @@ export class BackgroundJobRegistry {
|
|
|
333
348
|
// Raw bytes, decoded here: a Windows console writes its OEM code page.
|
|
334
349
|
// A process a sandbox started runs a Linux guest, so it is UTF-8.
|
|
335
350
|
const decoders = {
|
|
336
|
-
stdout: createHostOutputDecoder(
|
|
337
|
-
|
|
351
|
+
stdout: createHostOutputDecoder(
|
|
352
|
+
params.spawn && !params.hostOutput ? { platform: 'linux' } : {},
|
|
353
|
+
),
|
|
354
|
+
stderr: createHostOutputDecoder(
|
|
355
|
+
params.spawn && !params.hostOutput ? { platform: 'linux' } : {},
|
|
356
|
+
),
|
|
338
357
|
}
|
|
339
358
|
let startError: string | undefined
|
|
340
359
|
let settleStarted!: () => void
|
|
@@ -473,6 +492,7 @@ export class BackgroundJobRegistry {
|
|
|
473
492
|
const text = typeof data === 'string' ? data : decoders[stream].write(data)
|
|
474
493
|
if (text) append(text, stream)
|
|
475
494
|
}
|
|
495
|
+
for (const seed of params.initialOutput ?? []) append(seed.text, seed.stream)
|
|
476
496
|
child.stdout?.on('data', onData('stdout'))
|
|
477
497
|
child.stderr?.on('data', onData('stderr'))
|
|
478
498
|
|
|
@@ -855,6 +875,23 @@ export function bindOwner(
|
|
|
855
875
|
: {}),
|
|
856
876
|
})
|
|
857
877
|
},
|
|
878
|
+
// A foreground command that ran out of time, kept instead of killed.
|
|
879
|
+
// The same owner and cap as `start`; the process is the one already
|
|
880
|
+
// running, with what it has written so far.
|
|
881
|
+
adopt: (params: {
|
|
882
|
+
command: string
|
|
883
|
+
child: ReturnType<typeof spawn>
|
|
884
|
+
workingDirectory?: string
|
|
885
|
+
initialOutput?: StartJobParams['initialOutput']
|
|
886
|
+
}) =>
|
|
887
|
+
registry.start({
|
|
888
|
+
owner,
|
|
889
|
+
command: params.command,
|
|
890
|
+
workingDirectory: params.workingDirectory ?? defaults.workingDirectory ?? process.cwd(),
|
|
891
|
+
spawn: () => ({ child: params.child }),
|
|
892
|
+
hostOutput: true,
|
|
893
|
+
...(params.initialOutput ? { initialOutput: params.initialOutput } : {}),
|
|
894
|
+
}),
|
|
858
895
|
get: (id: string) => mine(id),
|
|
859
896
|
awaitStarted: (id: string) => {
|
|
860
897
|
mine(id)
|
|
@@ -2,7 +2,7 @@ import { GENAI, NAMZU } from '../../../constants/telemetry/index.js'
|
|
|
2
2
|
import { callableToolNames, formatToolNames } from '../../../registry/tool/callable.js'
|
|
3
3
|
import { renderToolSchema } from '../../../registry/tool/schema.js'
|
|
4
4
|
import type { ToolCall, ToolInputError } from '../../../types/message/index.js'
|
|
5
|
-
import type { PluginHookResult } from '../../../types/plugin/index.js'
|
|
5
|
+
import type { PluginHookPermission, PluginHookResult } from '../../../types/plugin/index.js'
|
|
6
6
|
import type { ToolDefinition } from '../../../types/tool/index.js'
|
|
7
7
|
import type { ToolCallRepair, ToolCallRepairReason } from '../../../types/tool/repair.js'
|
|
8
8
|
import { awaitWithAbort } from '../../../utils/await-with-abort.js'
|
|
@@ -10,6 +10,7 @@ import { toErrorMessage } from '../../../utils/error.js'
|
|
|
10
10
|
import type { Logger } from '../../../utils/logger.js'
|
|
11
11
|
import type {
|
|
12
12
|
EmitEvent,
|
|
13
|
+
PreToolHookNotes,
|
|
13
14
|
PreToolHookOutcome,
|
|
14
15
|
PreparedDirectCall,
|
|
15
16
|
ToolExecutorConfig,
|
|
@@ -49,6 +50,11 @@ export interface ToolAdmissionHost {
|
|
|
49
50
|
* step, which is the answer that sent a model round in a circle.
|
|
50
51
|
*/
|
|
51
52
|
readonly allowedTools: readonly string[] | undefined
|
|
53
|
+
/**
|
|
54
|
+
* A hook asked for the turn to stop after the current step. Optional so a
|
|
55
|
+
* host that builds an admission by hand (a test) need not say anything.
|
|
56
|
+
*/
|
|
57
|
+
readonly requestHalt?: (reason: string) => void
|
|
52
58
|
}
|
|
53
59
|
|
|
54
60
|
/**
|
|
@@ -89,7 +95,7 @@ export async function runPreToolHook(
|
|
|
89
95
|
signal,
|
|
90
96
|
)
|
|
91
97
|
signal.throwIfAborted()
|
|
92
|
-
return interpretPreToolResults(toolName, input, results)
|
|
98
|
+
return interpretPreToolResults(toolName, input, results, host.requestHalt)
|
|
93
99
|
}
|
|
94
100
|
|
|
95
101
|
export async function prepareDirectCall(
|
|
@@ -169,6 +175,7 @@ export async function prepareDirectCall(
|
|
|
169
175
|
...(providerInput && !truncationRepair && !preOutcome.modified && resolved.inputFailure
|
|
170
176
|
? { inputFailure: resolved.inputFailure }
|
|
171
177
|
: {}),
|
|
178
|
+
...hookNotesOf(preOutcome),
|
|
172
179
|
}
|
|
173
180
|
}
|
|
174
181
|
return {
|
|
@@ -321,6 +328,20 @@ export async function prepareDirectCall(
|
|
|
321
328
|
toolName,
|
|
322
329
|
input: preparation.prepared.input,
|
|
323
330
|
prepared: preparation.prepared,
|
|
331
|
+
...hookNotesOf(preOutcome),
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
/** The hook answers a ready or legacy call carries forward, or nothing. */
|
|
336
|
+
function hookNotesOf(outcome: Extract<PreToolHookOutcome, { kind: 'continue' }>): {
|
|
337
|
+
hook?: PreToolHookNotes
|
|
338
|
+
} {
|
|
339
|
+
if (outcome.permission === undefined && outcome.context === undefined) return {}
|
|
340
|
+
return {
|
|
341
|
+
hook: {
|
|
342
|
+
...(outcome.permission ? { permission: outcome.permission } : {}),
|
|
343
|
+
...(outcome.context !== undefined ? { context: outcome.context } : {}),
|
|
344
|
+
},
|
|
324
345
|
}
|
|
325
346
|
}
|
|
326
347
|
|
|
@@ -328,29 +349,49 @@ function interpretPreToolResults(
|
|
|
328
349
|
toolName: string,
|
|
329
350
|
initialInput: unknown,
|
|
330
351
|
results: readonly PluginHookResult[],
|
|
352
|
+
requestHalt?: (reason: string) => void,
|
|
331
353
|
): PreToolHookOutcome {
|
|
332
354
|
let currentInput = initialInput
|
|
333
355
|
let modified = false
|
|
356
|
+
let permission: PluginHookPermission | undefined
|
|
357
|
+
const contexts: string[] = []
|
|
358
|
+
/** `ask` outranks `allow`: the stricter answer is the one that stands. */
|
|
359
|
+
const takePermission = (next: PluginHookPermission | undefined) => {
|
|
360
|
+
if (next === undefined) return
|
|
361
|
+
if (permission === undefined || (permission.decision === 'allow' && next.decision === 'ask')) {
|
|
362
|
+
permission = next
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
const withContext = (text: string): string =>
|
|
366
|
+
contexts.length === 0 ? text : `${text}\n\n${hookNote(contexts)}`
|
|
367
|
+
// The hooks ran side by side on the original input, and their answers are
|
|
368
|
+
// combined here. The first refusal (or failure) in registration order is the
|
|
369
|
+
// answer, whatever the others said; of several rewrites the last wins;
|
|
370
|
+
// `ask` outranks `allow`; every context is kept; every request to stop is
|
|
371
|
+
// passed on.
|
|
372
|
+
let refusal: { kind: 'skip' | 'error'; text: string } | undefined
|
|
334
373
|
for (const result of results) {
|
|
335
374
|
switch (result.action) {
|
|
336
375
|
case 'continue':
|
|
376
|
+
takePermission(result.permission)
|
|
377
|
+
if (result.context) contexts.push(result.context)
|
|
378
|
+
if (result.halt) requestHalt?.(result.halt.reason)
|
|
337
379
|
continue
|
|
338
380
|
case 'modify':
|
|
339
381
|
currentInput = result.input
|
|
340
382
|
modified = true
|
|
383
|
+
takePermission(result.permission)
|
|
384
|
+
if (result.context) contexts.push(result.context)
|
|
385
|
+
if (result.halt) requestHalt?.(result.halt.reason)
|
|
341
386
|
continue
|
|
342
387
|
case 'skip':
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
}
|
|
388
|
+
if (result.context) contexts.push(result.context)
|
|
389
|
+
if (result.halt) requestHalt?.(result.halt.reason)
|
|
390
|
+
refusal ??= { kind: 'skip', text: skippedToolResultText(toolName, result.reason) }
|
|
391
|
+
continue
|
|
348
392
|
case 'error':
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
input: currentInput,
|
|
352
|
-
output: `Error: ${result.message}`,
|
|
353
|
-
}
|
|
393
|
+
refusal ??= { kind: 'error', text: `Error: ${result.message}` }
|
|
394
|
+
continue
|
|
354
395
|
case 'retry':
|
|
355
396
|
case 'annotate':
|
|
356
397
|
// There is no result to replace yet. Rejecting loudly beats
|
|
@@ -367,9 +408,34 @@ function interpretPreToolResults(
|
|
|
367
408
|
}
|
|
368
409
|
}
|
|
369
410
|
}
|
|
370
|
-
|
|
411
|
+
if (refusal) {
|
|
412
|
+
return {
|
|
413
|
+
kind: refusal.kind,
|
|
414
|
+
input: currentInput,
|
|
415
|
+
output: refusal.kind === 'skip' ? withContext(refusal.text) : refusal.text,
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
return {
|
|
419
|
+
kind: 'continue',
|
|
420
|
+
input: currentInput,
|
|
421
|
+
modified,
|
|
422
|
+
...(permission ? { permission } : {}),
|
|
423
|
+
...(contexts.length > 0 ? { context: contexts.join('\n') } : {}),
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
/**
|
|
428
|
+
* Hook text, framed so the model reads it as what a configured hook said and
|
|
429
|
+
* not as something the tool returned.
|
|
430
|
+
*/
|
|
431
|
+
export function hookNote(texts: readonly string[]): string {
|
|
432
|
+
const joined = texts.join('\n')
|
|
433
|
+
return `[Hook note]\n${joined.length > MAX_HOOK_NOTE_CHARS ? `${joined.slice(0, MAX_HOOK_NOTE_CHARS)}\n[truncated]` : joined}`
|
|
371
434
|
}
|
|
372
435
|
|
|
436
|
+
/** A hook's text is one more thing for the model to read; it gets a bound. */
|
|
437
|
+
const MAX_HOOK_NOTE_CHARS = 8_000
|
|
438
|
+
|
|
373
439
|
/**
|
|
374
440
|
* Turn the call the model issued into a name and a parsed input, giving
|
|
375
441
|
* a configured repairer one chance to fix it first.
|