@wrongstack/cli 0.9.0 → 0.9.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/index.js +260 -32
- package/dist/index.js.map +1 -1
- package/package.json +11 -11
package/dist/index.js
CHANGED
|
@@ -5,8 +5,8 @@ import * as fsp3 from 'fs/promises';
|
|
|
5
5
|
import { readdir, readFile } from 'fs/promises';
|
|
6
6
|
import { color, DefaultPathResolver, TOKENS, DefaultSystemPromptBuilder, makeAutonomyPromptContributor, ToolRegistry, createContextManagerTool, EventBus, SlashCommandRegistry, createDelegateTool, FLEET_ROSTER, createMcpControlTool, EternalAutonomyEngine, DefaultLogger, DefaultModelsRegistry, ProviderRegistry, InMemoryMetricsSink, wireMetricsToEvents, DefaultHealthRegistry, startMetricsServer, RecoveryLock, DefaultAttachmentStore, QueueStore, Context, loadTodosCheckpoint, attachTodosCheckpoint, loadDirectorState, loadPlan, createDefaultPipelines, AutoCompactionMiddleware, estimateRequestTokens, Agent, loadPlugins, FleetManager, makeDirectorSessionFactory, Director, AutoApprovePermissionPolicy, PhaseStore, AutoPhasePlanner, PhaseGraphBuilder, WorktreeManager, PhaseOrchestrator, makeLLMClassifier, resolveWstackPaths, DefaultSecretVault, migratePlaintextSecrets, DefaultConfigLoader, DefaultSessionReader, DefaultSessionRewinder, DefaultSessionStore, atomicWrite, DefaultPluginAPI, makeAgentSubagentRunner, NULL_FLEET_BUS, buildChildEnv, formatContextWindowModeList, repairToolUseAdjacency, getContextWindowMode, resolveContextWindowPolicy, AGENTS_BY_PHASE, dispatchAgent, formatTodosList, emptyPlan, clearPlan, savePlan, formatPlanTemplates, getPlanTemplate, addPlanItem, formatPlan, deriveTodosFromPlanItem, removePlanItem, setPlanItemStatus, SpecStore, TaskGraphStore, analyzeCriticalPath, getTemplate, listTemplates, templateToMarkdown, SpecParser, renderSpecAnalysis, AISpecBuilder, DefaultTaskStore, TaskTracker, renderProgress, renderTaskGraph, loadGoal, goalFilePath, summarizeUsage, saveGoal, emptyGoal, buildGoalPreamble, formatGoal, pendingBtwCount, setBtwNote, InputBuilder, FsError, ERROR_CODES, projectHash, WrongStackError, defaultOrchestrator, decryptConfigSecrets, encryptConfigSecrets as encryptConfigSecrets$1, SpecVersioning, ParallelEternalEngine, allServers as allServers$1 } from '@wrongstack/core';
|
|
7
7
|
import { createRequire } from 'module';
|
|
8
|
-
import * as
|
|
9
|
-
import
|
|
8
|
+
import * as os4 from 'os';
|
|
9
|
+
import os4__default from 'os';
|
|
10
10
|
import * as crypto2 from 'crypto';
|
|
11
11
|
import { randomUUID } from 'crypto';
|
|
12
12
|
import { DefaultSecretVault as DefaultSecretVault$1, encryptConfigSecrets, isSecretField, decryptConfigSecrets as decryptConfigSecrets$1 } from '@wrongstack/core/security';
|
|
@@ -18,7 +18,7 @@ import { builtinToolsPack, rememberTool, forgetTool } from '@wrongstack/tools';
|
|
|
18
18
|
import { spawn } from 'child_process';
|
|
19
19
|
import { SkillInstaller } from '@wrongstack/core/skills';
|
|
20
20
|
import * as readline from 'readline';
|
|
21
|
-
import * as
|
|
21
|
+
import * as fs10 from 'fs';
|
|
22
22
|
import { writeFileSync } from 'fs';
|
|
23
23
|
import { WrongStackACPServer } from '@wrongstack/acp/agent';
|
|
24
24
|
import { ACP_AGENT_COMMANDS, makeACPSubagentRunner, makeACPSubagentRunnerWithStop } from '@wrongstack/acp';
|
|
@@ -1686,7 +1686,7 @@ async function getUpdateNotification(signal, homeFn) {
|
|
|
1686
1686
|
var defaultHomeDir2, CACHE_TTL_MS;
|
|
1687
1687
|
var init_update_check = __esm({
|
|
1688
1688
|
"src/update-check.ts"() {
|
|
1689
|
-
defaultHomeDir2 = () =>
|
|
1689
|
+
defaultHomeDir2 = () => os4.homedir();
|
|
1690
1690
|
CACHE_TTL_MS = 24 * 60 * 60 * 1e3;
|
|
1691
1691
|
}
|
|
1692
1692
|
});
|
|
@@ -5824,7 +5824,7 @@ When the error confidence is low (< 0.85) or the problem spans multiple files,
|
|
|
5824
5824
|
};
|
|
5825
5825
|
}
|
|
5826
5826
|
function makeInstaller(opts, projectRoot, global) {
|
|
5827
|
-
const globalRoot = path25.join(
|
|
5827
|
+
const globalRoot = path25.join(os4.homedir(), ".wrongstack");
|
|
5828
5828
|
return new SkillInstaller({
|
|
5829
5829
|
manifestPath: path25.join(globalRoot, "installed-skills.json"),
|
|
5830
5830
|
projectSkillsDir: path25.join(projectRoot, ".wrongstack", "skills"),
|
|
@@ -6185,6 +6185,207 @@ function buildWorktreeCommand(opts) {
|
|
|
6185
6185
|
}
|
|
6186
6186
|
};
|
|
6187
6187
|
}
|
|
6188
|
+
async function runSettingsMenu(deps) {
|
|
6189
|
+
for (; ; ) {
|
|
6190
|
+
const config = deps.configStore.get();
|
|
6191
|
+
renderSettingsTopMenu(deps.renderer, config);
|
|
6192
|
+
const choice = (await deps.reader.readLine(`
|
|
6193
|
+
${color.amber("?")} Pick setting to edit: `)).trim().toLowerCase();
|
|
6194
|
+
if (!choice || choice === "q" || choice === "quit" || choice === "exit") {
|
|
6195
|
+
deps.renderer.write(color.dim("Done.\n"));
|
|
6196
|
+
return 0;
|
|
6197
|
+
}
|
|
6198
|
+
switch (choice) {
|
|
6199
|
+
case "1":
|
|
6200
|
+
await editAutoProceedDelay(deps);
|
|
6201
|
+
break;
|
|
6202
|
+
case "2":
|
|
6203
|
+
await editDefaultAutonomy(deps);
|
|
6204
|
+
break;
|
|
6205
|
+
case "d":
|
|
6206
|
+
await showDefaults(deps);
|
|
6207
|
+
break;
|
|
6208
|
+
default:
|
|
6209
|
+
deps.renderer.writeError(`Unknown selection: "${choice}". Try 1, 2, or q to quit.`);
|
|
6210
|
+
}
|
|
6211
|
+
}
|
|
6212
|
+
}
|
|
6213
|
+
function renderSettingsTopMenu(renderer, config) {
|
|
6214
|
+
const delay = config.autonomy?.autoProceedDelayMs ?? 45e3;
|
|
6215
|
+
const defMode = config.autonomy?.defaultMode ?? "off";
|
|
6216
|
+
renderer.write(`
|
|
6217
|
+
${color.bold("WrongStack")} ${color.dim("\u2014 Settings")}
|
|
6218
|
+
|
|
6219
|
+
`);
|
|
6220
|
+
renderer.write(` ${color.bold("1.")} auto-proceed delay: ${color.cyan(formatDelay(delay))} (in auto mode, wait before continuing)
|
|
6221
|
+
`);
|
|
6222
|
+
renderer.write(` ${color.bold("2.")} default autonomy mode: ${color.cyan(defMode)}
|
|
6223
|
+
`);
|
|
6224
|
+
renderer.write(`
|
|
6225
|
+
${color.dim("Actions:")}
|
|
6226
|
+
`);
|
|
6227
|
+
renderer.write(` ${color.bold("1")} Edit auto-proceed delay
|
|
6228
|
+
`);
|
|
6229
|
+
renderer.write(` ${color.bold("2")} Edit default autonomy mode
|
|
6230
|
+
`);
|
|
6231
|
+
renderer.write(` ${color.bold("d")} Show all defaults
|
|
6232
|
+
`);
|
|
6233
|
+
renderer.write(` ${color.bold("q")} Quit
|
|
6234
|
+
`);
|
|
6235
|
+
}
|
|
6236
|
+
async function editAutoProceedDelay(deps) {
|
|
6237
|
+
deps.renderer.write(`
|
|
6238
|
+
${color.bold("Auto-proceed delay")} ${color.dim("\u2014 wait time before auto-continuing in auto mode")}
|
|
6239
|
+
`);
|
|
6240
|
+
deps.renderer.write(color.dim(` Current: ${formatDelay(deps.configStore.get().autonomy?.autoProceedDelayMs ?? 45e3)}
|
|
6241
|
+
`));
|
|
6242
|
+
deps.renderer.write(color.dim(` Enter value in SECONDS (e.g. 30 for 30 seconds, 0 to disable)
|
|
6243
|
+
`));
|
|
6244
|
+
const raw = (await deps.reader.readLine(` ${color.amber("?")} Delay (seconds): `)).trim();
|
|
6245
|
+
if (!raw || raw === "q") return;
|
|
6246
|
+
const seconds = Number.parseFloat(raw);
|
|
6247
|
+
if (Number.isNaN(seconds) || seconds < 0) {
|
|
6248
|
+
deps.renderer.writeError(`Invalid number: "${raw}"`);
|
|
6249
|
+
return;
|
|
6250
|
+
}
|
|
6251
|
+
const ms = Math.round(seconds * 1e3);
|
|
6252
|
+
await mutateAutonomyConfig(deps, (autonomy) => {
|
|
6253
|
+
autonomy.autoProceedDelayMs = ms;
|
|
6254
|
+
});
|
|
6255
|
+
deps.renderer.write(` ${color.green("\u2713")} auto-proceed delay \u2192 ${formatDelay(ms)}
|
|
6256
|
+
`);
|
|
6257
|
+
}
|
|
6258
|
+
async function editDefaultAutonomy(deps) {
|
|
6259
|
+
deps.renderer.write(`
|
|
6260
|
+
${color.bold("Default Autonomy Mode")}
|
|
6261
|
+
|
|
6262
|
+
`);
|
|
6263
|
+
deps.renderer.write(` ${color.bold("1.")} off \u2014 agent stops after each turn (normal)
|
|
6264
|
+
`);
|
|
6265
|
+
deps.renderer.write(` ${color.bold("2.")} suggest \u2014 shows next-step suggestions
|
|
6266
|
+
`);
|
|
6267
|
+
deps.renderer.write(` ${color.bold("3.")} auto \u2014 self-driving, agent continues automatically
|
|
6268
|
+
`);
|
|
6269
|
+
deps.renderer.write(` ${color.bold("q")} Quit without changing
|
|
6270
|
+
`);
|
|
6271
|
+
const raw = (await deps.reader.readLine(` ${color.amber("?")} Default mode: `)).trim().toLowerCase();
|
|
6272
|
+
if (!raw || raw === "q") return;
|
|
6273
|
+
const modes = ["off", "suggest", "auto"];
|
|
6274
|
+
let selected = null;
|
|
6275
|
+
if (raw === "1") selected = "off";
|
|
6276
|
+
else if (raw === "2") selected = "suggest";
|
|
6277
|
+
else if (raw === "3") selected = "auto";
|
|
6278
|
+
else if (modes.includes(raw)) selected = raw;
|
|
6279
|
+
if (!selected) {
|
|
6280
|
+
deps.renderer.writeError(`Invalid mode: "${raw}". Use off, suggest, or auto.`);
|
|
6281
|
+
return;
|
|
6282
|
+
}
|
|
6283
|
+
await mutateAutonomyConfig(deps, (autonomy) => {
|
|
6284
|
+
autonomy.defaultMode = selected;
|
|
6285
|
+
});
|
|
6286
|
+
deps.renderer.write(` ${color.green("\u2713")} default autonomy \u2192 ${color.bold(selected)}
|
|
6287
|
+
`);
|
|
6288
|
+
}
|
|
6289
|
+
async function showDefaults(deps) {
|
|
6290
|
+
deps.renderer.write(`
|
|
6291
|
+
${color.bold("Default Values")}
|
|
6292
|
+
|
|
6293
|
+
`);
|
|
6294
|
+
deps.renderer.write(` auto-proceed delay: ${color.cyan("45s")} (WRONGSTACK_AUTO_PROCEED_DELAY_MS env)
|
|
6295
|
+
`);
|
|
6296
|
+
deps.renderer.write(` default autonomy mode: ${color.cyan("off")}
|
|
6297
|
+
`);
|
|
6298
|
+
deps.renderer.write(` iteration timeout: ${color.cyan("5 min")}
|
|
6299
|
+
`);
|
|
6300
|
+
deps.renderer.write(` session timeout: ${color.cyan("30 min")}
|
|
6301
|
+
`);
|
|
6302
|
+
deps.renderer.write(` max iterations: ${color.cyan("100")}
|
|
6303
|
+
`);
|
|
6304
|
+
deps.renderer.write(`
|
|
6305
|
+
${color.dim(" Press Enter to continue...")}`);
|
|
6306
|
+
await deps.reader.readLine("");
|
|
6307
|
+
}
|
|
6308
|
+
async function mutateAutonomyConfig(deps, mutator) {
|
|
6309
|
+
let raw;
|
|
6310
|
+
let fileExists = true;
|
|
6311
|
+
try {
|
|
6312
|
+
raw = await fsp3.readFile(deps.globalConfigPath, "utf8");
|
|
6313
|
+
} catch (err) {
|
|
6314
|
+
if (err.code !== "ENOENT") {
|
|
6315
|
+
throw new Error(`Could not read ${deps.globalConfigPath}: ${err.message}`);
|
|
6316
|
+
}
|
|
6317
|
+
fileExists = false;
|
|
6318
|
+
raw = "{}";
|
|
6319
|
+
}
|
|
6320
|
+
let parsed;
|
|
6321
|
+
try {
|
|
6322
|
+
parsed = JSON.parse(raw);
|
|
6323
|
+
} catch (err) {
|
|
6324
|
+
if (fileExists) {
|
|
6325
|
+
throw new Error(`Config at ${deps.globalConfigPath} is not valid JSON: ${err.message}`);
|
|
6326
|
+
}
|
|
6327
|
+
parsed = {};
|
|
6328
|
+
}
|
|
6329
|
+
const decrypted = decryptConfigSecrets(parsed, deps.vault);
|
|
6330
|
+
const autonomy = decrypted.autonomy ?? {};
|
|
6331
|
+
mutator(autonomy);
|
|
6332
|
+
decrypted.autonomy = autonomy;
|
|
6333
|
+
const encrypted = encryptConfigSecrets$1(decrypted, deps.vault);
|
|
6334
|
+
await atomicWrite(deps.globalConfigPath, JSON.stringify(encrypted, null, 2), { mode: 384 });
|
|
6335
|
+
deps.configStore.update({ autonomy: decrypted.autonomy });
|
|
6336
|
+
}
|
|
6337
|
+
function formatDelay(ms) {
|
|
6338
|
+
if (ms >= 6e4) return `${Math.round(ms / 6e4)}m`;
|
|
6339
|
+
if (ms === 0) return "disabled";
|
|
6340
|
+
return `${Math.round(ms / 1e3)}s`;
|
|
6341
|
+
}
|
|
6342
|
+
|
|
6343
|
+
// src/slash-commands/settings.ts
|
|
6344
|
+
var noOpVault = {
|
|
6345
|
+
encrypt: (v) => v,
|
|
6346
|
+
decrypt: (v) => v,
|
|
6347
|
+
isEncrypted: () => false
|
|
6348
|
+
};
|
|
6349
|
+
function buildSettingsCommand(opts) {
|
|
6350
|
+
return {
|
|
6351
|
+
name: "settings",
|
|
6352
|
+
description: "Open interactive settings menu (auto-proceed delay, defaults, etc.).",
|
|
6353
|
+
help: [
|
|
6354
|
+
"Usage:",
|
|
6355
|
+
" /settings Open interactive settings menu",
|
|
6356
|
+
"",
|
|
6357
|
+
"Configurable settings:",
|
|
6358
|
+
" auto-proceed delay \u2014 wait time before auto-continuing in auto mode",
|
|
6359
|
+
" default autonomy mode \u2014 startup autonomy mode",
|
|
6360
|
+
"",
|
|
6361
|
+
"Settings are persisted to ~/.wrongstack/config.json."
|
|
6362
|
+
].join("\n"),
|
|
6363
|
+
async run(args) {
|
|
6364
|
+
const trimmed = args.trim().toLowerCase();
|
|
6365
|
+
if (trimmed === "help" || trimmed === "--help") {
|
|
6366
|
+
return { message: this.help ?? "" };
|
|
6367
|
+
}
|
|
6368
|
+
if (!opts.configStore || !opts.paths) {
|
|
6369
|
+
return { message: `${color.red("Error")} config store not available.` };
|
|
6370
|
+
}
|
|
6371
|
+
if (!opts.reader || !opts.renderer) {
|
|
6372
|
+
return { message: `${color.red("Error")} settings menu requires a terminal (not available in headless mode).` };
|
|
6373
|
+
}
|
|
6374
|
+
try {
|
|
6375
|
+
await runSettingsMenu({
|
|
6376
|
+
renderer: opts.renderer,
|
|
6377
|
+
reader: opts.reader,
|
|
6378
|
+
configStore: opts.configStore,
|
|
6379
|
+
globalConfigPath: opts.paths.globalConfig,
|
|
6380
|
+
vault: noOpVault
|
|
6381
|
+
});
|
|
6382
|
+
return { message: `${color.green("Settings saved.")}` };
|
|
6383
|
+
} catch (err) {
|
|
6384
|
+
return { message: `${color.red("Settings error")}: ${err instanceof Error ? err.message : String(err)}` };
|
|
6385
|
+
}
|
|
6386
|
+
}
|
|
6387
|
+
};
|
|
6388
|
+
}
|
|
6188
6389
|
|
|
6189
6390
|
// src/slash-commands/index.ts
|
|
6190
6391
|
function buildBuiltinSlashCommands(opts) {
|
|
@@ -6229,6 +6430,7 @@ function buildBuiltinSlashCommands(opts) {
|
|
|
6229
6430
|
buildFixCommand(opts),
|
|
6230
6431
|
buildAutoPhaseCommand(opts),
|
|
6231
6432
|
buildWorktreeCommand(opts),
|
|
6433
|
+
buildSettingsCommand(opts),
|
|
6232
6434
|
buildStatuslineCommand({
|
|
6233
6435
|
cwd: opts.cwd,
|
|
6234
6436
|
hiddenItems: opts.statuslineHiddenItems ?? [],
|
|
@@ -6443,7 +6645,7 @@ async function bootConfig(flags) {
|
|
|
6443
6645
|
const cwd = typeof flags["cwd"] === "string" ? path25.resolve(flags["cwd"]) : process.cwd();
|
|
6444
6646
|
const pathResolver = new DefaultPathResolver(cwd);
|
|
6445
6647
|
const projectRoot = pathResolver.projectRoot;
|
|
6446
|
-
const userHome =
|
|
6648
|
+
const userHome = os4.homedir();
|
|
6447
6649
|
const wpaths = resolveWstackPaths({ projectRoot, userHome });
|
|
6448
6650
|
await ensureProjectMeta(wpaths, projectRoot);
|
|
6449
6651
|
const vault = new DefaultSecretVault({ keyFile: wpaths.secretsKey });
|
|
@@ -6507,7 +6709,7 @@ var ReadlineInputReader = class {
|
|
|
6507
6709
|
history = [];
|
|
6508
6710
|
pending = false;
|
|
6509
6711
|
constructor(opts = {}) {
|
|
6510
|
-
this.historyFile = opts.historyFile ?? path25.join(
|
|
6712
|
+
this.historyFile = opts.historyFile ?? path25.join(os4.homedir(), ".wrongstack", "history");
|
|
6511
6713
|
}
|
|
6512
6714
|
async loadHistory() {
|
|
6513
6715
|
try {
|
|
@@ -6737,6 +6939,24 @@ async function buildPickableProviders(modelsRegistry, config) {
|
|
|
6737
6939
|
}
|
|
6738
6940
|
return out;
|
|
6739
6941
|
}
|
|
6942
|
+
var defaultUidFn = () => os4__default.userInfo().uid;
|
|
6943
|
+
async function getFileUid(filePath) {
|
|
6944
|
+
try {
|
|
6945
|
+
const stat4 = await fsp3.stat(filePath);
|
|
6946
|
+
return stat4.uid;
|
|
6947
|
+
} catch {
|
|
6948
|
+
return void 0;
|
|
6949
|
+
}
|
|
6950
|
+
}
|
|
6951
|
+
async function checkConfigOwnership(homeFn, uidFn = defaultUidFn) {
|
|
6952
|
+
if (os4__default.platform() === "win32") return true;
|
|
6953
|
+
const cfg = configPath(homeFn);
|
|
6954
|
+
const fileUid = await getFileUid(cfg);
|
|
6955
|
+
if (fileUid === void 0) return true;
|
|
6956
|
+
const callerUid = uidFn();
|
|
6957
|
+
if (callerUid === void 0) return true;
|
|
6958
|
+
return fileUid === callerUid;
|
|
6959
|
+
}
|
|
6740
6960
|
var PROTECTED_BASENAMES = /* @__PURE__ */ new Set([
|
|
6741
6961
|
"config.json",
|
|
6742
6962
|
".key",
|
|
@@ -6802,7 +7022,7 @@ function diffSummary(oldCfg, newCfg) {
|
|
|
6802
7022
|
}
|
|
6803
7023
|
return changes.length > 0 ? changes.slice(0, 5).join(", ") : "no changes";
|
|
6804
7024
|
}
|
|
6805
|
-
var defaultHomeDir = () =>
|
|
7025
|
+
var defaultHomeDir = () => os4__default.homedir();
|
|
6806
7026
|
function historyDir(homeFn = defaultHomeDir) {
|
|
6807
7027
|
return path25.join(homeFn(), ".wrongstack", "config.history", "entries");
|
|
6808
7028
|
}
|
|
@@ -6928,6 +7148,9 @@ async function getHistoryEntry(id, homeFn = defaultHomeDir) {
|
|
|
6928
7148
|
async function restoreFromHistory(id, homeFn = defaultHomeDir) {
|
|
6929
7149
|
const entry = await getHistoryEntry(id, homeFn);
|
|
6930
7150
|
if (!entry) return { ok: false, backupId: null, error: "History entry not found" };
|
|
7151
|
+
if (!await checkConfigOwnership(homeFn)) {
|
|
7152
|
+
return { ok: false, backupId: null, error: "Operation denied: config file is not owned by current user" };
|
|
7153
|
+
}
|
|
6931
7154
|
await backupCurrent(homeFn);
|
|
6932
7155
|
let oldCfg = {};
|
|
6933
7156
|
try {
|
|
@@ -6964,6 +7187,9 @@ async function restoreLast(homeFn = defaultHomeDir) {
|
|
|
6964
7187
|
} catch {
|
|
6965
7188
|
return { ok: false, error: "No prior backup found" };
|
|
6966
7189
|
}
|
|
7190
|
+
if (!await checkConfigOwnership(homeFn)) {
|
|
7191
|
+
return { ok: false, error: "Operation denied: config file is not owned by current user" };
|
|
7192
|
+
}
|
|
6967
7193
|
await backupCurrent(homeFn);
|
|
6968
7194
|
try {
|
|
6969
7195
|
await atomicWrite(cfg, JSON.stringify(lastCfg, null, 2));
|
|
@@ -6978,11 +7204,11 @@ async function restoreLast(homeFn = defaultHomeDir) {
|
|
|
6978
7204
|
var theme = { primary: color.amber };
|
|
6979
7205
|
async function saveToGlobalConfig(configPath2, provider, model, homeFn = () => process.env.HOME ?? __require("os").homedir()) {
|
|
6980
7206
|
try {
|
|
6981
|
-
const { atomicWrite:
|
|
6982
|
-
const
|
|
7207
|
+
const { atomicWrite: atomicWrite9 } = await import('@wrongstack/core');
|
|
7208
|
+
const fs22 = await import('fs/promises');
|
|
6983
7209
|
let existing = {};
|
|
6984
7210
|
try {
|
|
6985
|
-
const raw = await
|
|
7211
|
+
const raw = await fs22.readFile(configPath2, "utf8");
|
|
6986
7212
|
existing = JSON.parse(raw);
|
|
6987
7213
|
} catch {
|
|
6988
7214
|
}
|
|
@@ -6990,7 +7216,7 @@ async function saveToGlobalConfig(configPath2, provider, model, homeFn = () => p
|
|
|
6990
7216
|
existing.provider = provider;
|
|
6991
7217
|
existing.model = model;
|
|
6992
7218
|
await backupCurrent(homeFn);
|
|
6993
|
-
await
|
|
7219
|
+
await atomicWrite9(configPath2, JSON.stringify(existing, null, 2), { mode: 384 });
|
|
6994
7220
|
try {
|
|
6995
7221
|
await appendHistory(
|
|
6996
7222
|
oldCfg,
|
|
@@ -7313,12 +7539,12 @@ function pickGroupIndex(opts) {
|
|
|
7313
7539
|
try {
|
|
7314
7540
|
let current = 0;
|
|
7315
7541
|
try {
|
|
7316
|
-
const parsed = Number.parseInt(
|
|
7542
|
+
const parsed = Number.parseInt(fs10.readFileSync(opts.cursorFile, "utf8").trim(), 10);
|
|
7317
7543
|
if (Number.isFinite(parsed)) current = wrap(parsed);
|
|
7318
7544
|
} catch {
|
|
7319
7545
|
}
|
|
7320
|
-
|
|
7321
|
-
|
|
7546
|
+
fs10.mkdirSync(path25.dirname(opts.cursorFile), { recursive: true });
|
|
7547
|
+
fs10.writeFileSync(opts.cursorFile, String(wrap(current + 1)));
|
|
7322
7548
|
return current;
|
|
7323
7549
|
} catch {
|
|
7324
7550
|
}
|
|
@@ -8591,7 +8817,7 @@ var diagCmd = async (_args, deps) => {
|
|
|
8591
8817
|
` modelsCache: ${deps.paths.modelsCache}`,
|
|
8592
8818
|
` cacheAge: ${isFinite(age) ? `${Math.round(age / 60)}m` : "never"}`,
|
|
8593
8819
|
` node: ${process.version}`,
|
|
8594
|
-
` os: ${
|
|
8820
|
+
` os: ${os4.platform()} ${os4.release()}`,
|
|
8595
8821
|
` provider: ${cfg.provider ?? "<unset>"}`,
|
|
8596
8822
|
` model: ${cfg.model ?? "<unset>"}`,
|
|
8597
8823
|
` tools: ${deps.toolRegistry?.list().length ?? 0}`,
|
|
@@ -9324,13 +9550,13 @@ async function listFleetRuns(deps) {
|
|
|
9324
9550
|
const runs = [];
|
|
9325
9551
|
for (const id of entries) {
|
|
9326
9552
|
const runDir = path25.join(deps.paths.projectSessions, id);
|
|
9327
|
-
let
|
|
9553
|
+
let stat4;
|
|
9328
9554
|
try {
|
|
9329
|
-
|
|
9555
|
+
stat4 = await fsp3.stat(runDir);
|
|
9330
9556
|
} catch {
|
|
9331
9557
|
continue;
|
|
9332
9558
|
}
|
|
9333
|
-
if (!
|
|
9559
|
+
if (!stat4.isDirectory()) continue;
|
|
9334
9560
|
let manifest = false;
|
|
9335
9561
|
let checkpoint = false;
|
|
9336
9562
|
let subagentCount = 0;
|
|
@@ -9376,15 +9602,15 @@ async function listFleetRuns(deps) {
|
|
|
9376
9602
|
}
|
|
9377
9603
|
async function showFleetRun(runId, deps) {
|
|
9378
9604
|
const runDir = path25.join(deps.paths.projectSessions, runId);
|
|
9379
|
-
let
|
|
9605
|
+
let stat4;
|
|
9380
9606
|
try {
|
|
9381
|
-
|
|
9607
|
+
stat4 = await fsp3.stat(runDir);
|
|
9382
9608
|
} catch {
|
|
9383
9609
|
deps.renderer.writeError(`Fleet run not found: ${runId}
|
|
9384
9610
|
`);
|
|
9385
9611
|
return 1;
|
|
9386
9612
|
}
|
|
9387
|
-
if (!
|
|
9613
|
+
if (!stat4.isDirectory()) {
|
|
9388
9614
|
deps.renderer.writeError(`Not a directory: ${runId}
|
|
9389
9615
|
`);
|
|
9390
9616
|
return 1;
|
|
@@ -9783,7 +10009,7 @@ var skillsCmd = async (_args, deps) => {
|
|
|
9783
10009
|
};
|
|
9784
10010
|
var versionCmd = async (_args, deps) => {
|
|
9785
10011
|
deps.renderer.write(
|
|
9786
|
-
`WrongStack ${CLI_VERSION} (apiVersion ${API_VERSION}, node ${process.version}, ${
|
|
10012
|
+
`WrongStack ${CLI_VERSION} (apiVersion ${API_VERSION}, node ${process.version}, ${os4.platform()})
|
|
9787
10013
|
`
|
|
9788
10014
|
);
|
|
9789
10015
|
return 0;
|
|
@@ -9863,22 +10089,22 @@ function fmtDuration(ms) {
|
|
|
9863
10089
|
const remMin = m - h * 60;
|
|
9864
10090
|
return `${h}h${remMin}m`;
|
|
9865
10091
|
}
|
|
9866
|
-
function fmtTaskResultLine(r,
|
|
10092
|
+
function fmtTaskResultLine(r, color41) {
|
|
9867
10093
|
const stats = `${r.iterations}it ${r.toolCalls}tc ${fmtDuration(r.durationMs)}`;
|
|
9868
10094
|
const errMsg = typeof r.error === "string" ? r.error : r.error?.message;
|
|
9869
10095
|
const errKind = typeof r.error === "object" ? r.error?.kind : void 0;
|
|
9870
10096
|
const errTail = errMsg ? ` \u2014 ${errMsg.replace(/\s+/g, " ").slice(0, 80)}${errMsg.length > 80 ? "\u2026" : ""}` : "";
|
|
9871
|
-
const errKindChip = errKind ?
|
|
9872
|
-
const errSnip = errMsg || errKind ? `${errKindChip}${
|
|
10097
|
+
const errKindChip = errKind ? color41.dim(` [${errKind}]`) : "";
|
|
10098
|
+
const errSnip = errMsg || errKind ? `${errKindChip}${color41.dim(errTail)}` : "";
|
|
9873
10099
|
switch (r.status) {
|
|
9874
10100
|
case "success":
|
|
9875
|
-
return { mark:
|
|
10101
|
+
return { mark: color41.green("\u2713"), stats, tail: "" };
|
|
9876
10102
|
case "timeout":
|
|
9877
|
-
return { mark:
|
|
10103
|
+
return { mark: color41.yellow("\u23F1"), stats: `${color41.yellow("timeout")} ${stats}`, tail: errSnip };
|
|
9878
10104
|
case "stopped":
|
|
9879
|
-
return { mark:
|
|
10105
|
+
return { mark: color41.dim("\u2298"), stats: `${color41.dim("stopped")} ${stats}`, tail: errSnip };
|
|
9880
10106
|
case "failed":
|
|
9881
|
-
return { mark:
|
|
10107
|
+
return { mark: color41.red("\u2717"), stats: `${color41.red("failed")} ${stats}`, tail: errSnip };
|
|
9882
10108
|
}
|
|
9883
10109
|
}
|
|
9884
10110
|
|
|
@@ -12988,6 +13214,8 @@ async function main(argv) {
|
|
|
12988
13214
|
statuslineHiddenItems: [...currentHiddenItems],
|
|
12989
13215
|
setStatuslineHiddenItems,
|
|
12990
13216
|
agentsMonitorController,
|
|
13217
|
+
configStore,
|
|
13218
|
+
reader,
|
|
12991
13219
|
confirm: async (question, defaultYes = true) => {
|
|
12992
13220
|
if (!process.stdin.isTTY) return false;
|
|
12993
13221
|
const hint = defaultYes ? "[Y/n/q]" : "[y/N/q]";
|
|
@@ -13218,12 +13446,12 @@ async function main(argv) {
|
|
|
13218
13446
|
if (!f.endsWith(".jsonl")) continue;
|
|
13219
13447
|
const full = path25.join(runDir, f);
|
|
13220
13448
|
try {
|
|
13221
|
-
const
|
|
13449
|
+
const stat4 = await fsp3.stat(full);
|
|
13222
13450
|
found.push({
|
|
13223
13451
|
runId,
|
|
13224
13452
|
subagentId: f.replace(/\.jsonl$/, ""),
|
|
13225
13453
|
file: full,
|
|
13226
|
-
size:
|
|
13454
|
+
size: stat4.size
|
|
13227
13455
|
});
|
|
13228
13456
|
} catch {
|
|
13229
13457
|
}
|