@namzu/sdk 61.3.0 → 62.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 +61 -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/bridge/acp/permission.d.ts +8 -0
- package/dist/bridge/acp/permission.d.ts.map +1 -1
- package/dist/bridge/acp/permission.js.map +1 -1
- package/dist/bridge/acp/server.d.ts.map +1 -1
- package/dist/bridge/acp/server.js +8 -1
- package/dist/bridge/acp/server.js.map +1 -1
- package/dist/constants/tools/index.d.ts +2 -0
- package/dist/constants/tools/index.d.ts.map +1 -1
- package/dist/constants/tools/index.js +23 -0
- package/dist/constants/tools/index.js.map +1 -1
- package/dist/eval/harness-protection.js +1 -1
- package/dist/eval/harness-protection.js.map +1 -1
- package/dist/learning/cycle.d.ts +5 -3
- package/dist/learning/cycle.d.ts.map +1 -1
- package/dist/learning/cycle.js +11 -13
- package/dist/learning/cycle.js.map +1 -1
- package/dist/learning/guidance.d.ts +74 -0
- package/dist/learning/guidance.d.ts.map +1 -0
- package/dist/learning/guidance.js +259 -0
- package/dist/learning/guidance.js.map +1 -0
- package/dist/learning/skill.d.ts +2 -2
- package/dist/learning/skill.d.ts.map +1 -1
- package/dist/learning/skill.js +6 -6
- package/dist/learning/skill.js.map +1 -1
- package/dist/learning/store.d.ts.map +1 -1
- package/dist/learning/store.js +6 -6
- package/dist/learning/store.js.map +1 -1
- package/dist/pals/communication/ingress-schema.d.ts +8 -8
- package/dist/pals/communication/schema.d.ts +2 -2
- package/dist/peers/client.d.ts +2 -3
- package/dist/peers/client.d.ts.map +1 -1
- package/dist/peers/client.js +2 -3
- package/dist/peers/client.js.map +1 -1
- package/dist/peers/endpoint.d.ts +1 -2
- package/dist/peers/endpoint.d.ts.map +1 -1
- package/dist/peers/endpoint.js +1 -2
- package/dist/peers/endpoint.js.map +1 -1
- package/dist/peers/protocol.d.ts.map +1 -1
- package/dist/peers/protocol.js +1 -0
- package/dist/peers/protocol.js.map +1 -1
- package/dist/prompt/coding-agent-doctrine.d.ts +4 -4
- package/dist/prompt/coding-agent-doctrine.d.ts.map +1 -1
- package/dist/prompt/coding-agent-doctrine.js +5 -3
- package/dist/prompt/coding-agent-doctrine.js.map +1 -1
- package/dist/prompt/index.d.ts +0 -4
- package/dist/prompt/index.d.ts.map +1 -1
- package/dist/prompt/index.js +0 -2
- package/dist/prompt/index.js.map +1 -1
- package/dist/provider/fallback.d.ts.map +1 -1
- package/dist/provider/fallback.js +3 -0
- package/dist/provider/fallback.js.map +1 -1
- package/dist/provider/idle-timeout.d.ts.map +1 -1
- package/dist/provider/idle-timeout.js +5 -0
- package/dist/provider/idle-timeout.js.map +1 -1
- package/dist/provider/model-window-suffix.d.ts.map +1 -1
- package/dist/provider/model-window-suffix.js +1 -0
- package/dist/provider/model-window-suffix.js.map +1 -1
- package/dist/provider/retry.d.ts.map +1 -1
- package/dist/provider/retry.js +5 -0
- package/dist/provider/retry.js.map +1 -1
- package/dist/provider/step-stopped.d.ts +19 -0
- package/dist/provider/step-stopped.d.ts.map +1 -0
- package/dist/provider/step-stopped.js +25 -0
- package/dist/provider/step-stopped.js.map +1 -0
- package/dist/provider/token-budget.d.ts.map +1 -1
- package/dist/provider/token-budget.js +6 -1
- package/dist/provider/token-budget.js.map +1 -1
- package/dist/public-runtime.d.ts +4 -15
- package/dist/public-runtime.d.ts.map +1 -1
- package/dist/public-runtime.js +3 -14
- package/dist/public-runtime.js.map +1 -1
- package/dist/public-tools.d.ts +0 -2
- package/dist/public-tools.d.ts.map +1 -1
- package/dist/public-tools.js +0 -2
- package/dist/public-tools.js.map +1 -1
- package/dist/public-types.d.ts +3 -21
- package/dist/public-types.d.ts.map +1 -1
- package/dist/runtime/query/iteration/index.d.ts +17 -0
- package/dist/runtime/query/iteration/index.d.ts.map +1 -1
- package/dist/runtime/query/iteration/index.js +168 -5
- package/dist/runtime/query/iteration/index.js.map +1 -1
- package/dist/runtime/query/iteration/phases/per-call-review.d.ts.map +1 -1
- package/dist/runtime/query/iteration/phases/per-call-review.js +4 -5
- package/dist/runtime/query/iteration/phases/per-call-review.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 +6 -3
- package/dist/runtime/query/iteration/phases/tool-review.js.map +1 -1
- package/dist/runtime/query/iteration/stream-turn.d.ts +9 -1
- package/dist/runtime/query/iteration/stream-turn.d.ts.map +1 -1
- package/dist/runtime/query/iteration/stream-turn.js +48 -2
- package/dist/runtime/query/iteration/stream-turn.js.map +1 -1
- package/dist/runtime/query/resume-pending.d.ts.map +1 -1
- package/dist/runtime/query/resume-pending.js +7 -4
- package/dist/runtime/query/resume-pending.js.map +1 -1
- package/dist/runtime/query/review-policy.d.ts +40 -8
- package/dist/runtime/query/review-policy.d.ts.map +1 -1
- package/dist/runtime/query/review-policy.js +139 -24
- package/dist/runtime/query/review-policy.js.map +1 -1
- package/dist/runtime/query/turn/completion-audit.d.ts +32 -0
- package/dist/runtime/query/turn/completion-audit.d.ts.map +1 -0
- package/dist/runtime/query/turn/completion-audit.js +56 -0
- package/dist/runtime/query/turn/completion-audit.js.map +1 -0
- package/dist/runtime/query/turn/stall-monitor.d.ts +78 -0
- package/dist/runtime/query/turn/stall-monitor.d.ts.map +1 -0
- package/dist/runtime/query/turn/stall-monitor.js +101 -0
- package/dist/runtime/query/turn/stall-monitor.js.map +1 -0
- package/dist/session/paths.d.ts +1 -2
- package/dist/session/paths.d.ts.map +1 -1
- package/dist/session/paths.js +1 -4
- package/dist/session/paths.js.map +1 -1
- package/dist/tools/builtins/bash.d.ts +2 -1
- package/dist/tools/builtins/bash.d.ts.map +1 -1
- package/dist/tools/builtins/bash.js +5 -2
- package/dist/tools/builtins/bash.js.map +1 -1
- package/dist/tools/builtins/computer-use.d.ts +80 -0
- package/dist/tools/builtins/computer-use.d.ts.map +1 -1
- package/dist/tools/builtins/computer-use.js +172 -9
- package/dist/tools/builtins/computer-use.js.map +1 -1
- package/dist/tools/builtins/content-fingerprint.d.ts +13 -0
- package/dist/tools/builtins/content-fingerprint.d.ts.map +1 -1
- package/dist/tools/builtins/content-fingerprint.js +25 -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 +7 -2
- package/dist/tools/builtins/edit.js.map +1 -1
- package/dist/tools/builtins/shell-read-credit.d.ts +15 -0
- package/dist/tools/builtins/shell-read-credit.d.ts.map +1 -0
- package/dist/tools/builtins/shell-read-credit.js +161 -0
- package/dist/tools/builtins/shell-read-credit.js.map +1 -0
- package/dist/tools/paths.d.ts +15 -2
- package/dist/tools/paths.d.ts.map +1 -1
- package/dist/tools/paths.js +17 -2
- package/dist/tools/paths.js.map +1 -1
- package/dist/turn/evidence-recall.d.ts +1 -1
- package/dist/turn/evidence-recall.d.ts.map +1 -1
- package/dist/turn/evidence-recall.js +5 -14
- package/dist/turn/evidence-recall.js.map +1 -1
- package/dist/types/acp/index.d.ts +6 -0
- package/dist/types/acp/index.d.ts.map +1 -1
- package/dist/types/agent/base.d.ts +4 -0
- package/dist/types/agent/base.d.ts.map +1 -1
- package/dist/types/hitl/index.d.ts +8 -0
- package/dist/types/hitl/index.d.ts.map +1 -1
- package/dist/types/hitl/index.js.map +1 -1
- package/dist/types/ids/index.d.ts +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 +1 -0
- package/dist/types/message/index.js.map +1 -1
- package/dist/types/provider/interface.d.ts +12 -0
- package/dist/types/provider/interface.d.ts.map +1 -1
- package/dist/types/session/config.d.ts +25 -0
- package/dist/types/session/config.d.ts.map +1 -1
- package/dist/types/session/records.d.ts.map +1 -1
- package/dist/types/session/records.js +2 -0
- package/dist/types/session/records.js.map +1 -1
- package/dist/types/session/turn.d.ts +1 -1
- package/dist/types/session/turn.d.ts.map +1 -1
- package/dist/types/session/turn.js.map +1 -1
- package/package.json +1 -1
- package/src/agents/QueryAgent.ts +2 -0
- package/src/bridge/acp/permission.ts +8 -0
- package/src/bridge/acp/server.ts +7 -1
- package/src/constants/tools/index.ts +27 -0
- package/src/eval/harness-protection.ts +1 -1
- package/src/learning/cycle.ts +15 -16
- package/src/learning/guidance.ts +339 -0
- package/src/learning/skill.ts +7 -7
- package/src/learning/store.ts +5 -6
- package/src/peers/client.ts +2 -3
- package/src/peers/endpoint.ts +1 -2
- package/src/peers/protocol.ts +1 -0
- package/src/prompt/coding-agent-doctrine.ts +5 -3
- package/src/prompt/index.ts +0 -4
- package/src/provider/fallback.ts +7 -0
- package/src/provider/idle-timeout.ts +8 -0
- package/src/provider/model-window-suffix.ts +1 -0
- package/src/provider/retry.ts +8 -0
- package/src/provider/step-stopped.ts +27 -0
- package/src/provider/token-budget.ts +6 -1
- package/src/public-runtime.ts +10 -28
- package/src/public-tools.ts +0 -3
- package/src/public-types.ts +5 -137
- package/src/runtime/query/iteration/index.ts +207 -5
- package/src/runtime/query/iteration/phases/per-call-review.ts +7 -5
- package/src/runtime/query/iteration/phases/tool-review.ts +5 -3
- package/src/runtime/query/iteration/stream-turn.ts +51 -1
- package/src/runtime/query/resume-pending.ts +11 -4
- package/src/runtime/query/review-policy.ts +157 -24
- package/src/runtime/query/turn/completion-audit.ts +71 -0
- package/src/runtime/query/turn/stall-monitor.ts +158 -0
- package/src/session/paths.ts +2 -6
- package/src/tools/builtins/bash.ts +6 -2
- package/src/tools/builtins/computer-use.ts +245 -7
- package/src/tools/builtins/content-fingerprint.ts +25 -0
- package/src/tools/builtins/edit.ts +11 -2
- package/src/tools/builtins/shell-read-credit.ts +159 -0
- package/src/tools/paths.ts +18 -2
- package/src/turn/evidence-recall.ts +7 -15
- package/src/types/acp/index.ts +6 -0
- package/src/types/agent/base.ts +4 -0
- package/src/types/hitl/index.ts +8 -0
- package/src/types/ids/index.ts +1 -1
- package/src/types/message/index.ts +1 -0
- package/src/types/provider/interface.ts +13 -0
- package/src/types/session/config.ts +27 -0
- package/src/types/session/records.ts +2 -0
- package/src/types/session/turn.ts +2 -1
- package/dist/learning/deprecated.d.ts +0 -86
- package/dist/learning/deprecated.d.ts.map +0 -1
- package/dist/learning/deprecated.js +0 -22
- package/dist/learning/deprecated.js.map +0 -1
- package/dist/manager/resident/activity.d.ts +0 -74
- package/dist/manager/resident/activity.d.ts.map +0 -1
- package/dist/manager/resident/activity.js +0 -125
- package/dist/manager/resident/activity.js.map +0 -1
- package/dist/manager/resident/agenda.d.ts +0 -167
- package/dist/manager/resident/agenda.d.ts.map +0 -1
- package/dist/manager/resident/agenda.js +0 -588
- package/dist/manager/resident/agenda.js.map +0 -1
- package/dist/manager/resident/consumption.d.ts +0 -98
- package/dist/manager/resident/consumption.d.ts.map +0 -1
- package/dist/manager/resident/consumption.js +0 -237
- package/dist/manager/resident/consumption.js.map +0 -1
- package/dist/manager/resident/delivery-window.d.ts +0 -28
- package/dist/manager/resident/delivery-window.d.ts.map +0 -1
- package/dist/manager/resident/delivery-window.js +0 -80
- package/dist/manager/resident/delivery-window.js.map +0 -1
- package/dist/manager/resident/evidence-recall.d.ts +0 -30
- package/dist/manager/resident/evidence-recall.d.ts.map +0 -1
- package/dist/manager/resident/evidence-recall.js +0 -297
- package/dist/manager/resident/evidence-recall.js.map +0 -1
- package/dist/manager/resident/history-disk.d.ts +0 -10
- package/dist/manager/resident/history-disk.d.ts.map +0 -1
- package/dist/manager/resident/history-disk.js +0 -50
- package/dist/manager/resident/history-disk.js.map +0 -1
- package/dist/manager/resident/history.d.ts +0 -115
- package/dist/manager/resident/history.d.ts.map +0 -1
- package/dist/manager/resident/history.js +0 -203
- package/dist/manager/resident/history.js.map +0 -1
- package/dist/manager/resident/host.d.ts +0 -112
- package/dist/manager/resident/host.d.ts.map +0 -1
- package/dist/manager/resident/host.js +0 -254
- package/dist/manager/resident/host.js.map +0 -1
- package/dist/manager/resident/initiative.d.ts +0 -86
- package/dist/manager/resident/initiative.d.ts.map +0 -1
- package/dist/manager/resident/initiative.js +0 -131
- package/dist/manager/resident/initiative.js.map +0 -1
- package/dist/manager/resident/loop.d.ts +0 -49
- package/dist/manager/resident/loop.d.ts.map +0 -1
- package/dist/manager/resident/loop.js +0 -75
- package/dist/manager/resident/loop.js.map +0 -1
- package/dist/manager/resident/outbox.d.ts +0 -124
- package/dist/manager/resident/outbox.d.ts.map +0 -1
- package/dist/manager/resident/outbox.js +0 -216
- package/dist/manager/resident/outbox.js.map +0 -1
- package/dist/manager/resident/proposal.d.ts +0 -65
- package/dist/manager/resident/proposal.d.ts.map +0 -1
- package/dist/manager/resident/proposal.js +0 -77
- package/dist/manager/resident/proposal.js.map +0 -1
- package/dist/manager/resident/store.d.ts +0 -108
- package/dist/manager/resident/store.d.ts.map +0 -1
- package/dist/manager/resident/store.js +0 -205
- package/dist/manager/resident/store.js.map +0 -1
- package/dist/manager/resident/tool-evidence.d.ts +0 -112
- package/dist/manager/resident/tool-evidence.d.ts.map +0 -1
- package/dist/manager/resident/tool-evidence.js +0 -289
- package/dist/manager/resident/tool-evidence.js.map +0 -1
- package/dist/prompt/resident-learning.d.ts +0 -29
- package/dist/prompt/resident-learning.d.ts.map +0 -1
- package/dist/prompt/resident-learning.js +0 -126
- package/dist/prompt/resident-learning.js.map +0 -1
- package/dist/prompt/resident-step.d.ts +0 -42
- package/dist/prompt/resident-step.d.ts.map +0 -1
- package/dist/prompt/resident-step.js +0 -137
- package/dist/prompt/resident-step.js.map +0 -1
- package/dist/tools/resident-history.d.ts +0 -12
- package/dist/tools/resident-history.d.ts.map +0 -1
- package/dist/tools/resident-history.js +0 -82
- package/dist/tools/resident-history.js.map +0 -1
- package/dist/tools/resident-tool-evidence.d.ts +0 -9
- package/dist/tools/resident-tool-evidence.d.ts.map +0 -1
- package/dist/tools/resident-tool-evidence.js +0 -61
- package/dist/tools/resident-tool-evidence.js.map +0 -1
- package/src/learning/deprecated.ts +0 -124
- package/src/manager/resident/activity.ts +0 -211
- package/src/manager/resident/agenda.ts +0 -937
- package/src/manager/resident/consumption.ts +0 -335
- package/src/manager/resident/delivery-window.ts +0 -99
- package/src/manager/resident/evidence-recall.ts +0 -369
- package/src/manager/resident/history-disk.ts +0 -63
- package/src/manager/resident/history.ts +0 -348
- package/src/manager/resident/host.ts +0 -390
- package/src/manager/resident/initiative.ts +0 -231
- package/src/manager/resident/loop.ts +0 -119
- package/src/manager/resident/outbox.ts +0 -341
- package/src/manager/resident/proposal.ts +0 -119
- package/src/manager/resident/store.ts +0 -279
- package/src/manager/resident/tool-evidence.ts +0 -455
- package/src/prompt/resident-learning.ts +0 -152
- package/src/prompt/resident-step.ts +0 -182
- package/src/tools/resident-history.ts +0 -88
- package/src/tools/resident-tool-evidence.ts +0 -72
|
@@ -29,6 +29,8 @@ import { diffRequestContext, snapshotRequestContext, } from '../request-context.
|
|
|
29
29
|
import { DEFAULT_MAX_REQUEST_RICH_CONTENT_BYTES, markProviderRejectedImage, projectRequestRichContent, } from '../request-rich-content.js';
|
|
30
30
|
import { withoutVoidAssistantTurns } from '../request-void-turns.js';
|
|
31
31
|
import { formatSteeringNote, isOperatorUserMessage } from '../steering.js';
|
|
32
|
+
import { COMPLETION_AUDIT_MESSAGE, CompletionAudit } from '../turn/completion-audit.js';
|
|
33
|
+
import { FORCED_STEP_MESSAGE, REASONING_CAPPED_MESSAGE, REASONING_ONLY_MESSAGE, StallMonitor, callChangedState, reasoningCapChars, } from '../turn/stall-monitor.js';
|
|
32
34
|
import { effortForModel } from './effort-clamp.js';
|
|
33
35
|
import { parseNativeCandidate } from './native-output.js';
|
|
34
36
|
import { drainArrivedTaskCompletions, holdForOutstandingWork, settleOutstandingWork, } from './outstanding-work.js';
|
|
@@ -46,6 +48,8 @@ import { RequestRepair } from './request-repair.js';
|
|
|
46
48
|
import { placeRequestContext } from './step-context.js';
|
|
47
49
|
import { beforeStep, prepareStep, selectContextModel, stepContextMessage, workContext, } from './step-shaping.js';
|
|
48
50
|
import { streamProviderTurn } from './stream-turn.js';
|
|
51
|
+
/** Capped steps in a row after which the per-step cap stops applying for the turn's next step. */
|
|
52
|
+
const MAX_CAPPED_STREAK = 3;
|
|
49
53
|
/** A host reviewer is not the model transport, even when its cause is an HTTP failure. */
|
|
50
54
|
class AnswerReviewFailure extends NamzuError {
|
|
51
55
|
constructor(cause) {
|
|
@@ -193,6 +197,16 @@ export class IterationOrchestrator {
|
|
|
193
197
|
stopDeferredForOutstandingWork = false;
|
|
194
198
|
/** Nudges sent since the model last finished a call without hitting its output cap. */
|
|
195
199
|
outputContinuations = 0;
|
|
200
|
+
/** Watches the turn's steps for reasoning that piles up while nothing changes. */
|
|
201
|
+
stallMonitor;
|
|
202
|
+
/** Holds the turn back once when it changed files and checked nothing afterwards. */
|
|
203
|
+
completionAudit;
|
|
204
|
+
/** The next step must call a tool, at low effort: set by the stall monitor or a capped step. */
|
|
205
|
+
forceActionNextStep = false;
|
|
206
|
+
/** Steps in a row cut at the per-step reasoning cap; past a few the cap stops applying. */
|
|
207
|
+
cappedStreak = 0;
|
|
208
|
+
/** A reply that held only reasoning was already answered with one more request. */
|
|
209
|
+
reasoningOnlyRetried = false;
|
|
196
210
|
/**
|
|
197
211
|
* The model a refused request moved to. Once set it replaces the model the
|
|
198
212
|
* step asked for, for the rest of the turn: the request that was refused
|
|
@@ -275,6 +289,11 @@ export class IterationOrchestrator {
|
|
|
275
289
|
this.rememberUserMessage(createRuntimeContextMessage(text, 'steering'));
|
|
276
290
|
},
|
|
277
291
|
};
|
|
292
|
+
if (ctx.turnConfig.completionAudit === true)
|
|
293
|
+
this.completionAudit = new CompletionAudit();
|
|
294
|
+
if (ctx.turnConfig.reasoning?.stall !== false) {
|
|
295
|
+
this.stallMonitor = new StallMonitor(ctx.turnConfig.reasoning?.stall || undefined);
|
|
296
|
+
}
|
|
278
297
|
ctx.checkpointMgr.setLatestUserMessageSource(() => this.latestUserMessage);
|
|
279
298
|
ctx.checkpointMgr.setAnswerReviewAttemptsSource?.(() => this.answerReviewAttempts);
|
|
280
299
|
ctx.checkpointMgr.setStructuredReviewAttemptsSource?.(() => this.structuredReviewAttempts);
|
|
@@ -871,6 +890,11 @@ export class IterationOrchestrator {
|
|
|
871
890
|
// died part-way has already emitted both `message_started` and
|
|
872
891
|
// `message_completed` under this id, which is the trail a
|
|
873
892
|
// reader wants most on exactly that turn.
|
|
893
|
+
// A step the loop forces to act runs at low effort with a tool call
|
|
894
|
+
// required, for this step only. Low is used only where the model
|
|
895
|
+
// is known to offer it; effort is refused, not clamped.
|
|
896
|
+
const forcedAction = this.forceActionNextStep && !forceFinalize && llmTools.length > 0;
|
|
897
|
+
this.forceActionNextStep = false;
|
|
874
898
|
stepMessageId = generateMessageId();
|
|
875
899
|
const requestedMember = this.ctx.servingMember?.() ?? {
|
|
876
900
|
index: 0,
|
|
@@ -895,11 +919,22 @@ export class IterationOrchestrator {
|
|
|
895
919
|
});
|
|
896
920
|
}
|
|
897
921
|
}
|
|
922
|
+
// A forced action step runs at low effort, where the model is known
|
|
923
|
+
// to offer it; effort is refused, not clamped.
|
|
924
|
+
const offeredEfforts = this.ctx.provider.reasoningEffortLevelsFor?.(stepModel);
|
|
925
|
+
const stepEffort = forcedAction && requestEffort && (offeredEfforts?.includes('low') ?? false)
|
|
926
|
+
? 'low'
|
|
927
|
+
: requestEffort;
|
|
928
|
+
// A provider that refuses a forced tool choice (some models do, and
|
|
929
|
+
// so does manual extended thinking) is not sent one: the step keeps
|
|
930
|
+
// its low effort and asks in words, on this request only.
|
|
931
|
+
const forcedChoiceRefused = forcedAction &&
|
|
932
|
+
this.ctx.provider.acceptsForcedToolChoiceFor?.(stepModel, turnConfig.thinking) === false;
|
|
898
933
|
const operatorInputAtDispatch = this.latestUserMessage;
|
|
899
934
|
const latestReviewUserMessage = (this.ctx.reviewAnswer || this.ctx.structuredOutput?.review) && operatorInputAtDispatch
|
|
900
935
|
? structuredClone(operatorInputAtDispatch)
|
|
901
936
|
: undefined;
|
|
902
|
-
const { response, messageId, requestMessages } = yield* streamProviderTurn(this.ctx.provider, {
|
|
937
|
+
const { response, messageId, requestMessages, reasoningCapped = false, } = yield* streamProviderTurn(this.ctx.provider, {
|
|
903
938
|
model: stepModel,
|
|
904
939
|
...(this.ctx.structuredOutput?.mode === 'native'
|
|
905
940
|
? {
|
|
@@ -914,7 +949,9 @@ export class IterationOrchestrator {
|
|
|
914
949
|
}
|
|
915
950
|
: {}),
|
|
916
951
|
providerRoute: requestedRoute,
|
|
917
|
-
messages
|
|
952
|
+
messages: forcedChoiceRefused
|
|
953
|
+
? [...messages, createRuntimeContextMessage(FORCED_STEP_MESSAGE, 'progress-nudge')]
|
|
954
|
+
: messages,
|
|
918
955
|
tools: llmTools.length > 0 ? llmTools : undefined,
|
|
919
956
|
...(enforceToolInputSchema ? { enforceToolInputSchema } : {}),
|
|
920
957
|
// The forced-final turn wins: a step that asked to force a
|
|
@@ -925,13 +962,15 @@ export class IterationOrchestrator {
|
|
|
925
962
|
toolChoice: forceFinalize && llmTools.length > 0
|
|
926
963
|
? 'none'
|
|
927
964
|
: llmTools.length > 0
|
|
928
|
-
?
|
|
965
|
+
? forcedAction && !forcedChoiceRefused
|
|
966
|
+
? (step.toolChoice ?? 'required')
|
|
967
|
+
: step.toolChoice
|
|
929
968
|
: undefined,
|
|
930
969
|
temperature: step.temperature ?? turnConfig.temperature,
|
|
931
970
|
maxTokens: outputCapOverride ?? step.maxResponseTokens ?? turnConfig.maxResponseTokens,
|
|
932
971
|
cacheControl: { type: 'auto' },
|
|
933
972
|
...(turnConfig.thinking ? { thinking: turnConfig.thinking } : {}),
|
|
934
|
-
...(
|
|
973
|
+
...(stepEffort ? { effort: stepEffort } : {}),
|
|
935
974
|
...(!forceFinalize && turnConfig.webSearch
|
|
936
975
|
? { webSearch: turnConfig.webSearch }
|
|
937
976
|
: {}),
|
|
@@ -943,8 +982,15 @@ export class IterationOrchestrator {
|
|
|
943
982
|
onAccepted: (identity) => this.acceptProviderRejectedImage(identity),
|
|
944
983
|
textOnly: this.textOnlyRecovery(stepModel),
|
|
945
984
|
repair: this.requestRepair,
|
|
946
|
-
}, Boolean(this.ctx.reviewAnswer || this.ctx.structuredOutput?.review || this.ctx.advisoryCtx), recorder.sessionId
|
|
985
|
+
}, Boolean(this.ctx.reviewAnswer || this.ctx.structuredOutput?.review || this.ctx.advisoryCtx), recorder.sessionId,
|
|
986
|
+
// Applies only to a step that can act. Stops after a few capped
|
|
987
|
+
// steps in a row, so a model that cannot act within the allowance
|
|
988
|
+
// still gets to finish.
|
|
989
|
+
this.cappedStreak >= MAX_CAPPED_STREAK || forceFinalize || llmTools.length === 0
|
|
990
|
+
? undefined
|
|
991
|
+
: reasoningCapChars(turnConfig.reasoning, stepEffort));
|
|
947
992
|
stepResponse = response;
|
|
993
|
+
this.cappedStreak = reasoningCapped ? this.cappedStreak + 1 : 0;
|
|
948
994
|
const reviewRequest = {
|
|
949
995
|
...(requestMessages ? { requestMessages } : {}),
|
|
950
996
|
...(latestReviewUserMessage ? { latestUserMessage: latestReviewUserMessage } : {}),
|
|
@@ -1206,6 +1252,25 @@ export class IterationOrchestrator {
|
|
|
1206
1252
|
usageBefore,
|
|
1207
1253
|
costBefore,
|
|
1208
1254
|
});
|
|
1255
|
+
// The step spent its whole reasoning allowance before acting. Tell
|
|
1256
|
+
// the model so and make the next step an action step.
|
|
1257
|
+
if (reasoningCapped && !forceFinalize) {
|
|
1258
|
+
this.ctx.log.info('Reasoning reached the per-step cap — asking the model to act', {
|
|
1259
|
+
[NAMZU.TURN_ID]: recorder.turnId,
|
|
1260
|
+
[NAMZU.ITERATION]: iterationNum,
|
|
1261
|
+
});
|
|
1262
|
+
recorder.pushMessage(createRuntimeContextMessage(REASONING_CAPPED_MESSAGE, 'progress-nudge'));
|
|
1263
|
+
this.forceActionNextStep = true;
|
|
1264
|
+
this.observeStall(response, []);
|
|
1265
|
+
await this.ctx.emitEvent({
|
|
1266
|
+
type: 'iteration_completed',
|
|
1267
|
+
turnId: recorder.turnId,
|
|
1268
|
+
iteration: iterationNum,
|
|
1269
|
+
hasToolCalls: false,
|
|
1270
|
+
});
|
|
1271
|
+
yield* this.ctx.drainPending();
|
|
1272
|
+
continue;
|
|
1273
|
+
}
|
|
1209
1274
|
if (this.ctx.structuredOutput?.mode === 'native') {
|
|
1210
1275
|
const candidate = await parseNativeCandidate(this.ctx.structuredOutput.schema, response, this.ctx.abortController.signal);
|
|
1211
1276
|
let outcome;
|
|
@@ -1445,6 +1510,27 @@ export class IterationOrchestrator {
|
|
|
1445
1510
|
let closingStopReason = forceFinalize
|
|
1446
1511
|
? guardResult.stopReason
|
|
1447
1512
|
: undefined;
|
|
1513
|
+
const reasoningOnly = !hasContent && (response.message.reasoning?.length ?? 0) > 0;
|
|
1514
|
+
if (hasContent)
|
|
1515
|
+
this.reasoningOnlyRetried = false;
|
|
1516
|
+
// A reply of reasoning alone is not an end: ask once more, plainly,
|
|
1517
|
+
// before the closing request below.
|
|
1518
|
+
if (reasoningOnly && !forceFinalize && !this.reasoningOnlyRetried) {
|
|
1519
|
+
this.reasoningOnlyRetried = true;
|
|
1520
|
+
this.ctx.log.warn('Reply held reasoning only — asking once more', {
|
|
1521
|
+
[NAMZU.TURN_ID]: recorder.turnId,
|
|
1522
|
+
[NAMZU.ITERATION]: iterationNum,
|
|
1523
|
+
});
|
|
1524
|
+
recorder.pushMessage(createRuntimeContextMessage(REASONING_ONLY_MESSAGE, 'progress-nudge'));
|
|
1525
|
+
await this.ctx.emitEvent({
|
|
1526
|
+
type: 'iteration_completed',
|
|
1527
|
+
turnId: recorder.turnId,
|
|
1528
|
+
iteration: iterationNum,
|
|
1529
|
+
hasToolCalls: false,
|
|
1530
|
+
});
|
|
1531
|
+
yield* this.ctx.drainPending();
|
|
1532
|
+
continue;
|
|
1533
|
+
}
|
|
1448
1534
|
if (!hasContent && !forceFinalize) {
|
|
1449
1535
|
this.ctx.log.warn('Empty completion detected — requesting final summary', {
|
|
1450
1536
|
[NAMZU.ITERATION]: iterationNum,
|
|
@@ -1452,6 +1538,13 @@ export class IterationOrchestrator {
|
|
|
1452
1538
|
});
|
|
1453
1539
|
closingStopReason = await this.requestFinalResponse(this.refusalPinnedModel ?? model, 'end_turn');
|
|
1454
1540
|
yield* this.ctx.drainPending();
|
|
1541
|
+
// Never end silently: if even the closing request produced nothing,
|
|
1542
|
+
// say so in plain words and how to go on.
|
|
1543
|
+
if (reasoningOnly &&
|
|
1544
|
+
closingStopReason === undefined &&
|
|
1545
|
+
!([...recorder.messages].reverse().find((m) => m.role === 'assistant')?.content ?? '').length) {
|
|
1546
|
+
recorder.setLastError('The model stopped after thinking without giving an answer or taking an action, even when asked again. Say "continue" and it will pick the work up from here.');
|
|
1547
|
+
}
|
|
1455
1548
|
}
|
|
1456
1549
|
await this.ctx.emitEvent({
|
|
1457
1550
|
type: 'iteration_completed',
|
|
@@ -1483,6 +1576,17 @@ export class IterationOrchestrator {
|
|
|
1483
1576
|
// The model is done and has no tool calls. A `turn_end` (or
|
|
1484
1577
|
// `subagent_stop`) hook may refuse to let it be: its reason goes
|
|
1485
1578
|
// back to the model and the turn goes on.
|
|
1579
|
+
// Files were changed and nothing checked them afterwards: ask once
|
|
1580
|
+
// for a check before the turn is allowed to end.
|
|
1581
|
+
if (!forceFinalize &&
|
|
1582
|
+
closingStopReason === undefined &&
|
|
1583
|
+
this.completionAudit?.takeBlock()) {
|
|
1584
|
+
this.ctx.log.info('Files changed and nothing checked them — asking for a check', {
|
|
1585
|
+
[NAMZU.TURN_ID]: recorder.turnId,
|
|
1586
|
+
});
|
|
1587
|
+
recorder.pushMessage(createRuntimeContextMessage(COMPLETION_AUDIT_MESSAGE, 'progress-nudge'));
|
|
1588
|
+
continue;
|
|
1589
|
+
}
|
|
1486
1590
|
if (!forceFinalize && closingStopReason === undefined) {
|
|
1487
1591
|
const feedback = yield* this.askStopHooks();
|
|
1488
1592
|
const stoppedByHook = this.ctx.toolExecutor.takeHalt?.();
|
|
@@ -1520,6 +1624,9 @@ export class IterationOrchestrator {
|
|
|
1520
1624
|
usageBefore,
|
|
1521
1625
|
costBefore,
|
|
1522
1626
|
});
|
|
1627
|
+
this.reasoningOnlyRetried = false;
|
|
1628
|
+
this.observeStall(response, reviewOutcome.results);
|
|
1629
|
+
this.observeAudit(response, reviewOutcome.results);
|
|
1523
1630
|
if (reviewOutcome.decision === 'stop') {
|
|
1524
1631
|
return;
|
|
1525
1632
|
}
|
|
@@ -2645,6 +2752,62 @@ export class IterationOrchestrator {
|
|
|
2645
2752
|
return undefined;
|
|
2646
2753
|
}
|
|
2647
2754
|
}
|
|
2755
|
+
/** Feed the completion audit the calls of one finished step. */
|
|
2756
|
+
observeAudit(response, results) {
|
|
2757
|
+
const audit = this.completionAudit;
|
|
2758
|
+
if (!audit)
|
|
2759
|
+
return;
|
|
2760
|
+
const calls = new Map((response.message.toolCalls ?? []).map((c) => [c.id, c]));
|
|
2761
|
+
audit.observe(results.map((result) => {
|
|
2762
|
+
let input;
|
|
2763
|
+
try {
|
|
2764
|
+
const call = calls.get(result.toolCallId);
|
|
2765
|
+
input = call ? JSON.parse(call.function.arguments) : undefined;
|
|
2766
|
+
}
|
|
2767
|
+
catch {
|
|
2768
|
+
input = undefined;
|
|
2769
|
+
}
|
|
2770
|
+
return { toolName: result.toolName, input, isError: result.isError };
|
|
2771
|
+
}));
|
|
2772
|
+
}
|
|
2773
|
+
/**
|
|
2774
|
+
* Feed the stall monitor one finished step and act on its verdict: a nudge
|
|
2775
|
+
* is recorded as a message, a force makes the next step an action step.
|
|
2776
|
+
*/
|
|
2777
|
+
observeStall(response, results) {
|
|
2778
|
+
const monitor = this.stallMonitor;
|
|
2779
|
+
if (!monitor)
|
|
2780
|
+
return;
|
|
2781
|
+
const calls = new Map((response.message.toolCalls ?? []).map((c) => [c.id, c]));
|
|
2782
|
+
let changedState = false;
|
|
2783
|
+
for (const result of results) {
|
|
2784
|
+
const call = calls.get(result.toolCallId);
|
|
2785
|
+
let readOnly;
|
|
2786
|
+
try {
|
|
2787
|
+
const input = call ? JSON.parse(call.function.arguments) : undefined;
|
|
2788
|
+
readOnly = this.ctx.tools.get(result.toolName)?.isReadOnly?.(input);
|
|
2789
|
+
}
|
|
2790
|
+
catch {
|
|
2791
|
+
readOnly = undefined;
|
|
2792
|
+
}
|
|
2793
|
+
if (callChangedState(result.toolName, readOnly, result.isError))
|
|
2794
|
+
changedState = true;
|
|
2795
|
+
}
|
|
2796
|
+
const reasoningChars = (response.message.reasoning ?? []).reduce((n, block) => n + (block.text?.length ?? 0), 0);
|
|
2797
|
+
const directive = monitor.observe({ reasoningChars, changedState });
|
|
2798
|
+
if (directive.kind === 'nudge') {
|
|
2799
|
+
this.ctx.log.info('Many steps without a change — nudging the model to act', {
|
|
2800
|
+
[NAMZU.TURN_ID]: this.ctx.recorder.turnId,
|
|
2801
|
+
});
|
|
2802
|
+
this.ctx.recorder.pushMessage(createRuntimeContextMessage(directive.text, 'progress-nudge'));
|
|
2803
|
+
}
|
|
2804
|
+
else if (directive.kind === 'force') {
|
|
2805
|
+
this.ctx.log.info('Still no change after the nudge — forcing an action step', {
|
|
2806
|
+
[NAMZU.TURN_ID]: this.ctx.recorder.turnId,
|
|
2807
|
+
});
|
|
2808
|
+
this.forceActionNextStep = true;
|
|
2809
|
+
}
|
|
2810
|
+
}
|
|
2648
2811
|
async requestFinalResponse(model, reason) {
|
|
2649
2812
|
if (this.ctx.structuredOutput?.mode === 'native')
|
|
2650
2813
|
return 'structured_output_failed';
|