@wrongstack/cli 0.308.7 → 0.309.1
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-5ZLGFHWP.js → acp-7NWCC2GO.js} +3 -3
- package/dist/{auth-WOKC2RVG.js → auth-GZ2FK5KR.js} +3 -3
- package/dist/auth-menu/loopback-server.d.ts +0 -12
- package/dist/{chunk-JQURRYU4.js → chunk-UINEP3E7.js} +2 -2
- package/dist/{chunk-DOJLAULS.js → chunk-WOTGMHAH.js} +36 -26
- package/dist/{chunk-SSSJQVUY.js → chunk-XQ6FI2K6.js} +14 -1
- package/dist/{chunk-7JOMY3HO.js → chunk-ZRZ54GVL.js} +2 -2
- package/dist/{cli-main-L3T4KJKU.js → cli-main-XGDOIPN5.js} +952 -618
- package/dist/diff-renderer.d.ts +17 -0
- package/dist/{execution-6HIKTAUB.js → execution-TYUXABWI.js} +51 -2
- package/dist/index.js +6 -6
- package/dist/{providers-models-4FAKM2WO.js → providers-models-D23WUD74.js} +2 -2
- package/dist/slash-commands/dev.d.ts +50 -0
- package/dist/slash-commands/effort.d.ts +33 -0
- package/dist/wiring/cli-execute-builder.d.ts +110 -85
- package/dist/wiring/cli-slash-commands-setup.d.ts +102 -72
- package/package.json +25 -25
|
@@ -50,7 +50,7 @@ import {
|
|
|
50
50
|
detectProjectFacts,
|
|
51
51
|
makeConfirmAwaiter,
|
|
52
52
|
renderAgentsTemplate
|
|
53
|
-
} from "./chunk-
|
|
53
|
+
} from "./chunk-WOTGMHAH.js";
|
|
54
54
|
import "./chunk-QD544J2B.js";
|
|
55
55
|
import {
|
|
56
56
|
fmtTaskResultLine,
|
|
@@ -71,7 +71,7 @@ import {
|
|
|
71
71
|
loadCachedAcpRegistry,
|
|
72
72
|
refreshAcpRegistry,
|
|
73
73
|
setupProvider
|
|
74
|
-
} from "./chunk-
|
|
74
|
+
} from "./chunk-UINEP3E7.js";
|
|
75
75
|
import {
|
|
76
76
|
addCustomProvider,
|
|
77
77
|
addKeyForCatalogProvider,
|
|
@@ -81,7 +81,7 @@ import {
|
|
|
81
81
|
runClaudeOAuthLogin,
|
|
82
82
|
runCopilotOAuthLogin,
|
|
83
83
|
validateFamily
|
|
84
|
-
} from "./chunk-
|
|
84
|
+
} from "./chunk-ZRZ54GVL.js";
|
|
85
85
|
import {
|
|
86
86
|
LOCAL_LLM_PRESETS,
|
|
87
87
|
parseSpawnFlags
|
|
@@ -98,7 +98,7 @@ import {
|
|
|
98
98
|
} from "./chunk-YMXXOOFN.js";
|
|
99
99
|
import {
|
|
100
100
|
runCodexOAuthLogin
|
|
101
|
-
} from "./chunk-
|
|
101
|
+
} from "./chunk-XQ6FI2K6.js";
|
|
102
102
|
import {
|
|
103
103
|
activeLabel,
|
|
104
104
|
loadConfigProviders,
|
|
@@ -1877,7 +1877,10 @@ function resolveSubagentCapabilities(subCfg, toolsForAllow) {
|
|
|
1877
1877
|
]).granted;
|
|
1878
1878
|
}
|
|
1879
1879
|
const allow = subCfg.tools;
|
|
1880
|
-
if (
|
|
1880
|
+
if (allow && allow.length === 0) {
|
|
1881
|
+
return clampSubagentCapabilities([ToolCapabilities.COORDINATION_RESULT_SUBMIT]).granted;
|
|
1882
|
+
}
|
|
1883
|
+
if (!allow) return WIDE_SUBAGENT_CAPABILITIES;
|
|
1881
1884
|
const caps = new Set(WIDE_SUBAGENT_CAPABILITIES);
|
|
1882
1885
|
for (const tool of toolsForAllow([...allow])) {
|
|
1883
1886
|
for (const capability of tool.capabilities ?? []) caps.add(capability);
|
|
@@ -5644,7 +5647,7 @@ async function runCliExecution(params) {
|
|
|
5644
5647
|
governanceHandle,
|
|
5645
5648
|
setConfig
|
|
5646
5649
|
} = params;
|
|
5647
|
-
const { execute } = await import("./execution-
|
|
5650
|
+
const { execute } = await import("./execution-TYUXABWI.js");
|
|
5648
5651
|
return execute(
|
|
5649
5652
|
toExecuteDeps({
|
|
5650
5653
|
core: {
|
|
@@ -5780,7 +5783,11 @@ async function runCliExecution(params) {
|
|
|
5780
5783
|
setConfig,
|
|
5781
5784
|
profileConfigPath,
|
|
5782
5785
|
mcpRegistry,
|
|
5783
|
-
|
|
5786
|
+
// cli-main attaches toolRegistry onto the Context object dynamically
|
|
5787
|
+
// (core Context does not declare it). The previous `?? agent.ctx.tools`
|
|
5788
|
+
// fallback was a latent crash: ctx.tools is a Tool[], which cannot
|
|
5789
|
+
// satisfy the ToolRegistry the picker calls into.
|
|
5790
|
+
toolRegistry: params.context.toolRegistry,
|
|
5784
5791
|
configStore,
|
|
5785
5792
|
getPluginItems: getPluginPickerItems,
|
|
5786
5793
|
togglePlugin: togglePluginFromPicker,
|
|
@@ -11316,49 +11323,179 @@ ${menu}` };
|
|
|
11316
11323
|
}
|
|
11317
11324
|
|
|
11318
11325
|
// src/slash-commands/dev.ts
|
|
11319
|
-
import {
|
|
11320
|
-
import {
|
|
11326
|
+
import { spawn as spawn4 } from "node:child_process";
|
|
11327
|
+
import { StringDecoder } from "node:string_decoder";
|
|
11321
11328
|
import { color as color23 } from "@wrongstack/core/utils";
|
|
11322
11329
|
var DEFAULT_TIMEOUT_MS = 6e4;
|
|
11323
11330
|
var MAX_OUTPUT_LINES = 500;
|
|
11324
|
-
var
|
|
11325
|
-
|
|
11326
|
-
|
|
11327
|
-
|
|
11328
|
-
|
|
11329
|
-
|
|
11330
|
-
|
|
11331
|
-
|
|
11332
|
-
|
|
11333
|
-
|
|
11331
|
+
var MAX_STREAM_BYTES = 2 * 1024 * 1024;
|
|
11332
|
+
var EXIT_SPAWN_FAILED = 127;
|
|
11333
|
+
var EXIT_TIMEOUT = 124;
|
|
11334
|
+
var SIGNAL_NUMBERS = {
|
|
11335
|
+
SIGHUP: 1,
|
|
11336
|
+
SIGINT: 2,
|
|
11337
|
+
SIGQUIT: 3,
|
|
11338
|
+
SIGABRT: 6,
|
|
11339
|
+
SIGKILL: 9,
|
|
11340
|
+
SIGALRM: 14,
|
|
11341
|
+
SIGTERM: 15
|
|
11342
|
+
};
|
|
11343
|
+
function foreignSignalExitCode(signal) {
|
|
11344
|
+
const n = SIGNAL_NUMBERS[signal];
|
|
11345
|
+
return n === void 0 ? 125 : 128 + n;
|
|
11346
|
+
}
|
|
11347
|
+
function tokenizeCommand(command, platform = process.platform) {
|
|
11348
|
+
const isWin32 = platform === "win32";
|
|
11349
|
+
const args = [];
|
|
11350
|
+
let current = "";
|
|
11351
|
+
let tokenStarted = false;
|
|
11352
|
+
let quote = null;
|
|
11353
|
+
for (let i = 0; i < command.length; i++) {
|
|
11354
|
+
const char = command[i];
|
|
11355
|
+
if (quote) {
|
|
11356
|
+
if (!isWin32 && char === "\\" && quote === '"' && i + 1 < command.length) {
|
|
11357
|
+
const next = command[i + 1];
|
|
11358
|
+
if (next === "\n") {
|
|
11359
|
+
i++;
|
|
11360
|
+
continue;
|
|
11361
|
+
}
|
|
11362
|
+
if (next === '"' || next === "\\" || next === "$" || next === "`") {
|
|
11363
|
+
current += next;
|
|
11364
|
+
i++;
|
|
11365
|
+
continue;
|
|
11366
|
+
}
|
|
11367
|
+
}
|
|
11368
|
+
if (char === quote) quote = null;
|
|
11369
|
+
else current += char;
|
|
11370
|
+
continue;
|
|
11371
|
+
}
|
|
11372
|
+
if (char === '"' || char === "'") {
|
|
11373
|
+
quote = char;
|
|
11374
|
+
tokenStarted = true;
|
|
11375
|
+
continue;
|
|
11376
|
+
}
|
|
11377
|
+
if (!isWin32 && char === "\\" && i + 1 < command.length) {
|
|
11378
|
+
current += command[++i];
|
|
11379
|
+
tokenStarted = true;
|
|
11380
|
+
continue;
|
|
11381
|
+
}
|
|
11382
|
+
if (/\s/.test(char)) {
|
|
11383
|
+
if (tokenStarted) {
|
|
11384
|
+
args.push(current);
|
|
11385
|
+
current = "";
|
|
11386
|
+
tokenStarted = false;
|
|
11387
|
+
}
|
|
11388
|
+
continue;
|
|
11389
|
+
}
|
|
11390
|
+
current += char;
|
|
11391
|
+
tokenStarted = true;
|
|
11334
11392
|
}
|
|
11393
|
+
if (quote) throw new Error(`Unterminated quoted argument in command: ${command}`);
|
|
11394
|
+
if (tokenStarted) args.push(current);
|
|
11395
|
+
return args;
|
|
11396
|
+
}
|
|
11397
|
+
function spawnFailure(stderr) {
|
|
11398
|
+
return { stdout: "", stderr, exitCode: EXIT_SPAWN_FAILED, killed: false, spawnFailed: true };
|
|
11335
11399
|
}
|
|
11336
|
-
function runCommand(cmd, cwd, timeout) {
|
|
11400
|
+
function runCommand(cmd, cwd, timeout = DEFAULT_TIMEOUT_MS) {
|
|
11401
|
+
let program;
|
|
11402
|
+
let args;
|
|
11403
|
+
try {
|
|
11404
|
+
const tokens = tokenizeCommand(cmd);
|
|
11405
|
+
program = tokens[0] ?? "";
|
|
11406
|
+
args = tokens.slice(1);
|
|
11407
|
+
} catch (err) {
|
|
11408
|
+
return Promise.resolve(spawnFailure(err instanceof Error ? err.message : String(err)));
|
|
11409
|
+
}
|
|
11410
|
+
if (!program) return Promise.resolve(spawnFailure("Empty command."));
|
|
11411
|
+
let command;
|
|
11412
|
+
let spawnArgs;
|
|
11413
|
+
let windowsVerbatimArguments;
|
|
11414
|
+
if (process.platform === "win32") {
|
|
11415
|
+
try {
|
|
11416
|
+
const shim = buildWin32CmdShimInvocation(program, args);
|
|
11417
|
+
command = shim.command;
|
|
11418
|
+
spawnArgs = shim.args;
|
|
11419
|
+
windowsVerbatimArguments = shim.windowsVerbatimArguments;
|
|
11420
|
+
} catch (err) {
|
|
11421
|
+
return Promise.resolve(spawnFailure(err instanceof Error ? err.message : String(err)));
|
|
11422
|
+
}
|
|
11423
|
+
} else {
|
|
11424
|
+
command = program;
|
|
11425
|
+
spawnArgs = args;
|
|
11426
|
+
}
|
|
11337
11427
|
return new Promise((resolve8) => {
|
|
11338
|
-
|
|
11339
|
-
|
|
11340
|
-
|
|
11341
|
-
|
|
11342
|
-
|
|
11343
|
-
|
|
11344
|
-
|
|
11345
|
-
|
|
11346
|
-
|
|
11347
|
-
|
|
11428
|
+
let child;
|
|
11429
|
+
try {
|
|
11430
|
+
child = spawn4(command, spawnArgs, {
|
|
11431
|
+
cwd,
|
|
11432
|
+
timeout,
|
|
11433
|
+
windowsHide: true,
|
|
11434
|
+
...windowsVerbatimArguments ? { windowsVerbatimArguments } : {}
|
|
11435
|
+
});
|
|
11436
|
+
} catch (err) {
|
|
11437
|
+
resolve8(spawnFailure(err instanceof Error ? err.message : String(err)));
|
|
11438
|
+
return;
|
|
11439
|
+
}
|
|
11440
|
+
let stdout = "";
|
|
11441
|
+
let stderr = "";
|
|
11442
|
+
const stdoutDecoder = new StringDecoder("utf8");
|
|
11443
|
+
const stderrDecoder = new StringDecoder("utf8");
|
|
11444
|
+
const appendCapped = (acc, decoder, chunk) => acc.length >= MAX_STREAM_BYTES ? acc : acc + decoder.write(chunk).slice(0, MAX_STREAM_BYTES - acc.length);
|
|
11445
|
+
child.stdout?.on("data", (chunk) => {
|
|
11446
|
+
stdout = appendCapped(stdout, stdoutDecoder, chunk);
|
|
11447
|
+
});
|
|
11448
|
+
child.stderr?.on("data", (chunk) => {
|
|
11449
|
+
stderr = appendCapped(stderr, stderrDecoder, chunk);
|
|
11450
|
+
});
|
|
11451
|
+
child.stdout?.on("error", (err) => {
|
|
11452
|
+
stderr = appendCapped(
|
|
11453
|
+
stderr,
|
|
11454
|
+
stderrDecoder,
|
|
11455
|
+
Buffer.from(`
|
|
11456
|
+
[stdout stream error: ${err.message}]`)
|
|
11457
|
+
);
|
|
11458
|
+
});
|
|
11459
|
+
child.stderr?.on("error", () => {
|
|
11460
|
+
});
|
|
11461
|
+
let settled = false;
|
|
11462
|
+
const finish = (result) => {
|
|
11463
|
+
if (settled) return;
|
|
11464
|
+
settled = true;
|
|
11465
|
+
resolve8(result);
|
|
11348
11466
|
};
|
|
11349
|
-
|
|
11350
|
-
|
|
11467
|
+
child.on("error", (err) => {
|
|
11468
|
+
finish({
|
|
11469
|
+
stdout,
|
|
11470
|
+
stderr: err.message,
|
|
11471
|
+
exitCode: EXIT_SPAWN_FAILED,
|
|
11472
|
+
killed: false,
|
|
11473
|
+
spawnFailed: true
|
|
11474
|
+
});
|
|
11475
|
+
});
|
|
11476
|
+
child.on("close", (code, signal) => {
|
|
11477
|
+
const timedOut = child.killed && code !== 0;
|
|
11478
|
+
const diedBySignal = signal !== null && !timedOut;
|
|
11479
|
+
const exitCode = timedOut ? EXIT_TIMEOUT : code ?? (diedBySignal ? foreignSignalExitCode(signal ?? "") : EXIT_SPAWN_FAILED);
|
|
11480
|
+
finish({
|
|
11351
11481
|
stdout,
|
|
11352
11482
|
stderr,
|
|
11353
|
-
exitCode
|
|
11354
|
-
killed:
|
|
11483
|
+
exitCode,
|
|
11484
|
+
// Contract (DevCommandResult.killed): true when the process died
|
|
11485
|
+
// from a signal — timeout kill OR foreign. `diedBySignal` alone
|
|
11486
|
+
// excludes our own timeout kill and reported killed:false on every
|
|
11487
|
+
// TIMEOUT (chimera finding).
|
|
11488
|
+
killed: timedOut || diedBySignal,
|
|
11489
|
+
spawnFailed: code === null && signal === null,
|
|
11490
|
+
...signal !== null ? { signalName: signal } : {},
|
|
11491
|
+
...timedOut ? { timedOut: true } : {}
|
|
11355
11492
|
});
|
|
11356
11493
|
});
|
|
11357
11494
|
});
|
|
11358
11495
|
}
|
|
11359
11496
|
function formatOutput(cmd, result, elapsed) {
|
|
11360
11497
|
const lines = [];
|
|
11361
|
-
const exitLabel = result.
|
|
11498
|
+
const exitLabel = result.timedOut ? color23.red("TIMEOUT") : result.killed ? color23.red(`KILLED${result.signalName ? ` (${result.signalName})` : ""}`) : result.spawnFailed ? color23.red("SPAWN ERROR") : result.exitCode === 0 ? color23.green("OK") : color23.red(`EXIT ${result.exitCode}`);
|
|
11362
11499
|
lines.push(`${color23.cyan("$")} ${color23.bold(cmd)} ${exitLabel} ${color23.dim(`${elapsed}ms`)}`);
|
|
11363
11500
|
const combined = (result.stdout + result.stderr).trimEnd();
|
|
11364
11501
|
if (combined) {
|
|
@@ -11416,7 +11553,6 @@ Examples:
|
|
|
11416
11553
|
/dev git diff --stat`
|
|
11417
11554
|
};
|
|
11418
11555
|
}
|
|
11419
|
-
validateCommand(cmd);
|
|
11420
11556
|
const cwd = opts.cwd;
|
|
11421
11557
|
const startedAt = Date.now();
|
|
11422
11558
|
opts.renderer.write(color23.dim(`$ ${cmd}`));
|
|
@@ -17241,7 +17377,7 @@ function buildMailboxDemoCommand(opts) {
|
|
|
17241
17377
|
}
|
|
17242
17378
|
|
|
17243
17379
|
// src/slash-commands/mailbox-serve.ts
|
|
17244
|
-
import { spawn as
|
|
17380
|
+
import { spawn as spawn5 } from "node:child_process";
|
|
17245
17381
|
import * as fs10 from "node:fs/promises";
|
|
17246
17382
|
import * as os2 from "node:os";
|
|
17247
17383
|
import * as path14 from "node:path";
|
|
@@ -17304,7 +17440,7 @@ function buildMailboxServeCommand(opts) {
|
|
|
17304
17440
|
spawnArgs = ["mailbox", "serve", ...flags];
|
|
17305
17441
|
if (isWin) shim = buildWin32CmdShimInvocation(wstackCmd, spawnArgs);
|
|
17306
17442
|
}
|
|
17307
|
-
const child =
|
|
17443
|
+
const child = spawn5(shim?.command ?? wstackCmd, shim?.args ?? spawnArgs, {
|
|
17308
17444
|
cwd,
|
|
17309
17445
|
// POSIX-only: own process group so the bridge outlives the REPL.
|
|
17310
17446
|
// On win32 `detached` opens a visible console window (project
|
|
@@ -20021,7 +20157,7 @@ import * as fs12 from "node:fs/promises";
|
|
|
20021
20157
|
import { decryptConfigSecrets as decryptConfigSecrets3, encryptConfigSecrets as encryptConfigSecrets3, noOpVault as noOpVault4 } from "@wrongstack/core/security";
|
|
20022
20158
|
import {
|
|
20023
20159
|
ConfigError as ConfigError4,
|
|
20024
|
-
ToolValidationError as
|
|
20160
|
+
ToolValidationError as ToolValidationError3
|
|
20025
20161
|
} from "@wrongstack/core/types";
|
|
20026
20162
|
import { atomicWrite as atomicWrite6, color as color41, toErrorMessage as toErrorMessage18 } from "@wrongstack/core/utils";
|
|
20027
20163
|
async function patchProfileConfig(mutate, profileConfigPath) {
|
|
@@ -20077,7 +20213,7 @@ function fmtModel(id, def) {
|
|
|
20077
20213
|
function safeAt(arr, idx) {
|
|
20078
20214
|
const v = arr[idx];
|
|
20079
20215
|
if (v === void 0)
|
|
20080
|
-
throw new
|
|
20216
|
+
throw new ToolValidationError3({
|
|
20081
20217
|
message: `Missing value at position ${idx}`,
|
|
20082
20218
|
field: `argv[${idx}]`
|
|
20083
20219
|
});
|
|
@@ -22966,7 +23102,9 @@ import {
|
|
|
22966
23102
|
} from "@wrongstack/core/coordination";
|
|
22967
23103
|
import { decryptConfigSecrets as decryptConfigSecrets4, encryptConfigSecrets as encryptConfigSecrets4, noOpVault as noOpVault6 } from "@wrongstack/core/security";
|
|
22968
23104
|
import {
|
|
22969
|
-
ConfigError as ConfigError5
|
|
23105
|
+
ConfigError as ConfigError5,
|
|
23106
|
+
REASONING_EFFORT_LEVELS,
|
|
23107
|
+
isReasoningEffort
|
|
22970
23108
|
} from "@wrongstack/core/types";
|
|
22971
23109
|
import { atomicWrite as atomicWrite8, color as color48, expectDefined as expectDefined6, toErrorMessage as toErrorMessage21 } from "@wrongstack/core/utils";
|
|
22972
23110
|
import { catalogProviderIdFor } from "@wrongstack/providers";
|
|
@@ -23021,18 +23159,6 @@ function parseTarget(tokens, profiles = {}) {
|
|
|
23021
23159
|
}
|
|
23022
23160
|
return { model: only };
|
|
23023
23161
|
}
|
|
23024
|
-
var REASONING_EFFORTS = [
|
|
23025
|
-
"none",
|
|
23026
|
-
"minimal",
|
|
23027
|
-
"low",
|
|
23028
|
-
"medium",
|
|
23029
|
-
"high",
|
|
23030
|
-
"xhigh",
|
|
23031
|
-
"max"
|
|
23032
|
-
];
|
|
23033
|
-
function isReasoningEffort(value) {
|
|
23034
|
-
return !!value && REASONING_EFFORTS.includes(value);
|
|
23035
|
-
}
|
|
23036
23162
|
function isReasoningMode(value) {
|
|
23037
23163
|
return value === "auto" || value === "on" || value === "off";
|
|
23038
23164
|
}
|
|
@@ -23410,7 +23536,7 @@ function buildSetModelCommand(opts) {
|
|
|
23410
23536
|
const key = parts[1];
|
|
23411
23537
|
if (!key) {
|
|
23412
23538
|
return {
|
|
23413
|
-
message: `${color48.amber("Usage:")} /setmodel ${sub} <role|phase|*> ${sub === "reasoning" ? "auto|on|off [effort]" : sub === "reasoning-effort" ?
|
|
23539
|
+
message: `${color48.amber("Usage:")} /setmodel ${sub} <role|phase|*> ${sub === "reasoning" ? "auto|on|off [effort]" : sub === "reasoning-effort" ? REASONING_EFFORT_LEVELS.join("|") : "on|off"}`
|
|
23414
23540
|
};
|
|
23415
23541
|
}
|
|
23416
23542
|
if (matrixKeyKind(key) === "unknown") {
|
|
@@ -23431,7 +23557,7 @@ function buildSetModelCommand(opts) {
|
|
|
23431
23557
|
if (parts[3] !== void 0) {
|
|
23432
23558
|
if (!isReasoningEffort(parts[3])) {
|
|
23433
23559
|
return {
|
|
23434
|
-
message: `${color48.red("Invalid effort")}: "${parts[3]}". Expected ${
|
|
23560
|
+
message: `${color48.red("Invalid effort")}: "${parts[3]}". Expected ${REASONING_EFFORT_LEVELS.join(", ")}.`
|
|
23435
23561
|
};
|
|
23436
23562
|
}
|
|
23437
23563
|
nextEffort = parts[3];
|
|
@@ -23439,7 +23565,7 @@ function buildSetModelCommand(opts) {
|
|
|
23439
23565
|
} else if (sub === "reasoning-effort") {
|
|
23440
23566
|
if (!isReasoningEffort(parts[2])) {
|
|
23441
23567
|
return {
|
|
23442
|
-
message: `${color48.amber("Usage:")} /setmodel reasoning-effort ${key} ${
|
|
23568
|
+
message: `${color48.amber("Usage:")} /setmodel reasoning-effort ${key} ${REASONING_EFFORT_LEVELS.join("|")}`
|
|
23443
23569
|
};
|
|
23444
23570
|
}
|
|
23445
23571
|
nextEffort = parts[2];
|
|
@@ -23549,17 +23675,219 @@ function buildSetModelCommand(opts) {
|
|
|
23549
23675
|
};
|
|
23550
23676
|
}
|
|
23551
23677
|
|
|
23678
|
+
// src/slash-commands/effort.ts
|
|
23679
|
+
import { decryptConfigSecrets as decryptConfigSecrets5, encryptConfigSecrets as encryptConfigSecrets5, noOpVault as noOpVault7 } from "@wrongstack/core/security";
|
|
23680
|
+
import {
|
|
23681
|
+
isReasoningEffort as isReasoningEffort2,
|
|
23682
|
+
REASONING_EFFORT_LEVELS as REASONING_EFFORT_LEVELS2
|
|
23683
|
+
} from "@wrongstack/core/types";
|
|
23684
|
+
import { atomicWrite as atomicWrite9, color as color49 } from "@wrongstack/core/utils";
|
|
23685
|
+
import { catalogProviderIdFor as catalogProviderIdFor2 } from "@wrongstack/providers";
|
|
23686
|
+
import * as fs14 from "node:fs/promises";
|
|
23687
|
+
function buildEffortCommand(opts) {
|
|
23688
|
+
const levelsHint = REASONING_EFFORT_LEVELS2.join("|");
|
|
23689
|
+
const help = [
|
|
23690
|
+
"Usage:",
|
|
23691
|
+
" /effort Show current session effort + supported levels",
|
|
23692
|
+
` /effort <level> Set session effort (${levelsHint})`,
|
|
23693
|
+
" /effort clear Remove the setting \u2014 provider default applies",
|
|
23694
|
+
" /effort matrix Show per-role/phase effort overrides (/setmodel)",
|
|
23695
|
+
"",
|
|
23696
|
+
"Applies to the active model on the next request. Unsupported values for the",
|
|
23697
|
+
"current model are rejected up front when its capabilities are known.",
|
|
23698
|
+
"Per-subagent overrides: /setmodel reasoning-effort <role|phase|*> <level>."
|
|
23699
|
+
].join("\n");
|
|
23700
|
+
async function loadModelLevels() {
|
|
23701
|
+
const registry = opts.modelsRegistry;
|
|
23702
|
+
if (!registry) return { levels: void 0, supported: void 0 };
|
|
23703
|
+
const config = opts.configStore.get();
|
|
23704
|
+
try {
|
|
23705
|
+
const catalogId = catalogProviderIdFor2(
|
|
23706
|
+
config.provider,
|
|
23707
|
+
config.providers?.[config.provider]?.type
|
|
23708
|
+
);
|
|
23709
|
+
const resolved = await registry.getModel(catalogId, config.model);
|
|
23710
|
+
const rc = resolved?.capabilities.reasoningConfig;
|
|
23711
|
+
if (!rc) {
|
|
23712
|
+
const provider = await registry.getProvider(catalogId).catch(() => void 0);
|
|
23713
|
+
const raw = provider?.models.find((m) => m.id === config.model);
|
|
23714
|
+
return { levels: void 0, supported: raw?.reasoning === false ? false : void 0 };
|
|
23715
|
+
}
|
|
23716
|
+
return {
|
|
23717
|
+
levels: rc.effortLevels?.length ? rc.effortLevels : void 0,
|
|
23718
|
+
// rc present ⇒ the model is known to reason. Only a DOCUMENTED
|
|
23719
|
+
// absence (`effortSupported === false`) marks it unsupported; an
|
|
23720
|
+
// undocumented vocabulary (`undefined`) is "supported, not
|
|
23721
|
+
// enumerated" — accept any canonical level and let the wire adapter
|
|
23722
|
+
// gate. `undefined` here is reserved for capabilities-unknown above.
|
|
23723
|
+
supported: rc.effortSupported !== false
|
|
23724
|
+
};
|
|
23725
|
+
} catch {
|
|
23726
|
+
return { levels: void 0, supported: void 0 };
|
|
23727
|
+
}
|
|
23728
|
+
}
|
|
23729
|
+
return {
|
|
23730
|
+
name: "effort",
|
|
23731
|
+
category: "Config",
|
|
23732
|
+
description: "View or set the session-wide reasoning effort for the active model.",
|
|
23733
|
+
argsHint: `[${levelsHint}|clear|matrix]`,
|
|
23734
|
+
help,
|
|
23735
|
+
async run(args) {
|
|
23736
|
+
const parts = args.trim().split(/\s+/).filter(Boolean);
|
|
23737
|
+
const sub = (parts[0] ?? "").toLowerCase();
|
|
23738
|
+
if (sub === "help" || sub === "--help") return { message: help };
|
|
23739
|
+
if (!opts.configStore || !opts.paths) {
|
|
23740
|
+
return { message: `${color49.red("Error")} config store not available.` };
|
|
23741
|
+
}
|
|
23742
|
+
const config = opts.configStore.get();
|
|
23743
|
+
if (sub === "matrix") {
|
|
23744
|
+
const matrix = config.modelMatrix ?? {};
|
|
23745
|
+
const entries = Object.entries(matrix).filter(([, e]) => e?.modelRuntime?.reasoning);
|
|
23746
|
+
if (entries.length === 0) {
|
|
23747
|
+
return {
|
|
23748
|
+
message: [
|
|
23749
|
+
`${color49.bold("Effort overrides")} ${color49.dim("(model matrix)")}`,
|
|
23750
|
+
` ${color49.dim("(none \u2014 set one with /setmodel reasoning-effort <role|phase|*> <level>)")}`
|
|
23751
|
+
].join("\n")
|
|
23752
|
+
};
|
|
23753
|
+
}
|
|
23754
|
+
const lines = [`${color49.bold("Effort overrides")} ${color49.dim("(model matrix)")}`];
|
|
23755
|
+
for (const [key, entry] of entries.sort(([a], [b]) => a.localeCompare(b))) {
|
|
23756
|
+
const reasoning = entry.modelRuntime.reasoning;
|
|
23757
|
+
const bits = [
|
|
23758
|
+
reasoning.effort ? `effort:${reasoning.effort}` : "",
|
|
23759
|
+
reasoning.mode ? `mode:${reasoning.mode}` : "",
|
|
23760
|
+
reasoning.preserve !== void 0 ? `preserve:${reasoning.preserve ? "on" : "off"}` : ""
|
|
23761
|
+
].filter(Boolean);
|
|
23762
|
+
lines.push(` ${color49.amber(key.padEnd(22))} \u2192 ${bits.join(" ")}`);
|
|
23763
|
+
}
|
|
23764
|
+
return { message: lines.join("\n") };
|
|
23765
|
+
}
|
|
23766
|
+
const { levels, supported } = await loadModelLevels();
|
|
23767
|
+
const current = config.modelRuntime?.reasoning?.effort;
|
|
23768
|
+
if (!sub) {
|
|
23769
|
+
const lines = [
|
|
23770
|
+
`${color49.bold("WrongStack")} ${color49.dim("\u2014 Session effort")}`,
|
|
23771
|
+
"",
|
|
23772
|
+
` ${color49.bold("model")} ${color49.cyan(`${config.provider}/${config.model}`)}`
|
|
23773
|
+
];
|
|
23774
|
+
if (current) {
|
|
23775
|
+
const ok = !levels || levels.includes(current);
|
|
23776
|
+
lines.push(
|
|
23777
|
+
` ${color49.bold("effort")} ${color49.bold(current)}${ok ? "" : ` ${color49.amber(`(not advertised by this model \u2014 supported: ${levels.join(", ")})`)}`}`
|
|
23778
|
+
);
|
|
23779
|
+
} else {
|
|
23780
|
+
lines.push(` ${color49.bold("effort")} ${color49.dim("(not set \u2014 provider default)")}`);
|
|
23781
|
+
}
|
|
23782
|
+
if (levels) {
|
|
23783
|
+
const rendered = REASONING_EFFORT_LEVELS2.filter((l) => levels.includes(l)).map(
|
|
23784
|
+
(l) => l === current ? color49.bold(l) : l
|
|
23785
|
+
);
|
|
23786
|
+
lines.push(` ${color49.bold("levels")} ${rendered.join(" \xB7 ")}`);
|
|
23787
|
+
} else if (supported === true) {
|
|
23788
|
+
lines.push(
|
|
23789
|
+
` ${color49.bold("levels")} ${color49.dim("(not enumerated \u2014 any level is accepted; the transport applies its own gating)")}`
|
|
23790
|
+
);
|
|
23791
|
+
} else if (supported === false) {
|
|
23792
|
+
lines.push(
|
|
23793
|
+
` ${color49.bold("levels")} ${color49.red("no effort control")}${color49.dim(" \u2014 documented as unsupported for this model")}`
|
|
23794
|
+
);
|
|
23795
|
+
} else {
|
|
23796
|
+
lines.push(
|
|
23797
|
+
` ${color49.bold("levels")} ${color49.dim("(unknown \u2014 the resolver drops unsupported values with a warning)")}`
|
|
23798
|
+
);
|
|
23799
|
+
}
|
|
23800
|
+
lines.push(
|
|
23801
|
+
"",
|
|
23802
|
+
` ${color49.dim("/effort <level> \xB7 clear \xB7 matrix \xB7 help")}`
|
|
23803
|
+
);
|
|
23804
|
+
return { message: lines.join("\n") };
|
|
23805
|
+
}
|
|
23806
|
+
if (sub === "clear" || sub === "off-default") {
|
|
23807
|
+
if (current === void 0) {
|
|
23808
|
+
return { message: `${color49.dim("No session effort set \u2014 provider default already applies.")}` };
|
|
23809
|
+
}
|
|
23810
|
+
await patchSessionEffort(void 0, opts.paths, config.activeProfile ?? "default");
|
|
23811
|
+
opts.configStore.update({
|
|
23812
|
+
modelRuntime: {
|
|
23813
|
+
...config.modelRuntime,
|
|
23814
|
+
reasoning: { ...config.modelRuntime?.reasoning, effort: void 0 }
|
|
23815
|
+
}
|
|
23816
|
+
});
|
|
23817
|
+
return {
|
|
23818
|
+
message: `${color49.green("\u2713")} session effort cleared ${color49.dim("\u2014 provider default applies")}`
|
|
23819
|
+
};
|
|
23820
|
+
}
|
|
23821
|
+
if (!isReasoningEffort2(sub)) {
|
|
23822
|
+
return {
|
|
23823
|
+
message: `${color49.amber("Usage:")} /effort ${REASONING_EFFORT_LEVELS2.join("|")} | clear | matrix`
|
|
23824
|
+
};
|
|
23825
|
+
}
|
|
23826
|
+
if (supported === false) {
|
|
23827
|
+
return {
|
|
23828
|
+
message: [
|
|
23829
|
+
`${color49.red("No effort control")} for ${config.provider}/${config.model}: the catalog documents this model's reasoning options without effort levels.`,
|
|
23830
|
+
` ${color49.dim("/effort clear removes the setting")}`
|
|
23831
|
+
].join("\n")
|
|
23832
|
+
};
|
|
23833
|
+
}
|
|
23834
|
+
if (levels && !levels.includes(sub)) {
|
|
23835
|
+
return {
|
|
23836
|
+
message: [
|
|
23837
|
+
`${color49.red("Unsupported effort")} for ${config.provider}/${config.model}: "${sub}".`,
|
|
23838
|
+
` ${color49.dim(`advertised: ${levels.join(", ")}`)}`,
|
|
23839
|
+
` ${color49.dim("the resolver would drop this value with a warning \u2014 pick an advertised level, or /effort clear")}`
|
|
23840
|
+
].join("\n")
|
|
23841
|
+
};
|
|
23842
|
+
}
|
|
23843
|
+
await patchSessionEffort(sub, opts.paths, config.activeProfile ?? "default");
|
|
23844
|
+
opts.configStore.update({
|
|
23845
|
+
modelRuntime: {
|
|
23846
|
+
...config.modelRuntime,
|
|
23847
|
+
reasoning: { ...config.modelRuntime?.reasoning, effort: sub }
|
|
23848
|
+
}
|
|
23849
|
+
});
|
|
23850
|
+
return {
|
|
23851
|
+
message: `${color49.green("\u2713")} session effort \u2192 ${color49.bold(sub)} ${color49.dim(`(${config.provider}/${config.model}, next request)`)}`
|
|
23852
|
+
};
|
|
23853
|
+
}
|
|
23854
|
+
};
|
|
23855
|
+
}
|
|
23856
|
+
async function patchSessionEffort(effort, paths, activeProfile) {
|
|
23857
|
+
const targetPath = paths.profileConfig(activeProfile);
|
|
23858
|
+
let raw = "{}";
|
|
23859
|
+
try {
|
|
23860
|
+
raw = await fs14.readFile(targetPath, "utf8");
|
|
23861
|
+
} catch {
|
|
23862
|
+
}
|
|
23863
|
+
let parsed;
|
|
23864
|
+
try {
|
|
23865
|
+
parsed = JSON.parse(raw);
|
|
23866
|
+
} catch {
|
|
23867
|
+
parsed = {};
|
|
23868
|
+
}
|
|
23869
|
+
const decrypted = decryptConfigSecrets5(parsed, noOpVault7);
|
|
23870
|
+
const mr = decrypted.modelRuntime ?? {};
|
|
23871
|
+
const reasoning = { ...mr.reasoning ?? {} };
|
|
23872
|
+
if (effort === void 0) delete reasoning.effort;
|
|
23873
|
+
else reasoning.effort = effort;
|
|
23874
|
+
mr.reasoning = reasoning;
|
|
23875
|
+
decrypted.modelRuntime = mr;
|
|
23876
|
+
const encrypted = encryptConfigSecrets5(decrypted, noOpVault7);
|
|
23877
|
+
await atomicWrite9(targetPath, JSON.stringify(encrypted, null, 2), { mode: 384 });
|
|
23878
|
+
}
|
|
23879
|
+
|
|
23552
23880
|
// src/slash-commands/suggest.ts
|
|
23553
|
-
import { execFile
|
|
23881
|
+
import { execFile } from "node:child_process";
|
|
23554
23882
|
import { access as access3 } from "node:fs/promises";
|
|
23555
23883
|
import * as path16 from "node:path";
|
|
23556
|
-
import { color as
|
|
23884
|
+
import { color as color50, toErrorMessage as toErrorMessage22 } from "@wrongstack/core/utils";
|
|
23557
23885
|
import { parseNextSteps } from "@wrongstack/tools/next-steps";
|
|
23558
23886
|
function readGitStatus(projectRoot, includeBranch) {
|
|
23559
23887
|
const args = ["status", "--short"];
|
|
23560
23888
|
if (includeBranch) args.push("--branch");
|
|
23561
23889
|
return new Promise((resolve8) => {
|
|
23562
|
-
|
|
23890
|
+
execFile(
|
|
23563
23891
|
"git",
|
|
23564
23892
|
args,
|
|
23565
23893
|
{
|
|
@@ -23645,7 +23973,7 @@ function buildSuggestCommand(opts) {
|
|
|
23645
23973
|
const suggestions = await generateHeuristicSuggestions(opts);
|
|
23646
23974
|
setSuggestions(suggestions);
|
|
23647
23975
|
opts.onSuggestions?.(suggestions);
|
|
23648
|
-
const display = formatSuggestions(suggestions) + "\n" +
|
|
23976
|
+
const display = formatSuggestions(suggestions) + "\n" + color50.dim("(Heuristic fallback \u2014 multi-agent not enabled)");
|
|
23649
23977
|
return { message: display };
|
|
23650
23978
|
}
|
|
23651
23979
|
if (!fresh && suggestCache && Date.now() - suggestCache.at < SUGGEST_CACHE_TTL_MS) {
|
|
@@ -23653,7 +23981,7 @@ function buildSuggestCommand(opts) {
|
|
|
23653
23981
|
opts.onSuggestions?.(suggestCache.suggestions);
|
|
23654
23982
|
const ageSec = Math.round((Date.now() - suggestCache.at) / 1e3);
|
|
23655
23983
|
return {
|
|
23656
|
-
message: formatSuggestions(suggestCache.suggestions) + "\n" +
|
|
23984
|
+
message: formatSuggestions(suggestCache.suggestions) + "\n" + color50.dim(`(cached ${ageSec}s ago \u2014 /suggest --fresh to regenerate)`)
|
|
23657
23985
|
};
|
|
23658
23986
|
}
|
|
23659
23987
|
const contextText = await collectContext({
|
|
@@ -23661,7 +23989,7 @@ function buildSuggestCommand(opts) {
|
|
|
23661
23989
|
projectRoot: opts.projectRoot
|
|
23662
23990
|
});
|
|
23663
23991
|
const task = buildSuggestPrompt(contextText);
|
|
23664
|
-
opts.renderer.write(
|
|
23992
|
+
opts.renderer.write(color50.dim("Generating suggestions..."));
|
|
23665
23993
|
try {
|
|
23666
23994
|
const raw = await opts.onSpawnAndWait(task, {
|
|
23667
23995
|
name: "suggest"
|
|
@@ -23756,14 +24084,14 @@ async function generateHeuristicSuggestions(opts) {
|
|
|
23756
24084
|
}
|
|
23757
24085
|
function formatSuggestions(suggestions) {
|
|
23758
24086
|
if (suggestions.length === 0) {
|
|
23759
|
-
return
|
|
24087
|
+
return color50.dim("No suggestions available.");
|
|
23760
24088
|
}
|
|
23761
24089
|
const lines = [
|
|
23762
|
-
` ${
|
|
24090
|
+
` ${color50.cyan("\u{1F4A1} Next steps")} ${color50.dim("(use /next 1, /next 2, or /next 1 2 3)")}`,
|
|
23763
24091
|
""
|
|
23764
24092
|
];
|
|
23765
24093
|
for (let i = 0; i < suggestions.length; i++) {
|
|
23766
|
-
const num =
|
|
24094
|
+
const num = color50.bold(`${i + 1}.`);
|
|
23767
24095
|
const text = suggestions[i] ?? "";
|
|
23768
24096
|
lines.push(` ${num} ${text}`);
|
|
23769
24097
|
}
|
|
@@ -23830,7 +24158,7 @@ function buildWebuiCommand() {
|
|
|
23830
24158
|
|
|
23831
24159
|
// src/slash-commands/theme.ts
|
|
23832
24160
|
import { THEME_PRESET_IDS } from "@wrongstack/core/types";
|
|
23833
|
-
import { color as
|
|
24161
|
+
import { color as color51, writeOut as writeOut3 } from "@wrongstack/core/utils";
|
|
23834
24162
|
var THEME_META = {
|
|
23835
24163
|
catppuccin: { name: "Catppuccin Mocha", desc: "Soft pastel dark theme (Default)" },
|
|
23836
24164
|
"tokyo-night": { name: "Tokyo Night", desc: "Deep violet, neon orange & cyan" },
|
|
@@ -23941,19 +24269,19 @@ async function runThemePicker(reader, activeId) {
|
|
|
23941
24269
|
);
|
|
23942
24270
|
const lines = [];
|
|
23943
24271
|
lines.push("");
|
|
23944
|
-
lines.push(`${
|
|
23945
|
-
lines.push(
|
|
24272
|
+
lines.push(`${color51.bold(color51.amber("WrongStack") + color51.dim(" \u2014 TUI Theme Selection"))}`);
|
|
24273
|
+
lines.push(color51.dim(" \u2191\u2193 navigate Enter select q quit"));
|
|
23946
24274
|
lines.push("");
|
|
23947
|
-
if (hasAbove) lines.push(
|
|
24275
|
+
if (hasAbove) lines.push(color51.dim(` \u2026 ${start} more above`));
|
|
23948
24276
|
for (let i = start; i < end; i++) {
|
|
23949
24277
|
const p = THEME_OPTIONS[i];
|
|
23950
|
-
const mark = p.id === activeId ?
|
|
23951
|
-
const prefix = i === currentCursor ?
|
|
23952
|
-
const name = i === currentCursor ?
|
|
24278
|
+
const mark = p.id === activeId ? color51.green(" [active]") : "";
|
|
24279
|
+
const prefix = i === currentCursor ? color51.bold("\u276F ") : " ";
|
|
24280
|
+
const name = i === currentCursor ? color51.bold(p.name) : p.name;
|
|
23953
24281
|
const desc = truncateDesc(p.desc, columns, p.id === activeId);
|
|
23954
|
-
lines.push(` ${prefix}${name.padEnd(21)} ${
|
|
24282
|
+
lines.push(` ${prefix}${name.padEnd(21)} ${color51.dim(desc)}${mark}`);
|
|
23955
24283
|
}
|
|
23956
|
-
if (hasBelow) lines.push(
|
|
24284
|
+
if (hasBelow) lines.push(color51.dim(` \u2026 ${THEME_OPTIONS.length - end} more below`));
|
|
23957
24285
|
lines.push("");
|
|
23958
24286
|
return lines.join("\n");
|
|
23959
24287
|
};
|
|
@@ -24008,21 +24336,21 @@ function buildThemeCommand(opts) {
|
|
|
24008
24336
|
}
|
|
24009
24337
|
}
|
|
24010
24338
|
return {
|
|
24011
|
-
message:
|
|
24339
|
+
message: color51.green(`Switched TUI theme preset to "${selected}" (saved to config).`),
|
|
24012
24340
|
metadata: { themePreset: selected }
|
|
24013
24341
|
};
|
|
24014
24342
|
}
|
|
24015
24343
|
const lines = [
|
|
24016
|
-
|
|
24344
|
+
color51.bold(`Current TUI theme: ${activePreset}`),
|
|
24017
24345
|
"",
|
|
24018
|
-
|
|
24346
|
+
color51.bold("Available Theme Presets:")
|
|
24019
24347
|
];
|
|
24020
24348
|
for (const t of THEME_OPTIONS) {
|
|
24021
|
-
const mark = t.id === activePreset ?
|
|
24022
|
-
lines.push(` \u2022 ${
|
|
24349
|
+
const mark = t.id === activePreset ? color51.green(" [active]") : "";
|
|
24350
|
+
lines.push(` \u2022 ${color51.bold(t.id.padEnd(21))} ${t.desc}${mark}`);
|
|
24023
24351
|
}
|
|
24024
24352
|
lines.push("");
|
|
24025
|
-
lines.push(
|
|
24353
|
+
lines.push(color51.dim("Usage: /theme <preset>"));
|
|
24026
24354
|
return { message: lines.join("\n") };
|
|
24027
24355
|
}
|
|
24028
24356
|
const preset = args.trim().toLowerCase();
|
|
@@ -24038,7 +24366,7 @@ function buildThemeCommand(opts) {
|
|
|
24038
24366
|
}
|
|
24039
24367
|
}
|
|
24040
24368
|
return {
|
|
24041
|
-
message:
|
|
24369
|
+
message: color51.green(`Switched TUI theme preset to "${preset}" (saved to config).`),
|
|
24042
24370
|
metadata: { themePreset: preset }
|
|
24043
24371
|
};
|
|
24044
24372
|
}
|
|
@@ -24046,7 +24374,7 @@ function buildThemeCommand(opts) {
|
|
|
24046
24374
|
}
|
|
24047
24375
|
|
|
24048
24376
|
// src/slash-commands/agents.ts
|
|
24049
|
-
import { noOpVault as
|
|
24377
|
+
import { noOpVault as noOpVault8 } from "@wrongstack/core/security";
|
|
24050
24378
|
function formatAgentLine(a) {
|
|
24051
24379
|
const statusIcon3 = {
|
|
24052
24380
|
spawned: "\u{1F7E2}",
|
|
@@ -24127,7 +24455,7 @@ function buildAgentsCommand(opts) {
|
|
|
24127
24455
|
configStore: opts.configStore,
|
|
24128
24456
|
profileConfigPath: opts.paths.profileConfig(activeProfile),
|
|
24129
24457
|
inProjectConfigPath: opts.paths.inProjectConfig,
|
|
24130
|
-
vault:
|
|
24458
|
+
vault: noOpVault8
|
|
24131
24459
|
},
|
|
24132
24460
|
(autonomy) => {
|
|
24133
24461
|
autonomy.fleetChatVerbosity = mode;
|
|
@@ -24285,8 +24613,8 @@ ${lines.join("\n")}` };
|
|
|
24285
24613
|
|
|
24286
24614
|
// src/slash-commands/hq.ts
|
|
24287
24615
|
import { readHqRuntimeFileSync, resolveHqConfig, resolveHqDataDir } from "@wrongstack/core/hq";
|
|
24288
|
-
import { noOpVault as
|
|
24289
|
-
import { color as
|
|
24616
|
+
import { noOpVault as noOpVault9 } from "@wrongstack/core/security";
|
|
24617
|
+
import { color as color52 } from "@wrongstack/core/utils";
|
|
24290
24618
|
function maskToken(t) {
|
|
24291
24619
|
if (t.length <= 10) return `${t.slice(0, 2)}\u2026(${t.length})`;
|
|
24292
24620
|
return `${t.slice(0, 6)}\u2026${t.slice(-4)} (${t.length} chars)`;
|
|
@@ -24297,12 +24625,12 @@ async function probeHq(url) {
|
|
|
24297
24625
|
const timer = setTimeout(() => ctrl.abort(), 2500);
|
|
24298
24626
|
const res = await fetch(url, { signal: ctrl.signal, redirect: "manual" }).catch(() => null);
|
|
24299
24627
|
clearTimeout(timer);
|
|
24300
|
-
if (!res) return
|
|
24301
|
-
if (res.ok) return
|
|
24302
|
-
if (res.status === 401) return
|
|
24303
|
-
return
|
|
24628
|
+
if (!res) return color52.red("unreachable");
|
|
24629
|
+
if (res.ok) return color52.green("reachable");
|
|
24630
|
+
if (res.status === 401) return color52.green("reachable") + color52.dim(" (token required)");
|
|
24631
|
+
return color52.amber(`reachable (HTTP ${res.status})`);
|
|
24304
24632
|
} catch {
|
|
24305
|
-
return
|
|
24633
|
+
return color52.red("unreachable");
|
|
24306
24634
|
}
|
|
24307
24635
|
}
|
|
24308
24636
|
function buildHqCommand(opts) {
|
|
@@ -24336,13 +24664,13 @@ function buildHqCommand(opts) {
|
|
|
24336
24664
|
const { cmd, rest } = parseSubcommand(args);
|
|
24337
24665
|
const sub = cmd;
|
|
24338
24666
|
if (!opts.configStore || !opts.paths) {
|
|
24339
|
-
return { message: `${
|
|
24667
|
+
return { message: `${color52.red("\u2717")} HQ config is unavailable in this surface.` };
|
|
24340
24668
|
}
|
|
24341
24669
|
const persistDeps = {
|
|
24342
24670
|
configStore: opts.configStore,
|
|
24343
24671
|
profileConfigPath: activeProfileConfigPath(opts.paths, opts.configStore.get()),
|
|
24344
24672
|
inProjectConfigPath: opts.paths.inProjectConfig,
|
|
24345
|
-
vault:
|
|
24673
|
+
vault: noOpVault9,
|
|
24346
24674
|
forceGlobal: true
|
|
24347
24675
|
};
|
|
24348
24676
|
const currentHq = opts.configStore.get().hq;
|
|
@@ -24350,14 +24678,14 @@ function buildHqCommand(opts) {
|
|
|
24350
24678
|
const url = (rest[0] ?? "").trim();
|
|
24351
24679
|
const token = rest.slice(1).join(" ").trim();
|
|
24352
24680
|
if (!url) {
|
|
24353
|
-
return { message: `${
|
|
24681
|
+
return { message: `${color52.amber("Usage:")} /hq set <http://host:3499> [client-token]` };
|
|
24354
24682
|
}
|
|
24355
24683
|
try {
|
|
24356
24684
|
const parsed = new URL(url);
|
|
24357
24685
|
if (parsed.protocol !== "http:" && parsed.protocol !== "https:") throw new Error("proto");
|
|
24358
24686
|
} catch {
|
|
24359
24687
|
return {
|
|
24360
|
-
message: `${
|
|
24688
|
+
message: `${color52.red("Invalid URL:")} ${url} ${color52.dim("(expected http://host:3499)")}`
|
|
24361
24689
|
};
|
|
24362
24690
|
}
|
|
24363
24691
|
await persistConfigSetting(persistDeps, (cfg) => {
|
|
@@ -24369,16 +24697,16 @@ function buildHqCommand(opts) {
|
|
|
24369
24697
|
});
|
|
24370
24698
|
const reach = await probeHq(url);
|
|
24371
24699
|
const tokLine = token ? `
|
|
24372
|
-
token: ${
|
|
24700
|
+
token: ${color52.dim(maskToken(token))}` : "";
|
|
24373
24701
|
return {
|
|
24374
|
-
message: `${
|
|
24702
|
+
message: `${color52.green("\u2713")} HQ set \u2192 ${color52.cyan(url)}${tokLine}
|
|
24375
24703
|
status: ${reach}
|
|
24376
|
-
${
|
|
24704
|
+
${color52.dim("Connects on the next session start.")}`
|
|
24377
24705
|
};
|
|
24378
24706
|
}
|
|
24379
24707
|
if (sub === "token") {
|
|
24380
24708
|
const token = rest.join(" ").trim();
|
|
24381
|
-
if (!token) return { message: `${
|
|
24709
|
+
if (!token) return { message: `${color52.amber("Usage:")} /hq token <client-token>` };
|
|
24382
24710
|
await persistConfigSetting(persistDeps, (cfg) => {
|
|
24383
24711
|
const hq = cfg.hq ?? {};
|
|
24384
24712
|
hq.token = token;
|
|
@@ -24386,14 +24714,14 @@ function buildHqCommand(opts) {
|
|
|
24386
24714
|
cfg.hq = hq;
|
|
24387
24715
|
});
|
|
24388
24716
|
return {
|
|
24389
|
-
message: `${
|
|
24717
|
+
message: `${color52.green("\u2713")} HQ client token saved ${color52.dim(maskToken(token))}`
|
|
24390
24718
|
};
|
|
24391
24719
|
}
|
|
24392
24720
|
if (sub === "raw") {
|
|
24393
24721
|
const mode = (rest[0] ?? "").trim().toLowerCase();
|
|
24394
24722
|
if (mode !== "on" && mode !== "off") {
|
|
24395
24723
|
return {
|
|
24396
|
-
message: `${
|
|
24724
|
+
message: `${color52.amber("Usage:")} /hq raw on|off ${color52.dim("(publish raw chat/tool content to HQ)")}`
|
|
24397
24725
|
};
|
|
24398
24726
|
}
|
|
24399
24727
|
const on = mode === "on";
|
|
@@ -24403,8 +24731,8 @@ function buildHqCommand(opts) {
|
|
|
24403
24731
|
cfg.hq = hq;
|
|
24404
24732
|
});
|
|
24405
24733
|
return {
|
|
24406
|
-
message: `${
|
|
24407
|
-
${
|
|
24734
|
+
message: `${color52.green("\u2713")} HQ raw content \u2192 ${on ? color52.amber("on (unredacted)") : color52.dim("off (redacted)")}
|
|
24735
|
+
${color52.dim("Applies to sessions started after this change. Only enable for HQ servers you trust.")}`
|
|
24408
24736
|
};
|
|
24409
24737
|
}
|
|
24410
24738
|
if (sub === "on" || sub === "off") {
|
|
@@ -24415,29 +24743,29 @@ function buildHqCommand(opts) {
|
|
|
24415
24743
|
cfg.hq = hq;
|
|
24416
24744
|
});
|
|
24417
24745
|
return {
|
|
24418
|
-
message: `${
|
|
24746
|
+
message: `${color52.green("\u2713")} HQ publishing \u2192 ${on ? color52.cyan("on") : color52.dim("off")}`
|
|
24419
24747
|
};
|
|
24420
24748
|
}
|
|
24421
24749
|
if (sub === "clear") {
|
|
24422
24750
|
await persistConfigSetting(persistDeps, (cfg) => {
|
|
24423
24751
|
delete cfg.hq;
|
|
24424
24752
|
});
|
|
24425
|
-
return { message: `${
|
|
24753
|
+
return { message: `${color52.green("\u2713")} HQ configuration cleared.` };
|
|
24426
24754
|
}
|
|
24427
24755
|
if (sub === "" || sub === "status") {
|
|
24428
24756
|
const dataDir = resolveHqDataDir(currentHq?.dataDir);
|
|
24429
24757
|
const runtime = readHqRuntimeFileSync(dataDir);
|
|
24430
24758
|
const resolved = resolveHqConfig({ config: currentHq });
|
|
24431
|
-
const lines = [`${
|
|
24759
|
+
const lines = [`${color52.bold("\u{1F4CB} WrongStack HQ \u2014 connection")}`, ""];
|
|
24432
24760
|
if (!resolved) {
|
|
24433
24761
|
lines.push(
|
|
24434
|
-
` ${
|
|
24762
|
+
` ${color52.dim("Not configured.")} Use ${color52.cyan("/hq set <url> [token]")} to connect,`
|
|
24435
24763
|
);
|
|
24436
|
-
lines.push(` or run ${
|
|
24764
|
+
lines.push(` or run ${color52.cyan("wstack --hq")} locally (auto-discovered).`);
|
|
24437
24765
|
if (runtime) {
|
|
24438
24766
|
lines.push("");
|
|
24439
24767
|
lines.push(
|
|
24440
|
-
` ${
|
|
24768
|
+
` ${color52.green("A local HQ is running")} at ${color52.cyan(runtime.url)} ${color52.dim("(start a new session to attach)")}`
|
|
24441
24769
|
);
|
|
24442
24770
|
}
|
|
24443
24771
|
const message = lines.join("\n");
|
|
@@ -24445,35 +24773,35 @@ function buildHqCommand(opts) {
|
|
|
24445
24773
|
}
|
|
24446
24774
|
if (resolved.discover && !runtime) {
|
|
24447
24775
|
lines.push(
|
|
24448
|
-
` mode: ${
|
|
24776
|
+
` mode: ${color52.cyan("auto-discovery")} ${color52.dim("(no local HQ running yet)")}`
|
|
24449
24777
|
);
|
|
24450
24778
|
lines.push(
|
|
24451
|
-
` ${
|
|
24779
|
+
` ${color52.dim("This session will attach automatically when `wstack --hq` starts")}`
|
|
24452
24780
|
);
|
|
24453
|
-
lines.push(` ${
|
|
24454
|
-
lines.push(` ${
|
|
24781
|
+
lines.push(` ${color52.dim(`on this machine (watching ${dataDir}).`)}`);
|
|
24782
|
+
lines.push(` ${color52.dim("Disable with WRONGSTACK_HQ_ENABLED=0 or /hq off.")}`);
|
|
24455
24783
|
return { message: lines.join("\n") };
|
|
24456
24784
|
}
|
|
24457
24785
|
const source = process.env["WRONGSTACK_HQ_URL"] ? "WRONGSTACK_HQ_URL env" : currentHq?.url ? "config.json" : runtime ? `local HQ marker (pid ${runtime.pid ?? "?"})` : "default";
|
|
24458
|
-
lines.push(` url: ${
|
|
24786
|
+
lines.push(` url: ${color52.cyan(resolved.url)}`);
|
|
24459
24787
|
lines.push(
|
|
24460
|
-
` enabled: ${resolved.enabled === false ?
|
|
24788
|
+
` enabled: ${resolved.enabled === false ? color52.dim("false") : color52.green("true")}`
|
|
24461
24789
|
);
|
|
24462
|
-
if (resolved.discover) lines.push(` mode: ${
|
|
24463
|
-
lines.push(` source: ${
|
|
24790
|
+
if (resolved.discover) lines.push(` mode: ${color52.cyan("auto-discovery")}`);
|
|
24791
|
+
lines.push(` source: ${color52.dim(source)}`);
|
|
24464
24792
|
lines.push(
|
|
24465
|
-
` token: ${resolved.token ?
|
|
24793
|
+
` token: ${resolved.token ? color52.dim(maskToken(resolved.token)) : color52.dim("none (open mode)")}`
|
|
24466
24794
|
);
|
|
24467
24795
|
lines.push(
|
|
24468
|
-
` content: ${resolved.rawContent === true ?
|
|
24796
|
+
` content: ${resolved.rawContent === true ? color52.amber("raw (unredacted)") : color52.dim("redacted \u2014 explicitly disabled; enable with /hq raw on")}`
|
|
24469
24797
|
);
|
|
24470
|
-
if (resolved.projectAlias) lines.push(` alias: ${
|
|
24798
|
+
if (resolved.projectAlias) lines.push(` alias: ${color52.cyan(resolved.projectAlias)}`);
|
|
24471
24799
|
lines.push(` status: ${await probeHq(resolved.url)}`);
|
|
24472
24800
|
return { message: lines.join("\n") };
|
|
24473
24801
|
}
|
|
24474
24802
|
return {
|
|
24475
|
-
message: `${
|
|
24476
|
-
${
|
|
24803
|
+
message: `${color52.red("Unknown subcommand:")} ${sub}
|
|
24804
|
+
${color52.dim("Try /hq, /hq set <url> [token], /hq raw on|off, /hq on|off, /hq clear, or /help hq")}`
|
|
24477
24805
|
};
|
|
24478
24806
|
}
|
|
24479
24807
|
};
|
|
@@ -24523,12 +24851,12 @@ function buildMouseCommand(_opts) {
|
|
|
24523
24851
|
}
|
|
24524
24852
|
|
|
24525
24853
|
// src/slash-commands/project.ts
|
|
24526
|
-
import { spawn as
|
|
24527
|
-
import * as
|
|
24854
|
+
import { spawn as spawn6 } from "node:child_process";
|
|
24855
|
+
import * as fs15 from "node:fs/promises";
|
|
24528
24856
|
import { createRequire } from "node:module";
|
|
24529
24857
|
import * as path17 from "node:path";
|
|
24530
24858
|
import {
|
|
24531
|
-
color as
|
|
24859
|
+
color as color53,
|
|
24532
24860
|
ensureProjectGitignore,
|
|
24533
24861
|
ensureProjectIdentity as ensureProjectIdentity2,
|
|
24534
24862
|
projectIdentityPath,
|
|
@@ -24661,17 +24989,17 @@ async function projectIdentityCommand(opts, ctx, action, confirmed) {
|
|
|
24661
24989
|
if (action === "show") {
|
|
24662
24990
|
const identity = await readProjectIdentity(root);
|
|
24663
24991
|
return identity ? {
|
|
24664
|
-
message: `${
|
|
24665
|
-
${
|
|
24666
|
-
} : { message: `No committed project identity. Run ${
|
|
24992
|
+
message: `${color53.bold("Project ID:")} ${color53.cyan(identity.projectId)}
|
|
24993
|
+
${color53.dim(filePath)}`
|
|
24994
|
+
} : { message: `No committed project identity. Run ${color53.cyan("/project init")}.` };
|
|
24667
24995
|
}
|
|
24668
24996
|
if (action === "init") {
|
|
24669
24997
|
const result2 = await ensureProjectIdentity2(root);
|
|
24670
24998
|
await ensureProjectGitignore(root);
|
|
24671
24999
|
return {
|
|
24672
|
-
message: result2.created ? `${
|
|
24673
|
-
${
|
|
24674
|
-
${
|
|
25000
|
+
message: result2.created ? `${color53.green("Created")} ${filePath}
|
|
25001
|
+
${color53.cyan(result2.identity.projectId)}
|
|
25002
|
+
${color53.dim("Commit this file so every clone and machine shares the same HQ project.")}` : `${color53.dim("Project identity already exists:")} ${color53.cyan(result2.identity.projectId)}`
|
|
24675
25003
|
};
|
|
24676
25004
|
}
|
|
24677
25005
|
if (!confirmed && opts.confirm) {
|
|
@@ -24686,17 +25014,17 @@ ${color52.dim("Commit this file so every clone and machine shares the same HQ pr
|
|
|
24686
25014
|
}
|
|
24687
25015
|
if (!confirmed) {
|
|
24688
25016
|
return {
|
|
24689
|
-
message: `Rekey requires confirmation. Pass ${
|
|
25017
|
+
message: `Rekey requires confirmation. Pass ${color53.cyan("--yes")} or ${color53.cyan("-y")}.`
|
|
24690
25018
|
};
|
|
24691
25019
|
}
|
|
24692
25020
|
const result = await rekeyProjectIdentity(root);
|
|
24693
25021
|
await ensureProjectGitignore(root);
|
|
24694
25022
|
return {
|
|
24695
25023
|
message: [
|
|
24696
|
-
result.previous ?
|
|
24697
|
-
`${
|
|
24698
|
-
|
|
24699
|
-
|
|
25024
|
+
result.previous ? color53.dim(`Previous: ${result.previous.projectId}`) : color53.dim("Previous: none"),
|
|
25025
|
+
`${color53.green("New project ID:")} ${color53.cyan(result.identity.projectId)}`,
|
|
25026
|
+
color53.dim(`Commit ${filePath} to make this fork independent on every machine.`),
|
|
25027
|
+
color53.dim("Restart WrongStack before publishing HQ or Kanban updates under the new ID.")
|
|
24700
25028
|
].join("\n")
|
|
24701
25029
|
};
|
|
24702
25030
|
}
|
|
@@ -24705,7 +25033,7 @@ async function listProjectsCommand(opts, ctx) {
|
|
|
24705
25033
|
const currentRoot = ctx?.projectRoot;
|
|
24706
25034
|
if (manifest.projects.length === 0) {
|
|
24707
25035
|
return {
|
|
24708
|
-
message:
|
|
25036
|
+
message: color53.dim("No projects registered. Add one: /project add <path> [name]")
|
|
24709
25037
|
};
|
|
24710
25038
|
}
|
|
24711
25039
|
const sorted = [...manifest.projects].sort((a, b) => {
|
|
@@ -24717,19 +25045,19 @@ async function listProjectsCommand(opts, ctx) {
|
|
|
24717
25045
|
const lines = [`Projects (${sorted.length}) registered in projects.json:`, ""];
|
|
24718
25046
|
for (const p of sorted) {
|
|
24719
25047
|
const isCurrent = p.root === currentRoot;
|
|
24720
|
-
const marker = isCurrent ?
|
|
24721
|
-
const name = isCurrent ?
|
|
24722
|
-
const slug =
|
|
24723
|
-
const last =
|
|
25048
|
+
const marker = isCurrent ? color53.green("\u25CF") : color53.dim("\u25CB");
|
|
25049
|
+
const name = isCurrent ? color53.bold(p.name) : p.name;
|
|
25050
|
+
const slug = color53.dim(`[${p.slug}]`);
|
|
25051
|
+
const last = color53.dim(fmtLastSeen(p.lastSeen));
|
|
24724
25052
|
lines.push(` ${marker} ${name} ${slug} ${last}`);
|
|
24725
25053
|
lines.push(` ${p.root}`);
|
|
24726
25054
|
if (isCurrent) {
|
|
24727
|
-
lines.push(` ${
|
|
25055
|
+
lines.push(` ${color53.green("\u2190 active session")}`);
|
|
24728
25056
|
}
|
|
24729
25057
|
lines.push("");
|
|
24730
25058
|
}
|
|
24731
25059
|
lines.push(
|
|
24732
|
-
|
|
25060
|
+
color53.dim(
|
|
24733
25061
|
"Commands: add <path> [name] | rename <slug> <name> | remove <slug> | switch [dir] (no args = picker)"
|
|
24734
25062
|
)
|
|
24735
25063
|
);
|
|
@@ -24738,19 +25066,19 @@ async function listProjectsCommand(opts, ctx) {
|
|
|
24738
25066
|
async function addProjectCommand(opts, ctx, targetPath, displayName) {
|
|
24739
25067
|
const resolved = path17.resolve(ctx?.projectRoot ?? ctx?.cwd ?? process.cwd(), targetPath);
|
|
24740
25068
|
try {
|
|
24741
|
-
await
|
|
25069
|
+
await fs15.access(resolved);
|
|
24742
25070
|
} catch {
|
|
24743
|
-
return { message:
|
|
25071
|
+
return { message: color53.red(`Directory not found: ${resolved}`) };
|
|
24744
25072
|
}
|
|
24745
|
-
const stat5 = await
|
|
25073
|
+
const stat5 = await fs15.stat(resolved);
|
|
24746
25074
|
if (!stat5.isDirectory()) {
|
|
24747
|
-
return { message:
|
|
25075
|
+
return { message: color53.red(`Not a directory: ${resolved}`) };
|
|
24748
25076
|
}
|
|
24749
25077
|
const manifest = await loadManifest(opts.paths?.globalConfig);
|
|
24750
25078
|
const existing = manifest.projects.find((p) => p.root === resolved);
|
|
24751
25079
|
if (existing) {
|
|
24752
25080
|
return {
|
|
24753
|
-
message:
|
|
25081
|
+
message: color53.yellow(`Project already registered: "${existing.name}" (${existing.slug})`)
|
|
24754
25082
|
};
|
|
24755
25083
|
}
|
|
24756
25084
|
const name = displayName?.trim() || path17.basename(resolved);
|
|
@@ -24762,9 +25090,9 @@ async function addProjectCommand(opts, ctx, targetPath, displayName) {
|
|
|
24762
25090
|
return {
|
|
24763
25091
|
message: [
|
|
24764
25092
|
"",
|
|
24765
|
-
|
|
24766
|
-
|
|
24767
|
-
|
|
25093
|
+
color53.green(` Added project: ${name}`),
|
|
25094
|
+
color53.dim(` Root: ${resolved}`),
|
|
25095
|
+
color53.dim(` Slug: ${slug}`),
|
|
24768
25096
|
""
|
|
24769
25097
|
].join("\n")
|
|
24770
25098
|
};
|
|
@@ -24774,7 +25102,7 @@ async function renameProjectCommand(opts, _ctx, slugOrName, newName) {
|
|
|
24774
25102
|
const project = findProject(manifest, slugOrName);
|
|
24775
25103
|
if (!project) {
|
|
24776
25104
|
return {
|
|
24777
|
-
message:
|
|
25105
|
+
message: color53.red(
|
|
24778
25106
|
`Project not found: "${slugOrName}". Use /project list to see available projects.`
|
|
24779
25107
|
)
|
|
24780
25108
|
};
|
|
@@ -24782,7 +25110,7 @@ async function renameProjectCommand(opts, _ctx, slugOrName, newName) {
|
|
|
24782
25110
|
const oldName = project.name;
|
|
24783
25111
|
project.name = newName;
|
|
24784
25112
|
await saveManifest(manifest, opts.paths?.globalConfig);
|
|
24785
|
-
return { message:
|
|
25113
|
+
return { message: color53.green(`Renamed: "${oldName}" \u2192 "${newName}" (${project.slug})`) };
|
|
24786
25114
|
}
|
|
24787
25115
|
async function removeProjectCommand(opts, _ctx, slugOrName) {
|
|
24788
25116
|
const manifest = await loadManifest(opts.paths?.globalConfig);
|
|
@@ -24791,7 +25119,7 @@ async function removeProjectCommand(opts, _ctx, slugOrName) {
|
|
|
24791
25119
|
);
|
|
24792
25120
|
if (idx === -1) {
|
|
24793
25121
|
return {
|
|
24794
|
-
message:
|
|
25122
|
+
message: color53.red(
|
|
24795
25123
|
`Project not found: "${slugOrName}". Use /project list to see available projects.`
|
|
24796
25124
|
)
|
|
24797
25125
|
};
|
|
@@ -24800,7 +25128,7 @@ async function removeProjectCommand(opts, _ctx, slugOrName) {
|
|
|
24800
25128
|
manifest.projects.splice(idx, 1);
|
|
24801
25129
|
await saveManifest(manifest, opts.paths?.globalConfig);
|
|
24802
25130
|
return {
|
|
24803
|
-
message:
|
|
25131
|
+
message: color53.dim(
|
|
24804
25132
|
`Removed: "${removed.name}" (${removed.root}) \u2014 data directory kept at ~/.wrongstack/projects/${removed.slug}/`
|
|
24805
25133
|
)
|
|
24806
25134
|
};
|
|
@@ -24808,13 +25136,13 @@ async function removeProjectCommand(opts, _ctx, slugOrName) {
|
|
|
24808
25136
|
async function switchProjectCommand(opts, ctx, target, displayName) {
|
|
24809
25137
|
const resolved = path17.resolve(ctx?.projectRoot ?? ctx?.cwd ?? process.cwd(), target);
|
|
24810
25138
|
try {
|
|
24811
|
-
await
|
|
25139
|
+
await fs15.access(resolved);
|
|
24812
25140
|
} catch {
|
|
24813
|
-
return { message:
|
|
25141
|
+
return { message: color53.red(`Directory not found: ${resolved}`) };
|
|
24814
25142
|
}
|
|
24815
|
-
const stat5 = await
|
|
25143
|
+
const stat5 = await fs15.stat(resolved);
|
|
24816
25144
|
if (!stat5.isDirectory()) {
|
|
24817
|
-
return { message:
|
|
25145
|
+
return { message: color53.red(`Not a directory: ${resolved}`) };
|
|
24818
25146
|
}
|
|
24819
25147
|
let cliPath;
|
|
24820
25148
|
try {
|
|
@@ -24822,12 +25150,12 @@ async function switchProjectCommand(opts, ctx, target, displayName) {
|
|
|
24822
25150
|
const pkgPath = req.resolve("@wrongstack/cli/package.json");
|
|
24823
25151
|
const pkgDir = path17.dirname(pkgPath);
|
|
24824
25152
|
cliPath = path17.join(pkgDir, "dist", "index.js");
|
|
24825
|
-
await
|
|
25153
|
+
await fs15.access(cliPath);
|
|
24826
25154
|
} catch {
|
|
24827
25155
|
cliPath = process.argv[1] ?? "";
|
|
24828
25156
|
if (!cliPath) {
|
|
24829
25157
|
return {
|
|
24830
|
-
message:
|
|
25158
|
+
message: color53.red(
|
|
24831
25159
|
"Could not locate the CLI entry point. Run `wstack` manually in the target directory."
|
|
24832
25160
|
)
|
|
24833
25161
|
};
|
|
@@ -24848,7 +25176,7 @@ async function switchProjectCommand(opts, ctx, target, displayName) {
|
|
|
24848
25176
|
const canSwitch = await confirmProjectSwitch(opts, targetName);
|
|
24849
25177
|
if (!canSwitch) return { message: "" };
|
|
24850
25178
|
const nodeExe = process.execPath;
|
|
24851
|
-
const child =
|
|
25179
|
+
const child = spawn6(nodeExe, [cliPath, "--no-interactive"], {
|
|
24852
25180
|
cwd: resolved,
|
|
24853
25181
|
stdio: "inherit",
|
|
24854
25182
|
detached: false
|
|
@@ -24860,14 +25188,14 @@ async function switchProjectCommand(opts, ctx, target, displayName) {
|
|
|
24860
25188
|
// and boot/tui-project-spawn.ts documents this exact bug being removed.
|
|
24861
25189
|
});
|
|
24862
25190
|
child.on("error", (err) => {
|
|
24863
|
-
console.error(
|
|
25191
|
+
console.error(color53.red(`Failed to spawn wstack: ${err.message}`));
|
|
24864
25192
|
});
|
|
24865
25193
|
child.unref();
|
|
24866
25194
|
return {
|
|
24867
25195
|
message: [
|
|
24868
25196
|
"",
|
|
24869
|
-
|
|
24870
|
-
|
|
25197
|
+
color53.green(` Spawning wstack in ${resolved} ...`),
|
|
25198
|
+
color53.dim(" (current session stays open \u2014 Ctrl+C to return)"),
|
|
24871
25199
|
""
|
|
24872
25200
|
].join("\n")
|
|
24873
25201
|
};
|
|
@@ -24881,45 +25209,45 @@ async function confirmProjectSwitch(opts, targetName) {
|
|
|
24881
25209
|
const parallelActive = parallelEngine?.currentState === "running";
|
|
24882
25210
|
const hasActiveAgents = fleetRunning > 0 || eternalActive || parallelActive;
|
|
24883
25211
|
if (!hasActiveAgents) return true;
|
|
24884
|
-
const parts = [
|
|
25212
|
+
const parts = [color53.yellow(`\u26A0 Switching projects will stop all running agents.`), ""];
|
|
24885
25213
|
if (fleetRunning > 0) {
|
|
24886
|
-
parts.push(
|
|
25214
|
+
parts.push(color53.dim(` \u2022 ${fleetRunning} subagent(s) currently running`));
|
|
24887
25215
|
}
|
|
24888
25216
|
if (eternalActive) {
|
|
24889
|
-
parts.push(
|
|
25217
|
+
parts.push(color53.dim(" \u2022 Eternal engine is active"));
|
|
24890
25218
|
}
|
|
24891
25219
|
if (parallelActive) {
|
|
24892
|
-
parts.push(
|
|
25220
|
+
parts.push(color53.dim(" \u2022 Parallel engine is active"));
|
|
24893
25221
|
}
|
|
24894
25222
|
parts.push("");
|
|
24895
|
-
parts.push(
|
|
25223
|
+
parts.push(color53.dim(` Target: ${targetName}`));
|
|
24896
25224
|
opts.renderer.write(`
|
|
24897
25225
|
${parts.join("\n")}
|
|
24898
25226
|
`);
|
|
24899
25227
|
if (!opts.confirm) return true;
|
|
24900
25228
|
const confirmed = await opts.confirm(
|
|
24901
|
-
|
|
25229
|
+
color53.yellow(`Stop all agents and switch to "${targetName}"?`),
|
|
24902
25230
|
false
|
|
24903
25231
|
// default to No for safety
|
|
24904
25232
|
);
|
|
24905
25233
|
if (!confirmed) {
|
|
24906
|
-
opts.renderer.write(
|
|
25234
|
+
opts.renderer.write(color53.dim(" Switch cancelled.\n"));
|
|
24907
25235
|
return false;
|
|
24908
25236
|
}
|
|
24909
25237
|
if (fleetRunning > 0) {
|
|
24910
25238
|
const killed = opts.onFleetKill ? await opts.onFleetKill() : 0;
|
|
24911
25239
|
if (killed > 0) {
|
|
24912
|
-
opts.renderer.write(
|
|
25240
|
+
opts.renderer.write(color53.dim(` Stopped ${killed} subagent(s).
|
|
24913
25241
|
`));
|
|
24914
25242
|
}
|
|
24915
25243
|
}
|
|
24916
25244
|
if (eternalActive) {
|
|
24917
25245
|
eternalEngine?.stop();
|
|
24918
|
-
opts.renderer.write(
|
|
25246
|
+
opts.renderer.write(color53.dim(" Stopped eternal engine.\n"));
|
|
24919
25247
|
}
|
|
24920
25248
|
if (parallelActive) {
|
|
24921
25249
|
parallelEngine?.stop();
|
|
24922
|
-
opts.renderer.write(
|
|
25250
|
+
opts.renderer.write(color53.dim(" Stopped parallel engine.\n"));
|
|
24923
25251
|
}
|
|
24924
25252
|
return true;
|
|
24925
25253
|
}
|
|
@@ -24931,16 +25259,16 @@ async function switchInteractiveCommand(opts, ctx) {
|
|
|
24931
25259
|
currentProjectRoot: currentRoot
|
|
24932
25260
|
});
|
|
24933
25261
|
if (!result) {
|
|
24934
|
-
return { message:
|
|
25262
|
+
return { message: color53.dim("Cancelled.") };
|
|
24935
25263
|
}
|
|
24936
25264
|
switch (result.kind) {
|
|
24937
25265
|
case "project": {
|
|
24938
25266
|
const project = manifest.projects.find((p) => p.slug === result.key);
|
|
24939
25267
|
if (!project) {
|
|
24940
|
-
return { message:
|
|
25268
|
+
return { message: color53.red(`Project not found: ${result.key}`) };
|
|
24941
25269
|
}
|
|
24942
25270
|
if (project.root === currentRoot) {
|
|
24943
|
-
return { message:
|
|
25271
|
+
return { message: color53.dim(`Already in ${project.name} (${project.root})`) };
|
|
24944
25272
|
}
|
|
24945
25273
|
const canSwitch = await confirmProjectSwitch(opts, project.name);
|
|
24946
25274
|
if (!canSwitch) return { message: "" };
|
|
@@ -24953,11 +25281,11 @@ async function switchInteractiveCommand(opts, ctx) {
|
|
|
24953
25281
|
case "prev-sessions":
|
|
24954
25282
|
return handlePrevSessions(opts, ctx);
|
|
24955
25283
|
default:
|
|
24956
|
-
return { message:
|
|
25284
|
+
return { message: color53.dim("Cancelled.") };
|
|
24957
25285
|
}
|
|
24958
25286
|
}
|
|
24959
25287
|
default:
|
|
24960
|
-
return { message:
|
|
25288
|
+
return { message: color53.dim("Cancelled.") };
|
|
24961
25289
|
}
|
|
24962
25290
|
}
|
|
24963
25291
|
async function spawnInProject(opts, _ctx, root, projectName) {
|
|
@@ -24967,12 +25295,12 @@ async function spawnInProject(opts, _ctx, root, projectName) {
|
|
|
24967
25295
|
const pkgPath = req.resolve("@wrongstack/cli/package.json");
|
|
24968
25296
|
const pkgDir = path17.dirname(pkgPath);
|
|
24969
25297
|
cliPath = path17.join(pkgDir, "dist", "index.js");
|
|
24970
|
-
await
|
|
25298
|
+
await fs15.access(cliPath);
|
|
24971
25299
|
} catch {
|
|
24972
25300
|
cliPath = process.argv[1] ?? "";
|
|
24973
25301
|
if (!cliPath) {
|
|
24974
25302
|
return {
|
|
24975
|
-
message:
|
|
25303
|
+
message: color53.red(
|
|
24976
25304
|
"Could not locate the CLI entry point. Run `wstack` manually in the target directory."
|
|
24977
25305
|
)
|
|
24978
25306
|
};
|
|
@@ -24990,7 +25318,7 @@ async function spawnInProject(opts, _ctx, root, projectName) {
|
|
|
24990
25318
|
}
|
|
24991
25319
|
await saveManifest(manifest, opts.paths?.globalConfig);
|
|
24992
25320
|
const nodeExe = process.execPath;
|
|
24993
|
-
const child =
|
|
25321
|
+
const child = spawn6(nodeExe, [cliPath, "--no-interactive"], {
|
|
24994
25322
|
cwd: root,
|
|
24995
25323
|
stdio: "inherit",
|
|
24996
25324
|
detached: false
|
|
@@ -25002,15 +25330,15 @@ async function spawnInProject(opts, _ctx, root, projectName) {
|
|
|
25002
25330
|
// and boot/tui-project-spawn.ts documents this exact bug being removed.
|
|
25003
25331
|
});
|
|
25004
25332
|
child.on("error", (err) => {
|
|
25005
|
-
console.error(
|
|
25333
|
+
console.error(color53.red(`Failed to spawn wstack: ${err.message}`));
|
|
25006
25334
|
});
|
|
25007
25335
|
child.unref();
|
|
25008
25336
|
return {
|
|
25009
25337
|
message: [
|
|
25010
25338
|
"",
|
|
25011
|
-
|
|
25012
|
-
|
|
25013
|
-
|
|
25339
|
+
color53.green(` Switched to ${projectName}`),
|
|
25340
|
+
color53.dim(` Root: ${root}`),
|
|
25341
|
+
color53.dim(" (current session stays open \u2014 Ctrl+C to return)"),
|
|
25014
25342
|
""
|
|
25015
25343
|
].join("\n")
|
|
25016
25344
|
};
|
|
@@ -25022,17 +25350,17 @@ async function handleNewSession(_opts, _ctx) {
|
|
|
25022
25350
|
const pkgPath = req.resolve("@wrongstack/cli/package.json");
|
|
25023
25351
|
const pkgDir = path17.dirname(pkgPath);
|
|
25024
25352
|
cliPath = path17.join(pkgDir, "dist", "index.js");
|
|
25025
|
-
await
|
|
25353
|
+
await fs15.access(cliPath);
|
|
25026
25354
|
} catch {
|
|
25027
25355
|
cliPath = process.argv[1] ?? "";
|
|
25028
25356
|
if (!cliPath) {
|
|
25029
25357
|
return {
|
|
25030
|
-
message:
|
|
25358
|
+
message: color53.red("Could not locate the CLI entry point. Run `wstack` manually.")
|
|
25031
25359
|
};
|
|
25032
25360
|
}
|
|
25033
25361
|
}
|
|
25034
25362
|
const nodeExe = process.execPath;
|
|
25035
|
-
const child =
|
|
25363
|
+
const child = spawn6(nodeExe, [cliPath, "--no-interactive"], {
|
|
25036
25364
|
cwd: process.cwd(),
|
|
25037
25365
|
stdio: "inherit",
|
|
25038
25366
|
detached: false
|
|
@@ -25044,14 +25372,14 @@ async function handleNewSession(_opts, _ctx) {
|
|
|
25044
25372
|
// and boot/tui-project-spawn.ts documents this exact bug being removed.
|
|
25045
25373
|
});
|
|
25046
25374
|
child.on("error", (err) => {
|
|
25047
|
-
console.error(
|
|
25375
|
+
console.error(color53.red(`Failed to spawn wstack: ${err.message}`));
|
|
25048
25376
|
});
|
|
25049
25377
|
child.unref();
|
|
25050
25378
|
return {
|
|
25051
25379
|
message: [
|
|
25052
25380
|
"",
|
|
25053
|
-
|
|
25054
|
-
|
|
25381
|
+
color53.green(" Starting new session ..."),
|
|
25382
|
+
color53.dim(" (current session stays open \u2014 Ctrl+C to return)"),
|
|
25055
25383
|
""
|
|
25056
25384
|
].join("\n")
|
|
25057
25385
|
};
|
|
@@ -25062,36 +25390,36 @@ async function handlePrevSessions(opts, _ctx) {
|
|
|
25062
25390
|
}
|
|
25063
25391
|
const list = await opts.sessionStore.list(15);
|
|
25064
25392
|
if (list.length === 0) {
|
|
25065
|
-
return { message:
|
|
25393
|
+
return { message: color53.dim("No saved sessions.") };
|
|
25066
25394
|
}
|
|
25067
25395
|
const currentId = opts.context?.session?.id;
|
|
25068
|
-
const lines = [
|
|
25396
|
+
const lines = [color53.bold(`Recent sessions (${list.length}):`), ""];
|
|
25069
25397
|
for (const s of list) {
|
|
25070
25398
|
const isCurrent = s.id === currentId;
|
|
25071
|
-
const marker = isCurrent ?
|
|
25072
|
-
const date =
|
|
25399
|
+
const marker = isCurrent ? color53.cyan("\u25CF") : " ";
|
|
25400
|
+
const date = color53.dim(s.startedAt.slice(0, 16).replace("T", " "));
|
|
25073
25401
|
const stats = [
|
|
25074
|
-
|
|
25075
|
-
s.toolCallCount ?
|
|
25076
|
-
s.iterationCount ?
|
|
25402
|
+
color53.dim(`${s.tokenTotal.toLocaleString()} tok`),
|
|
25403
|
+
s.toolCallCount ? color53.cyan(`${s.toolCallCount} calls`) : "",
|
|
25404
|
+
s.iterationCount ? color53.dim(`${s.iterationCount} iter`) : ""
|
|
25077
25405
|
].filter(Boolean).join(" ");
|
|
25078
|
-
const outcome = s.outcome === "completed" ?
|
|
25079
|
-
lines.push(` ${marker} ${
|
|
25080
|
-
lines.push(` ${stats} ${outcome} ${
|
|
25406
|
+
const outcome = s.outcome === "completed" ? color53.green("\u2713") : s.outcome === "aborted" ? color53.yellow("\u26A0") : s.outcome === "error" ? color53.red("\u2717") : color53.dim("?");
|
|
25407
|
+
lines.push(` ${marker} ${color53.bold(s.id)} ${date}`);
|
|
25408
|
+
lines.push(` ${stats} ${outcome} ${color53.dim(s.title)}`);
|
|
25081
25409
|
lines.push("");
|
|
25082
25410
|
}
|
|
25083
|
-
lines.push(
|
|
25411
|
+
lines.push(color53.dim("Resume: /sessions or wstack resume <id>"));
|
|
25084
25412
|
return { message: lines.join("\n") };
|
|
25085
25413
|
}
|
|
25086
25414
|
|
|
25087
25415
|
// src/slash-commands/review.ts
|
|
25088
|
-
import { spawn as
|
|
25416
|
+
import { spawn as spawn7 } from "node:child_process";
|
|
25089
25417
|
import * as fsp3 from "node:fs/promises";
|
|
25090
25418
|
import * as path18 from "node:path";
|
|
25091
25419
|
import { emitReviewIfChanged } from "@wrongstack/core/plugin";
|
|
25092
25420
|
async function runGit2(args, cwd) {
|
|
25093
25421
|
return new Promise((resolve8) => {
|
|
25094
|
-
const child =
|
|
25422
|
+
const child = spawn7("git", args, {
|
|
25095
25423
|
cwd,
|
|
25096
25424
|
stdio: ["ignore", "pipe", "pipe"],
|
|
25097
25425
|
signal: AbortSignal.timeout(1e4),
|
|
@@ -25288,11 +25616,15 @@ function buildSecurityCommand(opts) {
|
|
|
25288
25616
|
}
|
|
25289
25617
|
|
|
25290
25618
|
// src/slash-commands/settings.ts
|
|
25291
|
-
import { color as
|
|
25619
|
+
import { color as color56 } from "@wrongstack/core/utils";
|
|
25292
25620
|
|
|
25293
25621
|
// src/slash-commands/settings-mutations.ts
|
|
25294
|
-
import { noOpVault as
|
|
25295
|
-
import {
|
|
25622
|
+
import { noOpVault as noOpVault10 } from "@wrongstack/core/security";
|
|
25623
|
+
import {
|
|
25624
|
+
isReasoningEffort as isReasoningEffort3,
|
|
25625
|
+
REASONING_EFFORT_LEVELS as REASONING_EFFORT_LEVELS3
|
|
25626
|
+
} from "@wrongstack/core/types";
|
|
25627
|
+
import { color as color54, toErrorMessage as toErrorMessage23 } from "@wrongstack/core/utils";
|
|
25296
25628
|
import { getProcessRegistry } from "@wrongstack/tools";
|
|
25297
25629
|
|
|
25298
25630
|
// src/utils/delay-format.ts
|
|
@@ -25355,13 +25687,13 @@ async function executeSettingsSubcommand(sub, rest, opts) {
|
|
|
25355
25687
|
configStore: opts.configStore,
|
|
25356
25688
|
profileConfigPath: opts.paths.profileConfig(activeProfile),
|
|
25357
25689
|
inProjectConfigPath: opts.paths.inProjectConfig,
|
|
25358
|
-
vault:
|
|
25690
|
+
vault: noOpVault10
|
|
25359
25691
|
};
|
|
25360
25692
|
try {
|
|
25361
25693
|
if (sub === "hq") {
|
|
25362
25694
|
const raw = (rest[0] ?? "").toLowerCase();
|
|
25363
25695
|
if (!["on", "off"].includes(raw)) {
|
|
25364
|
-
return { message: `${
|
|
25696
|
+
return { message: `${color54.amber("Usage:")} /settings hq on|off` };
|
|
25365
25697
|
}
|
|
25366
25698
|
const on = raw === "on";
|
|
25367
25699
|
await persistConfigSetting({ ...persistDeps, forceGlobal: true }, (cfg) => {
|
|
@@ -25370,19 +25702,19 @@ async function executeSettingsSubcommand(sub, rest, opts) {
|
|
|
25370
25702
|
cfg.hq = hq;
|
|
25371
25703
|
});
|
|
25372
25704
|
return {
|
|
25373
|
-
message: `${
|
|
25705
|
+
message: `${color54.green("\u2713")} HQ publishing \u2192 ${on ? color54.cyan("on") : color54.dim("off")}`
|
|
25374
25706
|
};
|
|
25375
25707
|
}
|
|
25376
25708
|
if (sub === "hq-url") {
|
|
25377
25709
|
const raw = rest.join(" ").trim();
|
|
25378
25710
|
if (!raw)
|
|
25379
|
-
return { message: `${
|
|
25711
|
+
return { message: `${color54.amber("Usage:")} /settings hq-url <http://host:3499>` };
|
|
25380
25712
|
try {
|
|
25381
25713
|
const url = new URL(raw);
|
|
25382
25714
|
if (url.protocol !== "http:" && url.protocol !== "https:")
|
|
25383
25715
|
throw new Error("bad protocol");
|
|
25384
25716
|
} catch {
|
|
25385
|
-
return { message: `${
|
|
25717
|
+
return { message: `${color54.red("Invalid URL")}: ${raw}` };
|
|
25386
25718
|
}
|
|
25387
25719
|
await persistConfigSetting({ ...persistDeps, forceGlobal: true }, (cfg) => {
|
|
25388
25720
|
const hq = cfg.hq ?? {};
|
|
@@ -25390,12 +25722,12 @@ async function executeSettingsSubcommand(sub, rest, opts) {
|
|
|
25390
25722
|
hq.enabled = true;
|
|
25391
25723
|
cfg.hq = hq;
|
|
25392
25724
|
});
|
|
25393
|
-
return { message: `${
|
|
25725
|
+
return { message: `${color54.green("\u2713")} HQ URL \u2192 ${color54.cyan(raw)}` };
|
|
25394
25726
|
}
|
|
25395
25727
|
if (sub === "hq-token") {
|
|
25396
25728
|
const token = rest.join(" ").trim();
|
|
25397
25729
|
if (!token)
|
|
25398
|
-
return { message: `${
|
|
25730
|
+
return { message: `${color54.amber("Usage:")} /settings hq-token <client-token>` };
|
|
25399
25731
|
await persistConfigSetting({ ...persistDeps, forceGlobal: true }, (cfg) => {
|
|
25400
25732
|
const hq = cfg.hq ?? {};
|
|
25401
25733
|
hq.token = token;
|
|
@@ -25403,13 +25735,13 @@ async function executeSettingsSubcommand(sub, rest, opts) {
|
|
|
25403
25735
|
cfg.hq = hq;
|
|
25404
25736
|
});
|
|
25405
25737
|
return {
|
|
25406
|
-
message: `${
|
|
25738
|
+
message: `${color54.green("\u2713")} HQ token saved ${color54.dim("(active profile config)")}`
|
|
25407
25739
|
};
|
|
25408
25740
|
}
|
|
25409
25741
|
if (sub === "hq-raw") {
|
|
25410
25742
|
const raw = (rest[0] ?? "").toLowerCase();
|
|
25411
25743
|
if (!["on", "off"].includes(raw)) {
|
|
25412
|
-
return { message: `${
|
|
25744
|
+
return { message: `${color54.amber("Usage:")} /settings hq-raw on|off` };
|
|
25413
25745
|
}
|
|
25414
25746
|
const on = raw === "on";
|
|
25415
25747
|
await persistConfigSetting({ ...persistDeps, forceGlobal: true }, (cfg) => {
|
|
@@ -25418,56 +25750,56 @@ async function executeSettingsSubcommand(sub, rest, opts) {
|
|
|
25418
25750
|
cfg.hq = hq;
|
|
25419
25751
|
});
|
|
25420
25752
|
return {
|
|
25421
|
-
message: `${
|
|
25753
|
+
message: `${color54.green("\u2713")} HQ raw content \u2192 ${on ? color54.cyan("on") : color54.dim("off")}`
|
|
25422
25754
|
};
|
|
25423
25755
|
}
|
|
25424
25756
|
if (sub === "delay") {
|
|
25425
25757
|
const raw = rest[0];
|
|
25426
25758
|
if (raw === void 0) {
|
|
25427
25759
|
return {
|
|
25428
|
-
message: `${
|
|
25760
|
+
message: `${color54.amber("Usage:")} /settings delay <seconds> ${color54.dim("(0 disables)")}`
|
|
25429
25761
|
};
|
|
25430
25762
|
}
|
|
25431
25763
|
const seconds = Number.parseFloat(raw);
|
|
25432
25764
|
if (Number.isNaN(seconds) || seconds < 0) {
|
|
25433
25765
|
return {
|
|
25434
|
-
message: `${
|
|
25766
|
+
message: `${color54.red("Invalid number")}: "${raw}". Enter seconds, e.g. /settings delay 30`
|
|
25435
25767
|
};
|
|
25436
25768
|
}
|
|
25437
25769
|
const ms = Math.round(seconds * 1e3);
|
|
25438
25770
|
await persistAutonomySetting(persistDeps, (autonomy) => {
|
|
25439
25771
|
autonomy.autoProceedDelayMs = ms;
|
|
25440
25772
|
});
|
|
25441
|
-
return { message: `${
|
|
25773
|
+
return { message: `${color54.green("\u2713")} auto-proceed delay \u2192 ${formatDelay(ms)}` };
|
|
25442
25774
|
}
|
|
25443
25775
|
if (sub === "mode") {
|
|
25444
25776
|
const raw = (rest[0] ?? "").toLowerCase();
|
|
25445
25777
|
const modes = ["off", "suggest", "auto"];
|
|
25446
25778
|
if (!modes.includes(raw)) {
|
|
25447
|
-
return { message: `${
|
|
25779
|
+
return { message: `${color54.amber("Usage:")} /settings mode off|suggest|auto` };
|
|
25448
25780
|
}
|
|
25449
25781
|
await persistAutonomySetting(persistDeps, (autonomy) => {
|
|
25450
25782
|
autonomy.defaultMode = raw;
|
|
25451
25783
|
});
|
|
25452
|
-
return { message: `${
|
|
25784
|
+
return { message: `${color54.green("\u2713")} default autonomy \u2192 ${color54.bold(raw)}` };
|
|
25453
25785
|
}
|
|
25454
25786
|
if (sub === "hints") {
|
|
25455
25787
|
const raw = (rest[0] ?? "").toLowerCase();
|
|
25456
25788
|
if (!["on", "off"].includes(raw)) {
|
|
25457
|
-
return { message: `${
|
|
25789
|
+
return { message: `${color54.amber("Usage:")} /settings hints on|off` };
|
|
25458
25790
|
}
|
|
25459
25791
|
const on = raw === "on";
|
|
25460
25792
|
await persistConfigSetting(persistDeps, (cfg) => {
|
|
25461
25793
|
cfg.hints = on;
|
|
25462
25794
|
});
|
|
25463
25795
|
return {
|
|
25464
|
-
message: `${
|
|
25796
|
+
message: `${color54.green("\u2713")} launch hints \u2192 ${on ? color54.cyan("on") : color54.dim("off")}`
|
|
25465
25797
|
};
|
|
25466
25798
|
}
|
|
25467
25799
|
if (sub === "debug-stream") {
|
|
25468
25800
|
const raw = (rest[0] ?? "").toLowerCase();
|
|
25469
25801
|
if (!["on", "off"].includes(raw)) {
|
|
25470
|
-
return { message: `${
|
|
25802
|
+
return { message: `${color54.amber("Usage:")} /settings debug-stream on|off` };
|
|
25471
25803
|
}
|
|
25472
25804
|
const on = raw === "on";
|
|
25473
25805
|
const { setDebugStreamEnabled } = await import("@wrongstack/providers");
|
|
@@ -25476,24 +25808,24 @@ async function executeSettingsSubcommand(sub, rest, opts) {
|
|
|
25476
25808
|
cfg.debugStream = on;
|
|
25477
25809
|
});
|
|
25478
25810
|
return {
|
|
25479
|
-
message: `${
|
|
25811
|
+
message: `${color54.green("\u2713")} debug stream \u2192 ${on ? color54.cyan("on") : color54.dim("off")} ${color54.dim("raw SSE hex-dump to stderr")}`
|
|
25480
25812
|
};
|
|
25481
25813
|
}
|
|
25482
25814
|
if (sub === "config-scope") {
|
|
25483
25815
|
const raw = (rest[0] ?? "").toLowerCase();
|
|
25484
25816
|
if (!["global", "project"].includes(raw)) {
|
|
25485
|
-
return { message: `${
|
|
25817
|
+
return { message: `${color54.amber("Usage:")} /settings config-scope global|project` };
|
|
25486
25818
|
}
|
|
25487
25819
|
await persistConfigSetting(persistDeps, (cfg) => {
|
|
25488
25820
|
cfg.configScope = raw;
|
|
25489
25821
|
});
|
|
25490
|
-
const label = raw === "project" ? `${
|
|
25491
|
-
return { message: `${
|
|
25822
|
+
const label = raw === "project" ? `${color54.cyan("project")} \u2014 settings saved to <project>/.wrongstack/config.json` : `${color54.cyan("global")} \u2014 settings saved to ~/.wrongstack/profiles/${activeProfile}/config.json`;
|
|
25823
|
+
return { message: `${color54.green("\u2713")} config scope \u2192 ${label}` };
|
|
25492
25824
|
}
|
|
25493
25825
|
if (sub === "fs-access") {
|
|
25494
25826
|
const raw = (rest[0] ?? "").toLowerCase();
|
|
25495
25827
|
if (!["unrestricted", "project"].includes(raw)) {
|
|
25496
|
-
return { message: `${
|
|
25828
|
+
return { message: `${color54.amber("Usage:")} /settings fs-access unrestricted|project` };
|
|
25497
25829
|
}
|
|
25498
25830
|
const restrict = raw === "project";
|
|
25499
25831
|
const fsAccess = deriveFsAccessPair({ restrictFsToRoot: restrict });
|
|
@@ -25505,15 +25837,15 @@ async function executeSettingsSubcommand(sub, rest, opts) {
|
|
|
25505
25837
|
features.allowOutsideProjectRoot = fsAccess.allowOutsideProjectRoot;
|
|
25506
25838
|
cfg.features = features;
|
|
25507
25839
|
});
|
|
25508
|
-
const label = restrict ? `${
|
|
25840
|
+
const label = restrict ? `${color54.cyan("project")} \u2014 file tools confined to the project root` : `${color54.cyan("unrestricted")} \u2014 file tools may access paths outside the project root`;
|
|
25509
25841
|
return {
|
|
25510
|
-
message: `${
|
|
25842
|
+
message: `${color54.green("\u2713")} filesystem access \u2192 ${label} ${color54.dim("(restart or re-open the session to apply)")}`
|
|
25511
25843
|
};
|
|
25512
25844
|
}
|
|
25513
25845
|
if (sub === "refine") {
|
|
25514
25846
|
const raw = (rest[0] ?? "").toLowerCase();
|
|
25515
25847
|
if (!["on", "off"].includes(raw)) {
|
|
25516
|
-
return { message: `${
|
|
25848
|
+
return { message: `${color54.amber("Usage:")} /settings refine on|off` };
|
|
25517
25849
|
}
|
|
25518
25850
|
const on = raw === "on";
|
|
25519
25851
|
await persistAutonomySetting(persistDeps, (autonomy) => {
|
|
@@ -25523,52 +25855,52 @@ async function executeSettingsSubcommand(sub, rest, opts) {
|
|
|
25523
25855
|
opts.enhanceController.setEnabled(on);
|
|
25524
25856
|
}
|
|
25525
25857
|
return {
|
|
25526
|
-
message: `${
|
|
25858
|
+
message: `${color54.green("\u2713")} refine \u2192 ${on ? color54.cyan("on") : color54.dim("off")} ${color54.dim(on ? "prompts will be refined before sending" : "prompts sent verbatim")}`
|
|
25527
25859
|
};
|
|
25528
25860
|
}
|
|
25529
25861
|
if (sub === "refine-delay") {
|
|
25530
25862
|
const raw = rest[0];
|
|
25531
25863
|
if (raw === void 0) {
|
|
25532
|
-
return { message: `${
|
|
25864
|
+
return { message: `${color54.amber("Usage:")} /settings refine-delay <seconds>` };
|
|
25533
25865
|
}
|
|
25534
25866
|
const seconds = Number.parseFloat(raw);
|
|
25535
25867
|
if (Number.isNaN(seconds) || seconds < 0) {
|
|
25536
25868
|
return {
|
|
25537
|
-
message: `${
|
|
25869
|
+
message: `${color54.red("Invalid number")}: "${raw}". Enter seconds, e.g. /settings refine-delay 30`
|
|
25538
25870
|
};
|
|
25539
25871
|
}
|
|
25540
25872
|
const ms = Math.round(seconds * 1e3);
|
|
25541
25873
|
await persistAutonomySetting(persistDeps, (autonomy) => {
|
|
25542
25874
|
autonomy.enhanceDelayMs = ms;
|
|
25543
25875
|
});
|
|
25544
|
-
return { message: `${
|
|
25876
|
+
return { message: `${color54.green("\u2713")} refine-delay \u2192 ${formatDelay(ms)}` };
|
|
25545
25877
|
}
|
|
25546
25878
|
if (sub === "refine-language") {
|
|
25547
25879
|
const raw = (rest[0] ?? "").toLowerCase();
|
|
25548
25880
|
if (!["original", "english"].includes(raw)) {
|
|
25549
25881
|
return {
|
|
25550
|
-
message: `${
|
|
25882
|
+
message: `${color54.amber("Usage:")} /settings refine-language original|english`
|
|
25551
25883
|
};
|
|
25552
25884
|
}
|
|
25553
25885
|
await persistAutonomySetting(persistDeps, (autonomy) => {
|
|
25554
25886
|
autonomy.enhanceLanguage = raw;
|
|
25555
25887
|
});
|
|
25556
|
-
const label = raw === "original" ? `${
|
|
25557
|
-
return { message: `${
|
|
25888
|
+
const label = raw === "original" ? `${color54.cyan("original")} \u2014 use the language you wrote in` : `${color54.cyan("english")} \u2014 translate to English`;
|
|
25889
|
+
return { message: `${color54.green("\u2713")} refine-language \u2192 ${label}` };
|
|
25558
25890
|
}
|
|
25559
25891
|
if (sub === "refiner-provider") {
|
|
25560
25892
|
const raw = rest.join(" ").trim();
|
|
25561
25893
|
const currentProvider = opts.configStore.get().autonomy?.refinerProvider;
|
|
25562
25894
|
if (!raw) {
|
|
25563
25895
|
return {
|
|
25564
|
-
message: `${
|
|
25896
|
+
message: `${color54.amber("Usage:")} /settings refiner-provider <providerId> ${color54.dim('(e.g. "openai", "anthropic")' + (currentProvider ? ` Current: ${currentProvider}` : ""))}`
|
|
25565
25897
|
};
|
|
25566
25898
|
}
|
|
25567
25899
|
await persistAutonomySetting(persistDeps, (autonomy) => {
|
|
25568
25900
|
autonomy.refinerProvider = raw;
|
|
25569
25901
|
});
|
|
25570
25902
|
return {
|
|
25571
|
-
message: `${
|
|
25903
|
+
message: `${color54.green("\u2713")} refiner-provider \u2192 ${color54.cyan(raw)} ${color54.dim("goal refinement will use this provider when refiner-model is also set")}`
|
|
25572
25904
|
};
|
|
25573
25905
|
}
|
|
25574
25906
|
if (sub === "refiner-model") {
|
|
@@ -25576,14 +25908,14 @@ async function executeSettingsSubcommand(sub, rest, opts) {
|
|
|
25576
25908
|
const currentModel = opts.configStore.get().autonomy?.refinerModel;
|
|
25577
25909
|
if (!raw) {
|
|
25578
25910
|
return {
|
|
25579
|
-
message: `${
|
|
25911
|
+
message: `${color54.amber("Usage:")} /settings refiner-model <modelId> ${color54.dim('(must be a favorite or the active model; e.g. "gpt-4o-mini")' + (currentModel ? ` Current: ${currentModel}` : ""))}`
|
|
25580
25912
|
};
|
|
25581
25913
|
}
|
|
25582
25914
|
await persistAutonomySetting(persistDeps, (autonomy) => {
|
|
25583
25915
|
autonomy.refinerModel = raw;
|
|
25584
25916
|
});
|
|
25585
25917
|
return {
|
|
25586
|
-
message: `${
|
|
25918
|
+
message: `${color54.green("\u2713")} refiner-model \u2192 ${color54.cyan(raw)} ${color54.dim("goal refinement will use this model when it passes favorites/active validation")}`
|
|
25587
25919
|
};
|
|
25588
25920
|
}
|
|
25589
25921
|
if (sub === "refiner-fallback-profile") {
|
|
@@ -25591,14 +25923,14 @@ async function executeSettingsSubcommand(sub, rest, opts) {
|
|
|
25591
25923
|
const currentProfile = opts.configStore.get().autonomy?.refinerFallbackProfile;
|
|
25592
25924
|
if (!raw) {
|
|
25593
25925
|
return {
|
|
25594
|
-
message: `${
|
|
25926
|
+
message: `${color54.amber("Usage:")} /settings refiner-fallback-profile <name> ${color54.dim('(e.g. "default")' + (currentProfile ? ` Current: ${currentProfile}` : ""))}`
|
|
25595
25927
|
};
|
|
25596
25928
|
}
|
|
25597
25929
|
await persistAutonomySetting(persistDeps, (autonomy) => {
|
|
25598
25930
|
autonomy.refinerFallbackProfile = raw;
|
|
25599
25931
|
});
|
|
25600
25932
|
return {
|
|
25601
|
-
message: `${
|
|
25933
|
+
message: `${color54.green("\u2713")} refiner-fallback-profile \u2192 ${color54.cyan(raw)} ${color54.dim("goal refinement will use the first valid entry from this profile chain")}`
|
|
25602
25934
|
};
|
|
25603
25935
|
}
|
|
25604
25936
|
if (sub === "refiner-clear") {
|
|
@@ -25608,7 +25940,7 @@ async function executeSettingsSubcommand(sub, rest, opts) {
|
|
|
25608
25940
|
autonomy.refinerFallbackProfile = void 0;
|
|
25609
25941
|
});
|
|
25610
25942
|
return {
|
|
25611
|
-
message: `${
|
|
25943
|
+
message: `${color54.green("\u2713")} Refiner config cleared ${color54.dim("goal refinement will use the session provider+model")}`
|
|
25612
25944
|
};
|
|
25613
25945
|
}
|
|
25614
25946
|
if (sub === "semver-part") {
|
|
@@ -25616,7 +25948,7 @@ async function executeSettingsSubcommand(sub, rest, opts) {
|
|
|
25616
25948
|
const parts = ["patch", "minor", "major", "auto"];
|
|
25617
25949
|
if (!parts.includes(raw)) {
|
|
25618
25950
|
return {
|
|
25619
|
-
message: `${
|
|
25951
|
+
message: `${color54.amber("Usage:")} /settings semver-part patch|minor|major|auto`
|
|
25620
25952
|
};
|
|
25621
25953
|
}
|
|
25622
25954
|
await persistConfigSetting({ ...persistDeps, inProjectConfigPath: void 0 }, (cfg) => {
|
|
@@ -25625,13 +25957,13 @@ async function executeSettingsSubcommand(sub, rest, opts) {
|
|
|
25625
25957
|
cfg.extensions = ext;
|
|
25626
25958
|
});
|
|
25627
25959
|
return {
|
|
25628
|
-
message: `${
|
|
25960
|
+
message: `${color54.green("\u2713")} semver default part \u2192 ${color54.bold(raw)} ${color54.dim("saved to active profile config; used when /semver or semver_bump gets no explicit part")}`
|
|
25629
25961
|
};
|
|
25630
25962
|
}
|
|
25631
25963
|
if (sub === "breaker") {
|
|
25632
25964
|
const raw = (rest[0] ?? "").toLowerCase();
|
|
25633
25965
|
if (!["on", "off"].includes(raw)) {
|
|
25634
|
-
return { message: `${
|
|
25966
|
+
return { message: `${color54.amber("Usage:")} /settings breaker on|off` };
|
|
25635
25967
|
}
|
|
25636
25968
|
const on = raw === "on";
|
|
25637
25969
|
await persistConfigSetting(persistDeps, (cfg) => {
|
|
@@ -25640,20 +25972,20 @@ async function executeSettingsSubcommand(sub, rest, opts) {
|
|
|
25640
25972
|
});
|
|
25641
25973
|
getProcessRegistry().setBreakerConfig({ enabled: on });
|
|
25642
25974
|
return {
|
|
25643
|
-
message: `${
|
|
25975
|
+
message: `${color54.green("\u2713")} circuit breaker \u2192 ${on ? color54.cyan("on") : color54.dim("off")} ${color54.dim(on ? "bash/exec gated on repeated failures; trips arm the kill/reset countdown" : "bash/exec always proceed")}`
|
|
25644
25976
|
};
|
|
25645
25977
|
}
|
|
25646
25978
|
if (sub === "breaker-timeout") {
|
|
25647
25979
|
const raw = rest[0];
|
|
25648
25980
|
if (raw === void 0) {
|
|
25649
25981
|
return {
|
|
25650
|
-
message: `${
|
|
25982
|
+
message: `${color54.amber("Usage:")} /settings breaker-timeout <seconds> ${color54.dim("(0 = manual recovery only)")}`
|
|
25651
25983
|
};
|
|
25652
25984
|
}
|
|
25653
25985
|
const seconds = Number.parseFloat(raw);
|
|
25654
25986
|
if (Number.isNaN(seconds) || seconds < 0) {
|
|
25655
25987
|
return {
|
|
25656
|
-
message: `${
|
|
25988
|
+
message: `${color54.red("Invalid number")}: "${raw}". Enter seconds, e.g. /settings breaker-timeout 60`
|
|
25657
25989
|
};
|
|
25658
25990
|
}
|
|
25659
25991
|
const ms = Math.round(seconds * 1e3);
|
|
@@ -25666,7 +25998,7 @@ async function executeSettingsSubcommand(sub, rest, opts) {
|
|
|
25666
25998
|
});
|
|
25667
25999
|
getProcessRegistry().setBreakerConfig({ autoKillResetMs: ms });
|
|
25668
26000
|
return {
|
|
25669
|
-
message: `${
|
|
26001
|
+
message: `${color54.green("\u2713")} breaker kill/reset timeout \u2192 ${ms > 0 ? formatDelay(ms) : color54.dim("manual")} ${color54.dim(ms > 0 ? "statusline shows a countdown when the breaker trips" : "breaker trips require /kill reset")}`
|
|
25670
26002
|
};
|
|
25671
26003
|
}
|
|
25672
26004
|
if (sub === "context-mode") {
|
|
@@ -25674,7 +26006,7 @@ async function executeSettingsSubcommand(sub, rest, opts) {
|
|
|
25674
26006
|
const modes = ["balanced", "frugal", "deep"];
|
|
25675
26007
|
if (!modes.includes(raw)) {
|
|
25676
26008
|
return {
|
|
25677
|
-
message: `${
|
|
26009
|
+
message: `${color54.amber("Usage:")} /settings context-mode balanced|frugal|deep`
|
|
25678
26010
|
};
|
|
25679
26011
|
}
|
|
25680
26012
|
await persistConfigSetting(persistDeps, (cfg) => {
|
|
@@ -25683,7 +26015,7 @@ async function executeSettingsSubcommand(sub, rest, opts) {
|
|
|
25683
26015
|
cfg.context = ctx;
|
|
25684
26016
|
});
|
|
25685
26017
|
return {
|
|
25686
|
-
message: `${
|
|
26018
|
+
message: `${color54.green("\u2713")} context mode \u2192 ${color54.cyan(raw)} ${color54.dim("context window policy")}`
|
|
25687
26019
|
};
|
|
25688
26020
|
}
|
|
25689
26021
|
if (sub === "context-strategy") {
|
|
@@ -25691,7 +26023,7 @@ async function executeSettingsSubcommand(sub, rest, opts) {
|
|
|
25691
26023
|
const strategies = ["hybrid", "intelligent", "selective"];
|
|
25692
26024
|
if (!strategies.includes(raw)) {
|
|
25693
26025
|
return {
|
|
25694
|
-
message: `${
|
|
26026
|
+
message: `${color54.amber("Usage:")} /settings context-strategy hybrid|intelligent|selective`
|
|
25695
26027
|
};
|
|
25696
26028
|
}
|
|
25697
26029
|
await persistConfigSetting(persistDeps, (cfg) => {
|
|
@@ -25700,13 +26032,13 @@ async function executeSettingsSubcommand(sub, rest, opts) {
|
|
|
25700
26032
|
cfg.context = ctx;
|
|
25701
26033
|
});
|
|
25702
26034
|
return {
|
|
25703
|
-
message: `${
|
|
26035
|
+
message: `${color54.green("\u2713")} context strategy \u2192 ${color54.cyan(raw)} ${color54.dim("compactor strategy")}`
|
|
25704
26036
|
};
|
|
25705
26037
|
}
|
|
25706
26038
|
if (sub === "context-auto-compact") {
|
|
25707
26039
|
const raw = (rest[0] ?? "").toLowerCase();
|
|
25708
26040
|
if (!["on", "off"].includes(raw)) {
|
|
25709
|
-
return { message: `${
|
|
26041
|
+
return { message: `${color54.amber("Usage:")} /settings context-auto-compact on|off` };
|
|
25710
26042
|
}
|
|
25711
26043
|
const on = raw === "on";
|
|
25712
26044
|
await persistConfigSetting(persistDeps, (cfg) => {
|
|
@@ -25715,13 +26047,13 @@ async function executeSettingsSubcommand(sub, rest, opts) {
|
|
|
25715
26047
|
cfg.context = ctx;
|
|
25716
26048
|
});
|
|
25717
26049
|
return {
|
|
25718
|
-
message: `${
|
|
26050
|
+
message: `${color54.green("\u2713")} context auto-compact \u2192 ${on ? color54.cyan("on") : color54.dim("off")} ${color54.dim("auto-compact context when thresholds crossed")}`
|
|
25719
26051
|
};
|
|
25720
26052
|
}
|
|
25721
26053
|
if (sub === "nextsteps-tool") {
|
|
25722
26054
|
const raw = (rest[0] ?? "").toLowerCase();
|
|
25723
26055
|
if (!["on", "off"].includes(raw)) {
|
|
25724
|
-
return { message: `${
|
|
26056
|
+
return { message: `${color54.amber("Usage:")} /settings nextsteps-tool on|off` };
|
|
25725
26057
|
}
|
|
25726
26058
|
const on = raw === "on";
|
|
25727
26059
|
await persistConfigSetting(persistDeps, (cfg) => {
|
|
@@ -25730,7 +26062,7 @@ async function executeSettingsSubcommand(sub, rest, opts) {
|
|
|
25730
26062
|
cfg.tools = tools;
|
|
25731
26063
|
});
|
|
25732
26064
|
return {
|
|
25733
|
-
message: `${
|
|
26065
|
+
message: `${color54.green("\u2713")} nextsteps tool \u2192 ${on ? color54.cyan("on") : color54.dim("off")} ${color54.dim("takes effect in the next session")}`
|
|
25734
26066
|
};
|
|
25735
26067
|
}
|
|
25736
26068
|
if (sub === "token-saving") {
|
|
@@ -25738,7 +26070,7 @@ async function executeSettingsSubcommand(sub, rest, opts) {
|
|
|
25738
26070
|
const tiers = ["off", "minimal", "light", "medium", "aggressive"];
|
|
25739
26071
|
if (!tiers.includes(raw)) {
|
|
25740
26072
|
return {
|
|
25741
|
-
message: `${
|
|
26073
|
+
message: `${color54.amber("Usage:")} /settings token-saving off|minimal|light|medium|aggressive`
|
|
25742
26074
|
};
|
|
25743
26075
|
}
|
|
25744
26076
|
await persistConfigSetting(persistDeps, (cfg) => {
|
|
@@ -25747,47 +26079,47 @@ async function executeSettingsSubcommand(sub, rest, opts) {
|
|
|
25747
26079
|
cfg.features = feat;
|
|
25748
26080
|
});
|
|
25749
26081
|
return {
|
|
25750
|
-
message: `${
|
|
26082
|
+
message: `${color54.green("\u2713")} token-saving \u2192 ${color54.cyan(raw)} ${color54.dim("token-saving mode")}`
|
|
25751
26083
|
};
|
|
25752
26084
|
}
|
|
25753
26085
|
if (sub === "max-concurrent") {
|
|
25754
26086
|
const raw = rest[0];
|
|
25755
26087
|
if (raw === void 0) {
|
|
25756
26088
|
return {
|
|
25757
|
-
message: `${
|
|
26089
|
+
message: `${color54.amber("Usage:")} /settings max-concurrent <n> ${color54.dim("(0 = default)")}`
|
|
25758
26090
|
};
|
|
25759
26091
|
}
|
|
25760
26092
|
const n = Number.parseInt(raw, 10);
|
|
25761
26093
|
if (Number.isNaN(n) || n < 0) {
|
|
25762
26094
|
return {
|
|
25763
|
-
message: `${
|
|
26095
|
+
message: `${color54.red("Invalid number")}: "${raw}". Enter a non-negative integer (0 = default)`
|
|
25764
26096
|
};
|
|
25765
26097
|
}
|
|
25766
26098
|
await persistConfigSetting(persistDeps, (cfg) => {
|
|
25767
26099
|
cfg.maxConcurrent = n;
|
|
25768
26100
|
});
|
|
25769
26101
|
return {
|
|
25770
|
-
message: `${
|
|
26102
|
+
message: `${color54.green("\u2713")} max-concurrent \u2192 ${color54.cyan(n === 0 ? "default" : String(n))} ${color54.dim("max concurrent subagents")}`
|
|
25771
26103
|
};
|
|
25772
26104
|
}
|
|
25773
26105
|
if (sub === "title-animation") {
|
|
25774
26106
|
const raw = (rest[0] ?? "").toLowerCase();
|
|
25775
26107
|
if (!["on", "off"].includes(raw)) {
|
|
25776
|
-
return { message: `${
|
|
26108
|
+
return { message: `${color54.amber("Usage:")} /settings title-animation on|off` };
|
|
25777
26109
|
}
|
|
25778
26110
|
const on = raw === "on";
|
|
25779
26111
|
await persistAutonomySetting(persistDeps, (autonomy) => {
|
|
25780
26112
|
autonomy.terminalTitleAnimation = on;
|
|
25781
26113
|
});
|
|
25782
26114
|
return {
|
|
25783
|
-
message: `${
|
|
26115
|
+
message: `${color54.green("\u2713")} title animation \u2192 ${on ? color54.cyan("on") : color54.dim("off")} ${color54.dim("terminal title animation")}`
|
|
25784
26116
|
};
|
|
25785
26117
|
}
|
|
25786
26118
|
if (sub === "reasoning") {
|
|
25787
26119
|
const raw = (rest[0] ?? "").toLowerCase();
|
|
25788
26120
|
const modes = ["auto", "on", "off"];
|
|
25789
26121
|
if (!modes.includes(raw)) {
|
|
25790
|
-
return { message: `${
|
|
26122
|
+
return { message: `${color54.amber("Usage:")} /settings reasoning auto|on|off` };
|
|
25791
26123
|
}
|
|
25792
26124
|
await persistConfigSetting(persistDeps, (cfg) => {
|
|
25793
26125
|
const mr = cfg.modelRuntime;
|
|
@@ -25795,14 +26127,13 @@ async function executeSettingsSubcommand(sub, rest, opts) {
|
|
|
25795
26127
|
reasoning.mode = raw;
|
|
25796
26128
|
cfg.modelRuntime = { ...mr, reasoning };
|
|
25797
26129
|
});
|
|
25798
|
-
return { message: `${
|
|
26130
|
+
return { message: `${color54.green("\u2713")} reasoning mode \u2192 ${color54.bold(raw)}` };
|
|
25799
26131
|
}
|
|
25800
26132
|
if (sub === "reasoning-effort") {
|
|
25801
26133
|
const raw = (rest[0] ?? "").toLowerCase();
|
|
25802
|
-
|
|
25803
|
-
if (!efforts.includes(raw)) {
|
|
26134
|
+
if (!isReasoningEffort3(raw)) {
|
|
25804
26135
|
return {
|
|
25805
|
-
message: `${
|
|
26136
|
+
message: `${color54.amber("Usage:")} /settings reasoning-effort ${REASONING_EFFORT_LEVELS3.join("|")}`
|
|
25806
26137
|
};
|
|
25807
26138
|
}
|
|
25808
26139
|
await persistConfigSetting(persistDeps, (cfg) => {
|
|
@@ -25811,12 +26142,12 @@ async function executeSettingsSubcommand(sub, rest, opts) {
|
|
|
25811
26142
|
reasoning.effort = raw;
|
|
25812
26143
|
cfg.modelRuntime = { ...mr, reasoning };
|
|
25813
26144
|
});
|
|
25814
|
-
return { message: `${
|
|
26145
|
+
return { message: `${color54.green("\u2713")} reasoning effort \u2192 ${color54.bold(raw)}` };
|
|
25815
26146
|
}
|
|
25816
26147
|
if (sub === "reasoning-preserve") {
|
|
25817
26148
|
const raw = (rest[0] ?? "").toLowerCase();
|
|
25818
26149
|
if (!["on", "off"].includes(raw)) {
|
|
25819
|
-
return { message: `${
|
|
26150
|
+
return { message: `${color54.amber("Usage:")} /settings reasoning-preserve on|off` };
|
|
25820
26151
|
}
|
|
25821
26152
|
const on = raw === "on";
|
|
25822
26153
|
await persistConfigSetting(persistDeps, (cfg) => {
|
|
@@ -25826,24 +26157,24 @@ async function executeSettingsSubcommand(sub, rest, opts) {
|
|
|
25826
26157
|
cfg.modelRuntime = { ...mr, reasoning };
|
|
25827
26158
|
});
|
|
25828
26159
|
return {
|
|
25829
|
-
message: `${
|
|
26160
|
+
message: `${color54.green("\u2713")} reasoning preserve \u2192 ${on ? color54.cyan("on") : color54.dim("off")}`
|
|
25830
26161
|
};
|
|
25831
26162
|
}
|
|
25832
26163
|
if (sub === "cache-ttl") {
|
|
25833
26164
|
const raw = (rest[0] ?? "").toLowerCase();
|
|
25834
26165
|
if (!["5m", "1h"].includes(raw)) {
|
|
25835
|
-
return { message: `${
|
|
26166
|
+
return { message: `${color54.amber("Usage:")} /settings cache-ttl 5m|1h` };
|
|
25836
26167
|
}
|
|
25837
26168
|
await persistConfigSetting(persistDeps, (cfg) => {
|
|
25838
26169
|
const mr = cfg.modelRuntime;
|
|
25839
26170
|
cfg.modelRuntime = { ...mr, cache: { ttl: raw } };
|
|
25840
26171
|
});
|
|
25841
|
-
return { message: `${
|
|
26172
|
+
return { message: `${color54.green("\u2713")} cache TTL \u2192 ${color54.bold(raw)}` };
|
|
25842
26173
|
}
|
|
25843
26174
|
if (sub === "mcp") {
|
|
25844
26175
|
const raw = (rest[0] ?? "").toLowerCase();
|
|
25845
26176
|
if (!["on", "off"].includes(raw))
|
|
25846
|
-
return { message: `${
|
|
26177
|
+
return { message: `${color54.amber("Usage:")} /settings mcp on|off` };
|
|
25847
26178
|
const on = raw === "on";
|
|
25848
26179
|
await persistConfigSetting(persistDeps, (cfg) => {
|
|
25849
26180
|
const feats = cfg.features ?? {};
|
|
@@ -25851,13 +26182,13 @@ async function executeSettingsSubcommand(sub, rest, opts) {
|
|
|
25851
26182
|
cfg.features = feats;
|
|
25852
26183
|
});
|
|
25853
26184
|
return {
|
|
25854
|
-
message: `${
|
|
26185
|
+
message: `${color54.green("\u2713")} MCP features \u2192 ${on ? color54.cyan("on") : color54.dim("off")} ${color54.dim("restart to apply")}`
|
|
25855
26186
|
};
|
|
25856
26187
|
}
|
|
25857
26188
|
if (sub === "plugins") {
|
|
25858
26189
|
const raw = (rest[0] ?? "").toLowerCase();
|
|
25859
26190
|
if (!["on", "off"].includes(raw))
|
|
25860
|
-
return { message: `${
|
|
26191
|
+
return { message: `${color54.amber("Usage:")} /settings plugins on|off` };
|
|
25861
26192
|
const on = raw === "on";
|
|
25862
26193
|
await persistConfigSetting(persistDeps, (cfg) => {
|
|
25863
26194
|
const feats = cfg.features ?? {};
|
|
@@ -25865,13 +26196,13 @@ async function executeSettingsSubcommand(sub, rest, opts) {
|
|
|
25865
26196
|
cfg.features = feats;
|
|
25866
26197
|
});
|
|
25867
26198
|
return {
|
|
25868
|
-
message: `${
|
|
26199
|
+
message: `${color54.green("\u2713")} Plugin features \u2192 ${on ? color54.cyan("on") : color54.dim("off")} ${color54.dim("restart to apply")}`
|
|
25869
26200
|
};
|
|
25870
26201
|
}
|
|
25871
26202
|
if (sub === "memory") {
|
|
25872
26203
|
const raw = (rest[0] ?? "").toLowerCase();
|
|
25873
26204
|
if (!["on", "off"].includes(raw))
|
|
25874
|
-
return { message: `${
|
|
26205
|
+
return { message: `${color54.amber("Usage:")} /settings memory on|off` };
|
|
25875
26206
|
const on = raw === "on";
|
|
25876
26207
|
await persistConfigSetting(persistDeps, (cfg) => {
|
|
25877
26208
|
const feats = cfg.features ?? {};
|
|
@@ -25879,13 +26210,13 @@ async function executeSettingsSubcommand(sub, rest, opts) {
|
|
|
25879
26210
|
cfg.features = feats;
|
|
25880
26211
|
});
|
|
25881
26212
|
return {
|
|
25882
|
-
message: `${
|
|
26213
|
+
message: `${color54.green("\u2713")} Memory features \u2192 ${on ? color54.cyan("on") : color54.dim("off")} ${color54.dim("restart to apply")}`
|
|
25883
26214
|
};
|
|
25884
26215
|
}
|
|
25885
26216
|
if (sub === "skills") {
|
|
25886
26217
|
const raw = (rest[0] ?? "").toLowerCase();
|
|
25887
26218
|
if (!["on", "off"].includes(raw))
|
|
25888
|
-
return { message: `${
|
|
26219
|
+
return { message: `${color54.amber("Usage:")} /settings skills on|off` };
|
|
25889
26220
|
const on = raw === "on";
|
|
25890
26221
|
await persistConfigSetting(persistDeps, (cfg) => {
|
|
25891
26222
|
const feats = cfg.features ?? {};
|
|
@@ -25893,13 +26224,13 @@ async function executeSettingsSubcommand(sub, rest, opts) {
|
|
|
25893
26224
|
cfg.features = feats;
|
|
25894
26225
|
});
|
|
25895
26226
|
return {
|
|
25896
|
-
message: `${
|
|
26227
|
+
message: `${color54.green("\u2713")} Skills features \u2192 ${on ? color54.cyan("on") : color54.dim("off")} ${color54.dim("restart to apply")}`
|
|
25897
26228
|
};
|
|
25898
26229
|
}
|
|
25899
26230
|
if (sub === "models-registry") {
|
|
25900
26231
|
const raw = (rest[0] ?? "").toLowerCase();
|
|
25901
26232
|
if (!["on", "off"].includes(raw))
|
|
25902
|
-
return { message: `${
|
|
26233
|
+
return { message: `${color54.amber("Usage:")} /settings models-registry on|off` };
|
|
25903
26234
|
const on = raw === "on";
|
|
25904
26235
|
await persistConfigSetting(persistDeps, (cfg) => {
|
|
25905
26236
|
const feats = cfg.features ?? {};
|
|
@@ -25907,7 +26238,7 @@ async function executeSettingsSubcommand(sub, rest, opts) {
|
|
|
25907
26238
|
cfg.features = feats;
|
|
25908
26239
|
});
|
|
25909
26240
|
return {
|
|
25910
|
-
message: `${
|
|
26241
|
+
message: `${color54.green("\u2713")} Models registry \u2192 ${on ? color54.cyan("on") : color54.dim("off")} ${color54.dim("restart to apply")}`
|
|
25911
26242
|
};
|
|
25912
26243
|
}
|
|
25913
26244
|
if (sub === "stream-fleet") {
|
|
@@ -25915,7 +26246,7 @@ async function executeSettingsSubcommand(sub, rest, opts) {
|
|
|
25915
26246
|
const mode = raw === "on" ? "full" : raw === "off" || raw === "full" ? raw : void 0;
|
|
25916
26247
|
if (!mode)
|
|
25917
26248
|
return {
|
|
25918
|
-
message: `${
|
|
26249
|
+
message: `${color54.amber("Usage:")} /settings stream-fleet off|full (on = full)`
|
|
25919
26250
|
};
|
|
25920
26251
|
await persistAutonomySetting(persistDeps, (autonomy) => {
|
|
25921
26252
|
autonomy.fleetChatVerbosity = mode;
|
|
@@ -25923,43 +26254,43 @@ async function executeSettingsSubcommand(sub, rest, opts) {
|
|
|
25923
26254
|
opts.fleetStreamController?.setMode(mode);
|
|
25924
26255
|
const desc = mode === "full" ? "every subagent tool call and message in chat" : "subagent chat lines hidden (F2/F3 stay live)";
|
|
25925
26256
|
return {
|
|
25926
|
-
message: `${
|
|
26257
|
+
message: `${color54.green("\u2713")} fleet chat \u2192 ${color54.cyan(mode)} ${color54.dim(desc)}`
|
|
25927
26258
|
};
|
|
25928
26259
|
}
|
|
25929
26260
|
if (sub === "chime") {
|
|
25930
26261
|
const raw = (rest[0] ?? "").toLowerCase();
|
|
25931
26262
|
if (!["on", "off"].includes(raw))
|
|
25932
|
-
return { message: `${
|
|
26263
|
+
return { message: `${color54.amber("Usage:")} /settings chime on|off` };
|
|
25933
26264
|
const on = raw === "on";
|
|
25934
26265
|
await persistAutonomySetting(persistDeps, (autonomy) => {
|
|
25935
26266
|
autonomy.chime = on;
|
|
25936
26267
|
});
|
|
25937
26268
|
return {
|
|
25938
|
-
message: `${
|
|
26269
|
+
message: `${color54.green("\u2713")} completion chime \u2192 ${on ? color54.cyan("on") : color54.dim("off")}`
|
|
25939
26270
|
};
|
|
25940
26271
|
}
|
|
25941
26272
|
if (sub === "confirm-exit") {
|
|
25942
26273
|
const raw = (rest[0] ?? "").toLowerCase();
|
|
25943
26274
|
if (!["on", "off"].includes(raw))
|
|
25944
|
-
return { message: `${
|
|
26275
|
+
return { message: `${color54.amber("Usage:")} /settings confirm-exit on|off` };
|
|
25945
26276
|
const on = raw === "on";
|
|
25946
26277
|
await persistAutonomySetting(persistDeps, (autonomy) => {
|
|
25947
26278
|
autonomy.confirmExit = on;
|
|
25948
26279
|
});
|
|
25949
26280
|
return {
|
|
25950
|
-
message: `${
|
|
26281
|
+
message: `${color54.green("\u2713")} confirm before exit \u2192 ${on ? color54.cyan("on") : color54.dim("off")}`
|
|
25951
26282
|
};
|
|
25952
26283
|
}
|
|
25953
26284
|
if (sub === "max-iterations") {
|
|
25954
26285
|
const raw = rest[0];
|
|
25955
26286
|
if (raw === void 0)
|
|
25956
26287
|
return {
|
|
25957
|
-
message: `${
|
|
26288
|
+
message: `${color54.amber("Usage:")} /settings max-iterations <n> ${color54.dim("(0 = default)")}`
|
|
25958
26289
|
};
|
|
25959
26290
|
const n = Number.parseInt(raw, 10);
|
|
25960
26291
|
if (Number.isNaN(n) || n < 0)
|
|
25961
26292
|
return {
|
|
25962
|
-
message: `${
|
|
26293
|
+
message: `${color54.red("Invalid number")}: "${raw}". Enter a non-negative integer.`
|
|
25963
26294
|
};
|
|
25964
26295
|
await persistConfigSetting(persistDeps, (cfg) => {
|
|
25965
26296
|
const tools = cfg.tools ?? {};
|
|
@@ -25967,31 +26298,31 @@ async function executeSettingsSubcommand(sub, rest, opts) {
|
|
|
25967
26298
|
cfg.tools = tools;
|
|
25968
26299
|
});
|
|
25969
26300
|
return {
|
|
25970
|
-
message: `${
|
|
26301
|
+
message: `${color54.green("\u2713")} max iterations \u2192 ${color54.cyan(n === 0 ? "default" : String(n))} ${color54.dim("agent pauses after this many iterations")}`
|
|
25971
26302
|
};
|
|
25972
26303
|
}
|
|
25973
26304
|
if (sub === "auto-proceed-max-iterations") {
|
|
25974
26305
|
const raw = rest[0];
|
|
25975
26306
|
if (raw === void 0)
|
|
25976
26307
|
return {
|
|
25977
|
-
message: `${
|
|
26308
|
+
message: `${color54.amber("Usage:")} /settings auto-proceed-max-iterations <n> ${color54.dim("(0 = unlimited)")}`
|
|
25978
26309
|
};
|
|
25979
26310
|
const n = Number.parseInt(raw, 10);
|
|
25980
26311
|
if (Number.isNaN(n) || n < 0)
|
|
25981
26312
|
return {
|
|
25982
|
-
message: `${
|
|
26313
|
+
message: `${color54.red("Invalid number")}: "${raw}". Enter a non-negative integer.`
|
|
25983
26314
|
};
|
|
25984
26315
|
await persistAutonomySetting(persistDeps, (autonomy) => {
|
|
25985
26316
|
autonomy.autoProceedMaxIterations = n;
|
|
25986
26317
|
});
|
|
25987
26318
|
return {
|
|
25988
|
-
message: `${
|
|
26319
|
+
message: `${color54.green("\u2713")} auto-proceed max iterations \u2192 ${color54.cyan(n === 0 ? "unlimited" : String(n))}`
|
|
25989
26320
|
};
|
|
25990
26321
|
}
|
|
25991
26322
|
if (sub === "index-on-start") {
|
|
25992
26323
|
const raw = (rest[0] ?? "").toLowerCase();
|
|
25993
26324
|
if (!["on", "off"].includes(raw))
|
|
25994
|
-
return { message: `${
|
|
26325
|
+
return { message: `${color54.amber("Usage:")} /settings index-on-start on|off` };
|
|
25995
26326
|
const on = raw === "on";
|
|
25996
26327
|
await persistConfigSetting(persistDeps, (cfg) => {
|
|
25997
26328
|
const idx = cfg.indexing ?? {};
|
|
@@ -25999,7 +26330,7 @@ async function executeSettingsSubcommand(sub, rest, opts) {
|
|
|
25999
26330
|
cfg.indexing = idx;
|
|
26000
26331
|
});
|
|
26001
26332
|
return {
|
|
26002
|
-
message: `${
|
|
26333
|
+
message: `${color54.green("\u2713")} index on session start \u2192 ${on ? color54.cyan("on") : color54.dim("off")} ${color54.dim("effective next session")}`
|
|
26003
26334
|
};
|
|
26004
26335
|
}
|
|
26005
26336
|
if (sub === "log-level") {
|
|
@@ -26007,21 +26338,21 @@ async function executeSettingsSubcommand(sub, rest, opts) {
|
|
|
26007
26338
|
const levels = ["error", "warn", "info", "debug", "trace"];
|
|
26008
26339
|
if (!levels.includes(raw))
|
|
26009
26340
|
return {
|
|
26010
|
-
message: `${
|
|
26341
|
+
message: `${color54.amber("Usage:")} /settings log-level error|warn|info|debug|trace`
|
|
26011
26342
|
};
|
|
26012
26343
|
await persistConfigSetting(persistDeps, (cfg) => {
|
|
26013
26344
|
const log = cfg.log ?? {};
|
|
26014
26345
|
log.level = raw;
|
|
26015
26346
|
cfg.log = log;
|
|
26016
26347
|
});
|
|
26017
|
-
return { message: `${
|
|
26348
|
+
return { message: `${color54.green("\u2713")} log level \u2192 ${color54.cyan(raw)}` };
|
|
26018
26349
|
}
|
|
26019
26350
|
if (sub === "audit-level") {
|
|
26020
26351
|
const raw = (rest[0] ?? "").toLowerCase();
|
|
26021
26352
|
const levels = ["minimal", "standard", "full"];
|
|
26022
26353
|
if (!levels.includes(raw))
|
|
26023
26354
|
return {
|
|
26024
|
-
message: `${
|
|
26355
|
+
message: `${color54.amber("Usage:")} /settings audit-level minimal|standard|full`
|
|
26025
26356
|
};
|
|
26026
26357
|
await persistConfigSetting(persistDeps, (cfg) => {
|
|
26027
26358
|
const sess = cfg.session ?? {};
|
|
@@ -26029,38 +26360,38 @@ async function executeSettingsSubcommand(sub, rest, opts) {
|
|
|
26029
26360
|
cfg.session = sess;
|
|
26030
26361
|
});
|
|
26031
26362
|
return {
|
|
26032
|
-
message: `${
|
|
26363
|
+
message: `${color54.green("\u2713")} audit level \u2192 ${color54.cyan(raw)} ${color54.dim("restart to apply")}`
|
|
26033
26364
|
};
|
|
26034
26365
|
}
|
|
26035
26366
|
if (sub === "thinking-word") {
|
|
26036
26367
|
const raw = rest.join(" ").trim();
|
|
26037
26368
|
if (!raw)
|
|
26038
26369
|
return {
|
|
26039
|
-
message: `${
|
|
26370
|
+
message: `${color54.amber("Usage:")} /settings thinking-word <word> ${color54.dim('single short word, e.g. "thinking", "vibing", "cooking"')}`
|
|
26040
26371
|
};
|
|
26041
26372
|
if (raw.length > 16)
|
|
26042
|
-
return { message: `${
|
|
26373
|
+
return { message: `${color54.red("Word too long")}: max 16 characters.` };
|
|
26043
26374
|
await persistAutonomySetting(persistDeps, (autonomy) => {
|
|
26044
26375
|
autonomy.thinkingWord = raw;
|
|
26045
26376
|
});
|
|
26046
|
-
return { message: `${
|
|
26377
|
+
return { message: `${color54.green("\u2713")} thinking word \u2192 ${color54.cyan(raw)}` };
|
|
26047
26378
|
}
|
|
26048
26379
|
if (sub === "statusline") {
|
|
26049
26380
|
const raw = (rest[0] ?? "").toLowerCase();
|
|
26050
26381
|
const modes = ["minimum", "detailed", "no-color"];
|
|
26051
26382
|
if (!modes.includes(raw))
|
|
26052
26383
|
return {
|
|
26053
|
-
message: `${
|
|
26384
|
+
message: `${color54.amber("Usage:")} /settings statusline minimum|detailed|no-color`
|
|
26054
26385
|
};
|
|
26055
26386
|
await persistAutonomySetting(persistDeps, (autonomy) => {
|
|
26056
26387
|
autonomy.statuslineMode = raw;
|
|
26057
26388
|
});
|
|
26058
|
-
return { message: `${
|
|
26389
|
+
return { message: `${color54.green("\u2713")} statusline mode \u2192 ${color54.cyan(raw)}` };
|
|
26059
26390
|
}
|
|
26060
26391
|
if (sub === "read-symbols") {
|
|
26061
26392
|
const raw = (rest[0] ?? "").toLowerCase();
|
|
26062
26393
|
if (!["on", "off"].includes(raw)) {
|
|
26063
|
-
return { message: `${
|
|
26394
|
+
return { message: `${color54.amber("Usage:")} /settings read-symbols on|off` };
|
|
26064
26395
|
}
|
|
26065
26396
|
const on = raw === "on";
|
|
26066
26397
|
await persistAutonomySetting(persistDeps, (autonomy) => {
|
|
@@ -26070,7 +26401,7 @@ async function executeSettingsSubcommand(sub, rest, opts) {
|
|
|
26070
26401
|
opts.context.meta["tools.read.advancedMode"] = on;
|
|
26071
26402
|
}
|
|
26072
26403
|
return {
|
|
26073
|
-
message: `${
|
|
26404
|
+
message: `${color54.green("\u2713")} read symbols \u2192 ${on ? color54.cyan("on") : color54.dim("off")} ${color54.dim(on ? "codebase-index symbols will be included in read tool results" : "read tool returns file content only")}`
|
|
26074
26405
|
};
|
|
26075
26406
|
}
|
|
26076
26407
|
if (sub === "animation") {
|
|
@@ -26078,26 +26409,26 @@ async function executeSettingsSubcommand(sub, rest, opts) {
|
|
|
26078
26409
|
const styles = ["rainbow", "wave", "pulse", "dots", "breathe", "cycle"];
|
|
26079
26410
|
if (!styles.includes(raw))
|
|
26080
26411
|
return {
|
|
26081
|
-
message: `${
|
|
26412
|
+
message: `${color54.amber("Usage:")} /settings animation rainbow|wave|pulse|dots|breathe|cycle`
|
|
26082
26413
|
};
|
|
26083
26414
|
await persistAutonomySetting(persistDeps, (autonomy) => {
|
|
26084
26415
|
autonomy.animationStyle = raw;
|
|
26085
26416
|
});
|
|
26086
|
-
return { message: `${
|
|
26417
|
+
return { message: `${color54.green("\u2713")} animation style \u2192 ${color54.cyan(raw)}` };
|
|
26087
26418
|
}
|
|
26088
26419
|
return {
|
|
26089
|
-
message: `${
|
|
26420
|
+
message: `${color54.red("Unknown setting")} "${sub}". ${unknownSubcommand(sub, ALL_SETTINGS_KEYS, "settings")}`
|
|
26090
26421
|
};
|
|
26091
26422
|
} catch (err) {
|
|
26092
26423
|
return {
|
|
26093
|
-
message: `${
|
|
26424
|
+
message: `${color54.red("Settings error")}: ${toErrorMessage23(err)}`
|
|
26094
26425
|
};
|
|
26095
26426
|
}
|
|
26096
26427
|
}
|
|
26097
26428
|
|
|
26098
26429
|
// src/slash-commands/settings-view.ts
|
|
26099
26430
|
import { resolveFleetChatVerbosity } from "@wrongstack/core/types";
|
|
26100
|
-
import { color as
|
|
26431
|
+
import { color as color55 } from "@wrongstack/core/utils";
|
|
26101
26432
|
var SETTINGS_HELP = [
|
|
26102
26433
|
"Usage:",
|
|
26103
26434
|
" /settings Show current settings",
|
|
@@ -26155,16 +26486,16 @@ var SETTINGS_HELP = [
|
|
|
26155
26486
|
].join("\n");
|
|
26156
26487
|
function formatSettingsDefaults() {
|
|
26157
26488
|
return [
|
|
26158
|
-
`${
|
|
26489
|
+
`${color55.bold("Default Values")}`,
|
|
26159
26490
|
"",
|
|
26160
|
-
` auto-proceed delay: ${
|
|
26161
|
-
` default autonomy mode: ${
|
|
26162
|
-
` launch hints: ${
|
|
26163
|
-
` iteration timeout: ${
|
|
26164
|
-
` session timeout: ${
|
|
26165
|
-
` max iterations: ${
|
|
26166
|
-
` max concurrent: ${
|
|
26167
|
-
` semver default part: ${
|
|
26491
|
+
` auto-proceed delay: ${color55.cyan("45s")} ${color55.dim("(WRONGSTACK_AUTO_PROCEED_DELAY_MS env)")}`,
|
|
26492
|
+
` default autonomy mode: ${color55.cyan("off")}`,
|
|
26493
|
+
` launch hints: ${color55.cyan("on")}`,
|
|
26494
|
+
` iteration timeout: ${color55.cyan("5 min")}`,
|
|
26495
|
+
` session timeout: ${color55.cyan("30 min")}`,
|
|
26496
|
+
` max iterations: ${color55.cyan("100")}`,
|
|
26497
|
+
` max concurrent: ${color55.cyan("4")}`,
|
|
26498
|
+
` semver default part: ${color55.cyan("patch")}`
|
|
26168
26499
|
].join("\n");
|
|
26169
26500
|
}
|
|
26170
26501
|
function formatCurrentSettingsView(opts) {
|
|
@@ -26208,56 +26539,56 @@ function formatCurrentSettingsView(opts) {
|
|
|
26208
26539
|
const idx = opts.configStore.get().indexing;
|
|
26209
26540
|
const sess = opts.configStore.get().session;
|
|
26210
26541
|
return [
|
|
26211
|
-
`${
|
|
26542
|
+
`${color55.bold("WrongStack")} ${color55.dim("\u2014 Settings")}`,
|
|
26212
26543
|
"",
|
|
26213
|
-
` auto-proceed delay: ${
|
|
26214
|
-
` default autonomy mode: ${
|
|
26215
|
-
` fleet chat: ${
|
|
26216
|
-
` completion chime: ${au?.chime === true ?
|
|
26217
|
-
` confirm before exit: ${au?.confirmExit !== false ?
|
|
26218
|
-
` launch hints: ${hints ?
|
|
26219
|
-
` debug stream: ${debugStream ?
|
|
26220
|
-
` config scope: ${
|
|
26221
|
-
` filesystem access: ${
|
|
26222
|
-
` refine: ${enhanceEnabled ?
|
|
26223
|
-
` refine-delay: ${
|
|
26224
|
-
` refine-language: ${
|
|
26225
|
-
` refiner-provider: ${
|
|
26226
|
-
` refiner-model: ${
|
|
26227
|
-
` refiner-fallback-profile: ${
|
|
26228
|
-
` semver default part: ${
|
|
26229
|
-
` circuit breaker: ${breakerEnabled ?
|
|
26230
|
-
` context mode: ${
|
|
26231
|
-
` context strategy: ${
|
|
26232
|
-
` context auto-compact: ${contextAutoCompact ?
|
|
26233
|
-
` token-saving: ${
|
|
26234
|
-
` nextsteps tool: ${nextStepsToolEnabled ?
|
|
26235
|
-
` MCP features: ${feats?.mcp !== false ?
|
|
26236
|
-
` plugin features: ${feats?.plugins !== false ?
|
|
26237
|
-
` memory features: ${feats?.memory !== false ?
|
|
26238
|
-
` skills features: ${feats?.skills !== false ?
|
|
26239
|
-
` models registry: ${feats?.modelsRegistry !== false ?
|
|
26240
|
-
` max concurrent: ${
|
|
26241
|
-
` max iterations: ${
|
|
26242
|
-
` auto-proceed max iters: ${
|
|
26243
|
-
` title animation: ${titleAnimation ?
|
|
26244
|
-
` thinking word: ${
|
|
26245
|
-
` statusline mode: ${
|
|
26246
|
-
` animation style: ${
|
|
26247
|
-
` read symbols: ${au?.readAdvancedMode === true ?
|
|
26248
|
-
` reasoning mode: ${
|
|
26249
|
-
` reasoning effort: ${
|
|
26250
|
-
` reasoning preserve: ${reasoningPreserve ?
|
|
26251
|
-
` cache TTL: ${
|
|
26252
|
-
` index on start: ${idx?.onSessionStart !== false ?
|
|
26253
|
-
` log level: ${
|
|
26254
|
-
` audit level: ${
|
|
26255
|
-
` HQ publishing: ${hqEnabled ?
|
|
26256
|
-
` HQ URL: ${
|
|
26257
|
-
` HQ token: ${
|
|
26258
|
-
` HQ raw content: ${hq?.rawContent === true ?
|
|
26544
|
+
` auto-proceed delay: ${color55.cyan(formatDelay(delay))} ${color55.dim("change: /settings delay <seconds>")}`,
|
|
26545
|
+
` default autonomy mode: ${color55.cyan(mode)} ${color55.dim("change: /settings mode off|suggest|auto")}`,
|
|
26546
|
+
` fleet chat: ${color55.cyan(resolveFleetChatVerbosity(au))} ${color55.dim("change: /settings stream-fleet off|full")}`,
|
|
26547
|
+
` completion chime: ${au?.chime === true ? color55.cyan("on") : color55.dim("off")} ${color55.dim("change: /settings chime on|off")}`,
|
|
26548
|
+
` confirm before exit: ${au?.confirmExit !== false ? color55.cyan("on") : color55.dim("off")} ${color55.dim("change: /settings confirm-exit on|off")}`,
|
|
26549
|
+
` launch hints: ${hints ? color55.cyan("on") : color55.dim("off")} ${color55.dim("change: /settings hints on|off")}`,
|
|
26550
|
+
` debug stream: ${debugStream ? color55.cyan("on") : color55.dim("off")} ${color55.dim("change: /settings debug-stream on|off")}`,
|
|
26551
|
+
` config scope: ${color55.cyan(configScope)} ${color55.dim("change: /settings config-scope global|project")}`,
|
|
26552
|
+
` filesystem access: ${color55.cyan(fsAccess)} ${color55.dim("change: /settings fs-access unrestricted|project")}`,
|
|
26553
|
+
` refine: ${enhanceEnabled ? color55.cyan("on") : color55.dim("off")} ${color55.dim("change: /settings refine on|off")}`,
|
|
26554
|
+
` refine-delay: ${color55.cyan(formatDelay(enhanceDelay))} ${color55.dim("change: /settings refine-delay <seconds>")}`,
|
|
26555
|
+
` refine-language: ${color55.cyan(enhanceLanguage)} ${color55.dim("change: /settings refine-language original|english")}`,
|
|
26556
|
+
` refiner-provider: ${color55.cyan(au?.refinerProvider ?? color55.dim("(unset)"))} ${color55.dim("change: /settings refiner-provider <id>")}`,
|
|
26557
|
+
` refiner-model: ${color55.cyan(au?.refinerModel ?? color55.dim("(unset)"))} ${color55.dim("change: /settings refiner-model <model>")}`,
|
|
26558
|
+
` refiner-fallback-profile: ${color55.cyan(au?.refinerFallbackProfile ?? color55.dim("(unset)"))} ${color55.dim("change: /settings refiner-fallback-profile <name>")}`,
|
|
26559
|
+
` semver default part: ${color55.cyan(semverPart)} ${color55.dim("change: /settings semver-part patch|minor|major|auto")}`,
|
|
26560
|
+
` circuit breaker: ${breakerEnabled ? color55.cyan("on") : color55.dim("off")} (${breakerTimeout > 0 ? formatDelay(breakerTimeout) : color55.dim("manual")}) ${color55.dim("change: /settings breaker on|off")}`,
|
|
26561
|
+
` context mode: ${color55.cyan(contextMode)} ${color55.dim("change: /settings context-mode balanced|frugal|deep")}`,
|
|
26562
|
+
` context strategy: ${color55.cyan(contextStrategy)} ${color55.dim("change: /settings context-strategy hybrid|intelligent|selective")}`,
|
|
26563
|
+
` context auto-compact: ${contextAutoCompact ? color55.cyan("on") : color55.dim("off")} ${color55.dim("change: /settings context-auto-compact on|off")}`,
|
|
26564
|
+
` token-saving: ${color55.cyan(tokenSavingTier)} ${color55.dim("change: /settings token-saving off|minimal|light|medium|aggressive")}`,
|
|
26565
|
+
` nextsteps tool: ${nextStepsToolEnabled ? color55.cyan("on") : color55.dim("off")} ${color55.dim("change: /settings nextsteps-tool on|off")}`,
|
|
26566
|
+
` MCP features: ${feats?.mcp !== false ? color55.cyan("on") : color55.dim("off")} ${color55.dim("change: /settings mcp on|off")}`,
|
|
26567
|
+
` plugin features: ${feats?.plugins !== false ? color55.cyan("on") : color55.dim("off")} ${color55.dim("change: /settings plugins on|off")}`,
|
|
26568
|
+
` memory features: ${feats?.memory !== false ? color55.cyan("on") : color55.dim("off")} ${color55.dim("change: /settings memory on|off")}`,
|
|
26569
|
+
` skills features: ${feats?.skills !== false ? color55.cyan("on") : color55.dim("off")} ${color55.dim("change: /settings skills on|off")}`,
|
|
26570
|
+
` models registry: ${feats?.modelsRegistry !== false ? color55.cyan("on") : color55.dim("off")} ${color55.dim("change: /settings models-registry on|off")}`,
|
|
26571
|
+
` max concurrent: ${color55.cyan(maxConcurrent === 0 ? "default" : String(maxConcurrent))} ${color55.dim("change: /settings max-concurrent <n>")}`,
|
|
26572
|
+
` max iterations: ${color55.cyan(String(tools?.maxIterations ?? "default"))} ${color55.dim("change: /settings max-iterations <n>")}`,
|
|
26573
|
+
` auto-proceed max iters: ${color55.cyan(String(au?.autoProceedMaxIterations ?? "unlimited"))} ${color55.dim("change: /settings auto-proceed-max-iterations <n>")}`,
|
|
26574
|
+
` title animation: ${titleAnimation ? color55.cyan("on") : color55.dim("off")} ${color55.dim("change: /settings title-animation on|off")}`,
|
|
26575
|
+
` thinking word: ${color55.cyan(au?.thinkingWord ?? "thinking")} ${color55.dim("change: /settings thinking-word <word>")}`,
|
|
26576
|
+
` statusline mode: ${color55.cyan(au?.statuslineMode ?? "minimum")} ${color55.dim("change: /settings statusline minimum|detailed|no-color")}`,
|
|
26577
|
+
` animation style: ${color55.cyan(au?.animationStyle ?? "rainbow")} ${color55.dim("change: /settings animation rainbow|wave|pulse|dots|breathe|cycle")}`,
|
|
26578
|
+
` read symbols: ${au?.readAdvancedMode === true ? color55.cyan("on") : color55.dim("off")} ${color55.dim("change: /settings read-symbols on|off")}`,
|
|
26579
|
+
` reasoning mode: ${color55.cyan(reasoningMode)} ${color55.dim("change: /settings reasoning auto|on|off")}`,
|
|
26580
|
+
` reasoning effort: ${color55.cyan(reasoningEffort)} ${color55.dim("change: /settings reasoning-effort <level>")}`,
|
|
26581
|
+
` reasoning preserve: ${reasoningPreserve ? color55.cyan("on") : color55.dim("off")} ${color55.dim("change: /settings reasoning-preserve on|off")}`,
|
|
26582
|
+
` cache TTL: ${color55.cyan(cacheTtl)} ${color55.dim("change: /settings cache-ttl 5m|1h")}`,
|
|
26583
|
+
` index on start: ${idx?.onSessionStart !== false ? color55.cyan("on") : color55.dim("off")} ${color55.dim("change: /settings index-on-start on|off")}`,
|
|
26584
|
+
` log level: ${color55.cyan(log?.level ?? "info")} ${color55.dim("change: /settings log-level error|warn|info|debug|trace")}`,
|
|
26585
|
+
` audit level: ${color55.cyan(sess?.auditLevel ?? "standard")} ${color55.dim("change: /settings audit-level minimal|standard|full")}`,
|
|
26586
|
+
` HQ publishing: ${hqEnabled ? color55.cyan("on") : color55.dim("off")} ${color55.dim("change: /settings hq on|off")}`,
|
|
26587
|
+
` HQ URL: ${color55.cyan(hqUrl)} ${color55.dim("change: /settings hq-url <url>")}`,
|
|
26588
|
+
` HQ token: ${color55.cyan(hqToken)} ${color55.dim("change: /settings hq-token <token>")}`,
|
|
26589
|
+
` HQ raw content: ${hq?.rawContent === true ? color55.cyan("on") : color55.dim("off")} ${color55.dim("change: /settings hq-raw on|off")}`,
|
|
26259
26590
|
"",
|
|
26260
|
-
|
|
26591
|
+
color55.dim(` Persisted to ${persistedTo} \xB7 /settings help for more`)
|
|
26261
26592
|
].join("\n");
|
|
26262
26593
|
}
|
|
26263
26594
|
|
|
@@ -26275,7 +26606,7 @@ function buildSettingsCommand(opts) {
|
|
|
26275
26606
|
return { message: this.help ?? "" };
|
|
26276
26607
|
}
|
|
26277
26608
|
if (!opts.configStore || !opts.paths) {
|
|
26278
|
-
return { message: `${
|
|
26609
|
+
return { message: `${color56.red("Error")} config store not available.` };
|
|
26279
26610
|
}
|
|
26280
26611
|
if (!sub) {
|
|
26281
26612
|
return { message: formatCurrentSettingsView(opts) };
|
|
@@ -26291,8 +26622,8 @@ function buildSettingsCommand(opts) {
|
|
|
26291
26622
|
}
|
|
26292
26623
|
|
|
26293
26624
|
// src/slash-commands/shadow.ts
|
|
26294
|
-
import { ToolValidationError as
|
|
26295
|
-
import { color as
|
|
26625
|
+
import { ToolValidationError as ToolValidationError4 } from "@wrongstack/core/types";
|
|
26626
|
+
import { color as color57 } from "@wrongstack/core/utils";
|
|
26296
26627
|
var DEFAULT_SHADOW_INTERVAL_MS = 3e4;
|
|
26297
26628
|
var MIN_SHADOW_INTERVAL_MS = 5e3;
|
|
26298
26629
|
function buildShadowCommand(opts) {
|
|
@@ -26362,7 +26693,7 @@ function buildShadowCommand(opts) {
|
|
|
26362
26693
|
if (opts.shadowController?.activeId != null) {
|
|
26363
26694
|
return {
|
|
26364
26695
|
message: [
|
|
26365
|
-
`${
|
|
26696
|
+
`${color57.yellow("\u26A0")} A Shadow Agent is already running (${opts.shadowController.activeId.slice(0, 8)}).`,
|
|
26366
26697
|
"",
|
|
26367
26698
|
"Only one Shadow Agent instance is allowed per session.",
|
|
26368
26699
|
"Use /shadow status to view the current instance."
|
|
@@ -26401,16 +26732,16 @@ function buildShadowCommand(opts) {
|
|
|
26401
26732
|
shadowIntervalMs: intervalMs
|
|
26402
26733
|
});
|
|
26403
26734
|
return {
|
|
26404
|
-
message: `${
|
|
26405
|
-
${
|
|
26406
|
-
${
|
|
26735
|
+
message: `${color57.green("\u2713")} Shadow Agent queued: ${spawnId}
|
|
26736
|
+
${color57.dim("Mode:")} one-shot quiet check
|
|
26737
|
+
${color57.dim("Model:")} ${modelRef.label}`
|
|
26407
26738
|
};
|
|
26408
26739
|
}
|
|
26409
26740
|
case "stop": {
|
|
26410
26741
|
const activeId = opts.shadowController?.activeId;
|
|
26411
26742
|
if (!activeId) {
|
|
26412
26743
|
return {
|
|
26413
|
-
message: `${
|
|
26744
|
+
message: `${color57.yellow("\u26A0")} No active Shadow Agent is registered for this session.`
|
|
26414
26745
|
};
|
|
26415
26746
|
}
|
|
26416
26747
|
if (!opts.onFleetTerminate) {
|
|
@@ -26419,12 +26750,12 @@ ${color56.dim("Model:")} ${modelRef.label}`
|
|
|
26419
26750
|
const ok = await opts.onFleetTerminate(activeId);
|
|
26420
26751
|
if (ok) {
|
|
26421
26752
|
opts.shadowController?.clear();
|
|
26422
|
-
return { message: `${
|
|
26753
|
+
return { message: `${color57.green("\u2713")} Shadow Agent stopped: ${activeId}` };
|
|
26423
26754
|
}
|
|
26424
26755
|
return {
|
|
26425
26756
|
message: [
|
|
26426
|
-
`${
|
|
26427
|
-
`It may already be stopped. Use ${
|
|
26757
|
+
`${color57.red("\u2717")} Failed to stop Shadow Agent ${color57.bold(activeId)}.`,
|
|
26758
|
+
`It may already be stopped. Use ${color57.bold("/shadow status")} to inspect active agents.`
|
|
26428
26759
|
].join("\n")
|
|
26429
26760
|
};
|
|
26430
26761
|
}
|
|
@@ -26452,10 +26783,10 @@ ${color56.dim("Model:")} ${modelRef.label}`
|
|
|
26452
26783
|
opts.shadowController?.clear();
|
|
26453
26784
|
return {
|
|
26454
26785
|
message: [
|
|
26455
|
-
`${
|
|
26786
|
+
`${color57.red("\u26A0")} HOOP: Stopped ${killed} running agent(s)`,
|
|
26456
26787
|
"",
|
|
26457
|
-
`Target: ${
|
|
26458
|
-
`Reason: ${
|
|
26788
|
+
`Target: ${color57.bold("all")}`,
|
|
26789
|
+
`Reason: ${color57.yellow(reason)}`
|
|
26459
26790
|
].join("\n")
|
|
26460
26791
|
};
|
|
26461
26792
|
}
|
|
@@ -26469,10 +26800,10 @@ ${color56.dim("Model:")} ${modelRef.label}`
|
|
|
26469
26800
|
}
|
|
26470
26801
|
return {
|
|
26471
26802
|
message: [
|
|
26472
|
-
ok ? `${
|
|
26803
|
+
ok ? `${color57.red("\u26A0")} HOOP: Stopped agent` : `${color57.red("\u2717")} HOOP: Failed to stop agent`,
|
|
26473
26804
|
"",
|
|
26474
|
-
`Target: ${
|
|
26475
|
-
`Reason: ${
|
|
26805
|
+
`Target: ${color57.bold(targetId)}`,
|
|
26806
|
+
`Reason: ${color57.yellow(reason)}`,
|
|
26476
26807
|
agentInfo ? `
|
|
26477
26808
|
Agent info:
|
|
26478
26809
|
${agentInfo}` : ""
|
|
@@ -26497,7 +26828,7 @@ Current default: ${defaultModelRef.label}`
|
|
|
26497
26828
|
opts.shadowController?.setDefaults?.({ provider: parsed.provider, model: parsed.model });
|
|
26498
26829
|
return {
|
|
26499
26830
|
message: `/shadow model ${parsed.label}
|
|
26500
|
-
${
|
|
26831
|
+
${color57.dim("Model will be applied on next /shadow start")}`
|
|
26501
26832
|
};
|
|
26502
26833
|
}
|
|
26503
26834
|
case "interval": {
|
|
@@ -26517,7 +26848,7 @@ Current default: ${DEFAULT_SHADOW_INTERVAL_MS}ms (30 seconds)`
|
|
|
26517
26848
|
opts.shadowController?.setDefaults?.({ intervalMs: ms });
|
|
26518
26849
|
return {
|
|
26519
26850
|
message: `/shadow interval ${ms}ms
|
|
26520
|
-
${
|
|
26851
|
+
${color57.dim("Interval will be applied on next /shadow start")}`
|
|
26521
26852
|
};
|
|
26522
26853
|
}
|
|
26523
26854
|
default: {
|
|
@@ -26544,7 +26875,7 @@ function parseProviderModelRef(model, defaultRef) {
|
|
|
26544
26875
|
}
|
|
26545
26876
|
const slash = model.indexOf("/");
|
|
26546
26877
|
if (slash <= 0 || slash === model.length - 1) {
|
|
26547
|
-
throw new
|
|
26878
|
+
throw new ToolValidationError4({
|
|
26548
26879
|
message: `Model must be in provider/model format (e.g. provider/configured-model), got: "${model}"`,
|
|
26549
26880
|
field: "model",
|
|
26550
26881
|
context: { received: model }
|
|
@@ -26558,14 +26889,14 @@ function parseProviderModelRef(model, defaultRef) {
|
|
|
26558
26889
|
}
|
|
26559
26890
|
function parseInterval(value) {
|
|
26560
26891
|
if (value === true || !/^\d+$/.test(value)) {
|
|
26561
|
-
throw new
|
|
26892
|
+
throw new ToolValidationError4({
|
|
26562
26893
|
message: `interval must be an integer >= ${MIN_SHADOW_INTERVAL_MS}ms`,
|
|
26563
26894
|
field: "interval"
|
|
26564
26895
|
});
|
|
26565
26896
|
}
|
|
26566
26897
|
const ms = Number.parseInt(value, 10);
|
|
26567
26898
|
if (!Number.isFinite(ms) || ms < MIN_SHADOW_INTERVAL_MS) {
|
|
26568
|
-
throw new
|
|
26899
|
+
throw new ToolValidationError4({
|
|
26569
26900
|
message: `interval must be an integer >= ${MIN_SHADOW_INTERVAL_MS}ms`,
|
|
26570
26901
|
field: "interval",
|
|
26571
26902
|
context: { received: ms, minimum: MIN_SHADOW_INTERVAL_MS }
|
|
@@ -26790,7 +27121,7 @@ function buildStatuslineCommand(deps) {
|
|
|
26790
27121
|
}
|
|
26791
27122
|
|
|
26792
27123
|
// src/slash-commands/supervisor.ts
|
|
26793
|
-
import { color as
|
|
27124
|
+
import { color as color58 } from "@wrongstack/core/utils";
|
|
26794
27125
|
function fmtAge4(at) {
|
|
26795
27126
|
const s = Math.max(0, Math.round((Date.now() - at) / 1e3));
|
|
26796
27127
|
if (s < 60) return `${s}s ago`;
|
|
@@ -26826,13 +27157,13 @@ function buildSupervisorCommand(opts) {
|
|
|
26826
27157
|
}
|
|
26827
27158
|
if (sub === "on") {
|
|
26828
27159
|
supervisor.start();
|
|
26829
|
-
const msg2 = `Fleet supervisor ${
|
|
27160
|
+
const msg2 = `Fleet supervisor ${color58.green("armed")} \u2014 evaluating every ${Math.round(supervisor.configSnapshot().intervalMs / 1e3)}s.`;
|
|
26830
27161
|
opts.renderer.write(msg2);
|
|
26831
27162
|
return { message: msg2 };
|
|
26832
27163
|
}
|
|
26833
27164
|
if (sub === "off") {
|
|
26834
27165
|
supervisor.stop();
|
|
26835
|
-
const msg2 = `Fleet supervisor ${
|
|
27166
|
+
const msg2 = `Fleet supervisor ${color58.yellow("disarmed")} \u2014 no further automatic interventions this session.`;
|
|
26836
27167
|
opts.renderer.write(msg2);
|
|
26837
27168
|
return { message: msg2 };
|
|
26838
27169
|
}
|
|
@@ -26845,10 +27176,10 @@ function buildSupervisorCommand(opts) {
|
|
|
26845
27176
|
return { message: msg3 };
|
|
26846
27177
|
}
|
|
26847
27178
|
const lines2 = entries.map((e) => {
|
|
26848
|
-
const who = e.subagentId ? ` ${
|
|
27179
|
+
const who = e.subagentId ? ` ${color58.cyan(e.subagentId)}` : "";
|
|
26849
27180
|
const task = e.taskId ? ` task=${e.taskId.slice(0, 8)}` : "";
|
|
26850
|
-
const outcome = e.outcome === "approved" ?
|
|
26851
|
-
return `${
|
|
27181
|
+
const outcome = e.outcome === "approved" ? color58.green(e.outcome) : e.outcome === "denied" || e.outcome === "error" ? color58.red(e.outcome) : color58.yellow(e.outcome);
|
|
27182
|
+
return `${color58.dim(fmtAge4(e.at))} ${e.kind}${who}${task} \u2192 ${e.proposedAction} [${outcome}] ${color58.dim(e.detail)}`;
|
|
26852
27183
|
});
|
|
26853
27184
|
const msg2 = lines2.join("\n");
|
|
26854
27185
|
opts.renderer.write(msg2);
|
|
@@ -26858,12 +27189,12 @@ function buildSupervisorCommand(opts) {
|
|
|
26858
27189
|
const history = supervisor.history();
|
|
26859
27190
|
const last = history[history.length - 1];
|
|
26860
27191
|
const lines = [
|
|
26861
|
-
`Fleet supervisor: ${supervisor.isRunning() ?
|
|
27192
|
+
`Fleet supervisor: ${supervisor.isRunning() ? color58.green("armed") : color58.yellow("disarmed")}`,
|
|
26862
27193
|
` interval ${Math.round(cfg.intervalMs / 1e3)}s \xB7 cooldown ${Math.round(cfg.cooldownMs / 1e3)}s \xB7 max ${cfg.maxInterventionsPerSubagent} interventions/agent`,
|
|
26863
27194
|
` signals: starvation>${Math.round(cfg.pinnedWaitMs / 1e3)}s \xB7 overload\u2265${cfg.overloadPinnedThreshold} pinned \xB7 backlog>${cfg.backlogFactor}\xD7workers \xB7 stuck>${Math.round(cfg.stuckMs / 1e3)}s \xB7 failstreak\u2265${cfg.failureStreak}`,
|
|
26864
27195
|
` actions: retarget \u2713 \xB7 spawn ${cfg.allowSpawn ? "\u2713" : "\u2717"} \xB7 steer \u2713 \xB7 terminate ${cfg.allowTerminate ? "\u2713" : "\u2717 (config fleet.supervisor.allowTerminate)"}`,
|
|
26865
27196
|
` activity: ${history.length} engagement(s)${last ? ` \u2014 last: ${last.kind} \u2192 ${last.proposedAction} [${last.outcome}] ${fmtAge4(last.at)}` : ""}`,
|
|
26866
|
-
|
|
27197
|
+
color58.dim(" decisions are gated by the Brain \u2014 see /brain (risk ceiling applies)")
|
|
26867
27198
|
];
|
|
26868
27199
|
const msg = lines.join("\n");
|
|
26869
27200
|
opts.renderer.write(msg);
|
|
@@ -27290,21 +27621,21 @@ ${formatTaskProgress(file.tasks)}`;
|
|
|
27290
27621
|
}
|
|
27291
27622
|
|
|
27292
27623
|
// src/slash-commands/techstack.ts
|
|
27293
|
-
import * as
|
|
27624
|
+
import * as fs16 from "node:fs/promises";
|
|
27294
27625
|
import * as path19 from "node:path";
|
|
27295
|
-
import { color as
|
|
27626
|
+
import { color as color59, toErrorMessage as toErrorMessage25 } from "@wrongstack/core/utils";
|
|
27296
27627
|
async function discoverPackageFiles(projectRoot) {
|
|
27297
27628
|
const files = [];
|
|
27298
27629
|
const rootPkg = path19.join(projectRoot, "package.json");
|
|
27299
27630
|
try {
|
|
27300
|
-
await
|
|
27631
|
+
await fs16.access(rootPkg);
|
|
27301
27632
|
files.push(rootPkg);
|
|
27302
27633
|
} catch {
|
|
27303
27634
|
}
|
|
27304
27635
|
const workspaceFile = path19.join(projectRoot, "pnpm-workspace.yaml");
|
|
27305
27636
|
try {
|
|
27306
|
-
await
|
|
27307
|
-
const content = await
|
|
27637
|
+
await fs16.access(workspaceFile);
|
|
27638
|
+
const content = await fs16.readFile(workspaceFile, "utf8");
|
|
27308
27639
|
const globMatch = /packages?:\s*\[([^\]]+)\]/s.exec(content);
|
|
27309
27640
|
const rawGlobs = globMatch?.[1];
|
|
27310
27641
|
if (!rawGlobs) return files;
|
|
@@ -27313,12 +27644,12 @@ async function discoverPackageFiles(projectRoot) {
|
|
|
27313
27644
|
const dirPrefix = g.replace(/\/?\*$/, "").replace(/\/\*$/, "");
|
|
27314
27645
|
const dir = path19.join(projectRoot, dirPrefix);
|
|
27315
27646
|
try {
|
|
27316
|
-
const entries = await
|
|
27647
|
+
const entries = await fs16.readdir(dir, { withFileTypes: true });
|
|
27317
27648
|
for (const e of entries) {
|
|
27318
27649
|
if (!e.isDirectory()) continue;
|
|
27319
27650
|
const subPkg = path19.join(dir, e.name, "package.json");
|
|
27320
27651
|
try {
|
|
27321
|
-
await
|
|
27652
|
+
await fs16.access(subPkg);
|
|
27322
27653
|
files.push(subPkg);
|
|
27323
27654
|
} catch {
|
|
27324
27655
|
}
|
|
@@ -27442,10 +27773,10 @@ function buildTechStackCommand(opts) {
|
|
|
27442
27773
|
" 1. Reads every package.json in the project",
|
|
27443
27774
|
" 2. Looks up latest versions on the npm registry",
|
|
27444
27775
|
" 3. Flags outdated, dead, or obsolete packages",
|
|
27445
|
-
` 4. Writes a ${
|
|
27776
|
+
` 4. Writes a ${color59.cyan("techstack.md")} (or .json) report to the project root`,
|
|
27446
27777
|
"",
|
|
27447
27778
|
"Uses the `tech-stack` skill for version verification rules.",
|
|
27448
|
-
`Hooked into ${
|
|
27779
|
+
`Hooked into ${color59.cyan("/init")} \u2014 runs automatically on first project setup.`
|
|
27449
27780
|
].join("\n"),
|
|
27450
27781
|
async run(args, _ctx) {
|
|
27451
27782
|
const trimmed = args.trim().toLowerCase();
|
|
@@ -27529,12 +27860,12 @@ function buildTechStackCommand(opts) {
|
|
|
27529
27860
|
try {
|
|
27530
27861
|
packageFiles = await discoverPackageFiles(opts.projectRoot);
|
|
27531
27862
|
if (packageFiles.length === 0) {
|
|
27532
|
-
discoveryNote =
|
|
27863
|
+
discoveryNote = color59.amber(
|
|
27533
27864
|
"\u26A0 No package.json files found. This does not look like a Node.js project."
|
|
27534
27865
|
);
|
|
27535
27866
|
}
|
|
27536
27867
|
} catch (err) {
|
|
27537
|
-
discoveryNote =
|
|
27868
|
+
discoveryNote = color59.red(`Could not scan for package files: ${toErrorMessage25(err)}`);
|
|
27538
27869
|
}
|
|
27539
27870
|
const task = buildTechStackTask({
|
|
27540
27871
|
projectRoot: opts.projectRoot,
|
|
@@ -27557,11 +27888,11 @@ function buildTechStackCommand(opts) {
|
|
|
27557
27888
|
};
|
|
27558
27889
|
}
|
|
27559
27890
|
const header = isInit ? "Tech Stack Init Audit" : "Tech Stack Audit";
|
|
27560
|
-
const label = `${
|
|
27891
|
+
const label = `${color59.cyan("\u{1F50D}")} ${color59.bold(header)} ${color59.dim(`(${packageFiles.length} package files)`)}`;
|
|
27561
27892
|
opts.renderer.write(label);
|
|
27562
27893
|
if (discoveryNote) opts.renderer.write(discoveryNote);
|
|
27563
27894
|
opts.renderer.write(
|
|
27564
|
-
|
|
27895
|
+
color59.dim(
|
|
27565
27896
|
`Spawning tech-stack subagent \u2192 writes ${outputFormat === "json" ? "techstack.json" : "techstack.md"} when done.`
|
|
27566
27897
|
)
|
|
27567
27898
|
);
|
|
@@ -27583,10 +27914,10 @@ function buildTechStackCommand(opts) {
|
|
|
27583
27914
|
}
|
|
27584
27915
|
|
|
27585
27916
|
// src/slash-commands/telegram-settings.ts
|
|
27586
|
-
import { color as
|
|
27917
|
+
import { color as color61, toErrorMessage as toErrorMessage26 } from "@wrongstack/core/utils";
|
|
27587
27918
|
|
|
27588
27919
|
// src/slash-commands/telegram-setup.ts
|
|
27589
|
-
import { color as
|
|
27920
|
+
import { color as color60 } from "@wrongstack/core/utils";
|
|
27590
27921
|
|
|
27591
27922
|
// src/slash-commands/telegram-pairing.ts
|
|
27592
27923
|
var DISCOVERY_LIMIT = 25;
|
|
@@ -27702,31 +28033,31 @@ function buildTelegramSetupCommand(opts) {
|
|
|
27702
28033
|
if (BOT_TOKEN_RE.test(first)) {
|
|
27703
28034
|
return {
|
|
27704
28035
|
message: [
|
|
27705
|
-
`${
|
|
27706
|
-
`Run ${
|
|
28036
|
+
`${color60.red("\u2717")} Bot tokens are no longer accepted as slash-command arguments.`,
|
|
28037
|
+
`Run ${color60.cyan("/telegram-setup [chatId]")} and enter it at the masked prompt.`
|
|
27707
28038
|
].join("\n")
|
|
27708
28039
|
};
|
|
27709
28040
|
}
|
|
27710
28041
|
if (parts.length > 1) {
|
|
27711
|
-
return { message: `${
|
|
28042
|
+
return { message: `${color60.amber("Usage:")} /telegram-setup [chatId]` };
|
|
27712
28043
|
}
|
|
27713
28044
|
if (!opts.readSecret || !opts.vault || !opts.paths?.globalConfig) {
|
|
27714
28045
|
return {
|
|
27715
|
-
message: `${
|
|
28046
|
+
message: `${color60.red("\u2717")} Secure Telegram setup is unavailable in this session.`
|
|
27716
28047
|
};
|
|
27717
28048
|
}
|
|
27718
28049
|
let botToken;
|
|
27719
28050
|
try {
|
|
27720
|
-
botToken = (await opts.readSecret(`Telegram bot token ${
|
|
28051
|
+
botToken = (await opts.readSecret(`Telegram bot token ${color60.dim("(hidden, paste OK)")}: `)).trim();
|
|
27721
28052
|
} catch {
|
|
27722
|
-
return { message:
|
|
28053
|
+
return { message: color60.dim("Telegram setup cancelled.") };
|
|
27723
28054
|
}
|
|
27724
|
-
if (!botToken) return { message:
|
|
28055
|
+
if (!botToken) return { message: color60.dim("Telegram setup cancelled.") };
|
|
27725
28056
|
if (!BOT_TOKEN_RE.test(botToken)) {
|
|
27726
28057
|
return {
|
|
27727
28058
|
message: [
|
|
27728
|
-
`${
|
|
27729
|
-
`Expected: ${
|
|
28059
|
+
`${color60.red("\u2717")} Invalid token format.`,
|
|
28060
|
+
`Expected: ${color60.dim("123456789:ABCdefGHIjkl...")}`,
|
|
27730
28061
|
"",
|
|
27731
28062
|
"Get a valid token from @BotFather on Telegram."
|
|
27732
28063
|
].join("\n")
|
|
@@ -27741,7 +28072,7 @@ function buildTelegramSetupCommand(opts) {
|
|
|
27741
28072
|
} catch {
|
|
27742
28073
|
return {
|
|
27743
28074
|
message: [
|
|
27744
|
-
`${
|
|
28075
|
+
`${color60.red("\u2717")} Could not reach Telegram API.`,
|
|
27745
28076
|
"",
|
|
27746
28077
|
"Check your network connection and try again."
|
|
27747
28078
|
].join("\n")
|
|
@@ -27750,7 +28081,7 @@ function buildTelegramSetupCommand(opts) {
|
|
|
27750
28081
|
if (!botInfo.ok || !botInfo.result) {
|
|
27751
28082
|
return {
|
|
27752
28083
|
message: [
|
|
27753
|
-
`${
|
|
28084
|
+
`${color60.red("\u2717")} Invalid bot token.`,
|
|
27754
28085
|
"",
|
|
27755
28086
|
"Get a valid token from @BotFather on Telegram."
|
|
27756
28087
|
].join("\n")
|
|
@@ -27760,13 +28091,13 @@ function buildTelegramSetupCommand(opts) {
|
|
|
27760
28091
|
const classifiedChatId = chatId ? classifyTelegramChatId(chatId) : void 0;
|
|
27761
28092
|
if (classifiedChatId?.kind === "invalid") {
|
|
27762
28093
|
return {
|
|
27763
|
-
message: `${
|
|
28094
|
+
message: `${color60.red("\u2717")} Invalid Telegram chat ID. Expected a positive private chat ID.`
|
|
27764
28095
|
};
|
|
27765
28096
|
}
|
|
27766
28097
|
if (classifiedChatId?.kind === "group") {
|
|
27767
28098
|
return {
|
|
27768
28099
|
message: [
|
|
27769
|
-
`${
|
|
28100
|
+
`${color60.amber("\u26A0")} Shared group, supergroup, and channel IDs cannot be paired by manual ID.`,
|
|
27770
28101
|
"Run /telegram-setup without a chat ID and select a discovered private identity.",
|
|
27771
28102
|
"No configuration was changed."
|
|
27772
28103
|
].join("\n")
|
|
@@ -27780,7 +28111,7 @@ function buildTelegramSetupCommand(opts) {
|
|
|
27780
28111
|
} catch {
|
|
27781
28112
|
return {
|
|
27782
28113
|
message: [
|
|
27783
|
-
`${
|
|
28114
|
+
`${color60.red("\u2717")} Could not discover recent Telegram chats.`,
|
|
27784
28115
|
"Message the bot once, then run /telegram-setup again.",
|
|
27785
28116
|
"No configuration was changed."
|
|
27786
28117
|
].join("\n")
|
|
@@ -27789,7 +28120,7 @@ function buildTelegramSetupCommand(opts) {
|
|
|
27789
28120
|
if (candidates.length === 0) {
|
|
27790
28121
|
return {
|
|
27791
28122
|
message: [
|
|
27792
|
-
`${
|
|
28123
|
+
`${color60.amber("No recent chats found.")}`,
|
|
27793
28124
|
"Message the bot from the private account you want to pair, then run setup again.",
|
|
27794
28125
|
"No configuration was changed."
|
|
27795
28126
|
].join("\n")
|
|
@@ -27797,31 +28128,31 @@ function buildTelegramSetupCommand(opts) {
|
|
|
27797
28128
|
}
|
|
27798
28129
|
opts.renderer.write(
|
|
27799
28130
|
[
|
|
27800
|
-
|
|
28131
|
+
color60.bold("Recent Telegram identities"),
|
|
27801
28132
|
formatTelegramPairingCandidates(candidates),
|
|
27802
28133
|
"",
|
|
27803
|
-
|
|
28134
|
+
color60.dim("Choose a private candidate number, or press Enter to cancel.")
|
|
27804
28135
|
].join("\n")
|
|
27805
28136
|
);
|
|
27806
28137
|
let choiceInput;
|
|
27807
28138
|
try {
|
|
27808
28139
|
choiceInput = opts.readText ? await opts.readText("Pair candidate \u203A ") : await opts.reader.readLine("Pair candidate \u203A ");
|
|
27809
28140
|
} catch {
|
|
27810
|
-
return { message:
|
|
28141
|
+
return { message: color60.dim("Telegram setup cancelled. No configuration was changed.") };
|
|
27811
28142
|
}
|
|
27812
28143
|
const choice = parseTelegramPairingChoice(choiceInput, candidates);
|
|
27813
28144
|
if (choice.kind === "cancel") {
|
|
27814
|
-
return { message:
|
|
28145
|
+
return { message: color60.dim("Telegram setup cancelled. No configuration was changed.") };
|
|
27815
28146
|
}
|
|
27816
28147
|
if (choice.kind === "invalid") {
|
|
27817
28148
|
return {
|
|
27818
|
-
message: `${
|
|
28149
|
+
message: `${color60.red("\u2717")} Invalid pairing choice. No configuration was changed.`
|
|
27819
28150
|
};
|
|
27820
28151
|
}
|
|
27821
28152
|
if (!choice.candidate.eligible) {
|
|
27822
28153
|
return {
|
|
27823
28154
|
message: [
|
|
27824
|
-
`${
|
|
28155
|
+
`${color60.amber("\u26A0")} Shared, group, or ambiguous identities are not paired automatically.`,
|
|
27825
28156
|
"Use a private chat where chat_id and user_id identify the same account.",
|
|
27826
28157
|
"No configuration was changed."
|
|
27827
28158
|
].join("\n")
|
|
@@ -27863,7 +28194,7 @@ function buildTelegramSetupCommand(opts) {
|
|
|
27863
28194
|
} catch {
|
|
27864
28195
|
return {
|
|
27865
28196
|
message: [
|
|
27866
|
-
`${
|
|
28197
|
+
`${color60.red("\u2717")} Failed to save Telegram configuration.`,
|
|
27867
28198
|
"The token was not printed. Check the config path and vault, then try again."
|
|
27868
28199
|
].join("\n")
|
|
27869
28200
|
};
|
|
@@ -27871,15 +28202,15 @@ function buildTelegramSetupCommand(opts) {
|
|
|
27871
28202
|
const bot = botInfo.result;
|
|
27872
28203
|
return {
|
|
27873
28204
|
message: [
|
|
27874
|
-
`${
|
|
28205
|
+
`${color60.green("\u2713")} Telegram configured successfully.`,
|
|
27875
28206
|
"",
|
|
27876
|
-
`Bot: ${
|
|
28207
|
+
`Bot: ${color60.bold(`@${bot.username ?? bot.first_name}`)}`,
|
|
27877
28208
|
...pairedCandidate ? [
|
|
27878
|
-
`Paired private chat: ${
|
|
27879
|
-
`Paired user: ${
|
|
27880
|
-
] : chatId ? [`Default chat: ${
|
|
28209
|
+
`Paired private chat: ${color60.green(String(pairedCandidate.chatId))}`,
|
|
28210
|
+
`Paired user: ${color60.green(String(pairedCandidate.userId))}`
|
|
28211
|
+
] : chatId ? [`Default chat: ${color60.green(chatId)}`] : [],
|
|
27881
28212
|
"",
|
|
27882
|
-
`${
|
|
28213
|
+
`${color60.amber("\u26A0")} Restart WrongStack for the plugin to load the new token.`
|
|
27883
28214
|
].join("\n")
|
|
27884
28215
|
};
|
|
27885
28216
|
}
|
|
@@ -27913,15 +28244,15 @@ function buildTelegramSettingsCommand(opts) {
|
|
|
27913
28244
|
const chat = tg.notifyChatId !== void 0 && tg.notifyChatId !== null ? String(tg.notifyChatId) : "not set";
|
|
27914
28245
|
const hasToken = typeof tg.botToken === "string" && tg.botToken.length > 0;
|
|
27915
28246
|
return [
|
|
27916
|
-
`${
|
|
28247
|
+
`${color61.bold("Telegram")} ${color61.dim("\u2014 Notification Settings")}`,
|
|
27917
28248
|
"",
|
|
27918
|
-
` session end: ${sessionEnd ?
|
|
27919
|
-
` delegate done: ${delegate ?
|
|
27920
|
-
` long tool: ${
|
|
27921
|
-
` poll interval: ${
|
|
27922
|
-
` notify chat: ${
|
|
28249
|
+
` session end: ${sessionEnd ? color61.cyan("on") : color61.dim("off")} ${color61.dim("change: /telegram-settings session-end on|off")}`,
|
|
28250
|
+
` delegate done: ${delegate ? color61.cyan("on") : color61.dim("off")} ${color61.dim("change: /telegram-settings delegate on|off")}`,
|
|
28251
|
+
` long tool: ${color61.cyan(longTool)} ${color61.dim("change: /telegram-settings long-tool <ms|off>")}`,
|
|
28252
|
+
` poll interval: ${color61.cyan(poll)} ${color61.dim("change: /telegram-settings poll <seconds>")}`,
|
|
28253
|
+
` notify chat: ${color61.cyan(chat)} ${color61.dim("change: /telegram-settings chat <chatId>")}`,
|
|
27923
28254
|
"",
|
|
27924
|
-
hasToken ?
|
|
28255
|
+
hasToken ? color61.dim(" Bot token configured. Changes apply immediately.") : `${color61.amber("\u26A0")} No bot token configured. Run: /telegram-setup <botToken> [chatId]`
|
|
27925
28256
|
].join("\n");
|
|
27926
28257
|
}
|
|
27927
28258
|
return {
|
|
@@ -27937,7 +28268,7 @@ function buildTelegramSettingsCommand(opts) {
|
|
|
27937
28268
|
return { message: HELP2 };
|
|
27938
28269
|
}
|
|
27939
28270
|
if (!opts.configStore || !opts.paths?.globalConfig || !opts.vault) {
|
|
27940
|
-
return { message: `${
|
|
28271
|
+
return { message: `${color61.red("Error")} secure config persistence not available.` };
|
|
27941
28272
|
}
|
|
27942
28273
|
if (!sub) {
|
|
27943
28274
|
return { message: currentView() };
|
|
@@ -27951,7 +28282,7 @@ function buildTelegramSettingsCommand(opts) {
|
|
|
27951
28282
|
if (sub === "all") {
|
|
27952
28283
|
const raw = (rest[0] ?? "").toLowerCase();
|
|
27953
28284
|
if (!["on", "off"].includes(raw)) {
|
|
27954
|
-
return { message: `${
|
|
28285
|
+
return { message: `${color61.amber("Usage:")} /telegram-settings all on|off` };
|
|
27955
28286
|
}
|
|
27956
28287
|
const on = raw === "on";
|
|
27957
28288
|
await persistTelegramConfig(persistDeps, (tg) => {
|
|
@@ -27959,40 +28290,40 @@ function buildTelegramSettingsCommand(opts) {
|
|
|
27959
28290
|
tg.notifyOnDelegate = on;
|
|
27960
28291
|
});
|
|
27961
28292
|
return {
|
|
27962
|
-
message: `${
|
|
28293
|
+
message: `${color61.green("\u2713")} all event notifications \u2192 ${on ? color61.cyan("on") : color61.dim("off")} ${color61.dim("(session-end, delegate)")}`
|
|
27963
28294
|
};
|
|
27964
28295
|
}
|
|
27965
28296
|
if (sub === "session-end") {
|
|
27966
28297
|
const raw = (rest[0] ?? "").toLowerCase();
|
|
27967
28298
|
if (!["on", "off"].includes(raw)) {
|
|
27968
|
-
return { message: `${
|
|
28299
|
+
return { message: `${color61.amber("Usage:")} /telegram-settings session-end on|off` };
|
|
27969
28300
|
}
|
|
27970
28301
|
const on = raw === "on";
|
|
27971
28302
|
await persistTelegramConfig(persistDeps, (tg) => {
|
|
27972
28303
|
tg.notifyOnSessionEnd = on;
|
|
27973
28304
|
});
|
|
27974
28305
|
return {
|
|
27975
|
-
message: `${
|
|
28306
|
+
message: `${color61.green("\u2713")} session-end \u2192 ${on ? color61.cyan("on") : color61.dim("off")}`
|
|
27976
28307
|
};
|
|
27977
28308
|
}
|
|
27978
28309
|
if (sub === "delegate") {
|
|
27979
28310
|
const raw = (rest[0] ?? "").toLowerCase();
|
|
27980
28311
|
if (!["on", "off"].includes(raw)) {
|
|
27981
|
-
return { message: `${
|
|
28312
|
+
return { message: `${color61.amber("Usage:")} /telegram-settings delegate on|off` };
|
|
27982
28313
|
}
|
|
27983
28314
|
const on = raw === "on";
|
|
27984
28315
|
await persistTelegramConfig(persistDeps, (tg) => {
|
|
27985
28316
|
tg.notifyOnDelegate = on;
|
|
27986
28317
|
});
|
|
27987
28318
|
return {
|
|
27988
|
-
message: `${
|
|
28319
|
+
message: `${color61.green("\u2713")} delegate \u2192 ${on ? color61.cyan("on") : color61.dim("off")}`
|
|
27989
28320
|
};
|
|
27990
28321
|
}
|
|
27991
28322
|
if (sub === "long-tool") {
|
|
27992
28323
|
const raw = rest[0];
|
|
27993
28324
|
if (raw === void 0) {
|
|
27994
28325
|
return {
|
|
27995
|
-
message: `${
|
|
28326
|
+
message: `${color61.amber("Usage:")} /telegram-settings long-tool <ms|off> ${color61.dim("(0 or off disables)")}`
|
|
27996
28327
|
};
|
|
27997
28328
|
}
|
|
27998
28329
|
if (raw === "off") {
|
|
@@ -28000,57 +28331,57 @@ function buildTelegramSettingsCommand(opts) {
|
|
|
28000
28331
|
tg.longToolThresholdMs = 0;
|
|
28001
28332
|
});
|
|
28002
28333
|
return {
|
|
28003
|
-
message: `${
|
|
28334
|
+
message: `${color61.green("\u2713")} long-tool \u2192 ${color61.dim("off")}`
|
|
28004
28335
|
};
|
|
28005
28336
|
}
|
|
28006
28337
|
const ms = Number.parseInt(raw, 10);
|
|
28007
28338
|
if (Number.isNaN(ms) || ms < 0) {
|
|
28008
28339
|
return {
|
|
28009
|
-
message: `${
|
|
28340
|
+
message: `${color61.red("Invalid number")}: "${raw}". Enter milliseconds, e.g. /telegram-settings long-tool 15000`
|
|
28010
28341
|
};
|
|
28011
28342
|
}
|
|
28012
28343
|
await persistTelegramConfig(persistDeps, (tg) => {
|
|
28013
28344
|
tg.longToolThresholdMs = ms;
|
|
28014
28345
|
});
|
|
28015
28346
|
return {
|
|
28016
|
-
message: `${
|
|
28347
|
+
message: `${color61.green("\u2713")} long-tool \u2192 ${color61.cyan(`${ms}ms`)}`
|
|
28017
28348
|
};
|
|
28018
28349
|
}
|
|
28019
28350
|
if (sub === "poll") {
|
|
28020
28351
|
const raw = rest[0];
|
|
28021
28352
|
if (raw === void 0) {
|
|
28022
28353
|
return {
|
|
28023
|
-
message: `${
|
|
28354
|
+
message: `${color61.amber("Usage:")} /telegram-settings poll <seconds> ${color61.dim("(1\u201360)")}`
|
|
28024
28355
|
};
|
|
28025
28356
|
}
|
|
28026
28357
|
const sec = Number.parseInt(raw, 10);
|
|
28027
28358
|
if (Number.isNaN(sec) || sec < 1 || sec > 60) {
|
|
28028
28359
|
return {
|
|
28029
|
-
message: `${
|
|
28360
|
+
message: `${color61.red("Invalid value")}: "${raw}". Enter seconds between 1 and 60.`
|
|
28030
28361
|
};
|
|
28031
28362
|
}
|
|
28032
28363
|
await persistTelegramConfig(persistDeps, (tg) => {
|
|
28033
28364
|
tg.pollIntervalSec = sec;
|
|
28034
28365
|
});
|
|
28035
28366
|
return {
|
|
28036
|
-
message: `${
|
|
28367
|
+
message: `${color61.green("\u2713")} poll \u2192 ${color61.cyan(`${sec}s`)}`
|
|
28037
28368
|
};
|
|
28038
28369
|
}
|
|
28039
28370
|
if (sub === "chat") {
|
|
28040
28371
|
const raw = rest[0];
|
|
28041
28372
|
if (!raw) {
|
|
28042
|
-
return { message: `${
|
|
28373
|
+
return { message: `${color61.amber("Usage:")} /telegram-settings chat <chatId>` };
|
|
28043
28374
|
}
|
|
28044
28375
|
const classification = classifyTelegramChatId(raw);
|
|
28045
28376
|
if (classification.kind === "invalid") {
|
|
28046
|
-
return { message: `${
|
|
28377
|
+
return { message: `${color61.red("Invalid chat ID")}: expected a non-zero integer.` };
|
|
28047
28378
|
}
|
|
28048
28379
|
const current = opts.configStore.get();
|
|
28049
28380
|
const allowGroupChats = current.extensions?.telegram?.allowGroupChats === true;
|
|
28050
28381
|
if (classification.kind === "group" && !allowGroupChats) {
|
|
28051
28382
|
return {
|
|
28052
28383
|
message: [
|
|
28053
|
-
`${
|
|
28384
|
+
`${color61.amber("\u26A0")} Group, supergroup, and channel targets require explicit allowGroupChats=true.`,
|
|
28054
28385
|
"No configuration was changed."
|
|
28055
28386
|
].join("\n")
|
|
28056
28387
|
};
|
|
@@ -28073,15 +28404,15 @@ function buildTelegramSettingsCommand(opts) {
|
|
|
28073
28404
|
}
|
|
28074
28405
|
});
|
|
28075
28406
|
return {
|
|
28076
|
-
message: `${
|
|
28407
|
+
message: `${color61.green("\u2713")} notify chat \u2192 ${color61.cyan(raw)}`
|
|
28077
28408
|
};
|
|
28078
28409
|
}
|
|
28079
28410
|
return {
|
|
28080
|
-
message: `${
|
|
28411
|
+
message: `${color61.red("Unknown setting")} "${sub}". ${unknownSubcommand(sub, ["session-end", "delegate", "long-tool", "poll", "chat", "all"], "telegram-settings")}`
|
|
28081
28412
|
};
|
|
28082
28413
|
} catch (err) {
|
|
28083
28414
|
return {
|
|
28084
|
-
message: `${
|
|
28415
|
+
message: `${color61.red("Settings error")}: ${toErrorMessage26(err)}`
|
|
28085
28416
|
};
|
|
28086
28417
|
}
|
|
28087
28418
|
}
|
|
@@ -28227,9 +28558,9 @@ function buildTodosCommand(opts) {
|
|
|
28227
28558
|
}
|
|
28228
28559
|
|
|
28229
28560
|
// src/slash-commands/tool.ts
|
|
28230
|
-
import { noOpVault as
|
|
28561
|
+
import { noOpVault as noOpVault11 } from "@wrongstack/core/security";
|
|
28231
28562
|
import {
|
|
28232
|
-
color as
|
|
28563
|
+
color as color62,
|
|
28233
28564
|
getToolDescriptionMode,
|
|
28234
28565
|
getToolResultRenderMode,
|
|
28235
28566
|
normalizeToolDescriptionMode,
|
|
@@ -28243,11 +28574,11 @@ function fit(text, width) {
|
|
|
28243
28574
|
}
|
|
28244
28575
|
function formatDescriptionMode(mode) {
|
|
28245
28576
|
const raw = `desc:${mode}`;
|
|
28246
|
-
return mode === "simple" ?
|
|
28577
|
+
return mode === "simple" ? color62.amber(raw) : color62.cyan(raw);
|
|
28247
28578
|
}
|
|
28248
28579
|
function formatResultRenderMode(mode) {
|
|
28249
28580
|
const raw = `result:${mode}`;
|
|
28250
|
-
return mode === "simple" ?
|
|
28581
|
+
return mode === "simple" ? color62.amber(raw) : color62.cyan(raw);
|
|
28251
28582
|
}
|
|
28252
28583
|
function buildToolCommand(opts) {
|
|
28253
28584
|
const help = [
|
|
@@ -28311,7 +28642,7 @@ function buildToolCommand(opts) {
|
|
|
28311
28642
|
configStore: opts.configStore,
|
|
28312
28643
|
profileConfigPath: activeProfileConfigPath(opts.paths, opts.configStore.get()),
|
|
28313
28644
|
inProjectConfigPath: opts.paths.inProjectConfig,
|
|
28314
|
-
vault:
|
|
28645
|
+
vault: noOpVault11
|
|
28315
28646
|
},
|
|
28316
28647
|
(cfg) => {
|
|
28317
28648
|
cfg.tools = next;
|
|
@@ -28340,7 +28671,7 @@ function buildToolCommand(opts) {
|
|
|
28340
28671
|
configStore: opts.configStore,
|
|
28341
28672
|
profileConfigPath: activeProfileConfigPath(opts.paths, opts.configStore.get()),
|
|
28342
28673
|
inProjectConfigPath: opts.paths.inProjectConfig,
|
|
28343
|
-
vault:
|
|
28674
|
+
vault: noOpVault11
|
|
28344
28675
|
},
|
|
28345
28676
|
(cfg) => {
|
|
28346
28677
|
cfg.tools = nextTools;
|
|
@@ -28353,38 +28684,38 @@ function buildToolCommand(opts) {
|
|
|
28353
28684
|
const resultSimple = Object.entries(configured.resultRenderMode ?? {}).filter(([, mode]) => normalizeToolResultRenderMode(mode) === "simple").map(([name]) => name).sort();
|
|
28354
28685
|
const disabled = opts.toolRegistry.listDisabled();
|
|
28355
28686
|
const lines = [
|
|
28356
|
-
`${
|
|
28687
|
+
`${color62.bold("Tool modes")} ${color62.dim("(default: extend on both axes)")}`,
|
|
28357
28688
|
"",
|
|
28358
|
-
`${formatDescriptionMode("simple")}: ${descSimple.length > 0 ? descSimple.map((n) =>
|
|
28359
|
-
`${formatResultRenderMode("simple")}: ${resultSimple.length > 0 ? resultSimple.map((n) =>
|
|
28689
|
+
`${formatDescriptionMode("simple")}: ${descSimple.length > 0 ? descSimple.map((n) => color62.cyan(n)).join(", ") : color62.dim("none")}`,
|
|
28690
|
+
`${formatResultRenderMode("simple")}: ${resultSimple.length > 0 ? resultSimple.map((n) => color62.cyan(n)).join(", ") : color62.dim("none")}`,
|
|
28360
28691
|
""
|
|
28361
28692
|
];
|
|
28362
28693
|
if (disabled.length > 0) {
|
|
28363
28694
|
lines.push(
|
|
28364
|
-
`${
|
|
28695
|
+
`${color62.bold("Disabled tools")}`,
|
|
28365
28696
|
"",
|
|
28366
|
-
` ${
|
|
28697
|
+
` ${color62.red("disabled")}: ${disabled.map(({ tool }) => color62.dim(tool.name)).join(", ")}`,
|
|
28367
28698
|
""
|
|
28368
28699
|
);
|
|
28369
28700
|
}
|
|
28370
28701
|
lines.push(
|
|
28371
|
-
|
|
28702
|
+
color62.dim(
|
|
28372
28703
|
" /tool <name> desc simple \xB7 /tool <name> result simple \xB7 /tool list \xB7 /tool disable|enable <name>"
|
|
28373
28704
|
)
|
|
28374
28705
|
);
|
|
28375
28706
|
return lines.join("\n");
|
|
28376
28707
|
}
|
|
28377
28708
|
function formatList() {
|
|
28378
|
-
const header = ` ${
|
|
28709
|
+
const header = ` ${color62.dim(fit("tool", 28))} ${color62.dim(fit("owner", 28))} ${color62.dim(fit("status", 10))} ${color62.dim(fit("desc", 14))} ` + color62.dim("result");
|
|
28379
28710
|
const rows = opts.toolRegistry.listWithOwner().map(({ tool }) => {
|
|
28380
28711
|
const descMode = getToolDescriptionMode(opts.toolRegistry, tool.name);
|
|
28381
28712
|
const resultMode = getToolResultRenderMode(opts.toolRegistry, tool.name);
|
|
28382
28713
|
const owner = opts.toolRegistry.ownerOf(tool.name) ?? "core";
|
|
28383
|
-
const status = opts.toolRegistry.isDisabled(tool.name) ?
|
|
28384
|
-
return ` ${fit(tool.name, 28)} ${
|
|
28714
|
+
const status = opts.toolRegistry.isDisabled(tool.name) ? color62.red("disabled") : color62.green("active");
|
|
28715
|
+
return ` ${fit(tool.name, 28)} ${color62.dim(fit(`[${owner}]`, 28))} ${fit(status, 10)} ${fit(formatDescriptionMode(descMode), 14)} ` + formatResultRenderMode(resultMode);
|
|
28385
28716
|
});
|
|
28386
28717
|
return [
|
|
28387
|
-
`${
|
|
28718
|
+
`${color62.bold("Tool modes")} ${color62.dim("(default: extend on both axes)")}`,
|
|
28388
28719
|
"",
|
|
28389
28720
|
header,
|
|
28390
28721
|
...rows
|
|
@@ -28395,55 +28726,55 @@ function buildToolCommand(opts) {
|
|
|
28395
28726
|
const tool = reg.get(name);
|
|
28396
28727
|
if (!tool) {
|
|
28397
28728
|
if (reg.isDisabled(name)) {
|
|
28398
|
-
return `${
|
|
28729
|
+
return `${color62.amber(name)} is disabled. Use ${color62.dim(`/tool enable ${name}`)} to restore.`;
|
|
28399
28730
|
}
|
|
28400
|
-
return `${
|
|
28731
|
+
return `${color62.red("Unknown tool")}: ${name}. Use ${color62.dim("/tools")} to list registered tools.`;
|
|
28401
28732
|
}
|
|
28402
28733
|
const descMode = getToolDescriptionMode(reg, name);
|
|
28403
28734
|
const resultMode = getToolResultRenderMode(reg, name);
|
|
28404
|
-
const status = reg.isDisabled(name) ?
|
|
28735
|
+
const status = reg.isDisabled(name) ? color62.red("disabled") : color62.green("active");
|
|
28405
28736
|
return [
|
|
28406
|
-
`${
|
|
28737
|
+
`${color62.bold(name)} ${status}`,
|
|
28407
28738
|
`description mode: ${formatDescriptionMode(descMode)}`,
|
|
28408
28739
|
`result mode: ${formatResultRenderMode(resultMode)}`,
|
|
28409
28740
|
"",
|
|
28410
|
-
|
|
28741
|
+
color62.dim(tool.description)
|
|
28411
28742
|
].join("\n");
|
|
28412
28743
|
}
|
|
28413
28744
|
async function cmdEnable(name) {
|
|
28414
28745
|
const reg = opts.toolRegistry;
|
|
28415
28746
|
if (!reg.isDisabled(name)) {
|
|
28416
|
-
return `${
|
|
28747
|
+
return `${color62.amber(name)} is not disabled.`;
|
|
28417
28748
|
}
|
|
28418
28749
|
const ok = reg.enable(name);
|
|
28419
|
-
if (!ok) return `${
|
|
28750
|
+
if (!ok) return `${color62.red("Could not enable")}: ${name}.`;
|
|
28420
28751
|
const disabled = currentDisabledSet();
|
|
28421
28752
|
disabled.delete(name);
|
|
28422
28753
|
await persistDisabled(Array.from(disabled));
|
|
28423
|
-
return `${
|
|
28754
|
+
return `${color62.green("\u2713")} ${color62.cyan(name)} re-enabled \u2014 will appear in next provider request.`;
|
|
28424
28755
|
}
|
|
28425
28756
|
async function cmdEnableAll() {
|
|
28426
28757
|
const reg = opts.toolRegistry;
|
|
28427
28758
|
const count = reg.enableAll();
|
|
28428
|
-
if (count === 0) return `${
|
|
28759
|
+
if (count === 0) return `${color62.amber("No disabled tools to re-enable.")}`;
|
|
28429
28760
|
await persistDisabled([]);
|
|
28430
|
-
return `${
|
|
28761
|
+
return `${color62.green("\u2713")} All ${count} disabled tool(s) re-enabled.`;
|
|
28431
28762
|
}
|
|
28432
28763
|
async function cmdDisable(name) {
|
|
28433
28764
|
const reg = opts.toolRegistry;
|
|
28434
28765
|
const tool = reg.get(name);
|
|
28435
28766
|
if (!tool) {
|
|
28436
28767
|
if (reg.isDisabled(name)) {
|
|
28437
|
-
return `${
|
|
28768
|
+
return `${color62.amber(name)} is already disabled.`;
|
|
28438
28769
|
}
|
|
28439
|
-
return `${
|
|
28770
|
+
return `${color62.red("Unknown tool")}: ${name}. Use ${color62.dim("/tools")} to list registered tools.`;
|
|
28440
28771
|
}
|
|
28441
28772
|
const ok = reg.disable(name);
|
|
28442
|
-
if (!ok) return `${
|
|
28773
|
+
if (!ok) return `${color62.red("Could not disable")}: ${name}.`;
|
|
28443
28774
|
const disabled = currentDisabledSet();
|
|
28444
28775
|
disabled.add(name);
|
|
28445
28776
|
await persistDisabled(Array.from(disabled));
|
|
28446
|
-
return `${
|
|
28777
|
+
return `${color62.green("\u2713")} ${color62.cyan(name)} disabled \u2014 removed from system prompt and tool registry.`;
|
|
28447
28778
|
}
|
|
28448
28779
|
function applyDescMode(name, mode) {
|
|
28449
28780
|
opts.toolRegistry.setDescriptionMode?.(name, mode);
|
|
@@ -28459,7 +28790,7 @@ function buildToolCommand(opts) {
|
|
|
28459
28790
|
help,
|
|
28460
28791
|
async run(args) {
|
|
28461
28792
|
if (!opts.configStore) {
|
|
28462
|
-
return { message: `${
|
|
28793
|
+
return { message: `${color62.red("Error")} config store not available.` };
|
|
28463
28794
|
}
|
|
28464
28795
|
const parts = args.trim().split(/\s+/).filter(Boolean);
|
|
28465
28796
|
const sub = (parts[0] ?? "").toLowerCase();
|
|
@@ -28470,7 +28801,7 @@ function buildToolCommand(opts) {
|
|
|
28470
28801
|
try {
|
|
28471
28802
|
return { message: await cmdEnableAll() };
|
|
28472
28803
|
} catch (err) {
|
|
28473
|
-
return { message: `${
|
|
28804
|
+
return { message: `${color62.red("Error")}: ${toErrorMessage27(err)}` };
|
|
28474
28805
|
}
|
|
28475
28806
|
}
|
|
28476
28807
|
const name = parts[0] ?? "";
|
|
@@ -28478,43 +28809,43 @@ function buildToolCommand(opts) {
|
|
|
28478
28809
|
if (sub === "disable") {
|
|
28479
28810
|
const targets = parts.slice(1);
|
|
28480
28811
|
if (targets.length === 0)
|
|
28481
|
-
return { message: `${
|
|
28812
|
+
return { message: `${color62.amber("Usage:")} /tool disable <name> [name...]` };
|
|
28482
28813
|
try {
|
|
28483
28814
|
const results = [];
|
|
28484
28815
|
for (const t of targets) results.push(await cmdDisable(t));
|
|
28485
28816
|
return { message: results.join("\n") };
|
|
28486
28817
|
} catch (err) {
|
|
28487
|
-
return { message: `${
|
|
28818
|
+
return { message: `${color62.red("Error")}: ${toErrorMessage27(err)}` };
|
|
28488
28819
|
}
|
|
28489
28820
|
}
|
|
28490
28821
|
if (sub === "enable") {
|
|
28491
28822
|
const targets = parts.slice(1);
|
|
28492
28823
|
if (targets.length === 0)
|
|
28493
|
-
return { message: `${
|
|
28824
|
+
return { message: `${color62.amber("Usage:")} /tool enable <name> [name...]` };
|
|
28494
28825
|
try {
|
|
28495
28826
|
const results = [];
|
|
28496
28827
|
for (const t of targets) results.push(await cmdEnable(t));
|
|
28497
28828
|
return { message: results.join("\n") };
|
|
28498
28829
|
} catch (err) {
|
|
28499
|
-
return { message: `${
|
|
28830
|
+
return { message: `${color62.red("Error")}: ${toErrorMessage27(err)}` };
|
|
28500
28831
|
}
|
|
28501
28832
|
}
|
|
28502
28833
|
const action = parts[1]?.toLowerCase();
|
|
28503
28834
|
if (action === "disable" || action === "enable") {
|
|
28504
28835
|
if (parts.length > 2) {
|
|
28505
28836
|
return {
|
|
28506
|
-
message: `${
|
|
28837
|
+
message: `${color62.amber("Usage:")} /tool ${name} ${action}`
|
|
28507
28838
|
};
|
|
28508
28839
|
}
|
|
28509
28840
|
try {
|
|
28510
28841
|
return { message: action === "disable" ? await cmdDisable(name) : await cmdEnable(name) };
|
|
28511
28842
|
} catch (err) {
|
|
28512
|
-
return { message: `${
|
|
28843
|
+
return { message: `${color62.red("Error")}: ${toErrorMessage27(err)}` };
|
|
28513
28844
|
}
|
|
28514
28845
|
}
|
|
28515
28846
|
if (!opts.toolRegistry.get(name) && !opts.toolRegistry.isDisabled(name)) {
|
|
28516
28847
|
return {
|
|
28517
|
-
message: `${
|
|
28848
|
+
message: `${color62.red("Unknown tool")}: ${name}. Use ${color62.dim("/tools")} to list registered tools.`
|
|
28518
28849
|
};
|
|
28519
28850
|
}
|
|
28520
28851
|
if (parts.length === 1) return { message: formatOne(name) };
|
|
@@ -28523,53 +28854,53 @@ function buildToolCommand(opts) {
|
|
|
28523
28854
|
const rawMode = parts[2];
|
|
28524
28855
|
if (!rawMode) {
|
|
28525
28856
|
return {
|
|
28526
|
-
message: `${
|
|
28857
|
+
message: `${color62.amber("Usage:")} /tool ${name} ${axis} simple|extend`
|
|
28527
28858
|
};
|
|
28528
28859
|
}
|
|
28529
28860
|
const mode2 = normalizeToolDescriptionMode(rawMode);
|
|
28530
28861
|
if (!mode2) {
|
|
28531
28862
|
return {
|
|
28532
|
-
message: `${
|
|
28863
|
+
message: `${color62.amber("Usage:")} /tool ${name} ${axis} simple|extend`
|
|
28533
28864
|
};
|
|
28534
28865
|
}
|
|
28535
28866
|
try {
|
|
28536
28867
|
if (axis === "desc") {
|
|
28537
28868
|
const persisted2 = await persistModeForAxis(name, "desc", mode2);
|
|
28538
28869
|
applyDescMode(name, mode2);
|
|
28539
|
-
const persistence2 = persisted2 ?
|
|
28870
|
+
const persistence2 = persisted2 ? color62.dim("saved") : color62.dim("runtime only; config paths unavailable");
|
|
28540
28871
|
return {
|
|
28541
|
-
message: `${
|
|
28872
|
+
message: `${color62.green("\u2713")} ${color62.cyan(name)} ${formatDescriptionMode(mode2)} ${persistence2}`
|
|
28542
28873
|
};
|
|
28543
28874
|
}
|
|
28544
28875
|
const persisted = await persistModeForAxis(name, "result", mode2);
|
|
28545
28876
|
applyResultMode(name, mode2);
|
|
28546
|
-
const persistence = persisted ?
|
|
28877
|
+
const persistence = persisted ? color62.dim("saved") : color62.dim("runtime only; config paths unavailable");
|
|
28547
28878
|
return {
|
|
28548
|
-
message: `${
|
|
28879
|
+
message: `${color62.green("\u2713")} ${color62.cyan(name)} ${formatResultRenderMode(mode2)} ${persistence}`
|
|
28549
28880
|
};
|
|
28550
28881
|
} catch (err) {
|
|
28551
28882
|
return {
|
|
28552
|
-
message: `${
|
|
28883
|
+
message: `${color62.red("Could not save tool setting")}: ${toErrorMessage27(err)}`
|
|
28553
28884
|
};
|
|
28554
28885
|
}
|
|
28555
28886
|
}
|
|
28556
28887
|
const mode = normalizeToolDescriptionMode(axis);
|
|
28557
28888
|
if (!mode) {
|
|
28558
28889
|
return {
|
|
28559
|
-
message: `${
|
|
28890
|
+
message: `${color62.amber("Usage:")} /tool ${name} [desc|result] simple|extend`
|
|
28560
28891
|
};
|
|
28561
28892
|
}
|
|
28562
28893
|
try {
|
|
28563
28894
|
const persisted = await persistModeBoth(name, mode);
|
|
28564
28895
|
applyDescMode(name, mode);
|
|
28565
28896
|
applyResultMode(name, mode);
|
|
28566
|
-
const persistence = persisted ?
|
|
28897
|
+
const persistence = persisted ? color62.dim("saved (both axes)") : color62.dim("runtime only; config paths unavailable");
|
|
28567
28898
|
return {
|
|
28568
|
-
message: `${
|
|
28899
|
+
message: `${color62.green("\u2713")} ${color62.cyan(name)} ${formatDescriptionMode(mode)} + ${formatResultRenderMode(mode)} ${persistence}`
|
|
28569
28900
|
};
|
|
28570
28901
|
} catch (err) {
|
|
28571
28902
|
return {
|
|
28572
|
-
message: `${
|
|
28903
|
+
message: `${color62.red("Could not save tool setting")}: ${toErrorMessage27(err)}`
|
|
28573
28904
|
};
|
|
28574
28905
|
}
|
|
28575
28906
|
}
|
|
@@ -28577,14 +28908,14 @@ function buildToolCommand(opts) {
|
|
|
28577
28908
|
}
|
|
28578
28909
|
|
|
28579
28910
|
// src/slash-commands/tools.ts
|
|
28580
|
-
import { color as
|
|
28911
|
+
import { color as color63, getToolDescriptionMode as getToolDescriptionMode2 } from "@wrongstack/core/utils";
|
|
28581
28912
|
function fit2(text, width) {
|
|
28582
28913
|
if (text.length <= width) return text.padEnd(width);
|
|
28583
28914
|
return `${text.slice(0, Math.max(0, width - 3))}...`;
|
|
28584
28915
|
}
|
|
28585
28916
|
function formatDescriptionMode2(mode) {
|
|
28586
28917
|
const raw = `desc:${mode}`;
|
|
28587
|
-
return mode === "simple" ?
|
|
28918
|
+
return mode === "simple" ? color63.amber(raw) : color63.dim(raw);
|
|
28588
28919
|
}
|
|
28589
28920
|
function buildToolsCommand(opts) {
|
|
28590
28921
|
return {
|
|
@@ -28605,21 +28936,21 @@ function buildToolsCommand(opts) {
|
|
|
28605
28936
|
if (opened) return { message: "" };
|
|
28606
28937
|
}
|
|
28607
28938
|
if (filter && all.length === 0) {
|
|
28608
|
-
const msg2 = `${
|
|
28939
|
+
const msg2 = `${color63.bold("Tools")} \u2014 no tool name or owner matched "${filter}".`;
|
|
28609
28940
|
opts.renderer.write(msg2);
|
|
28610
28941
|
return { message: msg2 };
|
|
28611
28942
|
}
|
|
28612
|
-
const header = ` ${
|
|
28943
|
+
const header = ` ${color63.dim(fit2("tool", 28))} ${color63.dim(fit2("owner", 28))} ${color63.dim(fit2("rw", 4))} ${color63.dim(fit2("perm", 8))} ${color63.dim(fit2("status", 10))} ` + color63.dim("description");
|
|
28613
28944
|
const lines = all.map(({ tool, owner }) => {
|
|
28614
28945
|
const mode = getToolDescriptionMode2(reg, tool.name);
|
|
28615
|
-
const rw = tool.mutating ?
|
|
28616
|
-
const status = reg.isDisabled(tool.name) ?
|
|
28617
|
-
return ` ${fit2(tool.name, 28)} ${
|
|
28946
|
+
const rw = tool.mutating ? color63.yellow(fit2("mut", 4)) : color63.cyan(fit2("ro", 4));
|
|
28947
|
+
const status = reg.isDisabled(tool.name) ? color63.red("disabled") : color63.green("active");
|
|
28948
|
+
return ` ${fit2(tool.name, 28)} ${color63.dim(fit2(`[${owner}]`, 28))} ${rw} ${color63.dim(fit2(tool.permission, 8))} ${fit2(status, 10)} ` + formatDescriptionMode2(mode);
|
|
28618
28949
|
});
|
|
28619
28950
|
const extra = disabled.length > 0 ? `
|
|
28620
|
-
${
|
|
28621
|
-
const filterNote = filter ?
|
|
28622
|
-
const msg = `${
|
|
28951
|
+
${color63.dim(`${disabled.length} tool(s) disabled. Use /tool enable <name> or /tool enable-all to restore.`)}` : "";
|
|
28952
|
+
const filterNote = filter ? color63.dim(` matching "${filter}" (${all.length} of ${allTools.length})`) : "";
|
|
28953
|
+
const msg = `${color63.bold("Tools")}${filterNote} (${all.length} shown, ${disabled.length} disabled) ${color63.dim("description detail via /tool <name> simple|extend")}:
|
|
28623
28954
|
${header}
|
|
28624
28955
|
${lines.join("\n")}${extra}
|
|
28625
28956
|
`;
|
|
@@ -28630,10 +28961,10 @@ ${lines.join("\n")}${extra}
|
|
|
28630
28961
|
}
|
|
28631
28962
|
|
|
28632
28963
|
// src/slash-commands/tuneup.ts
|
|
28633
|
-
import * as
|
|
28964
|
+
import * as fs17 from "node:fs/promises";
|
|
28634
28965
|
import * as os3 from "node:os";
|
|
28635
28966
|
import * as path20 from "node:path";
|
|
28636
|
-
import { atomicWrite as
|
|
28967
|
+
import { atomicWrite as atomicWrite10, color as color64 } from "@wrongstack/core/utils";
|
|
28637
28968
|
|
|
28638
28969
|
// src/tuneup.ts
|
|
28639
28970
|
var DEFAULT_EAGER_MAX_CHARS = 24e3;
|
|
@@ -29111,17 +29442,17 @@ function buildTuneupCommand(opts) {
|
|
|
29111
29442
|
const parsed = parseArgs(args);
|
|
29112
29443
|
if (parsed.mode === "help") return { message: help };
|
|
29113
29444
|
if (parsed.mode === "usage") {
|
|
29114
|
-
return { message: `${
|
|
29445
|
+
return { message: `${color64.amber("Usage:")} /tuneup [fix [--power] [--pick] | deep]` };
|
|
29115
29446
|
}
|
|
29116
29447
|
if (!opts.paths) {
|
|
29117
|
-
return { message: `${
|
|
29448
|
+
return { message: `${color64.red("Error")} config paths not available.` };
|
|
29118
29449
|
}
|
|
29119
29450
|
const input = await gatherInput(opts, parsed.power);
|
|
29120
29451
|
const report = runTuneup(input);
|
|
29121
|
-
const lines = [`${
|
|
29452
|
+
const lines = [`${color64.bold("WrongStack")} ${color64.dim("\u2014 Tune-up")}`];
|
|
29122
29453
|
renderFindings(lines, report.findings);
|
|
29123
29454
|
if (parsed.mode === "deep") {
|
|
29124
|
-
lines.push("",
|
|
29455
|
+
lines.push("", color64.dim(" \u2192 asking the agent for a project-specific optimization plan\u2026"));
|
|
29125
29456
|
return { message: lines.join("\n"), runText: buildDeepPrompt(report) };
|
|
29126
29457
|
}
|
|
29127
29458
|
if (parsed.mode === "report") {
|
|
@@ -29143,18 +29474,18 @@ function buildTuneupCommand(opts) {
|
|
|
29143
29474
|
const applied = await applyActions(actions, opts);
|
|
29144
29475
|
lines.push("");
|
|
29145
29476
|
if (applied.messages.length === 0) {
|
|
29146
|
-
lines.push(
|
|
29477
|
+
lines.push(color64.dim(" no deterministic fixes to apply"));
|
|
29147
29478
|
} else {
|
|
29148
|
-
for (const m of applied.messages) lines.push(` ${
|
|
29479
|
+
for (const m of applied.messages) lines.push(` ${color64.green("\u2713")} ${m}`);
|
|
29149
29480
|
if (applied.changed) {
|
|
29150
29481
|
lines.push(
|
|
29151
|
-
` ${
|
|
29482
|
+
` ${color64.green("\u2713")} written ${color64.dim("(backup: config.json.last + timestamped .bak)")}`
|
|
29152
29483
|
);
|
|
29153
29484
|
}
|
|
29154
29485
|
}
|
|
29155
29486
|
const runText = report.agentHandoff || void 0;
|
|
29156
29487
|
if (runText) {
|
|
29157
|
-
lines.push("",
|
|
29488
|
+
lines.push("", color64.dim(" \u2192 handing instruction-file cleanups to the agent\u2026"));
|
|
29158
29489
|
}
|
|
29159
29490
|
return { message: lines.join("\n"), ...runText ? { runText } : {} };
|
|
29160
29491
|
}
|
|
@@ -29240,7 +29571,7 @@ async function gatherMemoryFiles(opts) {
|
|
|
29240
29571
|
const out = [];
|
|
29241
29572
|
for (const c of candidates) {
|
|
29242
29573
|
try {
|
|
29243
|
-
const content = await
|
|
29574
|
+
const content = await fs17.readFile(c.file, "utf8");
|
|
29244
29575
|
out.push({ label: c.label, path: c.file, content, committed: c.committed });
|
|
29245
29576
|
} catch {
|
|
29246
29577
|
}
|
|
@@ -29258,7 +29589,7 @@ async function gatherTrust(opts) {
|
|
|
29258
29589
|
const file = opts.paths?.projectTrust;
|
|
29259
29590
|
if (!file) return void 0;
|
|
29260
29591
|
try {
|
|
29261
|
-
const raw = await
|
|
29592
|
+
const raw = await fs17.readFile(file, "utf8");
|
|
29262
29593
|
const parsed = JSON.parse(raw);
|
|
29263
29594
|
if (parsed && typeof parsed === "object") return parsed;
|
|
29264
29595
|
} catch {
|
|
@@ -29269,7 +29600,7 @@ async function gatherConfigIssues(opts) {
|
|
|
29269
29600
|
if (!opts.paths) return 0;
|
|
29270
29601
|
const file = activeProfileConfigPath(opts.paths, opts.configStore.get());
|
|
29271
29602
|
try {
|
|
29272
|
-
const raw = await
|
|
29603
|
+
const raw = await fs17.readFile(file, "utf8");
|
|
29273
29604
|
const parsed = JSON.parse(raw);
|
|
29274
29605
|
return diagnoseConfig(parsed).findings.length;
|
|
29275
29606
|
} catch {
|
|
@@ -29287,14 +29618,14 @@ async function gatherSessionBytes(opts) {
|
|
|
29287
29618
|
}
|
|
29288
29619
|
async function dirSize(dir) {
|
|
29289
29620
|
let total = 0;
|
|
29290
|
-
const entries = await
|
|
29621
|
+
const entries = await fs17.readdir(dir, { withFileTypes: true });
|
|
29291
29622
|
for (const e of entries) {
|
|
29292
29623
|
const full = path20.join(dir, e.name);
|
|
29293
29624
|
if (e.isDirectory()) {
|
|
29294
29625
|
total += await dirSize(full);
|
|
29295
29626
|
} else if (e.isFile()) {
|
|
29296
29627
|
try {
|
|
29297
|
-
total += (await
|
|
29628
|
+
total += (await fs17.stat(full)).size;
|
|
29298
29629
|
} catch {
|
|
29299
29630
|
}
|
|
29300
29631
|
}
|
|
@@ -29307,7 +29638,7 @@ async function applyActions(actions, opts) {
|
|
|
29307
29638
|
const file = activeProfileConfigPath(opts.paths, opts.configStore.get());
|
|
29308
29639
|
let raw = "{}";
|
|
29309
29640
|
try {
|
|
29310
|
-
raw = await
|
|
29641
|
+
raw = await fs17.readFile(file, "utf8");
|
|
29311
29642
|
} catch {
|
|
29312
29643
|
}
|
|
29313
29644
|
let parsed;
|
|
@@ -29315,7 +29646,7 @@ async function applyActions(actions, opts) {
|
|
|
29315
29646
|
parsed = JSON.parse(raw);
|
|
29316
29647
|
} catch {
|
|
29317
29648
|
return {
|
|
29318
|
-
messages: [`${
|
|
29649
|
+
messages: [`${color64.red("\u2717")} global config is not valid JSON \u2014 run /doctor fix first`],
|
|
29319
29650
|
changed: false
|
|
29320
29651
|
};
|
|
29321
29652
|
}
|
|
@@ -29353,11 +29684,11 @@ async function applyActions(actions, opts) {
|
|
|
29353
29684
|
const changed = JSON.stringify(parsed) !== before;
|
|
29354
29685
|
if (!changed) return { messages, changed: false };
|
|
29355
29686
|
try {
|
|
29356
|
-
await
|
|
29357
|
-
await
|
|
29687
|
+
await atomicWrite10(`${file}.last`, raw);
|
|
29688
|
+
await atomicWrite10(`${file}.${Date.now()}.bak`, raw);
|
|
29358
29689
|
} catch {
|
|
29359
29690
|
}
|
|
29360
|
-
await
|
|
29691
|
+
await atomicWrite10(file, JSON.stringify(parsed, null, 2));
|
|
29361
29692
|
try {
|
|
29362
29693
|
const homeFn = () => path20.dirname(path20.dirname(file));
|
|
29363
29694
|
await appendHistory(JSON.parse(raw), parsed, "tuneup auto-fix", homeFn, file);
|
|
@@ -29424,26 +29755,26 @@ var CATEGORY_ORDER = [
|
|
|
29424
29755
|
function severityIcon(severity) {
|
|
29425
29756
|
switch (severity) {
|
|
29426
29757
|
case "error":
|
|
29427
|
-
return
|
|
29758
|
+
return color64.red("\u2717");
|
|
29428
29759
|
case "warning":
|
|
29429
|
-
return
|
|
29760
|
+
return color64.amber("!");
|
|
29430
29761
|
case "ok":
|
|
29431
|
-
return
|
|
29762
|
+
return color64.green("\u2713");
|
|
29432
29763
|
default:
|
|
29433
|
-
return
|
|
29764
|
+
return color64.cyan("\xB7");
|
|
29434
29765
|
}
|
|
29435
29766
|
}
|
|
29436
29767
|
function renderFindings(lines, findings) {
|
|
29437
29768
|
for (const category of CATEGORY_ORDER) {
|
|
29438
29769
|
const group = findings.filter((f) => f.category === category);
|
|
29439
29770
|
if (group.length === 0) continue;
|
|
29440
|
-
lines.push("",
|
|
29771
|
+
lines.push("", color64.bold(CATEGORY_LABELS[category]));
|
|
29441
29772
|
for (const f of group) {
|
|
29442
29773
|
lines.push(` ${severityIcon(f.severity)} ${f.problem}`);
|
|
29443
29774
|
if (f.suggestion) {
|
|
29444
|
-
for (const s of f.suggestion.split("\n")) lines.push(
|
|
29775
|
+
for (const s of f.suggestion.split("\n")) lines.push(color64.dim(` ${s}`));
|
|
29445
29776
|
}
|
|
29446
|
-
if (f.fix) lines.push(
|
|
29777
|
+
if (f.fix) lines.push(color64.dim(` \u2192 fixable: ${f.fix}`));
|
|
29447
29778
|
}
|
|
29448
29779
|
}
|
|
29449
29780
|
}
|
|
@@ -29452,20 +29783,20 @@ function summaryLine(findings, fixable, handoffs, power) {
|
|
|
29452
29783
|
(f) => f.severity === "warning" || f.severity === "error"
|
|
29453
29784
|
).length;
|
|
29454
29785
|
if (warnings === 0 && fixable === 0 && handoffs === 0) {
|
|
29455
|
-
return `${
|
|
29786
|
+
return `${color64.green("\u2713")} everything looks healthy`;
|
|
29456
29787
|
}
|
|
29457
29788
|
const parts = [];
|
|
29458
29789
|
if (warnings > 0) parts.push(`${warnings} warning(s)`);
|
|
29459
29790
|
if (fixable > 0) parts.push(`${fixable} auto-fixable`);
|
|
29460
29791
|
if (handoffs > 0) parts.push(`${handoffs} for the agent`);
|
|
29461
29792
|
const cmd = power ? "/tuneup fix --power" : "/tuneup fix";
|
|
29462
|
-
return `${parts.join(", ")} ${
|
|
29793
|
+
return `${parts.join(", ")} ${color64.dim(`\u2014 run ${cmd}`)}`;
|
|
29463
29794
|
}
|
|
29464
29795
|
|
|
29465
29796
|
// src/slash-commands/working-dir.ts
|
|
29466
|
-
import * as
|
|
29797
|
+
import * as fs18 from "node:fs/promises";
|
|
29467
29798
|
import * as path21 from "node:path";
|
|
29468
|
-
import { color as
|
|
29799
|
+
import { color as color65, toErrorMessage as toErrorMessage28 } from "@wrongstack/core/utils";
|
|
29469
29800
|
function buildWorkingDirCommand(_opts) {
|
|
29470
29801
|
return {
|
|
29471
29802
|
name: "working_dir",
|
|
@@ -29484,16 +29815,16 @@ function buildWorkingDirCommand(_opts) {
|
|
|
29484
29815
|
].join("\n"),
|
|
29485
29816
|
async run(args, ctx) {
|
|
29486
29817
|
if (!ctx) {
|
|
29487
|
-
return { message:
|
|
29818
|
+
return { message: color65.yellow("No active context. Start a session first.") };
|
|
29488
29819
|
}
|
|
29489
29820
|
const trimmed = args.trim();
|
|
29490
29821
|
if (!trimmed) {
|
|
29491
29822
|
const rel2 = path21.relative(ctx.projectRoot, ctx.workingDir) || ".";
|
|
29492
29823
|
return {
|
|
29493
29824
|
message: [
|
|
29494
|
-
`Working directory: ${
|
|
29495
|
-
|
|
29496
|
-
|
|
29825
|
+
`Working directory: ${color65.bold(ctx.workingDir)}`,
|
|
29826
|
+
color65.dim(` (relative to root: ${rel2})`),
|
|
29827
|
+
color65.dim(` Project root: ${ctx.projectRoot}`)
|
|
29497
29828
|
].join("\n")
|
|
29498
29829
|
};
|
|
29499
29830
|
}
|
|
@@ -29502,7 +29833,7 @@ function buildWorkingDirCommand(_opts) {
|
|
|
29502
29833
|
const rel = path21.relative(root, resolved);
|
|
29503
29834
|
if (rel.startsWith("..") || path21.isAbsolute(rel)) {
|
|
29504
29835
|
return {
|
|
29505
|
-
message:
|
|
29836
|
+
message: color65.red(
|
|
29506
29837
|
`Directory "${trimmed}" is outside the project root.
|
|
29507
29838
|
Resolved: ${resolved}
|
|
29508
29839
|
Root: ${root}`
|
|
@@ -29510,27 +29841,27 @@ function buildWorkingDirCommand(_opts) {
|
|
|
29510
29841
|
};
|
|
29511
29842
|
}
|
|
29512
29843
|
try {
|
|
29513
|
-
const stat5 = await
|
|
29844
|
+
const stat5 = await fs18.stat(resolved);
|
|
29514
29845
|
if (!stat5.isDirectory()) {
|
|
29515
|
-
return { message:
|
|
29846
|
+
return { message: color65.red(`Not a directory: ${resolved}`) };
|
|
29516
29847
|
}
|
|
29517
29848
|
} catch {
|
|
29518
|
-
return { message:
|
|
29849
|
+
return { message: color65.red(`Directory does not exist: ${resolved}`) };
|
|
29519
29850
|
}
|
|
29520
29851
|
const previous = ctx.workingDir;
|
|
29521
29852
|
try {
|
|
29522
29853
|
ctx.setWorkingDir(resolved);
|
|
29523
29854
|
} catch (err) {
|
|
29524
29855
|
return {
|
|
29525
|
-
message:
|
|
29856
|
+
message: color65.red(toErrorMessage28(err))
|
|
29526
29857
|
};
|
|
29527
29858
|
}
|
|
29528
29859
|
const prevRel = path21.relative(ctx.projectRoot, previous) || ".";
|
|
29529
29860
|
const newRel = path21.relative(ctx.projectRoot, resolved) || ".";
|
|
29530
29861
|
return {
|
|
29531
29862
|
message: [
|
|
29532
|
-
|
|
29533
|
-
|
|
29863
|
+
color65.green(` \u2713 ${prevRel} \u2192 ${color65.bold(newRel)}`),
|
|
29864
|
+
color65.dim(` ${resolved}`)
|
|
29534
29865
|
].join("\n")
|
|
29535
29866
|
};
|
|
29536
29867
|
}
|
|
@@ -29599,7 +29930,7 @@ function buildWorktreeCommand(opts) {
|
|
|
29599
29930
|
}
|
|
29600
29931
|
|
|
29601
29932
|
// src/slash-commands/yolo.ts
|
|
29602
|
-
import { color as
|
|
29933
|
+
import { color as color66 } from "@wrongstack/core/utils";
|
|
29603
29934
|
function buildYoloCommand(opts) {
|
|
29604
29935
|
return {
|
|
29605
29936
|
name: "yolo",
|
|
@@ -29623,7 +29954,7 @@ function buildYoloCommand(opts) {
|
|
|
29623
29954
|
}
|
|
29624
29955
|
if (!arg) {
|
|
29625
29956
|
const current = opts.onYolo();
|
|
29626
|
-
const status = current ? `${
|
|
29957
|
+
const status = current ? `${color66.yellow("ON")} ${color66.dim("(auto-approving tool calls)")}` : `${color66.green("OFF")} ${color66.dim("(permission prompts active)")}`;
|
|
29627
29958
|
const msg2 = `YOLO mode: ${status}`;
|
|
29628
29959
|
opts.renderer.write(msg2);
|
|
29629
29960
|
return { message: msg2 };
|
|
@@ -29638,11 +29969,11 @@ function buildYoloCommand(opts) {
|
|
|
29638
29969
|
} else if (arg === "destructive") {
|
|
29639
29970
|
const currentMode = opts.onYolo();
|
|
29640
29971
|
if (!currentMode) {
|
|
29641
|
-
const msg3 = `${
|
|
29972
|
+
const msg3 = `${color66.amber("YOLO is OFF.")} Destructive-gate flags are deprecated; prompts are active because YOLO is off.`;
|
|
29642
29973
|
opts.renderer.writeWarning(msg3);
|
|
29643
29974
|
return { message: msg3 };
|
|
29644
29975
|
}
|
|
29645
|
-
const msg2 = `${
|
|
29976
|
+
const msg2 = `${color66.amber("Destructive gate:")} ${color66.dim("deprecated \u2014 YOLO auto-approves all non-denied tool calls.")}`;
|
|
29646
29977
|
opts.renderer.writeWarning(msg2);
|
|
29647
29978
|
return { message: msg2 };
|
|
29648
29979
|
} else {
|
|
@@ -29651,7 +29982,7 @@ function buildYoloCommand(opts) {
|
|
|
29651
29982
|
return { message: msg2 };
|
|
29652
29983
|
}
|
|
29653
29984
|
opts.onYolo(newState);
|
|
29654
|
-
const label = newState ? `${
|
|
29985
|
+
const label = newState ? `${color66.yellow("ENABLED")} \u2014 tool calls will be auto-approved unless explicitly denied` : `${color66.green("DISABLED")} \u2014 permission prompts are active`;
|
|
29655
29986
|
const msg = `YOLO mode: ${label}`;
|
|
29656
29987
|
opts.renderer.write(msg);
|
|
29657
29988
|
return { message: msg };
|
|
@@ -29729,6 +30060,7 @@ function buildBuiltinSlashCommands(opts) {
|
|
|
29729
30060
|
buildTelegramSetupCommand(opts),
|
|
29730
30061
|
buildTelegramSettingsCommand(opts),
|
|
29731
30062
|
buildSetModelCommand(opts),
|
|
30063
|
+
buildEffortCommand(opts),
|
|
29732
30064
|
buildRefinerCommand(opts),
|
|
29733
30065
|
buildFallbackCommand(opts),
|
|
29734
30066
|
...opts.statusTracker ? [buildProviderStatusCommand(opts.statusTracker)] : [],
|
|
@@ -29810,7 +30142,7 @@ function setupCliSlashCommands(params) {
|
|
|
29810
30142
|
brain,
|
|
29811
30143
|
brainSettings,
|
|
29812
30144
|
brainRuntime,
|
|
29813
|
-
|
|
30145
|
+
initialBrainLog,
|
|
29814
30146
|
coordinatorController,
|
|
29815
30147
|
statusTracker,
|
|
29816
30148
|
shadowController,
|
|
@@ -29871,7 +30203,7 @@ function setupCliSlashCommands(params) {
|
|
|
29871
30203
|
modeStore,
|
|
29872
30204
|
fleetStreamController,
|
|
29873
30205
|
interruptController,
|
|
29874
|
-
enhanceController,
|
|
30206
|
+
...enhanceController ? { enhanceController } : {},
|
|
29875
30207
|
llmProvider: provider,
|
|
29876
30208
|
llmModel: config.model,
|
|
29877
30209
|
createProvider: (pid) => {
|
|
@@ -29881,23 +30213,23 @@ function setupCliSlashCommands(params) {
|
|
|
29881
30213
|
return void 0;
|
|
29882
30214
|
}
|
|
29883
30215
|
},
|
|
29884
|
-
statuslineConfig: statuslineConfigDeps,
|
|
30216
|
+
...statuslineConfigDeps ? { statuslineConfig: statuslineConfigDeps } : {},
|
|
29885
30217
|
statuslineHiddenItems: [...getCurrentHiddenItems()],
|
|
29886
30218
|
setStatuslineHiddenItems,
|
|
29887
30219
|
saveStatuslineHiddenItems,
|
|
29888
|
-
agentsMonitorController,
|
|
29889
|
-
agentMonitor,
|
|
30220
|
+
...agentsMonitorController ? { agentsMonitorController } : {},
|
|
30221
|
+
...agentMonitor ? { agentMonitor } : {},
|
|
29890
30222
|
onPanelOpen,
|
|
29891
30223
|
configStore,
|
|
29892
30224
|
reader,
|
|
29893
|
-
readSecret:
|
|
29894
|
-
readText:
|
|
30225
|
+
readSecret: secretInputController.readSecret,
|
|
30226
|
+
readText: secretInputController.readText,
|
|
29895
30227
|
vault,
|
|
29896
30228
|
brain,
|
|
29897
30229
|
brainSettings,
|
|
29898
30230
|
brainRuntime,
|
|
29899
|
-
getBrainLog: () =>
|
|
29900
|
-
coordinatorController,
|
|
30231
|
+
getBrainLog: () => initialBrainLog,
|
|
30232
|
+
...coordinatorController ? { coordinatorController } : {},
|
|
29901
30233
|
statusTracker,
|
|
29902
30234
|
shadowController,
|
|
29903
30235
|
...createFleetCommandHandlers({
|
|
@@ -29969,16 +30301,18 @@ function setupCliSlashCommands(params) {
|
|
|
29969
30301
|
sddRunRegistry,
|
|
29970
30302
|
getSddRuntimeState: getSddRuntimeStateForCli
|
|
29971
30303
|
}),
|
|
29972
|
-
|
|
29973
|
-
|
|
29974
|
-
|
|
29975
|
-
|
|
29976
|
-
|
|
29977
|
-
|
|
29978
|
-
|
|
29979
|
-
|
|
29980
|
-
|
|
29981
|
-
|
|
30304
|
+
...goalHost ? {
|
|
30305
|
+
onGoalStart: goalHost.onGoalStart,
|
|
30306
|
+
onGoalPause: goalHost.onGoalPause,
|
|
30307
|
+
onGoalResume: goalHost.onGoalResume,
|
|
30308
|
+
onGoalStop: goalHost.onGoalStop,
|
|
30309
|
+
getGoalRunner: goalHost.getGoalRunner,
|
|
30310
|
+
onGoalMoveTask: goalHost.onGoalMoveTask,
|
|
30311
|
+
onGoalAssignTask: goalHost.onGoalAssignTask,
|
|
30312
|
+
onGoalAddTask: goalHost.onGoalAddTask,
|
|
30313
|
+
onGoalRetryTask: goalHost.onGoalRetryTask,
|
|
30314
|
+
onWorktree: goalHost.onWorktree
|
|
30315
|
+
} : {}
|
|
29982
30316
|
});
|
|
29983
30317
|
for (const cmd of slashCmds) {
|
|
29984
30318
|
slashRegistry.register(cmd);
|
|
@@ -30857,7 +31191,7 @@ function installDesignStudio(deps) {
|
|
|
30857
31191
|
|
|
30858
31192
|
// src/wiring/metrics.ts
|
|
30859
31193
|
import { constants as fsConstants, writeFileSync } from "node:fs";
|
|
30860
|
-
import * as
|
|
31194
|
+
import * as fs19 from "node:fs/promises";
|
|
30861
31195
|
import * as path26 from "node:path";
|
|
30862
31196
|
import {
|
|
30863
31197
|
DefaultHealthRegistry,
|
|
@@ -31004,7 +31338,7 @@ function setupMetrics(params) {
|
|
|
31004
31338
|
name: "session-store",
|
|
31005
31339
|
check: async () => {
|
|
31006
31340
|
try {
|
|
31007
|
-
await
|
|
31341
|
+
await fs19.access(wpaths.projectSessions, fsConstants.R_OK | fsConstants.W_OK);
|
|
31008
31342
|
return { status: "healthy" };
|
|
31009
31343
|
} catch {
|
|
31010
31344
|
return { status: "unhealthy", detail: "session storage is not readable and writable" };
|
|
@@ -31015,7 +31349,7 @@ function setupMetrics(params) {
|
|
|
31015
31349
|
name: "project-storage",
|
|
31016
31350
|
check: async () => {
|
|
31017
31351
|
try {
|
|
31018
|
-
await
|
|
31352
|
+
await fs19.access(wpaths.projectDir, fsConstants.R_OK | fsConstants.W_OK);
|
|
31019
31353
|
return { status: "healthy" };
|
|
31020
31354
|
} catch {
|
|
31021
31355
|
return { status: "unhealthy", detail: "project storage is not readable and writable" };
|
|
@@ -31088,7 +31422,7 @@ import { resolveProjectDir as resolveProjectDir5 } from "@wrongstack/core/coordi
|
|
|
31088
31422
|
import { wstackGlobalRoot as wstackGlobalRoot5 } from "@wrongstack/core/utils";
|
|
31089
31423
|
|
|
31090
31424
|
// src/mailbox-bridge-bootstrap.ts
|
|
31091
|
-
import { spawn as
|
|
31425
|
+
import { spawn as spawn8 } from "node:child_process";
|
|
31092
31426
|
import * as path27 from "node:path";
|
|
31093
31427
|
import { readLiveLock } from "@wrongstack/core/coordination";
|
|
31094
31428
|
var MAILBOX_BRIDGE_BOOTSTRAP_TIMEOUT_MS = 5e3;
|
|
@@ -31169,7 +31503,7 @@ function defaultSpawn(args, cwd) {
|
|
|
31169
31503
|
spawnArgs = args;
|
|
31170
31504
|
if (isWin) shim = buildWin32CmdShimInvocation(cmd, spawnArgs);
|
|
31171
31505
|
}
|
|
31172
|
-
const child =
|
|
31506
|
+
const child = spawn8(shim?.command ?? cmd, shim?.args ?? spawnArgs, {
|
|
31173
31507
|
cwd,
|
|
31174
31508
|
// `detached` gives the bridge its own process group on POSIX so it
|
|
31175
31509
|
// outlives the REPL. On win32 it forces a visible console window
|
|
@@ -32349,14 +32683,14 @@ function setupProviderRuntime(deps) {
|
|
|
32349
32683
|
}
|
|
32350
32684
|
|
|
32351
32685
|
// src/wiring/provider-status.ts
|
|
32352
|
-
import * as
|
|
32686
|
+
import * as fs20 from "node:fs/promises";
|
|
32353
32687
|
import { ProviderModelStatusTracker } from "@wrongstack/core/coordination";
|
|
32354
|
-
import { atomicWrite as
|
|
32688
|
+
import { atomicWrite as atomicWrite11, withFileLock } from "@wrongstack/core/utils";
|
|
32355
32689
|
async function setupProviderStatus(input) {
|
|
32356
32690
|
const tracker = new ProviderModelStatusTracker({ events: input.events });
|
|
32357
32691
|
const statusFile = input.paths.profileProviderStatus(input.paths.profileName);
|
|
32358
32692
|
try {
|
|
32359
|
-
const saved = JSON.parse(await
|
|
32693
|
+
const saved = JSON.parse(await fs20.readFile(statusFile, "utf8"));
|
|
32360
32694
|
const restored = tracker.restoreSnapshot(saved);
|
|
32361
32695
|
if (restored > 0) input.logger.info(`Restored ${restored} provider waiting-room entries`);
|
|
32362
32696
|
} catch (error) {
|
|
@@ -32368,7 +32702,7 @@ async function setupProviderStatus(input) {
|
|
|
32368
32702
|
tracker.sweepExpired();
|
|
32369
32703
|
if (syncRunning) return;
|
|
32370
32704
|
syncRunning = true;
|
|
32371
|
-
void
|
|
32705
|
+
void fs20.readFile(statusFile, "utf8").then((raw) => tracker.restoreSnapshot(JSON.parse(raw))).catch((error) => warnUnlessMissing(input.logger, "sync", error)).finally(() => {
|
|
32372
32706
|
syncRunning = false;
|
|
32373
32707
|
});
|
|
32374
32708
|
}, 3e4);
|
|
@@ -32383,7 +32717,7 @@ async function setupProviderStatus(input) {
|
|
|
32383
32717
|
await withFileLock(statusFile, async () => {
|
|
32384
32718
|
let statuses = [];
|
|
32385
32719
|
try {
|
|
32386
|
-
const current = JSON.parse(await
|
|
32720
|
+
const current = JSON.parse(await fs20.readFile(statusFile, "utf8"));
|
|
32387
32721
|
if (Array.isArray(current.statuses)) statuses = current.statuses;
|
|
32388
32722
|
} catch (error) {
|
|
32389
32723
|
if (error.code !== "ENOENT") throw error;
|
|
@@ -32399,7 +32733,7 @@ async function setupProviderStatus(input) {
|
|
|
32399
32733
|
if (current && current.state !== "healthy") statuses.push(current);
|
|
32400
32734
|
}
|
|
32401
32735
|
}
|
|
32402
|
-
await
|
|
32736
|
+
await atomicWrite11(
|
|
32403
32737
|
statusFile,
|
|
32404
32738
|
JSON.stringify({ version: 1, updatedAt: Date.now(), statuses }, null, 2),
|
|
32405
32739
|
{ mode: 384 }
|
|
@@ -32921,7 +33255,7 @@ async function setupSession(params) {
|
|
|
32921
33255
|
}
|
|
32922
33256
|
|
|
32923
33257
|
// src/wiring/session-registry.ts
|
|
32924
|
-
import { execFile as
|
|
33258
|
+
import { execFile as execFile2 } from "node:child_process";
|
|
32925
33259
|
import * as path31 from "node:path";
|
|
32926
33260
|
async function setupSessionRegistry(deps) {
|
|
32927
33261
|
const { wpaths, projectRoot, session, context, tuiOwnsScreen, events } = deps;
|
|
@@ -32935,7 +33269,7 @@ async function setupSessionRegistry(deps) {
|
|
|
32935
33269
|
const projectSlug = path31.basename(wpaths.projectDir);
|
|
32936
33270
|
const projectName = path31.basename(projectRoot);
|
|
32937
33271
|
let gitBranch = await new Promise((resolve8) => {
|
|
32938
|
-
|
|
33272
|
+
execFile2(
|
|
32939
33273
|
"git",
|
|
32940
33274
|
["rev-parse", "--abbrev-ref", "HEAD"],
|
|
32941
33275
|
{
|
|
@@ -33610,7 +33944,7 @@ async function runInteractive(cliCtx) {
|
|
|
33610
33944
|
brain,
|
|
33611
33945
|
brainSettings,
|
|
33612
33946
|
brainRuntime,
|
|
33613
|
-
brainLog,
|
|
33947
|
+
initialBrainLog: brainLog,
|
|
33614
33948
|
coordinatorController,
|
|
33615
33949
|
statusTracker,
|
|
33616
33950
|
shadowController,
|
|
@@ -33820,4 +34154,4 @@ export {
|
|
|
33820
34154
|
CLI_VERSION,
|
|
33821
34155
|
runInteractive
|
|
33822
34156
|
};
|
|
33823
|
-
//# sourceMappingURL=cli-main-
|
|
34157
|
+
//# sourceMappingURL=cli-main-XGDOIPN5.js.map
|