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
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
const HEADLESS_OUTPUT_FORMATS = new Set(['json', 'stream-json']);
|
|
1
2
|
function readFlagValue(tokens, index) {
|
|
2
3
|
const token = tokens[index];
|
|
3
4
|
const eq = token.indexOf('=');
|
|
@@ -57,4 +58,30 @@ export function detectHeadlessOutputFromArgv(argv) {
|
|
|
57
58
|
outputProfile,
|
|
58
59
|
};
|
|
59
60
|
}
|
|
61
|
+
export function shouldForceColorForArgv(argv) {
|
|
62
|
+
if (process.env.NO_COLOR !== undefined)
|
|
63
|
+
return false;
|
|
64
|
+
const existingForceColor = process.env.FORCE_COLOR;
|
|
65
|
+
if (existingForceColor !== undefined && existingForceColor !== '')
|
|
66
|
+
return false;
|
|
67
|
+
const tokens = argv.slice(2);
|
|
68
|
+
for (let i = 0; i < tokens.length; i++) {
|
|
69
|
+
const token = tokens[i];
|
|
70
|
+
if (token === '--')
|
|
71
|
+
break;
|
|
72
|
+
if (token === '--output-format') {
|
|
73
|
+
const value = tokens[i + 1];
|
|
74
|
+
if (HEADLESS_OUTPUT_FORMATS.has(String(value)))
|
|
75
|
+
return false;
|
|
76
|
+
i += 1;
|
|
77
|
+
continue;
|
|
78
|
+
}
|
|
79
|
+
if (token.startsWith('--output-format=')) {
|
|
80
|
+
const value = token.slice('--output-format='.length);
|
|
81
|
+
if (HEADLESS_OUTPUT_FORMATS.has(value))
|
|
82
|
+
return false;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
return true;
|
|
86
|
+
}
|
|
60
87
|
//# sourceMappingURL=headless-detection.js.map
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { resolveExecutionProfile, } from '../core/facades/cli-chat.js';
|
|
2
|
+
export function resolveActiveChatFlowMode(sessionFlowMode, defaultFlowMode) {
|
|
3
|
+
return sessionFlowMode ?? defaultFlowMode ?? 'autopilot';
|
|
4
|
+
}
|
|
5
|
+
export function resolveChatCheckpointStrategy(flowMode, configured) {
|
|
6
|
+
const profile = resolveExecutionProfile(flowMode);
|
|
7
|
+
return profile.readOnly
|
|
8
|
+
? 'direct'
|
|
9
|
+
: (configured ?? profile.defaultCheckpointStrategy ?? 'worktree');
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=chat-flow.js.map
|
package/dist/cli/chat.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { buildSessionArtifactStateFromLoopResult, buildEffectiveConversationContext, ChatSessionManager, DEFAULT_LLM_OUTPUT_POLICY, emitLlmOutput, getDefaultSessionContextBudgetTokens, InputHistoryManager, logIgnoredError, getLogger, refreshSessionSummary, runSalmonLoop, TokenTracker, createInitialTracking, onNormalTurnComplete, runCompactionPipeline, reactiveCompact, } from '../core/facades/cli-chat.js';
|
|
2
2
|
import { createSubAgentController } from '../core/facades/cli-subagent.js';
|
|
3
3
|
import { createUiAuthorizationProvider } from './authorization/provider.js';
|
|
4
|
+
import { resolveActiveChatFlowMode, resolveChatCheckpointStrategy } from './chat-flow.js';
|
|
4
5
|
import { commands } from './commands/registry.js';
|
|
5
6
|
import { CHAT_QUEUE_CONFIG } from './config.js';
|
|
6
7
|
import { text } from './locales/index.js';
|
|
@@ -49,7 +50,10 @@ export async function startChatMode(options) {
|
|
|
49
50
|
let hideTimer = null;
|
|
50
51
|
let currentInstruction = null;
|
|
51
52
|
let lastInterruptedInput = null;
|
|
53
|
+
let currentFlowMode = null;
|
|
54
|
+
let lastInterruptedFlowMode = null;
|
|
52
55
|
let currentLlmOutputPolicy = options.llmOutput ?? DEFAULT_LLM_OUTPUT_POLICY;
|
|
56
|
+
let currentCompactionTracking = createInitialTracking();
|
|
53
57
|
const authorizationProvider = createUiAuthorizationProvider({
|
|
54
58
|
emit: (event) => {
|
|
55
59
|
latestEmit?.({ ...event, timestamp: new Date() });
|
|
@@ -156,8 +160,28 @@ export async function startChatMode(options) {
|
|
|
156
160
|
return false;
|
|
157
161
|
return /cancelled by user/i.test(reason);
|
|
158
162
|
};
|
|
159
|
-
const
|
|
163
|
+
const buildRecoveryFailureSummary = (result) => {
|
|
164
|
+
if (result.success)
|
|
165
|
+
return null;
|
|
166
|
+
const isRecoveryCandidate = result.reasonCode === 'TOOL_CORRECTION_REQUIRED' ||
|
|
167
|
+
result.reasonCode === 'AWAITING_INPUT' ||
|
|
168
|
+
isInterruptResult(result.reason);
|
|
169
|
+
if (!isRecoveryCandidate)
|
|
170
|
+
return null;
|
|
171
|
+
const summary = {};
|
|
172
|
+
if (typeof result.reasonCode === 'string')
|
|
173
|
+
summary.reasonCode = result.reasonCode;
|
|
174
|
+
if (typeof result.diagnosticCode === 'string')
|
|
175
|
+
summary.diagnosticCode = result.diagnosticCode;
|
|
176
|
+
if (typeof result.safeHint === 'string')
|
|
177
|
+
summary.safeHint = result.safeHint;
|
|
178
|
+
if (typeof result.failurePhase === 'string')
|
|
179
|
+
summary.failurePhase = result.failurePhase;
|
|
180
|
+
return Object.keys(summary).length > 0 ? summary : null;
|
|
181
|
+
};
|
|
182
|
+
const markInterrupted = (input, flowMode) => {
|
|
160
183
|
lastInterruptedInput = input;
|
|
184
|
+
lastInterruptedFlowMode = flowMode ?? null;
|
|
161
185
|
queue.pause();
|
|
162
186
|
latestEmit?.({
|
|
163
187
|
type: 'log',
|
|
@@ -172,6 +196,8 @@ export async function startChatMode(options) {
|
|
|
172
196
|
return;
|
|
173
197
|
if (!latestDispatch)
|
|
174
198
|
return;
|
|
199
|
+
const queuedFlowMode = queueOptions?.flowMode ??
|
|
200
|
+
resolveActiveChatFlowMode(sessionManager.getChatFlowMode(), options.defaultFlowMode);
|
|
175
201
|
try {
|
|
176
202
|
const currentSessionId = sessionManager.getCurrent().meta.id;
|
|
177
203
|
historyManager
|
|
@@ -203,13 +229,30 @@ export async function startChatMode(options) {
|
|
|
203
229
|
started = true;
|
|
204
230
|
latestDispatch?.({ type: 'SHIFT_QUEUE_MESSAGE' });
|
|
205
231
|
currentInstruction = trimmed;
|
|
232
|
+
currentFlowMode = queuedFlowMode;
|
|
206
233
|
const timeoutAbort = new AbortController();
|
|
207
234
|
const mergedSignal = mergeAbortSignals([latestGuiOptions?.signal, timeoutAbort.signal]);
|
|
235
|
+
// Run compaction pipeline (Level 1 Autocompact) before building context
|
|
236
|
+
const compactionResult = await runCompactionPipeline({
|
|
237
|
+
sessionManager,
|
|
238
|
+
llm: options.llm,
|
|
239
|
+
tracking: currentCompactionTracking,
|
|
240
|
+
signal: mergedSignal.signal,
|
|
241
|
+
});
|
|
242
|
+
if (compactionResult.performed) {
|
|
243
|
+
currentCompactionTracking = compactionResult.tracking;
|
|
244
|
+
}
|
|
208
245
|
const modelIdForBudget = options.llm.getModelId?.() || process.env.SALMONLOOP_MODEL || process.env.S8P_MODEL;
|
|
209
|
-
const
|
|
210
|
-
|
|
211
|
-
|
|
246
|
+
const baseSessionBudgetTokens = getDefaultSessionContextBudgetTokens({
|
|
247
|
+
modelId: modelIdForBudget,
|
|
248
|
+
});
|
|
249
|
+
const conversationContext = buildEffectiveConversationContext({
|
|
250
|
+
llm: options.llm,
|
|
251
|
+
sessionManager,
|
|
252
|
+
budgetTokens: baseSessionBudgetTokens,
|
|
212
253
|
});
|
|
254
|
+
const artifactHints = sessionManager.getArtifactState();
|
|
255
|
+
const replacementState = sessionManager.getReplacementState();
|
|
213
256
|
// Single source of truth: chat runtime owns when a user message is appended to the UI list.
|
|
214
257
|
// The UI layer must not also append user messages (to avoid duplicates).
|
|
215
258
|
latestDispatch?.({
|
|
@@ -228,27 +271,15 @@ export async function startChatMode(options) {
|
|
|
228
271
|
timestamp: Date.now(),
|
|
229
272
|
});
|
|
230
273
|
const execution = await withTimeout((async () => {
|
|
231
|
-
const
|
|
232
|
-
|
|
233
|
-
signal: mergedSignal.signal,
|
|
234
|
-
});
|
|
235
|
-
latestEmit?.({
|
|
236
|
-
type: 'log',
|
|
237
|
-
level: 'info',
|
|
238
|
-
message: text.cli.chatIntentRouted(intentDecision.intent, intentDecision.confidence, intentDecision.reason),
|
|
239
|
-
timestamp: new Date(),
|
|
240
|
-
});
|
|
241
|
-
const nonMutating = intentDecision.intent === 'review' ||
|
|
242
|
-
intentDecision.intent === 'research' ||
|
|
243
|
-
intentDecision.intent === 'answer';
|
|
244
|
-
const strategy = nonMutating ? 'direct' : options.checkpointStrategy || 'worktree';
|
|
274
|
+
const flowMode = queuedFlowMode;
|
|
275
|
+
const strategy = resolveChatCheckpointStrategy(flowMode, options.checkpointStrategy);
|
|
245
276
|
const verboseLevel = options.verbose === true ? 'basic' : options.verbose;
|
|
246
277
|
const result = await runSalmonLoop({
|
|
247
278
|
instruction: trimmed,
|
|
248
279
|
verify: options.verifyCommand,
|
|
249
280
|
repoPath: options.repoPath,
|
|
250
281
|
llm: options.llm,
|
|
251
|
-
mode:
|
|
282
|
+
mode: flowMode,
|
|
252
283
|
strategy,
|
|
253
284
|
verbose: verboseLevel,
|
|
254
285
|
onEvent: latestEmit,
|
|
@@ -257,6 +288,8 @@ export async function startChatMode(options) {
|
|
|
257
288
|
outcomeReporter: options.outcomeReporter,
|
|
258
289
|
auditScope: options.auditScope,
|
|
259
290
|
conversationContext: conversationContext.length > 0 ? conversationContext : undefined,
|
|
291
|
+
artifactHints,
|
|
292
|
+
replacementState,
|
|
260
293
|
astValidation: options.astValidation,
|
|
261
294
|
languagePlugins: options.languagePlugins,
|
|
262
295
|
// Resolve sessionId at call time to support `/session` switching.
|
|
@@ -266,15 +299,100 @@ export async function startChatMode(options) {
|
|
|
266
299
|
authorizationMode: 'deferred',
|
|
267
300
|
userInputProvider,
|
|
268
301
|
subAgentController,
|
|
302
|
+
permissionMode: options.permissionMode,
|
|
303
|
+
}).catch(async (error) => {
|
|
304
|
+
// Level 2: Reactive Compact
|
|
305
|
+
// If the provider reports prompt-too-long, attempt emergency compaction AND retry ONCE
|
|
306
|
+
// with a smaller session context budget to guarantee prompt reduction.
|
|
307
|
+
const isContextOverflow = (() => {
|
|
308
|
+
if (!error || typeof error !== 'object')
|
|
309
|
+
return false;
|
|
310
|
+
if ('llmCode' in error &&
|
|
311
|
+
error.llmCode === 'LLM_CONTEXT_LENGTH_EXCEEDED') {
|
|
312
|
+
return true;
|
|
313
|
+
}
|
|
314
|
+
const message = error instanceof Error
|
|
315
|
+
? error.message
|
|
316
|
+
: typeof error.message === 'string'
|
|
317
|
+
? String(error.message)
|
|
318
|
+
: '';
|
|
319
|
+
const lower = message.toLowerCase();
|
|
320
|
+
return (lower.includes('maximum context length') ||
|
|
321
|
+
lower.includes('context length') ||
|
|
322
|
+
lower.includes('too many tokens') ||
|
|
323
|
+
lower.includes('prompt is too long') ||
|
|
324
|
+
lower.includes('input is too long') ||
|
|
325
|
+
lower.includes('please reduce'));
|
|
326
|
+
})();
|
|
327
|
+
if (!isContextOverflow) {
|
|
328
|
+
throw error;
|
|
329
|
+
}
|
|
330
|
+
const reactiveResult = await reactiveCompact({
|
|
331
|
+
sessionManager,
|
|
332
|
+
llm: options.llm,
|
|
333
|
+
error,
|
|
334
|
+
tracking: currentCompactionTracking,
|
|
335
|
+
signal: mergedSignal.signal,
|
|
336
|
+
});
|
|
337
|
+
currentCompactionTracking = reactiveResult.tracking;
|
|
338
|
+
// Rebuild context and retry runSalmonLoop.
|
|
339
|
+
// Important: avoid duplicating the current instruction inside `conversationContext`,
|
|
340
|
+
// since `instruction: trimmed` is already provided as the primary input.
|
|
341
|
+
const history = sessionManager.getMessages();
|
|
342
|
+
const retryMessages = history.length > 0 &&
|
|
343
|
+
history[history.length - 1]?.role === 'user' &&
|
|
344
|
+
history[history.length - 1]?.content === trimmed
|
|
345
|
+
? history.slice(0, -1)
|
|
346
|
+
: history;
|
|
347
|
+
const reactiveBudgetTokens = Math.max(64, Math.min(baseSessionBudgetTokens - 1, Math.floor(baseSessionBudgetTokens * 0.5)));
|
|
348
|
+
getLogger().audit('COMPACTION_REACTIVE_RETRY', {
|
|
349
|
+
reason: 'context_overflow',
|
|
350
|
+
baseSessionBudgetTokens,
|
|
351
|
+
reactiveBudgetTokens,
|
|
352
|
+
baseIsMinimum: baseSessionBudgetTokens <= 256,
|
|
353
|
+
modelId: modelIdForBudget ?? 'unknown',
|
|
354
|
+
}, { source: 'chat', severity: 'low', scope: 'session', phase: 'COMPACTION' });
|
|
355
|
+
const newContext = buildEffectiveConversationContext({
|
|
356
|
+
llm: options.llm,
|
|
357
|
+
sessionManager,
|
|
358
|
+
messages: retryMessages,
|
|
359
|
+
budgetTokens: reactiveBudgetTokens,
|
|
360
|
+
});
|
|
361
|
+
return await runSalmonLoop({
|
|
362
|
+
instruction: trimmed,
|
|
363
|
+
verify: options.verifyCommand,
|
|
364
|
+
repoPath: options.repoPath,
|
|
365
|
+
llm: options.llm,
|
|
366
|
+
mode: flowMode,
|
|
367
|
+
strategy,
|
|
368
|
+
verbose: verboseLevel,
|
|
369
|
+
onEvent: latestEmit,
|
|
370
|
+
signal: mergedSignal.signal,
|
|
371
|
+
llmOutput: currentLlmOutputPolicy,
|
|
372
|
+
outcomeReporter: options.outcomeReporter,
|
|
373
|
+
auditScope: options.auditScope,
|
|
374
|
+
conversationContext: newContext.length > 0 ? newContext : undefined,
|
|
375
|
+
artifactHints,
|
|
376
|
+
replacementState,
|
|
377
|
+
astValidation: options.astValidation,
|
|
378
|
+
languagePlugins: options.languagePlugins,
|
|
379
|
+
langfuseSessionId: options.langfuseSessionId || sessionManager.getCurrent().meta.id,
|
|
380
|
+
langfuseUserId: options.langfuseUserId,
|
|
381
|
+
authorizationProvider,
|
|
382
|
+
authorizationMode: 'deferred',
|
|
383
|
+
userInputProvider,
|
|
384
|
+
subAgentController,
|
|
385
|
+
permissionMode: options.permissionMode,
|
|
386
|
+
});
|
|
269
387
|
});
|
|
270
|
-
return { kind: 'flow', mode:
|
|
388
|
+
return { kind: 'flow', mode: flowMode, result };
|
|
271
389
|
})(), CHAT_QUEUE_CONFIG.TASK_TIMEOUT_MS, () => timeoutAbort.abort()).finally(() => {
|
|
272
390
|
mergedSignal.cleanup();
|
|
273
391
|
});
|
|
274
392
|
const result = execution.result;
|
|
275
393
|
const mode = execution.mode;
|
|
276
394
|
if (!result.success && isInterruptResult(result.reason)) {
|
|
277
|
-
markInterrupted(trimmed);
|
|
395
|
+
markInterrupted(trimmed, mode);
|
|
278
396
|
}
|
|
279
397
|
// Add assistant message & iteration info
|
|
280
398
|
const changedFiles = result.changedFiles ?? [];
|
|
@@ -312,23 +430,38 @@ export async function startChatMode(options) {
|
|
|
312
430
|
if (usage) {
|
|
313
431
|
TokenTracker.accumulate(sessionManager.getCurrent(), usage);
|
|
314
432
|
}
|
|
433
|
+
sessionManager.mergeArtifactState(buildSessionArtifactStateFromLoopResult(result));
|
|
434
|
+
for (const preview of result.artifactHints?.toolResultPreviewArtifacts ?? []) {
|
|
435
|
+
sessionManager.freezeReplacementDecision({
|
|
436
|
+
toolResultId: `${preview.label}::${preview.artifact.handle}`,
|
|
437
|
+
decision: 'replaced',
|
|
438
|
+
preview: preview.label,
|
|
439
|
+
sourceArtifactHandle: preview.artifact.handle,
|
|
440
|
+
});
|
|
441
|
+
}
|
|
315
442
|
await refreshSessionSummary({
|
|
316
443
|
sessionManager,
|
|
317
444
|
llm: options.llm,
|
|
318
445
|
contextHash: result.contextHash,
|
|
319
446
|
strategy: 'auto',
|
|
447
|
+
recoveryStatePatch: {
|
|
448
|
+
lastFailureSummary: buildRecoveryFailureSummary(result),
|
|
449
|
+
},
|
|
320
450
|
});
|
|
451
|
+
currentCompactionTracking = onNormalTurnComplete(currentCompactionTracking);
|
|
321
452
|
await sessionManager.save();
|
|
322
453
|
currentInstruction = null;
|
|
454
|
+
currentFlowMode = null;
|
|
323
455
|
return result;
|
|
324
456
|
}).catch((error) => {
|
|
325
457
|
if (!started) {
|
|
326
458
|
latestDispatch?.({ type: 'REMOVE_QUEUE_MESSAGE', payload: { id: queueMessageId } });
|
|
327
459
|
}
|
|
328
460
|
if (isInterruptError(error) && currentInstruction) {
|
|
329
|
-
markInterrupted(currentInstruction);
|
|
461
|
+
markInterrupted(currentInstruction, currentFlowMode ?? undefined);
|
|
330
462
|
}
|
|
331
463
|
currentInstruction = null;
|
|
464
|
+
currentFlowMode = null;
|
|
332
465
|
throw error;
|
|
333
466
|
});
|
|
334
467
|
};
|
|
@@ -340,11 +473,13 @@ export async function startChatMode(options) {
|
|
|
340
473
|
resume: () => {
|
|
341
474
|
queue.resume();
|
|
342
475
|
lastInterruptedInput = null;
|
|
476
|
+
lastInterruptedFlowMode = null;
|
|
343
477
|
getLogger().audit('QUEUE_RESUME', { status: 'resumed' }, { source: 'chat', severity: 'low', scope: 'session' });
|
|
344
478
|
},
|
|
345
479
|
clear: () => {
|
|
346
480
|
const cleared = queue.clear();
|
|
347
481
|
lastInterruptedInput = null;
|
|
482
|
+
lastInterruptedFlowMode = null;
|
|
348
483
|
latestDispatch?.({ type: 'CLEAR_QUEUE_MESSAGES' });
|
|
349
484
|
getLogger().audit('QUEUE_CLEAR', { cleared }, { source: 'chat', severity: 'low', scope: 'session' });
|
|
350
485
|
return cleared;
|
|
@@ -353,9 +488,11 @@ export async function startChatMode(options) {
|
|
|
353
488
|
if (!lastInterruptedInput)
|
|
354
489
|
return false;
|
|
355
490
|
const retryInput = lastInterruptedInput;
|
|
491
|
+
const retryFlowMode = lastInterruptedFlowMode ?? undefined;
|
|
356
492
|
lastInterruptedInput = null;
|
|
493
|
+
lastInterruptedFlowMode = null;
|
|
357
494
|
queue.resume();
|
|
358
|
-
enqueueInput(retryInput, { front: true });
|
|
495
|
+
enqueueInput(retryInput, { front: true, flowMode: retryFlowMode });
|
|
359
496
|
return true;
|
|
360
497
|
},
|
|
361
498
|
status: () => {
|
|
@@ -1,13 +1,26 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { createPluginRegistry, createPromptRegistry, createRuntimeLlm, setPluginRegistry, setPromptRegistry, ExtensionConfigError, getLogger, normalizePermissionMode, PluginLoader, resolveConfig, resolveExtensions, } from '../../core/facades/cli-command-chat.js';
|
|
1
|
+
import { createPluginRegistry, createPromptRegistry, createRuntimeLlm, setPluginRegistry, setPromptRegistry, ExtensionConfigError, getLogger, normalizePermissionMode, PluginLoader, resolveExecutionProfile, resolveExtensions, } from '../../core/facades/cli-command-chat.js';
|
|
3
2
|
import { text } from '../locales/index.js';
|
|
4
|
-
import {
|
|
3
|
+
import { getOptionValueSourceWithGlobalFallback } from '../utils/command-option-source.js';
|
|
5
4
|
import { resolveLlmOutputPolicyFromCli } from '../utils/llm-output.js';
|
|
6
5
|
import { createOutcomeReporter } from '../utils/outcome-reporter.js';
|
|
6
|
+
import { resolveCliConfig } from '../utils/resolve-cli-config.js';
|
|
7
7
|
import { resolveVerifyOption } from '../utils/verify-resolver.js';
|
|
8
8
|
export async function handleChatCommand(options, command) {
|
|
9
9
|
const allOptions = command.optsWithGlobals();
|
|
10
|
-
const
|
|
10
|
+
const configResult = await resolveCliConfig({
|
|
11
|
+
repo: allOptions.repo,
|
|
12
|
+
cwd: process.cwd(),
|
|
13
|
+
configPath: allOptions.config,
|
|
14
|
+
enableConfigFile: allOptions.configFile !== false,
|
|
15
|
+
auditScope: allOptions.auditScope,
|
|
16
|
+
verbose: allOptions.verbose,
|
|
17
|
+
logMode: allOptions.logMode,
|
|
18
|
+
});
|
|
19
|
+
if (!configResult.ok) {
|
|
20
|
+
getLogger().error(configResult.message, true);
|
|
21
|
+
process.exit(1);
|
|
22
|
+
}
|
|
23
|
+
const { resolvedConfig, auditScope, repoPath: runPath, verboseLevel } = configResult;
|
|
11
24
|
const printInstruction = typeof allOptions.print === 'string'
|
|
12
25
|
? allOptions.print
|
|
13
26
|
: undefined;
|
|
@@ -28,20 +41,14 @@ export async function handleChatCommand(options, command) {
|
|
|
28
41
|
setPluginRegistry(languagePlugins);
|
|
29
42
|
setPromptRegistry(createPromptRegistry());
|
|
30
43
|
await PluginLoader.loadPlugins(languagePlugins, runPath);
|
|
31
|
-
const
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
const
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
if (!auditScopeResolution.ok) {
|
|
40
|
-
getLogger().error(text.cli.invalidAuditScope(auditScopeResolution.invalid), true);
|
|
41
|
-
process.exit(1);
|
|
42
|
-
}
|
|
43
|
-
const auditScope = auditScopeResolution.value;
|
|
44
|
-
const rawPermissionMode = allOptions.mode ?? resolvedConfig.permissionMode ?? 'interactive';
|
|
44
|
+
const defaultFlowMode = 'autopilot';
|
|
45
|
+
const defaultFlowProfile = resolveExecutionProfile(defaultFlowMode);
|
|
46
|
+
const modeOptionSource = getOptionValueSourceWithGlobalFallback(command, 'mode');
|
|
47
|
+
const checkpointStrategyOptionSource = getOptionValueSourceWithGlobalFallback(command, 'checkpointStrategy');
|
|
48
|
+
const rawPermissionMode = (modeOptionSource === 'cli' ? allOptions.mode : undefined) ??
|
|
49
|
+
resolvedConfig.permissionMode ??
|
|
50
|
+
defaultFlowProfile.defaultPermissionMode ??
|
|
51
|
+
'interactive';
|
|
45
52
|
const permissionMode = normalizePermissionMode(rawPermissionMode);
|
|
46
53
|
if (!permissionMode) {
|
|
47
54
|
getLogger().error(`Invalid --mode "${String(rawPermissionMode)}". Expected "interactive" or "yolo".`);
|
|
@@ -87,14 +94,13 @@ export async function handleChatCommand(options, command) {
|
|
|
87
94
|
repoPath: runPath,
|
|
88
95
|
llm,
|
|
89
96
|
verifyCommand,
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
: allOptions.checkpointStrategy || 'worktree',
|
|
97
|
+
defaultFlowMode,
|
|
98
|
+
checkpointStrategy: checkpointStrategyOptionSource === 'cli'
|
|
99
|
+
? allOptions.checkpointStrategy || 'worktree'
|
|
100
|
+
: undefined,
|
|
95
101
|
continue: continueSession,
|
|
96
102
|
resumeSessionId,
|
|
97
|
-
verbose:
|
|
103
|
+
verbose: verboseLevel,
|
|
98
104
|
llmOutput,
|
|
99
105
|
markdownTheme: resolvedConfig.markdownTheme,
|
|
100
106
|
markdownRenderMode: resolvedConfig.markdownRenderMode,
|
|
@@ -1,8 +1,21 @@
|
|
|
1
|
-
import { createContextCacheStore, createDefaultPermissionGate, ContextService,
|
|
1
|
+
import { createContextCacheStore, createDefaultPermissionGate, ContextService, getLogger, setChurnRankingPolicy, } from '../../core/facades/cli-context.js';
|
|
2
2
|
import { text } from '../locales/index.js';
|
|
3
|
+
import { resolveCliConfig } from '../utils/resolve-cli-config.js';
|
|
3
4
|
export async function handleContextCommand(options, command) {
|
|
4
5
|
const allOptions = command.optsWithGlobals();
|
|
5
|
-
const
|
|
6
|
+
const configResult = await resolveCliConfig({
|
|
7
|
+
repo: allOptions.repo,
|
|
8
|
+
cwd: process.cwd(),
|
|
9
|
+
configPath: allOptions.config,
|
|
10
|
+
enableConfigFile: allOptions.configFile !== false,
|
|
11
|
+
auditScope: allOptions.auditScope,
|
|
12
|
+
logMode: allOptions.logMode,
|
|
13
|
+
});
|
|
14
|
+
if (!configResult.ok) {
|
|
15
|
+
getLogger().error(configResult.message, true);
|
|
16
|
+
process.exit(1);
|
|
17
|
+
}
|
|
18
|
+
const { resolvedConfig, repoPath } = configResult;
|
|
6
19
|
if (options.file && options.selection) {
|
|
7
20
|
getLogger().error(text.cli.fileSelectionConflict, true);
|
|
8
21
|
process.exit(1);
|
|
@@ -26,7 +39,6 @@ export async function handleContextCommand(options, command) {
|
|
|
26
39
|
}
|
|
27
40
|
budgetChars = parsed;
|
|
28
41
|
}
|
|
29
|
-
const resolvedConfig = await resolveConfig({ repoRoot: repoPath });
|
|
30
42
|
setChurnRankingPolicy({
|
|
31
43
|
primaryBoost: resolvedConfig.raw?.context?.churn?.weight?.primary,
|
|
32
44
|
rerankWeight: resolvedConfig.raw?.context?.churn?.weight?.rerank,
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { FLOW_MODES, parseFlowMode } from '../../core/types/flow-mode.js';
|
|
2
|
+
import { text } from '../locales/index.js';
|
|
3
|
+
import { parseSuggestionContext } from './utils.js';
|
|
4
|
+
export const flowModeCommand = {
|
|
5
|
+
name: '/flow-mode',
|
|
6
|
+
description: text.cli.commandFlowMode,
|
|
7
|
+
order: 55,
|
|
8
|
+
getSuggestions: ({ input }) => {
|
|
9
|
+
const { argIndex, currentPrefix } = parseSuggestionContext(input);
|
|
10
|
+
if (argIndex !== 1)
|
|
11
|
+
return [];
|
|
12
|
+
const search = currentPrefix.toLowerCase();
|
|
13
|
+
return FLOW_MODES.filter((mode) => mode.startsWith(search)).map((mode) => ({
|
|
14
|
+
name: mode,
|
|
15
|
+
description: text.cli.flowModeSuggestion(mode),
|
|
16
|
+
}));
|
|
17
|
+
},
|
|
18
|
+
execute: async ({ emit, input, sessionManager }) => {
|
|
19
|
+
const args = input.trim().split(/\s+/).slice(1);
|
|
20
|
+
const rawValue = args[0];
|
|
21
|
+
if (!rawValue) {
|
|
22
|
+
const current = sessionManager.getChatFlowMode() ?? 'autopilot';
|
|
23
|
+
emit({
|
|
24
|
+
type: 'log',
|
|
25
|
+
level: 'info',
|
|
26
|
+
message: text.cli.flowModeCurrent(current),
|
|
27
|
+
timestamp: new Date(),
|
|
28
|
+
});
|
|
29
|
+
emit({
|
|
30
|
+
type: 'log',
|
|
31
|
+
level: 'info',
|
|
32
|
+
message: text.cli.flowModeUsage,
|
|
33
|
+
timestamp: new Date(),
|
|
34
|
+
});
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
const normalized = parseFlowMode(rawValue);
|
|
38
|
+
if (!normalized) {
|
|
39
|
+
emit({
|
|
40
|
+
type: 'log',
|
|
41
|
+
level: 'error',
|
|
42
|
+
message: text.cli.flowModeInvalid(rawValue),
|
|
43
|
+
timestamp: new Date(),
|
|
44
|
+
});
|
|
45
|
+
emit({
|
|
46
|
+
type: 'log',
|
|
47
|
+
level: 'info',
|
|
48
|
+
message: text.cli.flowModeUsage,
|
|
49
|
+
timestamp: new Date(),
|
|
50
|
+
});
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
sessionManager.updateChatFlowMode(normalized);
|
|
54
|
+
await sessionManager.save();
|
|
55
|
+
emit({
|
|
56
|
+
type: 'log',
|
|
57
|
+
level: 'info',
|
|
58
|
+
message: text.cli.flowModeUpdated(normalized),
|
|
59
|
+
timestamp: new Date(),
|
|
60
|
+
});
|
|
61
|
+
},
|
|
62
|
+
};
|
|
63
|
+
//# sourceMappingURL=flow-mode.js.map
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export function formatHelpRows(items) {
|
|
2
|
+
const rows = items.map((item) => {
|
|
3
|
+
const aliases = item.aliases?.length ? ` (${item.aliases.join(', ')})` : '';
|
|
4
|
+
return {
|
|
5
|
+
label: `${item.name}${aliases}`,
|
|
6
|
+
description: item.description,
|
|
7
|
+
};
|
|
8
|
+
});
|
|
9
|
+
const maxName = Math.max(...rows.map((row) => row.label.length), 0);
|
|
10
|
+
return rows.map((row) => `${row.label}`.padEnd(maxName + 2) + row.description).join('\n');
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=help-format.js.map
|
|
@@ -1,6 +1,9 @@
|
|
|
1
|
+
import { text } from '../locales/index.js';
|
|
1
2
|
import { allowlistCommand } from './allowlist.js';
|
|
2
3
|
import { configCommand } from './config.js';
|
|
3
4
|
import { exitCommand } from './exit.js';
|
|
5
|
+
import { flowModeCommand } from './flow-mode.js';
|
|
6
|
+
import { formatHelpRows } from './help-format.js';
|
|
4
7
|
import { llmOutputCommand } from './llm-output.js';
|
|
5
8
|
import { logModeCommand } from './log-mode.js';
|
|
6
9
|
import { modeCommand } from './mode.js';
|
|
@@ -19,6 +22,7 @@ const baseCommands = [
|
|
|
19
22
|
allowlistCommand,
|
|
20
23
|
modeCommand,
|
|
21
24
|
logModeCommand,
|
|
25
|
+
flowModeCommand,
|
|
22
26
|
configCommand,
|
|
23
27
|
subAgentCommand,
|
|
24
28
|
newCommand,
|
|
@@ -29,16 +33,11 @@ const baseCommands = [
|
|
|
29
33
|
order: 80,
|
|
30
34
|
execute: ({ emit }) => {
|
|
31
35
|
const visible = commands.filter((c) => !c.hidden);
|
|
32
|
-
const
|
|
33
|
-
const rows = visible.map((cmd) => {
|
|
34
|
-
const paddedName = `${cmd.name}`.padEnd(maxName + 2);
|
|
35
|
-
return `${paddedName}${cmd.description}`;
|
|
36
|
-
});
|
|
37
|
-
const helpMsg = rows.join('\n');
|
|
36
|
+
const helpMsg = formatHelpRows(visible);
|
|
38
37
|
emit({
|
|
39
38
|
type: 'log',
|
|
40
39
|
level: 'info',
|
|
41
|
-
message:
|
|
40
|
+
message: text.cli.helpAvailableCommands(helpMsg),
|
|
42
41
|
timestamp: new Date(),
|
|
43
42
|
});
|
|
44
43
|
},
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { FileAdapter } from '../../../core/adapters/fs/file-adapter.js';
|
|
2
|
+
import { buildBenchmarkPatchArtifact } from '../../../core/benchmark/patch-artifact.js';
|
|
3
|
+
import { encodeSweBenchPredictionJsonl } from '../../../core/benchmark/swe-bench.js';
|
|
4
|
+
export async function attachRunBenchmarkArtifacts(params) {
|
|
5
|
+
if (!params.exportPatchPath && !params.sweBenchPredictionsPath)
|
|
6
|
+
return;
|
|
7
|
+
const fileAdapter = new FileAdapter();
|
|
8
|
+
const artifact = await buildBenchmarkPatchArtifact({
|
|
9
|
+
repoPath: params.repoPath,
|
|
10
|
+
changedFilesHint: params.result.changedFiles,
|
|
11
|
+
excludePaths: [params.exportPatchPath, params.sweBenchPredictionsPath].filter((path) => typeof path === 'string'),
|
|
12
|
+
});
|
|
13
|
+
if (params.exportPatchPath) {
|
|
14
|
+
await fileAdapter.writeFile(params.exportPatchPath, artifact.patch);
|
|
15
|
+
}
|
|
16
|
+
params.result.benchmarkPatchArtifact = {
|
|
17
|
+
kind: 'git-unified-diff',
|
|
18
|
+
path: params.exportPatchPath,
|
|
19
|
+
sha256: artifact.sha256,
|
|
20
|
+
bytes: artifact.bytes,
|
|
21
|
+
changedFiles: artifact.changedFiles,
|
|
22
|
+
isEmpty: artifact.isEmpty,
|
|
23
|
+
};
|
|
24
|
+
if (params.sweBenchPredictionsPath) {
|
|
25
|
+
if (!params.sweBenchInstanceId || !params.sweBenchModelName) {
|
|
26
|
+
throw new Error('SWE-bench predictions require instance id and model name.');
|
|
27
|
+
}
|
|
28
|
+
await fileAdapter.appendFile(params.sweBenchPredictionsPath, encodeSweBenchPredictionJsonl({
|
|
29
|
+
instanceId: params.sweBenchInstanceId,
|
|
30
|
+
modelNameOrPath: params.sweBenchModelName,
|
|
31
|
+
modelPatch: artifact.patch,
|
|
32
|
+
}));
|
|
33
|
+
params.result.benchmarkArtifact = {
|
|
34
|
+
provider: 'swe-bench',
|
|
35
|
+
instanceId: params.sweBenchInstanceId,
|
|
36
|
+
modelNameOrPath: params.sweBenchModelName,
|
|
37
|
+
predictionsPath: params.sweBenchPredictionsPath,
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=benchmark-artifacts.js.map
|