@qduc/term2 0.31.1 → 0.32.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/README.md +52 -370
- package/dist/agent.d.ts +2 -1
- package/dist/agent.d.ts.map +1 -1
- package/dist/agent.js +11 -1
- package/dist/agent.js.map +1 -1
- package/dist/app.d.ts +3 -1
- package/dist/app.d.ts.map +1 -1
- package/dist/app.js +44 -4
- package/dist/app.js.map +1 -1
- package/dist/build-info.json +2 -2
- package/dist/cli.js +13 -3
- package/dist/cli.js.map +1 -1
- package/dist/commands/goal-command.d.ts.map +1 -1
- package/dist/commands/goal-command.js +9 -8
- package/dist/commands/goal-command.js.map +1 -1
- package/dist/commands/retry-failed-turn-command.d.ts.map +1 -1
- package/dist/commands/retry-failed-turn-command.js +3 -4
- package/dist/commands/retry-failed-turn-command.js.map +1 -1
- package/dist/components/InputBox.js +4 -6
- package/dist/components/InputBox.js.map +1 -1
- package/dist/components/layout/BottomArea.d.ts.map +1 -1
- package/dist/components/layout/BottomArea.js +13 -11
- package/dist/components/layout/BottomArea.js.map +1 -1
- package/dist/components/message/MessageList.d.ts +3 -1
- package/dist/components/message/MessageList.d.ts.map +1 -1
- package/dist/components/message/MessageList.js +5 -2
- package/dist/components/message/MessageList.js.map +1 -1
- package/dist/components/message/SessionBoundary.d.ts +11 -0
- package/dist/components/message/SessionBoundary.d.ts.map +1 -0
- package/dist/components/message/SessionBoundary.js +22 -0
- package/dist/components/message/SessionBoundary.js.map +1 -0
- package/dist/contracts/provider-input.d.ts +10 -0
- package/dist/contracts/provider-input.d.ts.map +1 -1
- package/dist/contracts/provider-input.js.map +1 -1
- package/dist/contracts/run-termination.d.ts +3 -1
- package/dist/contracts/run-termination.d.ts.map +1 -1
- package/dist/hooks/settings-completion-config.d.ts.map +1 -1
- package/dist/hooks/settings-completion-config.js +1 -0
- package/dist/hooks/settings-completion-config.js.map +1 -1
- package/dist/lib/agent-chat-service.d.ts +6 -0
- package/dist/lib/agent-chat-service.d.ts.map +1 -1
- package/dist/lib/agent-chat-service.js +27 -3
- package/dist/lib/agent-chat-service.js.map +1 -1
- package/dist/lib/agent-client.d.ts +6 -0
- package/dist/lib/agent-client.d.ts.map +1 -1
- package/dist/lib/agent-client.js +80 -22
- package/dist/lib/agent-client.js.map +1 -1
- package/dist/lib/agent-configuration.d.ts +2 -0
- package/dist/lib/agent-configuration.d.ts.map +1 -1
- package/dist/lib/agent-configuration.js +5 -0
- package/dist/lib/agent-configuration.js.map +1 -1
- package/dist/lib/agent-factory.d.ts.map +1 -1
- package/dist/lib/agent-factory.js +15 -4
- package/dist/lib/agent-factory.js.map +1 -1
- package/dist/non-interactive.d.ts +5 -0
- package/dist/non-interactive.d.ts.map +1 -1
- package/dist/non-interactive.js +63 -6
- package/dist/non-interactive.js.map +1 -1
- package/dist/prompts/durable-goal-context.d.ts.map +1 -1
- package/dist/prompts/durable-goal-context.js +12 -2
- package/dist/prompts/durable-goal-context.js.map +1 -1
- package/dist/prompts/durable-goal-context.test.ts +11 -0
- package/dist/prompts/durable-goal-context.ts +13 -2
- package/dist/providers/ai-sdk-openrouter.provider.js +3 -2
- package/dist/providers/ai-sdk-openrouter.provider.js.map +1 -1
- package/dist/providers/ai-sdk-streamed-model.d.ts.map +1 -1
- package/dist/providers/ai-sdk-streamed-model.js +12 -2
- package/dist/providers/ai-sdk-streamed-model.js.map +1 -1
- package/dist/providers/codex-responses-model.d.ts.map +1 -1
- package/dist/providers/codex-responses-model.js +35 -16
- package/dist/providers/codex-responses-model.js.map +1 -1
- package/dist/providers/openai-chat-completions-model.d.ts.map +1 -1
- package/dist/providers/openai-chat-completions-model.js +11 -3
- package/dist/providers/openai-chat-completions-model.js.map +1 -1
- package/dist/services/agent-runtime/application-run-loop.d.ts +34 -1
- package/dist/services/agent-runtime/application-run-loop.d.ts.map +1 -1
- package/dist/services/agent-runtime/application-run-loop.js +174 -33
- package/dist/services/agent-runtime/application-run-loop.js.map +1 -1
- package/dist/services/agent-runtime/context-compaction/index.d.ts.map +1 -1
- package/dist/services/agent-runtime/context-compaction/index.js +65 -16
- package/dist/services/agent-runtime/context-compaction/index.js.map +1 -1
- package/dist/services/agent-runtime/context-compaction/local-context-compactor.d.ts +7 -1
- package/dist/services/agent-runtime/context-compaction/local-context-compactor.d.ts.map +1 -1
- package/dist/services/agent-runtime/context-compaction/local-context-compactor.js +115 -20
- package/dist/services/agent-runtime/context-compaction/local-context-compactor.js.map +1 -1
- package/dist/services/agent-runtime/model-context-policy.d.ts +21 -0
- package/dist/services/agent-runtime/model-context-policy.d.ts.map +1 -0
- package/dist/services/agent-runtime/model-context-policy.js +46 -0
- package/dist/services/agent-runtime/model-context-policy.js.map +1 -0
- package/dist/services/agent-runtime/request-input-limit.d.ts +31 -0
- package/dist/services/agent-runtime/request-input-limit.d.ts.map +1 -0
- package/dist/services/agent-runtime/request-input-limit.js +86 -0
- package/dist/services/agent-runtime/request-input-limit.js.map +1 -0
- package/dist/services/agent-runtime/run-budget.d.ts +3 -5
- package/dist/services/agent-runtime/run-budget.d.ts.map +1 -1
- package/dist/services/agent-runtime/run-budget.js.map +1 -1
- package/dist/services/agent-runtime/tool-call-execution.d.ts +24 -2
- package/dist/services/agent-runtime/tool-call-execution.d.ts.map +1 -1
- package/dist/services/agent-runtime/tool-call-execution.js +36 -6
- package/dist/services/agent-runtime/tool-call-execution.js.map +1 -1
- package/dist/services/agent-runtime/tool-invocation-context.d.ts +24 -12
- package/dist/services/agent-runtime/tool-invocation-context.d.ts.map +1 -1
- package/dist/services/agent-runtime/tool-invocation-context.js +38 -27
- package/dist/services/agent-runtime/tool-invocation-context.js.map +1 -1
- package/dist/services/approval/approval-replay.d.ts +15 -24
- package/dist/services/approval/approval-replay.d.ts.map +1 -1
- package/dist/services/approval/approval-replay.js +12 -30
- package/dist/services/approval/approval-replay.js.map +1 -1
- package/dist/services/approval/non-interactive-approval-policy.d.ts.map +1 -1
- package/dist/services/approval/non-interactive-approval-policy.js +11 -0
- package/dist/services/approval/non-interactive-approval-policy.js.map +1 -1
- package/dist/services/approval/tool-approval-batch-coordinator.d.ts.map +1 -1
- package/dist/services/approval/tool-approval-batch-coordinator.js +0 -5
- package/dist/services/approval/tool-approval-batch-coordinator.js.map +1 -1
- package/dist/services/conversation/conversation-checkpoint-provenance.d.ts.map +1 -1
- package/dist/services/conversation/conversation-checkpoint-provenance.js +10 -2
- package/dist/services/conversation/conversation-checkpoint-provenance.js.map +1 -1
- package/dist/services/conversation/conversation-events.d.ts +2 -0
- package/dist/services/conversation/conversation-events.d.ts.map +1 -1
- package/dist/services/conversation/conversation-events.js.map +1 -1
- package/dist/services/conversation/conversation-orchestrator.d.ts +1 -1
- package/dist/services/conversation/conversation-orchestrator.d.ts.map +1 -1
- package/dist/services/conversation/conversation-orchestrator.js +14 -2
- package/dist/services/conversation/conversation-orchestrator.js.map +1 -1
- package/dist/services/conversation/conversation-replay.d.ts.map +1 -1
- package/dist/services/conversation/conversation-replay.js +78 -3
- package/dist/services/conversation/conversation-replay.js.map +1 -1
- package/dist/services/conversation/conversation-service.d.ts +2 -2
- package/dist/services/conversation/conversation-service.d.ts.map +1 -1
- package/dist/services/conversation/conversation-service.js +5 -1
- package/dist/services/conversation/conversation-service.js.map +1 -1
- package/dist/services/conversation/conversation-state-projector.d.ts +1 -0
- package/dist/services/conversation/conversation-state-projector.d.ts.map +1 -1
- package/dist/services/conversation/conversation-state-projector.js +5 -1
- package/dist/services/conversation/conversation-state-projector.js.map +1 -1
- package/dist/services/conversation/durable-goal-stop-check.d.ts +141 -0
- package/dist/services/conversation/durable-goal-stop-check.d.ts.map +1 -0
- package/dist/services/conversation/durable-goal-stop-check.js +351 -0
- package/dist/services/conversation/durable-goal-stop-check.js.map +1 -0
- package/dist/services/conversation/durable-goal.d.ts +16 -1
- package/dist/services/conversation/durable-goal.d.ts.map +1 -1
- package/dist/services/conversation/durable-goal.js +8 -0
- package/dist/services/conversation/durable-goal.js.map +1 -1
- package/dist/services/conversation/local-checkpoint-projection.d.ts.map +1 -1
- package/dist/services/conversation/local-checkpoint-projection.js +12 -1
- package/dist/services/conversation/local-checkpoint-projection.js.map +1 -1
- package/dist/services/conversation/session-browser.d.ts +2 -0
- package/dist/services/conversation/session-browser.d.ts.map +1 -1
- package/dist/services/conversation/session-browser.js +23 -8
- package/dist/services/conversation/session-browser.js.map +1 -1
- package/dist/services/conversation/session-index/session-index-worker-client.d.ts +3 -0
- package/dist/services/conversation/session-index/session-index-worker-client.d.ts.map +1 -1
- package/dist/services/conversation/session-index/session-index-worker-client.js +6 -1
- package/dist/services/conversation/session-index/session-index-worker-client.js.map +1 -1
- package/dist/services/conversation/session-index/session-index-worker.d.ts +16 -1
- package/dist/services/conversation/session-index/session-index-worker.d.ts.map +1 -1
- package/dist/services/conversation/session-index/session-index-worker.js +16 -0
- package/dist/services/conversation/session-index/session-index-worker.js.map +1 -1
- package/dist/services/conversation-agent-client.d.ts +1 -0
- package/dist/services/conversation-agent-client.d.ts.map +1 -1
- package/dist/services/logging/conversation-log-events.d.ts +7 -0
- package/dist/services/logging/conversation-log-events.d.ts.map +1 -1
- package/dist/services/logging/conversation-log-events.js.map +1 -1
- package/dist/services/retry/retry-classifier.d.ts.map +1 -1
- package/dist/services/retry/retry-classifier.js +2 -1
- package/dist/services/retry/retry-classifier.js.map +1 -1
- package/dist/services/retry/retry-error-classification.d.ts.map +1 -1
- package/dist/services/retry/retry-error-classification.js +1 -0
- package/dist/services/retry/retry-error-classification.js.map +1 -1
- package/dist/services/service-interfaces.d.ts +2 -0
- package/dist/services/service-interfaces.d.ts.map +1 -1
- package/dist/services/session/initial-turn-recovery-handler.d.ts.map +1 -1
- package/dist/services/session/initial-turn-recovery-handler.js +6 -0
- package/dist/services/session/initial-turn-recovery-handler.js.map +1 -1
- package/dist/services/session/session-composition.d.ts.map +1 -1
- package/dist/services/session/session-composition.js +7 -5
- package/dist/services/session/session-composition.js.map +1 -1
- package/dist/services/session/session-manager.d.ts +2 -0
- package/dist/services/session/session-manager.d.ts.map +1 -1
- package/dist/services/session/session-manager.js +10 -0
- package/dist/services/session/session-manager.js.map +1 -1
- package/dist/services/session/session-tool-tracker.d.ts +1 -0
- package/dist/services/session/session-tool-tracker.d.ts.map +1 -1
- package/dist/services/session/session-tool-tracker.js +8 -0
- package/dist/services/session/session-tool-tracker.js.map +1 -1
- package/dist/services/session/terminal-result-collector.d.ts.map +1 -1
- package/dist/services/session/terminal-result-collector.js +3 -0
- package/dist/services/session/terminal-result-collector.js.map +1 -1
- package/dist/services/session/turn-workflow.d.ts.map +1 -1
- package/dist/services/session/turn-workflow.js +3 -0
- package/dist/services/session/turn-workflow.js.map +1 -1
- package/dist/services/settings/settings-env.d.ts.map +1 -1
- package/dist/services/settings/settings-env.js +6 -0
- package/dist/services/settings/settings-env.js.map +1 -1
- package/dist/services/settings/settings-persistence.d.ts +2 -1
- package/dist/services/settings/settings-persistence.d.ts.map +1 -1
- package/dist/services/settings/settings-persistence.js +1 -1
- package/dist/services/settings/settings-persistence.js.map +1 -1
- package/dist/services/settings/settings-schema.d.ts +7 -1
- package/dist/services/settings/settings-schema.d.ts.map +1 -1
- package/dist/services/settings/settings-schema.js +17 -6
- package/dist/services/settings/settings-schema.js.map +1 -1
- package/dist/services/settings/settings-service.d.ts +3 -0
- package/dist/services/settings/settings-service.d.ts.map +1 -1
- package/dist/services/settings/settings-service.js +74 -31
- package/dist/services/settings/settings-service.js.map +1 -1
- package/dist/services/settings/settings-sources.d.ts +1 -0
- package/dist/services/settings/settings-sources.d.ts.map +1 -1
- package/dist/services/settings/settings-sources.js +1 -0
- package/dist/services/settings/settings-sources.js.map +1 -1
- package/dist/services/settings/settings-ui-metadata.js +1 -1
- package/dist/services/settings/settings-ui-metadata.js.map +1 -1
- package/dist/services/settings/test-helpers/settings-consumer-inventory.d.ts +1 -1
- package/dist/services/settings/test-helpers/settings-consumer-inventory.d.ts.map +1 -1
- package/dist/services/settings/test-helpers/settings-consumer-inventory.js +1 -0
- package/dist/services/settings/test-helpers/settings-consumer-inventory.js.map +1 -1
- package/dist/services/subagents/execution-runner.d.ts.map +1 -1
- package/dist/services/subagents/execution-runner.js +16 -3
- package/dist/services/subagents/execution-runner.js.map +1 -1
- package/dist/services/subagents/nested-runner.d.ts.map +1 -1
- package/dist/services/subagents/nested-runner.js +3 -2
- package/dist/services/subagents/nested-runner.js.map +1 -1
- package/dist/services/tool-execution-ledger.d.ts +22 -0
- package/dist/services/tool-execution-ledger.d.ts.map +1 -1
- package/dist/services/tool-execution-ledger.js +40 -3
- package/dist/services/tool-execution-ledger.js.map +1 -1
- package/dist/services/workflow-evolution/cli.d.ts +2 -0
- package/dist/services/workflow-evolution/cli.d.ts.map +1 -0
- package/dist/services/workflow-evolution/cli.js +26 -0
- package/dist/services/workflow-evolution/cli.js.map +1 -0
- package/dist/services/workflow-evolution/demo.d.ts +18 -0
- package/dist/services/workflow-evolution/demo.d.ts.map +1 -0
- package/dist/services/workflow-evolution/demo.js +177 -0
- package/dist/services/workflow-evolution/demo.js.map +1 -0
- package/dist/services/workflow-evolution/experiment.d.ts +304 -0
- package/dist/services/workflow-evolution/experiment.d.ts.map +1 -0
- package/dist/services/workflow-evolution/experiment.js +251 -0
- package/dist/services/workflow-evolution/experiment.js.map +1 -0
- package/dist/services/workflow-evolution/ledger.d.ts +5 -0
- package/dist/services/workflow-evolution/ledger.d.ts.map +1 -0
- package/dist/services/workflow-evolution/ledger.js +57 -0
- package/dist/services/workflow-evolution/ledger.js.map +1 -0
- package/dist/skins/rail/status.d.ts.map +1 -1
- package/dist/skins/rail/status.js +21 -11
- package/dist/skins/rail/status.js.map +1 -1
- package/dist/tools/agent/goal-check.d.ts +23 -0
- package/dist/tools/agent/goal-check.d.ts.map +1 -0
- package/dist/tools/agent/goal-check.js +79 -0
- package/dist/tools/agent/goal-check.js.map +1 -0
- package/dist/tools/system/run-code/run-code-runtime.d.ts.map +1 -1
- package/dist/tools/system/run-code/run-code-runtime.js +3 -1
- package/dist/tools/system/run-code/run-code-runtime.js.map +1 -1
- package/dist/tools/tool-names.d.ts +1 -0
- package/dist/tools/tool-names.d.ts.map +1 -1
- package/dist/tools/tool-names.js +1 -0
- package/dist/tools/tool-names.js.map +1 -1
- package/dist/tools/types.d.ts +21 -0
- package/dist/tools/types.d.ts.map +1 -1
- package/dist/tools/types.js +7 -0
- package/dist/tools/types.js.map +1 -1
- package/dist/utils/conversation/conversation-event-handler.d.ts.map +1 -1
- package/dist/utils/conversation/conversation-event-handler.js +4 -0
- package/dist/utils/conversation/conversation-event-handler.js.map +1 -1
- package/dist/utils/output/text-snippet.js +25 -33
- package/dist/utils/output/text-snippet.js.map +1 -1
- package/dist/utils/value-suggestions.d.ts.map +1 -1
- package/dist/utils/value-suggestions.js +1 -0
- package/dist/utils/value-suggestions.js.map +1 -1
- package/package.json +1 -1
|
@@ -1,4 +1,8 @@
|
|
|
1
|
+
import { isOpenAICompaction, projectModelRequestHistory } from '../conversation/conversation-state-projector.js';
|
|
2
|
+
import { getCatalogModel } from '../../providers/model-catalog/catalog.js';
|
|
3
|
+
import { resolveRequestOutput } from './model-context-policy.js';
|
|
1
4
|
import { z } from 'zod';
|
|
5
|
+
import { enforceRequestInputLimit, RequestInputLimitError, ProviderContextOverflowError, isProviderContextOverflow, } from './request-input-limit.js';
|
|
2
6
|
import { createContinuationHandle, unwrapContinuationHandle, } from '../../contracts/continuation-handle.js';
|
|
3
7
|
import { createAgentStream } from '../agent-stream.js';
|
|
4
8
|
import { ASSISTANT_TEXT_PART_SEPARATOR } from '../../contracts/streamed-model-turn.js';
|
|
@@ -280,6 +284,7 @@ export class ApplicationRunLoop {
|
|
|
280
284
|
? options.providerId
|
|
281
285
|
: undefined,
|
|
282
286
|
requestPreparation: options.requestPreparation,
|
|
287
|
+
requestInputLimit: options.requestInputLimit,
|
|
283
288
|
disableChainingForAttempt: options.disableChainingForAttempt === true,
|
|
284
289
|
sessionId: options.sessionId,
|
|
285
290
|
turnId: options.turnId,
|
|
@@ -312,6 +317,7 @@ export class ApplicationRunLoop {
|
|
|
312
317
|
}
|
|
313
318
|
state.approvalDecision = 'approved';
|
|
314
319
|
state.approvalDecisionCallId = getInterruptionCallId(interruption);
|
|
320
|
+
state.approvalDecisionInterruption = interruption;
|
|
315
321
|
};
|
|
316
322
|
state.reject = (interruption, approvalOptions) => {
|
|
317
323
|
if (isRunBudgetInteraction(interruption)) {
|
|
@@ -320,6 +326,7 @@ export class ApplicationRunLoop {
|
|
|
320
326
|
}
|
|
321
327
|
state.approvalDecision = 'rejected';
|
|
322
328
|
state.approvalDecisionCallId = getInterruptionCallId(interruption);
|
|
329
|
+
state.approvalDecisionInterruption = interruption;
|
|
323
330
|
state.approvalMessage = approvalOptions?.message;
|
|
324
331
|
};
|
|
325
332
|
return this.#run(state, options);
|
|
@@ -387,6 +394,8 @@ export class ApplicationRunLoop {
|
|
|
387
394
|
// root closure for callers that do not provide one again.
|
|
388
395
|
if (options.requestPreparation)
|
|
389
396
|
state.requestPreparation = options.requestPreparation;
|
|
397
|
+
if (options.requestInputLimit)
|
|
398
|
+
state.requestInputLimit = options.requestInputLimit;
|
|
390
399
|
if (options.compactionHistory)
|
|
391
400
|
state.compactionHistory = options.compactionHistory;
|
|
392
401
|
if (options.disableChainingForAttempt === true) {
|
|
@@ -527,9 +536,10 @@ export class ApplicationRunLoop {
|
|
|
527
536
|
}
|
|
528
537
|
}
|
|
529
538
|
if (state.toolExecution.pendingApprovals.length > 0 && state.approvalDecision) {
|
|
530
|
-
state.toolExecution.resolveApproval(state.approvalDecisionCallId, state.approvalDecision, state.approvalMessage, state.approvals);
|
|
539
|
+
state.toolExecution.resolveApproval({ callId: state.approvalDecisionCallId, interruption: state.approvalDecisionInterruption }, state.approvalDecision, state.approvalMessage, state.approvals);
|
|
531
540
|
state.approvalDecision = undefined;
|
|
532
541
|
state.approvalDecisionCallId = undefined;
|
|
542
|
+
state.approvalDecisionInterruption = undefined;
|
|
533
543
|
state.approvalMessage = undefined;
|
|
534
544
|
await state.toolExecution.settle(this.#toolCallContext(state, stream, queue, toolContext));
|
|
535
545
|
stream.interruptions = state.toolExecution.pendingApprovals.map((item) => item.interruption);
|
|
@@ -577,24 +587,40 @@ export class ApplicationRunLoop {
|
|
|
577
587
|
const compactionHistory = compactionHistoryResult.kind === 'ready' ? compactionHistoryResult.history : undefined;
|
|
578
588
|
if (options.boundaryCompaction && compactionHistory && !boundaryDecision?.deferCompaction) {
|
|
579
589
|
const compactionStartedAt = Date.now();
|
|
590
|
+
let costsRecordedLive = false;
|
|
580
591
|
const compaction = await options.boundaryCompaction.compact({
|
|
581
592
|
history: compactionHistory,
|
|
593
|
+
instructions: state.agent.resolveInstructionsForRequest?.() ?? state.agent.instructions,
|
|
594
|
+
tools: toModelTools(state.agent.tools),
|
|
595
|
+
recordCostRecords: (records) => {
|
|
596
|
+
if (records.length) {
|
|
597
|
+
costsRecordedLive = true;
|
|
598
|
+
state.costRecords ??= [];
|
|
599
|
+
state.costRecords.push(...records);
|
|
600
|
+
for (const record of records)
|
|
601
|
+
queue.push({ type: 'cost_update', record });
|
|
602
|
+
this.#evaluateRunBudget(state, stream, queue);
|
|
603
|
+
}
|
|
604
|
+
return !state.pendingRunBudgetInteraction && !state.criticalWrapUpPending;
|
|
605
|
+
},
|
|
582
606
|
automaticCompactionsThisRun: state.automaticCompactionsThisRun ?? 0,
|
|
583
607
|
lastCompletedInputTokens: state.lastCompletedInputTokens,
|
|
584
608
|
signal: options.signal,
|
|
585
609
|
onStarted: (provider) => outputPush(stream, queue, { type: 'context_compaction_started', provider, strategy: 'local' }),
|
|
586
610
|
});
|
|
611
|
+
if (compaction.kind !== 'unchanged' && !costsRecordedLive && compaction.costRecords?.length) {
|
|
612
|
+
state.costRecords ??= [];
|
|
613
|
+
state.costRecords.push(...compaction.costRecords);
|
|
614
|
+
}
|
|
587
615
|
if (compaction.kind === 'compacted') {
|
|
616
|
+
state.inputUsageInvalidatedByCompaction = true;
|
|
617
|
+
state.lastCompletedInputTokens = undefined;
|
|
588
618
|
state.compactedDuringRun = true;
|
|
589
619
|
state.history.splice(0, state.history.length, ...compaction.history);
|
|
590
620
|
state.input.splice(0, state.input.length, ...normalizeApplicationInput(compaction.modelInput));
|
|
591
621
|
state.responseId = undefined;
|
|
592
622
|
state.responseProviderId = undefined;
|
|
593
623
|
state.usesDeltaHistory = false;
|
|
594
|
-
if (compaction.costRecords?.length) {
|
|
595
|
-
state.costRecords ??= [];
|
|
596
|
-
state.costRecords.push(...compaction.costRecords);
|
|
597
|
-
}
|
|
598
624
|
state.automaticCompactionsThisRun = (state.automaticCompactionsThisRun ?? 0) + 1;
|
|
599
625
|
outputPush(stream, queue, {
|
|
600
626
|
type: 'context_compaction_completed',
|
|
@@ -610,6 +636,8 @@ export class ApplicationRunLoop {
|
|
|
610
636
|
strategy: 'local',
|
|
611
637
|
durationMs: Math.max(0, Date.now() - compactionStartedAt),
|
|
612
638
|
});
|
|
639
|
+
if (compaction.error)
|
|
640
|
+
throw compaction.error;
|
|
613
641
|
}
|
|
614
642
|
else if (compaction.notice && compaction.notice !== state.compactionNotice) {
|
|
615
643
|
state.compactionNotice = compaction.notice;
|
|
@@ -650,12 +678,14 @@ export class ApplicationRunLoop {
|
|
|
650
678
|
let activeRequestId = '';
|
|
651
679
|
let activeRequest;
|
|
652
680
|
let pendingNativeReasoning;
|
|
681
|
+
let deferredNativeReasoning = [];
|
|
653
682
|
let criticalWrapUp = false;
|
|
654
683
|
while (true) {
|
|
655
684
|
streamedToolCalls = [];
|
|
656
685
|
completion = undefined;
|
|
657
686
|
sawToolCall = false;
|
|
658
687
|
pendingNativeReasoning = undefined;
|
|
688
|
+
deferredNativeReasoning = [];
|
|
659
689
|
// Stable process-unique request id, allocated immediately before dispatch
|
|
660
690
|
// so a cost record can be settled exactly once (success or failure).
|
|
661
691
|
activeRequestId = this.#nextRequestId();
|
|
@@ -688,6 +718,11 @@ export class ApplicationRunLoop {
|
|
|
688
718
|
else
|
|
689
719
|
options.signal?.addEventListener('abort', abortRequest, { once: true });
|
|
690
720
|
const requestInstructions = state.agent.resolveInstructionsForRequest?.() ?? state.agent.instructions;
|
|
721
|
+
// Same synchronous step as the instructions above, so the snapshot is
|
|
722
|
+
// exactly the state the model is shown in this request.
|
|
723
|
+
state.requestSnapshot = state.agent.resolveRequestSnapshot?.();
|
|
724
|
+
const requestCatalog = getCatalogModel(state.currentProviderId ?? 'openai', state.agent.model);
|
|
725
|
+
const effectiveOutput = resolveRequestOutput(requestCatalog, state.agent.modelSettings?.maxTokens);
|
|
691
726
|
const request = {
|
|
692
727
|
instructions: criticalWrapUp
|
|
693
728
|
? `${requestInstructions}\n\nBudget containment is terminal. Do not call tools. In this one final response, summarize what you completed, the evidence you have, and what remains.`
|
|
@@ -700,16 +735,14 @@ export class ApplicationRunLoop {
|
|
|
700
735
|
? { previousResponseId: state.responseId }
|
|
701
736
|
: {}),
|
|
702
737
|
...(disableChaining ? { disableChaining: true } : {}),
|
|
703
|
-
input: state.input,
|
|
738
|
+
input: projectModelRequestHistory(state.input),
|
|
704
739
|
tools: toModelTools(criticalWrapUp ? [] : state.agent.tools),
|
|
705
740
|
applicationTools: criticalWrapUp ? [] : state.agent.tools,
|
|
706
741
|
...(state.agent.modelSettings?.temperature !== undefined
|
|
707
742
|
? { temperature: state.agent.modelSettings.temperature }
|
|
708
743
|
: {}),
|
|
709
744
|
...(state.agent.modelSettings?.reasoning ? { reasoning: state.agent.modelSettings.reasoning } : {}),
|
|
710
|
-
...(
|
|
711
|
-
? { maxTokens: state.agent.modelSettings.maxTokens }
|
|
712
|
-
: {}),
|
|
745
|
+
...(effectiveOutput !== undefined ? { maxTokens: effectiveOutput } : {}),
|
|
713
746
|
...(state.agent.outputType !== undefined ? { outputType: state.agent.outputType } : {}),
|
|
714
747
|
...(state.agent.modelSettings?.codex ? { codex: state.agent.modelSettings.codex } : {}),
|
|
715
748
|
...(state.agent.modelSettings?.providerData
|
|
@@ -805,7 +838,11 @@ export class ApplicationRunLoop {
|
|
|
805
838
|
if (event.type === 'tool_call') {
|
|
806
839
|
toolArgumentRunaway?.observeToolCallCompleted();
|
|
807
840
|
generationGuard.observeToolCall(event.arguments);
|
|
808
|
-
|
|
841
|
+
// The authoritative completion may introduce a native
|
|
842
|
+
// replacement boundary before this call's reasoning.
|
|
843
|
+
if (pendingNativeReasoning)
|
|
844
|
+
deferredNativeReasoning.push(pendingNativeReasoning);
|
|
845
|
+
pendingNativeReasoning = undefined;
|
|
809
846
|
sawToolCall = true;
|
|
810
847
|
streamedToolCalls.push(event);
|
|
811
848
|
}
|
|
@@ -820,6 +857,31 @@ export class ApplicationRunLoop {
|
|
|
820
857
|
};
|
|
821
858
|
const dispatch = async () => {
|
|
822
859
|
state.requestPreparation?.prepare(request);
|
|
860
|
+
// A response ID can be established after a self-contained request.
|
|
861
|
+
// It does not make this run's full history a delta needing a snapshot.
|
|
862
|
+
const needsChainedSnapshot = Boolean(request.previousResponseId && state.usesDeltaHistory);
|
|
863
|
+
const fullContext = needsChainedSnapshot && state.compactionHistory
|
|
864
|
+
? mergeChainedCompactionHistory(state.compactionHistory, state.history)
|
|
865
|
+
: undefined;
|
|
866
|
+
const contextCatalog = getCatalogModel(state.currentProviderId ?? 'openai', state.agent.model);
|
|
867
|
+
enforceRequestInputLimit({
|
|
868
|
+
contextWindow: contextCatalog?.contextWindow,
|
|
869
|
+
maxOutputTokens: request.maxTokens,
|
|
870
|
+
limit: state.requestInputLimit
|
|
871
|
+
? state.requestInputLimit()
|
|
872
|
+
: state.agent.modelSettings?.maxRequestInputTokens,
|
|
873
|
+
history: fullContext?.kind === 'ready'
|
|
874
|
+
? fullContext.history
|
|
875
|
+
: needsChainedSnapshot
|
|
876
|
+
? [...(state.compactionHistory ?? []), ...request.input]
|
|
877
|
+
: request.input,
|
|
878
|
+
instructions: request.instructions ?? '',
|
|
879
|
+
tools: request.tools,
|
|
880
|
+
lastCompletedInputTokens: state.inputUsageInvalidatedByCompaction
|
|
881
|
+
? undefined
|
|
882
|
+
: state.lastCompletedInputTokens,
|
|
883
|
+
chainedContextKnown: !needsChainedSnapshot || fullContext?.kind === 'ready',
|
|
884
|
+
});
|
|
823
885
|
await consume();
|
|
824
886
|
};
|
|
825
887
|
try {
|
|
@@ -830,6 +892,33 @@ export class ApplicationRunLoop {
|
|
|
830
892
|
break;
|
|
831
893
|
}
|
|
832
894
|
catch (error) {
|
|
895
|
+
if (error instanceof RequestInputLimitError) {
|
|
896
|
+
this.#deps.logDiagnostic?.('Request input admission refused', {
|
|
897
|
+
code: error.code,
|
|
898
|
+
action: error.action,
|
|
899
|
+
reason: error.reason,
|
|
900
|
+
guardClass: 'admission',
|
|
901
|
+
setting: 'agent.maxRequestInputTokens',
|
|
902
|
+
executionScope: state.hookScope ?? 'root',
|
|
903
|
+
recovery: 'retained_work',
|
|
904
|
+
limit: error.limit,
|
|
905
|
+
estimatedTokens: error.estimatedTokens,
|
|
906
|
+
observedTokens: error.observedTokens,
|
|
907
|
+
capacity: error.capacity,
|
|
908
|
+
outputReserve: error.outputReserve,
|
|
909
|
+
estimationReserve: error.estimationReserve,
|
|
910
|
+
});
|
|
911
|
+
throw error;
|
|
912
|
+
}
|
|
913
|
+
if (isProviderContextOverflow(error)) {
|
|
914
|
+
this.#observeTerminalFailure(error, {
|
|
915
|
+
requestId: activeRequestId,
|
|
916
|
+
provider: state.currentProviderId,
|
|
917
|
+
model: state.agent.model,
|
|
918
|
+
tier: resolveServiceTier(request),
|
|
919
|
+
});
|
|
920
|
+
throw new ProviderContextOverflowError(error);
|
|
921
|
+
}
|
|
833
922
|
const recoverOversizedToolArgument = isOversizedToolArgumentTrip(error) &&
|
|
834
923
|
(state.oversizedToolArgumentRecoveries ?? 0) < MAX_OVERSIZED_TOOL_ARGUMENT_RECOVERIES &&
|
|
835
924
|
!options.signal?.aborted;
|
|
@@ -946,6 +1035,9 @@ export class ApplicationRunLoop {
|
|
|
946
1035
|
if (criticalWrapUp) {
|
|
947
1036
|
return finish(stream, state, queue);
|
|
948
1037
|
}
|
|
1038
|
+
for (const reasoning of deferredNativeReasoning)
|
|
1039
|
+
commitPendingNativeReasoning(state, stream, queue, reasoning);
|
|
1040
|
+
pendingNativeReasoning = commitPendingNativeReasoning(state, stream, queue, pendingNativeReasoning);
|
|
949
1041
|
await this.#dispatchToolCalls(state, stream, queue, streamedToolCalls, toolContext);
|
|
950
1042
|
if (state.toolExecution.terminateAfterExecution)
|
|
951
1043
|
return finish(stream, state, queue);
|
|
@@ -989,6 +1081,7 @@ export class ApplicationRunLoop {
|
|
|
989
1081
|
if (normalizedCompletionUsage) {
|
|
990
1082
|
if (normalizedCompletionUsage.prompt_tokens !== undefined) {
|
|
991
1083
|
state.lastCompletedInputTokens = normalizedCompletionUsage.prompt_tokens;
|
|
1084
|
+
state.inputUsageInvalidatedByCompaction = false;
|
|
992
1085
|
}
|
|
993
1086
|
const accumulated = addTokenUsage(normalizeModelUsage(state.usage), normalizedCompletionUsage);
|
|
994
1087
|
state.usage = {
|
|
@@ -1047,32 +1140,33 @@ export class ApplicationRunLoop {
|
|
|
1047
1140
|
// completion rather than as separate stream events. Their reasoning may
|
|
1048
1141
|
// likewise be terminal-only, so associate it before replaying calls.
|
|
1049
1142
|
const toolCalls = [...streamedToolCalls];
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1143
|
+
const hasTerminalReasoning = finalCompletion.output.some((item) => item.type === 'reasoning' && appendNativeReasoning(undefined, item) !== undefined);
|
|
1144
|
+
if (hasTerminalReasoning) {
|
|
1145
|
+
// Terminal output supplies native ordering and authoritative metadata.
|
|
1146
|
+
// Streamed fragments have already been displayed, but are not history.
|
|
1147
|
+
pendingNativeReasoning = undefined;
|
|
1148
|
+
}
|
|
1149
|
+
else {
|
|
1150
|
+
for (const reasoning of deferredNativeReasoning)
|
|
1151
|
+
commitPendingNativeReasoning(state, stream, queue, reasoning);
|
|
1152
|
+
}
|
|
1153
|
+
for (const item of finalCompletion.output) {
|
|
1154
|
+
if (item.type === 'reasoning') {
|
|
1155
|
+
// Each terminal native item is independently replayable; encrypted
|
|
1156
|
+
// reasoning cannot be concatenated or overwritten by its sibling.
|
|
1157
|
+
pendingNativeReasoning = commitPendingNativeReasoning(state, stream, queue, pendingNativeReasoning);
|
|
1158
|
+
pendingNativeReasoning = appendNativeReasoning(undefined, item);
|
|
1159
|
+
continue;
|
|
1054
1160
|
}
|
|
1055
|
-
|
|
1056
|
-
if (item.type !== 'tool_call')
|
|
1057
|
-
continue;
|
|
1161
|
+
if (item.type === 'tool_call') {
|
|
1058
1162
|
pendingNativeReasoning = commitPendingNativeReasoning(state, stream, queue, pendingNativeReasoning);
|
|
1059
|
-
sawToolCall
|
|
1060
|
-
|
|
1163
|
+
if (!sawToolCall)
|
|
1164
|
+
toolCalls.push(item);
|
|
1165
|
+
continue;
|
|
1061
1166
|
}
|
|
1062
|
-
}
|
|
1063
|
-
// A native reasoning item belongs to the completed assistant turn even
|
|
1064
|
-
// when no tool call follows it. Commit it before assistant text so both
|
|
1065
|
-
// stateless continuation and persisted canonical history retain the
|
|
1066
|
-
// provider-specific metadata exactly once.
|
|
1067
|
-
pendingNativeReasoning = commitPendingNativeReasoning(state, stream, queue, pendingNativeReasoning);
|
|
1068
|
-
// Provider-native completion items (notably OpenAI compaction items)
|
|
1069
|
-
// must stay in the live provider history. The session layer later
|
|
1070
|
-
// applies compaction's replacement rule; keeping the item here also
|
|
1071
|
-
// makes it available to an in-flight tool continuation before that
|
|
1072
|
-
// terminal history commit occurs.
|
|
1073
|
-
for (const item of finalCompletion.output) {
|
|
1074
1167
|
if (item.type !== 'provider_opaque')
|
|
1075
1168
|
continue;
|
|
1169
|
+
pendingNativeReasoning = commitPendingNativeReasoning(state, stream, queue, pendingNativeReasoning);
|
|
1076
1170
|
const historyItem = {
|
|
1077
1171
|
...item.item,
|
|
1078
1172
|
providerOpaque: {
|
|
@@ -1082,8 +1176,16 @@ export class ApplicationRunLoop {
|
|
|
1082
1176
|
};
|
|
1083
1177
|
state.history.push(historyItem);
|
|
1084
1178
|
state.input.push(item);
|
|
1179
|
+
if (isOpenAICompaction(item)) {
|
|
1180
|
+
// Completion usage describes the request before native replacement.
|
|
1181
|
+
// Retain billed usage/costs; invalidate only the next admission hint.
|
|
1182
|
+
state.lastCompletedInputTokens = undefined;
|
|
1183
|
+
state.inputUsageInvalidatedByCompaction = true;
|
|
1184
|
+
}
|
|
1085
1185
|
outputPush(stream, queue, { type: 'item', item });
|
|
1086
1186
|
}
|
|
1187
|
+
sawToolCall = toolCalls.length > 0;
|
|
1188
|
+
pendingNativeReasoning = commitPendingNativeReasoning(state, stream, queue, pendingNativeReasoning);
|
|
1087
1189
|
const assistantText = finalCompletion.output
|
|
1088
1190
|
.filter((item) => item.type === 'message')
|
|
1089
1191
|
.flatMap((item) => item.content)
|
|
@@ -1129,6 +1231,21 @@ export class ApplicationRunLoop {
|
|
|
1129
1231
|
return finish(stream, state, queue);
|
|
1130
1232
|
}
|
|
1131
1233
|
if (!sawToolCall) {
|
|
1234
|
+
// The normal stop seam. A stop policy may keep the same run going; the
|
|
1235
|
+
// reminder is admitted at the next request boundary, where pending
|
|
1236
|
+
// budget evidence pauses first and turn accounting applies as usual.
|
|
1237
|
+
const stopDecision = options.onNormalStop && !options.signal?.aborted && !state.criticalWrapUpPending
|
|
1238
|
+
? options.onNormalStop(state.history, state.agent)
|
|
1239
|
+
: undefined;
|
|
1240
|
+
if (stopDecision) {
|
|
1241
|
+
this.#deps.logDiagnostic?.('Normal stop policy decided', { action: stopDecision.action, turnCount: state.turnCount, ...stopDecision.diagnostics }, { severity: 'debug', eventType: 'run_loop.normal_stop_policy' });
|
|
1242
|
+
}
|
|
1243
|
+
if (stopDecision?.action === 'continue') {
|
|
1244
|
+
this.#queuePendingSystemNotice(stopDecision.reminder);
|
|
1245
|
+
continue;
|
|
1246
|
+
}
|
|
1247
|
+
if (stopDecision?.terminalCause)
|
|
1248
|
+
state.terminalCause = stopDecision.terminalCause;
|
|
1132
1249
|
// Evidence discovered when a response has already completed needs no
|
|
1133
1250
|
// human boundary: there is no later request or tool to block.
|
|
1134
1251
|
state.pendingRunBudgetInteraction = undefined;
|
|
@@ -1151,6 +1268,7 @@ export class ApplicationRunLoop {
|
|
|
1151
1268
|
sessionId: state.sessionId,
|
|
1152
1269
|
turnId: state.turnId,
|
|
1153
1270
|
hookScope: state.hookScope,
|
|
1271
|
+
...(state.requestSnapshot ? { requestSnapshot: state.requestSnapshot } : {}),
|
|
1154
1272
|
onCall: (event) => {
|
|
1155
1273
|
const callItem = {
|
|
1156
1274
|
type: event.toolType === 'custom' ? 'custom_tool_call' : 'function_call',
|
|
@@ -1248,8 +1366,9 @@ export class ApplicationRunLoop {
|
|
|
1248
1366
|
}
|
|
1249
1367
|
if (!state.wrapUpOnCriticalRunBudget &&
|
|
1250
1368
|
!state.pendingRunBudgetInteraction &&
|
|
1251
|
-
state.runBudgetEscalation
|
|
1252
|
-
|
|
1369
|
+
(state.runBudgetEscalation === 'contain'
|
|
1370
|
+
? event.type === 'budget_stage' && event.stage === 'critical'
|
|
1371
|
+
: state.runBudgetEscalation !== 'warn' && this.#requiresHumanBudgetDecision(event))) {
|
|
1253
1372
|
state.pendingRunBudgetInteraction = { type: 'run_budget_interaction', event };
|
|
1254
1373
|
state.runBudgetGrantConsumed = false;
|
|
1255
1374
|
}
|
|
@@ -1439,6 +1558,28 @@ function normalizeHistory(input) {
|
|
|
1439
1558
|
}
|
|
1440
1559
|
function mergeChainedCompactionHistory(sessionHistory, deltaHistory) {
|
|
1441
1560
|
const firstDeltaItem = deltaHistory[0];
|
|
1561
|
+
const normalizedDelta = normalizeApplicationInput(deltaHistory);
|
|
1562
|
+
if (normalizedDelta[0]?.type === 'tool_result') {
|
|
1563
|
+
// A tool-only continuation needs a complete snapshot with still-open
|
|
1564
|
+
// producing calls. Normalize supported legacy/custom forms for comparison,
|
|
1565
|
+
// retain original provider items, and validate every later call/receipt.
|
|
1566
|
+
const pending = new Map();
|
|
1567
|
+
const seenCalls = new Set();
|
|
1568
|
+
for (const item of [...normalizeApplicationInput(sessionHistory), ...normalizedDelta]) {
|
|
1569
|
+
if (item.type === 'tool_call') {
|
|
1570
|
+
if (!item.id || seenCalls.has(item.id))
|
|
1571
|
+
return { kind: 'skipped', reason: 'user_mismatch' };
|
|
1572
|
+
seenCalls.add(item.id);
|
|
1573
|
+
pending.set(item.id, item.toolType ?? 'function');
|
|
1574
|
+
}
|
|
1575
|
+
else if (item.type === 'tool_result') {
|
|
1576
|
+
if (!item.id || pending.get(item.id) !== (item.toolType ?? 'function'))
|
|
1577
|
+
return { kind: 'skipped', reason: 'user_mismatch' };
|
|
1578
|
+
pending.delete(item.id);
|
|
1579
|
+
}
|
|
1580
|
+
}
|
|
1581
|
+
return { kind: 'ready', history: [...sessionHistory, ...deltaHistory] };
|
|
1582
|
+
}
|
|
1442
1583
|
if (!firstDeltaItem || firstDeltaItem.type !== 'message' || firstDeltaItem.role !== 'user') {
|
|
1443
1584
|
return { kind: 'skipped', reason: 'user_mismatch' };
|
|
1444
1585
|
}
|