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
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
*
|
|
10
10
|
* Based on best practices from LangChain, OpenAI Realtime API, and Voice AI systems.
|
|
11
11
|
*/
|
|
12
|
-
import {
|
|
12
|
+
import { tryGetLogger } from '../../observability/logger.js';
|
|
13
13
|
import { buildIncrementalSummaryPrompt, truncateSummary } from './prompts.js';
|
|
14
14
|
import { DEFAULT_SUMMARIZATION_CONFIG } from './types.js';
|
|
15
15
|
/**
|
|
@@ -49,6 +49,7 @@ export class ConversationSummarizer {
|
|
|
49
49
|
summaryVersion: 2,
|
|
50
50
|
structuredState: this.createEmptyStructuredState(),
|
|
51
51
|
contextHash: undefined,
|
|
52
|
+
recoveryState: undefined,
|
|
52
53
|
};
|
|
53
54
|
}
|
|
54
55
|
// ==================== Lifecycle ====================
|
|
@@ -57,7 +58,7 @@ export class ConversationSummarizer {
|
|
|
57
58
|
*/
|
|
58
59
|
async initialize() {
|
|
59
60
|
this.initialized = true;
|
|
60
|
-
|
|
61
|
+
tryGetLogger()?.debug('[Summarizer] Initialized');
|
|
61
62
|
}
|
|
62
63
|
/**
|
|
63
64
|
* Dispose resources.
|
|
@@ -77,10 +78,9 @@ export class ConversationSummarizer {
|
|
|
77
78
|
summarizedMessageIds: [...this.state.summarizedMessageIds],
|
|
78
79
|
lastSummarizedAt: this.state.lastSummarizedAt,
|
|
79
80
|
summaryVersion: this.state.summaryVersion,
|
|
80
|
-
structuredState: this.state.structuredState
|
|
81
|
-
? { ...this.state.structuredState }
|
|
82
|
-
: this.createEmptyStructuredState(),
|
|
81
|
+
structuredState: this.cloneStructuredState(this.state.structuredState),
|
|
83
82
|
contextHash: this.state.contextHash,
|
|
83
|
+
recoveryState: this.cloneRecoveryState(this.state.recoveryState),
|
|
84
84
|
};
|
|
85
85
|
}
|
|
86
86
|
/**
|
|
@@ -97,8 +97,9 @@ export class ConversationSummarizer {
|
|
|
97
97
|
? this.normalizeStructuredState(state.structuredState)
|
|
98
98
|
: this.createEmptyStructuredState(),
|
|
99
99
|
contextHash: state.contextHash,
|
|
100
|
+
recoveryState: this.cloneRecoveryState(state.recoveryState),
|
|
100
101
|
};
|
|
101
|
-
|
|
102
|
+
tryGetLogger()?.debug(`[Summarizer] Restored state with ${state.summarizedMessageIds.length} summarized messages`);
|
|
102
103
|
}
|
|
103
104
|
/**
|
|
104
105
|
* Reset summarizer state.
|
|
@@ -112,6 +113,7 @@ export class ConversationSummarizer {
|
|
|
112
113
|
summaryVersion: 2,
|
|
113
114
|
structuredState: this.createEmptyStructuredState(),
|
|
114
115
|
contextHash: undefined,
|
|
116
|
+
recoveryState: undefined,
|
|
115
117
|
};
|
|
116
118
|
this.summaryInProgress = false;
|
|
117
119
|
}
|
|
@@ -189,7 +191,7 @@ export class ConversationSummarizer {
|
|
|
189
191
|
*/
|
|
190
192
|
async triggerSummarization(messages, contextHash) {
|
|
191
193
|
if (this.summaryInProgress) {
|
|
192
|
-
|
|
194
|
+
tryGetLogger()?.debug('[Summarizer] Summary already in progress, skipping');
|
|
193
195
|
return null;
|
|
194
196
|
}
|
|
195
197
|
this.ensureStateAligned(contextHash);
|
|
@@ -200,7 +202,7 @@ export class ConversationSummarizer {
|
|
|
200
202
|
// Fire and forget
|
|
201
203
|
this.runSummarization(messages, contextHash).catch((err) => {
|
|
202
204
|
const errMsg = err instanceof Error ? err.message : String(err);
|
|
203
|
-
|
|
205
|
+
tryGetLogger()?.warn(`[Summarizer] Async summarization failed: ${errMsg}`);
|
|
204
206
|
});
|
|
205
207
|
return null;
|
|
206
208
|
}
|
|
@@ -269,7 +271,7 @@ export class ConversationSummarizer {
|
|
|
269
271
|
this.state.summarizedMessageIds.push(msg.id);
|
|
270
272
|
}
|
|
271
273
|
this.state.lastSummarizedAt = Date.now();
|
|
272
|
-
|
|
274
|
+
tryGetLogger()?.info(`[Summarizer] Summarized ${batch.length} messages, ` +
|
|
273
275
|
`reduced ${beforeTokens} → ${this.state.summaryTokens} tokens`);
|
|
274
276
|
return {
|
|
275
277
|
summary: newSummary,
|
|
@@ -281,7 +283,7 @@ export class ConversationSummarizer {
|
|
|
281
283
|
};
|
|
282
284
|
}
|
|
283
285
|
catch (error) {
|
|
284
|
-
|
|
286
|
+
tryGetLogger()?.error('[Summarizer] Summarization failed', error);
|
|
285
287
|
throw error;
|
|
286
288
|
}
|
|
287
289
|
finally {
|
|
@@ -306,7 +308,7 @@ export class ConversationSummarizer {
|
|
|
306
308
|
return;
|
|
307
309
|
if (!this.state.contextHash || this.state.contextHash === contextHash)
|
|
308
310
|
return;
|
|
309
|
-
|
|
311
|
+
tryGetLogger()?.warn(`[Summarizer] Context hash changed (${this.state.contextHash} -> ${contextHash}), rebuilding summary state`);
|
|
310
312
|
this.state.summary = '';
|
|
311
313
|
this.state.summaryTokens = 0;
|
|
312
314
|
this.state.summarizedMessageIds = [];
|
|
@@ -327,7 +329,7 @@ export class ConversationSummarizer {
|
|
|
327
329
|
}
|
|
328
330
|
catch (error) {
|
|
329
331
|
const errMsg = error instanceof Error ? error.message : String(error);
|
|
330
|
-
|
|
332
|
+
tryGetLogger()?.warn(`[Summarizer] Failed to parse structured summary state: ${errMsg}`);
|
|
331
333
|
return { summary, structuredState: this.createEmptyStructuredState() };
|
|
332
334
|
}
|
|
333
335
|
}
|
|
@@ -346,6 +348,47 @@ export class ConversationSummarizer {
|
|
|
346
348
|
normalized.owner = this.ensureStringArray(source.owner);
|
|
347
349
|
return normalized;
|
|
348
350
|
}
|
|
351
|
+
cloneStructuredState(state) {
|
|
352
|
+
if (!state)
|
|
353
|
+
return this.createEmptyStructuredState();
|
|
354
|
+
return {
|
|
355
|
+
decisions: [...state.decisions],
|
|
356
|
+
constraints: [...state.constraints],
|
|
357
|
+
open_questions: [...state.open_questions],
|
|
358
|
+
pending_tasks: [...state.pending_tasks],
|
|
359
|
+
rejected_options: [...state.rejected_options],
|
|
360
|
+
assumptions: [...state.assumptions],
|
|
361
|
+
risks: [...state.risks],
|
|
362
|
+
owner: [...state.owner],
|
|
363
|
+
};
|
|
364
|
+
}
|
|
365
|
+
cloneRecoveryFailureSummary(value) {
|
|
366
|
+
if (!value)
|
|
367
|
+
return undefined;
|
|
368
|
+
return {
|
|
369
|
+
reasonCode: value.reasonCode,
|
|
370
|
+
diagnosticCode: value.diagnosticCode,
|
|
371
|
+
safeHint: value.safeHint,
|
|
372
|
+
failurePhase: value.failurePhase,
|
|
373
|
+
};
|
|
374
|
+
}
|
|
375
|
+
cloneRecoveryState(state) {
|
|
376
|
+
if (!state)
|
|
377
|
+
return undefined;
|
|
378
|
+
const flowMode = typeof state.flowMode === 'string' ? state.flowMode : undefined;
|
|
379
|
+
const recentReadFiles = Array.isArray(state.recentReadFiles)
|
|
380
|
+
? state.recentReadFiles.filter((item) => typeof item === 'string')
|
|
381
|
+
: undefined;
|
|
382
|
+
const next = {};
|
|
383
|
+
if (flowMode)
|
|
384
|
+
next.flowMode = flowMode;
|
|
385
|
+
const lastFailureSummary = this.cloneRecoveryFailureSummary(state.lastFailureSummary);
|
|
386
|
+
if (lastFailureSummary)
|
|
387
|
+
next.lastFailureSummary = lastFailureSummary;
|
|
388
|
+
if (recentReadFiles && recentReadFiles.length > 0)
|
|
389
|
+
next.recentReadFiles = [...recentReadFiles];
|
|
390
|
+
return Object.keys(next).length > 0 ? next : undefined;
|
|
391
|
+
}
|
|
349
392
|
ensureStringArray(value) {
|
|
350
393
|
if (!Array.isArray(value))
|
|
351
394
|
return [];
|
|
@@ -387,9 +387,6 @@ export class TargetResolver {
|
|
|
387
387
|
debugLabel: 'context-targeting',
|
|
388
388
|
maxRounds: 5,
|
|
389
389
|
resolveData: async (ctx, key) => {
|
|
390
|
-
if (!ctx.primaryFile) {
|
|
391
|
-
return [];
|
|
392
|
-
}
|
|
393
390
|
if (key === 'explicitTargets') {
|
|
394
391
|
const primary = buildPrimaryTarget(ctx.primaryFile);
|
|
395
392
|
const explicit = buildExplicitTargets(req);
|
|
@@ -401,6 +398,8 @@ export class TargetResolver {
|
|
|
401
398
|
return dedupeTargets([...primary, ...diff]);
|
|
402
399
|
}
|
|
403
400
|
if (key === 'symbolTargets') {
|
|
401
|
+
if (!ctx.primaryFile)
|
|
402
|
+
return [];
|
|
404
403
|
const primary = buildPrimaryTarget(ctx.primaryFile);
|
|
405
404
|
const res = buildSymbolTargets({
|
|
406
405
|
primaryFile: ctx.primaryFile,
|
|
@@ -420,6 +419,8 @@ export class TargetResolver {
|
|
|
420
419
|
const combined = dedupeTargets([...primary, ...imports, ...rg]);
|
|
421
420
|
if (combined.length > 0)
|
|
422
421
|
return combined;
|
|
422
|
+
if (!ctx.primaryFile)
|
|
423
|
+
return [];
|
|
423
424
|
return [
|
|
424
425
|
{
|
|
425
426
|
path: ctx.primaryFile,
|
|
@@ -434,7 +435,6 @@ export class TargetResolver {
|
|
|
434
435
|
strategy: (engine) => {
|
|
435
436
|
return engine
|
|
436
437
|
.phase('Dependencies')
|
|
437
|
-
.require((c) => Boolean(c.primaryFile), 'No primary file provided')
|
|
438
438
|
.requireData(['explicitTargets', 'symbolTargets', 'diffTargets', 'defaultTargets'])
|
|
439
439
|
.phase('Selection')
|
|
440
440
|
.when((c) => (c.data?.explicitTargets || []).some((t) => t.reason === 'explicit_path'), (p) => {
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import { getLogger } from '../observability/logger.js';
|
|
1
3
|
import { loadConfig } from './load.js';
|
|
2
4
|
import { mergeScopedEntries } from './merge.js';
|
|
3
|
-
import { expandHome, getRepoMcpConfigPath, getRepoSkillConfigPath, getRepoToolConfigPath, getUserMcpConfigPath, getUserSkillConfigPath, getUserToolConfigPath, resolveRepoRelative, resolveUserRelative, } from './paths.js';
|
|
5
|
+
import { expandHome, getRepoMcpConfigPath, getRepoSkillConfigPath, getRepoToolConfigPath, getUserMcpConfigPath, getUserSkillConfigPath, getUserToolConfigPath, isWithinRoot, resolveRepoRelative, resolveUserRelative, } from './paths.js';
|
|
4
6
|
import { redactExtensions } from './redact.js';
|
|
5
7
|
import { McpConfigSchema, SkillsConfigSchema, ToolsConfigSchema } from './schemas.js';
|
|
6
8
|
function defaultEnabled(scope) {
|
|
@@ -63,16 +65,33 @@ function buildResolvedPlugins(entries, repoRoot) {
|
|
|
63
65
|
function buildResolvedSkills(user, repo, repoRoot) {
|
|
64
66
|
const repoDiscovery = repo?.discovery;
|
|
65
67
|
const userDiscovery = user?.discovery;
|
|
66
|
-
const useDefaults = repoDiscovery?.useDefaults ?? userDiscovery?.useDefaults ?? true;
|
|
67
68
|
const repoPaths = repoDiscovery && Array.isArray(repoDiscovery.paths) ? repoDiscovery.paths : undefined;
|
|
68
69
|
const userPaths = userDiscovery && Array.isArray(userDiscovery.paths) ? userDiscovery.paths : undefined;
|
|
69
70
|
let scope = 'repo';
|
|
70
71
|
let paths = [];
|
|
71
72
|
if (repoPaths && repoPaths.length > 0) {
|
|
72
73
|
scope = 'repo';
|
|
74
|
+
const root = repoRoot ?? '';
|
|
73
75
|
paths = repoPaths
|
|
74
|
-
.
|
|
75
|
-
|
|
76
|
+
.filter((raw) => {
|
|
77
|
+
// Reject absolute paths in repo scope — only user-level config may specify them
|
|
78
|
+
const expanded = expandHome(raw);
|
|
79
|
+
if (path.isAbsolute(expanded)) {
|
|
80
|
+
getLogger().audit('SKILL_PATH_REJECTED', { path: raw, repoRoot: root, reason: 'absolute_path_in_repo_scope' }, { source: 'skill-loader', severity: 'high', scope: 'repo' });
|
|
81
|
+
return false;
|
|
82
|
+
}
|
|
83
|
+
return true;
|
|
84
|
+
})
|
|
85
|
+
.map((value) => resolvePathForScope(value, 'repo', root))
|
|
86
|
+
.filter((p) => Boolean(p))
|
|
87
|
+
.filter((p) => {
|
|
88
|
+
// Validate resolved paths stay within repo root
|
|
89
|
+
if (!isWithinRoot(p, root)) {
|
|
90
|
+
getLogger().audit('SKILL_PATH_REJECTED', { path: p, repoRoot: root, reason: 'outside_repo_root' }, { source: 'skill-loader', severity: 'high', scope: 'repo' });
|
|
91
|
+
return false;
|
|
92
|
+
}
|
|
93
|
+
return true;
|
|
94
|
+
});
|
|
76
95
|
}
|
|
77
96
|
else if (userPaths && userPaths.length > 0) {
|
|
78
97
|
scope = 'user';
|
|
@@ -81,7 +100,6 @@ function buildResolvedSkills(user, repo, repoRoot) {
|
|
|
81
100
|
.filter((p) => Boolean(p));
|
|
82
101
|
}
|
|
83
102
|
return {
|
|
84
|
-
useDefaults,
|
|
85
103
|
paths,
|
|
86
104
|
scope,
|
|
87
105
|
};
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import os from 'node:os';
|
|
2
2
|
import path from 'node:path';
|
|
3
|
+
import { realpathSync } from '../adapters/fs/node-fs.js';
|
|
4
|
+
import { tryGetLogger } from '../observability/logger.js';
|
|
3
5
|
export const REPO_CONFIG_DIR = '.salmonloop/config';
|
|
4
6
|
export const USER_CONFIG_DIR = path.join(os.homedir(), '.salmonloop', 'config');
|
|
5
7
|
export function expandHome(value) {
|
|
@@ -37,4 +39,33 @@ export function getUserToolConfigPath() {
|
|
|
37
39
|
export function getUserSkillConfigPath() {
|
|
38
40
|
return path.join(USER_CONFIG_DIR, 'skills-user.json');
|
|
39
41
|
}
|
|
42
|
+
/**
|
|
43
|
+
* Check whether a candidate path resides within (or equals) a given root directory.
|
|
44
|
+
*
|
|
45
|
+
* Uses realpath resolution to detect symlink-based escapes when both paths exist.
|
|
46
|
+
* When the candidate does not yet exist on disk (e.g. configured before the
|
|
47
|
+
* directory is created), falls back to a lexical containment check on the
|
|
48
|
+
* resolved (but not realpath'd) path. This avoids silently discarding valid
|
|
49
|
+
* future paths while still catching traversal attacks on existing paths.
|
|
50
|
+
*
|
|
51
|
+
* @returns true when the resolved candidate is the root itself or a descendant;
|
|
52
|
+
* false when the path escapes the root.
|
|
53
|
+
*/
|
|
54
|
+
export function isWithinRoot(candidate, root) {
|
|
55
|
+
const resolvedCandidate = path.resolve(candidate);
|
|
56
|
+
const resolvedRoot = path.resolve(root);
|
|
57
|
+
try {
|
|
58
|
+
// Happy path: both exist — use realpath to resolve symlinks
|
|
59
|
+
const realCandidate = realpathSync(resolvedCandidate);
|
|
60
|
+
const realRoot = realpathSync(resolvedRoot);
|
|
61
|
+
return realCandidate === realRoot || realCandidate.startsWith(realRoot + path.sep);
|
|
62
|
+
}
|
|
63
|
+
catch {
|
|
64
|
+
// Candidate or root does not exist yet — fall back to lexical check.
|
|
65
|
+
// This allows pre-declaring paths that will be created later, while
|
|
66
|
+
// still catching obvious traversal sequences like `../../etc`.
|
|
67
|
+
tryGetLogger()?.debug(`isWithinRoot: path not on disk, using lexical check for "${candidate}" against root "${root}"`);
|
|
68
|
+
return (resolvedCandidate === resolvedRoot || resolvedCandidate.startsWith(resolvedRoot + path.sep));
|
|
69
|
+
}
|
|
70
|
+
}
|
|
40
71
|
//# sourceMappingURL=paths.js.map
|
|
@@ -59,12 +59,15 @@ export const ToolsConfigSchema = z.object({
|
|
|
59
59
|
version: z.literal(1),
|
|
60
60
|
plugins: z.record(z.string(), toolPluginSchema).optional().default({}),
|
|
61
61
|
});
|
|
62
|
-
const skillDiscoverySchema = z
|
|
63
|
-
|
|
62
|
+
const skillDiscoverySchema = z
|
|
63
|
+
.object({
|
|
64
64
|
paths: z.array(z.string()).optional(),
|
|
65
|
-
})
|
|
66
|
-
|
|
65
|
+
})
|
|
66
|
+
.strict();
|
|
67
|
+
export const SkillsConfigSchema = z
|
|
68
|
+
.object({
|
|
67
69
|
version: z.literal(1),
|
|
68
70
|
discovery: skillDiscoverySchema.optional().default({}),
|
|
69
|
-
})
|
|
71
|
+
})
|
|
72
|
+
.strict();
|
|
70
73
|
//# sourceMappingURL=schemas.js.map
|
|
@@ -3,9 +3,13 @@ export { routeChatIntent } from '../intent/chat-intent.js';
|
|
|
3
3
|
export { DEFAULT_LLM_OUTPUT_POLICY, emitLlmOutput } from '../llm/output-policy.js';
|
|
4
4
|
export { logIgnoredError } from '../observability/ignored-error.js';
|
|
5
5
|
export { getLogger } from '../observability/logger.js';
|
|
6
|
+
export { resolveExecutionProfile } from '../runtime/execution-profile.js';
|
|
6
7
|
export { runSalmonLoop } from '../runtime/loop.js';
|
|
8
|
+
export { buildSessionArtifactStateFromLoopResult } from '../session/artifact-state.js';
|
|
7
9
|
export { ChatSessionManager } from '../session/manager.js';
|
|
8
|
-
export {
|
|
9
|
-
export { refreshSessionSummary } from '../session/summary-sync.js';
|
|
10
|
+
export { getDefaultSessionContextBudgetTokens } from '../session/session-context-builder.js';
|
|
11
|
+
export { buildEffectiveConversationContext, refreshSessionSummary, } from '../session/summary-sync.js';
|
|
12
|
+
export { createInitialTracking, onNormalTurnComplete } from '../session/compaction/tracking.js';
|
|
13
|
+
export { runCompactionPipeline, reactiveCompact } from '../session/compaction/index.js';
|
|
10
14
|
export { TokenTracker } from '../session/token-tracker.js';
|
|
11
15
|
//# sourceMappingURL=cli-chat.js.map
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
export { normalizePermissionMode, resolveConfig } from '../config/index.js';
|
|
1
|
+
export { ConfigError, normalizePermissionMode, resolveConfig } from '../config/index.js';
|
|
2
2
|
export { ExtensionConfigError, resolveExtensions } from '../extensions/index.js';
|
|
3
3
|
export { createRuntimeLlm } from '../llm/factory.js';
|
|
4
4
|
export { getLogger } from '../observability/logger.js';
|
|
5
5
|
export { PluginLoader } from '../plugin/loader.js';
|
|
6
|
+
export { resolveExecutionProfile } from '../runtime/execution-profile.js';
|
|
6
7
|
export { clearPluginRegistry, createPluginRegistry, setPluginRegistry, } from '../plugin/registry.js';
|
|
7
8
|
export { clearPromptRegistry, createPromptRegistry, setPromptRegistry, } from '../prompts/registry.js';
|
|
8
9
|
//# sourceMappingURL=cli-command-chat.js.map
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
export { resolveExtensions } from '../extensions/index.js';
|
|
1
2
|
export { getLogger } from '../observability/logger.js';
|
|
2
3
|
export { skillToToolSpec } from '../skills/bridge.js';
|
|
4
|
+
export { SkillLoader } from '../skills/loader.js';
|
|
3
5
|
export { SkillParser } from '../skills/parser.js';
|
|
4
6
|
export { registerAllBuiltins } from '../tools/builtin/index.js';
|
|
5
7
|
export { ToolRegistry } from '../tools/registry.js';
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export { defaultPathAdapter } from '../adapters/path/path-adapter.js';
|
|
2
|
+
export { ConfigError } from '../config/index.js';
|
|
2
3
|
export { resolveConfig } from '../config/resolve.js';
|
|
3
4
|
export { createContextCacheStore } from '../context/cache/store-factory.js';
|
|
4
5
|
export { ContextService } from '../context/index.js';
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
export { normalizePermissionMode } from '../config/index.js';
|
|
2
|
-
export { getLogger } from '../observability/logger.js';
|
|
2
|
+
export { getLogger, PlainReporter, SilentReporter } from '../observability/logger.js';
|
|
3
3
|
export { createPluginRegistry, setPluginRegistry, } from '../plugin/registry.js';
|
|
4
4
|
export { createPromptRegistry, setPromptRegistry, } from '../prompts/registry.js';
|
|
5
5
|
export { getExitCode } from '../runtime/exit-codes.js';
|
|
6
|
-
export {
|
|
6
|
+
export { resolveExecutionProfile } from '../runtime/execution-profile.js';
|
|
7
|
+
export { getDefaultSessionContextBudgetTokens } from '../session/session-context-builder.js';
|
|
8
|
+
export { buildEffectiveConversationContext } from '../session/summary-sync.js';
|
|
7
9
|
//# sourceMappingURL=cli-run-handler.js.map
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
export { mkdir } from '../adapters/fs/node-fs.js';
|
|
2
|
-
export { defaultPathAdapter } from '../adapters/path/path-adapter.js';
|
|
3
1
|
export { createSalmonTaskExecutor } from '../backends/salmon-loop/task-executor.js';
|
|
4
2
|
export { GitSnapshotCheckpointService } from '../checkpoint-domain/service.js';
|
|
5
3
|
export { resolveConfig } from '../config/resolve.js';
|
|
@@ -11,11 +9,11 @@ export { PluginLoader } from '../plugin/loader.js';
|
|
|
11
9
|
export { clearPluginRegistry, createPluginRegistry, setPluginRegistry, } from '../plugin/registry.js';
|
|
12
10
|
export { clearPromptRegistry, createPromptRegistry, setPromptRegistry, } from '../prompts/registry.js';
|
|
13
11
|
export { buildA2AAgentCard } from '../protocols/a2a/agent-card.js';
|
|
12
|
+
export { buildA2AFlowSkills } from '../protocols/shared/flow-mode-mapping.js';
|
|
14
13
|
export { createAcpFormalAgent } from '../protocols/acp/formal-agent.js';
|
|
15
14
|
export { startAcpStdioServer } from '../protocols/acp/stdio-server.js';
|
|
16
15
|
export { createAgentServerRuntime } from '../runtime/agent-server-runtime.js';
|
|
16
|
+
export { resolveExecutionProfile } from '../runtime/execution-profile.js';
|
|
17
17
|
export { runSalmonLoop } from '../runtime/loop.js';
|
|
18
18
|
export { getUserAcpSessionStorePath } from '../runtime/paths.js';
|
|
19
|
-
export { getSidecarSocketPath, getSidecarListenOptions, createPipeListenOptions, createTcpListenOptions, } from '../runtime/sidecar-paths.js';
|
|
20
|
-
export { buildSidecarRouteDescriptors, defaultSidecarRouteCatalog, } from '../runtime/sidecar-route-catalog.js';
|
|
21
19
|
//# sourceMappingURL=cli-serve.js.map
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { getLogger } from '../observability/logger.js';
|
|
1
|
+
export { getLogger, tryGetLogger } from '../observability/logger.js';
|
|
2
2
|
//# sourceMappingURL=cli-utils-worktree.js.map
|
|
@@ -97,6 +97,15 @@ function buildDependencyGuidance(input) {
|
|
|
97
97
|
}
|
|
98
98
|
function buildErrorCodeGuidance(input) {
|
|
99
99
|
switch (input.errorCode) {
|
|
100
|
+
case 'LLM_RATE_LIMITED':
|
|
101
|
+
return {
|
|
102
|
+
diagnosticCode: 'LLM_RATE_LIMITED',
|
|
103
|
+
safeHint: 'LLM is rate limited. Please retry in a moment.',
|
|
104
|
+
remediationSteps: [
|
|
105
|
+
'Retry the command after a short delay.',
|
|
106
|
+
'If it persists, reduce concurrency or check provider quota.',
|
|
107
|
+
],
|
|
108
|
+
};
|
|
100
109
|
case 'LLM_HTTP_REQUEST_FAILED':
|
|
101
110
|
return {
|
|
102
111
|
diagnosticCode: 'LLM_HTTP_REQUEST_FAILED',
|
|
@@ -106,6 +115,15 @@ function buildErrorCodeGuidance(input) {
|
|
|
106
115
|
'If it persists, check provider status or credentials.',
|
|
107
116
|
],
|
|
108
117
|
};
|
|
118
|
+
case 'LLM_AUTHENTICATION_FAILED':
|
|
119
|
+
return {
|
|
120
|
+
diagnosticCode: 'LLM_AUTHENTICATION_FAILED',
|
|
121
|
+
safeHint: 'LLM provider rejected the request credentials or access.',
|
|
122
|
+
remediationSteps: [
|
|
123
|
+
'Check the provider API key, app id, and model access configuration.',
|
|
124
|
+
'If the configuration is correct, confirm the selected model is enabled for this account.',
|
|
125
|
+
],
|
|
126
|
+
};
|
|
109
127
|
case 'LLM_HTTP_ABORTED':
|
|
110
128
|
return {
|
|
111
129
|
diagnosticCode: 'LLM_HTTP_ABORTED',
|
|
@@ -184,7 +202,10 @@ export function buildFailureGuidance(input) {
|
|
|
184
202
|
const dependencyGuidance = buildDependencyGuidance(input);
|
|
185
203
|
if (dependencyGuidance)
|
|
186
204
|
return dependencyGuidance;
|
|
187
|
-
const errorCodeGuidance = buildErrorCodeGuidance(
|
|
205
|
+
const errorCodeGuidance = buildErrorCodeGuidance({
|
|
206
|
+
...input,
|
|
207
|
+
errorCode: input.rootCause ?? input.errorCode,
|
|
208
|
+
});
|
|
188
209
|
if (errorCodeGuidance)
|
|
189
210
|
return errorCodeGuidance;
|
|
190
211
|
if (input.reasonCode === 'PREFLIGHT_NOT_GIT') {
|
|
@@ -210,6 +231,37 @@ export function buildFailureGuidance(input) {
|
|
|
210
231
|
remediationSteps: ['Resolve conflicting local changes, then retry.'],
|
|
211
232
|
};
|
|
212
233
|
}
|
|
234
|
+
if (input.reasonCode === 'VERIFY_COMMAND_MISSING') {
|
|
235
|
+
return {
|
|
236
|
+
diagnosticCode: 'VERIFY_COMMAND_MISSING',
|
|
237
|
+
safeHint: 'Autopilot changed the workspace but no verification command was configured.',
|
|
238
|
+
remediationSteps: [
|
|
239
|
+
'Provide a verify command that exercises the changed behavior.',
|
|
240
|
+
'Retry after configuring verification for this run.',
|
|
241
|
+
],
|
|
242
|
+
};
|
|
243
|
+
}
|
|
244
|
+
if (input.reasonCode === 'TOOL_CORRECTION_REQUIRED') {
|
|
245
|
+
const correctionHint = (() => {
|
|
246
|
+
switch (input.errorCode) {
|
|
247
|
+
case 'INVALID_INPUT':
|
|
248
|
+
case 'INVALID_TOOL_ARGUMENTS_JSON':
|
|
249
|
+
case 'MALFORMED_TOOL_CALL':
|
|
250
|
+
return {
|
|
251
|
+
diagnosticCode: 'TOOL_ARGUMENT_CORRECTION_NEEDED',
|
|
252
|
+
safeHint: 'A tool call used invalid arguments. Adjust the tool arguments and retry.',
|
|
253
|
+
remediationSteps: [
|
|
254
|
+
'Retry with a valid JSON object that matches the tool input schema.',
|
|
255
|
+
'Reuse the latest tool error details to correct only the invalid fields.',
|
|
256
|
+
],
|
|
257
|
+
};
|
|
258
|
+
default:
|
|
259
|
+
return undefined;
|
|
260
|
+
}
|
|
261
|
+
})();
|
|
262
|
+
if (correctionHint)
|
|
263
|
+
return correctionHint;
|
|
264
|
+
}
|
|
213
265
|
return {
|
|
214
266
|
diagnosticCode: input.reasonCode,
|
|
215
267
|
safeHint: input.fallbackReason,
|
|
@@ -1,9 +1,12 @@
|
|
|
1
|
+
import { resolveLlmCapabilities } from '../../llm/capabilities.js';
|
|
1
2
|
import { Phase } from '../../types/runtime.js';
|
|
2
3
|
import { DecisionEngine, PlanBuilder } from './DecisionEngine.js';
|
|
3
4
|
function defaultMaxRoundsForPhase(phase) {
|
|
4
5
|
// Explore needs more rounds to navigate the codebase
|
|
5
6
|
if (phase === Phase.EXPLORE)
|
|
6
7
|
return 8;
|
|
8
|
+
if (phase === Phase.AUTOPILOT)
|
|
9
|
+
return 8;
|
|
7
10
|
if (phase === Phase.RESEARCH)
|
|
8
11
|
return 8;
|
|
9
12
|
if (phase === Phase.PLAN)
|
|
@@ -13,7 +16,7 @@ function defaultMaxRoundsForPhase(phase) {
|
|
|
13
16
|
return 4;
|
|
14
17
|
}
|
|
15
18
|
export function resolveLlmToolCallingPolicy(phase, llm) {
|
|
16
|
-
const caps = llm
|
|
19
|
+
const caps = resolveLlmCapabilities(llm, phase);
|
|
17
20
|
const maxRounds = defaultMaxRoundsForPhase(phase);
|
|
18
21
|
// Grizzco DSL engine is transaction-shaped; for LLM policies we inject a minimal context and keep all
|
|
19
22
|
// decisions inside ctx.data to avoid coupling to file/operation semantics.
|