@wrongstack/cli 0.300.0 → 0.302.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/{acp-IDNS2YVE.js → acp-DATHHPNT.js} +34 -15
- package/dist/acp-server-agent.d.ts +1 -1
- package/dist/{audit-2ZSFGNIF.js → audit-QRCLEHHW.js} +5 -1
- package/dist/{auth-6T6ZOT2R.js → auth-PJD3JRH2.js} +150 -37
- package/dist/boot/dispatch-webui.d.ts +3 -16
- package/dist/boot/launch-menu.d.ts +2 -4
- package/dist/boot/tool-registry.d.ts +3 -0
- package/dist/boot/webui-session-child.d.ts +91 -0
- package/dist/chimera-reviewer-policy.d.ts +10 -3
- package/dist/chimera-work-registry.d.ts +19 -0
- package/dist/{chronicle-QQEQFSSE.js → chronicle-63MFCZN6.js} +26 -5
- package/dist/{chunk-YWUPHRGB.js → chunk-263G3FMB.js} +33 -10
- package/dist/{chunk-GYDQABMA.js → chunk-2KDOFTTM.js} +44 -32
- package/dist/{chunk-V76R7DC5.js → chunk-3MOUBRKZ.js} +311 -309
- package/dist/chunk-CSAPOCBP.js +24 -0
- package/dist/{chunk-N7ULWBO5.js → chunk-ETOEGL3V.js} +3 -7
- package/dist/{chunk-3MWUZMOL.js → chunk-GUHQQG63.js} +14 -3
- package/dist/chunk-KE7E7DPX.js +38 -0
- package/dist/{chunk-PEMN4T5O.js → chunk-MT6FGXO3.js} +23 -4
- package/dist/chunk-PFVVUH5B.js +127 -0
- package/dist/{chunk-DPJZQCVP.js → chunk-YMXXOOFN.js} +1 -1
- package/dist/{chunk-4WJKVQJY.js → chunk-ZECLGUTF.js} +15 -3
- package/dist/cli-context.d.ts +2 -0
- package/dist/{cli-main-7B3G2YSG.js → cli-main-EOJ74CI4.js} +336 -99
- package/dist/execute-deps.d.ts +3 -0
- package/dist/{execution-SHGM7BVC.js → execution-CQ772VPS.js} +246 -97
- package/dist/execution-chimera-cascade.d.ts +3 -4
- package/dist/execution-chimera-review.d.ts +2 -3
- package/dist/execution-cleanup.d.ts +3 -2
- package/dist/execution.d.ts +1 -1
- package/dist/{export-TPORYVRZ.js → export-DOBGPY23.js} +12 -1
- package/dist/fleet/host-context.d.ts +1 -1
- package/dist/fleet/host-helpers.d.ts +14 -0
- package/dist/fleet/status-broadcast.d.ts +1 -1
- package/dist/{hq-DVDD4XPV.js → hq-LN5CJHCM.js} +2 -2
- package/dist/hq-server/routes.d.ts +10 -1
- package/dist/hq-server/ws.d.ts +17 -6
- package/dist/{hq-server-DQHLNHDL.js → hq-server-S7HZG3PA.js} +3 -2
- package/dist/index.js +142 -100
- package/dist/live-settings-input.d.ts +5 -0
- package/dist/{mcp-CYLPUEHC.js → mcp-OHPJH73U.js} +6 -2
- package/dist/{modeldiag-YOQZHBQV.js → modeldiag-3DOK4BWW.js} +2 -2
- package/dist/{plugin-usage-EOG4ET4S.js → plugin-usage-YEVLOR33.js} +7 -3
- package/dist/{plugins-56CMWMPR.js → plugins-K3BAUP4D.js} +3 -3
- package/dist/profile-config-path.d.ts +0 -2
- package/dist/provider-helpers.d.ts +0 -5
- package/dist/{providers-models-K6RT7ABI.js → providers-models-WEZ4EGLL.js} +6 -5
- package/dist/{replay-KCTXNMZQ.js → replay-FCBNHW3K.js} +5 -1
- package/dist/{rewind-EJMVFVLS.js → rewind-AOD3JIYX.js} +5 -1
- package/dist/{sessions-config-NLCMK3BY.js → sessions-config-XXN7267N.js} +8 -3
- package/dist/subcommands/flags.d.ts +23 -0
- package/dist/terminal-format.d.ts +15 -0
- package/dist/{webui-server-G3EKFXLL.js → webui-server-NFNRGNNT.js} +54 -29
- package/dist/webui-server-options.d.ts +7 -0
- package/dist/wiring/brain-and-orchestration.d.ts +1 -1
- package/dist/wiring/mailbox-bridge-bootstrap.d.ts +3 -1
- package/dist/wiring/management-tools.d.ts +9 -1
- package/dist/wiring/pipeline.d.ts +5 -5
- package/dist/wiring/plugins.d.ts +2 -3
- package/dist/wiring/provider-utility-tools.d.ts +1 -0
- package/dist/wiring/tools.d.ts +4 -5
- package/package.json +23 -23
|
@@ -25,22 +25,34 @@ import {
|
|
|
25
25
|
trySaveSpecFromAIOutput,
|
|
26
26
|
trySaveTasksFromAIOutput
|
|
27
27
|
} from "./chunk-XTIXVJXP.js";
|
|
28
|
+
import {
|
|
29
|
+
WEBUI_SESSION_CHILD_CAPABILITIES,
|
|
30
|
+
writeWebuiSessionChildError,
|
|
31
|
+
writeWebuiSessionChildReady
|
|
32
|
+
} from "./chunk-PFVVUH5B.js";
|
|
28
33
|
import {
|
|
29
34
|
theme
|
|
30
35
|
} from "./chunk-QD544J2B.js";
|
|
31
36
|
import {
|
|
32
37
|
fmtTok
|
|
33
38
|
} from "./chunk-TYO2OVAD.js";
|
|
39
|
+
import {
|
|
40
|
+
terminalLink,
|
|
41
|
+
terminalText
|
|
42
|
+
} from "./chunk-KE7E7DPX.js";
|
|
34
43
|
import {
|
|
35
44
|
CLI_VERSION
|
|
36
45
|
} from "./chunk-XJXDOF63.js";
|
|
37
46
|
import {
|
|
38
47
|
resolveActiveApiKey
|
|
39
48
|
} from "./chunk-PJHET45A.js";
|
|
49
|
+
import {
|
|
50
|
+
activeProfileConfigPath
|
|
51
|
+
} from "./chunk-YMXXOOFN.js";
|
|
40
52
|
import "./chunk-7OCVIDC7.js";
|
|
41
53
|
|
|
42
54
|
// src/execution.ts
|
|
43
|
-
import * as
|
|
55
|
+
import * as path12 from "node:path";
|
|
44
56
|
import { effectiveFallbackChain as effectiveFallbackChain2, setQueuedMessagesSnapshot as setQueuedMessagesSnapshot2 } from "@wrongstack/core/agent";
|
|
45
57
|
import { attachTodosCheckpoint as attachTodosCheckpoint2 } from "@wrongstack/core/storage";
|
|
46
58
|
import { normalizeTokenSavingTier as normalizeTokenSavingTier2 } from "@wrongstack/core/types";
|
|
@@ -148,6 +160,7 @@ async function runTuiDispatch(options) {
|
|
|
148
160
|
}
|
|
149
161
|
|
|
150
162
|
// src/boot/dispatch-webui.ts
|
|
163
|
+
import * as path from "node:path";
|
|
151
164
|
import { color as color2 } from "@wrongstack/core/utils";
|
|
152
165
|
async function runWebUIDispatch(ctx) {
|
|
153
166
|
const {
|
|
@@ -183,12 +196,14 @@ async function runWebUIDispatch(ctx) {
|
|
|
183
196
|
agentTranscripts,
|
|
184
197
|
sddSubagentFactory,
|
|
185
198
|
onKanbanDispatch,
|
|
186
|
-
getFleetBudget
|
|
199
|
+
getFleetBudget,
|
|
200
|
+
webuiSessionChild
|
|
187
201
|
} = ctx;
|
|
188
|
-
const
|
|
202
|
+
const isSessionChild = Boolean(webuiSessionChild);
|
|
203
|
+
const isSimpleUi = !isSessionChild && flags["simpleui"] === true;
|
|
189
204
|
agent.disableInteractiveConfirmation();
|
|
190
205
|
renderer.setSilent(true);
|
|
191
|
-
const { runWebUI } = await import("./webui-server-
|
|
206
|
+
const { runWebUI } = await import("./webui-server-NFNRGNNT.js");
|
|
192
207
|
const flagValue = (names) => {
|
|
193
208
|
for (const name of names) {
|
|
194
209
|
if (!Object.hasOwn(flags, name)) continue;
|
|
@@ -231,22 +246,32 @@ async function runWebUIDispatch(ctx) {
|
|
|
231
246
|
let webuiRequireToken;
|
|
232
247
|
let frontendDistDir;
|
|
233
248
|
try {
|
|
234
|
-
webuiHost = flagValue(["webui-host", "host"]) ?? process.env["WEBUI_HOST"] ?? process.env["WS_HOST"] ?? "127.0.0.1";
|
|
249
|
+
webuiHost = webuiSessionChild?.host ?? flagValue(["webui-host", "host"]) ?? process.env["WEBUI_HOST"] ?? process.env["WS_HOST"] ?? "127.0.0.1";
|
|
235
250
|
const defaultPort = isSimpleUi ? 3466 : 3456;
|
|
236
|
-
webuiPort = parsePort(
|
|
251
|
+
webuiPort = webuiSessionChild?.port ?? parsePort(
|
|
237
252
|
flagValue(["webui-port", "http-port", "port", "ws-port"]) ?? process.env["WEBUI_PORT"] ?? process.env["PORT"] ?? process.env["WS_PORT"],
|
|
238
253
|
defaultPort,
|
|
239
254
|
"--port"
|
|
240
255
|
);
|
|
241
|
-
webuiAccessToken = flagValue(["webui-token"]) ?? process.env["WEBUI_TOKEN"] ?? process.env["WEBUI_AUTH_TOKEN"];
|
|
242
|
-
webuiPublicUrl = flagValue(["webui-public-url", "public-url"]) ?? process.env["WEBUI_PUBLIC_URL"];
|
|
243
|
-
webuiPublicWsUrl = flagValue(["webui-public-ws-url", "public-ws-url"]) ?? process.env["WEBUI_PUBLIC_WS_URL"];
|
|
244
|
-
webuiRequireToken = flagBoolean(["webui-require-token", "require-token"]) ?? envFlag("WEBUI_REQUIRE_TOKEN");
|
|
256
|
+
webuiAccessToken = webuiSessionChild?.token ?? flagValue(["webui-token"]) ?? process.env["WEBUI_TOKEN"] ?? process.env["WEBUI_AUTH_TOKEN"];
|
|
257
|
+
webuiPublicUrl = webuiSessionChild?.publicUrl ?? flagValue(["webui-public-url", "public-url"]) ?? process.env["WEBUI_PUBLIC_URL"];
|
|
258
|
+
webuiPublicWsUrl = webuiSessionChild?.publicWsUrl ?? flagValue(["webui-public-ws-url", "public-ws-url"]) ?? process.env["WEBUI_PUBLIC_WS_URL"];
|
|
259
|
+
webuiRequireToken = webuiSessionChild?.requireToken ?? flagBoolean(["webui-require-token", "require-token"]) ?? envFlag("WEBUI_REQUIRE_TOKEN");
|
|
245
260
|
if (isSimpleUi) {
|
|
246
261
|
const { ensureSimpleUiDistDir } = await import("./simpleui-dist-JIFGUJO7.js");
|
|
247
262
|
frontendDistDir = await ensureSimpleUiDistDir();
|
|
248
263
|
}
|
|
249
264
|
} catch (err) {
|
|
265
|
+
if (webuiSessionChild) {
|
|
266
|
+
await writeWebuiSessionChildError(webuiSessionChild.readyFile, {
|
|
267
|
+
protocolVersion: webuiSessionChild.protocolVersion,
|
|
268
|
+
runtimeId: webuiSessionChild.runtimeId,
|
|
269
|
+
parentShellId: webuiSessionChild.parentShellId,
|
|
270
|
+
phase: "validate_args",
|
|
271
|
+
recoverable: false,
|
|
272
|
+
error: err
|
|
273
|
+
}).catch(() => void 0);
|
|
274
|
+
}
|
|
250
275
|
renderer.setSilent(false);
|
|
251
276
|
renderer.writeInfo(color2.red(` ${err instanceof Error ? err.message : String(err)}`));
|
|
252
277
|
return 1;
|
|
@@ -264,9 +289,11 @@ async function runWebUIDispatch(ctx) {
|
|
|
264
289
|
publicUrl: webuiPublicUrl,
|
|
265
290
|
publicWsUrl: webuiPublicWsUrl,
|
|
266
291
|
requireToken: webuiRequireToken,
|
|
292
|
+
strictPort: webuiSessionChild?.strictPort,
|
|
267
293
|
projectRoot,
|
|
268
294
|
appConfig: config,
|
|
269
|
-
open: !!flags.open,
|
|
295
|
+
open: webuiSessionChild ? false : !!flags.open,
|
|
296
|
+
webuiSessionChild,
|
|
270
297
|
agentTranscripts,
|
|
271
298
|
hqAllowExec: flagBoolean(["hq-allow-exec"]) ?? false,
|
|
272
299
|
modelsRegistry,
|
|
@@ -309,12 +336,57 @@ async function runWebUIDispatch(ctx) {
|
|
|
309
336
|
// listening, using the RESOLVED port. Requested ports auto-advance past
|
|
310
337
|
// busy ports inside runWebUI, so a banner printed up-front lies whenever
|
|
311
338
|
// the default when it is taken (a second instance, leftover socket).
|
|
312
|
-
onListening: ({ url }) => {
|
|
339
|
+
onListening: ({ httpPort, host, url, authToken }) => {
|
|
340
|
+
if (webuiSessionChild) {
|
|
341
|
+
void writeWebuiSessionChildReady(webuiSessionChild.readyFile, {
|
|
342
|
+
type: "webui.session_child.ready",
|
|
343
|
+
protocolVersion: webuiSessionChild.protocolVersion,
|
|
344
|
+
runtime: {
|
|
345
|
+
role: "session-child",
|
|
346
|
+
runtimeId: webuiSessionChild.runtimeId,
|
|
347
|
+
pid: process.pid,
|
|
348
|
+
parentPid: webuiSessionChild.parentPid,
|
|
349
|
+
parentShellId: webuiSessionChild.parentShellId,
|
|
350
|
+
startedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
351
|
+
},
|
|
352
|
+
project: {
|
|
353
|
+
projectRoot,
|
|
354
|
+
workingDir: webuiSessionChild.workingDir,
|
|
355
|
+
projectSlug: path.basename(projectRoot) || projectRoot,
|
|
356
|
+
projectName: path.basename(projectRoot) || projectRoot
|
|
357
|
+
},
|
|
358
|
+
session: {
|
|
359
|
+
sessionId: session.id,
|
|
360
|
+
created: !webuiSessionChild.resume,
|
|
361
|
+
resumed: webuiSessionChild.resume,
|
|
362
|
+
provider: config.provider,
|
|
363
|
+
model: config.model
|
|
364
|
+
},
|
|
365
|
+
endpoint: {
|
|
366
|
+
surface: "webui",
|
|
367
|
+
host,
|
|
368
|
+
httpPort,
|
|
369
|
+
url,
|
|
370
|
+
...webuiPublicUrl ? { publicUrl: webuiPublicUrl } : {},
|
|
371
|
+
...webuiPublicWsUrl ? { publicWsUrl: webuiPublicWsUrl } : {},
|
|
372
|
+
requireToken: webuiRequireToken,
|
|
373
|
+
auth: authToken ? { scheme: "registry-token", tokenPresent: true, token: authToken } : { scheme: "none", tokenPresent: false }
|
|
374
|
+
},
|
|
375
|
+
registry: {
|
|
376
|
+
webuiInstanceRegistered: true,
|
|
377
|
+
sessionRegistered: true
|
|
378
|
+
},
|
|
379
|
+
capabilities: [...WEBUI_SESSION_CHILD_CAPABILITIES]
|
|
380
|
+
}).catch(() => void 0);
|
|
381
|
+
return;
|
|
382
|
+
}
|
|
313
383
|
const surface = isSimpleUi ? "SimpleUI" : "WebUI";
|
|
314
|
-
renderer.writeInfo(color2.green(` \u2726 ${surface} running \u2192 ${color2.bold(url)}`));
|
|
315
384
|
renderer.writeInfo(
|
|
316
|
-
|
|
317
|
-
|
|
385
|
+
` \u2726 ${terminalText(surface, "success", { bold: true })} ${terminalText("running \u2192", "muted")} ${terminalLink(url)}`
|
|
386
|
+
);
|
|
387
|
+
renderer.writeInfo(
|
|
388
|
+
` ${terminalText(`Press Ctrl+C in this terminal to stop the ${surface} server.`, "muted")}
|
|
389
|
+
`
|
|
318
390
|
);
|
|
319
391
|
},
|
|
320
392
|
// Make autonomy.switch from the browser flip the CLI's real
|
|
@@ -337,6 +409,16 @@ async function runWebUIDispatch(ctx) {
|
|
|
337
409
|
);
|
|
338
410
|
resolve3(0);
|
|
339
411
|
}).catch((err) => {
|
|
412
|
+
if (webuiSessionChild) {
|
|
413
|
+
void writeWebuiSessionChildError(webuiSessionChild.readyFile, {
|
|
414
|
+
protocolVersion: webuiSessionChild.protocolVersion,
|
|
415
|
+
runtimeId: webuiSessionChild.runtimeId,
|
|
416
|
+
parentShellId: webuiSessionChild.parentShellId,
|
|
417
|
+
phase: "start_server",
|
|
418
|
+
recoverable: false,
|
|
419
|
+
error: err
|
|
420
|
+
}).catch(() => void 0);
|
|
421
|
+
}
|
|
340
422
|
renderer.setSilent(false);
|
|
341
423
|
renderer.writeInfo(
|
|
342
424
|
color2.red(
|
|
@@ -353,8 +435,8 @@ async function runWebUIDispatch(ctx) {
|
|
|
353
435
|
function resolveExecutionMode(positional, flags) {
|
|
354
436
|
const prompt = typeof flags["prompt"] === "string" ? flags["prompt"] : "";
|
|
355
437
|
if (positional.length > 0 || prompt.length > 0) return "single-shot";
|
|
356
|
-
if (flags.tui && flags["no-tui"] !== true && !flags.webui) return "tui";
|
|
357
|
-
if (flags.webui) return "webui";
|
|
438
|
+
if (flags.tui && flags["no-tui"] !== true && !flags.webui && !flags["webui-session-child"]) return "tui";
|
|
439
|
+
if (flags.webui || flags["webui-session-child"]) return "webui";
|
|
358
440
|
return "repl";
|
|
359
441
|
}
|
|
360
442
|
|
|
@@ -494,7 +576,7 @@ function createTuiCoordinatorCallbacks({
|
|
|
494
576
|
}
|
|
495
577
|
|
|
496
578
|
// src/boot/tui-coordinator-setup.ts
|
|
497
|
-
import * as
|
|
579
|
+
import * as path2 from "node:path";
|
|
498
580
|
import { AutonomousCoordinator } from "@wrongstack/core/coordination";
|
|
499
581
|
function setupAutonomousCoordinator(ctx) {
|
|
500
582
|
const { state, events, context, wpaths, mailbox, director, getDirector, coordinatorController, onCoordinatorStopSetter } = ctx;
|
|
@@ -503,7 +585,7 @@ function setupAutonomousCoordinator(ctx) {
|
|
|
503
585
|
const currentDirector = getDirector?.() ?? director;
|
|
504
586
|
if (!currentDirector) return null;
|
|
505
587
|
const transcript = context.session.transcriptPath;
|
|
506
|
-
const sessionDir = transcript ?
|
|
588
|
+
const sessionDir = transcript ? path2.dirname(transcript) : wpaths.projectDir;
|
|
507
589
|
const llmProvider = {
|
|
508
590
|
decide: async (prompt) => {
|
|
509
591
|
const sysPrompt = [
|
|
@@ -714,10 +796,10 @@ function wireGoal(events) {
|
|
|
714
796
|
}
|
|
715
797
|
|
|
716
798
|
// src/boot/tui-live-sessions.ts
|
|
717
|
-
import * as
|
|
799
|
+
import * as path3 from "node:path";
|
|
718
800
|
async function getLiveSessions(ctx) {
|
|
719
801
|
const { SessionRegistry } = await import("@wrongstack/core/storage");
|
|
720
|
-
const globalRoot =
|
|
802
|
+
const globalRoot = path3.dirname(ctx.state.wpaths.globalConfig);
|
|
721
803
|
const registry = new SessionRegistry(globalRoot);
|
|
722
804
|
const sessions = await registry.list();
|
|
723
805
|
return sessions.filter((s) => s.status !== "stale").map((s) => ({
|
|
@@ -747,7 +829,7 @@ function onSwitchToSession(ctx, _sessionId, targetRoot, projectName) {
|
|
|
747
829
|
}
|
|
748
830
|
|
|
749
831
|
// src/boot/tui-project-picker-callback.ts
|
|
750
|
-
import * as
|
|
832
|
+
import * as path4 from "node:path";
|
|
751
833
|
import { color as color3 } from "@wrongstack/core/utils";
|
|
752
834
|
async function getProjectPickerItems(ctx) {
|
|
753
835
|
const { buildPickerItems } = await import("./project-picker-BOCWHBXP.js");
|
|
@@ -761,7 +843,7 @@ async function onProjectSelect(ctx, slug, kind) {
|
|
|
761
843
|
try {
|
|
762
844
|
if (kind === "action") {
|
|
763
845
|
if (slug === "new-session") {
|
|
764
|
-
const name =
|
|
846
|
+
const name = path4.basename(state.projectRoot) || state.projectRoot;
|
|
765
847
|
const err2 = await switchProjectInPlace2(state.projectRoot, name);
|
|
766
848
|
if (err2) renderer.write(color3.red(`Project switch failed: ${err2}
|
|
767
849
|
`));
|
|
@@ -772,8 +854,8 @@ async function onProjectSelect(ctx, slug, kind) {
|
|
|
772
854
|
const manifest = await loadManifest(state.wpaths.globalConfig);
|
|
773
855
|
const project = manifest.projects.find((p) => p.slug === slug);
|
|
774
856
|
if (!project) return;
|
|
775
|
-
const targetRoot =
|
|
776
|
-
if (
|
|
857
|
+
const targetRoot = path4.resolve(project.root);
|
|
858
|
+
if (path4.resolve(state.projectRoot) === targetRoot) return;
|
|
777
859
|
const fleetStatus = director?.status();
|
|
778
860
|
const fleetRunning = fleetStatus?.subagents.filter((a) => a.status === "running").length ?? 0;
|
|
779
861
|
const eternalActive = getEternalEngine?.()?.currentState === "running";
|
|
@@ -811,7 +893,7 @@ ${parts.join("\n")}
|
|
|
811
893
|
import { spawn } from "node:child_process";
|
|
812
894
|
import { createRequire } from "node:module";
|
|
813
895
|
import * as fs from "node:fs/promises";
|
|
814
|
-
import * as
|
|
896
|
+
import * as path5 from "node:path";
|
|
815
897
|
import { color as color4 } from "@wrongstack/core/utils";
|
|
816
898
|
async function handleProjectSwitchSpawn(opts) {
|
|
817
899
|
const PROJECT_SWITCH_EXIT_CODE = 42;
|
|
@@ -824,8 +906,8 @@ async function handleProjectSwitchSpawn(opts) {
|
|
|
824
906
|
try {
|
|
825
907
|
const req = createRequire(import.meta.url);
|
|
826
908
|
const pkgPath = req.resolve("@wrongstack/cli/package.json");
|
|
827
|
-
const pkgDir =
|
|
828
|
-
cliPath =
|
|
909
|
+
const pkgDir = path5.dirname(pkgPath);
|
|
910
|
+
cliPath = path5.join(pkgDir, "dist", "index.js");
|
|
829
911
|
await fs.access(cliPath);
|
|
830
912
|
} catch {
|
|
831
913
|
cliPath = process.argv[1] ?? "";
|
|
@@ -837,13 +919,16 @@ async function handleProjectSwitchSpawn(opts) {
|
|
|
837
919
|
const nodeExe = process.execPath;
|
|
838
920
|
const spawnArgs = [cliPath, "--no-interactive"];
|
|
839
921
|
if (resumeSessionId) spawnArgs.push("--resume", resumeSessionId);
|
|
840
|
-
spawn(nodeExe, spawnArgs, {
|
|
922
|
+
const child = spawn(nodeExe, spawnArgs, {
|
|
841
923
|
cwd: root,
|
|
842
924
|
stdio: "ignore",
|
|
843
|
-
detached: true
|
|
844
|
-
|
|
925
|
+
detached: true,
|
|
926
|
+
windowsHide: true
|
|
927
|
+
});
|
|
928
|
+
child.on("error", (err) => {
|
|
845
929
|
console.error(color4.red(`Failed to spawn wstack: ${err.message}`));
|
|
846
930
|
});
|
|
931
|
+
child.unref();
|
|
847
932
|
console.log(
|
|
848
933
|
[
|
|
849
934
|
"",
|
|
@@ -858,7 +943,7 @@ async function handleProjectSwitchSpawn(opts) {
|
|
|
858
943
|
|
|
859
944
|
// src/boot/tui-project-switch.ts
|
|
860
945
|
import * as fs2 from "node:fs/promises";
|
|
861
|
-
import * as
|
|
946
|
+
import * as path6 from "node:path";
|
|
862
947
|
import {
|
|
863
948
|
DefaultSystemPromptBuilder,
|
|
864
949
|
setQueuedMessagesSnapshot
|
|
@@ -879,7 +964,7 @@ async function switchProjectInPlace(ctx, targetRoot, displayName) {
|
|
|
879
964
|
skillLoader,
|
|
880
965
|
attachTodosCheckpoint: attachTodosCheckpoint3
|
|
881
966
|
} = ctx;
|
|
882
|
-
const resolved =
|
|
967
|
+
const resolved = path6.resolve(targetRoot);
|
|
883
968
|
const stat2 = await fs2.stat(resolved).catch(() => null);
|
|
884
969
|
if (!stat2?.isDirectory()) return `Cannot switch: not a directory: ${resolved}`;
|
|
885
970
|
const oldWriter = context.session;
|
|
@@ -918,7 +1003,7 @@ async function switchProjectInPlace(ctx, targetRoot, displayName) {
|
|
|
918
1003
|
await state.activateSessionIdentity(nextWriter.id, {
|
|
919
1004
|
projectSlug: nextWpaths.projectSlug,
|
|
920
1005
|
projectRoot: resolved,
|
|
921
|
-
projectName: displayName ||
|
|
1006
|
+
projectName: displayName || path6.basename(resolved),
|
|
922
1007
|
workingDir: resolved
|
|
923
1008
|
});
|
|
924
1009
|
} catch (err) {
|
|
@@ -938,6 +1023,7 @@ async function switchProjectInPlace(ctx, targetRoot, displayName) {
|
|
|
938
1023
|
context.state.replaceMessages([]);
|
|
939
1024
|
context.state.replaceTodos([]);
|
|
940
1025
|
context.clearFileTracking();
|
|
1026
|
+
context.clearMemoryEvidence?.();
|
|
941
1027
|
context.tokenCounter.reset();
|
|
942
1028
|
context.meta["packageTrackerOpts"] = { storageDir: nextWpaths.projectDir, projectRoot: resolved };
|
|
943
1029
|
context.state.setMeta(
|
|
@@ -979,7 +1065,8 @@ async function switchProjectInPlace(ctx, targetRoot, displayName) {
|
|
|
979
1065
|
context.systemPrompt = await switchBuilder.build({
|
|
980
1066
|
cwd: resolved,
|
|
981
1067
|
projectRoot: resolved,
|
|
982
|
-
tools: agent.tools.
|
|
1068
|
+
tools: agent.tools.listForProvider(),
|
|
1069
|
+
catalogTools: agent.tools.list(),
|
|
983
1070
|
provider: context.provider.id,
|
|
984
1071
|
model: context.model
|
|
985
1072
|
});
|
|
@@ -1053,7 +1140,7 @@ async function onSDDOutput(output) {
|
|
|
1053
1140
|
}
|
|
1054
1141
|
|
|
1055
1142
|
// src/boot/tui-session-resume.ts
|
|
1056
|
-
import * as
|
|
1143
|
+
import * as path7 from "node:path";
|
|
1057
1144
|
import { attachTodosCheckpoint, loadTodosCheckpoint } from "@wrongstack/core/storage";
|
|
1058
1145
|
import { sessionScopedPath as sessionScopedPath2 } from "@wrongstack/core/utils";
|
|
1059
1146
|
async function resumeSession(ctx, sessionId) {
|
|
@@ -1079,7 +1166,7 @@ async function resumeSession(ctx, sessionId) {
|
|
|
1079
1166
|
}
|
|
1080
1167
|
try {
|
|
1081
1168
|
const { SessionRegistry } = await import("@wrongstack/core/storage");
|
|
1082
|
-
const registry = new SessionRegistry(
|
|
1169
|
+
const registry = new SessionRegistry(path7.dirname(state.wpaths.globalConfig));
|
|
1083
1170
|
const live = (await registry.list()).find(
|
|
1084
1171
|
(s) => s.sessionId === canonicalSessionId && s.status !== "stale" && s.pid !== process.pid
|
|
1085
1172
|
);
|
|
@@ -1290,10 +1377,10 @@ async function resumeSession(ctx, sessionId) {
|
|
|
1290
1377
|
|
|
1291
1378
|
// src/boot/tui-settings-adapter.ts
|
|
1292
1379
|
import * as fs3 from "node:fs/promises";
|
|
1293
|
-
import * as
|
|
1380
|
+
import * as path8 from "node:path";
|
|
1294
1381
|
import { decryptConfigSecrets, encryptConfigSecrets, noOpVault } from "@wrongstack/core/security";
|
|
1295
1382
|
import { normalizeTokenSavingTier, resolveFleetChatVerbosity } from "@wrongstack/core/types";
|
|
1296
|
-
import { atomicWrite } from "@wrongstack/core/utils";
|
|
1383
|
+
import { atomicWrite, deepMerge } from "@wrongstack/core/utils";
|
|
1297
1384
|
import { getProcessRegistry } from "@wrongstack/tools";
|
|
1298
1385
|
var PANEL_IDS_CLI = [
|
|
1299
1386
|
"projectPicker",
|
|
@@ -1372,6 +1459,7 @@ function createSettingsAdapter(ctx) {
|
|
|
1372
1459
|
auditLevel: cfg.session?.auditLevel ?? "standard",
|
|
1373
1460
|
indexOnStart: cfg.indexing?.onSessionStart !== false,
|
|
1374
1461
|
maxIterations: cfg.tools?.maxIterations ?? 500,
|
|
1462
|
+
nextStepsTool: cfg.tools?.nextsteps?.enabled === true,
|
|
1375
1463
|
restrictFsToRoot: resolvedRestrict,
|
|
1376
1464
|
autoProceedMaxIterations: cfg.autonomy?.autoProceedMaxIterations ?? 50,
|
|
1377
1465
|
debugStream: cfg.debugStream ?? false,
|
|
@@ -1411,12 +1499,15 @@ function createSettingsAdapter(ctx) {
|
|
|
1411
1499
|
}
|
|
1412
1500
|
async function saveSettings(s) {
|
|
1413
1501
|
try {
|
|
1414
|
-
if (s.mode !== void 0 || s.delayMs !== void 0 || s.titleAnimation !== void 0 || s.yolo !== void 0 || s.fleetChatVerbosity !== void 0 || s.chime !== void 0 || s.confirmExit !== void 0 || s.mouseMode !== void 0 || s.featureMcp !== void 0 || s.featurePlugins !== void 0 || s.featureMemory !== void 0 || s.featureSkills !== void 0 || s.featureModelsRegistry !== void 0 || s.featureTokenSaving !== void 0 || s.allowOutsideProjectRoot !== void 0 || s.contextAutoCompact !== void 0 || s.contextStrategy !== void 0 || s.contextMode !== void 0 || s.maxConcurrent !== void 0 || s.logLevel !== void 0 || s.auditLevel !== void 0 || s.indexOnStart !== void 0 || s.maxIterations !== void 0 || s.restrictFsToRoot !== void 0 || s.nextPrediction !== void 0 || s.debugStream !== void 0 || s.shellBangWarningDontShowAgain !== void 0 || s.configScope !== void 0 || s.enhanceDelayMs !== void 0 || s.enhanceEnabled !== void 0 || s.enhanceLanguage !== void 0 || s.midRunSendPicker !== void 0 || s.statuslineMode !== void 0 || s.thinkingWord !== void 0 || s.animationStyle !== void 0 || s.autonomyNextPrompt !== void 0 || s.autoProceedMaxIterations !== void 0 || s.reasoningMode !== void 0 || s.reasoningEffort !== void 0 || s.reasoningPreserve !== void 0 || s.cacheTtl !== void 0 || s.breakerEnabled !== void 0 || s.breakerAutoKillResetMs !== void 0 || s.showModelReasoning !== void 0 || s.showAgentSwarmPanel !== void 0 || s.panelPositions !== void 0 || s.showSageMemoryInject !== void 0 || s.sageMemoryInjectThreshold !== void 0 || s.readSymbols !== void 0) {
|
|
1502
|
+
if (s.mode !== void 0 || s.delayMs !== void 0 || s.titleAnimation !== void 0 || s.yolo !== void 0 || s.fleetChatVerbosity !== void 0 || s.chime !== void 0 || s.confirmExit !== void 0 || s.mouseMode !== void 0 || s.featureMcp !== void 0 || s.featurePlugins !== void 0 || s.featureMemory !== void 0 || s.featureSkills !== void 0 || s.featureModelsRegistry !== void 0 || s.featureTokenSaving !== void 0 || s.allowOutsideProjectRoot !== void 0 || s.contextAutoCompact !== void 0 || s.contextStrategy !== void 0 || s.contextMode !== void 0 || s.maxConcurrent !== void 0 || s.logLevel !== void 0 || s.auditLevel !== void 0 || s.indexOnStart !== void 0 || s.maxIterations !== void 0 || s.nextStepsTool !== void 0 || s.restrictFsToRoot !== void 0 || s.nextPrediction !== void 0 || s.debugStream !== void 0 || s.shellBangWarningDontShowAgain !== void 0 || s.configScope !== void 0 || s.enhanceDelayMs !== void 0 || s.enhanceEnabled !== void 0 || s.enhanceLanguage !== void 0 || s.midRunSendPicker !== void 0 || s.statuslineMode !== void 0 || s.thinkingWord !== void 0 || s.animationStyle !== void 0 || s.autonomyNextPrompt !== void 0 || s.autoProceedMaxIterations !== void 0 || s.reasoningMode !== void 0 || s.reasoningEffort !== void 0 || s.reasoningPreserve !== void 0 || s.cacheTtl !== void 0 || s.breakerEnabled !== void 0 || s.breakerAutoKillResetMs !== void 0 || s.showModelReasoning !== void 0 || s.showAgentSwarmPanel !== void 0 || s.panelPositions !== void 0 || s.showSageMemoryInject !== void 0 || s.sageMemoryInjectThreshold !== void 0 || s.readSymbols !== void 0) {
|
|
1415
1503
|
const cfg = configStore.get();
|
|
1416
|
-
const activeProfileName = cfg.activeProfile ?? "default";
|
|
1417
1504
|
const persistDeps = {
|
|
1418
1505
|
configStore,
|
|
1419
|
-
|
|
1506
|
+
// Third copy of "which profile is active" — an inline cast plus a
|
|
1507
|
+
// `?? 'default'`, identical to `activeProfileConfigPath` two files
|
|
1508
|
+
// over. The comment above already promised this resolution was
|
|
1509
|
+
// delegated; now it is.
|
|
1510
|
+
profileConfigPath: activeProfileConfigPath(wpaths, cfg),
|
|
1420
1511
|
inProjectConfigPath: wpaths.inProjectConfig,
|
|
1421
1512
|
vault: noOpVault,
|
|
1422
1513
|
resolveProfilePath: (name) => wpaths.profileConfig(name)
|
|
@@ -1506,9 +1597,10 @@ function createSettingsAdapter(ctx) {
|
|
|
1506
1597
|
idx.onSessionStart = s.indexOnStart;
|
|
1507
1598
|
decrypted.indexing = idx;
|
|
1508
1599
|
}
|
|
1509
|
-
if (s.maxIterations !== void 0 || fsAccess !== void 0) {
|
|
1600
|
+
if (s.maxIterations !== void 0 || s.nextStepsTool !== void 0 || fsAccess !== void 0) {
|
|
1510
1601
|
const tools = decrypted.tools ?? {};
|
|
1511
1602
|
if (s.maxIterations !== void 0) tools.maxIterations = s.maxIterations;
|
|
1603
|
+
if (s.nextStepsTool !== void 0) tools.nextsteps = { enabled: s.nextStepsTool };
|
|
1512
1604
|
if (fsAccess !== void 0) tools.restrictToProjectRoot = fsAccess.restrictToProjectRoot;
|
|
1513
1605
|
decrypted.tools = tools;
|
|
1514
1606
|
}
|
|
@@ -1563,7 +1655,7 @@ function createSettingsAdapter(ctx) {
|
|
|
1563
1655
|
const destRaw = await fs3.readFile(actualTarget, "utf8");
|
|
1564
1656
|
const destParsed = JSON.parse(destRaw);
|
|
1565
1657
|
const destDecrypted = decryptConfigSecrets(destParsed, noOpVault);
|
|
1566
|
-
mergedToWrite =
|
|
1658
|
+
mergedToWrite = deepMerge(destDecrypted, decrypted);
|
|
1567
1659
|
} catch (err) {
|
|
1568
1660
|
if (err.code !== "ENOENT") {
|
|
1569
1661
|
throw new Error(
|
|
@@ -1576,7 +1668,7 @@ function createSettingsAdapter(ctx) {
|
|
|
1576
1668
|
const isProjectTarget = actualTarget === wpaths.inProjectConfig;
|
|
1577
1669
|
const toWrite = isProjectTarget ? filterSafeForProject(mergedToWrite) : mergedToWrite;
|
|
1578
1670
|
const encrypted = encryptConfigSecrets(toWrite, noOpVault);
|
|
1579
|
-
await fs3.mkdir(
|
|
1671
|
+
await fs3.mkdir(path8.dirname(actualTarget), { recursive: true });
|
|
1580
1672
|
await atomicWrite(actualTarget, JSON.stringify(encrypted, null, 2), { mode: 384 });
|
|
1581
1673
|
const currentConfig = configStore.get();
|
|
1582
1674
|
const nextModelRuntime = {
|
|
@@ -1620,7 +1712,7 @@ function createSettingsAdapter(ctx) {
|
|
|
1620
1712
|
...decrypted.indexing ?? {}
|
|
1621
1713
|
}
|
|
1622
1714
|
} : {},
|
|
1623
|
-
...s.maxIterations !== void 0 || fsAccess !== void 0 ? {
|
|
1715
|
+
...s.maxIterations !== void 0 || s.nextStepsTool !== void 0 || fsAccess !== void 0 ? {
|
|
1624
1716
|
tools: {
|
|
1625
1717
|
...currentConfig.tools,
|
|
1626
1718
|
...decrypted.tools ?? {}
|
|
@@ -1734,6 +1826,7 @@ function createBrainPanelHost(deps) {
|
|
|
1734
1826
|
councilDistinctness: snap.council.distinctness,
|
|
1735
1827
|
councilPerCallTimeoutMs: snap.council.perCallTimeoutMs,
|
|
1736
1828
|
councilMaxConcurrency: snap.council.maxConcurrency,
|
|
1829
|
+
councilVoterMaxTokens: snap.council.voterMaxTokens,
|
|
1737
1830
|
councilJudgeMaxTokens: snap.council.judgeMaxTokens,
|
|
1738
1831
|
// The EFFECTIVE judge, not `council.judge`. The configured one is
|
|
1739
1832
|
// usually absent, so the panel used to read "auto" and say nothing
|
|
@@ -1815,6 +1908,7 @@ function createBrainPanelHost(deps) {
|
|
|
1815
1908
|
setCouncilDistinctness: (mode) => apply({ council: { distinctness: mode } }),
|
|
1816
1909
|
setCouncilPerCallTimeout: (ms) => apply({ council: { perCallTimeoutMs: ms ?? null } }),
|
|
1817
1910
|
setCouncilMaxConcurrency: (count) => apply({ council: { maxConcurrency: count ?? null } }),
|
|
1911
|
+
setCouncilVoterMaxTokens: (tokens) => apply({ council: { voterMaxTokens: tokens ?? null } }),
|
|
1818
1912
|
setCouncilJudgeMaxTokens: (tokens) => apply({ council: { judgeMaxTokens: tokens ?? null } }),
|
|
1819
1913
|
setLedgerEnabled: (on) => apply({ ledger: { enabled: on } }),
|
|
1820
1914
|
setAutoDeny: (count) => apply({ ledger: { autoDenyAfterFailures: count ?? null } }),
|
|
@@ -1851,7 +1945,7 @@ var reviewerRoundRobinCursor = 0;
|
|
|
1851
1945
|
function __resetReviewerRoundRobinCursor(value = 0) {
|
|
1852
1946
|
reviewerRoundRobinCursor = value;
|
|
1853
1947
|
}
|
|
1854
|
-
function
|
|
1948
|
+
function assignReviewerModels(provider, model, fallbackModels, selection = "round-robin", statusTracker, random = Math.random) {
|
|
1855
1949
|
const pool = buildReviewerModelPool(provider, model, fallbackModels, statusTracker);
|
|
1856
1950
|
if (pool.length <= 1) {
|
|
1857
1951
|
return {
|
|
@@ -1860,20 +1954,24 @@ function assignReviewerModelsRoundRobin(provider, model, fallbackModels, statusT
|
|
|
1860
1954
|
fallbackModels: [...fallbackModels]
|
|
1861
1955
|
};
|
|
1862
1956
|
}
|
|
1957
|
+
const cursor = selection === "random" ? Math.min(pool.length - 1, Math.floor(Math.max(0, random()) * pool.length)) : reviewerRoundRobinCursor;
|
|
1863
1958
|
const assignment = selectRoundRobinReviewerAssignment(
|
|
1864
1959
|
pool,
|
|
1865
|
-
|
|
1960
|
+
cursor,
|
|
1866
1961
|
provider,
|
|
1867
1962
|
model,
|
|
1868
1963
|
statusTracker
|
|
1869
1964
|
);
|
|
1870
|
-
reviewerRoundRobinCursor = assignment.nextCursor;
|
|
1965
|
+
if (selection === "round-robin") reviewerRoundRobinCursor = assignment.nextCursor;
|
|
1871
1966
|
return {
|
|
1872
1967
|
provider: assignment.provider,
|
|
1873
1968
|
model: assignment.model,
|
|
1874
1969
|
fallbackModels: assignment.fallbackModels
|
|
1875
1970
|
};
|
|
1876
1971
|
}
|
|
1972
|
+
function assignReviewerModelsRoundRobin(provider, model, fallbackModels, statusTracker) {
|
|
1973
|
+
return assignReviewerModels(provider, model, fallbackModels, "round-robin", statusTracker);
|
|
1974
|
+
}
|
|
1877
1975
|
var MAX_REVIEWER_ATTEMPTS = 4;
|
|
1878
1976
|
var REVIEWER_ATTEMPT_TIMEOUT_MS = 9e5;
|
|
1879
1977
|
var REVIEWER_LADDER_BUDGET_MS = 12e5;
|
|
@@ -1976,7 +2074,7 @@ async function finalizeExecutionCleanup(input) {
|
|
|
1976
2074
|
session,
|
|
1977
2075
|
tokenCounter,
|
|
1978
2076
|
events,
|
|
1979
|
-
|
|
2077
|
+
chimeraWork,
|
|
1980
2078
|
director,
|
|
1981
2079
|
reader
|
|
1982
2080
|
} = input;
|
|
@@ -2028,25 +2126,34 @@ async function finalizeExecutionCleanup(input) {
|
|
|
2028
2126
|
})
|
|
2029
2127
|
);
|
|
2030
2128
|
});
|
|
2031
|
-
|
|
2032
|
-
|
|
2033
|
-
|
|
2034
|
-
|
|
2035
|
-
|
|
2036
|
-
|
|
2037
|
-
|
|
2038
|
-
|
|
2039
|
-
|
|
2040
|
-
|
|
2041
|
-
|
|
2042
|
-
|
|
2043
|
-
|
|
2044
|
-
|
|
2045
|
-
|
|
2046
|
-
|
|
2047
|
-
|
|
2048
|
-
});
|
|
2129
|
+
const sessionEndProducers = /* @__PURE__ */ new Set();
|
|
2130
|
+
events.emit(
|
|
2131
|
+
"session.ended",
|
|
2132
|
+
{
|
|
2133
|
+
id: activeSession.id,
|
|
2134
|
+
sessionId: activeSession.id,
|
|
2135
|
+
usage: tokenCounter.total(),
|
|
2136
|
+
waitUntil: (work) => {
|
|
2137
|
+
const tracked = Promise.resolve(work).finally(() => sessionEndProducers.delete(tracked));
|
|
2138
|
+
void tracked.catch(() => void 0);
|
|
2139
|
+
sessionEndProducers.add(tracked);
|
|
2140
|
+
}
|
|
2141
|
+
}
|
|
2142
|
+
);
|
|
2143
|
+
try {
|
|
2144
|
+
while (sessionEndProducers.size > 0) {
|
|
2145
|
+
await Promise.allSettled([...sessionEndProducers]);
|
|
2049
2146
|
}
|
|
2147
|
+
await chimeraWork?.drainAndClose();
|
|
2148
|
+
} catch (err) {
|
|
2149
|
+
console.warn(
|
|
2150
|
+
JSON.stringify({
|
|
2151
|
+
level: "warn",
|
|
2152
|
+
event: "shutdown.chimera_work_failed",
|
|
2153
|
+
message: `Pending chimera work failed: ${err instanceof Error ? err.message : String(err)}`,
|
|
2154
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
2155
|
+
})
|
|
2156
|
+
);
|
|
2050
2157
|
}
|
|
2051
2158
|
if (director) {
|
|
2052
2159
|
try {
|
|
@@ -2447,9 +2554,46 @@ var FleetStatusLine = class {
|
|
|
2447
2554
|
}
|
|
2448
2555
|
};
|
|
2449
2556
|
|
|
2557
|
+
// src/chimera-work-registry.ts
|
|
2558
|
+
function createChimeraWorkRegistry() {
|
|
2559
|
+
const pending = /* @__PURE__ */ new Set();
|
|
2560
|
+
let accepting = true;
|
|
2561
|
+
let closePromise;
|
|
2562
|
+
const track = (work) => {
|
|
2563
|
+
if (!accepting) return false;
|
|
2564
|
+
const tracked = Promise.resolve(work).finally(() => {
|
|
2565
|
+
pending.delete(tracked);
|
|
2566
|
+
});
|
|
2567
|
+
void tracked.catch(() => void 0);
|
|
2568
|
+
pending.add(tracked);
|
|
2569
|
+
return true;
|
|
2570
|
+
};
|
|
2571
|
+
const snapshot = () => {
|
|
2572
|
+
if (pending.size === 0) return void 0;
|
|
2573
|
+
return Promise.allSettled([...pending]).then(() => void 0);
|
|
2574
|
+
};
|
|
2575
|
+
const drainAndClose = () => {
|
|
2576
|
+
closePromise ??= (async () => {
|
|
2577
|
+
while (pending.size > 0) {
|
|
2578
|
+
await Promise.allSettled([...pending]);
|
|
2579
|
+
}
|
|
2580
|
+
accepting = false;
|
|
2581
|
+
})();
|
|
2582
|
+
return closePromise;
|
|
2583
|
+
};
|
|
2584
|
+
return {
|
|
2585
|
+
track,
|
|
2586
|
+
pending: snapshot,
|
|
2587
|
+
drainAndClose,
|
|
2588
|
+
get size() {
|
|
2589
|
+
return pending.size;
|
|
2590
|
+
}
|
|
2591
|
+
};
|
|
2592
|
+
}
|
|
2593
|
+
|
|
2450
2594
|
// src/execution-chimera-cascade.ts
|
|
2451
2595
|
import * as fsp from "node:fs/promises";
|
|
2452
|
-
import * as
|
|
2596
|
+
import * as path9 from "node:path";
|
|
2453
2597
|
import { emitReviewIfChanged } from "@wrongstack/core/plugin";
|
|
2454
2598
|
|
|
2455
2599
|
// src/chimera-review-task.ts
|
|
@@ -2708,7 +2852,7 @@ function installChimeraCascadeHandler({
|
|
|
2708
2852
|
director,
|
|
2709
2853
|
session,
|
|
2710
2854
|
getPendingWork,
|
|
2711
|
-
|
|
2855
|
+
trackWork,
|
|
2712
2856
|
buildLadder
|
|
2713
2857
|
}) {
|
|
2714
2858
|
events.onPattern("chimera.cascade_needed", (_event, payload) => {
|
|
@@ -2797,7 +2941,7 @@ function installChimeraCascadeHandler({
|
|
|
2797
2941
|
}
|
|
2798
2942
|
await maybeReReviewCascade({ events, session, bundle: p.bundle });
|
|
2799
2943
|
})();
|
|
2800
|
-
|
|
2944
|
+
trackWork(pendingWork);
|
|
2801
2945
|
});
|
|
2802
2946
|
}
|
|
2803
2947
|
async function maybeReReviewCascade({
|
|
@@ -2812,7 +2956,7 @@ async function maybeReReviewCascade({
|
|
|
2812
2956
|
const reReadFiles = [];
|
|
2813
2957
|
for (const f of bundle.files) {
|
|
2814
2958
|
try {
|
|
2815
|
-
const absPath =
|
|
2959
|
+
const absPath = path9.join(bundle.cwd, f.path);
|
|
2816
2960
|
const content = await fsp.readFile(absPath, "utf8");
|
|
2817
2961
|
reReadFiles.push({ path: f.path, status: "modified", content });
|
|
2818
2962
|
} catch {
|
|
@@ -2836,7 +2980,7 @@ async function maybeReReviewCascade({
|
|
|
2836
2980
|
stopReason: "end_turn",
|
|
2837
2981
|
usage: { input: 0, output: 0 }
|
|
2838
2982
|
});
|
|
2839
|
-
const emitted = emitReviewIfChanged(
|
|
2983
|
+
const emitted = await emitReviewIfChanged(
|
|
2840
2984
|
{ events, emitCustom: events.emitCustom.bind(events) },
|
|
2841
2985
|
reReviewBundle
|
|
2842
2986
|
);
|
|
@@ -2881,7 +3025,7 @@ async function maybeReReviewCascade({
|
|
|
2881
3025
|
|
|
2882
3026
|
// src/execution-chimera-review.ts
|
|
2883
3027
|
import { randomUUID as randomUUID3 } from "node:crypto";
|
|
2884
|
-
import
|
|
3028
|
+
import path10 from "node:path";
|
|
2885
3029
|
import { effectiveFallbackChain } from "@wrongstack/core/agent";
|
|
2886
3030
|
import {
|
|
2887
3031
|
CHIMERA_REVIEW_PROMPT,
|
|
@@ -2894,7 +3038,7 @@ import {
|
|
|
2894
3038
|
function normalizeFileKeyForCitation(raw, cwd) {
|
|
2895
3039
|
const forward = raw.replace(/\\/g, "/").replace(/^\.\//, "");
|
|
2896
3040
|
const isAbsolute = forward.startsWith("/") || /^[a-zA-Z]:\//.test(forward);
|
|
2897
|
-
const pathMod = process.platform === "win32" ?
|
|
3041
|
+
const pathMod = process.platform === "win32" ? path10.win32 : path10;
|
|
2898
3042
|
const relative = isAbsolute ? pathMod.relative(cwd, forward).replace(/\\/g, "/").replace(/^\.\//, "") : forward;
|
|
2899
3043
|
return process.platform === "win32" ? relative.toLowerCase() : relative;
|
|
2900
3044
|
}
|
|
@@ -2908,13 +3052,14 @@ function installChimeraReviewHandler({
|
|
|
2908
3052
|
projectDir,
|
|
2909
3053
|
statusTracker,
|
|
2910
3054
|
persistReview = persistChimeraReview,
|
|
2911
|
-
|
|
3055
|
+
trackWork
|
|
2912
3056
|
}) {
|
|
2913
3057
|
events.onPattern("chimera.review_needed", (_event, payload) => {
|
|
2914
3058
|
const p = payload;
|
|
2915
3059
|
const reviewSessionId = agent.ctx.activeRunSessionId ?? agent.ctx.session?.id ?? session.id;
|
|
2916
3060
|
const dir = director;
|
|
2917
3061
|
if (!dir) {
|
|
3062
|
+
void recordCompletedReview(events, { bundle: p }).catch(() => void 0);
|
|
2918
3063
|
return;
|
|
2919
3064
|
}
|
|
2920
3065
|
if (p.files.length === 0) return;
|
|
@@ -2957,11 +3102,11 @@ function installChimeraReviewHandler({
|
|
|
2957
3102
|
`\u{1F982} Chimera report persistence failed: ${message}. The review remains in the session transcript and mailbox.`
|
|
2958
3103
|
);
|
|
2959
3104
|
} finally {
|
|
2960
|
-
recordCompletedReview(events, completion);
|
|
3105
|
+
await recordCompletedReview(events, completion);
|
|
2961
3106
|
events.emitCustom("chimera.review_complete", completion);
|
|
2962
3107
|
}
|
|
2963
3108
|
};
|
|
2964
|
-
|
|
3109
|
+
trackWork(
|
|
2965
3110
|
(async () => {
|
|
2966
3111
|
let subagentId;
|
|
2967
3112
|
try {
|
|
@@ -2973,10 +3118,11 @@ function installChimeraReviewHandler({
|
|
|
2973
3118
|
const baseProvider = rawProvider || tProvider || config.provider;
|
|
2974
3119
|
const baseModel = rawModel || tModel || config.model;
|
|
2975
3120
|
const baseFallbacks = p.reviewFallbackModels ? [...p.reviewFallbackModels] : resolveReviewerFallbackModels(void 0);
|
|
2976
|
-
const assigned =
|
|
3121
|
+
const assigned = assignReviewerModels(
|
|
2977
3122
|
baseProvider,
|
|
2978
3123
|
baseModel,
|
|
2979
3124
|
baseFallbacks,
|
|
3125
|
+
p.reviewModelSelection ?? "round-robin",
|
|
2980
3126
|
statusTracker
|
|
2981
3127
|
);
|
|
2982
3128
|
const ladder = buildReviewerAttemptLadder({
|
|
@@ -3090,16 +3236,16 @@ function installChimeraReviewHandler({
|
|
|
3090
3236
|
const changedBasenameIndex = /* @__PURE__ */ new Map();
|
|
3091
3237
|
for (const file of p.files) {
|
|
3092
3238
|
const normalized = normalizeFileKeyForCitation(file.path, p.cwd);
|
|
3093
|
-
const
|
|
3094
|
-
const bucket = changedBasenameIndex.get(
|
|
3239
|
+
const basename6 = path10.basename(file.path).toLowerCase();
|
|
3240
|
+
const bucket = changedBasenameIndex.get(basename6);
|
|
3095
3241
|
if (bucket) bucket.push(normalized);
|
|
3096
|
-
else changedBasenameIndex.set(
|
|
3242
|
+
else changedBasenameIndex.set(basename6, [normalized]);
|
|
3097
3243
|
}
|
|
3098
3244
|
const droppedCitations = citedFindings.filter((finding) => {
|
|
3099
3245
|
const citedKey = normalizeFileKeyForCitation(finding.location.file, p.cwd);
|
|
3100
3246
|
if (citedPaths.has(citedKey)) return false;
|
|
3101
|
-
const
|
|
3102
|
-
const bucket = changedBasenameIndex.get(
|
|
3247
|
+
const basename6 = path10.basename(finding.location.file).toLowerCase();
|
|
3248
|
+
const bucket = changedBasenameIndex.get(basename6);
|
|
3103
3249
|
return !(bucket && bucket.length === 1);
|
|
3104
3250
|
});
|
|
3105
3251
|
const effectiveHasFindings = reviewHasFindings && (parsedReview.findings.length === 0 || parsedReview.findings.length > droppedCitations.length);
|
|
@@ -3621,7 +3767,7 @@ function printBanner(renderer, projectName) {
|
|
|
3621
3767
|
|
|
3622
3768
|
// src/repl-client-registration.ts
|
|
3623
3769
|
import * as crypto from "node:crypto";
|
|
3624
|
-
import * as
|
|
3770
|
+
import * as path11 from "node:path";
|
|
3625
3771
|
import {
|
|
3626
3772
|
getSharedProjectMailbox,
|
|
3627
3773
|
resolveProjectDir
|
|
@@ -3634,7 +3780,7 @@ function registerReplClient(opts) {
|
|
|
3634
3780
|
const hqConnection = startCliHqConnection({
|
|
3635
3781
|
clientKind: "repl",
|
|
3636
3782
|
projectRoot: replProjectRoot,
|
|
3637
|
-
projectName:
|
|
3783
|
+
projectName: path11.basename(replProjectRoot),
|
|
3638
3784
|
appConfig: opts.appConfig,
|
|
3639
3785
|
capabilities: ["telemetry.publish", "mailbox.summary"]
|
|
3640
3786
|
});
|
|
@@ -3648,7 +3794,7 @@ function registerReplClient(opts) {
|
|
|
3648
3794
|
clientMailbox.registerClient({
|
|
3649
3795
|
clientId,
|
|
3650
3796
|
sessionId: opts.getSessionId?.() ?? replProjectRoot,
|
|
3651
|
-
name: `REPL [${
|
|
3797
|
+
name: `REPL [${path11.basename(replProjectRoot)}]`,
|
|
3652
3798
|
source: "repl",
|
|
3653
3799
|
pid: process.pid
|
|
3654
3800
|
}).then(() => {
|
|
@@ -4442,7 +4588,8 @@ async function execute(deps) {
|
|
|
4442
4588
|
slashRegistry,
|
|
4443
4589
|
tokenCounter,
|
|
4444
4590
|
activateSessionIdentity,
|
|
4445
|
-
updateInfo: initialUpdateInfo
|
|
4591
|
+
updateInfo: initialUpdateInfo,
|
|
4592
|
+
webuiSessionChild
|
|
4446
4593
|
},
|
|
4447
4594
|
session: {
|
|
4448
4595
|
session,
|
|
@@ -4555,7 +4702,7 @@ async function execute(deps) {
|
|
|
4555
4702
|
const profileName = config.activeProfile ?? "default";
|
|
4556
4703
|
const bootUpdateInfo = initialUpdateInfo;
|
|
4557
4704
|
const offStorageObservability = installStorageObservability(events, context.traceId);
|
|
4558
|
-
|
|
4705
|
+
const chimeraWork = createChimeraWorkRegistry();
|
|
4559
4706
|
installChimeraReviewHandler({
|
|
4560
4707
|
events,
|
|
4561
4708
|
director,
|
|
@@ -4569,8 +4716,8 @@ async function execute(deps) {
|
|
|
4569
4716
|
// this, a 429-stricken model is re-spawned on every concurrent reviewer
|
|
4570
4717
|
// turn and burns the whole chain instead of staying quarantined.
|
|
4571
4718
|
statusTracker,
|
|
4572
|
-
|
|
4573
|
-
|
|
4719
|
+
trackWork: (work) => {
|
|
4720
|
+
chimeraWork.track(work);
|
|
4574
4721
|
}
|
|
4575
4722
|
});
|
|
4576
4723
|
installChimeraCascadeHandler({
|
|
@@ -4581,9 +4728,9 @@ async function execute(deps) {
|
|
|
4581
4728
|
profileChain: effectiveFallbackChain2(config),
|
|
4582
4729
|
session: { provider: config.provider, model: config.model }
|
|
4583
4730
|
}),
|
|
4584
|
-
getPendingWork: () =>
|
|
4585
|
-
|
|
4586
|
-
|
|
4731
|
+
getPendingWork: () => chimeraWork.pending(),
|
|
4732
|
+
trackWork: (work) => {
|
|
4733
|
+
chimeraWork.track(work);
|
|
4587
4734
|
}
|
|
4588
4735
|
});
|
|
4589
4736
|
let code = 0;
|
|
@@ -4910,6 +5057,7 @@ async function execute(deps) {
|
|
|
4910
5057
|
sddSubagentFactory,
|
|
4911
5058
|
statusTracker,
|
|
4912
5059
|
updateInfo: bootUpdateInfo,
|
|
5060
|
+
webuiSessionChild,
|
|
4913
5061
|
getFleetBudget: () => {
|
|
4914
5062
|
const d = getDirector?.() ?? null;
|
|
4915
5063
|
if (!d) return null;
|
|
@@ -4952,7 +5100,7 @@ async function execute(deps) {
|
|
|
4952
5100
|
attachments,
|
|
4953
5101
|
effectiveMaxContext,
|
|
4954
5102
|
getEffectiveMaxContext,
|
|
4955
|
-
projectName:
|
|
5103
|
+
projectName: path12.basename(projectRoot) || void 0,
|
|
4956
5104
|
projectRoot,
|
|
4957
5105
|
appConfig: config,
|
|
4958
5106
|
getSessionId: () => agent.ctx.session?.id ?? session.id,
|
|
@@ -4995,7 +5143,7 @@ async function execute(deps) {
|
|
|
4995
5143
|
session,
|
|
4996
5144
|
tokenCounter,
|
|
4997
5145
|
events,
|
|
4998
|
-
|
|
5146
|
+
chimeraWork,
|
|
4999
5147
|
director,
|
|
5000
5148
|
reader
|
|
5001
5149
|
});
|
|
@@ -5006,8 +5154,9 @@ export {
|
|
|
5006
5154
|
CHIMERA_REVIEW_READ_ONLY_TOOLS,
|
|
5007
5155
|
__resetReviewerRoundRobinCursor,
|
|
5008
5156
|
applyChimeraReviewerReadOnlyPolicy,
|
|
5157
|
+
assignReviewerModels,
|
|
5009
5158
|
assignReviewerModelsRoundRobin,
|
|
5010
5159
|
execute,
|
|
5011
5160
|
resolveReviewerFallbackModels
|
|
5012
5161
|
};
|
|
5013
|
-
//# sourceMappingURL=execution-
|
|
5162
|
+
//# sourceMappingURL=execution-CQ772VPS.js.map
|