@namzu/sdk 35.0.0 → 37.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 +218 -0
- package/README.md +68 -41
- package/dist/bridge/a2a/mapper.d.ts.map +1 -1
- package/dist/bridge/a2a/mapper.js +2 -0
- package/dist/bridge/a2a/mapper.js.map +1 -1
- package/dist/bridge/sse/mapper.d.ts.map +1 -1
- package/dist/bridge/sse/mapper.js +2 -0
- package/dist/bridge/sse/mapper.js.map +1 -1
- package/dist/compaction/extractor.d.ts +1 -1
- package/dist/compaction/extractor.d.ts.map +1 -1
- package/dist/compaction/extractor.js +15 -7
- package/dist/compaction/extractor.js.map +1 -1
- package/dist/compaction/manager.d.ts +2 -0
- package/dist/compaction/manager.d.ts.map +1 -1
- package/dist/compaction/manager.js +12 -1
- package/dist/compaction/manager.js.map +1 -1
- package/dist/compaction/verifier.d.ts.map +1 -1
- package/dist/compaction/verifier.js +82 -15
- package/dist/compaction/verifier.js.map +1 -1
- package/dist/contracts/schemas.d.ts +10 -10
- package/dist/eval/harness-verification.d.ts +63 -0
- package/dist/eval/harness-verification.d.ts.map +1 -0
- package/dist/eval/harness-verification.js +165 -0
- package/dist/eval/harness-verification.js.map +1 -0
- package/dist/eval/index.d.ts +2 -0
- package/dist/eval/index.d.ts.map +1 -1
- package/dist/eval/index.js +1 -0
- package/dist/eval/index.js.map +1 -1
- package/dist/execution/code-runtime/json-value.d.ts +10 -0
- package/dist/execution/code-runtime/json-value.d.ts.map +1 -0
- package/dist/execution/code-runtime/json-value.js +89 -0
- package/dist/execution/code-runtime/json-value.js.map +1 -0
- package/dist/execution/code-runtime/worker-program.d.ts +8 -0
- package/dist/execution/code-runtime/worker-program.d.ts.map +1 -0
- package/dist/execution/code-runtime/worker-program.js +240 -0
- package/dist/execution/code-runtime/worker-program.js.map +1 -0
- package/dist/execution/code-runtime/worker.d.ts +22 -0
- package/dist/execution/code-runtime/worker.d.ts.map +1 -1
- package/dist/execution/code-runtime/worker.js +148 -111
- package/dist/execution/code-runtime/worker.js.map +1 -1
- package/dist/manager/agent/lifecycle.d.ts +12 -0
- package/dist/manager/agent/lifecycle.d.ts.map +1 -1
- package/dist/manager/agent/lifecycle.js +306 -37
- package/dist/manager/agent/lifecycle.js.map +1 -1
- package/dist/manager/run/persistence.d.ts +2 -0
- package/dist/manager/run/persistence.d.ts.map +1 -1
- package/dist/manager/run/persistence.js +6 -0
- package/dist/manager/run/persistence.js.map +1 -1
- package/dist/provider/capabilities.d.ts +3 -1
- package/dist/provider/capabilities.d.ts.map +1 -1
- package/dist/provider/capabilities.js +13 -0
- package/dist/provider/capabilities.js.map +1 -1
- package/dist/provider/fallback.d.ts.map +1 -1
- package/dist/provider/fallback.js +2 -0
- package/dist/provider/fallback.js.map +1 -1
- package/dist/provider/token-budget.d.ts.map +1 -1
- package/dist/provider/token-budget.js +56 -8
- package/dist/provider/token-budget.js.map +1 -1
- package/dist/public-runtime.d.ts +5 -3
- package/dist/public-runtime.d.ts.map +1 -1
- package/dist/public-runtime.js +3 -2
- package/dist/public-runtime.js.map +1 -1
- package/dist/public-tools.d.ts +1 -1
- package/dist/public-tools.d.ts.map +1 -1
- package/dist/public-tools.js +1 -1
- package/dist/public-tools.js.map +1 -1
- package/dist/public-types.d.ts +1 -0
- package/dist/public-types.d.ts.map +1 -1
- package/dist/registry/tool/execute.d.ts +3 -0
- package/dist/registry/tool/execute.d.ts.map +1 -1
- package/dist/registry/tool/execute.js +11 -80
- package/dist/registry/tool/execute.js.map +1 -1
- package/dist/run/command-gate.d.ts.map +1 -1
- package/dist/run/command-gate.js +65 -12
- package/dist/run/command-gate.js.map +1 -1
- package/dist/run/index.d.ts +2 -0
- package/dist/run/index.d.ts.map +1 -1
- package/dist/run/index.js +1 -0
- package/dist/run/index.js.map +1 -1
- package/dist/run/memory-promoter.d.ts +3 -35
- package/dist/run/memory-promoter.d.ts.map +1 -1
- package/dist/run/memory-promoter.js +32 -40
- package/dist/run/memory-promoter.js.map +1 -1
- package/dist/run/memory-recall.d.ts +25 -0
- package/dist/run/memory-recall.d.ts.map +1 -0
- package/dist/run/memory-recall.js +228 -0
- package/dist/run/memory-recall.js.map +1 -0
- package/dist/run/reporter.d.ts.map +1 -1
- package/dist/run/reporter.js +1 -0
- package/dist/run/reporter.js.map +1 -1
- package/dist/run/token-budget.d.ts +2 -0
- package/dist/run/token-budget.d.ts.map +1 -1
- package/dist/run/token-budget.js +4 -0
- package/dist/run/token-budget.js.map +1 -1
- package/dist/run/workspace-fingerprint.d.ts +10 -3
- package/dist/run/workspace-fingerprint.d.ts.map +1 -1
- package/dist/run/workspace-fingerprint.js +17 -8
- package/dist/run/workspace-fingerprint.js.map +1 -1
- package/dist/runtime/query/checkpoint.d.ts +14 -0
- package/dist/runtime/query/checkpoint.d.ts.map +1 -1
- package/dist/runtime/query/checkpoint.js +82 -1
- package/dist/runtime/query/checkpoint.js.map +1 -1
- package/dist/runtime/query/executor.d.ts +6 -0
- package/dist/runtime/query/executor.d.ts.map +1 -1
- package/dist/runtime/query/executor.js +120 -24
- package/dist/runtime/query/executor.js.map +1 -1
- package/dist/runtime/query/index.d.ts +12 -8
- package/dist/runtime/query/index.d.ts.map +1 -1
- package/dist/runtime/query/index.js +55 -7
- package/dist/runtime/query/index.js.map +1 -1
- package/dist/runtime/query/iteration/index.d.ts +13 -3
- package/dist/runtime/query/iteration/index.d.ts.map +1 -1
- package/dist/runtime/query/iteration/index.js +356 -42
- package/dist/runtime/query/iteration/index.js.map +1 -1
- package/dist/runtime/query/iteration/native-output.d.ts +10 -0
- package/dist/runtime/query/iteration/native-output.d.ts.map +1 -0
- package/dist/runtime/query/iteration/native-output.js +32 -0
- package/dist/runtime/query/iteration/native-output.js.map +1 -0
- package/dist/runtime/query/iteration/phases/advisory.d.ts.map +1 -1
- package/dist/runtime/query/iteration/phases/advisory.js +18 -13
- package/dist/runtime/query/iteration/phases/advisory.js.map +1 -1
- package/dist/runtime/query/iteration/phases/compaction.d.ts +2 -0
- package/dist/runtime/query/iteration/phases/compaction.d.ts.map +1 -1
- package/dist/runtime/query/iteration/phases/compaction.js +32 -11
- package/dist/runtime/query/iteration/phases/compaction.js.map +1 -1
- package/dist/runtime/query/iteration/phases/context.d.ts +11 -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 +1 -1
- package/dist/runtime/query/iteration/phases/tool-review.js.map +1 -1
- package/dist/runtime/query/iteration/phases/working-memory.d.ts +1 -1
- package/dist/runtime/query/iteration/phases/working-memory.d.ts.map +1 -1
- package/dist/runtime/query/iteration/phases/working-memory.js +23 -6
- package/dist/runtime/query/iteration/phases/working-memory.js.map +1 -1
- package/dist/runtime/query/iteration/stream-turn.d.ts.map +1 -1
- package/dist/runtime/query/iteration/stream-turn.js +12 -5
- package/dist/runtime/query/iteration/stream-turn.js.map +1 -1
- package/dist/runtime/query/prompt.d.ts.map +1 -1
- package/dist/runtime/query/prompt.js +14 -4
- package/dist/runtime/query/prompt.js.map +1 -1
- package/dist/runtime/query/steering.d.ts +6 -2
- package/dist/runtime/query/steering.d.ts.map +1 -1
- package/dist/runtime/query/steering.js +17 -2
- package/dist/runtime/query/steering.js.map +1 -1
- package/dist/runtime/query/tool-call-budget.d.ts +19 -0
- package/dist/runtime/query/tool-call-budget.d.ts.map +1 -0
- package/dist/runtime/query/tool-call-budget.js +110 -0
- package/dist/runtime/query/tool-call-budget.js.map +1 -0
- package/dist/runtime/query/tooling.d.ts +2 -0
- package/dist/runtime/query/tooling.d.ts.map +1 -1
- package/dist/runtime/query/tooling.js +4 -0
- package/dist/runtime/query/tooling.js.map +1 -1
- package/dist/sandbox/file-walk-program.d.ts +3 -0
- package/dist/sandbox/file-walk-program.d.ts.map +1 -0
- package/dist/sandbox/file-walk-program.js +94 -0
- package/dist/sandbox/file-walk-program.js.map +1 -0
- package/dist/sandbox/file-walk.d.ts +12 -0
- package/dist/sandbox/file-walk.d.ts.map +1 -0
- package/dist/sandbox/file-walk.js +429 -0
- package/dist/sandbox/file-walk.js.map +1 -0
- package/dist/sandbox/index.d.ts +2 -0
- package/dist/sandbox/index.d.ts.map +1 -1
- package/dist/sandbox/index.js +1 -0
- package/dist/sandbox/index.js.map +1 -1
- package/dist/sandbox/provider/local.d.ts.map +1 -1
- package/dist/sandbox/provider/local.js +9 -0
- package/dist/sandbox/provider/local.js.map +1 -1
- package/dist/scheduler/completion-inbox.d.ts +3 -2
- package/dist/scheduler/completion-inbox.d.ts.map +1 -1
- package/dist/scheduler/completion-inbox.js +29 -15
- package/dist/scheduler/completion-inbox.js.map +1 -1
- package/dist/scheduler/local.d.ts.map +1 -1
- package/dist/scheduler/local.js +1 -0
- package/dist/scheduler/local.js.map +1 -1
- package/dist/session/handoff/capacity.d.ts +2 -2
- package/dist/session/handoff/capacity.d.ts.map +1 -1
- package/dist/session/handoff/capacity.js +3 -2
- package/dist/session/handoff/capacity.js.map +1 -1
- package/dist/store/memory/disk.d.ts +6 -2
- package/dist/store/memory/disk.d.ts.map +1 -1
- package/dist/store/memory/disk.js +42 -25
- package/dist/store/memory/disk.js.map +1 -1
- package/dist/store/memory/index.d.ts +4 -0
- package/dist/store/memory/index.d.ts.map +1 -1
- package/dist/store/memory/index.js +55 -19
- package/dist/store/memory/index.js.map +1 -1
- package/dist/store/memory/memory.d.ts +3 -2
- package/dist/store/memory/memory.d.ts.map +1 -1
- package/dist/store/memory/memory.js +11 -2
- package/dist/store/memory/memory.js.map +1 -1
- package/dist/store/memory/operation-lock.d.ts +11 -0
- package/dist/store/memory/operation-lock.d.ts.map +1 -0
- package/dist/store/memory/operation-lock.js +94 -0
- package/dist/store/memory/operation-lock.js.map +1 -0
- package/dist/tools/builtins/bash.d.ts.map +1 -1
- package/dist/tools/builtins/bash.js +215 -59
- package/dist/tools/builtins/bash.js.map +1 -1
- package/dist/tools/builtins/computer-use.d.ts.map +1 -1
- package/dist/tools/builtins/computer-use.js +60 -10
- package/dist/tools/builtins/computer-use.js.map +1 -1
- package/dist/tools/builtins/glob.d.ts +2 -1
- package/dist/tools/builtins/glob.d.ts.map +1 -1
- package/dist/tools/builtins/glob.js +95 -103
- package/dist/tools/builtins/glob.js.map +1 -1
- package/dist/tools/builtins/grep.d.ts.map +1 -1
- package/dist/tools/builtins/grep.js +155 -111
- package/dist/tools/builtins/grep.js.map +1 -1
- package/dist/tools/builtins/ls.js +2 -2
- package/dist/tools/builtins/ls.js.map +1 -1
- package/dist/tools/builtins/run-code.d.ts +6 -0
- package/dist/tools/builtins/run-code.d.ts.map +1 -1
- package/dist/tools/builtins/run-code.js +15 -4
- package/dist/tools/builtins/run-code.js.map +1 -1
- package/dist/tools/builtins/search-tools.d.ts.map +1 -1
- package/dist/tools/builtins/search-tools.js +14 -2
- package/dist/tools/builtins/search-tools.js.map +1 -1
- package/dist/tools/defineTool.d.ts +2 -0
- package/dist/tools/defineTool.d.ts.map +1 -1
- package/dist/tools/defineTool.js +3 -0
- package/dist/tools/defineTool.js.map +1 -1
- package/dist/tools/memory/delete.d.ts +4 -0
- package/dist/tools/memory/delete.d.ts.map +1 -0
- package/dist/tools/memory/delete.js +26 -0
- package/dist/tools/memory/delete.js.map +1 -0
- package/dist/tools/memory/index.d.ts +2 -0
- package/dist/tools/memory/index.d.ts.map +1 -1
- package/dist/tools/memory/index.js +6 -0
- package/dist/tools/memory/index.js.map +1 -1
- package/dist/tools/memory/save.d.ts.map +1 -1
- package/dist/tools/memory/save.js +3 -2
- package/dist/tools/memory/save.js.map +1 -1
- package/dist/tools/memory/search.d.ts.map +1 -1
- package/dist/tools/memory/search.js +12 -5
- package/dist/tools/memory/search.js.map +1 -1
- package/dist/tools/memory/update.d.ts +4 -0
- package/dist/tools/memory/update.d.ts.map +1 -0
- package/dist/tools/memory/update.js +47 -0
- package/dist/tools/memory/update.js.map +1 -0
- package/dist/types/agent/scheduler.d.ts +5 -0
- package/dist/types/agent/scheduler.d.ts.map +1 -1
- package/dist/types/agent/task.d.ts +10 -0
- package/dist/types/agent/task.d.ts.map +1 -1
- package/dist/types/computer-use/index.d.ts +6 -0
- package/dist/types/computer-use/index.d.ts.map +1 -1
- package/dist/types/computer-use/index.js.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 +11 -1
- package/dist/types/hitl/index.d.ts.map +1 -1
- package/dist/types/hitl/index.js.map +1 -1
- package/dist/types/memory/index.d.ts +14 -1
- package/dist/types/memory/index.d.ts.map +1 -1
- package/dist/types/project/entity.d.ts +1 -0
- package/dist/types/project/entity.d.ts.map +1 -1
- package/dist/types/provider/config.d.ts +2 -0
- package/dist/types/provider/config.d.ts.map +1 -1
- package/dist/types/provider/model.d.ts +4 -0
- package/dist/types/provider/model.d.ts.map +1 -1
- package/dist/types/run/answer-review.d.ts +2 -0
- package/dist/types/run/answer-review.d.ts.map +1 -1
- package/dist/types/run/events.d.ts +9 -0
- package/dist/types/run/events.d.ts.map +1 -1
- package/dist/types/run/events.js.map +1 -1
- package/dist/types/run/prepare-step.d.ts +19 -1
- package/dist/types/run/prepare-step.d.ts.map +1 -1
- package/dist/types/sandbox/index.d.ts +20 -0
- package/dist/types/sandbox/index.d.ts.map +1 -1
- package/dist/types/sandbox/index.js.map +1 -1
- package/dist/types/structured-output/index.d.ts +8 -2
- package/dist/types/structured-output/index.d.ts.map +1 -1
- package/dist/types/tool/index.d.ts +15 -0
- package/dist/types/tool/index.d.ts.map +1 -1
- package/dist/types/tool/index.js.map +1 -1
- package/dist/utils/json-snapshot.d.ts +3 -0
- package/dist/utils/json-snapshot.d.ts.map +1 -0
- package/dist/utils/json-snapshot.js +79 -0
- package/dist/utils/json-snapshot.js.map +1 -0
- package/package.json +8 -1
- package/src/bridge/a2a/mapper.ts +2 -0
- package/src/bridge/sse/mapper.ts +2 -0
- package/src/compaction/extractor.ts +21 -8
- package/src/compaction/manager.ts +11 -1
- package/src/compaction/verifier.ts +80 -18
- package/src/eval/harness-verification.ts +270 -0
- package/src/eval/index.ts +10 -0
- package/src/execution/code-runtime/json-value.ts +82 -0
- package/src/execution/code-runtime/worker-program.ts +239 -0
- package/src/execution/code-runtime/worker.ts +164 -111
- package/src/manager/agent/lifecycle.ts +340 -45
- package/src/manager/run/persistence.ts +7 -0
- package/src/provider/capabilities.ts +25 -1
- package/src/provider/fallback.ts +2 -0
- package/src/provider/token-budget.ts +52 -8
- package/src/public-runtime.ts +6 -1
- package/src/public-tools.ts +5 -1
- package/src/public-types.ts +1 -0
- package/src/registry/tool/execute.ts +17 -79
- package/src/run/command-gate.ts +61 -13
- package/src/run/index.ts +2 -0
- package/src/run/memory-promoter.ts +32 -40
- package/src/run/memory-recall.ts +254 -0
- package/src/run/reporter.ts +1 -0
- package/src/run/token-budget.ts +4 -0
- package/src/run/workspace-fingerprint.ts +17 -8
- package/src/runtime/query/checkpoint.ts +96 -2
- package/src/runtime/query/executor.ts +131 -28
- package/src/runtime/query/index.ts +81 -16
- package/src/runtime/query/iteration/index.ts +406 -53
- package/src/runtime/query/iteration/native-output.ts +35 -0
- package/src/runtime/query/iteration/phases/advisory.ts +21 -11
- package/src/runtime/query/iteration/phases/compaction.ts +36 -14
- package/src/runtime/query/iteration/phases/context.ts +11 -0
- package/src/runtime/query/iteration/phases/tool-review.ts +5 -1
- package/src/runtime/query/iteration/phases/working-memory.ts +23 -5
- package/src/runtime/query/iteration/stream-turn.ts +11 -5
- package/src/runtime/query/prompt.ts +21 -4
- package/src/runtime/query/steering.ts +19 -2
- package/src/runtime/query/tool-call-budget.ts +115 -0
- package/src/runtime/query/tooling.ts +6 -0
- package/src/sandbox/file-walk-program.ts +93 -0
- package/src/sandbox/file-walk.ts +463 -0
- package/src/sandbox/index.ts +2 -0
- package/src/sandbox/provider/local.ts +13 -0
- package/src/scheduler/completion-inbox.ts +29 -19
- package/src/scheduler/local.ts +1 -0
- package/src/session/handoff/capacity.ts +7 -3
- package/src/store/memory/disk.ts +52 -30
- package/src/store/memory/index.ts +75 -27
- package/src/store/memory/memory.ts +18 -6
- package/src/store/memory/operation-lock.ts +99 -0
- package/src/tools/builtins/bash.ts +230 -58
- package/src/tools/builtins/computer-use.ts +61 -7
- package/src/tools/builtins/glob.ts +104 -122
- package/src/tools/builtins/grep.ts +166 -132
- package/src/tools/builtins/ls.ts +2 -2
- package/src/tools/builtins/run-code.ts +24 -5
- package/src/tools/builtins/search-tools.ts +18 -3
- package/src/tools/defineTool.ts +5 -0
- package/src/tools/memory/delete.ts +29 -0
- package/src/tools/memory/index.ts +6 -0
- package/src/tools/memory/save.ts +4 -2
- package/src/tools/memory/search.ts +12 -5
- package/src/tools/memory/update.ts +50 -0
- package/src/types/agent/scheduler.ts +6 -0
- package/src/types/agent/task.ts +13 -0
- package/src/types/computer-use/index.ts +6 -0
- package/src/types/errors/catalog.ts +1 -1
- package/src/types/hitl/index.ts +11 -1
- package/src/types/memory/index.ts +16 -1
- package/src/types/project/entity.ts +1 -0
- package/src/types/provider/config.ts +2 -0
- package/src/types/provider/model.ts +4 -0
- package/src/types/run/answer-review.ts +2 -0
- package/src/types/run/events.ts +10 -0
- package/src/types/run/prepare-step.ts +19 -1
- package/src/types/sandbox/index.ts +21 -0
- package/src/types/structured-output/index.ts +15 -2
- package/src/types/tool/index.ts +16 -0
- package/src/utils/json-snapshot.ts +76 -0
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import { type Span, SpanStatusCode } from '@opentelemetry/api'
|
|
2
2
|
import { resolveContextWindow } from '../../../compaction/context-window.js'
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
extractFromAssistantMessage,
|
|
5
|
+
extractFromUserMessage,
|
|
6
|
+
} from '../../../compaction/extractor.js'
|
|
7
|
+
import { estimateMessageTokens } from '../../../compaction/token-estimate.js'
|
|
4
8
|
import { AUTO_CONTINUATION_USER_MESSAGE } from '../../../constants/continuation.js'
|
|
5
9
|
import {
|
|
6
10
|
DEFAULT_STRUCTURED_OUTPUT_RETRIES,
|
|
@@ -9,6 +13,7 @@ import {
|
|
|
9
13
|
import { renderSkillsSection } from '../../../persona/assembler.js'
|
|
10
14
|
import { resolveProviderCapabilities } from '../../../provider/capabilities.js'
|
|
11
15
|
import { collectChatCompletion } from '../../../provider/collect-chat-completion.js'
|
|
16
|
+
import { renderToolSchema } from '../../../registry/tool/schema.js'
|
|
12
17
|
import { formatCompletionNotification } from '../../../scheduler/completion-inbox.js'
|
|
13
18
|
import {
|
|
14
19
|
GENAI,
|
|
@@ -24,6 +29,7 @@ import { NamzuError } from '../../../types/errors/index.js'
|
|
|
24
29
|
import type { MessageId } from '../../../types/ids/index.js'
|
|
25
30
|
import {
|
|
26
31
|
type Message,
|
|
32
|
+
type UserMessage,
|
|
27
33
|
createAssistantMessage,
|
|
28
34
|
createRuntimeContextMessage,
|
|
29
35
|
createSystemMessage,
|
|
@@ -33,6 +39,7 @@ import { classifyProviderError } from '../../../types/provider/errors.js'
|
|
|
33
39
|
import type { ChatCompletionResponse } from '../../../types/provider/index.js'
|
|
34
40
|
import type { AnswerReview } from '../../../types/run/answer-review.js'
|
|
35
41
|
import type {
|
|
42
|
+
PrepareStepContext,
|
|
36
43
|
PrepareStepResult,
|
|
37
44
|
RunEvent,
|
|
38
45
|
StepFailure,
|
|
@@ -54,10 +61,16 @@ import {
|
|
|
54
61
|
markProviderRejectedImage,
|
|
55
62
|
projectRequestRichContent,
|
|
56
63
|
} from '../request-rich-content.js'
|
|
57
|
-
import { formatSteeringNote } from '../steering.js'
|
|
64
|
+
import { formatSteeringNote, isOperatorUserMessage } from '../steering.js'
|
|
65
|
+
import { parseNativeCandidate } from './native-output.js'
|
|
58
66
|
import { runAdvisoryPhase } from './phases/advisory.js'
|
|
59
67
|
import { runIterationCheckpoint } from './phases/checkpoint.js'
|
|
60
|
-
import {
|
|
68
|
+
import {
|
|
69
|
+
activeContextWindow,
|
|
70
|
+
measureContext,
|
|
71
|
+
relieveOverflow,
|
|
72
|
+
runCompactionCheck,
|
|
73
|
+
} from './phases/compaction.js'
|
|
61
74
|
import type { IterationContext } from './phases/index.js'
|
|
62
75
|
import { runPlanGate } from './phases/plan.js'
|
|
63
76
|
import { runToolReview } from './phases/tool-review.js'
|
|
@@ -168,9 +181,34 @@ export class IterationOrchestrator {
|
|
|
168
181
|
* sets it.
|
|
169
182
|
*/
|
|
170
183
|
private stopDeferredForOutstandingWork = false
|
|
184
|
+
/** One current input, independent of the compactable history array. */
|
|
185
|
+
private latestUserMessage: UserMessage | undefined
|
|
171
186
|
|
|
172
187
|
constructor(ctx: IterationContext) {
|
|
173
|
-
this.ctx =
|
|
188
|
+
this.ctx = {
|
|
189
|
+
...ctx,
|
|
190
|
+
onSteeringDelivered: (text) => {
|
|
191
|
+
this.rememberUserMessage(createRuntimeContextMessage(text, 'steering'))
|
|
192
|
+
},
|
|
193
|
+
}
|
|
194
|
+
ctx.checkpointMgr.setLatestUserMessageSource(() => this.latestUserMessage)
|
|
195
|
+
ctx.checkpointMgr.setStructuredReviewAttemptsSource?.(() => this.structuredReviewAttempts)
|
|
196
|
+
ctx.checkpointMgr.setNativeStructuredAttemptsSource?.(() => this.nativeStructuredAttempts)
|
|
197
|
+
if (ctx.structuredOutput?.mode === 'native') {
|
|
198
|
+
const limit = ctx.structuredOutput.maxRetries
|
|
199
|
+
if (limit !== undefined && (!Number.isSafeInteger(limit) || limit < 0))
|
|
200
|
+
throw new RangeError(
|
|
201
|
+
'Native structuredOutput.maxRetries must be a nonnegative safe integer',
|
|
202
|
+
)
|
|
203
|
+
}
|
|
204
|
+
if (
|
|
205
|
+
ctx.structuredOutput?.mode !== undefined &&
|
|
206
|
+
!['tool', 'native'].includes(ctx.structuredOutput.mode)
|
|
207
|
+
)
|
|
208
|
+
throw new RangeError('Unknown structuredOutput.mode')
|
|
209
|
+
const maxReviews = ctx.structuredOutput?.maxReviews
|
|
210
|
+
if (maxReviews !== undefined && (!Number.isSafeInteger(maxReviews) || maxReviews < 0))
|
|
211
|
+
throw new RangeError('structuredOutput.maxReviews must be a nonnegative safe integer')
|
|
174
212
|
}
|
|
175
213
|
|
|
176
214
|
/**
|
|
@@ -252,6 +290,17 @@ export class IterationOrchestrator {
|
|
|
252
290
|
const { runConfig, runMgr } = this.ctx
|
|
253
291
|
const { model } = runConfig
|
|
254
292
|
const tracer = getTracer()
|
|
293
|
+
// Resume hydration happens after construction, before the loop starts.
|
|
294
|
+
this.latestUserMessage = this.ctx.checkpointMgr.restoredLatestUserMessage
|
|
295
|
+
this.structuredReviewAttempts = this.ctx.checkpointMgr.restoredStructuredReviewAttempts ?? 0
|
|
296
|
+
this.nativeStructuredAttempts = this.ctx.checkpointMgr.restoredNativeStructuredAttempts ?? 0
|
|
297
|
+
if (!this.latestUserMessage) {
|
|
298
|
+
for (const message of runMgr.messages) this.rememberUserMessage(message, false)
|
|
299
|
+
}
|
|
300
|
+
// The restored field can outlive the historical message it describes.
|
|
301
|
+
// Only known post-checkpoint arrivals may supersede it, never an old
|
|
302
|
+
// retained user turn encountered while scanning restored history.
|
|
303
|
+
for (const message of this.ctx.resumedInput ?? []) this.rememberUserMessage(message)
|
|
255
304
|
|
|
256
305
|
// One context-overflow relief per *stuck point*, not per run.
|
|
257
306
|
//
|
|
@@ -278,6 +327,26 @@ export class IterationOrchestrator {
|
|
|
278
327
|
// no post-loop block reaches.
|
|
279
328
|
try {
|
|
280
329
|
while (true) {
|
|
330
|
+
if (this.ctx.abortController.signal.aborted) {
|
|
331
|
+
runMgr.setStopReason('cancelled')
|
|
332
|
+
runMgr.markCancelled()
|
|
333
|
+
break
|
|
334
|
+
}
|
|
335
|
+
if (
|
|
336
|
+
this.ctx.structuredOutput?.mode === 'native' &&
|
|
337
|
+
this.nativeStructuredAttempts > this.structuredOutputRetryLimit()
|
|
338
|
+
) {
|
|
339
|
+
runMgr.setStopReason('structured_output_failed')
|
|
340
|
+
break
|
|
341
|
+
}
|
|
342
|
+
if (
|
|
343
|
+
this.ctx.structuredOutput?.review &&
|
|
344
|
+
this.structuredReviewAttempts >
|
|
345
|
+
(this.ctx.structuredOutput.maxReviews ?? DEFAULT_ANSWER_REVIEW_LIMIT)
|
|
346
|
+
) {
|
|
347
|
+
runMgr.setStopReason('answer_rejected')
|
|
348
|
+
break
|
|
349
|
+
}
|
|
281
350
|
// Read AND clear, in that order, in this one place.
|
|
282
351
|
//
|
|
283
352
|
// The flag is set by the previous iteration and read by this
|
|
@@ -325,6 +394,14 @@ export class IterationOrchestrator {
|
|
|
325
394
|
// run and been paid for; this is the seam a host with a live
|
|
326
395
|
// rate limit or a revoked tenant actually needs.
|
|
327
396
|
const veto = await this.beforeStep(runMgr.currentIteration + 1)
|
|
397
|
+
// The hook may settle because its run signal was aborted. Stop
|
|
398
|
+
// before interpreting that settlement as a policy refusal or
|
|
399
|
+
// counting an iteration that will never reach the provider.
|
|
400
|
+
if (this.ctx.abortController.signal.aborted) {
|
|
401
|
+
runMgr.setStopReason('cancelled')
|
|
402
|
+
runMgr.markCancelled()
|
|
403
|
+
break
|
|
404
|
+
}
|
|
328
405
|
if (veto) {
|
|
329
406
|
// Namespaced. The un-namespaced keys elsewhere in this file are
|
|
330
407
|
// the frozen inventory LOG-22 exists to drain; a new call site
|
|
@@ -431,10 +508,6 @@ export class IterationOrchestrator {
|
|
|
431
508
|
// compaction preserves). No-op when no provider is configured.
|
|
432
509
|
await refreshWorkingMemory(this.ctx)
|
|
433
510
|
await runCompactionCheck(this.ctx)
|
|
434
|
-
// A context edit is a host-visible state transition, not a prelude
|
|
435
|
-
// whose events may wait behind the next network call. In particular,
|
|
436
|
-
// a slow or failing provider must not leave the host displaying the
|
|
437
|
-
// pre-compaction context after Run.messages already shrank.
|
|
438
511
|
yield* this.ctx.drainPending()
|
|
439
512
|
|
|
440
513
|
// Cache discipline: keep the tools param byte-stable even on the
|
|
@@ -452,10 +525,25 @@ export class IterationOrchestrator {
|
|
|
452
525
|
// Shape this step before calling the model. `stopWhen` decides
|
|
453
526
|
// whether to keep going; this decides HOW. No-op when the host
|
|
454
527
|
// supplied no hook.
|
|
528
|
+
const contextModelBeforePreparation = this.ctx.contextModel ?? model
|
|
455
529
|
const step = await this.prepareStep(iterationNum)
|
|
530
|
+
stepModel = step.model ?? model
|
|
531
|
+
await this.selectContextModel(stepModel)
|
|
532
|
+
// Preserve post-compaction preparation/recall semantics. A changed
|
|
533
|
+
// model needs a second check against its own window; never replay
|
|
534
|
+
// host preparation effects merely to rebuild its request guidance.
|
|
535
|
+
if (stepModel !== contextModelBeforePreparation) await runCompactionCheck(this.ctx)
|
|
536
|
+
// Publish context edits before entering a possibly slow provider.
|
|
537
|
+
yield* this.ctx.drainPending()
|
|
456
538
|
|
|
457
539
|
const stepAllowedTools = step.allowedTools ?? this.ctx.allowedTools
|
|
458
|
-
const llmTools = this.ctx.tools
|
|
540
|
+
const llmTools = this.ctx.tools
|
|
541
|
+
.toLLMTools(stepAllowedTools)
|
|
542
|
+
.filter(
|
|
543
|
+
(tool) =>
|
|
544
|
+
this.ctx.structuredOutput?.mode !== 'native' ||
|
|
545
|
+
tool.function.name !== STRUCTURED_OUTPUT_TOOL_NAME,
|
|
546
|
+
)
|
|
459
547
|
// The same list the request was built from now also bounds what
|
|
460
548
|
// may run. Narrowing only the request left the restriction
|
|
461
549
|
// presentational — the model was shown fewer tools and could
|
|
@@ -632,6 +720,18 @@ export class IterationOrchestrator {
|
|
|
632
720
|
this.ctx.provider,
|
|
633
721
|
{
|
|
634
722
|
model: stepModel,
|
|
723
|
+
...(this.ctx.structuredOutput?.mode === 'native'
|
|
724
|
+
? {
|
|
725
|
+
responseFormat: {
|
|
726
|
+
type: 'json_schema' as const,
|
|
727
|
+
json_schema: {
|
|
728
|
+
name: 'structured_output',
|
|
729
|
+
schema: renderToolSchema(this.ctx.structuredOutput.schema),
|
|
730
|
+
strict: true,
|
|
731
|
+
},
|
|
732
|
+
},
|
|
733
|
+
}
|
|
734
|
+
: {}),
|
|
635
735
|
providerRoute: requestedRoute,
|
|
636
736
|
messages,
|
|
637
737
|
tools: llmTools.length > 0 ? llmTools : undefined,
|
|
@@ -771,11 +871,7 @@ export class IterationOrchestrator {
|
|
|
771
871
|
const contextFigures = this.ctx.compactionConfig
|
|
772
872
|
? (() => {
|
|
773
873
|
const measured = measureContext(this.ctx)
|
|
774
|
-
const window =
|
|
775
|
-
this.ctx.compactionConfig?.contextWindowTokens,
|
|
776
|
-
runConfig.model,
|
|
777
|
-
this.ctx.providerContextWindow,
|
|
778
|
-
)
|
|
874
|
+
const window = activeContextWindow(this.ctx)
|
|
779
875
|
return {
|
|
780
876
|
contextTokens: measured.tokens,
|
|
781
877
|
contextMeasuredBy: measured.source,
|
|
@@ -932,6 +1028,70 @@ export class IterationOrchestrator {
|
|
|
932
1028
|
costBefore,
|
|
933
1029
|
})
|
|
934
1030
|
|
|
1031
|
+
if (this.ctx.structuredOutput?.mode === 'native') {
|
|
1032
|
+
const candidate = await parseNativeCandidate(
|
|
1033
|
+
this.ctx.structuredOutput.schema,
|
|
1034
|
+
response,
|
|
1035
|
+
this.ctx.abortController.signal,
|
|
1036
|
+
)
|
|
1037
|
+
let outcome: 'accepted' | 'retry' | 'exhausted' | 'cancelled'
|
|
1038
|
+
if (candidate.success) outcome = await this.reviewStructuredOutput(candidate.value)
|
|
1039
|
+
else {
|
|
1040
|
+
this.nativeStructuredAttempts++
|
|
1041
|
+
runMgr.pushMessage(
|
|
1042
|
+
createRuntimeContextMessage(
|
|
1043
|
+
'Return a complete JSON value matching the supplied response schema. Do not continue a partial JSON fragment.',
|
|
1044
|
+
'structured-output',
|
|
1045
|
+
),
|
|
1046
|
+
)
|
|
1047
|
+
const checkpoint = await this.ctx.checkpointMgr.create(runMgr, iterationNum)
|
|
1048
|
+
await this.ctx.emitEvent({
|
|
1049
|
+
type: 'checkpoint_created',
|
|
1050
|
+
runId: runMgr.id,
|
|
1051
|
+
checkpointId: checkpoint.id,
|
|
1052
|
+
iteration: iterationNum,
|
|
1053
|
+
})
|
|
1054
|
+
outcome =
|
|
1055
|
+
this.nativeStructuredAttempts > this.structuredOutputRetryLimit()
|
|
1056
|
+
? 'exhausted'
|
|
1057
|
+
: 'retry'
|
|
1058
|
+
}
|
|
1059
|
+
await this.ctx.emitEvent({
|
|
1060
|
+
type: 'iteration_completed',
|
|
1061
|
+
runId: runMgr.id,
|
|
1062
|
+
iteration: iterationNum,
|
|
1063
|
+
hasToolCalls: false,
|
|
1064
|
+
})
|
|
1065
|
+
yield* this.ctx.drainPending()
|
|
1066
|
+
if (this.ctx.abortController.signal.aborted || outcome === 'cancelled') {
|
|
1067
|
+
runMgr.setStopReason('cancelled')
|
|
1068
|
+
runMgr.markCancelled()
|
|
1069
|
+
break
|
|
1070
|
+
}
|
|
1071
|
+
if (outcome === 'accepted') {
|
|
1072
|
+
if (!forceFinalize) {
|
|
1073
|
+
const changed = yield* this.holdForOutstandingWork(iterationNum, false)
|
|
1074
|
+
const inbound = this.deliverInbound()
|
|
1075
|
+
if (changed || inbound > 0) continue
|
|
1076
|
+
}
|
|
1077
|
+
if (this.ctx.abortController.signal.aborted) {
|
|
1078
|
+
runMgr.setStopReason('cancelled')
|
|
1079
|
+
runMgr.markCancelled()
|
|
1080
|
+
break
|
|
1081
|
+
}
|
|
1082
|
+
this.publishStructuredOutput()
|
|
1083
|
+
runMgr.setStopReason('end_turn')
|
|
1084
|
+
break
|
|
1085
|
+
}
|
|
1086
|
+
if (outcome === 'exhausted') {
|
|
1087
|
+
runMgr.setStopReason(
|
|
1088
|
+
candidate.success ? 'answer_rejected' : 'structured_output_failed',
|
|
1089
|
+
)
|
|
1090
|
+
break
|
|
1091
|
+
}
|
|
1092
|
+
continue
|
|
1093
|
+
}
|
|
1094
|
+
|
|
935
1095
|
const hasContent =
|
|
936
1096
|
response.message.content !== null && response.message.content.length > 0
|
|
937
1097
|
|
|
@@ -1022,6 +1182,11 @@ export class IterationOrchestrator {
|
|
|
1022
1182
|
// a loud stop rather than a loop.
|
|
1023
1183
|
if (!forceFinalize && this.ctx.reviewAnswer) {
|
|
1024
1184
|
const review = await this.reviewAnswer(response.message.content ?? '')
|
|
1185
|
+
if (this.ctx.abortController.signal.aborted) {
|
|
1186
|
+
runMgr.setStopReason('cancelled')
|
|
1187
|
+
runMgr.markCancelled()
|
|
1188
|
+
break
|
|
1189
|
+
}
|
|
1025
1190
|
if (review && !review.accept) {
|
|
1026
1191
|
const attempt = ++this.answerReviewAttempts
|
|
1027
1192
|
const limit = this.ctx.maxAnswerReviews ?? DEFAULT_ANSWER_REVIEW_LIMIT
|
|
@@ -1159,12 +1324,39 @@ export class IterationOrchestrator {
|
|
|
1159
1324
|
// run ends here rather than paying for another turn whose only
|
|
1160
1325
|
// job would be to restate it — unless it shared its turn with
|
|
1161
1326
|
// other calls, which relays instead. See the method.
|
|
1162
|
-
|
|
1327
|
+
const structuredOutcome = await this.captureStructuredOutput(
|
|
1328
|
+
reviewOutcome.results,
|
|
1329
|
+
response,
|
|
1330
|
+
)
|
|
1331
|
+
if (
|
|
1332
|
+
structuredOutcome === 'retry' ||
|
|
1333
|
+
structuredOutcome === 'exhausted' ||
|
|
1334
|
+
structuredOutcome === 'cancelled'
|
|
1335
|
+
) {
|
|
1336
|
+
await this.ctx.emitEvent({
|
|
1337
|
+
type: 'iteration_completed',
|
|
1338
|
+
runId: runMgr.id,
|
|
1339
|
+
iteration: iterationNum,
|
|
1340
|
+
hasToolCalls: true,
|
|
1341
|
+
})
|
|
1342
|
+
yield* this.ctx.drainPending()
|
|
1343
|
+
if (this.ctx.abortController.signal.aborted) {
|
|
1344
|
+
runMgr.setStopReason('cancelled')
|
|
1345
|
+
runMgr.markCancelled()
|
|
1346
|
+
break
|
|
1347
|
+
}
|
|
1348
|
+
if (structuredOutcome === 'retry') continue
|
|
1349
|
+
runMgr.setStopReason(
|
|
1350
|
+
structuredOutcome === 'cancelled' ? 'cancelled' : 'answer_rejected',
|
|
1351
|
+
)
|
|
1352
|
+
if (structuredOutcome === 'cancelled') runMgr.markCancelled()
|
|
1353
|
+
break
|
|
1354
|
+
}
|
|
1355
|
+
if (structuredOutcome === 'accepted') {
|
|
1163
1356
|
this.ctx.log.info('Structured output produced — ending run', {
|
|
1164
1357
|
[NAMZU.RUN_ID]: runMgr.id,
|
|
1165
1358
|
[NAMZU.ITERATION]: iterationNum,
|
|
1166
1359
|
})
|
|
1167
|
-
runMgr.setStopReason('end_turn')
|
|
1168
1360
|
await this.ctx.emitEvent({
|
|
1169
1361
|
type: 'iteration_completed',
|
|
1170
1362
|
runId: runMgr.id,
|
|
@@ -1172,6 +1364,13 @@ export class IterationOrchestrator {
|
|
|
1172
1364
|
hasToolCalls: true,
|
|
1173
1365
|
})
|
|
1174
1366
|
yield* this.ctx.drainPending()
|
|
1367
|
+
if (this.ctx.abortController.signal.aborted) {
|
|
1368
|
+
runMgr.setStopReason('cancelled')
|
|
1369
|
+
runMgr.markCancelled()
|
|
1370
|
+
break
|
|
1371
|
+
}
|
|
1372
|
+
this.publishStructuredOutput()
|
|
1373
|
+
runMgr.setStopReason('end_turn')
|
|
1175
1374
|
break
|
|
1176
1375
|
}
|
|
1177
1376
|
|
|
@@ -1450,9 +1649,9 @@ export class IterationOrchestrator {
|
|
|
1450
1649
|
/**
|
|
1451
1650
|
* Hold the run open for a worker that has not finished, and deliver it.
|
|
1452
1651
|
*
|
|
1453
|
-
* Returns whether a completion
|
|
1454
|
-
* caller continues
|
|
1455
|
-
*
|
|
1652
|
+
* Returns whether a completion or operator message entered the transcript —
|
|
1653
|
+
* the caller continues on `true`, so the model gets a turn to respond.
|
|
1654
|
+
* That turn is the entire justification for waiting, which
|
|
1456
1655
|
* is why only the exits that can still take one call this.
|
|
1457
1656
|
*
|
|
1458
1657
|
* Bounded by `settleGraceMs` and by `maxIterations`, so a worker that never
|
|
@@ -1473,14 +1672,34 @@ export class IterationOrchestrator {
|
|
|
1473
1672
|
[NAMZU.ITERATION]: iterationNum,
|
|
1474
1673
|
'namzu.runtime.grace_ms': graceMs,
|
|
1475
1674
|
})
|
|
1476
|
-
|
|
1675
|
+
// User input releases this wait without cancelling any child. Both waits
|
|
1676
|
+
// share a disposable signal so the losing arrival listener cannot leak.
|
|
1677
|
+
const waiting = new AbortController()
|
|
1678
|
+
const runSignal = this.ctx.abortController.signal
|
|
1679
|
+
const cancelWait = () => waiting.abort(runSignal.reason)
|
|
1680
|
+
runSignal.addEventListener('abort', cancelWait, { once: true })
|
|
1681
|
+
if (runSignal.aborted) cancelWait()
|
|
1682
|
+
try {
|
|
1683
|
+
await Promise.race([
|
|
1684
|
+
this.ctx.completionInbox.waitForArrival(graceMs, waiting.signal),
|
|
1685
|
+
...(this.ctx.waitForInbound ? [this.ctx.waitForInbound(waiting.signal)] : []),
|
|
1686
|
+
])
|
|
1687
|
+
} catch (error) {
|
|
1688
|
+
if (!runSignal.aborted) throw error
|
|
1689
|
+
} finally {
|
|
1690
|
+
waiting.abort()
|
|
1691
|
+
runSignal.removeEventListener('abort', cancelWait)
|
|
1692
|
+
}
|
|
1693
|
+
runSignal.throwIfAborted()
|
|
1477
1694
|
|
|
1478
1695
|
const arrived = this.ctx.completionInbox.drain()
|
|
1479
|
-
if (arrived.length
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1696
|
+
if (arrived.length > 0) {
|
|
1697
|
+
this.ctx.runMgr.pushMessage(
|
|
1698
|
+
createRuntimeContextMessage(formatCompletionNotification(arrived), 'task-completion'),
|
|
1699
|
+
)
|
|
1700
|
+
}
|
|
1701
|
+
const inbound = this.deliverInbound()
|
|
1702
|
+
if (arrived.length === 0 && inbound === 0) return false
|
|
1484
1703
|
await this.ctx.emitEvent({
|
|
1485
1704
|
type: 'iteration_completed',
|
|
1486
1705
|
runId: this.ctx.runMgr.id,
|
|
@@ -1583,19 +1802,51 @@ export class IterationOrchestrator {
|
|
|
1583
1802
|
* message becomes the reason, so an operator is not left with a run
|
|
1584
1803
|
* that stopped and no account of it.
|
|
1585
1804
|
*/
|
|
1805
|
+
private stepContext(stepNumber: number, prepared: PrepareStepResult): PrepareStepContext {
|
|
1806
|
+
const model = prepared.model ?? this.ctx.runConfig.model
|
|
1807
|
+
const window = resolveContextWindow(
|
|
1808
|
+
this.ctx.compactionConfig?.contextWindowTokens,
|
|
1809
|
+
model,
|
|
1810
|
+
model === this.ctx.runConfig.model
|
|
1811
|
+
? this.ctx.providerContextWindow
|
|
1812
|
+
: model === this.ctx.contextModel
|
|
1813
|
+
? this.ctx.activeProviderContextWindow
|
|
1814
|
+
: undefined,
|
|
1815
|
+
)
|
|
1816
|
+
const skills = prepared.skills ? renderSkillsSection([...prepared.skills]) : null
|
|
1817
|
+
const preamble = [prepared.system, skills].filter(Boolean).join('\n\n')
|
|
1818
|
+
const preparedTokens = preamble ? estimateMessageTokens(createSystemMessage(preamble)) : 0
|
|
1819
|
+
const responseReserve = Math.min(
|
|
1820
|
+
prepared.maxResponseTokens ??
|
|
1821
|
+
this.ctx.runConfig.maxResponseTokens ??
|
|
1822
|
+
Math.floor(window.tokens / 4),
|
|
1823
|
+
Math.floor(window.tokens / 4),
|
|
1824
|
+
)
|
|
1825
|
+
return {
|
|
1826
|
+
runId: this.ctx.runMgr.id,
|
|
1827
|
+
stepNumber,
|
|
1828
|
+
messages: this.ctx.runMgr.messages,
|
|
1829
|
+
...(this.latestUserMessage ? { latestUserMessage: this.latestUserMessage } : {}),
|
|
1830
|
+
signal: this.ctx.abortController.signal,
|
|
1831
|
+
contextBudget: {
|
|
1832
|
+
windowTokens: window.tokens,
|
|
1833
|
+
remainingTokens: Math.max(
|
|
1834
|
+
0,
|
|
1835
|
+
Math.floor(
|
|
1836
|
+
window.tokens - measureContext(this.ctx).tokens - preparedTokens - responseReserve,
|
|
1837
|
+
),
|
|
1838
|
+
),
|
|
1839
|
+
},
|
|
1840
|
+
steps: this.steps,
|
|
1841
|
+
prepared,
|
|
1842
|
+
}
|
|
1843
|
+
}
|
|
1844
|
+
|
|
1586
1845
|
private async beforeStep(stepNumber: number): Promise<StepVeto | undefined> {
|
|
1587
1846
|
const configured = this.ctx.beforeStep
|
|
1588
1847
|
if (!configured) return undefined
|
|
1589
1848
|
try {
|
|
1590
|
-
return (
|
|
1591
|
-
(await configured({
|
|
1592
|
-
runId: this.ctx.runMgr.id,
|
|
1593
|
-
stepNumber,
|
|
1594
|
-
messages: this.ctx.runMgr.messages,
|
|
1595
|
-
steps: this.steps,
|
|
1596
|
-
prepared: {},
|
|
1597
|
-
})) ?? undefined
|
|
1598
|
-
)
|
|
1849
|
+
return (await configured(this.stepContext(stepNumber, {}))) ?? undefined
|
|
1599
1850
|
} catch (err) {
|
|
1600
1851
|
return { reason: `beforeStep threw: ${toErrorMessage(err)}` }
|
|
1601
1852
|
}
|
|
@@ -1621,14 +1872,9 @@ export class IterationOrchestrator {
|
|
|
1621
1872
|
let result: PrepareStepResult = {}
|
|
1622
1873
|
for (const stage of stages) {
|
|
1623
1874
|
try {
|
|
1624
|
-
const decided = await stage(
|
|
1625
|
-
runId: this.ctx.runMgr.id,
|
|
1626
|
-
stepNumber,
|
|
1627
|
-
messages: this.ctx.runMgr.messages,
|
|
1628
|
-
steps: this.steps,
|
|
1629
|
-
prepared: result,
|
|
1630
|
-
})
|
|
1875
|
+
const decided = await stage(this.stepContext(stepNumber, result))
|
|
1631
1876
|
if (decided) result = { ...result, ...decided }
|
|
1877
|
+
await this.selectContextModel(result.model ?? this.ctx.runConfig.model)
|
|
1632
1878
|
} catch (err) {
|
|
1633
1879
|
// Skipped, and the rest still run: one broken concern must
|
|
1634
1880
|
// not silently disable the others it was declared beside.
|
|
@@ -1690,6 +1936,18 @@ export class IterationOrchestrator {
|
|
|
1690
1936
|
return prepared
|
|
1691
1937
|
}
|
|
1692
1938
|
|
|
1939
|
+
private async selectContextModel(model: string | undefined): Promise<void> {
|
|
1940
|
+
if (model !== (this.ctx.contextModel ?? this.ctx.runConfig.model)) {
|
|
1941
|
+
// A measurement from another tokenizer cannot price the new request.
|
|
1942
|
+
this.ctx.runMgr.clearLastPromptTokens()
|
|
1943
|
+
}
|
|
1944
|
+
this.ctx.contextModel = model
|
|
1945
|
+
this.ctx.activeProviderContextWindow =
|
|
1946
|
+
model && model !== this.ctx.runConfig.model && !this.ctx.compactionConfig?.contextWindowTokens
|
|
1947
|
+
? await this.ctx.resolveModelContextWindow?.(model)
|
|
1948
|
+
: undefined
|
|
1949
|
+
}
|
|
1950
|
+
|
|
1693
1951
|
/** Steps completed so far, exposed on the returned `Run`. */
|
|
1694
1952
|
private readonly steps: StepResult[] = []
|
|
1695
1953
|
|
|
@@ -1718,18 +1976,33 @@ export class IterationOrchestrator {
|
|
|
1718
1976
|
* empty drain must change nothing at all: a `continue` on nothing queued
|
|
1719
1977
|
* spends an iteration and a model call to say the same thing again.
|
|
1720
1978
|
*/
|
|
1979
|
+
private rememberUserMessage(message: Message, arriving = true): void {
|
|
1980
|
+
if (!isOperatorUserMessage(message)) return
|
|
1981
|
+
this.latestUserMessage = message
|
|
1982
|
+
// The hook field alone does not reach the model. Preserve arrivals in
|
|
1983
|
+
// the compaction state too, before their original message or attached
|
|
1984
|
+
// tool result can be shed. Initial history was already extracted at seed.
|
|
1985
|
+
const manager = this.ctx.workingStateManager
|
|
1986
|
+
if (arriving && manager) {
|
|
1987
|
+
extractFromUserMessage(manager, message.content, !manager.getState().task)
|
|
1988
|
+
}
|
|
1989
|
+
}
|
|
1990
|
+
|
|
1721
1991
|
private deliverInbound(): number {
|
|
1722
1992
|
const queued = this.ctx.inboundMessages?.() ?? []
|
|
1723
|
-
for (const message of queued)
|
|
1993
|
+
for (const message of queued) {
|
|
1994
|
+
this.ctx.runMgr.pushMessage(message)
|
|
1995
|
+
this.rememberUserMessage(message)
|
|
1996
|
+
}
|
|
1724
1997
|
|
|
1725
1998
|
// The steering channel's remainder. `attachSteering` already took
|
|
1726
1999
|
// what it could carry on a tool result; anything still pending is
|
|
1727
2000
|
// guidance from a turn that had no result to attach it to.
|
|
1728
2001
|
const stranded = this.ctx.steering?.drain()
|
|
1729
2002
|
if (stranded) {
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
)
|
|
2003
|
+
const message = createRuntimeContextMessage(formatSteeringNote(stranded), 'steering')
|
|
2004
|
+
this.ctx.runMgr.pushMessage(message)
|
|
2005
|
+
this.rememberUserMessage(createRuntimeContextMessage(stranded, 'steering'))
|
|
1733
2006
|
}
|
|
1734
2007
|
|
|
1735
2008
|
return queued.length + (stranded ? 1 : 0)
|
|
@@ -1836,7 +2109,10 @@ export class IterationOrchestrator {
|
|
|
1836
2109
|
|
|
1837
2110
|
/** Turns spent asking the model again for a valid structured output. */
|
|
1838
2111
|
private structuredOutputAttempts = 0
|
|
2112
|
+
private nativeStructuredAttempts = 0
|
|
1839
2113
|
private structuredOutputDone = false
|
|
2114
|
+
private pendingStructuredOutput: unknown
|
|
2115
|
+
private structuredReviewAttempts = 0
|
|
1840
2116
|
|
|
1841
2117
|
private structuredOutputRetryLimit(): number {
|
|
1842
2118
|
return this.ctx.structuredOutput?.maxRetries ?? DEFAULT_STRUCTURED_OUTPUT_RETRIES
|
|
@@ -1863,6 +2139,7 @@ export class IterationOrchestrator {
|
|
|
1863
2139
|
results: readonly ToolCallOutcome[],
|
|
1864
2140
|
response: ChatCompletionResponse,
|
|
1865
2141
|
): ToolCallOutcome | undefined {
|
|
2142
|
+
if (this.ctx.structuredOutput?.mode === 'native') return undefined
|
|
1866
2143
|
const terminal = results.filter((r) => this.ctx.tools.get(r.toolName)?.terminal === true)
|
|
1867
2144
|
if (terminal.length === 0) return undefined
|
|
1868
2145
|
|
|
@@ -1931,13 +2208,14 @@ export class IterationOrchestrator {
|
|
|
1931
2208
|
* doing work, and it is the bound the neighbour relies on for the
|
|
1932
2209
|
* identical pathology.
|
|
1933
2210
|
*/
|
|
1934
|
-
private captureStructuredOutput(
|
|
2211
|
+
private async captureStructuredOutput(
|
|
1935
2212
|
results: readonly ToolCallOutcome[],
|
|
1936
2213
|
response: ChatCompletionResponse,
|
|
1937
|
-
):
|
|
1938
|
-
if (!this.needsStructuredOutput()
|
|
2214
|
+
): Promise<'absent' | 'accepted' | 'retry' | 'exhausted' | 'cancelled'> {
|
|
2215
|
+
if (!this.needsStructuredOutput() || this.ctx.structuredOutput?.mode === 'native')
|
|
2216
|
+
return 'absent'
|
|
1939
2217
|
const hit = results.find((r) => r.toolName === STRUCTURED_OUTPUT_TOOL_NAME && !r.isError)
|
|
1940
|
-
if (!hit) return
|
|
2218
|
+
if (!hit) return 'absent'
|
|
1941
2219
|
|
|
1942
2220
|
const callCount = response.message.toolCalls?.length ?? 0
|
|
1943
2221
|
if (callCount > 1) {
|
|
@@ -1945,18 +2223,90 @@ export class IterationOrchestrator {
|
|
|
1945
2223
|
[NAMZU.RUN_ID]: this.ctx.runMgr.id,
|
|
1946
2224
|
'namzu.runtime.calls_in_turn': callCount,
|
|
1947
2225
|
})
|
|
1948
|
-
return
|
|
2226
|
+
return 'absent'
|
|
1949
2227
|
}
|
|
1950
2228
|
|
|
2229
|
+
let parsed: unknown
|
|
1951
2230
|
try {
|
|
1952
|
-
|
|
2231
|
+
parsed = JSON.parse(hit.output)
|
|
1953
2232
|
} catch {
|
|
1954
2233
|
// The tool serializes its own validated input, so this is
|
|
1955
2234
|
// unreachable in practice; keep the raw text rather than losing it.
|
|
1956
|
-
this.ctx.
|
|
2235
|
+
if (this.ctx.structuredOutput?.review)
|
|
2236
|
+
throw new Error(
|
|
2237
|
+
'Structured review requires an intact JSON tool result; check tool-output limits and result transformations',
|
|
2238
|
+
)
|
|
2239
|
+
parsed = hit.output
|
|
1957
2240
|
}
|
|
2241
|
+
return this.reviewStructuredOutput(parsed)
|
|
2242
|
+
}
|
|
2243
|
+
|
|
2244
|
+
private publishStructuredOutput(): void {
|
|
2245
|
+
this.ctx.runMgr.setStructuredOutput(this.pendingStructuredOutput)
|
|
1958
2246
|
this.structuredOutputDone = true
|
|
1959
|
-
|
|
2247
|
+
}
|
|
2248
|
+
|
|
2249
|
+
private async reviewStructuredOutput(
|
|
2250
|
+
parsed: unknown,
|
|
2251
|
+
): Promise<'accepted' | 'retry' | 'exhausted' | 'cancelled'> {
|
|
2252
|
+
if (this.ctx.abortController.signal.aborted) return 'cancelled'
|
|
2253
|
+
const reviewer = this.ctx.structuredOutput?.review
|
|
2254
|
+
if (reviewer) {
|
|
2255
|
+
const signal = this.ctx.abortController.signal
|
|
2256
|
+
if (signal.aborted) return 'cancelled'
|
|
2257
|
+
let onAbort: () => void = () => {}
|
|
2258
|
+
const aborted = new Promise<never>((_resolve, reject) => {
|
|
2259
|
+
onAbort = () => reject(signal.reason ?? new Error('Structured review cancelled'))
|
|
2260
|
+
signal.addEventListener('abort', onAbort, { once: true })
|
|
2261
|
+
})
|
|
2262
|
+
let verdict: AnswerReview
|
|
2263
|
+
try {
|
|
2264
|
+
verdict = await Promise.race([
|
|
2265
|
+
Promise.resolve().then(() =>
|
|
2266
|
+
reviewer(structuredClone(parsed), {
|
|
2267
|
+
runId: this.ctx.runMgr.id,
|
|
2268
|
+
iteration: this.ctx.runMgr.currentIteration,
|
|
2269
|
+
signal,
|
|
2270
|
+
messages: this.ctx.runMgr.messages,
|
|
2271
|
+
}),
|
|
2272
|
+
),
|
|
2273
|
+
aborted,
|
|
2274
|
+
])
|
|
2275
|
+
} catch (error) {
|
|
2276
|
+
if (signal.aborted) return 'cancelled'
|
|
2277
|
+
throw error
|
|
2278
|
+
} finally {
|
|
2279
|
+
signal.removeEventListener('abort', onAbort)
|
|
2280
|
+
}
|
|
2281
|
+
if (signal.aborted) return 'cancelled'
|
|
2282
|
+
if (!verdict || typeof verdict.accept !== 'boolean')
|
|
2283
|
+
throw new Error('Structured reviewer returned an invalid verdict')
|
|
2284
|
+
if (!verdict.accept) {
|
|
2285
|
+
if (typeof verdict.feedback !== 'string' || verdict.feedback.trim().length === 0)
|
|
2286
|
+
throw new Error('Structured reviewer rejection requires feedback')
|
|
2287
|
+
this.structuredReviewAttempts++
|
|
2288
|
+
this.ctx.runMgr.pushMessage(createRuntimeContextMessage(verdict.feedback, 'answer-review'))
|
|
2289
|
+
// Persist both the feedback and its consumed allowance before the
|
|
2290
|
+
// next request. This checkpoint is not an approval/park boundary.
|
|
2291
|
+
const checkpoint = await this.ctx.checkpointMgr.create(
|
|
2292
|
+
this.ctx.runMgr,
|
|
2293
|
+
this.ctx.runMgr.currentIteration,
|
|
2294
|
+
)
|
|
2295
|
+
await this.ctx.emitEvent({
|
|
2296
|
+
type: 'checkpoint_created',
|
|
2297
|
+
runId: this.ctx.runMgr.id,
|
|
2298
|
+
checkpointId: checkpoint.id,
|
|
2299
|
+
iteration: this.ctx.runMgr.currentIteration,
|
|
2300
|
+
})
|
|
2301
|
+
if (signal.aborted) return 'cancelled'
|
|
2302
|
+
return this.structuredReviewAttempts >
|
|
2303
|
+
(this.ctx.structuredOutput?.maxReviews ?? DEFAULT_ANSWER_REVIEW_LIMIT)
|
|
2304
|
+
? 'exhausted'
|
|
2305
|
+
: 'retry'
|
|
2306
|
+
}
|
|
2307
|
+
}
|
|
2308
|
+
this.pendingStructuredOutput = parsed
|
|
2309
|
+
return 'accepted'
|
|
1960
2310
|
}
|
|
1961
2311
|
|
|
1962
2312
|
/**
|
|
@@ -1977,6 +2327,7 @@ export class IterationOrchestrator {
|
|
|
1977
2327
|
return await this.ctx.reviewAnswer(answer, {
|
|
1978
2328
|
runId: this.ctx.runMgr.id,
|
|
1979
2329
|
iteration: this.ctx.runMgr.currentIteration,
|
|
2330
|
+
signal: this.ctx.abortController.signal,
|
|
1980
2331
|
messages: this.ctx.runMgr.messages,
|
|
1981
2332
|
})
|
|
1982
2333
|
} catch (err) {
|
|
@@ -2039,6 +2390,8 @@ export class IterationOrchestrator {
|
|
|
2039
2390
|
model: string,
|
|
2040
2391
|
reason: StopReason,
|
|
2041
2392
|
): Promise<StopReason | undefined> {
|
|
2393
|
+
if (this.ctx.structuredOutput?.mode === 'native') return 'structured_output_failed'
|
|
2394
|
+
|
|
2042
2395
|
const lastAssistant = [...this.ctx.runMgr.messages]
|
|
2043
2396
|
.reverse()
|
|
2044
2397
|
.find((m) => m.role === 'assistant')
|