@wrongstack/cli 0.305.0 → 0.306.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-K7CYVVKH.js → auth-GVPYLJPS.js} +7 -7
- package/dist/boot/short-circuit-flags.d.ts +7 -1
- package/dist/boot/system-prompt-menu.d.ts +151 -0
- package/dist/chimera-cascade-evidence.d.ts +102 -0
- package/dist/chimera-review-task.d.ts +7 -0
- package/dist/{chunk-C5NXM2SI.js → chunk-5JW3XCRA.js} +7 -3
- package/dist/{chunk-FJVCVZIV.js → chunk-WC3DK6BI.js} +5 -5
- package/dist/{cli-main-W3T56YCY.js → cli-main-DHNFGP3Z.js} +278 -197
- package/dist/diag-doctor-WTBHPOMB.js +329 -0
- package/dist/{execution-YMBD7YWC.js → execution-TTE7R5UY.js} +313 -53
- package/dist/execution-chimera-cascade.d.ts +7 -1
- package/dist/{hq-5G6D5YIU.js → hq-ZK6PGN3W.js} +95 -6
- package/dist/index.js +759 -546
- package/dist/{modeldiag-SIVUOX2Y.js → modeldiag-6VS5KDP5.js} +4 -4
- package/dist/subcommands/handlers/daemon-inventory.d.ts +41 -0
- package/dist/wiring/management-tools.d.ts +8 -1
- package/package.json +24 -23
- package/dist/diag-doctor-ZF5BF2MK.js +0 -169
|
@@ -44,6 +44,27 @@ import {
|
|
|
44
44
|
PLUGIN_AUDIT_ENTRIES,
|
|
45
45
|
runPluginManagementCommand
|
|
46
46
|
} from "./chunk-RK7E3IXT.js";
|
|
47
|
+
import {
|
|
48
|
+
configureSimpleUiRuntimeContext,
|
|
49
|
+
detectProjectFacts,
|
|
50
|
+
makeConfirmAwaiter,
|
|
51
|
+
renderAgentsTemplate
|
|
52
|
+
} from "./chunk-YKBRFSGL.js";
|
|
53
|
+
import "./chunk-QD544J2B.js";
|
|
54
|
+
import {
|
|
55
|
+
fmtTaskResultLine,
|
|
56
|
+
fmtTok,
|
|
57
|
+
patchConfig
|
|
58
|
+
} from "./chunk-TYO2OVAD.js";
|
|
59
|
+
import {
|
|
60
|
+
CLI_VERSION
|
|
61
|
+
} from "./chunk-XJXDOF63.js";
|
|
62
|
+
import {
|
|
63
|
+
buildWin32CmdShimInvocation
|
|
64
|
+
} from "./chunk-U3SS4NRH.js";
|
|
65
|
+
import {
|
|
66
|
+
checkForUpdate
|
|
67
|
+
} from "./chunk-NUIHRGPY.js";
|
|
47
68
|
import {
|
|
48
69
|
createGracefulShutdown,
|
|
49
70
|
loadCachedAcpRegistry,
|
|
@@ -59,30 +80,18 @@ import {
|
|
|
59
80
|
runClaudeOAuthLogin,
|
|
60
81
|
runCopilotOAuthLogin,
|
|
61
82
|
validateFamily
|
|
62
|
-
} from "./chunk-
|
|
63
|
-
import {
|
|
64
|
-
runCodexOAuthLogin
|
|
65
|
-
} from "./chunk-SSSJQVUY.js";
|
|
66
|
-
import {
|
|
67
|
-
configureSimpleUiRuntimeContext,
|
|
68
|
-
detectProjectFacts,
|
|
69
|
-
makeConfirmAwaiter,
|
|
70
|
-
renderAgentsTemplate
|
|
71
|
-
} from "./chunk-YKBRFSGL.js";
|
|
72
|
-
import "./chunk-QD544J2B.js";
|
|
73
|
-
import {
|
|
74
|
-
fmtTaskResultLine,
|
|
75
|
-
fmtTok,
|
|
76
|
-
patchConfig
|
|
77
|
-
} from "./chunk-TYO2OVAD.js";
|
|
83
|
+
} from "./chunk-WC3DK6BI.js";
|
|
78
84
|
import {
|
|
79
85
|
LOCAL_LLM_PRESETS,
|
|
80
86
|
parseSpawnFlags
|
|
81
|
-
} from "./chunk-
|
|
87
|
+
} from "./chunk-5JW3XCRA.js";
|
|
82
88
|
import {
|
|
83
89
|
buildPickableProviders,
|
|
84
90
|
visibleModelIds
|
|
85
91
|
} from "./chunk-3IC4IEZC.js";
|
|
92
|
+
import {
|
|
93
|
+
runCodexOAuthLogin
|
|
94
|
+
} from "./chunk-SSSJQVUY.js";
|
|
86
95
|
import {
|
|
87
96
|
activeLabel,
|
|
88
97
|
loadConfigProviders,
|
|
@@ -97,15 +106,6 @@ import {
|
|
|
97
106
|
import {
|
|
98
107
|
activeProfileConfigPath
|
|
99
108
|
} from "./chunk-YMXXOOFN.js";
|
|
100
|
-
import {
|
|
101
|
-
buildWin32CmdShimInvocation
|
|
102
|
-
} from "./chunk-U3SS4NRH.js";
|
|
103
|
-
import {
|
|
104
|
-
checkForUpdate
|
|
105
|
-
} from "./chunk-NUIHRGPY.js";
|
|
106
|
-
import {
|
|
107
|
-
CLI_VERSION
|
|
108
|
-
} from "./chunk-XJXDOF63.js";
|
|
109
109
|
import {
|
|
110
110
|
__require
|
|
111
111
|
} from "./chunk-7OCVIDC7.js";
|
|
@@ -8033,6 +8033,12 @@ function registerProviderUtilityTools(input) {
|
|
|
8033
8033
|
fallbackProfileManager: input.fallbackProfileManager,
|
|
8034
8034
|
defaultProvider: config.provider,
|
|
8035
8035
|
defaultModel: config.model,
|
|
8036
|
+
// Same live router the council gets below. Without it the `role` input
|
|
8037
|
+
// was inert (the orchestrator's pickForTask path no-ops), and without the
|
|
8038
|
+
// tracker no llm-tool call ever recorded provider health, so blocked
|
|
8039
|
+
// entries were neither skipped nor reported for this tool's traffic.
|
|
8040
|
+
modelRouter: createLiveModelRouter(input.getConfig),
|
|
8041
|
+
statusTracker: input.statusTracker,
|
|
8036
8042
|
wrapProviderCall: input.wrapProviderCall
|
|
8037
8043
|
});
|
|
8038
8044
|
registerOrOverride(input.toolRegistry, "llm", llmTool);
|
|
@@ -8362,27 +8368,40 @@ async function setupLifecycleAndPlugins(deps) {
|
|
|
8362
8368
|
}
|
|
8363
8369
|
|
|
8364
8370
|
// src/wiring/management-tools.ts
|
|
8365
|
-
import * as fs5 from "node:fs/promises";
|
|
8366
8371
|
import {
|
|
8367
8372
|
createFallbackManageTools,
|
|
8368
8373
|
createPluginManagerTool
|
|
8369
8374
|
} from "@wrongstack/core/tools";
|
|
8375
|
+
import { updateJsonObjectFile } from "@wrongstack/core/utils";
|
|
8370
8376
|
function registerCliManagementTools({
|
|
8371
8377
|
toolRegistry,
|
|
8372
8378
|
configStore,
|
|
8373
8379
|
profileConfigPath,
|
|
8374
8380
|
stdinInteractive,
|
|
8375
|
-
getHookRunner
|
|
8381
|
+
getHookRunner,
|
|
8382
|
+
getSwitchProviderAndModel
|
|
8376
8383
|
}) {
|
|
8377
8384
|
const fallbackManageTools = createFallbackManageTools({
|
|
8378
8385
|
getConfig: () => configStore.get(),
|
|
8386
|
+
// updateJsonObjectFile is the same atomic read-mutate-write helper
|
|
8387
|
+
// mcp_control uses on this very file — the previous bare
|
|
8388
|
+
// readFile→JSON.parse→writeFile raced it and could drop concurrent
|
|
8389
|
+
// updates (and tore the file on a crash mid-write).
|
|
8379
8390
|
updateConfig: async (mutate) => {
|
|
8380
|
-
const
|
|
8381
|
-
|
|
8382
|
-
|
|
8383
|
-
|
|
8384
|
-
configStore.update(parsed);
|
|
8391
|
+
const next = await updateJsonObjectFile(profileConfigPath, (cfg) => {
|
|
8392
|
+
mutate(cfg);
|
|
8393
|
+
});
|
|
8394
|
+
configStore.update(next);
|
|
8385
8395
|
},
|
|
8396
|
+
...getSwitchProviderAndModel ? {
|
|
8397
|
+
switchProviderAndModel: async (providerId, modelId) => {
|
|
8398
|
+
const switchFn = getSwitchProviderAndModel();
|
|
8399
|
+
if (!switchFn) {
|
|
8400
|
+
return "the live model switch is not ready yet (still booting) \u2014 try again shortly";
|
|
8401
|
+
}
|
|
8402
|
+
return switchFn(providerId, modelId);
|
|
8403
|
+
}
|
|
8404
|
+
} : {},
|
|
8386
8405
|
// Interactive key entry for REPL mode reads a line from stdin without echo.
|
|
8387
8406
|
...stdinInteractive ? {
|
|
8388
8407
|
requestInput: async (prompt) => {
|
|
@@ -8739,14 +8758,14 @@ function setupProviderRuntime(deps) {
|
|
|
8739
8758
|
}
|
|
8740
8759
|
|
|
8741
8760
|
// src/wiring/provider-status.ts
|
|
8742
|
-
import * as
|
|
8761
|
+
import * as fs5 from "node:fs/promises";
|
|
8743
8762
|
import { ProviderModelStatusTracker } from "@wrongstack/core/coordination";
|
|
8744
8763
|
import { atomicWrite as atomicWrite2, withFileLock } from "@wrongstack/core/utils";
|
|
8745
8764
|
async function setupProviderStatus(input) {
|
|
8746
8765
|
const tracker = new ProviderModelStatusTracker({ events: input.events });
|
|
8747
8766
|
const statusFile = input.paths.profileProviderStatus(input.paths.profileName);
|
|
8748
8767
|
try {
|
|
8749
|
-
const saved = JSON.parse(await
|
|
8768
|
+
const saved = JSON.parse(await fs5.readFile(statusFile, "utf8"));
|
|
8750
8769
|
const restored = tracker.restoreSnapshot(saved);
|
|
8751
8770
|
if (restored > 0) input.logger.info(`Restored ${restored} provider waiting-room entries`);
|
|
8752
8771
|
} catch (error) {
|
|
@@ -8758,7 +8777,7 @@ async function setupProviderStatus(input) {
|
|
|
8758
8777
|
tracker.sweepExpired();
|
|
8759
8778
|
if (syncRunning) return;
|
|
8760
8779
|
syncRunning = true;
|
|
8761
|
-
void
|
|
8780
|
+
void fs5.readFile(statusFile, "utf8").then((raw) => tracker.restoreSnapshot(JSON.parse(raw))).catch((error) => warnUnlessMissing(input.logger, "sync", error)).finally(() => {
|
|
8762
8781
|
syncRunning = false;
|
|
8763
8782
|
});
|
|
8764
8783
|
}, 3e4);
|
|
@@ -8773,7 +8792,7 @@ async function setupProviderStatus(input) {
|
|
|
8773
8792
|
await withFileLock(statusFile, async () => {
|
|
8774
8793
|
let statuses = [];
|
|
8775
8794
|
try {
|
|
8776
|
-
const current = JSON.parse(await
|
|
8795
|
+
const current = JSON.parse(await fs5.readFile(statusFile, "utf8"));
|
|
8777
8796
|
if (Array.isArray(current.statuses)) statuses = current.statuses;
|
|
8778
8797
|
} catch (error) {
|
|
8779
8798
|
if (error.code !== "ENOENT") throw error;
|
|
@@ -9542,7 +9561,11 @@ import {
|
|
|
9542
9561
|
sessionScopedPath as sessionScopedPath3,
|
|
9543
9562
|
toErrorMessage as toErrorMessage5
|
|
9544
9563
|
} from "@wrongstack/core/utils";
|
|
9545
|
-
import {
|
|
9564
|
+
import {
|
|
9565
|
+
attachSessionKanbanMirror,
|
|
9566
|
+
hydrateSessionKanban,
|
|
9567
|
+
sessionKanbanDegradation
|
|
9568
|
+
} from "@wrongstack/tools/session-kanban";
|
|
9546
9569
|
async function setupSession(params) {
|
|
9547
9570
|
const {
|
|
9548
9571
|
config,
|
|
@@ -9706,6 +9729,12 @@ async function setupSession(params) {
|
|
|
9706
9729
|
const taskPath = sessionScopedPath3(wpaths.projectSessions, sessionId, ".tasks.json");
|
|
9707
9730
|
context.state.setMeta("task.path", taskPath);
|
|
9708
9731
|
await hydrateSessionKanban(context);
|
|
9732
|
+
const kanbanDown = sessionKanbanDegradation();
|
|
9733
|
+
if (kanbanDown) {
|
|
9734
|
+
renderer.writeInfo(
|
|
9735
|
+
`Kanban board sync unavailable \u2014 continuing without it (${kanbanDown}). Run \`wstack doctor --daemons\` for detail.`
|
|
9736
|
+
);
|
|
9737
|
+
}
|
|
9709
9738
|
const detachSessionKanbanMirror = attachSessionKanbanMirror(context);
|
|
9710
9739
|
const detachTodosCheckpoint = async () => {
|
|
9711
9740
|
detachSessionKanbanMirror();
|
|
@@ -9804,7 +9833,7 @@ import {
|
|
|
9804
9833
|
readJsonObjectFile,
|
|
9805
9834
|
removeJsonPath,
|
|
9806
9835
|
setJsonPath,
|
|
9807
|
-
updateJsonObjectFile
|
|
9836
|
+
updateJsonObjectFile as updateJsonObjectFile2
|
|
9808
9837
|
} from "@wrongstack/core/utils";
|
|
9809
9838
|
function parseMcpArgs(args) {
|
|
9810
9839
|
const trimmed = args.trim();
|
|
@@ -9902,7 +9931,7 @@ async function runAdd(name, enable, configured, configPath, mcpRegistry, all) {
|
|
|
9902
9931
|
}
|
|
9903
9932
|
const existing = configured[name];
|
|
9904
9933
|
const nextCfg = existing ? { ...preset, ...existing, enabled: enable } : { ...preset, enabled: enable };
|
|
9905
|
-
await
|
|
9934
|
+
await updateJsonObjectFile2(configPath, (full) => {
|
|
9906
9935
|
const current = isMcpServerRecord(full.mcpServers) ? full.mcpServers : {};
|
|
9907
9936
|
setJsonPath(full, ["mcpServers", name], { ...current[name], ...nextCfg });
|
|
9908
9937
|
});
|
|
@@ -9941,7 +9970,7 @@ async function runRemove(name, configured, configPath, mcpRegistry) {
|
|
|
9941
9970
|
);
|
|
9942
9971
|
}
|
|
9943
9972
|
if (typeof mcpRegistry.forget === "function") mcpRegistry.forget(name);
|
|
9944
|
-
await
|
|
9973
|
+
await updateJsonObjectFile2(configPath, (full) => {
|
|
9945
9974
|
const current = isMcpServerRecord(full.mcpServers) ? full.mcpServers : configured;
|
|
9946
9975
|
setJsonPath(full, ["mcpServers"], { ...current });
|
|
9947
9976
|
removeJsonPath(full, ["mcpServers", name]);
|
|
@@ -9960,7 +9989,7 @@ async function runEnable(name, configured, configPath, mcpRegistry) {
|
|
|
9960
9989
|
return `${color8.green("Enabled")} "${name}" and started.`;
|
|
9961
9990
|
}
|
|
9962
9991
|
}
|
|
9963
|
-
await
|
|
9992
|
+
await updateJsonObjectFile2(configPath, (full) => {
|
|
9964
9993
|
const current = isMcpServerRecord(full.mcpServers) ? full.mcpServers : {};
|
|
9965
9994
|
setJsonPath(full, ["mcpServers", name], { ...cfg, ...current[name], enabled: true });
|
|
9966
9995
|
});
|
|
@@ -9988,7 +10017,7 @@ async function runDisable(name, configured, configPath, mcpRegistry) {
|
|
|
9988
10017
|
})
|
|
9989
10018
|
);
|
|
9990
10019
|
}
|
|
9991
|
-
await
|
|
10020
|
+
await updateJsonObjectFile2(configPath, (full) => {
|
|
9992
10021
|
const current = isMcpServerRecord(full.mcpServers) ? full.mcpServers : {};
|
|
9993
10022
|
setJsonPath(full, ["mcpServers", name], { ...cfg, ...current[name], enabled: false });
|
|
9994
10023
|
});
|
|
@@ -11332,7 +11361,7 @@ ${color13.dim("YOLO enabled; tool calls run without approval unless an explicit
|
|
|
11332
11361
|
|
|
11333
11362
|
// src/slash-commands/brain.ts
|
|
11334
11363
|
import { randomUUID as randomUUID5 } from "node:crypto";
|
|
11335
|
-
import { readFile as
|
|
11364
|
+
import { readFile as readFile6 } from "node:fs/promises";
|
|
11336
11365
|
import { parseModelRef } from "@wrongstack/core/agent";
|
|
11337
11366
|
import { BUILTIN_COUNCIL_PERSONA_IDS, BUILTIN_COUNCIL_PERSONAS } from "@wrongstack/core/execution";
|
|
11338
11367
|
import { color as color14 } from "@wrongstack/core/utils";
|
|
@@ -11778,7 +11807,7 @@ function buildBrainCommand(opts) {
|
|
|
11778
11807
|
const n = Math.max(1, Math.min(100, Number.parseInt(rest[0] ?? "15", 10) || 15));
|
|
11779
11808
|
let raw;
|
|
11780
11809
|
try {
|
|
11781
|
-
raw = await
|
|
11810
|
+
raw = await readFile6(ledgerPath, "utf8");
|
|
11782
11811
|
} catch {
|
|
11783
11812
|
const msg3 = `No ledger entries yet (${ledgerPath}).`;
|
|
11784
11813
|
opts.renderer.write(msg3);
|
|
@@ -12657,7 +12686,7 @@ function buildCompactCommand(opts) {
|
|
|
12657
12686
|
}
|
|
12658
12687
|
|
|
12659
12688
|
// src/slash-commands/context.ts
|
|
12660
|
-
import * as
|
|
12689
|
+
import * as fs6 from "node:fs/promises";
|
|
12661
12690
|
import {
|
|
12662
12691
|
formatContextWindowModeList,
|
|
12663
12692
|
getContextWindowMode,
|
|
@@ -12971,6 +13000,7 @@ var SOURCE_LABELS = {
|
|
|
12971
13000
|
contributor: "contributor",
|
|
12972
13001
|
ledger: "completed-work ledger",
|
|
12973
13002
|
glossary: "project jargon dictionary",
|
|
13003
|
+
peers: "fleet peer awareness",
|
|
12974
13004
|
nextsteps: "next-steps gate",
|
|
12975
13005
|
other: "other (untagged)"
|
|
12976
13006
|
};
|
|
@@ -13019,7 +13049,7 @@ async function persistContextConfig(opts, patch) {
|
|
|
13019
13049
|
const configPath = activeProfileConfigPath(opts.paths, opts.configStore.get());
|
|
13020
13050
|
let raw = "{}";
|
|
13021
13051
|
try {
|
|
13022
|
-
raw = await
|
|
13052
|
+
raw = await fs6.readFile(configPath, "utf8");
|
|
13023
13053
|
} catch (err) {
|
|
13024
13054
|
if (err.code !== "ENOENT") {
|
|
13025
13055
|
return `Could not read ${configPath}: ${err.message}`;
|
|
@@ -13424,7 +13454,7 @@ function listRoles() {
|
|
|
13424
13454
|
}
|
|
13425
13455
|
|
|
13426
13456
|
// src/slash-commands/design.ts
|
|
13427
|
-
import * as
|
|
13457
|
+
import * as fs7 from "node:fs/promises";
|
|
13428
13458
|
import * as path19 from "node:path";
|
|
13429
13459
|
import {
|
|
13430
13460
|
applyTokenOverrides,
|
|
@@ -13584,8 +13614,8 @@ ${menu}` };
|
|
|
13584
13614
|
return { message: e.message };
|
|
13585
13615
|
}
|
|
13586
13616
|
try {
|
|
13587
|
-
await
|
|
13588
|
-
await
|
|
13617
|
+
await fs7.mkdir(path19.dirname(abs), { recursive: true });
|
|
13618
|
+
await fs7.writeFile(abs, result.content);
|
|
13589
13619
|
} catch (e) {
|
|
13590
13620
|
return { message: `Failed to write ${result.path}: ${e.message}` };
|
|
13591
13621
|
}
|
|
@@ -13752,7 +13782,7 @@ function buildStatsCommand(opts) {
|
|
|
13752
13782
|
}
|
|
13753
13783
|
|
|
13754
13784
|
// src/slash-commands/doctor.ts
|
|
13755
|
-
import * as
|
|
13785
|
+
import * as fs8 from "node:fs/promises";
|
|
13756
13786
|
import * as path20 from "node:path";
|
|
13757
13787
|
import { atomicWrite as atomicWrite4, color as color22, toErrorMessage as toErrorMessage10 } from "@wrongstack/core/utils";
|
|
13758
13788
|
|
|
@@ -14317,7 +14347,7 @@ function buildDoctorCommand(opts) {
|
|
|
14317
14347
|
const base = path20.basename(file);
|
|
14318
14348
|
const candidates = [`${base}.last`];
|
|
14319
14349
|
try {
|
|
14320
|
-
const siblings = await
|
|
14350
|
+
const siblings = await fs8.readdir(dir);
|
|
14321
14351
|
candidates.push(
|
|
14322
14352
|
...siblings.filter((f) => f.startsWith(`${base}.`) && f.endsWith(".bak")).sort().reverse()
|
|
14323
14353
|
);
|
|
@@ -14325,7 +14355,7 @@ function buildDoctorCommand(opts) {
|
|
|
14325
14355
|
}
|
|
14326
14356
|
for (const name of candidates) {
|
|
14327
14357
|
try {
|
|
14328
|
-
const raw = await
|
|
14358
|
+
const raw = await fs8.readFile(path20.join(dir, name), "utf8");
|
|
14329
14359
|
JSON.parse(raw);
|
|
14330
14360
|
return { name, raw };
|
|
14331
14361
|
} catch {
|
|
@@ -14378,7 +14408,7 @@ function buildDoctorCommand(opts) {
|
|
|
14378
14408
|
for (const target of targets) {
|
|
14379
14409
|
let raw;
|
|
14380
14410
|
try {
|
|
14381
|
-
raw = await
|
|
14411
|
+
raw = await fs8.readFile(target.file, "utf8");
|
|
14382
14412
|
} catch {
|
|
14383
14413
|
if (!target.isProject) {
|
|
14384
14414
|
lines.push(
|
|
@@ -14693,7 +14723,7 @@ function buildFKeyAliasCommands(opts) {
|
|
|
14693
14723
|
}
|
|
14694
14724
|
|
|
14695
14725
|
// src/slash-commands/fallback.ts
|
|
14696
|
-
import * as
|
|
14726
|
+
import * as fs9 from "node:fs/promises";
|
|
14697
14727
|
import {
|
|
14698
14728
|
normalizeModelRef,
|
|
14699
14729
|
parseModelRef as parseModelRef2,
|
|
@@ -14737,7 +14767,7 @@ async function patchGlobalConfig(globalConfigPath, mutate) {
|
|
|
14737
14767
|
let raw = "{}";
|
|
14738
14768
|
let fileExists2 = true;
|
|
14739
14769
|
try {
|
|
14740
|
-
raw = await
|
|
14770
|
+
raw = await fs9.readFile(globalConfigPath, "utf8");
|
|
14741
14771
|
} catch (err) {
|
|
14742
14772
|
if (err.code !== "ENOENT") throw err;
|
|
14743
14773
|
fileExists2 = false;
|
|
@@ -16798,7 +16828,7 @@ ${color27.dim("(dry-run)")}`
|
|
|
16798
16828
|
}
|
|
16799
16829
|
|
|
16800
16830
|
// src/slash-commands/gitid.ts
|
|
16801
|
-
import * as
|
|
16831
|
+
import * as fs10 from "node:fs/promises";
|
|
16802
16832
|
import { decryptConfigSecrets as decryptConfigSecrets2, encryptConfigSecrets as encryptConfigSecrets2, noOpVault as noOpVault3 } from "@wrongstack/core/security";
|
|
16803
16833
|
import { ConfigError as ConfigError2 } from "@wrongstack/core/types";
|
|
16804
16834
|
import {
|
|
@@ -16815,7 +16845,7 @@ async function patchGlobalConfig2(globalConfigPath, mutate) {
|
|
|
16815
16845
|
let raw = "{}";
|
|
16816
16846
|
let fileExists2 = true;
|
|
16817
16847
|
try {
|
|
16818
|
-
raw = await
|
|
16848
|
+
raw = await fs10.readFile(globalConfigPath, "utf8");
|
|
16819
16849
|
} catch (err) {
|
|
16820
16850
|
if (err.code !== "ENOENT") throw err;
|
|
16821
16851
|
fileExists2 = false;
|
|
@@ -17272,7 +17302,7 @@ function buildHelpCommand(opts) {
|
|
|
17272
17302
|
}
|
|
17273
17303
|
|
|
17274
17304
|
// src/slash-commands/init.ts
|
|
17275
|
-
import * as
|
|
17305
|
+
import * as fs11 from "node:fs/promises";
|
|
17276
17306
|
import * as path22 from "node:path";
|
|
17277
17307
|
import { color as color30 } from "@wrongstack/core/utils";
|
|
17278
17308
|
function buildInitCommand(opts) {
|
|
@@ -17287,19 +17317,19 @@ function buildInitCommand(opts) {
|
|
|
17287
17317
|
const isFirstInit = !await fileExists(file);
|
|
17288
17318
|
const detected = await detectProjectFacts(root);
|
|
17289
17319
|
const body = renderAgentsTemplate(detected);
|
|
17290
|
-
await
|
|
17320
|
+
await fs11.mkdir(dir, { recursive: true });
|
|
17291
17321
|
let backedUp = false;
|
|
17292
17322
|
if (!isFirstInit) {
|
|
17293
17323
|
try {
|
|
17294
|
-
await
|
|
17324
|
+
await fs11.copyFile(file, `${file}.bak`);
|
|
17295
17325
|
backedUp = true;
|
|
17296
17326
|
} catch {
|
|
17297
17327
|
}
|
|
17298
17328
|
}
|
|
17299
|
-
await
|
|
17329
|
+
await fs11.writeFile(file, body, "utf8");
|
|
17300
17330
|
let nodePkg = false;
|
|
17301
17331
|
try {
|
|
17302
|
-
await
|
|
17332
|
+
await fs11.access(path22.join(root, "package.json"));
|
|
17303
17333
|
nodePkg = true;
|
|
17304
17334
|
} catch {
|
|
17305
17335
|
}
|
|
@@ -17337,7 +17367,7 @@ function buildInitCommand(opts) {
|
|
|
17337
17367
|
}
|
|
17338
17368
|
async function fileExists(filePath) {
|
|
17339
17369
|
try {
|
|
17340
|
-
await
|
|
17370
|
+
await fs11.access(filePath);
|
|
17341
17371
|
return true;
|
|
17342
17372
|
} catch {
|
|
17343
17373
|
return false;
|
|
@@ -17456,6 +17486,7 @@ import {
|
|
|
17456
17486
|
updateTask,
|
|
17457
17487
|
updateTaskAssignment
|
|
17458
17488
|
} from "@wrongstack/kanban";
|
|
17489
|
+
import { preflightManagedTransition } from "@wrongstack/kanban/manager/lifecycle";
|
|
17459
17490
|
import { TaskGraphStore } from "@wrongstack/sdd";
|
|
17460
17491
|
|
|
17461
17492
|
// src/slash-commands/kanban-agent-helpers.ts
|
|
@@ -18227,9 +18258,9 @@ async function handleTaskSubcommand(opts, projectRoot, args, showHelp) {
|
|
|
18227
18258
|
try {
|
|
18228
18259
|
const result = await transitionTask(projectRoot, boardId, taskId, {
|
|
18229
18260
|
to,
|
|
18230
|
-
actor: "kanban-slash",
|
|
18231
|
-
action: `Moved to ${resolvedColumnId} via /kanban task move`,
|
|
18232
|
-
comment: moveNote ? `${moveNote} (move \u2192 ${resolvedColumnId})` :
|
|
18261
|
+
actor: "kanban-slash:move",
|
|
18262
|
+
action: moveNote ? `${moveNote} (move \u2192 ${resolvedColumnId})` : `Moved to ${resolvedColumnId} via /kanban task move`,
|
|
18263
|
+
comment: moveNote ? `${moveNote} (move \u2192 ${resolvedColumnId})` : `Moved to ${resolvedColumnId} via /kanban task move (board=${boardId}, task=${taskId})`,
|
|
18233
18264
|
// Reviewers require a non-empty attachment URL to advance into review.
|
|
18234
18265
|
// Forward the caller's `--attachment`; if missing, the move must fail at
|
|
18235
18266
|
// `validateReviewEvidence` so the audit ledger never records a fabricated
|
|
@@ -18263,7 +18294,7 @@ async function handleTaskSubcommand(opts, projectRoot, args, showHelp) {
|
|
|
18263
18294
|
)
|
|
18264
18295
|
};
|
|
18265
18296
|
}
|
|
18266
|
-
const { attachment, note, positional, warnings } = parseTaskEvidenceFlags(rest.slice(1));
|
|
18297
|
+
const { attachment, note, tickChecks, positional, warnings } = parseTaskEvidenceFlags(rest.slice(1));
|
|
18267
18298
|
if (positional.length > 0) {
|
|
18268
18299
|
return {
|
|
18269
18300
|
message: color32.red(
|
|
@@ -18292,73 +18323,36 @@ async function handleTaskSubcommand(opts, projectRoot, args, showHelp) {
|
|
|
18292
18323
|
)
|
|
18293
18324
|
};
|
|
18294
18325
|
}
|
|
18295
|
-
const preflightIssues = [];
|
|
18296
|
-
const needsRunningEvidence = path32.includes("running");
|
|
18297
|
-
const needsReviewEvidence = path32.includes("review");
|
|
18298
|
-
const needsDoneEvidence = path32.includes("done");
|
|
18299
18326
|
const currentTask = board.tasks.find((t) => t.id === taskId);
|
|
18300
18327
|
if (!currentTask) {
|
|
18301
18328
|
return { message: color32.red("Task not found") };
|
|
18302
18329
|
}
|
|
18303
|
-
|
|
18304
|
-
|
|
18305
|
-
|
|
18306
|
-
|
|
18307
|
-
|
|
18308
|
-
|
|
18309
|
-
|
|
18310
|
-
].every((value) => typeof value === "string" && value.trim().length > 0);
|
|
18311
|
-
if (!hasLease) {
|
|
18312
|
-
preflightIssues.push(
|
|
18313
|
-
"The /kanban task done path needs the card to already be Running with lease metadata; move it into Running first via /kanban task assign or /kanban task dispatch."
|
|
18314
|
-
);
|
|
18315
|
-
}
|
|
18316
|
-
}
|
|
18317
|
-
if (needsReviewEvidence && !attachment) {
|
|
18318
|
-
preflightIssues.push(
|
|
18319
|
-
'Review evidence requires --attachment <url>; re-run `/kanban task done <boardId> <taskId> --attachment https://example.test/review --note "..."`.'
|
|
18320
|
-
);
|
|
18321
|
-
} else if (needsReviewEvidence && !currentTask.assignment?.lastResult) {
|
|
18322
|
-
preflightIssues.push(
|
|
18323
|
-
"Review evidence requires the card to carry an assignment.lastResult; dispatch the worker through the agentic supervisor so it records implementation output."
|
|
18324
|
-
);
|
|
18330
|
+
const preflightIssues = [];
|
|
18331
|
+
if (!note || !note.trim()) {
|
|
18332
|
+
return {
|
|
18333
|
+
message: color32.red(
|
|
18334
|
+
`Refusing /kanban task ${currentStage ?? "unknown"} \u2192 done without a reviewer note. Re-run with --note "<what proves the work is ready>".`
|
|
18335
|
+
)
|
|
18336
|
+
};
|
|
18325
18337
|
}
|
|
18326
|
-
|
|
18327
|
-
|
|
18328
|
-
|
|
18329
|
-
|
|
18330
|
-
|
|
18331
|
-
|
|
18332
|
-
|
|
18333
|
-
|
|
18334
|
-
|
|
18335
|
-
|
|
18336
|
-
)
|
|
18337
|
-
|
|
18338
|
-
|
|
18339
|
-
|
|
18340
|
-
|
|
18341
|
-
|
|
18342
|
-
|
|
18343
|
-
|
|
18344
|
-
const childTasks = board.tasks.filter(
|
|
18345
|
-
(entry) => currentTask.childTaskIds.includes(entry.id)
|
|
18346
|
-
);
|
|
18347
|
-
const missingChildren = currentTask.childTaskIds.filter(
|
|
18348
|
-
(childId) => !childTasks.some((entry) => entry.id === childId)
|
|
18349
|
-
);
|
|
18350
|
-
if (missingChildren.length > 0) {
|
|
18351
|
-
preflightIssues.push(
|
|
18352
|
-
`Atomic parent references unresolved children (${missingChildren.join(", ")}); resolve them via the kanban tool before retrying.`
|
|
18353
|
-
);
|
|
18354
|
-
}
|
|
18355
|
-
const incompleteChildren = childTasks.filter((child) => child.status !== "completed");
|
|
18356
|
-
if (incompleteChildren.length > 0) {
|
|
18357
|
-
const ids = incompleteChildren.map((child) => child.id).join(", ");
|
|
18358
|
-
preflightIssues.push(
|
|
18359
|
-
`Atomic parent's children must be completed before the parent can advance to Done (pending: ${ids}).`
|
|
18360
|
-
);
|
|
18361
|
-
}
|
|
18338
|
+
const noteText = note.trim();
|
|
18339
|
+
const sharedAttachment = attachment ? {
|
|
18340
|
+
url: attachment,
|
|
18341
|
+
type: "url",
|
|
18342
|
+
title: "Reviewer evidence (kanban-slash:done)"
|
|
18343
|
+
} : void 0;
|
|
18344
|
+
for (const to of path32) {
|
|
18345
|
+
const transitionInput = {
|
|
18346
|
+
to,
|
|
18347
|
+
actor: "kanban-slash:done",
|
|
18348
|
+
action: `${noteText} (${to})`,
|
|
18349
|
+
comment: `${noteText} (${to})`,
|
|
18350
|
+
...sharedAttachment ? { attachment: sharedAttachment } : {},
|
|
18351
|
+
...tickChecks ? { tickChecks } : {}
|
|
18352
|
+
};
|
|
18353
|
+
const issues = preflightManagedTransition(board, currentTask, transitionInput);
|
|
18354
|
+
for (const issue of issues) {
|
|
18355
|
+
preflightIssues.push(issue.message);
|
|
18362
18356
|
}
|
|
18363
18357
|
}
|
|
18364
18358
|
if (preflightIssues.length > 0) {
|
|
@@ -18373,16 +18367,17 @@ async function handleTaskSubcommand(opts, projectRoot, args, showHelp) {
|
|
|
18373
18367
|
for (const to of path32) {
|
|
18374
18368
|
await transitionTask(projectRoot, boardId, taskId, {
|
|
18375
18369
|
to,
|
|
18376
|
-
actor: "kanban-slash",
|
|
18377
|
-
action:
|
|
18378
|
-
comment:
|
|
18370
|
+
actor: "kanban-slash:done",
|
|
18371
|
+
action: noteText ? `${noteText} (${to})` : "",
|
|
18372
|
+
comment: noteText ? `${noteText} (${to})` : "",
|
|
18379
18373
|
...attachment ? {
|
|
18380
18374
|
attachment: {
|
|
18381
18375
|
url: attachment,
|
|
18382
18376
|
type: "url",
|
|
18383
|
-
title: "Reviewer evidence (kanban-slash)"
|
|
18377
|
+
title: "Reviewer evidence (kanban-slash:done)"
|
|
18384
18378
|
}
|
|
18385
|
-
} : {}
|
|
18379
|
+
} : {},
|
|
18380
|
+
...tickChecks.length > 0 ? { tickChecks } : {}
|
|
18386
18381
|
});
|
|
18387
18382
|
}
|
|
18388
18383
|
return { message: color32.green("\u2705 Task marked completed.") };
|
|
@@ -18805,14 +18800,17 @@ function resolveColumnReference(board, requested) {
|
|
|
18805
18800
|
function parseTaskEvidenceFlags(tokens) {
|
|
18806
18801
|
let attachment;
|
|
18807
18802
|
let note;
|
|
18803
|
+
const tickChecks = [];
|
|
18808
18804
|
const positional = [];
|
|
18809
18805
|
const warnings = [];
|
|
18810
18806
|
const ATTACHMENT_KEYS = /* @__PURE__ */ new Set(["--attachment", "--evidence", "--link"]);
|
|
18811
18807
|
const NOTE_KEYS = /* @__PURE__ */ new Set(["--note", "--comment", "--action"]);
|
|
18808
|
+
const TICK_CHECK_KEYS = /* @__PURE__ */ new Set(["--tick-check", "--tick-checks"]);
|
|
18809
|
+
const VALID_TICK_STATUSES = /* @__PURE__ */ new Set(["passed", "failed", "skipped"]);
|
|
18812
18810
|
for (let i = 0; i < tokens.length; i++) {
|
|
18813
18811
|
const token = tokens[i];
|
|
18814
18812
|
const eq = token.indexOf("=");
|
|
18815
|
-
const inline = eq > 0 && (ATTACHMENT_KEYS.has(token.slice(0, eq)) || NOTE_KEYS.has(token.slice(0, eq)));
|
|
18813
|
+
const inline = eq > 0 && (ATTACHMENT_KEYS.has(token.slice(0, eq)) || NOTE_KEYS.has(token.slice(0, eq)) || TICK_CHECK_KEYS.has(token.slice(0, eq)));
|
|
18816
18814
|
const key = inline ? token.slice(0, eq) : token;
|
|
18817
18815
|
if (ATTACHMENT_KEYS.has(key)) {
|
|
18818
18816
|
const value = inline ? token.slice(eq + 1) : tokens[i + 1];
|
|
@@ -18830,6 +18828,32 @@ function parseTaskEvidenceFlags(tokens) {
|
|
|
18830
18828
|
attachment = value;
|
|
18831
18829
|
continue;
|
|
18832
18830
|
}
|
|
18831
|
+
if (TICK_CHECK_KEYS.has(key)) {
|
|
18832
|
+
const raw = inline ? token.slice(eq + 1) : tokens[i + 1];
|
|
18833
|
+
if (!raw?.trim()) {
|
|
18834
|
+
warnings.push(`${key} expects <checkId>=<status> but none was provided`);
|
|
18835
|
+
i = inline ? i : i + 1;
|
|
18836
|
+
continue;
|
|
18837
|
+
}
|
|
18838
|
+
if (!inline && raw.startsWith("-")) {
|
|
18839
|
+
warnings.push(`${key} expects <checkId>=<status> but none was provided`);
|
|
18840
|
+
i++;
|
|
18841
|
+
continue;
|
|
18842
|
+
}
|
|
18843
|
+
const sep2 = raw.lastIndexOf("=");
|
|
18844
|
+
const checkId = sep2 >= 0 ? raw.slice(0, sep2).trim() : "";
|
|
18845
|
+
const status = sep2 >= 0 ? raw.slice(sep2 + 1).trim() : "";
|
|
18846
|
+
if (!checkId || !status || !VALID_TICK_STATUSES.has(status)) {
|
|
18847
|
+
warnings.push(
|
|
18848
|
+
`${key} expects <checkId>=<status> where status is passed|failed|skipped (got "${raw}")`
|
|
18849
|
+
);
|
|
18850
|
+
i = inline ? i : i + 1;
|
|
18851
|
+
continue;
|
|
18852
|
+
}
|
|
18853
|
+
tickChecks.push({ checkId, checkStatus: status });
|
|
18854
|
+
i = inline ? i : i + 1;
|
|
18855
|
+
continue;
|
|
18856
|
+
}
|
|
18833
18857
|
if (NOTE_KEYS.has(key)) {
|
|
18834
18858
|
const inlineValue = inline ? token.slice(eq + 1) : void 0;
|
|
18835
18859
|
if (inlineValue !== void 0) {
|
|
@@ -18857,7 +18881,7 @@ function parseTaskEvidenceFlags(tokens) {
|
|
|
18857
18881
|
}
|
|
18858
18882
|
positional.push(token);
|
|
18859
18883
|
}
|
|
18860
|
-
return { attachment, note, positional, warnings };
|
|
18884
|
+
return { attachment, note, tickChecks, positional, warnings };
|
|
18861
18885
|
}
|
|
18862
18886
|
|
|
18863
18887
|
// src/slash-commands/mailbox.ts
|
|
@@ -19385,7 +19409,7 @@ function buildMailboxDemoCommand(opts) {
|
|
|
19385
19409
|
|
|
19386
19410
|
// src/slash-commands/mailbox-serve.ts
|
|
19387
19411
|
import { spawn as spawn6 } from "node:child_process";
|
|
19388
|
-
import * as
|
|
19412
|
+
import * as fs12 from "node:fs/promises";
|
|
19389
19413
|
import * as os2 from "node:os";
|
|
19390
19414
|
import * as path23 from "node:path";
|
|
19391
19415
|
import { resolveProjectDir as resolveProjectDir5 } from "@wrongstack/core/coordination";
|
|
@@ -19460,7 +19484,7 @@ function buildMailboxServeCommand(opts) {
|
|
|
19460
19484
|
});
|
|
19461
19485
|
child.unref();
|
|
19462
19486
|
try {
|
|
19463
|
-
await
|
|
19487
|
+
await fs12.writeFile(pidFile, String(child.pid ?? ""), { mode: 384 });
|
|
19464
19488
|
} catch {
|
|
19465
19489
|
}
|
|
19466
19490
|
const head = [];
|
|
@@ -21713,7 +21737,7 @@ ${targetMode.description}`
|
|
|
21713
21737
|
}
|
|
21714
21738
|
|
|
21715
21739
|
// src/slash-commands/modelcaps.ts
|
|
21716
|
-
import * as
|
|
21740
|
+
import * as fs13 from "node:fs/promises";
|
|
21717
21741
|
import { hasProviderCredential } from "@wrongstack/core/models";
|
|
21718
21742
|
import { color as color36 } from "@wrongstack/core/utils";
|
|
21719
21743
|
function fmtTokens(n) {
|
|
@@ -21786,7 +21810,7 @@ function buildModelCapsCommand(opts) {
|
|
|
21786
21810
|
}
|
|
21787
21811
|
let providers;
|
|
21788
21812
|
try {
|
|
21789
|
-
const raw = await
|
|
21813
|
+
const raw = await fs13.readFile(cachePath, "utf8");
|
|
21790
21814
|
const parsed = JSON.parse(raw);
|
|
21791
21815
|
const payload = parsed.payload ?? parsed;
|
|
21792
21816
|
providers = Object.entries(payload).map(([id, p]) => ({
|
|
@@ -21863,7 +21887,7 @@ function buildModelCapsCommand(opts) {
|
|
|
21863
21887
|
}
|
|
21864
21888
|
|
|
21865
21889
|
// src/slash-commands/models.ts
|
|
21866
|
-
import * as
|
|
21890
|
+
import * as fs14 from "node:fs/promises";
|
|
21867
21891
|
import { decryptConfigSecrets as decryptConfigSecrets3, encryptConfigSecrets as encryptConfigSecrets3, noOpVault as noOpVault4 } from "@wrongstack/core/security";
|
|
21868
21892
|
import {
|
|
21869
21893
|
ConfigError as ConfigError4,
|
|
@@ -21875,7 +21899,7 @@ async function patchProfileConfig(mutate, profileConfigPath) {
|
|
|
21875
21899
|
let raw = "{}";
|
|
21876
21900
|
let fileExists2 = true;
|
|
21877
21901
|
try {
|
|
21878
|
-
raw = await
|
|
21902
|
+
raw = await fs14.readFile(targetPath, "utf8");
|
|
21879
21903
|
} catch (err) {
|
|
21880
21904
|
if (err.code !== "ENOENT") throw err;
|
|
21881
21905
|
fileExists2 = false;
|
|
@@ -24771,7 +24795,7 @@ async function killSession(sessionId, confirm) {
|
|
|
24771
24795
|
}
|
|
24772
24796
|
|
|
24773
24797
|
// src/slash-commands/setmodel.ts
|
|
24774
|
-
import * as
|
|
24798
|
+
import * as fs15 from "node:fs/promises";
|
|
24775
24799
|
import { fallbackProfileChain, parseModelRef as parseModelRef3 } from "@wrongstack/core/agent";
|
|
24776
24800
|
import { AGENT_CATALOG as AGENT_CATALOG2, AGENTS_BY_PHASE as AGENTS_BY_PHASE3 } from "@wrongstack/core/agent-catalog";
|
|
24777
24801
|
import {
|
|
@@ -24883,7 +24907,7 @@ async function patchProfileConfig2(mutate, profileConfigPath) {
|
|
|
24883
24907
|
let raw = "{}";
|
|
24884
24908
|
let fileExists2 = true;
|
|
24885
24909
|
try {
|
|
24886
|
-
raw = await
|
|
24910
|
+
raw = await fs15.readFile(targetPath, "utf8");
|
|
24887
24911
|
} catch (err) {
|
|
24888
24912
|
if (err.code !== "ENOENT") throw err;
|
|
24889
24913
|
fileExists2 = false;
|
|
@@ -25507,7 +25531,7 @@ function parseSuggestions(raw) {
|
|
|
25507
25531
|
if (/^none\b/i.test(trimmed) || /no (?:pending actions|further steps)/i.test(trimmed)) {
|
|
25508
25532
|
return [];
|
|
25509
25533
|
}
|
|
25510
|
-
const { texts } = parseNextSteps(raw, false
|
|
25534
|
+
const { texts } = parseNextSteps(raw, false);
|
|
25511
25535
|
if (texts.length > 0) return texts;
|
|
25512
25536
|
return raw.split("\n").map((l) => l.trim()).filter((l) => l.length > 10 && !l.startsWith("#") && !l.startsWith("```")).slice(0, 5);
|
|
25513
25537
|
}
|
|
@@ -25646,24 +25670,78 @@ function buildWebuiCommand() {
|
|
|
25646
25670
|
}
|
|
25647
25671
|
|
|
25648
25672
|
// src/slash-commands/theme.ts
|
|
25673
|
+
import { THEME_PRESET_IDS } from "@wrongstack/core/types";
|
|
25649
25674
|
import { color as color46, writeOut as writeOut3 } from "@wrongstack/core/utils";
|
|
25650
|
-
var
|
|
25651
|
-
|
|
25652
|
-
|
|
25653
|
-
|
|
25654
|
-
|
|
25655
|
-
|
|
25656
|
-
|
|
25657
|
-
|
|
25658
|
-
|
|
25659
|
-
|
|
25660
|
-
|
|
25661
|
-
|
|
25662
|
-
|
|
25663
|
-
|
|
25664
|
-
|
|
25665
|
-
|
|
25666
|
-
|
|
25675
|
+
var THEME_META = {
|
|
25676
|
+
catppuccin: { name: "Catppuccin Mocha", desc: "Soft pastel dark theme (Default)" },
|
|
25677
|
+
"tokyo-night": { name: "Tokyo Night", desc: "Deep violet, neon orange & cyan" },
|
|
25678
|
+
nord: { name: "Nord", desc: "Cool arctic blue & slate pastels" },
|
|
25679
|
+
cyberpunk: { name: "Cyberpunk Neon", desc: "High-contrast magenta, cyan & yellow" },
|
|
25680
|
+
dracula: { name: "Dracula", desc: "Vibrant purple, pink & green" },
|
|
25681
|
+
"gruvbox-dark": { name: "Gruvbox Dark", desc: "Warm earthy retro \u2014 orange, olive & aqua" },
|
|
25682
|
+
"solarized-dark": { name: "Solarized Dark", desc: "Base16 classic \u2014 teal & ochre precision" },
|
|
25683
|
+
"one-dark": { name: "One Dark", desc: "Atom's iconic palette \u2014 blue-led, warm accents" },
|
|
25684
|
+
monokai: { name: "Monokai", desc: "Sublime classic \u2014 vivid magenta, cyan & lime" },
|
|
25685
|
+
"rose-pine": { name: "Ros\xE9 Pine", desc: "Aesthetic pine & foam \u2014 soft evening pastels" },
|
|
25686
|
+
kanagawa: { name: "Kanagawa", desc: "Hokusai-inspired waves \u2014 sumi ink on washi" },
|
|
25687
|
+
"ayu-dark": { name: "Ayu Dark", desc: "Simple pleasant dark \u2014 warm orange + cool blue" },
|
|
25688
|
+
everforest: { name: "Everforest", desc: "Green-based comfort \u2014 forest greens & warm tans" },
|
|
25689
|
+
"night-owl": { name: "Night Owl", desc: "Sarah Drasner's night \u2014 deep navy + bold accents" },
|
|
25690
|
+
synthwave: { name: "Synthwave '84", desc: "Hot pink + neon cyan on deep purple" },
|
|
25691
|
+
"github-dark": { name: "GitHub Dark", desc: "GitHub's default dark \u2014 crisp blue on near-black" },
|
|
25692
|
+
"material-ocean": {
|
|
25693
|
+
name: "Material Ocean",
|
|
25694
|
+
desc: "Deepest Material variant \u2014 ink blue with pastel accents"
|
|
25695
|
+
},
|
|
25696
|
+
nightfox: { name: "Nightfox", desc: "Balanced slate blue with muted sage and rose" },
|
|
25697
|
+
oxocarbon: {
|
|
25698
|
+
name: "Oxocarbon",
|
|
25699
|
+
desc: "IBM Carbon-derived \u2014 neutral greys, electric blue & pink"
|
|
25700
|
+
},
|
|
25701
|
+
"catppuccin-macchiato": {
|
|
25702
|
+
name: "Catppuccin Macchiato",
|
|
25703
|
+
desc: "Warmer, one shade lighter than Mocha"
|
|
25704
|
+
},
|
|
25705
|
+
"catppuccin-frappe": {
|
|
25706
|
+
name: "Catppuccin Frapp\xE9",
|
|
25707
|
+
desc: "The lightest Catppuccin dark \u2014 gentle midday contrast"
|
|
25708
|
+
},
|
|
25709
|
+
"gruvbox-material": {
|
|
25710
|
+
name: "Gruvbox Material",
|
|
25711
|
+
desc: "Softened Gruvbox \u2014 same warmth, lower eye strain"
|
|
25712
|
+
},
|
|
25713
|
+
"tokyo-night-storm": {
|
|
25714
|
+
name: "Tokyo Night Storm",
|
|
25715
|
+
desc: "Tokyo Night on a lifted blue-grey base"
|
|
25716
|
+
},
|
|
25717
|
+
"rose-pine-moon": {
|
|
25718
|
+
name: "Ros\xE9 Pine Moon",
|
|
25719
|
+
desc: "Ros\xE9 Pine at dusk \u2014 deeper base, same soft accents"
|
|
25720
|
+
},
|
|
25721
|
+
zenburn: { name: "Zenburn", desc: "The classic low-contrast grey \u2014 desaturated and calm" },
|
|
25722
|
+
palenight: { name: "Palenight", desc: "Material Palenight \u2014 indigo base, candy accents" },
|
|
25723
|
+
horizon: { name: "Horizon", desc: "Warm coral and mint on charcoal \u2014 sunset gradient" },
|
|
25724
|
+
sonokai: { name: "Sonokai", desc: "Monokai Pro descendant \u2014 punchy on warm graphite" },
|
|
25725
|
+
"edge-dark": { name: "Edge Dark", desc: "Clean, evenly-weighted palette on desaturated navy" },
|
|
25726
|
+
moonfly: { name: "Moonfly", desc: "Near-black base with high-chroma accents \u2014 max contrast" },
|
|
25727
|
+
melange: { name: "Melange", desc: "Warm sepia and clay \u2014 the least blue dark theme here" },
|
|
25728
|
+
poimandres: { name: "Poimandres", desc: "Teal-forward, low-saturation \u2014 mint on deep indigo" },
|
|
25729
|
+
"vitesse-dark": {
|
|
25730
|
+
name: "Vitesse Dark",
|
|
25731
|
+
desc: "Anthony Fu's minimal palette \u2014 muted, print-like"
|
|
25732
|
+
},
|
|
25733
|
+
aura: { name: "Aura Dark", desc: "Vivid purple and spring green on near-black violet" },
|
|
25734
|
+
"dark-plus": { name: "VS Code Dark+", desc: "VS Code's default \u2014 familiar blue/orange/teal" }
|
|
25735
|
+
};
|
|
25736
|
+
var THEME_OPTIONS = THEME_PRESET_IDS.map((id) => ({ id, ...THEME_META[id] }));
|
|
25737
|
+
function presetHelpLines(perLine = 4) {
|
|
25738
|
+
const lines = [];
|
|
25739
|
+
for (let i = 0; i < THEME_PRESET_IDS.length; i += perLine) {
|
|
25740
|
+
const chunk = THEME_PRESET_IDS.slice(i, i + perLine).join(", ");
|
|
25741
|
+
lines.push(` ${chunk}${i + perLine < THEME_PRESET_IDS.length ? "," : ""}`);
|
|
25742
|
+
}
|
|
25743
|
+
return lines;
|
|
25744
|
+
}
|
|
25667
25745
|
async function runThemePicker(reader, activeId) {
|
|
25668
25746
|
let cursor = THEME_OPTIONS.findIndex((p) => p.id === activeId);
|
|
25669
25747
|
if (cursor < 0) cursor = 0;
|
|
@@ -25678,7 +25756,7 @@ ${color46.bold(color46.amber("WrongStack") + color46.dim(" \u2014 TUI Theme Sele
|
|
|
25678
25756
|
const mark = p.id === activeId ? color46.green(" [active]") : "";
|
|
25679
25757
|
const prefix = i === currentCursor ? color46.bold("\u276F ") : " ";
|
|
25680
25758
|
const name = i === currentCursor ? color46.bold(p.name) : p.name;
|
|
25681
|
-
lines.push(` ${prefix}${name.padEnd(
|
|
25759
|
+
lines.push(` ${prefix}${name.padEnd(21)} ${color46.dim(p.desc)}${mark}`);
|
|
25682
25760
|
}
|
|
25683
25761
|
lines.push("");
|
|
25684
25762
|
return lines.join("\n");
|
|
@@ -25708,16 +25786,14 @@ function buildThemeCommand(opts) {
|
|
|
25708
25786
|
name: "theme",
|
|
25709
25787
|
category: "Config",
|
|
25710
25788
|
description: "Switch or select the TUI color theme preset interactively",
|
|
25711
|
-
argsHint:
|
|
25789
|
+
argsHint: `[<preset>] (${THEME_PRESET_IDS.length} available \u2014 run /theme to pick)`,
|
|
25712
25790
|
help: [
|
|
25713
25791
|
"Usage:",
|
|
25714
25792
|
" /theme Interactive menu selection or view available theme presets",
|
|
25715
25793
|
" /theme <preset> Switch directly to a theme preset",
|
|
25716
25794
|
"",
|
|
25717
|
-
|
|
25718
|
-
|
|
25719
|
-
" gruvbox-dark, solarized-dark, one-dark, monokai, rose-pine,",
|
|
25720
|
-
" kanagawa, ayu-dark, everforest, night-owl, synthwave"
|
|
25795
|
+
`Available presets (${THEME_PRESET_IDS.length}):`,
|
|
25796
|
+
...presetHelpLines()
|
|
25721
25797
|
].join("\n"),
|
|
25722
25798
|
async run(args) {
|
|
25723
25799
|
const validPresets = THEME_OPTIONS.map((t) => t.id);
|
|
@@ -25747,7 +25823,7 @@ function buildThemeCommand(opts) {
|
|
|
25747
25823
|
];
|
|
25748
25824
|
for (const t of THEME_OPTIONS) {
|
|
25749
25825
|
const mark = t.id === activePreset ? color46.green(" [active]") : "";
|
|
25750
|
-
lines.push(` \u2022 ${color46.bold(t.id.padEnd(
|
|
25826
|
+
lines.push(` \u2022 ${color46.bold(t.id.padEnd(21))} ${t.desc}${mark}`);
|
|
25751
25827
|
}
|
|
25752
25828
|
lines.push("");
|
|
25753
25829
|
lines.push(color46.dim("Usage: /theme <preset>"));
|
|
@@ -26244,7 +26320,7 @@ function buildMouseCommand(_opts) {
|
|
|
26244
26320
|
|
|
26245
26321
|
// src/slash-commands/project.ts
|
|
26246
26322
|
import { spawn as spawn7 } from "node:child_process";
|
|
26247
|
-
import * as
|
|
26323
|
+
import * as fs16 from "node:fs/promises";
|
|
26248
26324
|
import { createRequire } from "node:module";
|
|
26249
26325
|
import * as path26 from "node:path";
|
|
26250
26326
|
import {
|
|
@@ -26458,11 +26534,11 @@ async function listProjectsCommand(opts, ctx) {
|
|
|
26458
26534
|
async function addProjectCommand(opts, ctx, targetPath, displayName) {
|
|
26459
26535
|
const resolved = path26.resolve(ctx?.projectRoot ?? ctx?.cwd ?? process.cwd(), targetPath);
|
|
26460
26536
|
try {
|
|
26461
|
-
await
|
|
26537
|
+
await fs16.access(resolved);
|
|
26462
26538
|
} catch {
|
|
26463
26539
|
return { message: color48.red(`Directory not found: ${resolved}`) };
|
|
26464
26540
|
}
|
|
26465
|
-
const stat5 = await
|
|
26541
|
+
const stat5 = await fs16.stat(resolved);
|
|
26466
26542
|
if (!stat5.isDirectory()) {
|
|
26467
26543
|
return { message: color48.red(`Not a directory: ${resolved}`) };
|
|
26468
26544
|
}
|
|
@@ -26528,11 +26604,11 @@ async function removeProjectCommand(opts, _ctx, slugOrName) {
|
|
|
26528
26604
|
async function switchProjectCommand(opts, ctx, target, displayName) {
|
|
26529
26605
|
const resolved = path26.resolve(ctx?.projectRoot ?? ctx?.cwd ?? process.cwd(), target);
|
|
26530
26606
|
try {
|
|
26531
|
-
await
|
|
26607
|
+
await fs16.access(resolved);
|
|
26532
26608
|
} catch {
|
|
26533
26609
|
return { message: color48.red(`Directory not found: ${resolved}`) };
|
|
26534
26610
|
}
|
|
26535
|
-
const stat5 = await
|
|
26611
|
+
const stat5 = await fs16.stat(resolved);
|
|
26536
26612
|
if (!stat5.isDirectory()) {
|
|
26537
26613
|
return { message: color48.red(`Not a directory: ${resolved}`) };
|
|
26538
26614
|
}
|
|
@@ -26542,7 +26618,7 @@ async function switchProjectCommand(opts, ctx, target, displayName) {
|
|
|
26542
26618
|
const pkgPath = req.resolve("@wrongstack/cli/package.json");
|
|
26543
26619
|
const pkgDir = path26.dirname(pkgPath);
|
|
26544
26620
|
cliPath = path26.join(pkgDir, "dist", "index.js");
|
|
26545
|
-
await
|
|
26621
|
+
await fs16.access(cliPath);
|
|
26546
26622
|
} catch {
|
|
26547
26623
|
cliPath = process.argv[1] ?? "";
|
|
26548
26624
|
if (!cliPath) {
|
|
@@ -26687,7 +26763,7 @@ async function spawnInProject(opts, _ctx, root, projectName) {
|
|
|
26687
26763
|
const pkgPath = req.resolve("@wrongstack/cli/package.json");
|
|
26688
26764
|
const pkgDir = path26.dirname(pkgPath);
|
|
26689
26765
|
cliPath = path26.join(pkgDir, "dist", "index.js");
|
|
26690
|
-
await
|
|
26766
|
+
await fs16.access(cliPath);
|
|
26691
26767
|
} catch {
|
|
26692
26768
|
cliPath = process.argv[1] ?? "";
|
|
26693
26769
|
if (!cliPath) {
|
|
@@ -26742,7 +26818,7 @@ async function handleNewSession(_opts, _ctx) {
|
|
|
26742
26818
|
const pkgPath = req.resolve("@wrongstack/cli/package.json");
|
|
26743
26819
|
const pkgDir = path26.dirname(pkgPath);
|
|
26744
26820
|
cliPath = path26.join(pkgDir, "dist", "index.js");
|
|
26745
|
-
await
|
|
26821
|
+
await fs16.access(cliPath);
|
|
26746
26822
|
} catch {
|
|
26747
26823
|
cliPath = process.argv[1] ?? "";
|
|
26748
26824
|
if (!cliPath) {
|
|
@@ -26905,7 +26981,9 @@ function buildReviewCommand(opts) {
|
|
|
26905
26981
|
maxFiles: limit,
|
|
26906
26982
|
autoFix: "off",
|
|
26907
26983
|
cascadeOn: "off",
|
|
26908
|
-
maxCascadeDepth: 0
|
|
26984
|
+
maxCascadeDepth: 0,
|
|
26985
|
+
fallbackModels: [],
|
|
26986
|
+
fallbackProfile: void 0
|
|
26909
26987
|
},
|
|
26910
26988
|
cwd,
|
|
26911
26989
|
files: filesWithContent
|
|
@@ -28948,21 +29026,21 @@ ${formatTaskProgress(file.tasks)}`;
|
|
|
28948
29026
|
}
|
|
28949
29027
|
|
|
28950
29028
|
// src/slash-commands/techstack.ts
|
|
28951
|
-
import * as
|
|
29029
|
+
import * as fs17 from "node:fs/promises";
|
|
28952
29030
|
import * as path28 from "node:path";
|
|
28953
29031
|
import { color as color52, toErrorMessage as toErrorMessage26 } from "@wrongstack/core/utils";
|
|
28954
29032
|
async function discoverPackageFiles(projectRoot) {
|
|
28955
29033
|
const files = [];
|
|
28956
29034
|
const rootPkg = path28.join(projectRoot, "package.json");
|
|
28957
29035
|
try {
|
|
28958
|
-
await
|
|
29036
|
+
await fs17.access(rootPkg);
|
|
28959
29037
|
files.push(rootPkg);
|
|
28960
29038
|
} catch {
|
|
28961
29039
|
}
|
|
28962
29040
|
const workspaceFile = path28.join(projectRoot, "pnpm-workspace.yaml");
|
|
28963
29041
|
try {
|
|
28964
|
-
await
|
|
28965
|
-
const content = await
|
|
29042
|
+
await fs17.access(workspaceFile);
|
|
29043
|
+
const content = await fs17.readFile(workspaceFile, "utf8");
|
|
28966
29044
|
const globMatch = /packages?:\s*\[([^\]]+)\]/s.exec(content);
|
|
28967
29045
|
const rawGlobs = globMatch?.[1];
|
|
28968
29046
|
if (!rawGlobs) return files;
|
|
@@ -28971,12 +29049,12 @@ async function discoverPackageFiles(projectRoot) {
|
|
|
28971
29049
|
const dirPrefix = g.replace(/\/?\*$/, "").replace(/\/\*$/, "");
|
|
28972
29050
|
const dir = path28.join(projectRoot, dirPrefix);
|
|
28973
29051
|
try {
|
|
28974
|
-
const entries = await
|
|
29052
|
+
const entries = await fs17.readdir(dir, { withFileTypes: true });
|
|
28975
29053
|
for (const e of entries) {
|
|
28976
29054
|
if (!e.isDirectory()) continue;
|
|
28977
29055
|
const subPkg = path28.join(dir, e.name, "package.json");
|
|
28978
29056
|
try {
|
|
28979
|
-
await
|
|
29057
|
+
await fs17.access(subPkg);
|
|
28980
29058
|
files.push(subPkg);
|
|
28981
29059
|
} catch {
|
|
28982
29060
|
}
|
|
@@ -30288,7 +30366,7 @@ ${lines.join("\n")}${extra}
|
|
|
30288
30366
|
}
|
|
30289
30367
|
|
|
30290
30368
|
// src/slash-commands/tuneup.ts
|
|
30291
|
-
import * as
|
|
30369
|
+
import * as fs18 from "node:fs/promises";
|
|
30292
30370
|
import * as os3 from "node:os";
|
|
30293
30371
|
import * as path29 from "node:path";
|
|
30294
30372
|
import { atomicWrite as atomicWrite10, color as color57 } from "@wrongstack/core/utils";
|
|
@@ -30898,7 +30976,7 @@ async function gatherMemoryFiles(opts) {
|
|
|
30898
30976
|
const out = [];
|
|
30899
30977
|
for (const c of candidates) {
|
|
30900
30978
|
try {
|
|
30901
|
-
const content = await
|
|
30979
|
+
const content = await fs18.readFile(c.file, "utf8");
|
|
30902
30980
|
out.push({ label: c.label, path: c.file, content, committed: c.committed });
|
|
30903
30981
|
} catch {
|
|
30904
30982
|
}
|
|
@@ -30916,7 +30994,7 @@ async function gatherTrust(opts) {
|
|
|
30916
30994
|
const file = opts.paths?.projectTrust;
|
|
30917
30995
|
if (!file) return void 0;
|
|
30918
30996
|
try {
|
|
30919
|
-
const raw = await
|
|
30997
|
+
const raw = await fs18.readFile(file, "utf8");
|
|
30920
30998
|
const parsed = JSON.parse(raw);
|
|
30921
30999
|
if (parsed && typeof parsed === "object") return parsed;
|
|
30922
31000
|
} catch {
|
|
@@ -30927,7 +31005,7 @@ async function gatherConfigIssues(opts) {
|
|
|
30927
31005
|
if (!opts.paths) return 0;
|
|
30928
31006
|
const file = activeProfileConfigPath(opts.paths, opts.configStore.get());
|
|
30929
31007
|
try {
|
|
30930
|
-
const raw = await
|
|
31008
|
+
const raw = await fs18.readFile(file, "utf8");
|
|
30931
31009
|
const parsed = JSON.parse(raw);
|
|
30932
31010
|
return diagnoseConfig(parsed).findings.length;
|
|
30933
31011
|
} catch {
|
|
@@ -30945,14 +31023,14 @@ async function gatherSessionBytes(opts) {
|
|
|
30945
31023
|
}
|
|
30946
31024
|
async function dirSize(dir) {
|
|
30947
31025
|
let total = 0;
|
|
30948
|
-
const entries = await
|
|
31026
|
+
const entries = await fs18.readdir(dir, { withFileTypes: true });
|
|
30949
31027
|
for (const e of entries) {
|
|
30950
31028
|
const full = path29.join(dir, e.name);
|
|
30951
31029
|
if (e.isDirectory()) {
|
|
30952
31030
|
total += await dirSize(full);
|
|
30953
31031
|
} else if (e.isFile()) {
|
|
30954
31032
|
try {
|
|
30955
|
-
total += (await
|
|
31033
|
+
total += (await fs18.stat(full)).size;
|
|
30956
31034
|
} catch {
|
|
30957
31035
|
}
|
|
30958
31036
|
}
|
|
@@ -30965,7 +31043,7 @@ async function applyActions(actions, opts) {
|
|
|
30965
31043
|
const file = activeProfileConfigPath(opts.paths, opts.configStore.get());
|
|
30966
31044
|
let raw = "{}";
|
|
30967
31045
|
try {
|
|
30968
|
-
raw = await
|
|
31046
|
+
raw = await fs18.readFile(file, "utf8");
|
|
30969
31047
|
} catch {
|
|
30970
31048
|
}
|
|
30971
31049
|
let parsed;
|
|
@@ -31121,7 +31199,7 @@ function summaryLine(findings, fixable, handoffs, power) {
|
|
|
31121
31199
|
}
|
|
31122
31200
|
|
|
31123
31201
|
// src/slash-commands/working-dir.ts
|
|
31124
|
-
import * as
|
|
31202
|
+
import * as fs19 from "node:fs/promises";
|
|
31125
31203
|
import * as path30 from "node:path";
|
|
31126
31204
|
import { color as color58, toErrorMessage as toErrorMessage29 } from "@wrongstack/core/utils";
|
|
31127
31205
|
function buildWorkingDirCommand(_opts) {
|
|
@@ -31168,7 +31246,7 @@ function buildWorkingDirCommand(_opts) {
|
|
|
31168
31246
|
};
|
|
31169
31247
|
}
|
|
31170
31248
|
try {
|
|
31171
|
-
const stat5 = await
|
|
31249
|
+
const stat5 = await fs19.stat(resolved);
|
|
31172
31250
|
if (!stat5.isDirectory()) {
|
|
31173
31251
|
return { message: color58.red(`Not a directory: ${resolved}`) };
|
|
31174
31252
|
}
|
|
@@ -31523,12 +31601,14 @@ async function runInteractive(cliCtx) {
|
|
|
31523
31601
|
});
|
|
31524
31602
|
const stdinInteractive = process.stdin.isTTY;
|
|
31525
31603
|
const hookRunnerRef = { current: null };
|
|
31604
|
+
const switchProviderAndModelRef = { current: null };
|
|
31526
31605
|
registerCliManagementTools({
|
|
31527
31606
|
toolRegistry,
|
|
31528
31607
|
configStore,
|
|
31529
31608
|
profileConfigPath,
|
|
31530
31609
|
stdinInteractive,
|
|
31531
|
-
getHookRunner: () => hookRunnerRef.current
|
|
31610
|
+
getHookRunner: () => hookRunnerRef.current,
|
|
31611
|
+
getSwitchProviderAndModel: () => switchProviderAndModelRef.current
|
|
31532
31612
|
});
|
|
31533
31613
|
const { metricsSink, healthRegistry, metricsStatus } = (() => {
|
|
31534
31614
|
const ms = setupMetrics({
|
|
@@ -31773,6 +31853,7 @@ async function runInteractive(cliCtx) {
|
|
|
31773
31853
|
buildProviderForIdRuntime: buildProviderForId,
|
|
31774
31854
|
statusTracker
|
|
31775
31855
|
});
|
|
31856
|
+
switchProviderAndModelRef.current = switchProviderAndModel;
|
|
31776
31857
|
await adoptResumedProvider({
|
|
31777
31858
|
resumedProvider: sessResult.resumedProvider,
|
|
31778
31859
|
resumedModel: sessResult.resumedModel,
|
|
@@ -32161,7 +32242,7 @@ async function runInteractive(cliCtx) {
|
|
|
32161
32242
|
onEvent: evOn
|
|
32162
32243
|
});
|
|
32163
32244
|
const savedProviderCfg = config.providers?.[config.provider];
|
|
32164
|
-
const { execute } = await import("./execution-
|
|
32245
|
+
const { execute } = await import("./execution-TTE7R5UY.js");
|
|
32165
32246
|
const stopHeapWatchdog = startSharedHeapWatchdog({
|
|
32166
32247
|
collectStats: () => {
|
|
32167
32248
|
const hqQueue = hqPublisherRef.current?.getQueueStats();
|
|
@@ -32399,4 +32480,4 @@ export {
|
|
|
32399
32480
|
CLI_VERSION,
|
|
32400
32481
|
runInteractive
|
|
32401
32482
|
};
|
|
32402
|
-
//# sourceMappingURL=cli-main-
|
|
32483
|
+
//# sourceMappingURL=cli-main-DHNFGP3Z.js.map
|