@wrongstack/cli 0.306.3 → 0.307.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/{auth-L3WGSGDX.js → auth-TVOOHL4Q.js} +45 -106
- package/dist/boot/short-circuit-flags.d.ts +2 -2
- package/dist/chimera-cascade-evidence.d.ts +1 -1
- package/dist/chunk-2VMJ3E5Z.js +71 -0
- package/dist/{chunk-5N34EWJR.js → chunk-2ZNBRZ4W.js} +2 -2
- package/dist/{chunk-RHLQT3EV.js → chunk-CB35UVXO.js} +1636 -1528
- package/dist/{chunk-YKBRFSGL.js → chunk-DOJLAULS.js} +28 -28
- package/dist/{chunk-JUHRI6OV.js → chunk-G7337TTK.js} +24 -5
- package/dist/{chunk-KXN5HZDL.js → chunk-PKHGLWUJ.js} +24 -6
- package/dist/{chunk-HITHEXE3.js → chunk-TOG7OMKJ.js} +2 -2
- package/dist/{chunk-ARWGQUB3.js → chunk-XSG33WHN.js} +15 -5
- package/dist/{cli-main-3PUWFKSL.js → cli-main-YDOZZOZA.js} +29026 -28205
- package/dist/cli-main.d.ts +0 -20
- package/dist/{execution-4IG5XKOL.js → execution-CGT6J5ZN.js} +306 -274
- package/dist/fleet/host-learning-scheduler.d.ts +27 -0
- package/dist/fleet/host-shadow-manager.d.ts +64 -0
- package/dist/fleet/host.d.ts +5 -140
- package/dist/{hq-ZK6PGN3W.js → hq-PA6RH2UW.js} +2 -2
- package/dist/hq-server/mailbox-gateway-manager.d.ts +32 -0
- package/dist/hq-server/routes/auth/bootstrap-routes.d.ts +5 -0
- package/dist/hq-server/routes/auth/common.d.ts +11 -0
- package/dist/hq-server/routes/auth/password-routes.d.ts +9 -0
- package/dist/hq-server/routes/auth/session-audit-routes.d.ts +6 -0
- package/dist/hq-server/routes/auth/totp-routes.d.ts +9 -0
- package/dist/hq-server/routes/auth-handlers.d.ts +5 -132
- package/dist/hq-server/routes/command-handlers.d.ts +7 -0
- package/dist/hq-server/routes/data-handlers.d.ts +8 -0
- package/dist/hq-server/routes/mailbox-handlers.d.ts +22 -0
- package/dist/hq-server/routes.d.ts +3 -3
- package/dist/hq-server/server-lifecycle.d.ts +37 -0
- package/dist/hq-server/snapshot.d.ts +6 -5
- package/dist/hq-server/types.d.ts +4 -0
- package/dist/hq-server/upgrade-handler.d.ts +34 -0
- package/dist/hq-server/ws-client-events.d.ts +25 -0
- package/dist/hq-server/ws-leader.d.ts +47 -0
- package/dist/hq-server/ws-resume.d.ts +27 -0
- package/dist/hq-server/ws.d.ts +4 -71
- package/dist/{hq-server-IVZLVCFV.js → hq-server-PBRU275L.js} +2 -2
- package/dist/hq-server.d.ts +0 -38
- package/dist/index.js +1267 -122
- package/dist/{mcp-JNWEQ6T2.js → mcp-CMLFHRG2.js} +19 -9
- package/dist/mcp-serve.d.ts +31 -1
- package/dist/{modeldiag-6VS5KDP5.js → modeldiag-ICMPHT5L.js} +868 -831
- package/dist/{project-manifest-GE25PW4S.js → project-manifest-YFTJ3D5N.js} +2 -2
- package/dist/{project-picker-BOCWHBXP.js → project-picker-R5TYAE3Q.js} +3 -3
- package/dist/{providers-models-HQN3AT3K.js → providers-models-4FAKM2WO.js} +4 -4
- package/dist/repl-eternal-loop.d.ts +8 -0
- package/dist/repl-goal-banner.d.ts +21 -0
- package/dist/slash-commands/brain-council.d.ts +36 -0
- package/dist/slash-commands/brain-status.d.ts +12 -0
- package/dist/slash-commands/fallback.d.ts +6 -0
- package/dist/slash-commands/kanban-board-handlers.d.ts +13 -0
- package/dist/slash-commands/kanban-lifecycle-diagnostics.d.ts +16 -0
- package/dist/slash-commands/kanban-task-subcommands.d.ts +8 -0
- package/dist/slash-commands/memory-audience.d.ts +14 -0
- package/dist/slash-commands/memory-gather.d.ts +9 -0
- package/dist/slash-commands/memory-stats.d.ts +5 -0
- package/dist/slash-commands/settings-mutations.d.ts +6 -0
- package/dist/slash-commands/settings-view.d.ts +5 -0
- package/dist/subcommands/handlers/modeldiag-bench.d.ts +10 -0
- package/dist/subcommands/handlers/modeldiag-eval.d.ts +27 -0
- package/dist/subcommands/handlers/modeldiag-test.d.ts +8 -0
- package/dist/{version-help-ASKQYXDJ.js → version-help-TFD6VPF3.js} +2 -2
- package/dist/vibe-protocol-wiring.d.ts +10 -0
- package/dist/webui-server/credential-watcher.d.ts +15 -0
- package/dist/webui-server/domain-handlers.d.ts +21 -0
- package/dist/webui-server/route-contexts.d.ts +41 -0
- package/dist/{webui-server-FTG7JAZU.js → webui-server-IPHGJGXE.js} +515 -437
- package/dist/wiring/cli-execute-builder.d.ts +88 -0
- package/dist/wiring/cli-heap-watchdog.d.ts +33 -0
- package/dist/wiring/cli-prompt-and-tools-setup.d.ts +25 -0
- package/dist/wiring/cli-slash-commands-setup.d.ts +79 -0
- package/dist/wiring/heap-watchdog-setup.d.ts +53 -0
- package/dist/wiring/metrics.d.ts +1 -0
- package/dist/wiring/replay-governance-setup.d.ts +31 -0
- package/package.json +27 -27
|
@@ -29,27 +29,27 @@ import {
|
|
|
29
29
|
import {
|
|
30
30
|
theme
|
|
31
31
|
} from "./chunk-QD544J2B.js";
|
|
32
|
-
import {
|
|
33
|
-
fmtTok
|
|
34
|
-
} from "./chunk-TYO2OVAD.js";
|
|
35
32
|
import {
|
|
36
33
|
WEBUI_SESSION_CHILD_CAPABILITIES,
|
|
37
34
|
writeWebuiSessionChildError,
|
|
38
35
|
writeWebuiSessionChildReady
|
|
39
36
|
} from "./chunk-3JPTNADJ.js";
|
|
40
37
|
import {
|
|
41
|
-
|
|
42
|
-
} from "./chunk-
|
|
38
|
+
fmtTok
|
|
39
|
+
} from "./chunk-TYO2OVAD.js";
|
|
43
40
|
import {
|
|
44
41
|
terminalLink,
|
|
45
42
|
terminalText
|
|
46
43
|
} from "./chunk-KE7E7DPX.js";
|
|
47
44
|
import {
|
|
48
|
-
|
|
49
|
-
} from "./chunk-
|
|
45
|
+
CLI_VERSION
|
|
46
|
+
} from "./chunk-XJXDOF63.js";
|
|
50
47
|
import {
|
|
51
48
|
activeProfileConfigPath
|
|
52
49
|
} from "./chunk-YMXXOOFN.js";
|
|
50
|
+
import {
|
|
51
|
+
resolveActiveApiKey
|
|
52
|
+
} from "./chunk-SZ42FYPT.js";
|
|
53
53
|
import "./chunk-7OCVIDC7.js";
|
|
54
54
|
|
|
55
55
|
// src/execution.ts
|
|
@@ -205,7 +205,7 @@ async function runWebUIDispatch(ctx) {
|
|
|
205
205
|
const isSimpleUi = !isSessionChild && flags["simpleui"] === true;
|
|
206
206
|
agent.disableInteractiveConfirmation();
|
|
207
207
|
renderer.setSilent(true);
|
|
208
|
-
const { runWebUI } = await import("./webui-server-
|
|
208
|
+
const { runWebUI } = await import("./webui-server-IPHGJGXE.js");
|
|
209
209
|
const flagValue = (names) => {
|
|
210
210
|
for (const name of names) {
|
|
211
211
|
if (!Object.hasOwn(flags, name)) continue;
|
|
@@ -870,7 +870,7 @@ function onSwitchToSession(ctx, _sessionId, targetRoot, projectName) {
|
|
|
870
870
|
import * as path4 from "node:path";
|
|
871
871
|
import { color as color3 } from "@wrongstack/core/utils";
|
|
872
872
|
async function getProjectPickerItems(ctx) {
|
|
873
|
-
const { buildPickerItems } = await import("./project-picker-
|
|
873
|
+
const { buildPickerItems } = await import("./project-picker-R5TYAE3Q.js");
|
|
874
874
|
return buildPickerItems({
|
|
875
875
|
globalConfigPath: ctx.state.wpaths.globalConfig,
|
|
876
876
|
currentProjectRoot: ctx.state.projectRoot
|
|
@@ -888,7 +888,7 @@ async function onProjectSelect(ctx, slug, kind) {
|
|
|
888
888
|
}
|
|
889
889
|
return;
|
|
890
890
|
}
|
|
891
|
-
const { loadManifest, saveManifest } = await import("./project-manifest-
|
|
891
|
+
const { loadManifest, saveManifest } = await import("./project-manifest-YFTJ3D5N.js");
|
|
892
892
|
const manifest = await loadManifest(state.wpaths.globalConfig);
|
|
893
893
|
const project = manifest.projects.find((p) => p.slug === slug);
|
|
894
894
|
if (!project) return;
|
|
@@ -1318,7 +1318,7 @@ async function resumeSession(ctx, sessionId) {
|
|
|
1318
1318
|
throw err;
|
|
1319
1319
|
}
|
|
1320
1320
|
writerSwapped = true;
|
|
1321
|
-
state.sessionRef
|
|
1321
|
+
if (state.sessionRef) state.sessionRef.current = resumed.writer;
|
|
1322
1322
|
await agent.ctx.flushConversationJournal().catch((err) => {
|
|
1323
1323
|
console.error(
|
|
1324
1324
|
JSON.stringify({
|
|
@@ -1358,30 +1358,31 @@ async function resumeSession(ctx, sessionId) {
|
|
|
1358
1358
|
const targetProviderId = typeof meta.provider === "string" && meta.provider.length > 0 ? meta.provider : currentProviderId;
|
|
1359
1359
|
const targetModel = typeof meta.model === "string" && meta.model.length > 0 ? meta.model : agent.ctx.model;
|
|
1360
1360
|
if (switchProviderAndModel && targetProviderId && (targetProviderId !== currentProviderId || targetModel !== agent.ctx.model)) {
|
|
1361
|
-
|
|
1362
|
-
(
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
)
|
|
1373
|
-
|
|
1374
|
-
|
|
1361
|
+
try {
|
|
1362
|
+
await Promise.resolve(switchProviderAndModel(targetProviderId, targetModel));
|
|
1363
|
+
} catch (err) {
|
|
1364
|
+
console.error(
|
|
1365
|
+
JSON.stringify({
|
|
1366
|
+
level: "error",
|
|
1367
|
+
event: "execution.resume_model_restore_failed",
|
|
1368
|
+
provider: targetProviderId,
|
|
1369
|
+
model: targetModel,
|
|
1370
|
+
message: err instanceof Error ? err.message : String(err),
|
|
1371
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
1372
|
+
})
|
|
1373
|
+
);
|
|
1374
|
+
}
|
|
1375
1375
|
} else if (targetModel !== agent.ctx.model) {
|
|
1376
1376
|
agent.ctx.model = targetModel;
|
|
1377
1377
|
}
|
|
1378
|
-
let
|
|
1378
|
+
let finalizeOldWriter;
|
|
1379
1379
|
if (oldWriter && oldWriter !== resumed.writer) {
|
|
1380
|
+
const staleWriter = oldWriter;
|
|
1380
1381
|
const endedUsage = tokenCounter.total();
|
|
1381
|
-
|
|
1382
|
+
finalizeOldWriter = async () => {
|
|
1382
1383
|
let appendOk = false;
|
|
1383
1384
|
try {
|
|
1384
|
-
await
|
|
1385
|
+
await staleWriter.append({
|
|
1385
1386
|
type: "session_end",
|
|
1386
1387
|
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1387
1388
|
usage: endedUsage
|
|
@@ -1399,7 +1400,7 @@ async function resumeSession(ctx, sessionId) {
|
|
|
1399
1400
|
}
|
|
1400
1401
|
if (appendOk) {
|
|
1401
1402
|
try {
|
|
1402
|
-
await
|
|
1403
|
+
await staleWriter.close();
|
|
1403
1404
|
} catch (err) {
|
|
1404
1405
|
console.error(
|
|
1405
1406
|
JSON.stringify({
|
|
@@ -1411,7 +1412,7 @@ async function resumeSession(ctx, sessionId) {
|
|
|
1411
1412
|
);
|
|
1412
1413
|
}
|
|
1413
1414
|
}
|
|
1414
|
-
}
|
|
1415
|
+
};
|
|
1415
1416
|
}
|
|
1416
1417
|
tokenCounter.reset();
|
|
1417
1418
|
tokenCounter.account(resumed.data.usage, targetModel, targetProviderId);
|
|
@@ -1424,7 +1425,7 @@ async function resumeSession(ctx, sessionId) {
|
|
|
1424
1425
|
sessionId: resumed.writer.id,
|
|
1425
1426
|
contextSnapshot: { tokens, maxContext }
|
|
1426
1427
|
};
|
|
1427
|
-
void
|
|
1428
|
+
if (finalizeOldWriter) void finalizeOldWriter();
|
|
1428
1429
|
return result;
|
|
1429
1430
|
} catch (err) {
|
|
1430
1431
|
if (!identityClaimed) await resumeClaim?.cancel().catch(() => void 0);
|
|
@@ -2750,18 +2751,26 @@ import { emitReviewIfChanged } from "@wrongstack/core/plugin";
|
|
|
2750
2751
|
|
|
2751
2752
|
// src/chimera-cascade-evidence.ts
|
|
2752
2753
|
import { spawn as spawn2 } from "node:child_process";
|
|
2753
|
-
var JSON_BLOCK_RE = /```json
|
|
2754
|
+
var JSON_BLOCK_RE = /```(?:json)?\s*([\s\S]*?)```/gi;
|
|
2755
|
+
function tryParseJson(raw) {
|
|
2756
|
+
try {
|
|
2757
|
+
return JSON.parse(raw);
|
|
2758
|
+
} catch {
|
|
2759
|
+
try {
|
|
2760
|
+
const cleaned = raw.replace(/,\s*([}\]])/g, "$1");
|
|
2761
|
+
return JSON.parse(cleaned);
|
|
2762
|
+
} catch {
|
|
2763
|
+
return null;
|
|
2764
|
+
}
|
|
2765
|
+
}
|
|
2766
|
+
}
|
|
2754
2767
|
function extractCascadeEvidence(text) {
|
|
2755
2768
|
if (!text) return null;
|
|
2756
2769
|
for (const match of text.matchAll(JSON_BLOCK_RE)) {
|
|
2757
2770
|
const body = match[1]?.trim();
|
|
2758
2771
|
if (!body) continue;
|
|
2759
|
-
|
|
2760
|
-
|
|
2761
|
-
parsed = JSON.parse(body);
|
|
2762
|
-
} catch {
|
|
2763
|
-
continue;
|
|
2764
|
-
}
|
|
2772
|
+
const parsed = tryParseJson(body);
|
|
2773
|
+
if (!parsed) continue;
|
|
2765
2774
|
const evidence = parseEvidenceObject(parsed);
|
|
2766
2775
|
if (evidence) return evidence;
|
|
2767
2776
|
}
|
|
@@ -2822,7 +2831,7 @@ function isSafeCascadeCommand(command) {
|
|
|
2822
2831
|
const tokens = command.trim().split(/\s+/);
|
|
2823
2832
|
if (tokens.length === 0) return false;
|
|
2824
2833
|
if (!SAFE_EXECUTABLES.has(tokens[0])) return false;
|
|
2825
|
-
return tokens.every((token) => /^[A-Za-z0-9@/._
|
|
2834
|
+
return tokens.every((token) => /^[A-Za-z0-9@/._:=~+*?[\]-]+$/.test(token));
|
|
2826
2835
|
}
|
|
2827
2836
|
var runCascadeVerificationCommand = (command, cwd, timeoutMs) => {
|
|
2828
2837
|
if (!isSafeCascadeCommand(command)) {
|
|
@@ -3656,6 +3665,10 @@ function installChimeraReviewHandler({
|
|
|
3656
3665
|
const inScopeCited = citedFindings.filter((finding) => {
|
|
3657
3666
|
const citedKey = normalizeFileKeyForCitation(finding.location.file, p.cwd);
|
|
3658
3667
|
if (citedPaths.has(citedKey)) return true;
|
|
3668
|
+
const suffixMatches = [...citedPaths].filter(
|
|
3669
|
+
(cp) => cp.endsWith(`/${citedKey}`) || cp === citedKey
|
|
3670
|
+
);
|
|
3671
|
+
if (suffixMatches.length === 1) return true;
|
|
3659
3672
|
const basename7 = path11.basename(finding.location.file).toLowerCase();
|
|
3660
3673
|
const bucket = changedBasenameIndex.get(basename7);
|
|
3661
3674
|
return !!(bucket && bucket.length === 1);
|
|
@@ -3672,7 +3685,7 @@ function installChimeraReviewHandler({
|
|
|
3672
3685
|
const failedVerificationCount = inScopeCited.filter(
|
|
3673
3686
|
(finding) => finding.verification?.status === "failed"
|
|
3674
3687
|
).length;
|
|
3675
|
-
const effectiveHasFindings = reviewHasFindings && actionableFindings.length > 0;
|
|
3688
|
+
const effectiveHasFindings = reviewHasFindings && (actionableFindings.length > 0 || unverifiedInScope.length > 0);
|
|
3676
3689
|
const verifiedCount = actionableFindings.length;
|
|
3677
3690
|
const unverifiedCount = unverifiedInScope.length;
|
|
3678
3691
|
const hallucinationNote = droppedCitations.length > 0 ? `
|
|
@@ -3958,13 +3971,11 @@ async function predictNextTasks(input, opts) {
|
|
|
3958
3971
|
|
|
3959
3972
|
// src/repl.ts
|
|
3960
3973
|
import { detectContinueIntent, InputBuilder, resolveContinuation } from "@wrongstack/core/agent";
|
|
3961
|
-
import { goalFilePath, loadGoal, summarizeUsage } from "@wrongstack/core/goal";
|
|
3962
3974
|
import {
|
|
3963
|
-
color as
|
|
3975
|
+
color as color11,
|
|
3964
3976
|
estimateRequestTokensCalibrated as estimateRequestTokensCalibrated2,
|
|
3965
|
-
expectDefined,
|
|
3966
3977
|
hasOpenTodos as hasOpenTodos2,
|
|
3967
|
-
toErrorMessage
|
|
3978
|
+
toErrorMessage as toErrorMessage3
|
|
3968
3979
|
} from "@wrongstack/core/utils";
|
|
3969
3980
|
import { readClipboardImage, routeImagesForModel } from "@wrongstack/runtime";
|
|
3970
3981
|
import { createAutoProceedLoopGuard } from "@wrongstack/tools/auto-proceed-loop-guard";
|
|
@@ -4190,11 +4201,210 @@ function registerReplClient(opts) {
|
|
|
4190
4201
|
};
|
|
4191
4202
|
}
|
|
4192
4203
|
|
|
4204
|
+
// src/repl-eternal-loop.ts
|
|
4205
|
+
import { goalFilePath as goalFilePath2, summarizeUsage } from "@wrongstack/core/goal";
|
|
4206
|
+
import { color as color8, toErrorMessage as toErrorMessage2 } from "@wrongstack/core/utils";
|
|
4207
|
+
|
|
4208
|
+
// src/repl-goal-banner.ts
|
|
4209
|
+
import { goalFilePath, loadGoal } from "@wrongstack/core/goal";
|
|
4210
|
+
import { color as color7, expectDefined, toErrorMessage } from "@wrongstack/core/utils";
|
|
4211
|
+
async function loadGoalSafe(opts) {
|
|
4212
|
+
if (!opts.projectRoot) return null;
|
|
4213
|
+
try {
|
|
4214
|
+
return await loadGoal(goalFilePath(opts.projectRoot));
|
|
4215
|
+
} catch {
|
|
4216
|
+
return null;
|
|
4217
|
+
}
|
|
4218
|
+
}
|
|
4219
|
+
async function renderGoalBanner(opts) {
|
|
4220
|
+
const goal = await loadGoalSafe(opts);
|
|
4221
|
+
if (!goal) return;
|
|
4222
|
+
const summary = goal.goal.length > 80 ? `${goal.goal.slice(0, 77)}\u2026` : goal.goal;
|
|
4223
|
+
const stateColor = goal.goalState === "active" ? color7.green : goal.goalState === "paused" ? color7.amber : goal.goalState === "completed" ? color7.green : color7.dim;
|
|
4224
|
+
opts.renderer.write(
|
|
4225
|
+
color7.dim("Goal: ") + stateColor(summary) + color7.dim(` [${goal.goalState}] (iter ${goal.iterations})`) + "\n"
|
|
4226
|
+
);
|
|
4227
|
+
if (goal.journal.length > 0) {
|
|
4228
|
+
const lastEntry = expectDefined(goal.journal[goal.journal.length - 1]);
|
|
4229
|
+
const statusIcon = lastEntry.status === "success" ? "\u2713" : lastEntry.status === "failure" ? "\u2717" : lastEntry.status === "aborted" ? "\u2298" : lastEntry.status === "skipped" ? "\u229D" : "\xB7";
|
|
4230
|
+
opts.renderer.write(
|
|
4231
|
+
color7.dim(` Last: ${statusIcon} ${lastEntry.task} (${lastEntry.status})`) + "\n"
|
|
4232
|
+
);
|
|
4233
|
+
}
|
|
4234
|
+
if (goal.engineState === "running") {
|
|
4235
|
+
opts.renderer.write(
|
|
4236
|
+
color7.amber(" \u21BA Eternal engine was running when last session ended.") + "\n"
|
|
4237
|
+
);
|
|
4238
|
+
try {
|
|
4239
|
+
const answer = (await opts.reader.readLine(color7.dim(" Resume eternal mode? [y/N] "))).trim().toLowerCase();
|
|
4240
|
+
if (answer === "y" || answer === "yes") {
|
|
4241
|
+
try {
|
|
4242
|
+
await opts.slashRegistry.dispatch("/autonomy eternal", opts.agent.ctx);
|
|
4243
|
+
} catch (err) {
|
|
4244
|
+
opts.renderer.writeError(`Auto-resume failed: ${toErrorMessage(err)}`);
|
|
4245
|
+
}
|
|
4246
|
+
} else {
|
|
4247
|
+
opts.renderer.write(
|
|
4248
|
+
color7.dim(" Not resuming. Use `/autonomy eternal` later to continue.") + "\n"
|
|
4249
|
+
);
|
|
4250
|
+
}
|
|
4251
|
+
} catch {
|
|
4252
|
+
opts.renderer.write(color7.dim(" Use `/autonomy eternal` to resume.") + "\n");
|
|
4253
|
+
}
|
|
4254
|
+
} else if (goal.goalState === "paused") {
|
|
4255
|
+
opts.renderer.write(color7.amber(" \u23F8 Goal is paused. Use `/goal resume` to continue.") + "\n");
|
|
4256
|
+
} else if (goal.goalState === "completed") {
|
|
4257
|
+
opts.renderer.write(
|
|
4258
|
+
color7.green(" \u2713 Goal completed! Use `/goal clear` to set a new goal.") + "\n"
|
|
4259
|
+
);
|
|
4260
|
+
} else if (goal.goalState === "abandoned") {
|
|
4261
|
+
opts.renderer.write(color7.dim(" Use `/goal clear` to set a new goal.") + "\n");
|
|
4262
|
+
}
|
|
4263
|
+
opts.renderer.write("\n");
|
|
4264
|
+
}
|
|
4265
|
+
|
|
4266
|
+
// src/repl-eternal-loop.ts
|
|
4267
|
+
async function runReplEternalLoop(opts, onInterruptsReset) {
|
|
4268
|
+
const autonomy = opts.getAutonomy?.();
|
|
4269
|
+
if (autonomy === "eternal") {
|
|
4270
|
+
const engine = opts.getEternalEngine?.();
|
|
4271
|
+
if (!engine) {
|
|
4272
|
+
opts.renderer.writeWarning("Eternal mode set but no engine wired \u2014 falling back to off.");
|
|
4273
|
+
return false;
|
|
4274
|
+
}
|
|
4275
|
+
const beforeGoal = await loadGoalSafe(opts);
|
|
4276
|
+
const beforeIter = beforeGoal?.iterations ?? 0;
|
|
4277
|
+
opts.renderer.write(color8.dim(`
|
|
4278
|
+
\u21B3 [eternal #${beforeIter + 1}] running iteration\u2026
|
|
4279
|
+
`));
|
|
4280
|
+
onInterruptsReset();
|
|
4281
|
+
try {
|
|
4282
|
+
const ok = await engine.runOneIteration();
|
|
4283
|
+
const afterGoal = await loadGoalSafe(opts);
|
|
4284
|
+
const last = afterGoal?.journal[afterGoal.journal.length - 1];
|
|
4285
|
+
if (!ok && !last) {
|
|
4286
|
+
opts.renderer.write(color8.dim(" \u21B3 [eternal] iteration produced no progress.\n"));
|
|
4287
|
+
} else if (last) {
|
|
4288
|
+
const mark = last.status === "success" ? color8.green("\u2713") : last.status === "failure" ? color8.red("\u2717") : color8.amber("\u2298");
|
|
4289
|
+
const tail = last.note ? color8.dim(` \u2014 ${last.note.slice(0, 80)}`) : "";
|
|
4290
|
+
opts.renderer.write(
|
|
4291
|
+
` ${mark} ${color8.dim(`#${last.iteration}`)} ${color8.dim(`[${last.source}]`)} ${last.task}${tail}
|
|
4292
|
+
`
|
|
4293
|
+
);
|
|
4294
|
+
}
|
|
4295
|
+
if (engine.currentState === "stopped") {
|
|
4296
|
+
const goal = await loadGoalSafe(opts);
|
|
4297
|
+
if (goal?.goalState === "completed") {
|
|
4298
|
+
const u = goal.journal.length > 0 ? summarizeUsage(goal) : null;
|
|
4299
|
+
const costLine = u && u.iterationsWithUsage > 0 ? color8.dim(
|
|
4300
|
+
` \u2014 ${u.totalCostUsd.toFixed(4)} \xB7 ${u.totalInputTokens} in / ${u.totalOutputTokens} out \xB7 ${goal.iterations} iterations`
|
|
4301
|
+
) : goal.iterations > 0 ? color8.dim(` \u2014 ${goal.iterations} iterations`) : "";
|
|
4302
|
+
opts.renderer.write(
|
|
4303
|
+
color8.green(`
|
|
4304
|
+
\u{1F3AF} Goal completed!${costLine}
|
|
4305
|
+
|
|
4306
|
+
`) + color8.dim(" Goal cleared. Use /goal set <mission> to create a new goal.\n")
|
|
4307
|
+
);
|
|
4308
|
+
if (opts.projectRoot) {
|
|
4309
|
+
try {
|
|
4310
|
+
const { unlink } = await import("node:fs/promises");
|
|
4311
|
+
await unlink(goalFilePath2(opts.projectRoot));
|
|
4312
|
+
} catch {
|
|
4313
|
+
}
|
|
4314
|
+
}
|
|
4315
|
+
}
|
|
4316
|
+
opts.onAutonomy?.("auto");
|
|
4317
|
+
return true;
|
|
4318
|
+
}
|
|
4319
|
+
} catch (err) {
|
|
4320
|
+
opts.renderer.writeError(`[eternal] ${toErrorMessage2(err)}`);
|
|
4321
|
+
}
|
|
4322
|
+
await new Promise((resolve3) => setTimeout(resolve3, 250));
|
|
4323
|
+
return true;
|
|
4324
|
+
}
|
|
4325
|
+
if (autonomy === "eternal-parallel") {
|
|
4326
|
+
const engine = opts.getParallelEngine?.();
|
|
4327
|
+
if (!engine) {
|
|
4328
|
+
opts.renderer.writeWarning(
|
|
4329
|
+
"Parallel mode set but no engine wired \u2014 falling back to off."
|
|
4330
|
+
);
|
|
4331
|
+
return false;
|
|
4332
|
+
}
|
|
4333
|
+
const beforeGoal = await loadGoalSafe(opts);
|
|
4334
|
+
const beforeIter = beforeGoal?.iterations ?? 0;
|
|
4335
|
+
const coord = engine.getCoordinator();
|
|
4336
|
+
if (coord) {
|
|
4337
|
+
const stats = coord.getStats();
|
|
4338
|
+
opts.renderer.write(
|
|
4339
|
+
color8.dim(
|
|
4340
|
+
` \u250C\u2500 Fleet: ${stats.running} running, ${stats.idle} idle, ${stats.pending} pending, ${stats.completed} done`
|
|
4341
|
+
) + "\n"
|
|
4342
|
+
);
|
|
4343
|
+
}
|
|
4344
|
+
opts.renderer.write(
|
|
4345
|
+
color8.magenta(` \u21B3 [parallel #${beforeIter + 1}] launching fan-out\u2026
|
|
4346
|
+
`)
|
|
4347
|
+
);
|
|
4348
|
+
onInterruptsReset();
|
|
4349
|
+
try {
|
|
4350
|
+
await engine.runOneIteration();
|
|
4351
|
+
const afterGoal = await loadGoalSafe(opts);
|
|
4352
|
+
const last = afterGoal?.journal[afterGoal.journal.length - 1];
|
|
4353
|
+
if (coord) {
|
|
4354
|
+
const stats = coord.getStats();
|
|
4355
|
+
opts.renderer.write(
|
|
4356
|
+
color8.dim(
|
|
4357
|
+
` \u2514\u2500 Fleet: ${stats.running} running, ${stats.idle} idle, ${stats.completed} done
|
|
4358
|
+
`
|
|
4359
|
+
)
|
|
4360
|
+
);
|
|
4361
|
+
}
|
|
4362
|
+
if (last) {
|
|
4363
|
+
const mark = last.status === "success" ? color8.green("\u2713") : last.status === "failure" ? color8.red("\u2717") : color8.amber("\u2298");
|
|
4364
|
+
const tail = last.note ? color8.dim(` \u2014 ${last.note.slice(0, 80)}`) : "";
|
|
4365
|
+
opts.renderer.write(
|
|
4366
|
+
` ${mark} ${color8.dim(`#${last.iteration}`)} ${color8.dim(`[${last.source}]`)} ${last.task}${tail}
|
|
4367
|
+
`
|
|
4368
|
+
);
|
|
4369
|
+
}
|
|
4370
|
+
if (engine.currentState === "stopped") {
|
|
4371
|
+
const goal = await loadGoalSafe(opts);
|
|
4372
|
+
if (goal?.goalState === "completed") {
|
|
4373
|
+
const u = goal.journal.length > 0 ? summarizeUsage(goal) : null;
|
|
4374
|
+
const costLine = u && u.iterationsWithUsage > 0 ? color8.dim(
|
|
4375
|
+
` \u2014 ${u.totalCostUsd.toFixed(4)} \xB7 ${u.totalInputTokens} in / ${u.totalOutputTokens} out \xB7 ${goal.iterations} iterations`
|
|
4376
|
+
) : goal.iterations > 0 ? color8.dim(` \u2014 ${goal.iterations} iterations`) : "";
|
|
4377
|
+
opts.renderer.write(
|
|
4378
|
+
color8.green(`
|
|
4379
|
+
\u{1F3AF} Goal completed!${costLine}
|
|
4380
|
+
|
|
4381
|
+
`) + color8.dim(" Goal cleared. Use /goal set <mission> to create a new goal.\n")
|
|
4382
|
+
);
|
|
4383
|
+
if (opts.projectRoot) {
|
|
4384
|
+
try {
|
|
4385
|
+
const { unlink } = await import("node:fs/promises");
|
|
4386
|
+
await unlink(goalFilePath2(opts.projectRoot));
|
|
4387
|
+
} catch {
|
|
4388
|
+
}
|
|
4389
|
+
}
|
|
4390
|
+
}
|
|
4391
|
+
opts.onAutonomy?.("auto");
|
|
4392
|
+
return true;
|
|
4393
|
+
}
|
|
4394
|
+
} catch (err) {
|
|
4395
|
+
opts.renderer.writeError(`[parallel] ${toErrorMessage2(err)}`);
|
|
4396
|
+
}
|
|
4397
|
+
await new Promise((resolve3) => setTimeout(resolve3, 250));
|
|
4398
|
+
return true;
|
|
4399
|
+
}
|
|
4400
|
+
return false;
|
|
4401
|
+
}
|
|
4402
|
+
|
|
4193
4403
|
// src/repl-input.ts
|
|
4194
|
-
import { color as
|
|
4404
|
+
import { color as color9 } from "@wrongstack/core/utils";
|
|
4195
4405
|
async function readPossiblyMultiline(opts) {
|
|
4196
4406
|
const firstPrompt = theme.primary("\u203A ");
|
|
4197
|
-
const contPrompt =
|
|
4407
|
+
const contPrompt = color9.dim("\xB7 ");
|
|
4198
4408
|
const first = await opts.reader.readLine(firstPrompt);
|
|
4199
4409
|
if (first.trim() === '"""') {
|
|
4200
4410
|
const parts = [];
|
|
@@ -4219,7 +4429,7 @@ async function readPossiblyMultiline(opts) {
|
|
|
4219
4429
|
}
|
|
4220
4430
|
|
|
4221
4431
|
// src/repl-rendering.ts
|
|
4222
|
-
import { color as
|
|
4432
|
+
import { color as color10 } from "@wrongstack/core/utils";
|
|
4223
4433
|
var FILLED = "\u2588";
|
|
4224
4434
|
var EMPTY = "\u2591";
|
|
4225
4435
|
function renderContextChip(used, max) {
|
|
@@ -4236,13 +4446,13 @@ function renderProgress(ratio, width) {
|
|
|
4236
4446
|
}
|
|
4237
4447
|
function printBanner(renderer, projectName) {
|
|
4238
4448
|
const lines = [
|
|
4239
|
-
theme.primary(theme.bold("WrongStack")) +
|
|
4240
|
-
|
|
4449
|
+
theme.primary(theme.bold("WrongStack")) + color10.dim(` v${CLI_VERSION}`),
|
|
4450
|
+
color10.dim("Built on the wrong stack. Shipped anyway.")
|
|
4241
4451
|
];
|
|
4242
4452
|
if (projectName && projectName.length > 0) {
|
|
4243
|
-
lines.push(
|
|
4453
|
+
lines.push(color10.dim("Project: ") + theme.bold(projectName));
|
|
4244
4454
|
}
|
|
4245
|
-
lines.push(
|
|
4455
|
+
lines.push(color10.dim("Type /help for commands, /exit or q to quit."), "");
|
|
4246
4456
|
renderer.write(`${lines.join("\n")}
|
|
4247
4457
|
`);
|
|
4248
4458
|
}
|
|
@@ -4311,144 +4521,21 @@ async function runRepl(opts) {
|
|
|
4311
4521
|
try {
|
|
4312
4522
|
for (; ; ) {
|
|
4313
4523
|
if (exiting) break;
|
|
4314
|
-
|
|
4315
|
-
|
|
4316
|
-
|
|
4317
|
-
opts.renderer.writeWarning("Eternal mode set but no engine wired \u2014 falling back to off.");
|
|
4318
|
-
} else {
|
|
4319
|
-
const beforeGoal = await loadGoalSafe(opts);
|
|
4320
|
-
const beforeIter = beforeGoal?.iterations ?? 0;
|
|
4321
|
-
opts.renderer.write(color9.dim(`
|
|
4322
|
-
\u21B3 [eternal #${beforeIter + 1}] running iteration\u2026
|
|
4323
|
-
`));
|
|
4524
|
+
const autonomy = opts.getAutonomy?.();
|
|
4525
|
+
if (autonomy === "eternal" || autonomy === "eternal-parallel") {
|
|
4526
|
+
const handled = await runReplEternalLoop(opts, () => {
|
|
4324
4527
|
interrupts = 0;
|
|
4325
|
-
|
|
4326
|
-
|
|
4327
|
-
const afterGoal = await loadGoalSafe(opts);
|
|
4328
|
-
const last = afterGoal?.journal[afterGoal.journal.length - 1];
|
|
4329
|
-
if (!ok && !last) {
|
|
4330
|
-
opts.renderer.write(color9.dim(" \u21B3 [eternal] iteration produced no progress.\n"));
|
|
4331
|
-
} else if (last) {
|
|
4332
|
-
const mark = last.status === "success" ? color9.green("\u2713") : last.status === "failure" ? color9.red("\u2717") : color9.amber("\u2298");
|
|
4333
|
-
const tail = last.note ? color9.dim(` \u2014 ${last.note.slice(0, 80)}`) : "";
|
|
4334
|
-
opts.renderer.write(
|
|
4335
|
-
` ${mark} ${color9.dim(`#${last.iteration}`)} ${color9.dim(`[${last.source}]`)} ${last.task}${tail}
|
|
4336
|
-
`
|
|
4337
|
-
);
|
|
4338
|
-
}
|
|
4339
|
-
if (engine.currentState === "stopped") {
|
|
4340
|
-
const goal = await loadGoalSafe(opts);
|
|
4341
|
-
if (goal?.goalState === "completed") {
|
|
4342
|
-
const u = goal.journal.length > 0 ? summarizeUsage(goal) : null;
|
|
4343
|
-
const costLine = u && u.iterationsWithUsage > 0 ? color9.dim(
|
|
4344
|
-
` \u2014 ${u.totalCostUsd.toFixed(4)} \xB7 ${u.totalInputTokens} in / ${u.totalOutputTokens} out \xB7 ${goal.iterations} iterations`
|
|
4345
|
-
) : goal.iterations > 0 ? color9.dim(` \u2014 ${goal.iterations} iterations`) : "";
|
|
4346
|
-
opts.renderer.write(
|
|
4347
|
-
color9.green(`
|
|
4348
|
-
\u{1F3AF} Goal completed!${costLine}
|
|
4349
|
-
|
|
4350
|
-
`) + color9.dim(" Goal cleared. Use /goal set <mission> to create a new goal.\n")
|
|
4351
|
-
);
|
|
4352
|
-
if (opts.projectRoot) {
|
|
4353
|
-
try {
|
|
4354
|
-
const { unlink } = await import("node:fs/promises");
|
|
4355
|
-
await unlink(goalFilePath(opts.projectRoot));
|
|
4356
|
-
} catch {
|
|
4357
|
-
}
|
|
4358
|
-
}
|
|
4359
|
-
}
|
|
4360
|
-
opts.onAutonomy?.("auto");
|
|
4361
|
-
continue;
|
|
4362
|
-
}
|
|
4363
|
-
} catch (err) {
|
|
4364
|
-
opts.renderer.writeError(`[eternal] ${toErrorMessage(err)}`);
|
|
4365
|
-
}
|
|
4366
|
-
await new Promise((resolve3) => setTimeout(resolve3, 250));
|
|
4367
|
-
continue;
|
|
4368
|
-
}
|
|
4369
|
-
} else if (opts.getAutonomy?.() === "eternal-parallel") {
|
|
4370
|
-
const engine = opts.getParallelEngine?.();
|
|
4371
|
-
if (!engine) {
|
|
4372
|
-
opts.renderer.writeWarning(
|
|
4373
|
-
"Parallel mode set but no engine wired \u2014 falling back to off."
|
|
4374
|
-
);
|
|
4375
|
-
} else {
|
|
4376
|
-
const beforeGoal = await loadGoalSafe(opts);
|
|
4377
|
-
const beforeIter = beforeGoal?.iterations ?? 0;
|
|
4378
|
-
const coord = engine.getCoordinator();
|
|
4379
|
-
if (coord) {
|
|
4380
|
-
const stats = coord.getStats();
|
|
4381
|
-
opts.renderer.write(
|
|
4382
|
-
color9.dim(
|
|
4383
|
-
` \u250C\u2500 Fleet: ${stats.running} running, ${stats.idle} idle, ${stats.pending} pending, ${stats.completed} done`
|
|
4384
|
-
) + "\n"
|
|
4385
|
-
);
|
|
4386
|
-
}
|
|
4387
|
-
opts.renderer.write(
|
|
4388
|
-
color9.magenta(` \u21B3 [parallel #${beforeIter + 1}] launching fan-out\u2026
|
|
4389
|
-
`)
|
|
4390
|
-
);
|
|
4391
|
-
interrupts = 0;
|
|
4392
|
-
try {
|
|
4393
|
-
await engine.runOneIteration();
|
|
4394
|
-
const afterGoal = await loadGoalSafe(opts);
|
|
4395
|
-
const last = afterGoal?.journal[afterGoal.journal.length - 1];
|
|
4396
|
-
if (coord) {
|
|
4397
|
-
const stats = coord.getStats();
|
|
4398
|
-
opts.renderer.write(
|
|
4399
|
-
color9.dim(
|
|
4400
|
-
` \u2514\u2500 Fleet: ${stats.running} running, ${stats.idle} idle, ${stats.completed} done
|
|
4401
|
-
`
|
|
4402
|
-
)
|
|
4403
|
-
);
|
|
4404
|
-
}
|
|
4405
|
-
if (last) {
|
|
4406
|
-
const mark = last.status === "success" ? color9.green("\u2713") : last.status === "failure" ? color9.red("\u2717") : color9.amber("\u2298");
|
|
4407
|
-
const tail = last.note ? color9.dim(` \u2014 ${last.note.slice(0, 80)}`) : "";
|
|
4408
|
-
opts.renderer.write(
|
|
4409
|
-
` ${mark} ${color9.dim(`#${last.iteration}`)} ${color9.dim(`[${last.source}]`)} ${last.task}${tail}
|
|
4410
|
-
`
|
|
4411
|
-
);
|
|
4412
|
-
}
|
|
4413
|
-
if (engine.currentState === "stopped") {
|
|
4414
|
-
const goal = await loadGoalSafe(opts);
|
|
4415
|
-
if (goal?.goalState === "completed") {
|
|
4416
|
-
const u = goal.journal.length > 0 ? summarizeUsage(goal) : null;
|
|
4417
|
-
const costLine = u && u.iterationsWithUsage > 0 ? color9.dim(
|
|
4418
|
-
` \u2014 ${u.totalCostUsd.toFixed(4)} \xB7 ${u.totalInputTokens} in / ${u.totalOutputTokens} out \xB7 ${goal.iterations} iterations`
|
|
4419
|
-
) : goal.iterations > 0 ? color9.dim(` \u2014 ${goal.iterations} iterations`) : "";
|
|
4420
|
-
opts.renderer.write(
|
|
4421
|
-
color9.green(`
|
|
4422
|
-
\u{1F3AF} Goal completed!${costLine}
|
|
4423
|
-
|
|
4424
|
-
`) + color9.dim(" Goal cleared. Use /goal set <mission> to create a new goal.\n")
|
|
4425
|
-
);
|
|
4426
|
-
if (opts.projectRoot) {
|
|
4427
|
-
try {
|
|
4428
|
-
const { unlink } = await import("node:fs/promises");
|
|
4429
|
-
await unlink(goalFilePath(opts.projectRoot));
|
|
4430
|
-
} catch {
|
|
4431
|
-
}
|
|
4432
|
-
}
|
|
4433
|
-
}
|
|
4434
|
-
opts.onAutonomy?.("auto");
|
|
4435
|
-
continue;
|
|
4436
|
-
}
|
|
4437
|
-
} catch (err) {
|
|
4438
|
-
opts.renderer.writeError(`[parallel] ${toErrorMessage(err)}`);
|
|
4439
|
-
}
|
|
4440
|
-
await new Promise((resolve3) => setTimeout(resolve3, 250));
|
|
4441
|
-
continue;
|
|
4442
|
-
}
|
|
4528
|
+
});
|
|
4529
|
+
if (handled) continue;
|
|
4443
4530
|
}
|
|
4444
4531
|
{
|
|
4445
4532
|
const mode = opts.getAutonomy?.() ?? "off";
|
|
4446
4533
|
const suggestions = opts.getSuggestions?.() ?? [];
|
|
4447
4534
|
if (mode === "suggest" && suggestions.length > 0) {
|
|
4448
|
-
const lines = suggestions.map((s, i) => ` ${
|
|
4535
|
+
const lines = suggestions.map((s, i) => ` ${color11.bold(`${i + 1}.`)} ${color11.dim(s)}`);
|
|
4449
4536
|
opts.renderer.write(
|
|
4450
4537
|
`
|
|
4451
|
-
${
|
|
4538
|
+
${color11.cyan(" \u{1F4A1} Suggested next steps")} ${color11.dim("(use /next 1, /next 2, or /next 1 2 3)")}
|
|
4452
4539
|
${lines.join("\n")}
|
|
4453
4540
|
|
|
4454
4541
|
`
|
|
@@ -4482,8 +4569,7 @@ ${lines.join("\n")}
|
|
|
4482
4569
|
}
|
|
4483
4570
|
}
|
|
4484
4571
|
}
|
|
4485
|
-
if (
|
|
4486
|
-
} else {
|
|
4572
|
+
if (top) {
|
|
4487
4573
|
const maxAuto = opts.autoProceedMaxIterations ?? DEFAULT_MAX_CONSECUTIVE_AUTO_PROCEED;
|
|
4488
4574
|
if (maxAuto > 0 && autoIterCount >= maxAuto) {
|
|
4489
4575
|
if (!autoCapWarned) {
|
|
@@ -4536,7 +4622,7 @@ ${lines.join("\n")}
|
|
|
4536
4622
|
autoCapWarned = false;
|
|
4537
4623
|
autoProceedLoopGuard.reset();
|
|
4538
4624
|
if (trimmed === "q") {
|
|
4539
|
-
opts.renderer.write(
|
|
4625
|
+
opts.renderer.write(color11.dim(" Goodbye!\n"));
|
|
4540
4626
|
break;
|
|
4541
4627
|
}
|
|
4542
4628
|
if (trimmed === "wd" || trimmed.startsWith("cd ")) {
|
|
@@ -4546,7 +4632,7 @@ ${lines.join("\n")}
|
|
|
4546
4632
|
if (res?.message) opts.renderer.write(`${res.message}
|
|
4547
4633
|
`);
|
|
4548
4634
|
} catch (err) {
|
|
4549
|
-
opts.renderer.writeError(
|
|
4635
|
+
opts.renderer.writeError(toErrorMessage3(err));
|
|
4550
4636
|
}
|
|
4551
4637
|
continue;
|
|
4552
4638
|
}
|
|
@@ -4578,14 +4664,14 @@ ${lines.join("\n")}
|
|
|
4578
4664
|
if (specSaved) {
|
|
4579
4665
|
opts.renderer.write(
|
|
4580
4666
|
`
|
|
4581
|
-
${
|
|
4667
|
+
${color11.cyan(" \u2713 Spec detected and saved! Use /sdd approve to continue.")}
|
|
4582
4668
|
`
|
|
4583
4669
|
);
|
|
4584
4670
|
}
|
|
4585
4671
|
const planSaved = trySaveImplementationPlan(runResult.finalText);
|
|
4586
4672
|
if (planSaved) {
|
|
4587
4673
|
opts.renderer.write(`
|
|
4588
|
-
${
|
|
4674
|
+
${color11.cyan(" \u2713 Implementation plan saved!")}
|
|
4589
4675
|
`);
|
|
4590
4676
|
}
|
|
4591
4677
|
const tasksSaved = await trySaveTasksFromAIOutput(runResult.finalText);
|
|
@@ -4594,7 +4680,7 @@ ${color9.cyan(" \u2713 Implementation plan saved!")}
|
|
|
4594
4680
|
const count = progress?.total ?? 0;
|
|
4595
4681
|
opts.renderer.write(
|
|
4596
4682
|
`
|
|
4597
|
-
${
|
|
4683
|
+
${color11.cyan(` \u2713 ${count} tasks detected and saved! Use /sdd approve to execute.`)}
|
|
4598
4684
|
`
|
|
4599
4685
|
);
|
|
4600
4686
|
}
|
|
@@ -4606,13 +4692,13 @@ ${color9.cyan(` \u2713 ${count} tasks detected and saved! Use /sdd approve to e
|
|
|
4606
4692
|
if (progress) {
|
|
4607
4693
|
opts.renderer.write(
|
|
4608
4694
|
`
|
|
4609
|
-
${
|
|
4695
|
+
${color11.cyan(` \u2713 ${autoCompleted} task(s) auto-completed! Progress: ${progress.completed}/${progress.total} (${progress.percentComplete}%)`)}
|
|
4610
4696
|
`
|
|
4611
4697
|
);
|
|
4612
4698
|
const taskList2 = renderTaskListWithProgress();
|
|
4613
4699
|
if (taskList2) {
|
|
4614
4700
|
opts.renderer.write(`
|
|
4615
|
-
${
|
|
4701
|
+
${color11.dim(taskList2)}
|
|
4616
4702
|
`);
|
|
4617
4703
|
}
|
|
4618
4704
|
}
|
|
@@ -4620,7 +4706,7 @@ ${color9.dim(taskList2)}
|
|
|
4620
4706
|
const taskList2 = renderTaskListWithProgress();
|
|
4621
4707
|
if (taskList2) {
|
|
4622
4708
|
opts.renderer.write(`
|
|
4623
|
-
${
|
|
4709
|
+
${color11.dim(taskList2)}
|
|
4624
4710
|
`);
|
|
4625
4711
|
}
|
|
4626
4712
|
}
|
|
@@ -4638,7 +4724,7 @@ ${color9.dim(taskList2)}
|
|
|
4638
4724
|
}
|
|
4639
4725
|
}
|
|
4640
4726
|
} catch (err) {
|
|
4641
|
-
opts.renderer.writeError(
|
|
4727
|
+
opts.renderer.writeError(toErrorMessage3(err));
|
|
4642
4728
|
}
|
|
4643
4729
|
continue;
|
|
4644
4730
|
}
|
|
@@ -4663,22 +4749,22 @@ ${color9.dim(taskList2)}
|
|
|
4663
4749
|
}
|
|
4664
4750
|
if (resolved.source === "open") {
|
|
4665
4751
|
opts.renderer.write(
|
|
4666
|
-
` ${
|
|
4667
|
-
` +
|
|
4752
|
+
` ${color11.amber("\u26A0")} ${color11.bold("'continue' has no anchor")} ${color11.dim("\u2014 no pending todo or suggestion.")}
|
|
4753
|
+
` + color11.dim(
|
|
4668
4754
|
" If you proceed, I'll choose the next step from context; that can drift.\n"
|
|
4669
4755
|
)
|
|
4670
4756
|
);
|
|
4671
|
-
const ans = (await opts.reader.readLine(
|
|
4757
|
+
const ans = (await opts.reader.readLine(color11.dim(" Proceed anyway? [Y/n \xB7 e = type your own] "))).trim().toLowerCase();
|
|
4672
4758
|
if (ans === "n" || ans === "no") {
|
|
4673
|
-
opts.renderer.write(
|
|
4759
|
+
opts.renderer.write(color11.dim(" Cancelled \u2014 nothing sent.\n"));
|
|
4674
4760
|
continue;
|
|
4675
4761
|
}
|
|
4676
4762
|
if (ans === "e" || ans === "edit") {
|
|
4677
|
-
opts.renderer.write(
|
|
4763
|
+
opts.renderer.write(color11.dim(" Okay \u2014 type what to continue with.\n"));
|
|
4678
4764
|
continue;
|
|
4679
4765
|
}
|
|
4680
4766
|
} else {
|
|
4681
|
-
opts.renderer.write(
|
|
4767
|
+
opts.renderer.write(color11.dim(` ${resolved.label}
|
|
4682
4768
|
`));
|
|
4683
4769
|
}
|
|
4684
4770
|
builder.appendText(resolved.text);
|
|
@@ -4686,7 +4772,7 @@ ${color9.dim(taskList2)}
|
|
|
4686
4772
|
const ph = await builder.appendPaste(raw);
|
|
4687
4773
|
if (ph) {
|
|
4688
4774
|
const lineCount = raw.split("\n").length;
|
|
4689
|
-
opts.renderer.write(
|
|
4775
|
+
opts.renderer.write(color11.dim(` \u21B3 ${ph} (${lineCount} lines)
|
|
4690
4776
|
`));
|
|
4691
4777
|
}
|
|
4692
4778
|
}
|
|
@@ -4739,7 +4825,7 @@ ${taskList}`;
|
|
|
4739
4825
|
}) : { blocks: effectiveBlocks, route: "none", convertedImages: 0 };
|
|
4740
4826
|
if (routed.route === "adapter") {
|
|
4741
4827
|
opts.renderer.write(
|
|
4742
|
-
|
|
4828
|
+
color11.dim(
|
|
4743
4829
|
` \u21B3 image analyzed via ${routed.adapterName ?? "vision adapter"} (${routed.convertedImages} image${routed.convertedImages === 1 ? "" : "s"})
|
|
4744
4830
|
`
|
|
4745
4831
|
)
|
|
@@ -4773,14 +4859,14 @@ ${taskList}`;
|
|
|
4773
4859
|
if (specSaved) {
|
|
4774
4860
|
opts.renderer.write(
|
|
4775
4861
|
`
|
|
4776
|
-
${
|
|
4862
|
+
${color11.cyan(" \u2713 Spec detected and saved! Use /sdd approve to continue.")}
|
|
4777
4863
|
`
|
|
4778
4864
|
);
|
|
4779
4865
|
}
|
|
4780
4866
|
const planSaved = trySaveImplementationPlan(result.finalText);
|
|
4781
4867
|
if (planSaved) {
|
|
4782
4868
|
opts.renderer.write(`
|
|
4783
|
-
${
|
|
4869
|
+
${color11.cyan(" \u2713 Implementation plan saved!")}
|
|
4784
4870
|
`);
|
|
4785
4871
|
}
|
|
4786
4872
|
const tasksSaved = await trySaveTasksFromAIOutput(result.finalText);
|
|
@@ -4789,7 +4875,7 @@ ${color9.cyan(" \u2713 Implementation plan saved!")}
|
|
|
4789
4875
|
const count = progress?.total ?? 0;
|
|
4790
4876
|
opts.renderer.write(
|
|
4791
4877
|
`
|
|
4792
|
-
${
|
|
4878
|
+
${color11.cyan(` \u2713 ${count} tasks detected and saved! Use /sdd approve to execute.`)}
|
|
4793
4879
|
`
|
|
4794
4880
|
);
|
|
4795
4881
|
}
|
|
@@ -4801,13 +4887,13 @@ ${color9.cyan(` \u2713 ${count} tasks detected and saved! Use /sdd approve to e
|
|
|
4801
4887
|
if (progress) {
|
|
4802
4888
|
opts.renderer.write(
|
|
4803
4889
|
`
|
|
4804
|
-
${
|
|
4890
|
+
${color11.cyan(` \u2713 ${autoCompleted} task(s) auto-completed! Progress: ${progress.completed}/${progress.total} (${progress.percentComplete}%)`)}
|
|
4805
4891
|
`
|
|
4806
4892
|
);
|
|
4807
4893
|
if (progress.percentComplete === 100) {
|
|
4808
4894
|
opts.renderer.write(
|
|
4809
4895
|
`
|
|
4810
|
-
${
|
|
4896
|
+
${color11.green(" \u{1F389} All tasks completed! Use /sdd cancel to end the session.")}
|
|
4811
4897
|
`
|
|
4812
4898
|
);
|
|
4813
4899
|
}
|
|
@@ -4816,14 +4902,14 @@ ${color9.green(" \u{1F389} All tasks completed! Use /sdd cancel to end the sess
|
|
|
4816
4902
|
const taskList2 = renderTaskListWithProgress();
|
|
4817
4903
|
if (taskList2) {
|
|
4818
4904
|
opts.renderer.write(`
|
|
4819
|
-
${
|
|
4905
|
+
${color11.dim(taskList2)}
|
|
4820
4906
|
`);
|
|
4821
4907
|
}
|
|
4822
4908
|
} else {
|
|
4823
4909
|
const taskList2 = renderTaskListWithProgress();
|
|
4824
4910
|
if (taskList2) {
|
|
4825
4911
|
opts.renderer.write(`
|
|
4826
|
-
${
|
|
4912
|
+
${color11.dim(taskList2)}
|
|
4827
4913
|
`);
|
|
4828
4914
|
}
|
|
4829
4915
|
}
|
|
@@ -4840,15 +4926,15 @@ ${color9.dim(taskList2)}
|
|
|
4840
4926
|
const ctxChip = effectiveMaxContext && effectiveMaxContext > 0 ? ` ctx: ${renderContextChip(after.input, effectiveMaxContext)}` : "";
|
|
4841
4927
|
opts.renderer.write(
|
|
4842
4928
|
`
|
|
4843
|
-
${
|
|
4929
|
+
${color11.dim(
|
|
4844
4930
|
`[in: ${fmtTok(after.input - before.input)} out: ${fmtTok(after.output - before.output)} iters: ${result.iterations} cost: ${(costAfter - costBefore).toFixed(4)} ${((Date.now() - startedAt) / 1e3).toFixed(1)}s]${ctxChip}`
|
|
4845
4931
|
)}
|
|
4846
4932
|
`
|
|
4847
4933
|
);
|
|
4848
4934
|
}
|
|
4849
4935
|
if (result.status === "done" && opts.getAutonomy) {
|
|
4850
|
-
const
|
|
4851
|
-
if (
|
|
4936
|
+
const autonomy2 = opts.getAutonomy();
|
|
4937
|
+
if (autonomy2 === "suggest" && !hasOpenTodos2(opts.agent.ctx.todos)) {
|
|
4852
4938
|
const suggestPrompt = 'Based on what you just did, suggest 3 exact prompt messages that can be submitted back to you through the TUI or WebUI. Each prompt must ask the agent to perform work; never assign a manual chore to the user. If you include suggestions, wrap them in a balanced <nextsteps>...</nextsteps> block, with one numbered prompt per line and no explanation. If there is nothing meaningful left, say "No further steps needed."';
|
|
4853
4939
|
const suggestBlocks = [{ type: "text", text: suggestPrompt }];
|
|
4854
4940
|
const suggestCtrl = new AbortController();
|
|
@@ -4867,7 +4953,7 @@ ${color9.dim(
|
|
|
4867
4953
|
if (suggestResult.status === "done" && suggestResult.finalText) {
|
|
4868
4954
|
opts.renderer.write(
|
|
4869
4955
|
`
|
|
4870
|
-
${
|
|
4956
|
+
${color11.cyan(" Suggested next steps:")}
|
|
4871
4957
|
${suggestResult.finalText}
|
|
4872
4958
|
`
|
|
4873
4959
|
);
|
|
@@ -4886,8 +4972,8 @@ ${suggestResult.finalText}
|
|
|
4886
4972
|
}
|
|
4887
4973
|
}
|
|
4888
4974
|
if (result.status === "done" && opts.getNextPredict?.() && !hasOpenTodos2(opts.agent.ctx.todos)) {
|
|
4889
|
-
const
|
|
4890
|
-
if (
|
|
4975
|
+
const autonomy2 = opts.getAutonomy?.() ?? "off";
|
|
4976
|
+
if (autonomy2 === "off") {
|
|
4891
4977
|
const predictCtrl = new AbortController();
|
|
4892
4978
|
activeCtrl = predictCtrl;
|
|
4893
4979
|
try {
|
|
@@ -4906,8 +4992,8 @@ ${suggestResult.finalText}
|
|
|
4906
4992
|
if (predictions.length > 0) {
|
|
4907
4993
|
const lines = predictions.map((p, i) => ` ${i + 1}. ${p}`).join("\n");
|
|
4908
4994
|
opts.renderer.write(`
|
|
4909
|
-
${
|
|
4910
|
-
${
|
|
4995
|
+
${color11.dim(" \u21B3 likely next:")}
|
|
4996
|
+
${color11.dim(lines)}
|
|
4911
4997
|
`);
|
|
4912
4998
|
}
|
|
4913
4999
|
} catch {
|
|
@@ -4917,7 +5003,7 @@ ${color9.dim(lines)}
|
|
|
4917
5003
|
}
|
|
4918
5004
|
}
|
|
4919
5005
|
} catch (err) {
|
|
4920
|
-
opts.renderer.writeError(
|
|
5006
|
+
opts.renderer.writeError(toErrorMessage3(err));
|
|
4921
5007
|
} finally {
|
|
4922
5008
|
activeCtrl = void 0;
|
|
4923
5009
|
}
|
|
@@ -4935,71 +5021,17 @@ async function pasteClipboardImage(builder, opts) {
|
|
|
4935
5021
|
try {
|
|
4936
5022
|
const img = await readClipboardImage();
|
|
4937
5023
|
if (!img) {
|
|
4938
|
-
opts.renderer.write(
|
|
5024
|
+
opts.renderer.write(color11.dim(" no image on clipboard\n"));
|
|
4939
5025
|
return;
|
|
4940
5026
|
}
|
|
4941
5027
|
const placeholder = await builder.appendImage(img.base64, img.mediaType);
|
|
4942
5028
|
const kb = (img.bytes / 1024).toFixed(0);
|
|
4943
|
-
opts.renderer.write(
|
|
5029
|
+
opts.renderer.write(color11.dim(` \u21B3 ${placeholder} (PNG ${kb}KB)
|
|
4944
5030
|
`));
|
|
4945
5031
|
} catch (err) {
|
|
4946
|
-
opts.renderer.writeError(`Clipboard image error: ${
|
|
5032
|
+
opts.renderer.writeError(`Clipboard image error: ${toErrorMessage3(err)}`);
|
|
4947
5033
|
}
|
|
4948
5034
|
}
|
|
4949
|
-
async function loadGoalSafe(opts) {
|
|
4950
|
-
if (!opts.projectRoot) return null;
|
|
4951
|
-
try {
|
|
4952
|
-
return await loadGoal(goalFilePath(opts.projectRoot));
|
|
4953
|
-
} catch {
|
|
4954
|
-
return null;
|
|
4955
|
-
}
|
|
4956
|
-
}
|
|
4957
|
-
async function renderGoalBanner(opts) {
|
|
4958
|
-
const goal = await loadGoalSafe(opts);
|
|
4959
|
-
if (!goal) return;
|
|
4960
|
-
const summary = goal.goal.length > 80 ? `${goal.goal.slice(0, 77)}\u2026` : goal.goal;
|
|
4961
|
-
const stateColor = goal.goalState === "active" ? color9.green : goal.goalState === "paused" ? color9.amber : goal.goalState === "completed" ? color9.green : goal.goalState === "abandoned" ? color9.dim : color9.dim;
|
|
4962
|
-
opts.renderer.write(
|
|
4963
|
-
color9.dim("Goal: ") + stateColor(summary) + color9.dim(` [${goal.goalState}] (iter ${goal.iterations})`) + "\n"
|
|
4964
|
-
);
|
|
4965
|
-
if (goal.journal.length > 0) {
|
|
4966
|
-
const lastEntry = expectDefined(goal.journal[goal.journal.length - 1]);
|
|
4967
|
-
const statusIcon = lastEntry.status === "success" ? "\u2713" : lastEntry.status === "failure" ? "\u2717" : lastEntry.status === "aborted" ? "\u2298" : lastEntry.status === "skipped" ? "\u229D" : "\xB7";
|
|
4968
|
-
opts.renderer.write(
|
|
4969
|
-
color9.dim(` Last: ${statusIcon} ${lastEntry.task} (${lastEntry.status})`) + "\n"
|
|
4970
|
-
);
|
|
4971
|
-
}
|
|
4972
|
-
if (goal.engineState === "running") {
|
|
4973
|
-
opts.renderer.write(
|
|
4974
|
-
color9.amber(" \u21BA Eternal engine was running when last session ended.") + "\n"
|
|
4975
|
-
);
|
|
4976
|
-
try {
|
|
4977
|
-
const answer = (await opts.reader.readLine(color9.dim(" Resume eternal mode? [y/N] "))).trim().toLowerCase();
|
|
4978
|
-
if (answer === "y" || answer === "yes") {
|
|
4979
|
-
try {
|
|
4980
|
-
await opts.slashRegistry.dispatch("/autonomy eternal", opts.agent.ctx);
|
|
4981
|
-
} catch (err) {
|
|
4982
|
-
opts.renderer.writeError(`Auto-resume failed: ${toErrorMessage(err)}`);
|
|
4983
|
-
}
|
|
4984
|
-
} else {
|
|
4985
|
-
opts.renderer.write(
|
|
4986
|
-
color9.dim(" Not resuming. Use `/autonomy eternal` later to continue.") + "\n"
|
|
4987
|
-
);
|
|
4988
|
-
}
|
|
4989
|
-
} catch {
|
|
4990
|
-
opts.renderer.write(color9.dim(" Use `/autonomy eternal` to resume.") + "\n");
|
|
4991
|
-
}
|
|
4992
|
-
} else if (goal.goalState === "paused") {
|
|
4993
|
-
opts.renderer.write(color9.amber(" \u23F8 Goal is paused. Use `/goal resume` to continue.") + "\n");
|
|
4994
|
-
} else if (goal.goalState === "completed") {
|
|
4995
|
-
opts.renderer.write(
|
|
4996
|
-
color9.green(" \u2713 Goal completed! Use `/goal clear` to set a new goal.") + "\n"
|
|
4997
|
-
);
|
|
4998
|
-
} else if (goal.goalState === "abandoned") {
|
|
4999
|
-
opts.renderer.write(color9.dim(" Use `/goal clear` to set a new goal.") + "\n");
|
|
5000
|
-
}
|
|
5001
|
-
opts.renderer.write("\n");
|
|
5002
|
-
}
|
|
5003
5035
|
|
|
5004
5036
|
// src/execution-tui-next-step-callbacks.ts
|
|
5005
5037
|
function createTuiNextStepCallbacks(input) {
|
|
@@ -5998,4 +6030,4 @@ export {
|
|
|
5998
6030
|
execute,
|
|
5999
6031
|
resolveReviewerFallbackModels
|
|
6000
6032
|
};
|
|
6001
|
-
//# sourceMappingURL=execution-
|
|
6033
|
+
//# sourceMappingURL=execution-CGT6J5ZN.js.map
|