@wrongstack/cli 0.6.7 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -3,7 +3,7 @@ import * as path23 from 'path';
3
3
  import { join } from 'path';
4
4
  import * as fsp2 from 'fs/promises';
5
5
  import { readdir, readFile } from 'fs/promises';
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, makeAgentSubagentRunner, NULL_FLEET_BUS, resolveWstackPaths, DefaultSecretVault, migratePlaintextSecrets, DefaultConfigLoader, DefaultSessionReader, DefaultSessionRewinder, DefaultSessionStore, atomicWrite, DefaultPluginAPI, AutoApprovePermissionPolicy, formatContextWindowModeList, repairToolUseAdjacency, getContextWindowMode, resolveContextWindowPolicy, 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, InputBuilder, projectHash, defaultOrchestrator, decryptConfigSecrets, encryptConfigSecrets as encryptConfigSecrets$1, SpecVersioning, ParallelEternalEngine, allServers as allServers$1 } from '@wrongstack/core';
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, makeAgentSubagentRunner, NULL_FLEET_BUS, resolveWstackPaths, DefaultSecretVault, migratePlaintextSecrets, DefaultConfigLoader, DefaultSessionReader, DefaultSessionRewinder, DefaultSessionStore, atomicWrite, DefaultPluginAPI, AutoApprovePermissionPolicy, formatContextWindowModeList, repairToolUseAdjacency, getContextWindowMode, resolveContextWindowPolicy, 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, 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
8
  import * as os6 from 'os';
9
9
  import os6__default from 'os';
@@ -2753,7 +2753,16 @@ function entryId(ts) {
2753
2753
  return ts.replace(/[:.]/g, "-").slice(0, 19);
2754
2754
  }
2755
2755
  async function ensureHistoryDir(homeFn = defaultHomeDir) {
2756
- await fsp2.mkdir(historyDir(homeFn), { recursive: true });
2756
+ try {
2757
+ await fsp2.mkdir(historyDir(homeFn), { recursive: true });
2758
+ } catch (err) {
2759
+ throw new FsError({
2760
+ message: err instanceof Error ? err.message : String(err),
2761
+ code: ERROR_CODES.FS_MKDIR_FAILED,
2762
+ path: historyDir(homeFn),
2763
+ cause: err
2764
+ });
2765
+ }
2757
2766
  }
