salmon-loop 0.2.3 → 0.2.16
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/dist/cli/argv/headless-detection.js +27 -0
- package/dist/cli/chat-flow.js +11 -0
- package/dist/cli/chat.js +161 -24
- package/dist/cli/commands/chat.js +30 -24
- package/dist/cli/commands/context.js +15 -3
- package/dist/cli/commands/flow-mode.js +63 -0
- package/dist/cli/commands/help-format.js +12 -0
- package/dist/cli/commands/registry.js +6 -7
- package/dist/cli/commands/run/benchmark-artifacts.js +41 -0
- package/dist/cli/commands/run/config-resolution.js +30 -24
- package/dist/cli/commands/run/early-errors.js +23 -0
- package/dist/cli/commands/run/handler.js +131 -44
- package/dist/cli/commands/run/headless-error-writer.js +8 -0
- package/dist/cli/commands/run/loop-params.js +3 -0
- package/dist/cli/commands/run/mode.js +2 -5
- package/dist/cli/commands/run/parse-options.js +18 -2
- package/dist/cli/commands/run/persist-session.js +10 -1
- package/dist/cli/commands/run/preflight.js +10 -0
- package/dist/cli/commands/run/reporter-factory.js +4 -0
- package/dist/cli/commands/run/runtime-llm.js +38 -11
- package/dist/cli/commands/run/runtime-options.js +2 -2
- package/dist/cli/commands/run/validate-options.js +0 -5
- package/dist/cli/commands/run/verbose.js +2 -7
- package/dist/cli/commands/serve.js +117 -90
- package/dist/cli/commands/tool-names.js +78 -78
- package/dist/cli/headless/anthropic-stream-normalized-encoder.js +6 -1
- package/dist/cli/headless/json-protocol.js +37 -0
- package/dist/cli/headless/native-stream-normalized-encoder.js +6 -1
- package/dist/cli/headless/protocol-metadata.js +22 -0
- package/dist/cli/headless/stream-json-protocol.js +34 -1
- package/dist/cli/index.js +6 -4
- package/dist/cli/locales/en.js +32 -6
- package/dist/cli/program-bootstrap.js +14 -4
- package/dist/cli/program-commands.js +9 -1
- package/dist/cli/program-options.js +1 -0
- package/dist/cli/reporters/anthropic-stream.js +7 -1
- package/dist/cli/reporters/json.js +4 -0
- package/dist/cli/reporters/stream-json.js +17 -2
- package/dist/cli/run-cli.js +5 -3
- package/dist/cli/slash/runtime.js +30 -15
- package/dist/cli/ui/components/CommandInput.js +7 -3
- package/dist/cli/ui/components/CommandSuggestionList.js +1 -1
- package/dist/cli/utils/command-option-source.js +13 -0
- package/dist/cli/utils/output-format.js +6 -0
- package/dist/cli/utils/resolve-cli-config.js +98 -0
- package/dist/cli/utils/verbose-level.js +8 -0
- package/dist/cli/utils/verify-resolver.js +8 -4
- package/dist/cli/utils/worktree-prepare-resolver.js +7 -3
- package/dist/core/adapters/fs/file-adapter.js +6 -0
- package/dist/core/adapters/fs/filesystem.js +2 -1
- package/dist/core/adapters/git/git-adapter.js +78 -1
- package/dist/core/benchmark/patch-artifact.js +124 -0
- package/dist/core/benchmark/swe-bench.js +25 -0
- package/dist/core/config/load.js +39 -18
- package/dist/core/config/merge.js +27 -0
- package/dist/core/config/paths.js +24 -5
- package/dist/core/config/resolve-llm.js +12 -0
- package/dist/core/config/resolve.js +7 -5
- package/dist/core/config/resolvers/server.js +0 -6
- package/dist/core/config/validate.js +94 -21
- package/dist/core/context/gatherers/metadata-gatherer.js +1 -0
- package/dist/core/context/gatherers/ripgrep-gatherer.js +84 -2
- package/dist/core/context/keywords.js +18 -4
- package/dist/core/context/service-deps.js +2 -2
- package/dist/core/context/service.js +8 -0
- package/dist/core/context/steps/context-gather.js +38 -0
- package/dist/core/context/summarization/summarizer.js +55 -12
- package/dist/core/context/targeting/target-resolver.js +4 -4
- package/dist/core/extensions/index.js +23 -5
- package/dist/core/extensions/paths.js +31 -0
- package/dist/core/extensions/schemas.js +8 -5
- package/dist/core/facades/cli-chat.js +6 -2
- package/dist/core/facades/cli-command-chat.js +2 -1
- package/dist/core/facades/cli-command-tool-names.js +2 -0
- package/dist/core/facades/cli-context.js +1 -0
- package/dist/core/facades/cli-observability.js +1 -1
- package/dist/core/facades/cli-run-handler.js +4 -2
- package/dist/core/facades/cli-run-persist-session.js +1 -0
- package/dist/core/facades/cli-serve.js +2 -4
- package/dist/core/facades/cli-utils-worktree.js +1 -1
- package/dist/core/failure/diagnostics.js +53 -1
- package/dist/core/grizzco/dsl/llm-strategy.js +4 -1
- package/dist/core/grizzco/engine/outcome/loop-result-mapper.js +67 -9
- package/dist/core/grizzco/engine/pipeline/pipeline.js +6 -2
- package/dist/core/grizzco/engine/transaction/attempt-failure.js +90 -15
- package/dist/core/grizzco/engine/transaction/report-mapper.js +17 -3
- package/dist/core/grizzco/engine/transaction/transaction-runner.js +173 -7
- package/dist/core/grizzco/flows/AutopilotFlow.js +18 -0
- package/dist/core/grizzco/flows/flow-dispatch.js +11 -0
- package/dist/core/grizzco/steps/answer.js +13 -14
- package/dist/core/grizzco/steps/autopilot.js +396 -0
- package/dist/core/grizzco/steps/cache-sharing.js +29 -0
- package/dist/core/grizzco/steps/explore.js +37 -21
- package/dist/core/grizzco/steps/generateReview.js +2 -5
- package/dist/core/grizzco/steps/patch/apply-check.js +10 -0
- package/dist/core/grizzco/steps/patch/diff-normalization.js +70 -0
- package/dist/core/grizzco/steps/patch/diff-salvage.js +46 -0
- package/dist/core/grizzco/steps/patch/prompt-input.js +42 -0
- package/dist/core/grizzco/steps/patch.js +105 -146
- package/dist/core/grizzco/steps/plan.js +101 -25
- package/dist/core/grizzco/steps/preflight.js +5 -3
- package/dist/core/grizzco/steps/request-assembly.js +78 -0
- package/dist/core/grizzco/steps/research.js +39 -36
- package/dist/core/grizzco/steps/tool-runtime.js +47 -0
- package/dist/core/grizzco/steps/verify-shared.js +23 -0
- package/dist/core/grizzco/steps/verify.js +13 -21
- package/dist/core/intent/chat-intent.js +0 -4
- package/dist/core/llm/ai-sdk/chat-executor.js +2 -0
- package/dist/core/llm/ai-sdk/high-level-phase-specs.js +63 -0
- package/dist/core/llm/ai-sdk/message-mapper.js +40 -10
- package/dist/core/llm/ai-sdk/provider-factory.js +14 -0
- package/dist/core/llm/ai-sdk/request-params.js +74 -1
- package/dist/core/llm/ai-sdk/result-mapper.js +16 -0
- package/dist/core/llm/ai-sdk.js +112 -27
- package/dist/core/llm/capabilities.js +12 -0
- package/dist/core/llm/contracts/repair.js +36 -30
- package/dist/core/llm/errors.js +83 -2
- package/dist/core/llm/message-composition.js +7 -22
- package/dist/core/llm/phase-router.js +29 -10
- package/dist/core/llm/redact.js +28 -3
- package/dist/core/llm/registry.js +2 -0
- package/dist/core/llm/request-augmentation.js +55 -0
- package/dist/core/llm/request-envelope.js +334 -0
- package/dist/core/llm/shared-request-assembly.js +35 -0
- package/dist/core/llm/stream-utils.js +13 -4
- package/dist/core/llm/utils.js +18 -29
- package/dist/core/memory/relevant-retrieval.js +144 -0
- package/dist/core/observability/logger.js +11 -2
- package/dist/core/patch/diff.js +1 -0
- package/dist/core/prompts/registry.js +39 -2
- package/dist/core/prompts/runtime.js +50 -12
- package/dist/core/prompts/templates/phases/patch_user.hbs +2 -5
- package/dist/core/prompts/templates/phases/research_user.hbs +11 -0
- package/dist/core/prompts/templates/phases/review_user.hbs +3 -0
- package/dist/core/prompts/templates/system/answer_system.hbs +5 -0
- package/dist/core/prompts/templates/system/autopilot_system.hbs +11 -0
- package/dist/core/prompts/templates/system/explore_system.hbs +14 -23
- package/dist/core/prompts/templates/system/main_system.hbs +4 -16
- package/dist/core/prompts/templates/system/patch_system.hbs +39 -8
- package/dist/core/prompts/templates/system/plan_system.hbs +86 -1
- package/dist/core/prompts/templates/system/research_system.hbs +2 -0
- package/dist/core/protocols/a2a/agent-card.js +3 -2
- package/dist/core/protocols/a2a/sdk/executor.js +8 -6
- package/dist/core/protocols/a2a/sdk/server.js +0 -1
- package/dist/core/protocols/acp/formal-agent.js +221 -55
- package/dist/core/protocols/acp/handlers.js +5 -1
- package/dist/core/protocols/acp/permission-provider.js +21 -1
- package/dist/core/protocols/shared/execution-request.js +24 -0
- package/dist/core/protocols/shared/flow-mode-mapping.js +23 -0
- package/dist/core/public-capabilities/flow-mode-metadata.js +39 -0
- package/dist/core/public-capabilities/projections.js +29 -0
- package/dist/core/public-capabilities/registry.js +26 -0
- package/dist/core/public-capabilities/types.js +2 -0
- package/dist/core/runtime/agent-server-runtime.js +47 -43
- package/dist/core/runtime/execution-profile.js +67 -0
- package/dist/core/session/artifact-state.js +160 -0
- package/dist/core/session/compaction/index.js +183 -0
- package/dist/core/session/compaction/microcompact.js +78 -0
- package/dist/core/session/compaction/tracking.js +48 -0
- package/dist/core/session/compaction/types.js +11 -0
- package/dist/core/session/compression.js +12 -4
- package/dist/core/session/manager.js +247 -10
- package/dist/core/session/pruning-strategy.js +55 -9
- package/dist/core/session/replacement-preview-provider.js +24 -0
- package/dist/core/session/replacement-state.js +131 -0
- package/dist/core/session/resume-repair/pipeline.js +79 -0
- package/dist/core/session/resume-repair/stages/load-raw-archive-state.js +40 -0
- package/dist/core/session/resume-repair/stages/reattach-runtime-state.js +8 -0
- package/dist/core/session/resume-repair/stages/recover-orphaned-branches.js +10 -0
- package/dist/core/session/resume-repair/stages/relink-boundary-and-tail.js +36 -0
- package/dist/core/session/resume-repair/stages/replay-startup-hooks.js +23 -0
- package/dist/core/session/resume-repair/stages/rescue-stale-metadata.js +17 -0
- package/dist/core/session/resume-repair/types.js +2 -0
- package/dist/core/session/summary-sync.js +164 -13
- package/dist/core/session/token-tracker.js +6 -0
- package/dist/core/skills/audit.js +34 -0
- package/dist/core/skills/bridge.js +84 -7
- package/dist/core/skills/discovery.js +94 -0
- package/dist/core/skills/feature-flags.js +52 -0
- package/dist/core/skills/index.js +1 -1
- package/dist/core/skills/loader.js +195 -20
- package/dist/core/skills/parser.js +296 -24
- package/dist/core/skills/permissions.js +117 -0
- package/dist/core/skills/runtime/MicroTaskRunner.js +10 -4
- package/dist/core/skills/runtime/SkillRunner.js +240 -61
- package/dist/core/strata/layers/shadow-driver/shadow-driver.js +37 -7
- package/dist/core/strata/layers/worktree.js +70 -13
- package/dist/core/strata/runtime/synchronizer.js +29 -2
- package/dist/core/streaming/stream-assembler.js +75 -31
- package/dist/core/sub-agent/context-snapshot.js +156 -0
- package/dist/core/sub-agent/core/loop.js +1 -1
- package/dist/core/sub-agent/core/manager.js +119 -20
- package/dist/core/sub-agent/dispatch-policy.js +29 -0
- package/dist/core/sub-agent/prefix-consistency.js +48 -0
- package/dist/core/sub-agent/registry-defaults.js +4 -0
- package/dist/core/sub-agent/tools/task-spawn.js +79 -2
- package/dist/core/sub-agent/types.js +134 -5
- package/dist/core/tools/audit.js +13 -4
- package/dist/core/tools/builtin/ast-grep.js +1 -1
- package/dist/core/tools/builtin/ast.js +1 -1
- package/dist/core/tools/builtin/benchmark.js +360 -0
- package/dist/core/tools/builtin/code-search/backends/rg.js +2 -1
- package/dist/core/tools/builtin/code-search/executor.js +6 -1
- package/dist/core/tools/builtin/code-search/spec.js +26 -2
- package/dist/core/tools/builtin/fs.js +256 -23
- package/dist/core/tools/builtin/git.js +2 -2
- package/dist/core/tools/builtin/index.js +51 -2
- package/dist/core/tools/builtin/interaction.js +8 -1
- package/dist/core/tools/builtin/plan.js +37 -15
- package/dist/core/tools/builtin/shell.js +1 -1
- package/dist/core/tools/loader.js +39 -16
- package/dist/core/tools/mapper.js +17 -3
- package/dist/core/tools/parallel/scheduler.js +35 -4
- package/dist/core/tools/permissions/permission-rules.js +5 -10
- package/dist/core/tools/policy.js +6 -1
- package/dist/core/tools/recoverable-tool-errors.js +10 -0
- package/dist/core/tools/router.js +24 -6
- package/dist/core/tools/session.js +458 -48
- package/dist/core/tools/tool-visibility.js +62 -0
- package/dist/core/tools/types.js +9 -1
- package/dist/core/types/execution.js +4 -0
- package/dist/core/types/flow-mode.js +8 -0
- package/dist/core/utils/path.js +52 -0
- package/dist/core/verification/runner.js +4 -1
- package/dist/interfaces/cli/task-runner.js +4 -3
- package/dist/languages/typescript/index.js +4 -1
- package/dist/locales/en.js +87 -2
- package/dist/utils/eol.js +1 -1
- package/package.json +15 -8
- package/scripts/fix-es-abstract-compat.js +77 -0
- package/dist/core/runtime/fastify-server-bundle.js +0 -26
- package/dist/core/runtime/sidecar-fastify-plugin.js +0 -35
- package/dist/core/runtime/sidecar-paths.js +0 -47
- package/dist/core/runtime/sidecar-route-catalog.js +0 -103
|
@@ -3,8 +3,35 @@ import { getBudgetRunSummary } from '../../../context/budget/integration.js';
|
|
|
3
3
|
import { getAuthorizationDecisionsFromAuditTrail } from '../../../observability/authorization-decisions.js';
|
|
4
4
|
import { buildFailureEnvelope } from '../../../observability/error-envelope.js';
|
|
5
5
|
import { getTokenUsageFromAuditTrail } from '../../../observability/token-usage.js';
|
|
6
|
+
import { resolveExecutionProfile } from '../../../runtime/execution-profile.js';
|
|
6
7
|
import { ErrorType, Phase } from '../../../types/runtime.js';
|
|
8
|
+
const ROOT_CAUSE_CODES = [
|
|
9
|
+
'LLM_RATE_LIMITED',
|
|
10
|
+
'LLM_UPSTREAM_5XX',
|
|
11
|
+
'LLM_NETWORK_UNREACHABLE',
|
|
12
|
+
'LLM_REQUEST_TIMEOUT',
|
|
13
|
+
'PLAN_OUTPUT_NOT_JSON',
|
|
14
|
+
'PLAN_SCHEMA_INVALID',
|
|
15
|
+
'STDOUT_CONTRACT_VIOLATION',
|
|
16
|
+
'RESOURCE_LIMIT_CONFIRMED',
|
|
17
|
+
];
|
|
18
|
+
function toRootCauseCode(code) {
|
|
19
|
+
if (typeof code !== 'string')
|
|
20
|
+
return undefined;
|
|
21
|
+
return ROOT_CAUSE_CODES.includes(code)
|
|
22
|
+
? code
|
|
23
|
+
: undefined;
|
|
24
|
+
}
|
|
7
25
|
export function buildLoopResultFromTransaction({ executionReport, flowMode, options, telemetry, auditPath, }) {
|
|
26
|
+
const profile = resolveExecutionProfile(flowMode);
|
|
27
|
+
const rootCause = toRootCauseCode(executionReport.lastErrorCode);
|
|
28
|
+
const terminalReason = executionReport.retryExhausted
|
|
29
|
+
? 'RETRY_BUDGET_EXHAUSTED'
|
|
30
|
+
: executionReport.terminalReasonCode === 'AWAITING_INPUT'
|
|
31
|
+
? undefined
|
|
32
|
+
: executionReport.success
|
|
33
|
+
? undefined
|
|
34
|
+
: 'NON_RETRYABLE_FAILURE';
|
|
8
35
|
const ctx = executionReport.lastContext ??
|
|
9
36
|
executionReport.flowReport.data;
|
|
10
37
|
const contextHash = (() => {
|
|
@@ -19,11 +46,35 @@ export function buildLoopResultFromTransaction({ executionReport, flowMode, opti
|
|
|
19
46
|
const verifyArtifact = ctx && typeof ctx === 'object' && 'verifyArtifact' in ctx
|
|
20
47
|
? ctx.verifyArtifact
|
|
21
48
|
: executionReport.lastVerifyArtifact;
|
|
22
|
-
const
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
:
|
|
26
|
-
|
|
49
|
+
const artifactHints = (() => {
|
|
50
|
+
const hints = {
|
|
51
|
+
verifyArtifact,
|
|
52
|
+
subAgentPatchArtifacts: executionReport.lastSubAgentPatchArtifacts?.length
|
|
53
|
+
? executionReport.lastSubAgentPatchArtifacts
|
|
54
|
+
: undefined,
|
|
55
|
+
subAgentAuditArtifacts: executionReport.lastSubAgentAuditArtifacts?.length
|
|
56
|
+
? executionReport.lastSubAgentAuditArtifacts
|
|
57
|
+
: undefined,
|
|
58
|
+
recentReadArtifacts: executionReport.lastRecentReadArtifacts?.length
|
|
59
|
+
? executionReport.lastRecentReadArtifacts
|
|
60
|
+
: undefined,
|
|
61
|
+
toolResultPreviewArtifacts: executionReport.lastToolResultPreviewArtifacts?.length
|
|
62
|
+
? executionReport.lastToolResultPreviewArtifacts
|
|
63
|
+
: undefined,
|
|
64
|
+
};
|
|
65
|
+
if (!hints.verifyArtifact &&
|
|
66
|
+
!hints.subAgentPatchArtifacts &&
|
|
67
|
+
!hints.subAgentAuditArtifacts &&
|
|
68
|
+
!hints.recentReadArtifacts &&
|
|
69
|
+
!hints.toolResultPreviewArtifacts) {
|
|
70
|
+
return undefined;
|
|
71
|
+
}
|
|
72
|
+
return hints;
|
|
73
|
+
})();
|
|
74
|
+
const assistantMessage = ((flowMode === 'answer' || profile.driver === 'agent') &&
|
|
75
|
+
ctx?.report?.summary?.trim?.()
|
|
76
|
+
? String(ctx.report.summary).trim()
|
|
77
|
+
: undefined) ?? undefined;
|
|
27
78
|
const finalPatch = ctx && typeof ctx === 'object' && 'diff' in ctx ? ctx.diff : undefined;
|
|
28
79
|
const changedFiles = ctx && typeof ctx === 'object' && 'changedFiles' in ctx ? ctx.changedFiles : undefined;
|
|
29
80
|
const authorizationDecisions = (() => {
|
|
@@ -36,14 +87,12 @@ export function buildLoopResultFromTransaction({ executionReport, flowMode, opti
|
|
|
36
87
|
const attempts = executionReport.attempts;
|
|
37
88
|
const usage = getTokenUsageFromAuditTrail() ?? undefined;
|
|
38
89
|
const budgetSummary = getBudgetRunSummary() ?? undefined;
|
|
39
|
-
if (options.dryRun ||
|
|
40
|
-
flowMode === 'review' ||
|
|
41
|
-
flowMode === 'research' ||
|
|
42
|
-
flowMode === 'answer') {
|
|
90
|
+
if (options.dryRun || profile.readOnly) {
|
|
43
91
|
return {
|
|
44
92
|
success: true,
|
|
45
93
|
reason: text.loop.operationCompleted,
|
|
46
94
|
reasonCode: options.dryRun ? 'DRY_RUN' : 'SUCCESS',
|
|
95
|
+
terminalReason,
|
|
47
96
|
attempts,
|
|
48
97
|
contextHash,
|
|
49
98
|
logs: telemetry.getLogs(),
|
|
@@ -55,6 +104,7 @@ export function buildLoopResultFromTransaction({ executionReport, flowMode, opti
|
|
|
55
104
|
assistantMessage,
|
|
56
105
|
auditPath,
|
|
57
106
|
verifyArtifact,
|
|
107
|
+
artifactHints,
|
|
58
108
|
authorizationSummary: executionReport.authorizationSummary || undefined,
|
|
59
109
|
strategyName: executionReport.flowReport.strategyName ?? flowMode,
|
|
60
110
|
fsMode: executionReport.flowReport.fsMode ?? flowMode,
|
|
@@ -65,6 +115,7 @@ export function buildLoopResultFromTransaction({ executionReport, flowMode, opti
|
|
|
65
115
|
success: true,
|
|
66
116
|
reason: text.loop.operationCompleted,
|
|
67
117
|
reasonCode: 'SUCCESS',
|
|
118
|
+
terminalReason,
|
|
68
119
|
attempts,
|
|
69
120
|
contextHash,
|
|
70
121
|
logs: telemetry.getLogs(),
|
|
@@ -76,6 +127,7 @@ export function buildLoopResultFromTransaction({ executionReport, flowMode, opti
|
|
|
76
127
|
assistantMessage,
|
|
77
128
|
auditPath,
|
|
78
129
|
verifyArtifact,
|
|
130
|
+
artifactHints,
|
|
79
131
|
authorizationSummary: executionReport.authorizationSummary || undefined,
|
|
80
132
|
strategyName: executionReport.flowReport.strategyName ?? flowMode,
|
|
81
133
|
fsMode: executionReport.flowReport.fsMode ?? flowMode,
|
|
@@ -107,6 +159,8 @@ export function buildLoopResultFromTransaction({ executionReport, flowMode, opti
|
|
|
107
159
|
success: false,
|
|
108
160
|
reason: safeHint,
|
|
109
161
|
reasonCode,
|
|
162
|
+
terminalReason,
|
|
163
|
+
rootCause,
|
|
110
164
|
diagnosticCode: executionReport.terminalDiagnosticCode ?? reasonCode,
|
|
111
165
|
safeHint,
|
|
112
166
|
remediationSteps,
|
|
@@ -122,6 +176,7 @@ export function buildLoopResultFromTransaction({ executionReport, flowMode, opti
|
|
|
122
176
|
errorCode: executionReport.lastErrorCode,
|
|
123
177
|
auditPath,
|
|
124
178
|
verifyArtifact,
|
|
179
|
+
artifactHints,
|
|
125
180
|
authorizationSummary: executionReport.authorizationSummary || undefined,
|
|
126
181
|
strategyName: executionReport.flowReport.strategyName ?? flowMode,
|
|
127
182
|
fsMode: executionReport.flowReport.fsMode ?? flowMode,
|
|
@@ -138,6 +193,7 @@ export function buildLoopFailureResult({ message, flowMode, telemetry, auditPath
|
|
|
138
193
|
const decisions = getAuthorizationDecisionsFromAuditTrail();
|
|
139
194
|
return decisions.length > 0 ? decisions : undefined;
|
|
140
195
|
})();
|
|
196
|
+
const rootCause = toRootCauseCode(errorCode);
|
|
141
197
|
const errorEnvelope = buildFailureEnvelope({
|
|
142
198
|
phase: failurePhase,
|
|
143
199
|
fallbackMessage: message,
|
|
@@ -146,6 +202,8 @@ export function buildLoopFailureResult({ message, flowMode, telemetry, auditPath
|
|
|
146
202
|
success: false,
|
|
147
203
|
reason: message,
|
|
148
204
|
reasonCode,
|
|
205
|
+
terminalReason: 'NON_RETRYABLE_FAILURE',
|
|
206
|
+
rootCause,
|
|
149
207
|
diagnosticCode: reasonCode,
|
|
150
208
|
safeHint: message,
|
|
151
209
|
remediationSteps: [],
|
|
@@ -300,19 +300,23 @@ export class Pipeline {
|
|
|
300
300
|
async execute() {
|
|
301
301
|
try {
|
|
302
302
|
const data = await this.promise;
|
|
303
|
+
const lastExecutedStep = [...this.traces].reverse().find((trace) => !trace.name.endsWith(':recovery'))?.name ??
|
|
304
|
+
this.lastStepName;
|
|
303
305
|
return {
|
|
304
306
|
success: true,
|
|
305
307
|
duration: Date.now() - this.startTime,
|
|
306
|
-
lastStep:
|
|
308
|
+
lastStep: lastExecutedStep,
|
|
307
309
|
data,
|
|
308
310
|
traces: this.traces,
|
|
309
311
|
};
|
|
310
312
|
}
|
|
311
313
|
catch (error) {
|
|
314
|
+
const lastExecutedStep = [...this.traces].reverse().find((trace) => !trace.name.endsWith(':recovery'))?.name ??
|
|
315
|
+
this.lastStepName;
|
|
312
316
|
return {
|
|
313
317
|
success: false,
|
|
314
318
|
error: error instanceof Error ? error : new Error(String(error)),
|
|
315
|
-
lastStep:
|
|
319
|
+
lastStep: lastExecutedStep,
|
|
316
320
|
duration: Date.now() - this.startTime,
|
|
317
321
|
data: this.ctxRef.current,
|
|
318
322
|
traces: this.traces,
|
|
@@ -2,6 +2,8 @@ import { text } from '../../../../locales/index.js';
|
|
|
2
2
|
import { buildFailureGuidance } from '../../../failure/diagnostics.js';
|
|
3
3
|
import { sanitizeError } from '../../../llm/errors.js';
|
|
4
4
|
import { mapErrorForDisplay } from '../../../observability/error-mapping.js';
|
|
5
|
+
import { resolveExecutionProfile } from '../../../runtime/execution-profile.js';
|
|
6
|
+
import { isRecoverableToolInputErrorCode } from '../../../tools/recoverable-tool-errors.js';
|
|
5
7
|
import { EXECUTION_PHASES } from '../../../types/runtime.js';
|
|
6
8
|
import { classifyError, isRetryable } from '../../../verification/runner.js';
|
|
7
9
|
const RETRYABLE_PHASES = new Set([
|
|
@@ -19,6 +21,7 @@ const NON_RETRYABLE_PERMISSION_CODES = new Set([
|
|
|
19
21
|
'PERMISSION_REQUIRED_CONTEXT_CACHE_OUTSIDE_ROOT',
|
|
20
22
|
'PERMISSION_DENIED_CONTEXT_CACHE_OUTSIDE_ROOT',
|
|
21
23
|
]);
|
|
24
|
+
const NON_RETRYABLE_LLM_CODES = new Set(['LLM_AUTHENTICATION_FAILED']);
|
|
22
25
|
function inferFailurePhase(flowReport) {
|
|
23
26
|
const failedTrace = [...flowReport.traces].reverse().find((trace) => Boolean(trace.error));
|
|
24
27
|
if (failedTrace && EXECUTION_PHASES.includes(failedTrace.name)) {
|
|
@@ -67,6 +70,7 @@ function extractInterrupt(error) {
|
|
|
67
70
|
}
|
|
68
71
|
export function resolveAttemptFailure(params) {
|
|
69
72
|
const { flowReport, context, flowMode } = params;
|
|
73
|
+
const profile = resolveExecutionProfile(flowMode);
|
|
70
74
|
const interrupt = extractInterrupt(flowReport.error);
|
|
71
75
|
const interruptCode = extractErrorCode(flowReport.error);
|
|
72
76
|
if (interruptCode === 'INTERRUPT_REQUIRED' && interrupt?.type === 'awaiting_input') {
|
|
@@ -87,23 +91,19 @@ export function resolveAttemptFailure(params) {
|
|
|
87
91
|
inputRequired,
|
|
88
92
|
};
|
|
89
93
|
}
|
|
90
|
-
const
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
const applyBackFailed =
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
context?.applyBackResult?.success === false &&
|
|
97
|
-
!context.applyBackResult.skipped;
|
|
94
|
+
const autopilotCompletion = flowMode === 'autopilot' && context && 'completion' in context ? context.completion : undefined;
|
|
95
|
+
const verifyOk = profile.verifyPolicy === 'never' ? true : context?.verifyResult?.ok !== false;
|
|
96
|
+
const applyBackResult = context && 'applyBackResult' in context ? context.applyBackResult : undefined;
|
|
97
|
+
const applyBackFailed = profile.failurePolicy === 'rollback' &&
|
|
98
|
+
applyBackResult?.success === false &&
|
|
99
|
+
!applyBackResult.skipped;
|
|
98
100
|
const environmentMode = context?.options?.environmentMode;
|
|
99
101
|
if (applyBackFailed) {
|
|
100
|
-
const fallbackReason =
|
|
101
|
-
context.applyBackResult?.error ||
|
|
102
|
-
text.loop.applyBackFailed;
|
|
102
|
+
const fallbackReason = applyBackResult?.safeMessage || applyBackResult?.error || text.loop.applyBackFailed;
|
|
103
103
|
const guidance = buildFailureGuidance({
|
|
104
104
|
reasonCode: 'APPLY_BACK_FAILED',
|
|
105
105
|
failurePhase: 'APPLY_BACK',
|
|
106
|
-
errorCode:
|
|
106
|
+
errorCode: applyBackResult?.errorCode || 'APPLY_BACK_FAILED',
|
|
107
107
|
environmentMode,
|
|
108
108
|
fallbackReason,
|
|
109
109
|
});
|
|
@@ -112,16 +112,51 @@ export function resolveAttemptFailure(params) {
|
|
|
112
112
|
reasonCode: 'APPLY_BACK_FAILED',
|
|
113
113
|
failurePhase: 'APPLY_BACK',
|
|
114
114
|
retryable: false,
|
|
115
|
-
errorCode:
|
|
115
|
+
errorCode: applyBackResult?.errorCode || 'APPLY_BACK_FAILED',
|
|
116
116
|
diagnosticCode: guidance.diagnosticCode,
|
|
117
117
|
safeHint: guidance.safeHint,
|
|
118
118
|
remediationSteps: guidance.remediationSteps,
|
|
119
119
|
};
|
|
120
120
|
}
|
|
121
|
-
if (flowReport.success && verifyOk) {
|
|
121
|
+
if (flowReport.success && verifyOk && !autopilotCompletion) {
|
|
122
122
|
return undefined;
|
|
123
123
|
}
|
|
124
124
|
const errorCode = extractErrorCode(flowReport.error) ?? extractErrorCodeFromTraces(flowReport);
|
|
125
|
+
if (flowMode === 'autopilot' && autopilotCompletion) {
|
|
126
|
+
if (autopilotCompletion.status === 'changed' ||
|
|
127
|
+
autopilotCompletion.status === 'read_only_answer') {
|
|
128
|
+
if (flowReport.success && verifyOk)
|
|
129
|
+
return undefined;
|
|
130
|
+
}
|
|
131
|
+
const reasonCode = autopilotCompletion.status === 'verification_missing'
|
|
132
|
+
? 'VERIFY_COMMAND_MISSING'
|
|
133
|
+
: autopilotCompletion.status === 'tool_failure' &&
|
|
134
|
+
isRecoverableToolInputErrorCode(autopilotCompletion.errorCode)
|
|
135
|
+
? 'TOOL_CORRECTION_REQUIRED'
|
|
136
|
+
: 'LOOP_FAILED';
|
|
137
|
+
const failurePhase = autopilotCompletion.status === 'verification_missing' ? 'VERIFY' : 'AUTOPILOT';
|
|
138
|
+
const fallbackReason = autopilotCompletion.reason ||
|
|
139
|
+
(autopilotCompletion.status === 'no_effect'
|
|
140
|
+
? 'Autopilot completed without changing files or producing an answer.'
|
|
141
|
+
: text.loop.loopExecutionFailed);
|
|
142
|
+
const guidance = buildFailureGuidance({
|
|
143
|
+
reasonCode,
|
|
144
|
+
failurePhase,
|
|
145
|
+
errorCode: autopilotCompletion.errorCode,
|
|
146
|
+
environmentMode,
|
|
147
|
+
fallbackReason,
|
|
148
|
+
});
|
|
149
|
+
return {
|
|
150
|
+
reason: guidance.safeHint,
|
|
151
|
+
reasonCode,
|
|
152
|
+
failurePhase,
|
|
153
|
+
retryable: reasonCode === 'TOOL_CORRECTION_REQUIRED' || autopilotCompletion.status === 'no_effect',
|
|
154
|
+
errorCode: autopilotCompletion.errorCode,
|
|
155
|
+
diagnosticCode: guidance.diagnosticCode,
|
|
156
|
+
safeHint: guidance.safeHint,
|
|
157
|
+
remediationSteps: guidance.remediationSteps,
|
|
158
|
+
};
|
|
159
|
+
}
|
|
125
160
|
if (errorCode === 'PREFLIGHT_NOT_GIT') {
|
|
126
161
|
const fallbackReason = sanitizeReason(flowReport.error);
|
|
127
162
|
const guidance = buildFailureGuidance({
|
|
@@ -182,7 +217,28 @@ export function resolveAttemptFailure(params) {
|
|
|
182
217
|
remediationSteps: guidance.remediationSteps,
|
|
183
218
|
};
|
|
184
219
|
}
|
|
185
|
-
if (
|
|
220
|
+
if (errorCode && NON_RETRYABLE_LLM_CODES.has(errorCode)) {
|
|
221
|
+
const failurePhase = inferFailurePhase(flowReport);
|
|
222
|
+
const fallbackReason = sanitizeReason(flowReport.error);
|
|
223
|
+
const guidance = buildFailureGuidance({
|
|
224
|
+
reasonCode: 'LOOP_FAILED',
|
|
225
|
+
failurePhase,
|
|
226
|
+
errorCode,
|
|
227
|
+
environmentMode,
|
|
228
|
+
fallbackReason,
|
|
229
|
+
});
|
|
230
|
+
return {
|
|
231
|
+
reason: guidance.safeHint,
|
|
232
|
+
reasonCode: 'LOOP_FAILED',
|
|
233
|
+
failurePhase,
|
|
234
|
+
retryable: false,
|
|
235
|
+
errorCode,
|
|
236
|
+
diagnosticCode: guidance.diagnosticCode,
|
|
237
|
+
safeHint: guidance.safeHint,
|
|
238
|
+
remediationSteps: guidance.remediationSteps,
|
|
239
|
+
};
|
|
240
|
+
}
|
|
241
|
+
if (profile.verifyPolicy !== 'never' && context?.verifyResult?.ok === false) {
|
|
186
242
|
const verifyOutput = context.verifyResult.output || text.loop.loopExecutionFailed;
|
|
187
243
|
const errorType = classifyError(verifyOutput);
|
|
188
244
|
const fallbackReason = sanitizeReason(context.lastError || verifyOutput);
|
|
@@ -207,6 +263,25 @@ export function resolveAttemptFailure(params) {
|
|
|
207
263
|
}
|
|
208
264
|
const failurePhase = inferFailurePhase(flowReport);
|
|
209
265
|
const fallbackReason = sanitizeReason(context?.lastError || flowReport.error);
|
|
266
|
+
if (isRecoverableToolInputErrorCode(errorCode)) {
|
|
267
|
+
const guidance = buildFailureGuidance({
|
|
268
|
+
reasonCode: 'TOOL_CORRECTION_REQUIRED',
|
|
269
|
+
failurePhase,
|
|
270
|
+
errorCode,
|
|
271
|
+
environmentMode,
|
|
272
|
+
fallbackReason,
|
|
273
|
+
});
|
|
274
|
+
return {
|
|
275
|
+
reason: guidance.safeHint,
|
|
276
|
+
reasonCode: 'TOOL_CORRECTION_REQUIRED',
|
|
277
|
+
failurePhase,
|
|
278
|
+
retryable: RETRYABLE_PHASES.has(failurePhase),
|
|
279
|
+
errorCode,
|
|
280
|
+
diagnosticCode: guidance.diagnosticCode,
|
|
281
|
+
safeHint: guidance.safeHint,
|
|
282
|
+
remediationSteps: guidance.remediationSteps,
|
|
283
|
+
};
|
|
284
|
+
}
|
|
210
285
|
const guidance = buildFailureGuidance({
|
|
211
286
|
reasonCode: failurePhase === 'ROLLBACK' ? 'ROLLBACK_FAILED' : 'LOOP_FAILED',
|
|
212
287
|
failurePhase,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export function mapSuccessReport(params) {
|
|
2
|
-
const { attempt, flowReport, history, authorizationSummary, lastContext, lastVerifyArtifact, lastErrorCode, } = params;
|
|
2
|
+
const { attempt, flowReport, history, authorizationSummary, lastContext, lastVerifyArtifact, lastSubAgentPatchArtifacts, lastSubAgentAuditArtifacts, lastRecentReadArtifacts, lastToolResultPreviewArtifacts, lastErrorCode, } = params;
|
|
3
3
|
return {
|
|
4
4
|
success: true,
|
|
5
5
|
attempts: attempt,
|
|
@@ -10,10 +10,14 @@ export function mapSuccessReport(params) {
|
|
|
10
10
|
retryExhausted: false,
|
|
11
11
|
lastContext,
|
|
12
12
|
lastVerifyArtifact,
|
|
13
|
+
lastSubAgentPatchArtifacts,
|
|
14
|
+
lastSubAgentAuditArtifacts,
|
|
15
|
+
lastRecentReadArtifacts,
|
|
16
|
+
lastToolResultPreviewArtifacts,
|
|
13
17
|
};
|
|
14
18
|
}
|
|
15
19
|
export function mapTerminalFailureReport(params) {
|
|
16
|
-
const { attempt, flowReport, history, authorizationSummary, lastContext, lastVerifyArtifact, failure, lastErrorCode, } = params;
|
|
20
|
+
const { attempt, flowReport, history, authorizationSummary, lastContext, lastVerifyArtifact, lastSubAgentPatchArtifacts, lastSubAgentAuditArtifacts, lastRecentReadArtifacts, lastToolResultPreviewArtifacts, failure, lastErrorCode, } = params;
|
|
17
21
|
return {
|
|
18
22
|
success: false,
|
|
19
23
|
attempts: attempt,
|
|
@@ -24,6 +28,10 @@ export function mapTerminalFailureReport(params) {
|
|
|
24
28
|
retryExhausted: false,
|
|
25
29
|
lastContext,
|
|
26
30
|
lastVerifyArtifact,
|
|
31
|
+
lastSubAgentPatchArtifacts,
|
|
32
|
+
lastSubAgentAuditArtifacts,
|
|
33
|
+
lastRecentReadArtifacts,
|
|
34
|
+
lastToolResultPreviewArtifacts,
|
|
27
35
|
terminalReason: failure.reason,
|
|
28
36
|
terminalReasonCode: failure.reasonCode,
|
|
29
37
|
terminalFailurePhase: failure.failurePhase,
|
|
@@ -34,7 +42,7 @@ export function mapTerminalFailureReport(params) {
|
|
|
34
42
|
};
|
|
35
43
|
}
|
|
36
44
|
export function mapRetryExhaustedReport(params) {
|
|
37
|
-
const { attempts, flowReport, history, authorizationSummary, lastErrorCode, lastContext, lastVerifyArtifact, } = params;
|
|
45
|
+
const { attempts, flowReport, history, authorizationSummary, failure, lastErrorCode, lastContext, lastVerifyArtifact, lastSubAgentPatchArtifacts, lastSubAgentAuditArtifacts, lastRecentReadArtifacts, lastToolResultPreviewArtifacts, } = params;
|
|
38
46
|
return {
|
|
39
47
|
success: false,
|
|
40
48
|
attempts,
|
|
@@ -45,6 +53,12 @@ export function mapRetryExhaustedReport(params) {
|
|
|
45
53
|
retryExhausted: true,
|
|
46
54
|
lastContext,
|
|
47
55
|
lastVerifyArtifact,
|
|
56
|
+
lastSubAgentPatchArtifacts,
|
|
57
|
+
lastSubAgentAuditArtifacts,
|
|
58
|
+
lastRecentReadArtifacts,
|
|
59
|
+
lastToolResultPreviewArtifacts,
|
|
60
|
+
terminalFailurePhase: failure?.failurePhase,
|
|
61
|
+
terminalDiagnosticCode: failure?.diagnosticCode,
|
|
48
62
|
};
|
|
49
63
|
}
|
|
50
64
|
//# sourceMappingURL=report-mapper.js.map
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { recordAuditEvent } from '../../../observability/audit-trail.js';
|
|
2
|
+
import { mapErrorForAudit } from '../../../observability/error-mapping.js';
|
|
2
3
|
import { ReflectionEngine } from '../../../reflection/engine.js';
|
|
3
|
-
import {
|
|
4
|
+
import { resolveExecutionProfile } from '../../../runtime/execution-profile.js';
|
|
5
|
+
import { executeFlowAttempt } from '../../flows/flow-dispatch.js';
|
|
4
6
|
import { resolveAttemptFailure } from './attempt-failure.js';
|
|
5
7
|
import { buildAuthorizationSummary } from './authorization-summary.js';
|
|
6
8
|
import { mapRetryExhaustedReport, mapSuccessReport, mapTerminalFailureReport, } from './report-mapper.js';
|
|
@@ -11,6 +13,108 @@ export class FlowTransactionCancelledError extends Error {
|
|
|
11
13
|
this.name = 'FlowTransactionCancelledError';
|
|
12
14
|
}
|
|
13
15
|
}
|
|
16
|
+
function isArtifactHandle(value) {
|
|
17
|
+
return (Boolean(value) &&
|
|
18
|
+
typeof value === 'object' &&
|
|
19
|
+
typeof value.handle === 'string');
|
|
20
|
+
}
|
|
21
|
+
function mergeArtifactHandles(existing, incoming, limit = 4) {
|
|
22
|
+
const merged = [...existing];
|
|
23
|
+
const seen = new Set(existing.map((artifact) => artifact.handle));
|
|
24
|
+
for (const artifact of incoming) {
|
|
25
|
+
if (seen.has(artifact.handle))
|
|
26
|
+
continue;
|
|
27
|
+
merged.push(artifact);
|
|
28
|
+
seen.add(artifact.handle);
|
|
29
|
+
}
|
|
30
|
+
if (merged.length <= limit)
|
|
31
|
+
return merged;
|
|
32
|
+
return merged.slice(merged.length - limit);
|
|
33
|
+
}
|
|
34
|
+
function extractSubAgentArtifacts(entries) {
|
|
35
|
+
if (!Array.isArray(entries) || entries.length === 0) {
|
|
36
|
+
return { patchArtifacts: [], auditArtifacts: [] };
|
|
37
|
+
}
|
|
38
|
+
const patchArtifacts = [];
|
|
39
|
+
const auditArtifacts = [];
|
|
40
|
+
for (const entry of entries) {
|
|
41
|
+
if (entry?.toolName !== 'agent_dispatch' || entry.toolResultStatus !== 'ok')
|
|
42
|
+
continue;
|
|
43
|
+
if (isArtifactHandle(entry.toolResultPatchArtifact)) {
|
|
44
|
+
patchArtifacts.push(entry.toolResultPatchArtifact);
|
|
45
|
+
}
|
|
46
|
+
if (isArtifactHandle(entry.toolResultAuditArtifact)) {
|
|
47
|
+
auditArtifacts.push(entry.toolResultAuditArtifact);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
return { patchArtifacts, auditArtifacts };
|
|
51
|
+
}
|
|
52
|
+
function extractRecentReadArtifacts(entries) {
|
|
53
|
+
if (!Array.isArray(entries) || entries.length === 0) {
|
|
54
|
+
return [];
|
|
55
|
+
}
|
|
56
|
+
const recentReads = [];
|
|
57
|
+
for (const entry of entries) {
|
|
58
|
+
if (entry.toolIntent !== 'READ' || entry.toolResultStatus !== 'ok')
|
|
59
|
+
continue;
|
|
60
|
+
if (typeof entry.toolResultReadArtifactPath !== 'string')
|
|
61
|
+
continue;
|
|
62
|
+
if (!isArtifactHandle(entry.toolResultReadArtifact))
|
|
63
|
+
continue;
|
|
64
|
+
recentReads.push({
|
|
65
|
+
path: entry.toolResultReadArtifactPath,
|
|
66
|
+
artifact: entry.toolResultReadArtifact,
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
return recentReads;
|
|
70
|
+
}
|
|
71
|
+
function mergeReadArtifacts(existing, incoming, limit = 6) {
|
|
72
|
+
const merged = [];
|
|
73
|
+
const seen = new Set();
|
|
74
|
+
for (const item of [...existing, ...incoming]) {
|
|
75
|
+
const key = `${item.path}::${item.artifact.handle}`;
|
|
76
|
+
if (seen.has(key))
|
|
77
|
+
continue;
|
|
78
|
+
seen.add(key);
|
|
79
|
+
merged.push(item);
|
|
80
|
+
}
|
|
81
|
+
if (merged.length <= limit)
|
|
82
|
+
return merged;
|
|
83
|
+
return merged.slice(merged.length - limit);
|
|
84
|
+
}
|
|
85
|
+
function extractToolResultPreviewArtifacts(entries) {
|
|
86
|
+
if (!Array.isArray(entries) || entries.length === 0) {
|
|
87
|
+
return [];
|
|
88
|
+
}
|
|
89
|
+
const previews = [];
|
|
90
|
+
for (const entry of entries) {
|
|
91
|
+
if (entry.toolResultStatus !== 'ok')
|
|
92
|
+
continue;
|
|
93
|
+
if (typeof entry.toolResultPreviewLabel !== 'string')
|
|
94
|
+
continue;
|
|
95
|
+
if (!isArtifactHandle(entry.toolResultPreviewArtifact))
|
|
96
|
+
continue;
|
|
97
|
+
previews.push({
|
|
98
|
+
label: entry.toolResultPreviewLabel,
|
|
99
|
+
artifact: entry.toolResultPreviewArtifact,
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
return previews;
|
|
103
|
+
}
|
|
104
|
+
function mergePreviewArtifacts(existing, incoming, limit = 6) {
|
|
105
|
+
const merged = [];
|
|
106
|
+
const seen = new Set();
|
|
107
|
+
for (const item of [...existing, ...incoming]) {
|
|
108
|
+
const key = `${item.label}::${item.artifact.handle}`;
|
|
109
|
+
if (seen.has(key))
|
|
110
|
+
continue;
|
|
111
|
+
seen.add(key);
|
|
112
|
+
merged.push(item);
|
|
113
|
+
}
|
|
114
|
+
if (merged.length <= limit)
|
|
115
|
+
return merged;
|
|
116
|
+
return merged.slice(merged.length - limit);
|
|
117
|
+
}
|
|
14
118
|
export class FlowTransactionRunner {
|
|
15
119
|
params;
|
|
16
120
|
historyEntries = [];
|
|
@@ -19,8 +123,25 @@ export class FlowTransactionRunner {
|
|
|
19
123
|
authorizationSummary = null;
|
|
20
124
|
lastContext;
|
|
21
125
|
lastVerifyArtifact;
|
|
126
|
+
lastSubAgentPatchArtifacts;
|
|
127
|
+
lastSubAgentAuditArtifacts;
|
|
128
|
+
lastRecentReadArtifacts;
|
|
129
|
+
lastToolResultPreviewArtifacts;
|
|
130
|
+
lastReplacementState;
|
|
22
131
|
constructor(params) {
|
|
23
132
|
this.params = params;
|
|
133
|
+
this.lastVerifyArtifact = params.options.artifactHints?.verifyArtifact;
|
|
134
|
+
this.lastSubAgentPatchArtifacts = [
|
|
135
|
+
...(params.options.artifactHints?.subAgentPatchArtifacts ?? []),
|
|
136
|
+
];
|
|
137
|
+
this.lastSubAgentAuditArtifacts = [
|
|
138
|
+
...(params.options.artifactHints?.subAgentAuditArtifacts ?? []),
|
|
139
|
+
];
|
|
140
|
+
this.lastRecentReadArtifacts = [...(params.options.artifactHints?.recentReadArtifacts ?? [])];
|
|
141
|
+
this.lastToolResultPreviewArtifacts = [
|
|
142
|
+
...(params.options.artifactHints?.toolResultPreviewArtifacts ?? []),
|
|
143
|
+
];
|
|
144
|
+
this.lastReplacementState = params.options.replacementState;
|
|
24
145
|
}
|
|
25
146
|
isShrinkCtx(ctx) {
|
|
26
147
|
return Boolean(ctx && 'verifyResult' in ctx);
|
|
@@ -28,13 +149,15 @@ export class FlowTransactionRunner {
|
|
|
28
149
|
async execute() {
|
|
29
150
|
let retries = 0;
|
|
30
151
|
let lastReport;
|
|
152
|
+
let lastAttemptFailure;
|
|
153
|
+
const profile = resolveExecutionProfile(this.params.flowMode);
|
|
31
154
|
while (true) {
|
|
32
155
|
if (this.params.options.signal?.aborted) {
|
|
33
156
|
throw new FlowTransactionCancelledError();
|
|
34
157
|
}
|
|
35
158
|
const attempt = retries + 1;
|
|
36
159
|
recordAuditEvent('loop.attempt.start', { attempt, flowMode: this.params.flowMode }, { phase: 'PREFLIGHT', scope: 'session' });
|
|
37
|
-
const result = await
|
|
160
|
+
const result = await executeFlowAttempt({
|
|
38
161
|
workspace: this.params.env.workspace,
|
|
39
162
|
options: this.params.options,
|
|
40
163
|
mode: this.params.flowMode,
|
|
@@ -45,6 +168,20 @@ export class FlowTransactionRunner {
|
|
|
45
168
|
shadowInitialRef: this.params.env.shadowInitialRef,
|
|
46
169
|
attempt,
|
|
47
170
|
initialContext: this.currentContext,
|
|
171
|
+
artifactHints: {
|
|
172
|
+
verifyArtifact: this.lastVerifyArtifact,
|
|
173
|
+
subAgentPatchArtifacts: this.lastSubAgentPatchArtifacts.length > 0
|
|
174
|
+
? this.lastSubAgentPatchArtifacts
|
|
175
|
+
: undefined,
|
|
176
|
+
subAgentAuditArtifacts: this.lastSubAgentAuditArtifacts.length > 0
|
|
177
|
+
? this.lastSubAgentAuditArtifacts
|
|
178
|
+
: undefined,
|
|
179
|
+
recentReadArtifacts: this.lastRecentReadArtifacts.length > 0 ? this.lastRecentReadArtifacts : undefined,
|
|
180
|
+
toolResultPreviewArtifacts: this.lastToolResultPreviewArtifacts.length > 0
|
|
181
|
+
? this.lastToolResultPreviewArtifacts
|
|
182
|
+
: undefined,
|
|
183
|
+
},
|
|
184
|
+
replacementState: this.lastReplacementState,
|
|
48
185
|
lastError: this.currentLastError,
|
|
49
186
|
applyBackRuntime: {
|
|
50
187
|
activeRepoPath: this.params.env.activeRepoPath,
|
|
@@ -63,11 +200,18 @@ export class FlowTransactionRunner {
|
|
|
63
200
|
if (shrinkCtx?.verifyArtifact) {
|
|
64
201
|
this.lastVerifyArtifact = shrinkCtx.verifyArtifact;
|
|
65
202
|
}
|
|
203
|
+
const subAgentArtifacts = extractSubAgentArtifacts(terminalCtx?.toolCallingAudit);
|
|
204
|
+
this.lastSubAgentPatchArtifacts = mergeArtifactHandles(this.lastSubAgentPatchArtifacts, subAgentArtifacts.patchArtifacts);
|
|
205
|
+
this.lastSubAgentAuditArtifacts = mergeArtifactHandles(this.lastSubAgentAuditArtifacts, subAgentArtifacts.auditArtifacts);
|
|
206
|
+
this.lastRecentReadArtifacts = mergeReadArtifacts(this.lastRecentReadArtifacts, extractRecentReadArtifacts(terminalCtx?.toolCallingAudit));
|
|
207
|
+
this.lastToolResultPreviewArtifacts = mergePreviewArtifacts(this.lastToolResultPreviewArtifacts, extractToolResultPreviewArtifacts(terminalCtx?.toolCallingAudit));
|
|
208
|
+
this.lastReplacementState = terminalCtx?.replacementState ?? this.lastReplacementState;
|
|
66
209
|
const attemptFailure = resolveAttemptFailure({
|
|
67
210
|
flowReport: result,
|
|
68
211
|
context: shrinkCtx,
|
|
69
212
|
flowMode: this.params.flowMode,
|
|
70
213
|
});
|
|
214
|
+
lastAttemptFailure = attemptFailure;
|
|
71
215
|
const entry = {
|
|
72
216
|
attempt,
|
|
73
217
|
plan: shrinkCtx?.plan ?? null,
|
|
@@ -81,9 +225,11 @@ export class FlowTransactionRunner {
|
|
|
81
225
|
this.params.telemetry.addHistory(entry);
|
|
82
226
|
this.authorizationSummary = buildAuthorizationSummary(shrinkCtx?.toolAuditLogger?.getLogs?.());
|
|
83
227
|
if (!attemptFailure) {
|
|
84
|
-
const successPhase =
|
|
85
|
-
?
|
|
86
|
-
:
|
|
228
|
+
const successPhase = profile.failurePolicy === 'preserve'
|
|
229
|
+
? profile.entryPhase
|
|
230
|
+
: profile.readOnly
|
|
231
|
+
? 'SHRINK'
|
|
232
|
+
: 'APPLY_BACK';
|
|
87
233
|
recordAuditEvent('loop.attempt.success', { attempt, flowMode: this.params.flowMode }, { phase: successPhase, severity: 'low', scope: 'session' });
|
|
88
234
|
// Reflection Mechanism: trigger when multiple attempts were needed
|
|
89
235
|
if (attempt > 1 && this.params.options.llm) {
|
|
@@ -106,8 +252,12 @@ export class FlowTransactionRunner {
|
|
|
106
252
|
history: this.historyEntries,
|
|
107
253
|
authorizationSummary: this.authorizationSummary,
|
|
108
254
|
lastErrorCode: this.extractErrorCode(result.error),
|
|
109
|
-
lastContext:
|
|
255
|
+
lastContext: terminalCtx,
|
|
110
256
|
lastVerifyArtifact: this.lastVerifyArtifact,
|
|
257
|
+
lastSubAgentPatchArtifacts: this.lastSubAgentPatchArtifacts,
|
|
258
|
+
lastSubAgentAuditArtifacts: this.lastSubAgentAuditArtifacts,
|
|
259
|
+
lastRecentReadArtifacts: this.lastRecentReadArtifacts,
|
|
260
|
+
lastToolResultPreviewArtifacts: this.lastToolResultPreviewArtifacts,
|
|
111
261
|
});
|
|
112
262
|
}
|
|
113
263
|
if (attemptFailure.reasonCode === 'AWAITING_INPUT') {
|
|
@@ -120,6 +270,10 @@ export class FlowTransactionRunner {
|
|
|
120
270
|
timestamp: this.params.now(),
|
|
121
271
|
});
|
|
122
272
|
}
|
|
273
|
+
const mappedAuditError = mapErrorForAudit({
|
|
274
|
+
message: attemptFailure.safeHint ?? attemptFailure.reason,
|
|
275
|
+
code: attemptFailure.errorCode ?? attemptFailure.reasonCode,
|
|
276
|
+
});
|
|
123
277
|
recordAuditEvent('loop.attempt.failure', {
|
|
124
278
|
attempt,
|
|
125
279
|
flowMode: this.params.flowMode,
|
|
@@ -131,6 +285,9 @@ export class FlowTransactionRunner {
|
|
|
131
285
|
failurePhase: attemptFailure.failurePhase,
|
|
132
286
|
retryable: attemptFailure.retryable,
|
|
133
287
|
errorCode: attemptFailure.errorCode,
|
|
288
|
+
errorSummary: mappedAuditError.summary,
|
|
289
|
+
errorCategory: mappedAuditError.category,
|
|
290
|
+
errorRedacted: mappedAuditError.redacted,
|
|
134
291
|
lastStep: result.lastStep,
|
|
135
292
|
}, {
|
|
136
293
|
phase: attemptFailure.failurePhase,
|
|
@@ -152,8 +309,12 @@ export class FlowTransactionRunner {
|
|
|
152
309
|
history: this.historyEntries,
|
|
153
310
|
authorizationSummary: this.authorizationSummary,
|
|
154
311
|
lastErrorCode: attemptFailure.errorCode ?? this.extractErrorCode(result.error),
|
|
155
|
-
lastContext:
|
|
312
|
+
lastContext: terminalCtx,
|
|
156
313
|
lastVerifyArtifact: this.lastVerifyArtifact,
|
|
314
|
+
lastSubAgentPatchArtifacts: this.lastSubAgentPatchArtifacts,
|
|
315
|
+
lastSubAgentAuditArtifacts: this.lastSubAgentAuditArtifacts,
|
|
316
|
+
lastRecentReadArtifacts: this.lastRecentReadArtifacts,
|
|
317
|
+
lastToolResultPreviewArtifacts: this.lastToolResultPreviewArtifacts,
|
|
157
318
|
failure: attemptFailure,
|
|
158
319
|
});
|
|
159
320
|
}
|
|
@@ -176,9 +337,14 @@ export class FlowTransactionRunner {
|
|
|
176
337
|
flowReport: lastReport,
|
|
177
338
|
history: this.historyEntries,
|
|
178
339
|
authorizationSummary: this.authorizationSummary,
|
|
340
|
+
failure: lastAttemptFailure,
|
|
179
341
|
lastErrorCode: this.extractErrorCode(lastReport.error),
|
|
180
342
|
lastContext: this.lastContext,
|
|
181
343
|
lastVerifyArtifact: this.lastVerifyArtifact,
|
|
344
|
+
lastSubAgentPatchArtifacts: this.lastSubAgentPatchArtifacts,
|
|
345
|
+
lastSubAgentAuditArtifacts: this.lastSubAgentAuditArtifacts,
|
|
346
|
+
lastRecentReadArtifacts: this.lastRecentReadArtifacts,
|
|
347
|
+
lastToolResultPreviewArtifacts: this.lastToolResultPreviewArtifacts,
|
|
182
348
|
});
|
|
183
349
|
}
|
|
184
350
|
extractErrorCode(error) {
|