salmon-loop 0.3.2 → 0.5.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/dist/cli/authorization/non-interactive.js +9 -13
- package/dist/cli/authorization/provider.js +2 -10
- package/dist/cli/chat.js +12 -6
- package/dist/cli/commands/allowlist.js +1 -1
- package/dist/cli/commands/chat.js +13 -13
- package/dist/cli/commands/config.js +2 -2
- package/dist/cli/commands/mode.js +2 -2
- package/dist/cli/commands/parallel.js +1 -1
- package/dist/cli/commands/run/handler.js +9 -4
- package/dist/cli/commands/run/loop-params.js +2 -0
- package/dist/cli/commands/run/parse-options.js +14 -26
- package/dist/cli/commands/run/runtime-llm.js +15 -12
- package/dist/cli/commands/run/runtime-options.js +3 -1
- package/dist/cli/config.js +0 -8
- package/dist/cli/headless/openai-responses-canonical-applier.js +1 -7
- package/dist/cli/locales/en.js +2 -2
- package/dist/cli/reporters/standard.js +12 -3
- package/dist/cli/reporters/stream-json.js +2 -1
- package/dist/cli/slash/runtime.js +2 -2
- package/dist/cli/ui/hooks/useLoopEvents.js +1 -1
- package/dist/cli/ui/hooks/useLoopState.js +1 -1
- package/dist/core/adapters/fs/file-adapter.js +3 -1
- package/dist/core/adapters/git/git-adapter.js +6 -3
- package/dist/core/adapters/git/git-runner.js +5 -2
- package/dist/core/adapters/git/lock-manager.js +7 -4
- package/dist/core/ast/parser.js +18 -9
- package/dist/core/checkpoint-domain/manifest-store.js +21 -13
- package/dist/core/checkpoint-domain/service.js +3 -1
- package/dist/core/config/limits.js +1 -1
- package/dist/core/config/model-pricing.js +61 -0
- package/dist/core/config/schema.js +738 -0
- package/dist/core/config/validate.js +11 -922
- package/dist/core/context/ast/skeleton-extractor.js +225 -0
- package/dist/core/context/ast/source-outline.js +24 -1
- package/dist/core/context/budget/dynamic-adjuster.js +20 -5
- package/dist/core/context/builder.js +7 -3
- package/dist/core/context/cache/store-factory.js +3 -1
- package/dist/core/context/dependencies.js +2 -1
- package/dist/core/context/effectiveness/persistence.js +50 -0
- package/dist/core/context/effectiveness/tracker.js +24 -0
- package/dist/core/context/gatherers/architecture-gatherer.js +2 -1
- package/dist/core/context/gatherers/artifact-gatherer.js +7 -4
- package/dist/core/context/gatherers/ast-gatherer.js +34 -40
- package/dist/core/context/gatherers/ghost-dependency-gatherer.js +0 -1
- package/dist/core/context/gatherers/git-history-gatherer.js +3 -1
- package/dist/core/context/gatherers/knowledge-gatherer.js +21 -2
- package/dist/core/context/gatherers/metadata-gatherer.js +12 -7
- package/dist/core/context/gatherers/ripgrep-gatherer.js +6 -3
- package/dist/core/context/service.js +12 -2
- package/dist/core/context/steps/context-gather.js +14 -3
- package/dist/core/context/steps/context-targets.js +1 -0
- package/dist/core/context/targeting/target-resolver.js +29 -11
- package/dist/core/context/token/cache.js +5 -2
- package/dist/core/context/token/encoding-registry.js +7 -6
- package/dist/core/context/truncation/strategies/json.js +5 -2
- package/dist/core/context/truncation/type-detector.js +3 -1
- package/dist/core/extensions/index.js +48 -3
- package/dist/core/extensions/load.js +3 -2
- package/dist/core/extensions/merge.js +5 -1
- package/dist/core/extensions/paths.js +8 -2
- package/dist/core/extensions/schemas.js +21 -0
- package/dist/core/facades/cli-authorization-provider.js +1 -0
- package/dist/core/facades/cli-command-chat.js +2 -0
- package/dist/core/facades/cli-run-handler.js +1 -0
- package/dist/core/facades/cli-utils-serialize.js +2 -0
- package/dist/core/feedback/parsers.js +290 -1
- package/dist/core/grizzco/dsl/llm-strategy.js +4 -3
- package/dist/core/grizzco/engine/observability/loop-telemetry.js +5 -2
- package/dist/core/grizzco/engine/outcome/loop-result-mapper.js +30 -13
- package/dist/core/grizzco/engine/pipeline/pipeline.js +149 -240
- package/dist/core/grizzco/engine/transaction/attempt-failure.js +49 -24
- package/dist/core/grizzco/engine/transaction/authorization-summary.js +2 -1
- package/dist/core/grizzco/engine/transaction/transaction-runner.js +40 -34
- package/dist/core/grizzco/execution/RejectionManager.js +7 -5
- package/dist/core/grizzco/runtime/apply-back-runtime.js +5 -2
- package/dist/core/grizzco/services/implementations/default/GitConfigService.js +2 -1
- package/dist/core/grizzco/services/registry.js +18 -0
- package/dist/core/grizzco/steps/audit.js +20 -10
- package/dist/core/grizzco/steps/autopilot.js +21 -32
- package/dist/core/grizzco/steps/display-report.js +4 -11
- package/dist/core/grizzco/steps/explore.js +14 -4
- package/dist/core/grizzco/steps/generateReview.js +3 -1
- package/dist/core/grizzco/steps/patch/prompt-input.js +4 -1
- package/dist/core/grizzco/steps/patch.js +1 -0
- package/dist/core/grizzco/steps/plan.js +58 -49
- package/dist/core/grizzco/steps/research.js +3 -1
- package/dist/core/grizzco/steps/tool-runtime.js +3 -0
- package/dist/core/grizzco/steps/verify.js +7 -1
- package/dist/core/grizzco/validation/AstValidationService.js +3 -1
- package/dist/core/grizzco/workers/strata-sync-worker.js +2 -1
- package/dist/core/history/input-history.js +3 -1
- package/dist/core/intent/chat-intent.js +3 -1
- package/dist/core/llm/ai-sdk/message-mapper.js +37 -26
- package/dist/core/llm/ai-sdk/request-params.js +2 -6
- package/dist/core/llm/ai-sdk/result-mapper.js +14 -8
- package/dist/core/llm/ai-sdk/retry-classifier.js +17 -7
- package/dist/core/llm/ai-sdk/retry-executor.js +1 -1
- package/dist/core/llm/contracts/repair.js +16 -8
- package/dist/core/llm/errors.js +18 -14
- package/dist/core/llm/output-policy.js +8 -0
- package/dist/core/llm/redact.js +1 -3
- package/dist/core/llm/retry-utils.js +8 -2
- package/dist/core/llm/stream-utils.js +5 -3
- package/dist/core/llm/sub-agent-factory.js +51 -0
- package/dist/core/llm/tool-calling-stub.js +48 -0
- package/dist/core/llm/utils.js +17 -6
- package/dist/core/mcp/bridge/prompt-command-provider.js +4 -3
- package/dist/core/mcp/bridge/resource-context-provider.js +3 -1
- package/dist/core/mcp/bridge/tool-bridge.js +5 -14
- package/dist/core/mcp/catalog/discovery.js +3 -1
- package/dist/core/mcp/client/connection-manager.js +7 -4
- package/dist/core/mcp/client/transport-factory.js +7 -3
- package/dist/core/mcp/host/sampling-provider.js +1 -1
- package/dist/core/mcp/schema/json-schema-to-zod.js +2 -1
- package/dist/core/memory/relevant-retrieval.js +6 -4
- package/dist/core/observability/audit-file.js +2 -1
- package/dist/core/observability/audit-trail.js +3 -1
- package/dist/core/observability/authorization-decisions.js +13 -12
- package/dist/core/observability/error-mapping.js +2 -1
- package/dist/core/observability/logger.js +2 -1
- package/dist/core/observability/monitor.js +24 -0
- package/dist/core/observability/run-outcome-reporter.js +1 -0
- package/dist/core/observability/token-usage.js +5 -4
- package/dist/core/permission-gate/default-gate.js +5 -8
- package/dist/core/plan/storage.js +7 -4
- package/dist/core/plugin/loader.js +8 -5
- package/dist/core/prompts/registry.js +12 -30
- package/dist/core/prompts/runtime.js +3 -1
- package/dist/core/prompts/templates/system/autopilot_system.hbs +28 -4
- package/dist/core/protocols/a2a/sdk/executor.js +3 -1
- package/dist/core/protocols/a2a/sdk/server.js +5 -4
- package/dist/core/protocols/acp/acp-command-runner.js +7 -6
- package/dist/core/protocols/acp/acp-session-persistence.js +13 -10
- package/dist/core/protocols/acp/formal-agent.js +13 -6
- package/dist/core/protocols/acp/permission-provider.js +3 -2
- package/dist/core/protocols/acp/stdio-server.js +6 -6
- package/dist/core/reflection/engine.js +114 -14
- package/dist/core/runtime/agent-server-runtime.js +3 -2
- package/dist/core/runtime/batch-runner.js +81 -0
- package/dist/core/runtime/initialize.js +71 -6
- package/dist/core/runtime/loop-finalize.js +3 -0
- package/dist/core/runtime/loop-session-runner.js +5 -0
- package/dist/core/runtime/loop.js +4 -0
- package/dist/core/runtime/paths.js +9 -6
- package/dist/core/runtime/spawn-interactive.js +5 -4
- package/dist/core/security/redaction.js +3 -2
- package/dist/core/session/compaction/index.js +4 -3
- package/dist/core/session/compression.js +3 -1
- package/dist/core/session/manager.js +26 -38
- package/dist/core/session/pruning-strategy.js +2 -1
- package/dist/core/session/token-tracker.js +27 -9
- package/dist/core/skills/parser.js +3 -2
- package/dist/core/skills/permissions.js +2 -2
- package/dist/core/skills/runtime/MicroTaskRunner.js +1 -1
- package/dist/core/skills/runtime/SkillRunner.js +5 -2
- package/dist/core/slash/steps/slash-execute.js +7 -5
- package/dist/core/slash/strategy.js +1 -1
- package/dist/core/strata/checkpoint/manager.js +16 -10
- package/dist/core/strata/checkpoint/snapshot-create.js +5 -4
- package/dist/core/strata/checkpoint/snapshot-write-tree.js +7 -3
- package/dist/core/strata/engine/shadow-merge-engine.js +4 -2
- package/dist/core/strata/interaction/file-system-provider.js +2 -1
- package/dist/core/strata/layers/file-state-resolver.js +9 -7
- package/dist/core/strata/layers/immutable-git-layer.js +3 -1
- package/dist/core/strata/layers/shadow-driver/readonly-lock.js +8 -6
- package/dist/core/strata/layers/shadow-driver/shadow-driver.js +2 -1
- package/dist/core/strata/layers/worktree.js +9 -10
- package/dist/core/strata/runtime/environment.js +2 -1
- package/dist/core/strata/runtime/synchronizer.js +28 -26
- package/dist/core/streaming/canonical/parts-from-llm-stream-chunk.js +1 -11
- package/dist/core/structured-output/json-extract.js +3 -1
- package/dist/core/structured-output/json-schema-validator.js +1 -13
- package/dist/core/sub-agent/artifacts/store.js +2 -1
- package/dist/core/sub-agent/context-snapshot.js +12 -6
- package/dist/core/sub-agent/controller.js +70 -1
- package/dist/core/sub-agent/core/loop.js +25 -3
- package/dist/core/sub-agent/core/manager.js +343 -117
- package/dist/core/sub-agent/registry-defaults.js +12 -0
- package/dist/core/sub-agent/registry.js +8 -0
- package/dist/core/sub-agent/summary.js +96 -0
- package/dist/core/sub-agent/team.js +98 -0
- package/dist/core/sub-agent/tools/task-await.js +109 -0
- package/dist/core/sub-agent/tools/task-spawn.js +52 -7
- package/dist/core/sub-agent/tools/team.js +92 -0
- package/dist/core/sub-agent/types.js +11 -2
- package/dist/core/target-runtime/profile.js +3 -1
- package/dist/core/tools/audit.js +3 -2
- package/dist/core/tools/budget.js +7 -12
- package/dist/core/tools/builtin/ast.js +144 -0
- package/dist/core/tools/builtin/code-search/backends/powershell.js +3 -1
- package/dist/core/tools/builtin/code-search/backends/rg.js +3 -1
- package/dist/core/tools/builtin/code-search/executor.js +46 -43
- package/dist/core/tools/builtin/code-search/parse/plain-grep.js +3 -1
- package/dist/core/tools/builtin/code-search/parse/rg-json.js +3 -1
- package/dist/core/tools/builtin/fs.js +90 -7
- package/dist/core/tools/builtin/git.js +242 -0
- package/dist/core/tools/builtin/glob.js +79 -0
- package/dist/core/tools/builtin/index.js +53 -111
- package/dist/core/tools/builtin/interaction.js +13 -15
- package/dist/core/tools/builtin/knowledge.js +146 -4
- package/dist/core/tools/builtin/proposal.js +14 -3
- package/dist/core/tools/builtin/verify.js +35 -3
- package/dist/core/tools/capability/executor.js +5 -5
- package/dist/core/tools/headless-payload.js +1 -3
- package/dist/core/tools/mapper.js +8 -42
- package/dist/core/tools/parallel/persistence.js +17 -5
- package/dist/core/tools/parallel/scheduler.js +23 -21
- package/dist/core/tools/permissions/permission-rules.js +69 -115
- package/dist/core/tools/plugins/loader.js +4 -3
- package/dist/core/tools/router.js +112 -58
- package/dist/core/tools/session.js +64 -102
- package/dist/core/tools/streaming/ToolCallAccumulator.js +1 -3
- package/dist/core/tools/tool-visibility.js +2 -1
- package/dist/core/tools/types.js +10 -0
- package/dist/core/types/batch.js +2 -0
- package/dist/core/utils/error.js +79 -0
- package/dist/core/utils/sanitizer.js +5 -2
- package/dist/core/utils/serialize.js +66 -0
- package/dist/core/utils/zod.js +29 -0
- package/dist/core/verification/detect-runner.js +86 -0
- package/dist/core/verification/runner.js +76 -0
- package/dist/core/version.js +3 -1
- package/dist/core/workspace/capabilities.js +3 -2
- package/dist/integrations/langfuse/litellm-langfuse-outcome-reporter.js +9 -8
- package/dist/languages/python/index.js +154 -0
- package/dist/locales/en.js +8 -1
- package/package.json +2 -1
|
@@ -3,7 +3,7 @@ import { mapErrorForAudit } from '../../../observability/error-mapping.js';
|
|
|
3
3
|
import { ReflectionEngine } from '../../../reflection/engine.js';
|
|
4
4
|
import { resolveExecutionProfile } from '../../../runtime/execution-profile.js';
|
|
5
5
|
import { executeFlowAttempt } from '../../flows/flow-dispatch.js';
|
|
6
|
-
import { resolveAttemptFailure } from './attempt-failure.js';
|
|
6
|
+
import { extractErrorCode, resolveAttemptFailure } from './attempt-failure.js';
|
|
7
7
|
import { buildAuthorizationSummary } from './authorization-summary.js';
|
|
8
8
|
import { mapRetryExhaustedReport, mapSuccessReport, mapTerminalFailureReport, } from './report-mapper.js';
|
|
9
9
|
import { evaluateRetryPolicy } from './retry-policy.js';
|
|
@@ -128,7 +128,6 @@ export class FlowTransactionRunner {
|
|
|
128
128
|
lastRecentReadArtifacts;
|
|
129
129
|
lastToolResultPreviewArtifacts;
|
|
130
130
|
lastReplacementState;
|
|
131
|
-
pendingAutopilotVerification;
|
|
132
131
|
constructor(params) {
|
|
133
132
|
this.params = params;
|
|
134
133
|
this.lastVerifyArtifact = params.options.artifactHints?.verifyArtifact;
|
|
@@ -183,7 +182,6 @@ export class FlowTransactionRunner {
|
|
|
183
182
|
: undefined,
|
|
184
183
|
},
|
|
185
184
|
replacementState: this.lastReplacementState,
|
|
186
|
-
pendingVerification: this.pendingAutopilotVerification,
|
|
187
185
|
lastError: this.currentLastError,
|
|
188
186
|
applyBackRuntime: {
|
|
189
187
|
activeRepoPath: this.params.env.activeRepoPath,
|
|
@@ -212,20 +210,9 @@ export class FlowTransactionRunner {
|
|
|
212
210
|
flowReport: result,
|
|
213
211
|
context: shrinkCtx,
|
|
214
212
|
flowMode: this.params.flowMode,
|
|
213
|
+
verifyPolicy: this.params.options.verifyPolicy,
|
|
215
214
|
});
|
|
216
215
|
lastAttemptFailure = attemptFailure;
|
|
217
|
-
if (this.params.flowMode === 'autopilot') {
|
|
218
|
-
if (attemptFailure?.reasonCode === 'VERIFY_FAILED') {
|
|
219
|
-
this.pendingAutopilotVerification = {
|
|
220
|
-
changedFiles: terminalCtx && 'changedFiles' in terminalCtx
|
|
221
|
-
? (terminalCtx.changedFiles ?? undefined)
|
|
222
|
-
: undefined,
|
|
223
|
-
};
|
|
224
|
-
}
|
|
225
|
-
else if (!attemptFailure) {
|
|
226
|
-
this.pendingAutopilotVerification = undefined;
|
|
227
|
-
}
|
|
228
|
-
}
|
|
229
216
|
const entry = {
|
|
230
217
|
attempt,
|
|
231
218
|
plan: shrinkCtx?.plan ?? null,
|
|
@@ -245,27 +232,24 @@ export class FlowTransactionRunner {
|
|
|
245
232
|
? 'SHRINK'
|
|
246
233
|
: 'APPLY_BACK';
|
|
247
234
|
recordAuditEvent('loop.attempt.success', { attempt, flowMode: this.params.flowMode }, { phase: successPhase, severity: 'low', scope: 'session' });
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
235
|
+
this.emitReflection({
|
|
236
|
+
success: true,
|
|
237
|
+
attempt,
|
|
238
|
+
input: {
|
|
252
239
|
instruction: this.params.options.instruction,
|
|
253
240
|
history: this.historyEntries,
|
|
254
241
|
success: true,
|
|
255
242
|
metadata: shrinkCtx?.context?.projectMetadata,
|
|
256
243
|
finalPlan: shrinkCtx?.plan,
|
|
257
244
|
finalPatch: shrinkCtx?.diff,
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
.reflect(reflectionInput, this.params.options.repoPath)
|
|
261
|
-
.catch((e) => recordAuditEvent('reflection.error', { error: String(e) }, { severity: 'medium' }));
|
|
262
|
-
}
|
|
245
|
+
},
|
|
246
|
+
});
|
|
263
247
|
return mapSuccessReport({
|
|
264
248
|
attempt,
|
|
265
249
|
flowReport: result,
|
|
266
250
|
history: this.historyEntries,
|
|
267
251
|
authorizationSummary: this.authorizationSummary,
|
|
268
|
-
lastErrorCode:
|
|
252
|
+
lastErrorCode: extractErrorCode(result.error),
|
|
269
253
|
lastContext: terminalCtx,
|
|
270
254
|
lastVerifyArtifact: this.lastVerifyArtifact,
|
|
271
255
|
lastSubAgentPatchArtifacts: this.lastSubAgentPatchArtifacts,
|
|
@@ -317,12 +301,20 @@ export class FlowTransactionRunner {
|
|
|
317
301
|
if (retryDecision.retryExhausted) {
|
|
318
302
|
break;
|
|
319
303
|
}
|
|
304
|
+
this.emitReflection({
|
|
305
|
+
success: false,
|
|
306
|
+
input: {
|
|
307
|
+
instruction: this.params.options.instruction,
|
|
308
|
+
history: this.historyEntries,
|
|
309
|
+
success: false,
|
|
310
|
+
},
|
|
311
|
+
});
|
|
320
312
|
return mapTerminalFailureReport({
|
|
321
313
|
attempt,
|
|
322
314
|
flowReport: result,
|
|
323
315
|
history: this.historyEntries,
|
|
324
316
|
authorizationSummary: this.authorizationSummary,
|
|
325
|
-
lastErrorCode: attemptFailure.errorCode ??
|
|
317
|
+
lastErrorCode: attemptFailure.errorCode ?? extractErrorCode(result.error),
|
|
326
318
|
lastContext: terminalCtx,
|
|
327
319
|
lastVerifyArtifact: this.lastVerifyArtifact,
|
|
328
320
|
lastSubAgentPatchArtifacts: this.lastSubAgentPatchArtifacts,
|
|
@@ -333,7 +325,7 @@ export class FlowTransactionRunner {
|
|
|
333
325
|
});
|
|
334
326
|
}
|
|
335
327
|
this.currentContext = shrinkCtx?.context;
|
|
336
|
-
this.currentLastError = attemptFailure.reason;
|
|
328
|
+
this.currentLastError = shrinkCtx?.lastError ?? attemptFailure.reason;
|
|
337
329
|
this.params.emit({
|
|
338
330
|
type: 'retry',
|
|
339
331
|
fromAttempt: attempt,
|
|
@@ -346,13 +338,21 @@ export class FlowTransactionRunner {
|
|
|
346
338
|
if (!lastReport) {
|
|
347
339
|
throw new Error('SalmonLoop execution terminated without a FlowReport');
|
|
348
340
|
}
|
|
341
|
+
this.emitReflection({
|
|
342
|
+
success: false,
|
|
343
|
+
input: {
|
|
344
|
+
instruction: this.params.options.instruction,
|
|
345
|
+
history: this.historyEntries,
|
|
346
|
+
success: false,
|
|
347
|
+
},
|
|
348
|
+
});
|
|
349
349
|
return mapRetryExhaustedReport({
|
|
350
350
|
attempts: retries,
|
|
351
351
|
flowReport: lastReport,
|
|
352
352
|
history: this.historyEntries,
|
|
353
353
|
authorizationSummary: this.authorizationSummary,
|
|
354
354
|
failure: lastAttemptFailure,
|
|
355
|
-
lastErrorCode:
|
|
355
|
+
lastErrorCode: extractErrorCode(lastReport.error),
|
|
356
356
|
lastContext: this.lastContext,
|
|
357
357
|
lastVerifyArtifact: this.lastVerifyArtifact,
|
|
358
358
|
lastSubAgentPatchArtifacts: this.lastSubAgentPatchArtifacts,
|
|
@@ -361,13 +361,19 @@ export class FlowTransactionRunner {
|
|
|
361
361
|
lastToolResultPreviewArtifacts: this.lastToolResultPreviewArtifacts,
|
|
362
362
|
});
|
|
363
363
|
}
|
|
364
|
-
|
|
365
|
-
if (
|
|
366
|
-
return
|
|
367
|
-
|
|
368
|
-
|
|
364
|
+
emitReflection(params) {
|
|
365
|
+
if (!this.params.options.llm)
|
|
366
|
+
return;
|
|
367
|
+
const engine = new ReflectionEngine(this.params.options.llm);
|
|
368
|
+
const { repoPath } = this.params.options;
|
|
369
|
+
const fallback = (e) => recordAuditEvent('reflection.error', { error: String(e) }, { severity: 'medium' });
|
|
370
|
+
if (params.success) {
|
|
371
|
+
const method = (params.attempt ?? 1) > 1 ? 'reflect' : 'reflectOnSuccess';
|
|
372
|
+
engine[method](params.input, repoPath).catch(fallback);
|
|
373
|
+
}
|
|
374
|
+
else {
|
|
375
|
+
engine.reflectOnFailure(params.input, repoPath).catch(fallback);
|
|
369
376
|
}
|
|
370
|
-
return undefined;
|
|
371
377
|
}
|
|
372
378
|
}
|
|
373
379
|
//# sourceMappingURL=transaction-runner.js.map
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import * as path from 'path';
|
|
2
2
|
import * as fs from '../../adapters/fs/node-fs.js';
|
|
3
|
+
import { getLogger } from '../../observability/logger.js';
|
|
3
4
|
/**
|
|
4
5
|
* RejectionManager
|
|
5
6
|
* Handles creation and management of .rej files for failed merges.
|
|
@@ -46,13 +47,14 @@ export class RejectionManager {
|
|
|
46
47
|
...header,
|
|
47
48
|
});
|
|
48
49
|
}
|
|
49
|
-
catch {
|
|
50
|
-
|
|
50
|
+
catch (error) {
|
|
51
|
+
getLogger().debug(`[RejectionManager] Malformed rejection file ${file}: ${error instanceof Error ? error.message : String(error)}`);
|
|
51
52
|
}
|
|
52
53
|
}
|
|
53
54
|
return rejections;
|
|
54
55
|
}
|
|
55
|
-
catch {
|
|
56
|
+
catch (error) {
|
|
57
|
+
getLogger().debug(`[RejectionManager] Failed to read rejection directory: ${error instanceof Error ? error.message : String(error)}`);
|
|
56
58
|
return [];
|
|
57
59
|
}
|
|
58
60
|
}
|
|
@@ -63,8 +65,8 @@ export class RejectionManager {
|
|
|
63
65
|
try {
|
|
64
66
|
await fs.rm(this.rejectDir, { recursive: true, force: true });
|
|
65
67
|
}
|
|
66
|
-
catch {
|
|
67
|
-
|
|
68
|
+
catch (error) {
|
|
69
|
+
getLogger().warn(`[RejectionManager] Failed to clear rejection directory: ${error instanceof Error ? error.message : String(error)}`);
|
|
68
70
|
}
|
|
69
71
|
}
|
|
70
72
|
}
|
|
@@ -2,6 +2,8 @@ import { text } from '../../../locales/index.js';
|
|
|
2
2
|
import { recordAuditEvent } from '../../observability/audit-trail.js';
|
|
3
3
|
import { writeDebugArtifact } from '../../observability/debug-artifacts.js';
|
|
4
4
|
import { buildErrorEnvelope, toSafeErrorSummary } from '../../observability/error-envelope.js';
|
|
5
|
+
import { getLogger } from '../../observability/logger.js';
|
|
6
|
+
import { isRecord } from '../../utils/serialize.js';
|
|
5
7
|
import { collectSidecarPaths } from './apply-back-utils.js';
|
|
6
8
|
export async function runApplyBackPhase(params) {
|
|
7
9
|
const { checkpointRef, initialSnapshotHash, options, synchronizer, activeRepoPath, shadowTaskId, attempt, emit, } = params;
|
|
@@ -89,13 +91,14 @@ export async function runApplyBackPhase(params) {
|
|
|
89
91
|
`safeTelemetry=${JSON.stringify(toSafeTelemetry(applyBackTelemetry), null, 2)}`,
|
|
90
92
|
'',
|
|
91
93
|
`errorType=${error instanceof Error ? error.name : typeof error}`,
|
|
92
|
-
`errorCode=${error
|
|
94
|
+
`errorCode=${isRecord(error) ? (error.code ?? error.llmCode ?? '') : ''}`,
|
|
93
95
|
`errorMessage=${error instanceof Error ? error.message : String(error)}`,
|
|
94
96
|
].join('\n'),
|
|
95
97
|
});
|
|
96
98
|
}
|
|
97
|
-
catch {
|
|
99
|
+
catch (artifactError) {
|
|
98
100
|
// Best-effort: do not mask the primary failure if artifact writing fails.
|
|
101
|
+
getLogger().debug(`[ApplyBackRuntime] Failed to write debug artifact: ${artifactError instanceof Error ? artifactError.message : String(artifactError)}`);
|
|
99
102
|
}
|
|
100
103
|
const envelope = buildErrorEnvelope({
|
|
101
104
|
domain: 'applyBack',
|
|
@@ -10,7 +10,8 @@ export class GitConfigService {
|
|
|
10
10
|
try {
|
|
11
11
|
return await git.exec(['config', '--get', key], { allowError: true });
|
|
12
12
|
}
|
|
13
|
-
catch {
|
|
13
|
+
catch (error) {
|
|
14
|
+
getLogger().debug(`[GitConfigService] git config --get failed for key "${key}": ${error instanceof Error ? error.message : String(error)}`);
|
|
14
15
|
return null;
|
|
15
16
|
}
|
|
16
17
|
};
|
|
@@ -26,5 +26,23 @@ export const registry = {
|
|
|
26
26
|
has(id) {
|
|
27
27
|
return services.has(id);
|
|
28
28
|
},
|
|
29
|
+
/**
|
|
30
|
+
* Unregister a data service by its identifier
|
|
31
|
+
*/
|
|
32
|
+
unregister(id) {
|
|
33
|
+
return services.delete(id);
|
|
34
|
+
},
|
|
35
|
+
/**
|
|
36
|
+
* Clear all registered services (for testing or shutdown)
|
|
37
|
+
*/
|
|
38
|
+
clear() {
|
|
39
|
+
services.clear();
|
|
40
|
+
},
|
|
41
|
+
/**
|
|
42
|
+
* List all registered service IDs
|
|
43
|
+
*/
|
|
44
|
+
list() {
|
|
45
|
+
return Array.from(services.keys());
|
|
46
|
+
},
|
|
29
47
|
};
|
|
30
48
|
//# sourceMappingURL=registry.js.map
|
|
@@ -8,6 +8,8 @@ import { mapErrorForDisplay } from '../../observability/error-mapping.js';
|
|
|
8
8
|
import { getLogger } from '../../observability/logger.js';
|
|
9
9
|
import { getAuditDir } from '../../runtime/paths.js';
|
|
10
10
|
import { SalmonError } from '../../types/errors.js';
|
|
11
|
+
import { errorMessage } from '../../utils/error.js';
|
|
12
|
+
import { isRecord } from '../../utils/serialize.js';
|
|
11
13
|
function replaceRedactedTokens(value) {
|
|
12
14
|
if (value === null || value === undefined)
|
|
13
15
|
return value;
|
|
@@ -43,7 +45,7 @@ export async function saveAudit(report, _options) {
|
|
|
43
45
|
});
|
|
44
46
|
}
|
|
45
47
|
catch (error) {
|
|
46
|
-
const msg =
|
|
48
|
+
const msg = errorMessage(error);
|
|
47
49
|
getLogger().warn(`[Audit] Failed to externalize verify output: ${msg}`);
|
|
48
50
|
recordAuditEvent('audit.blob.externalize.failed', { target: 'verifyResult.output', error: msg.slice(0, 500) }, { source: 'saveAudit', severity: 'low', scope: 'session', phase: 'AUDIT' });
|
|
49
51
|
}
|
|
@@ -55,7 +57,7 @@ export async function saveAudit(report, _options) {
|
|
|
55
57
|
});
|
|
56
58
|
}
|
|
57
59
|
catch (error) {
|
|
58
|
-
const msg =
|
|
60
|
+
const msg = errorMessage(error);
|
|
59
61
|
getLogger().warn(`[Audit] Failed to externalize tool audit summaries: ${msg}`);
|
|
60
62
|
recordAuditEvent('audit.blob.externalize.failed', { target: 'toolAuditLogs.*', error: msg.slice(0, 500) }, { source: 'saveAudit', severity: 'low', scope: 'session', phase: 'AUDIT' });
|
|
61
63
|
}
|
|
@@ -70,7 +72,12 @@ export async function saveAudit(report, _options) {
|
|
|
70
72
|
: errorInfo?.code || errorInfo?.llmCode,
|
|
71
73
|
}
|
|
72
74
|
: report.error
|
|
73
|
-
? {
|
|
75
|
+
? {
|
|
76
|
+
name: 'UnknownError',
|
|
77
|
+
message: String(report.error),
|
|
78
|
+
stack: undefined,
|
|
79
|
+
code: undefined,
|
|
80
|
+
}
|
|
74
81
|
: undefined;
|
|
75
82
|
const mappedErrorMeta = replaceRedactedTokens(errorMeta);
|
|
76
83
|
const errorDisplay = mapErrorForDisplay({
|
|
@@ -130,7 +137,7 @@ export async function saveAudit(report, _options) {
|
|
|
130
137
|
return `${auditDir}/${filename}`;
|
|
131
138
|
}
|
|
132
139
|
catch (error) {
|
|
133
|
-
const msg =
|
|
140
|
+
const msg = errorMessage(error);
|
|
134
141
|
getLogger().error(`[Audit] Failed to save audit log: ${msg}`);
|
|
135
142
|
return undefined;
|
|
136
143
|
}
|
|
@@ -162,7 +169,7 @@ async function writeBlobBestEffort(args) {
|
|
|
162
169
|
return { path: path.join('blobs', blobName), sha256, chars: content.length };
|
|
163
170
|
}
|
|
164
171
|
catch (error) {
|
|
165
|
-
const msg =
|
|
172
|
+
const msg = errorMessage(error);
|
|
166
173
|
getLogger().warn(`[Audit] Failed to write blob ${blobName}: ${msg}`);
|
|
167
174
|
recordAuditEvent('audit.blob.write.failed', {
|
|
168
175
|
target: auditTarget,
|
|
@@ -179,7 +186,7 @@ async function externalizeVerifyOutput(args) {
|
|
|
179
186
|
if (!sanitizedContext)
|
|
180
187
|
return;
|
|
181
188
|
const verifyResult = sanitizedContext.verifyResult;
|
|
182
|
-
if (!verifyResult
|
|
189
|
+
if (!isRecord(verifyResult))
|
|
183
190
|
return;
|
|
184
191
|
const output = verifyResult.output;
|
|
185
192
|
if (typeof output !== 'string')
|
|
@@ -292,15 +299,18 @@ function sanitizeContext(ctx) {
|
|
|
292
299
|
if (typed.applyBackResult)
|
|
293
300
|
safe.applyBackResult = typed.applyBackResult;
|
|
294
301
|
if (typed.toolCallingAudit && Array.isArray(typed.toolCallingAudit)) {
|
|
302
|
+
const KEYS_TO_STRIP = new Set([
|
|
303
|
+
'rawArgsPreview',
|
|
304
|
+
'parsedArgsPreview',
|
|
305
|
+
'toolResultErrorMessage',
|
|
306
|
+
]);
|
|
295
307
|
safe.toolCallingAudit = typed.toolCallingAudit.map((entry) => {
|
|
296
308
|
if (!entry || typeof entry !== 'object')
|
|
297
309
|
return entry;
|
|
298
|
-
const
|
|
299
|
-
const keepArgsPreview = typedEntry.toolResultErrorCode === 'INVALID_INPUT';
|
|
310
|
+
const keepArgsPreview = entry.toolResultErrorCode === 'INVALID_INPUT';
|
|
300
311
|
if (keepArgsPreview)
|
|
301
312
|
return entry;
|
|
302
|
-
|
|
303
|
-
return rest;
|
|
313
|
+
return Object.fromEntries(Object.entries(entry).filter(([k]) => !KEYS_TO_STRIP.has(k)));
|
|
304
314
|
});
|
|
305
315
|
}
|
|
306
316
|
if (typed.toolAuditLogger?.getLogs) {
|
|
@@ -6,6 +6,7 @@ import { GitAdapter } from '../../adapters/git/git-adapter.js';
|
|
|
6
6
|
import { LIMITS } from '../../config/limits.js';
|
|
7
7
|
import { supportsLlmStreaming } from '../../llm/capabilities.js';
|
|
8
8
|
import { emitLlmOutput } from '../../llm/output-policy.js';
|
|
9
|
+
import { getLogger } from '../../observability/logger.js';
|
|
9
10
|
import { getAutopilotSystemPrompt } from '../../prompts/runtime.js';
|
|
10
11
|
import { SessionReplacementPreviewProvider } from '../../session/replacement-preview-provider.js';
|
|
11
12
|
import { chatWithTools, chatWithToolsStreaming } from '../../tools/session.js';
|
|
@@ -286,13 +287,11 @@ function isRuntimeGeneratedPath(path) {
|
|
|
286
287
|
return false;
|
|
287
288
|
}
|
|
288
289
|
function lastFailedToolAuditEntry(entries) {
|
|
289
|
-
if (!Array.isArray(entries))
|
|
290
|
+
if (!Array.isArray(entries) || entries.length === 0)
|
|
290
291
|
return undefined;
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
return entry;
|
|
295
|
-
}
|
|
292
|
+
const last = entries[entries.length - 1];
|
|
293
|
+
if (last?.toolResultStatus && last.toolResultStatus !== 'ok') {
|
|
294
|
+
return last;
|
|
296
295
|
}
|
|
297
296
|
return undefined;
|
|
298
297
|
}
|
|
@@ -370,12 +369,16 @@ export async function runAutopilot(ctx) {
|
|
|
370
369
|
try {
|
|
371
370
|
workspaceFingerprintBefore = await captureWorkspaceFingerprintForContext(ctx);
|
|
372
371
|
}
|
|
373
|
-
catch {
|
|
372
|
+
catch (error) {
|
|
373
|
+
getLogger().debug(`[Autopilot] Workspace fingerprint capture failed (before): ${error instanceof Error ? error.message : String(error)}`);
|
|
374
374
|
samplingFailedClosed = true;
|
|
375
375
|
}
|
|
376
376
|
}
|
|
377
|
-
|
|
378
|
-
|
|
377
|
+
let assistant = null;
|
|
378
|
+
let content = '';
|
|
379
|
+
const messages = shared.baseMessages;
|
|
380
|
+
assistant = supportsTools
|
|
381
|
+
? await (supportsStreaming ? chatWithToolsStreaming : chatWithTools)(messages, {
|
|
379
382
|
phase: AUTOPILOT_TOOL_PHASE,
|
|
380
383
|
providerHints: shared.envelope.providerHints,
|
|
381
384
|
temperature: 0.2,
|
|
@@ -400,7 +403,7 @@ export async function runAutopilot(ctx) {
|
|
|
400
403
|
},
|
|
401
404
|
emit: (event) => ctx.emit({ ...event, timestamp: event.timestamp ?? new Date() }),
|
|
402
405
|
})
|
|
403
|
-
: await llmClient.chat(
|
|
406
|
+
: await llmClient.chat(messages, {
|
|
404
407
|
phase: 'AUTOPILOT',
|
|
405
408
|
providerHints: shared.envelope.providerHints,
|
|
406
409
|
temperature: 0.2,
|
|
@@ -408,7 +411,7 @@ export async function runAutopilot(ctx) {
|
|
|
408
411
|
tools: [],
|
|
409
412
|
toolChoice: 'none',
|
|
410
413
|
});
|
|
411
|
-
|
|
414
|
+
content = String(assistant?.content ?? '').trim();
|
|
412
415
|
if (!supportsTools) {
|
|
413
416
|
emitLlmOutput({
|
|
414
417
|
emit: ctx.emit,
|
|
@@ -435,28 +438,18 @@ export async function runAutopilot(ctx) {
|
|
|
435
438
|
workspaceFingerprintBefore.head !== workspaceFingerprintAfter.head ||
|
|
436
439
|
workspaceFingerprintBefore.index !== workspaceFingerprintAfter.index;
|
|
437
440
|
}
|
|
438
|
-
catch {
|
|
441
|
+
catch (error) {
|
|
442
|
+
getLogger().debug(`[Autopilot] Workspace fingerprint capture failed (after): ${error instanceof Error ? error.message : String(error)}`);
|
|
439
443
|
mutated = true;
|
|
440
444
|
}
|
|
441
445
|
}
|
|
442
446
|
}
|
|
443
|
-
const
|
|
444
|
-
? ctx.pendingVerification.changedFiles
|
|
445
|
-
: undefined;
|
|
446
|
-
const effectiveChangedFiles = changedFiles && changedFiles.length > 0
|
|
447
|
-
? changedFiles
|
|
448
|
-
: pendingChangedFiles && pendingChangedFiles.length > 0
|
|
449
|
-
? pendingChangedFiles
|
|
450
|
-
: undefined;
|
|
451
|
-
const effectiveMutated = mutated || Boolean(ctx.pendingVerification);
|
|
447
|
+
const effectiveChangedFiles = changedFiles && changedFiles.length > 0 ? changedFiles : undefined;
|
|
452
448
|
return {
|
|
453
449
|
...ctx,
|
|
454
|
-
mutated
|
|
450
|
+
mutated,
|
|
455
451
|
changedFiles: effectiveChangedFiles,
|
|
456
|
-
|
|
457
|
-
? { changedFiles: effectiveChangedFiles }
|
|
458
|
-
: ctx.pendingVerification,
|
|
459
|
-
completion: resolveAutopilotCompletion({ content, mutated: effectiveMutated, localAudit }),
|
|
452
|
+
completion: resolveAutopilotCompletion({ content, mutated, localAudit }),
|
|
460
453
|
toolCallingAudit: mergedAudit,
|
|
461
454
|
report: {
|
|
462
455
|
kind: 'answer',
|
|
@@ -473,13 +466,10 @@ export async function runAutopilotVerifyGate(ctx) {
|
|
|
473
466
|
};
|
|
474
467
|
}
|
|
475
468
|
if (!ctx.options.verify) {
|
|
469
|
+
// Autopilot is LLM-driven: the agent verifies on its own via shell.exec.
|
|
470
|
+
// Skip the gate instead of failing — the agent's tool calls are the verification.
|
|
476
471
|
return {
|
|
477
472
|
...ctx,
|
|
478
|
-
completion: {
|
|
479
|
-
status: 'verification_missing',
|
|
480
|
-
reason: 'Autopilot changed the workspace but no verification command was configured.',
|
|
481
|
-
errorCode: 'VERIFY_COMMAND_MISSING',
|
|
482
|
-
},
|
|
483
473
|
verifyResult: undefined,
|
|
484
474
|
};
|
|
485
475
|
}
|
|
@@ -491,7 +481,6 @@ export async function runAutopilotVerifyGate(ctx) {
|
|
|
491
481
|
const nextCtx = {
|
|
492
482
|
...ctx,
|
|
493
483
|
verifyResult,
|
|
494
|
-
pendingVerification: verifyResult.ok ? undefined : ctx.pendingVerification,
|
|
495
484
|
};
|
|
496
485
|
return verifyArtifact ? { ...nextCtx, verifyArtifact } : nextCtx;
|
|
497
486
|
}
|
|
@@ -1,18 +1,11 @@
|
|
|
1
1
|
import { text } from '../../../locales/index.js';
|
|
2
2
|
import { SalmonError } from '../../types/errors.js';
|
|
3
|
+
import { safeStringify } from '../../utils/serialize.js';
|
|
3
4
|
export class ReportContextMissingError extends SalmonError {
|
|
4
5
|
constructor(message) {
|
|
5
6
|
super(message, 'REPORT_CONTEXT_MISSING');
|
|
6
7
|
}
|
|
7
8
|
}
|
|
8
|
-
function safeStringify(value) {
|
|
9
|
-
try {
|
|
10
|
-
return JSON.stringify(value, null, 2);
|
|
11
|
-
}
|
|
12
|
-
catch {
|
|
13
|
-
return String(value);
|
|
14
|
-
}
|
|
15
|
-
}
|
|
16
9
|
function removeLeadingSpaces(content) {
|
|
17
10
|
const lines = content.split('\n');
|
|
18
11
|
const minIndent = lines
|
|
@@ -40,7 +33,7 @@ function normalizeSuggestions(input) {
|
|
|
40
33
|
}
|
|
41
34
|
if (isReviewSuggestion(item)) {
|
|
42
35
|
const type = typeof item.type === 'string' ? item.type : 'note';
|
|
43
|
-
const content = typeof item.content === 'string' ? item.content : safeStringify(item);
|
|
36
|
+
const content = typeof item.content === 'string' ? item.content : safeStringify(item, { indent: 2 });
|
|
44
37
|
return { type, content };
|
|
45
38
|
}
|
|
46
39
|
return { type: 'note', content: String(item) };
|
|
@@ -51,10 +44,10 @@ function normalizeSuggestions(input) {
|
|
|
51
44
|
}
|
|
52
45
|
if (isReviewSuggestion(input)) {
|
|
53
46
|
const type = typeof input.type === 'string' ? input.type : 'note';
|
|
54
|
-
const content = typeof input.content === 'string' ? input.content : safeStringify(input);
|
|
47
|
+
const content = typeof input.content === 'string' ? input.content : safeStringify(input, { indent: 2 });
|
|
55
48
|
return [{ type, content }];
|
|
56
49
|
}
|
|
57
|
-
return [{ type: 'note', content: safeStringify(input) }];
|
|
50
|
+
return [{ type: 'note', content: safeStringify(input, { indent: 2 }) }];
|
|
58
51
|
}
|
|
59
52
|
export async function displayReport(ctx) {
|
|
60
53
|
if (!ctx.report || !ctx.report.kind) {
|
|
@@ -2,12 +2,14 @@ import path from 'path';
|
|
|
2
2
|
import { text } from '../../../locales/index.js';
|
|
3
3
|
import { supportsLlmStreaming } from '../../llm/capabilities.js';
|
|
4
4
|
import { recordAuditEvent } from '../../observability/audit-trail.js';
|
|
5
|
+
import { getLogger } from '../../observability/logger.js';
|
|
5
6
|
import { getExplorePrompt, getExploreSystemPrompt } from '../../prompts/runtime.js';
|
|
6
7
|
import { SessionReplacementPreviewProvider } from '../../session/replacement-preview-provider.js';
|
|
7
8
|
import { chatWithTools, chatWithToolsStreaming } from '../../tools/session.js';
|
|
8
9
|
import { SalmonError } from '../../types/errors.js';
|
|
9
10
|
import { Phase } from '../../types/runtime.js';
|
|
10
11
|
import { ensureInSandbox, isSafeRelativePath, normalizePath } from '../../utils/path.js';
|
|
12
|
+
import { isRecord } from '../../utils/serialize.js';
|
|
11
13
|
import { resolveLlmToolCallingPolicy } from '../dsl/llm-strategy.js';
|
|
12
14
|
import { ContextValidator } from '../validation/ContextValidator.js';
|
|
13
15
|
import { buildPhaseRequestEnvelope } from './request-assembly.js';
|
|
@@ -103,7 +105,11 @@ export const exploreCodebase = async (ctx) => {
|
|
|
103
105
|
// Intercept tools with READ intent
|
|
104
106
|
if (intent === 'READ' && result.status === 'ok') {
|
|
105
107
|
const output = result.output;
|
|
106
|
-
const content = typeof output === 'string'
|
|
108
|
+
const content = typeof output === 'string'
|
|
109
|
+
? output
|
|
110
|
+
: isRecord(output) && typeof output.content === 'string'
|
|
111
|
+
? output.content
|
|
112
|
+
: undefined;
|
|
107
113
|
if (typeof content === 'string') {
|
|
108
114
|
try {
|
|
109
115
|
// Attempt to parse arguments to get the file path
|
|
@@ -114,8 +120,9 @@ export const exploreCodebase = async (ctx) => {
|
|
|
114
120
|
capturedFiles.set(filePath, content);
|
|
115
121
|
}
|
|
116
122
|
}
|
|
117
|
-
catch {
|
|
123
|
+
catch (error) {
|
|
118
124
|
// Ignore parsing errors, just don't capture
|
|
125
|
+
getLogger().debug(`[Explore] Failed to parse tool arguments for file capture: ${error instanceof Error ? error.message : String(error)}`);
|
|
119
126
|
}
|
|
120
127
|
}
|
|
121
128
|
}
|
|
@@ -191,15 +198,18 @@ export const exploreCodebase = async (ctx) => {
|
|
|
191
198
|
capturedFiles.set(rel, content);
|
|
192
199
|
}
|
|
193
200
|
}
|
|
194
|
-
catch {
|
|
201
|
+
catch (error) {
|
|
195
202
|
// Best-effort; failure here should not abort exploration.
|
|
203
|
+
getLogger().debug(`[Explore] Failed to read inferred file "${rel}": ${error instanceof Error ? error.message : String(error)}`);
|
|
196
204
|
}
|
|
197
205
|
}
|
|
198
206
|
}
|
|
199
207
|
// Validation: Check for exploration consistency using ContextValidator on LOCAL audit
|
|
200
208
|
const validation = ContextValidator.validateExploration(localAudit, capturedFiles.size);
|
|
201
209
|
if (!validation.isValid) {
|
|
202
|
-
const
|
|
210
|
+
const validationMessages = text.grizzco.validation;
|
|
211
|
+
const raw = validation.errorCode ? validationMessages[validation.errorCode] : undefined;
|
|
212
|
+
const msg = typeof raw === 'string' ? raw : (validation.errorCode ?? 'unknown');
|
|
203
213
|
ctx.emit({
|
|
204
214
|
type: 'log',
|
|
205
215
|
level: 'error',
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { text } from '../../../locales/index.js';
|
|
2
2
|
import { emitLlmOutput } from '../../llm/output-policy.js';
|
|
3
|
+
import { getLogger } from '../../observability/logger.js';
|
|
3
4
|
import { getReviewPrompt } from '../../prompts/runtime.js';
|
|
4
5
|
function normalizeReviewSuggestions(value) {
|
|
5
6
|
if (value == null)
|
|
@@ -23,7 +24,8 @@ function parseReviewResponse(content) {
|
|
|
23
24
|
try {
|
|
24
25
|
return normalizeReviewSuggestions(JSON.parse(content));
|
|
25
26
|
}
|
|
26
|
-
catch {
|
|
27
|
+
catch (error) {
|
|
28
|
+
getLogger().debug(`[GenerateReview] Failed to parse review response as JSON: ${error instanceof Error ? error.message : String(error)}`);
|
|
27
29
|
return normalizeReviewSuggestions(content);
|
|
28
30
|
}
|
|
29
31
|
}
|
|
@@ -5,9 +5,12 @@ import { Phase } from '../../../types/runtime.js';
|
|
|
5
5
|
import { buildPhaseRequestEnvelope } from '../request-assembly.js';
|
|
6
6
|
export async function buildPatchPromptInput(args) {
|
|
7
7
|
const planStr = JSON.stringify(args.plan, null, 2);
|
|
8
|
-
const
|
|
8
|
+
const baseSystemPrompt = await getPatchSystemPrompt(args.promptVisibleTools, {
|
|
9
9
|
plan: args.planRuntime,
|
|
10
10
|
});
|
|
11
|
+
const systemPrompt = args.subAgentSystemPrompt
|
|
12
|
+
? [baseSystemPrompt, args.subAgentSystemPrompt]
|
|
13
|
+
: baseSystemPrompt;
|
|
11
14
|
const requestEnvelope = await buildPhaseRequestEnvelope({
|
|
12
15
|
phase: args.phase ?? Phase.PATCH,
|
|
13
16
|
defaultNamespace: 'patch',
|
|
@@ -95,6 +95,7 @@ export const generatePatch = async (ctx) => {
|
|
|
95
95
|
artifactHints: ctx.artifactHints,
|
|
96
96
|
replacementState: ctx.replacementState,
|
|
97
97
|
toolCallingAudit: ctx.toolCallingAudit,
|
|
98
|
+
subAgentSystemPrompt: ctx.options.subAgentSystemPrompt,
|
|
98
99
|
});
|
|
99
100
|
const { cacheSurface, envelope, baseMessages } = patchPromptInput;
|
|
100
101
|
const supportsStreaming = supportsLlmStreaming(ctx.options.llm, Phase.PATCH);
|