2758
2767
  async function readIndex(homeFn = defaultHomeDir) {
2759
2768
  try {
@@ -2765,7 +2774,16 @@ async function readIndex(homeFn = defaultHomeDir) {
2765
2774
  }
2766
2775
  async function writeIndex(idx, homeFn = defaultHomeDir) {
2767
2776
  await ensureHistoryDir(homeFn);
2768
- await atomicWrite(historyIndexPath(homeFn), JSON.stringify(idx, null, 2));
2777
+ try {
2778
+ await atomicWrite(historyIndexPath(homeFn), JSON.stringify(idx, null, 2));
2779
+ } catch (err) {
2780
+ throw new FsError({
2781
+ message: err instanceof Error ? err.message : String(err),
2782
+ code: ERROR_CODES.FS_ATOMIC_WRITE_FAILED,
2783
+ path: historyIndexPath(homeFn),
2784
+ cause: err
2785
+ });
2786
+ }
2769
2787
  }
2770
2788
  async function backupCurrent(homeFn = defaultHomeDir) {
2771
2789
  const cfg = configPath(homeFn);
@@ -2810,11 +2828,20 @@ async function appendHistory(oldCfg, newCfg, description, homeFn = defaultHomeDi
2810
2828
  snapshotMasked: maskConfigSecrets(newCfg),
2811
2829
  diffSummary: diffSummary(oldCfg, newCfg)
2812
2830
  };
2813
- await fsp2.writeFile(
2814
- path23.join(historyDir(homeFn), `${id}.json`),
2815
- JSON.stringify(entry, null, 2),
2816
- "utf8"
2817
- );
2831
+ try {
2832
+ await fsp2.writeFile(
2833
+ path23.join(historyDir(homeFn), `${id}.json`),
2834
+ JSON.stringify(entry, null, 2),
2835
+ "utf8"
2836
+ );
2837
+ } catch (err) {
2838
+ throw new FsError({
2839
+ message: err instanceof Error ? err.message : String(err),
2840
+ code: ERROR_CODES.FS_WRITE_FAILED,
2841
+ path: path23.join(historyDir(homeFn), `${id}.json`),
2842
+ cause: err
2843
+ });
2844
+ }
2818
2845
  const idx = await readIndex(homeFn);
2819
2846
  idx.entries.unshift({ id, timestamp, description });
2820
2847
  await writeIndex(idx, homeFn);
@@ -3476,17 +3503,37 @@ function buildClearCommand(opts) {
3476
3503
  };
3477
3504
  }
3478
3505
  async function runGit(args, cwd) {
3479
- return new Promise((resolve4) => {
3480
- const child = spawn("git", args, {
3481
- cwd,
3482
- stdio: ["ignore", "pipe", "pipe"]
3506
+ try {
3507
+ return await new Promise((resolve4, reject) => {
3508
+ const child = spawn("git", args, {
3509
+ cwd,
3510
+ stdio: ["ignore", "pipe", "pipe"]
3511
+ });
3512
+ let stdout = "";
3513
+ let stderr = "";
3514
+ child.stdout?.on("data", (d) => stdout += d);
3515
+ child.stderr?.on("data", (d) => stderr += d);
3516
+ child.on("error", (err) => {
3517
+ reject(new WrongStackError({
3518
+ message: `Failed to run git: ${err.message}`,
3519
+ code: ERROR_CODES.TOOL_EXECUTION_FAILED,
3520
+ subsystem: "tool",
3521
+ context: { command: "git", args, cwd },
3522
+ cause: err
3523
+ }));
3524
+ });
3525
+ child.on("close", (code) => resolve4({ stdout, stderr, code: code ?? 0 }));
3483
3526
  });
3484
- let stdout = "";
3485
- let stderr = "";
3486
- child.stdout?.on("data", (d) => stdout += d);
3487
- child.stderr?.on("data", (d) => stderr += d);
3488
- child.on("close", (code) => resolve4({ stdout, stderr, code: code ?? 0 }));
3489
- });
3527
+ } catch (err) {
3528
+ if (err instanceof WrongStackError) throw err;
3529
+ throw new WrongStackError({
3530
+ message: err instanceof Error ? err.message : String(err),
3531
+ code: ERROR_CODES.TOOL_EXECUTION_FAILED,
3532
+ subsystem: "tool",
3533
+ context: { command: "git", args, cwd },
3534
+ cause: err
3535
+ });
3536
+ }
3490
3537
  }
3491
3538
  function detectCommitType(stats) {
3492
3539
  const lines = stats.split("\n");
@@ -5505,8 +5552,17 @@ async function loadStatuslineConfig() {
5505
5552
  }
5506
5553
  async function saveStatuslineConfig(cfg) {
5507
5554
  const p = resolveConfigPath();
5508
- await fsp2.mkdir(path23.dirname(p), { recursive: true });
5509
- await atomicWrite(p, JSON.stringify(cfg, null, 2));
5555
+ try {
5556
+ await fsp2.mkdir(path23.dirname(p), { recursive: true });
5557
+ await atomicWrite(p, JSON.stringify(cfg, null, 2));
5558
+ } catch (err) {
5559
+ throw new FsError({
5560
+ message: err instanceof Error ? err.message : String(err),
5561
+ code: err instanceof Error && err.message.includes("mkdir") ? ERROR_CODES.FS_MKDIR_FAILED : ERROR_CODES.FS_ATOMIC_WRITE_FAILED,
5562
+ path: p,
5563
+ cause: err
5564
+ });
5565
+ }
5510
5566
  }
5511
5567
  function buildStatuslineCommand(deps) {
5512
5568
  return {
@@ -6708,6 +6764,7 @@ async function runProjectCheck(opts) {
6708
6764
  const { spawn: spawn3 } = await import('child_process');
6709
6765
  await new Promise((resolve4, reject) => {
6710
6766
  const child = spawn3("git", ["init"], { cwd: projectRoot });
6767
+ child.on("error", reject);
6711
6768
  child.on("close", (code) => code === 0 ? resolve4() : reject(new Error(`git init failed with ${code}`)));
6712
6769
  });
6713
6770
  renderer.write(` ${color.green("\u2713")} Git repository initialized
@@ -7786,7 +7843,7 @@ var updateCmd = async (args, deps) => {
7786
7843
  deps.renderer.write(`Updating wrongstack from v${info.current} to v${info.latest}...
7787
7844
  `);
7788
7845
  try {
7789
- const result = await new Promise((resolve4) => {
7846
+ const result = await new Promise((resolve4, reject) => {
7790
7847
  const child = spawn("npm", ["install", "-g", "wrongstack@latest"], {
7791
7848
  cwd,
7792
7849
  stdio: "pipe"
@@ -7795,6 +7852,7 @@ var updateCmd = async (args, deps) => {
7795
7852
  child.stderr?.on("data", (d) => {
7796
7853
  stderr += d;
7797
7854
  });
7855
+ child.on("error", reject);
7798
7856
  child.on("close", (code) => resolve4({ code: code ?? 0 }));
7799
7857
  });
7800
7858
  if (result.code === 0) {
@@ -9382,9 +9440,15 @@ async function runRepl(opts) {
9382
9440
  } else {
9383
9441
  const beforeGoal = await loadGoalSafe(opts);
9384
9442
  const beforeIter = beforeGoal?.iterations ?? 0;
9443
+ const coord = engine.getCoordinator();
9444
+ if (coord) {
9445
+ const stats = coord.getStats();
9446
+ opts.renderer.write(
9447
+ color.dim(` \u250C\u2500 Fleet: ${stats.running} running, ${stats.idle} idle, ${stats.pending} pending, ${stats.completed} done`) + "\n"
9448
+ );
9449
+ }
9385
9450
  opts.renderer.write(
9386
- color.magenta(`
9387
- \u21B3 [parallel #${beforeIter + 1}] launching fan-out\u2026
9451
+ color.magenta(` \u21B3 [parallel #${beforeIter + 1}] launching fan-out\u2026
9388
9452
  `)
9389
9453
  );
9390
9454
  interrupts = 0;
@@ -9392,6 +9456,13 @@ async function runRepl(opts) {
9392
9456
  const ok = await engine.runOneIteration();
9393
9457
  const afterGoal = await loadGoalSafe(opts);
9394
9458
  const last = afterGoal?.journal[afterGoal.journal.length - 1];
9459
+ if (coord) {
9460
+ const stats = coord.getStats();
9461
+ opts.renderer.write(
9462
+ color.dim(` \u2514\u2500 Fleet: ${stats.running} running, ${stats.idle} idle, ${stats.completed} done
9463
+ `)
9464
+ );
9465
+ }
9395
9466
  if (last) {
9396
9467
  const mark = last.status === "success" ? color.green("\u2713") : last.status === "failure" ? color.red("\u2717") : color.amber("\u2298");
9397
9468
  const tail = last.note ? color.dim(` \u2014 ${last.note.slice(0, 80)}`) : "";
@@ -9743,9 +9814,17 @@ async function renderGoalBanner(opts) {
9743
9814
  const goal = await loadGoalSafe(opts);
9744
9815
  if (!goal) return;
9745
9816
  const summary = goal.goal.length > 80 ? `${goal.goal.slice(0, 77)}\u2026` : goal.goal;
9817
+ const stateColor = goal.goalState === "active" ? color.green : goal.goalState === "paused" ? color.amber : goal.goalState === "completed" ? color.green : goal.goalState === "abandoned" ? color.dim : color.dim;
9746
9818
  opts.renderer.write(
9747
- color.dim("Goal: ") + color.bold(summary) + color.dim(` (iter ${goal.iterations})`) + "\n"
9819
+ color.dim("Goal: ") + stateColor(summary) + color.dim(` [${goal.goalState}] (iter ${goal.iterations})`) + "\n"
9748
9820
  );
9821
+ if (goal.journal.length > 0) {
9822
+ const lastEntry = goal.journal[goal.journal.length - 1];
9823
+ const statusIcon2 = lastEntry.status === "success" ? "\u2713" : lastEntry.status === "failure" ? "\u2717" : lastEntry.status === "aborted" ? "\u2298" : lastEntry.status === "skipped" ? "\u229D" : "\xB7";
9824
+ opts.renderer.write(
9825
+ color.dim(` Last: ${statusIcon2} ${lastEntry.task} (${lastEntry.status})`) + "\n"
9826
+ );
9827
+ }
9749
9828
  if (goal.engineState === "running") {
9750
9829
  opts.renderer.write(
9751
9830
  color.amber(" \u21BA Eternal engine was running when last session ended.") + "\n"
@@ -9770,6 +9849,18 @@ async function renderGoalBanner(opts) {
9770
9849
  color.dim(" Use `/autonomy eternal` to resume.") + "\n"
9771
9850
  );
9772
9851
  }
9852
+ } else if (goal.goalState === "paused") {
9853
+ opts.renderer.write(
9854
+ color.amber(" \u23F8 Goal is paused. Use `/goal resume` to continue.") + "\n"
9855
+ );
9856
+ } else if (goal.goalState === "completed") {
9857
+ opts.renderer.write(
9858
+ color.green(" \u2713 Goal completed! Use `/goal clear` to set a new goal.") + "\n"
9859
+ );
9860
+ } else if (goal.goalState === "abandoned") {
9861
+ opts.renderer.write(
9862
+ color.dim(" Use `/goal clear` to set a new goal.") + "\n"
9863
+ );
9773
9864
  }
9774
9865
  opts.renderer.write("\n");
9775
9866
  }
@@ -10011,6 +10102,7 @@ async function execute(deps) {
10011
10102
  setStatuslineHiddenItems,
10012
10103
  initialGoal: goalFlag,
10013
10104
  initialAsk: askFlag,
10105
+ projectRoot,
10014
10106
  getSDDContext: () => {
10015
10107
  const { getActiveSDDContext: getActiveSDDContext2 } = (init_sdd(), __toCommonJS(sdd_exports));
10016
10108
  return getActiveSDDContext2();
@@ -12095,10 +12187,11 @@ Restart WrongStack to load or unload plugin code in this session.`;
12095
12187
  onBeforeExit: async () => {
12096
12188
  const { spawn: spawn3 } = await import('child_process');
12097
12189
  const cwd2 = projectRoot;
12098
- const statusResult = await new Promise((resolve4) => {
12190
+ const statusResult = await new Promise((resolve4, reject) => {
12099
12191
  const child = spawn3("git", ["status", "--porcelain"], { cwd: cwd2, stdio: ["ignore", "pipe", "pipe"] });
12100
12192
  let stdout = "";
12101
12193
  child.stdout?.on("data", (d) => stdout += d);
12194
+ child.on("error", reject);
12102
12195
  child.on("close", (code) => resolve4({ stdout, code: code ?? 0 }));
12103
12196
  });
12104
12197
  if (statusResult.stdout.trim().length > 0) {
@@ -12262,12 +12355,12 @@ if (isMain) {
12262
12355
  main(process.argv.slice(2)).then(
12263
12356
  (c) => {
12264
12357
  process.exitCode = c;
12265
- setTimeout(() => process.exit(c), 200).unref();
12358
+ setTimeout(() => process.exit(c), 500).unref();
12266
12359
  },
12267
12360
  (err) => {
12268
12361
  process.stderr.write((err instanceof Error ? err.stack : String(err)) + "\n");
12269
12362
  process.exitCode = 1;
12270
- setTimeout(() => process.exit(1), 200).unref();
12363
+ setTimeout(() => process.exit(1), 500).unref();
12271
12364
  }
12272
12365
  );
12273
12366
  }