@wrongstack/cli 1.0.19 → 1.0.24

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.
Files changed (124) hide show
  1. package/dist/{acp-INCNOH42.js → acp-AJWSKWE5.js} +18 -7
  2. package/dist/arg-parser.d.ts +1 -0
  3. package/dist/{auth-YXK3EDUL.js → auth-GRBZ7Y3D.js} +61 -15
  4. package/dist/auth-menu/direct.d.ts +1 -0
  5. package/dist/auth-menu/local.d.ts +2 -0
  6. package/dist/auth-menu/oauth-menu.d.ts +3 -1
  7. package/dist/auth-menu/panel-service.d.ts +20 -0
  8. package/dist/{bench-YBU6BVQP.js → bench-N5K7Z5O3.js} +2 -2
  9. package/dist/boot/config-backup-recovery.d.ts +2 -1
  10. package/dist/boot/dispatch-webui.d.ts +11 -0
  11. package/dist/boot/short-circuit-desktop.d.ts +1 -0
  12. package/dist/boot/tui-project-picker-callback.d.ts +1 -1
  13. package/dist/boot/tui-settings-adapter.d.ts +15 -2
  14. package/dist/{boot-auto-thin-MANHOYHE.js → boot-auto-thin-6Q56FY3F.js} +3 -2
  15. package/dist/{chunk-6WRKAACA.js → chunk-2BKFWIER.js} +4 -2
  16. package/dist/{chunk-JY52HWL6.js → chunk-2EBVTYJR.js} +2 -2
  17. package/dist/chunk-3OCUS3VN.js +46 -0
  18. package/dist/chunk-424ORSE7.js +56 -0
  19. package/dist/{chunk-KEPABQYT.js → chunk-5SEYGOCH.js} +8 -82
  20. package/dist/chunk-BBHWW6LR.js +549 -0
  21. package/dist/{chunk-CJTBLTS4.js → chunk-BLD5DSVA.js} +4 -3
  22. package/dist/{chunk-KK2LB3ZS.js → chunk-DRM7PSW7.js} +9 -5
  23. package/dist/{chunk-XJ7K67PP.js → chunk-JF2MULWF.js} +17 -10
  24. package/dist/{chunk-SIS37L3W.js → chunk-L2RVEQWO.js} +211 -193
  25. package/dist/{chunk-RDHFXOJM.js → chunk-LFMVHT3R.js} +106 -57
  26. package/dist/chunk-LUMETJFO.js +171 -0
  27. package/dist/{chunk-C3Z4N6A6.js → chunk-MHEBWVXL.js} +6 -2
  28. package/dist/{chunk-2ENZU66X.js → chunk-PGKJ2OQP.js} +5 -5
  29. package/dist/{chunk-672UXYL3.js → chunk-QBBF7GIK.js} +2 -2
  30. package/dist/{chunk-DE7BZDNK.js → chunk-QFPQXKCG.js} +11 -3
  31. package/dist/chunk-R4QGL6GB.js +10 -0
  32. package/dist/chunk-S4FFHDJG.js +93 -0
  33. package/dist/chunk-SFBFYIOW.js +271 -0
  34. package/dist/{chunk-JX6KL7OF.js → chunk-SKPDE62W.js} +4 -3
  35. package/dist/{chunk-RMQNCHGO.js → chunk-U46QR4WR.js} +5 -9
  36. package/dist/{chunk-B4JLSXZB.js → chunk-WSTVGC2C.js} +73 -45
  37. package/dist/chunk-YBUCXXYZ.js +36 -0
  38. package/dist/{chunk-2VMJ3E5Z.js → chunk-YTEOAWOJ.js} +6 -2
  39. package/dist/{chunk-GPPRNAKW.js → chunk-ZMX5HRLI.js} +2 -2
  40. package/dist/{chunk-YLQEGYV4.js → chunk-ZZRSG7VK.js} +14 -4
  41. package/dist/{cli-context-33F74CSZ.js → cli-context-34Q5IJRA.js} +121 -89
  42. package/dist/cli-entry-point.d.ts +2 -0
  43. package/dist/{cli-main-FNGMKPBA.js → cli-main-AELJDBGU.js} +1439 -1276
  44. package/dist/config-doctor.d.ts +10 -2
  45. package/dist/{config-transfer-2YF3CRTN.js → config-transfer-RUWLDCNK.js} +34 -13
  46. package/dist/{diag-doctor-ANPRUYFM.js → diag-doctor-WIFJH3XH.js} +2 -2
  47. package/dist/execute-deps.d.ts +2 -1
  48. package/dist/{execution-A6WJLSOC.js → execution-PYC5FCS4.js} +303 -256
  49. package/dist/{hq-XQWQTRDA.js → hq-JTUTFI4L.js} +274 -258
  50. package/dist/hq-command-controller.d.ts +1 -1
  51. package/dist/{hq-server-IIBZQZU4.js → hq-server-PC7GZMPT.js} +2 -2
  52. package/dist/{hq-service-L5INQFM4.js → hq-service-NW56MUP2.js} +11 -4
  53. package/dist/index.d.ts +1 -1
  54. package/dist/index.js +17 -12
  55. package/dist/kanban-supervisor-67ECABTD.js +7 -0
  56. package/dist/live-settings-input.d.ts +7 -0
  57. package/dist/{mailbox-serve-3GFOK2I7.js → mailbox-serve-WDOCH6KR.js} +3 -3
  58. package/dist/{mcp-DC5WSBOO.js → mcp-LBS45HWZ.js} +4 -4
  59. package/dist/modeldiag-36OGAL5C.js +828 -0
  60. package/dist/{per-subcommand-help-DHTYU524.js → per-subcommand-help-XE77MTGJ.js} +3 -3
  61. package/dist/permission-prompt-mirror.d.ts +1 -1
  62. package/dist/permission-prompt.d.ts +2 -2
  63. package/dist/plugin-config.d.ts +12 -0
  64. package/dist/plugin-management-types.d.ts +31 -0
  65. package/dist/plugin-management.d.ts +2 -30
  66. package/dist/plugin-package-install.d.ts +3 -0
  67. package/dist/{plugin-usage-M6KET4OZ.js → plugin-usage-S5LVGMBW.js} +6 -5
  68. package/dist/{plugins-WJLW6ULV.js → plugins-RHBIVLI7.js} +4 -3
  69. package/dist/provider-config-utils.d.ts +1 -6
  70. package/dist/{providers-models-LFNZ5WI7.js → providers-models-2CFG46RD.js} +41 -31
  71. package/dist/release-asset-download.d.ts +3 -0
  72. package/dist/services/dispatch-classifier.d.ts +39 -5
  73. package/dist/{sessions-config-UL45XKX7.js → sessions-config-IQUH2GXT.js} +13 -5
  74. package/dist/settings-menu.d.ts +2 -0
  75. package/dist/short-circuit-flags-SDT53OML.js +10 -0
  76. package/dist/{simpleui-dist-CXSIDAXZ.js → simpleui-dist-7BQISSEP.js} +7 -3
  77. package/dist/skill-suggest-L2EVWB6R.js +290 -0
  78. package/dist/slash-commands/effort.d.ts +1 -1
  79. package/dist/slash-commands/fallback.d.ts +1 -1
  80. package/dist/slash-commands/gitid.d.ts +1 -1
  81. package/dist/slash-commands/jev.d.ts +4 -0
  82. package/dist/slash-commands/openai-quota.d.ts +15 -0
  83. package/dist/slash-commands/sdd-task-mutations.d.ts +4 -0
  84. package/dist/slash-commands/settings-keys.d.ts +2 -0
  85. package/dist/slash-commands/settings-reset.d.ts +6 -0
  86. package/dist/standalone-update-MW47J3AK.js +164 -0
  87. package/dist/standalone-update.d.ts +19 -0
  88. package/dist/subcommands/handlers/hq-alerts.d.ts +3 -0
  89. package/dist/subcommands/handlers/hq-audit.d.ts +46 -0
  90. package/dist/subcommands/handlers/hq-data-dir.d.ts +13 -0
  91. package/dist/subcommands/handlers/skill-suggest.d.ts +21 -0
  92. package/dist/subcommands/handlers/typesafe-brain-replay.d.ts +26 -0
  93. package/dist/subcommands/handlers/typesafe-judgment-check.d.ts +3 -0
  94. package/dist/subcommands/handlers/typesafe-topic-replay.d.ts +19 -0
  95. package/dist/subcommands/handlers/typesafe-triage-replay.d.ts +18 -0
  96. package/dist/subcommands/handlers/typesafe.d.ts +23 -0
  97. package/dist/{subcommands-XSLXMIDP.js → subcommands-ZTSIN7LG.js} +2 -2
  98. package/dist/typesafe-HVEVPA6R.js +316 -0
  99. package/dist/typesafe-brain-replay-C5276FVR.js +222 -0
  100. package/dist/typesafe-judgment-check-GGYYV5UF.js +29 -0
  101. package/dist/typesafe-topic-replay-4W73BOLV.js +218 -0
  102. package/dist/typesafe-triage-replay-FGAW7QM7.js +215 -0
  103. package/dist/{update-5DPB4YD4.js → update-7XIOEXTD.js} +4 -3
  104. package/dist/{update-check-BS3DHTSI.js → update-check-2POMBHFB.js} +3 -2
  105. package/dist/update-check.d.ts +1 -1
  106. package/dist/version-help-WZ623NWM.js +10 -0
  107. package/dist/version.d.ts +3 -2
  108. package/dist/webui-client-observability.d.ts +7 -0
  109. package/dist/{webui-server-MRPGTTKL.js → webui-server-L2SICPTB.js} +158 -94
  110. package/dist/webui-server-options.d.ts +11 -0
  111. package/dist/webui-server.d.ts +15 -1
  112. package/dist/wiring/domain-glossary.d.ts +5 -4
  113. package/dist/wiring/plugins.d.ts +1 -1
  114. package/dist/wiring/provider-persisters.d.ts +24 -0
  115. package/dist/wiring/provider-runtime.d.ts +9 -1
  116. package/dist/wiring/runtime-dispatch-state.d.ts +3 -1
  117. package/package.json +28 -28
  118. package/dist/chunk-2CZEORLV.js +0 -54
  119. package/dist/chunk-DR2OXU46.js +0 -174
  120. package/dist/chunk-JACOMTIH.js +0 -275
  121. package/dist/chunk-XJXDOF63.js +0 -28
  122. package/dist/modeldiag-CJSFHZ3J.js +0 -1356
  123. package/dist/short-circuit-flags-7GQIGMVD.js +0 -10
  124. package/dist/version-help-WXI42PZ3.js +0 -10
@@ -1,24 +1,27 @@
1
1
  import {
2
2
  createKanbanRunMirror
3
3
  } from "./chunk-VCYZ3WZV.js";
4
+ import {
5
+ createKanbanSupervisor
6
+ } from "./chunk-R4QGL6GB.js";
4
7
  import {
5
8
  WEBUI_SESSION_CHILD_CAPABILITIES
6
- } from "./chunk-GPPRNAKW.js";
9
+ } from "./chunk-ZMX5HRLI.js";
7
10
  import {
8
11
  createHqCommandDispatcher,
9
12
  createProjectKanbanAssignHandler,
10
13
  createProjectKanbanTransitionHandler
11
- } from "./chunk-JY52HWL6.js";
14
+ } from "./chunk-2EBVTYJR.js";
12
15
  import {
13
16
  startCliHqConnection
14
- } from "./chunk-CJTBLTS4.js";
15
- import {
16
- CLI_VERSION
17
- } from "./chunk-XJXDOF63.js";
17
+ } from "./chunk-BLD5DSVA.js";
18
18
  import {
19
19
  loadConfigProviders,
20
20
  mutateConfigProviders
21
- } from "./chunk-DR2OXU46.js";
21
+ } from "./chunk-LUMETJFO.js";
22
+ import {
23
+ CLI_VERSION
24
+ } from "./chunk-YBUCXXYZ.js";
22
25
 
23
26
  // src/webui-server.ts
24
27
  import * as path7 from "node:path";
@@ -48,12 +51,14 @@ import {
48
51
  sendSerialized,
49
52
  stampDispatchSession,
50
53
  startTerminalDashboard,
51
- startWebUILiveStatusLogger,
52
54
  toSessionHistoryEntries
53
55
  } from "@wrongstack/webui-server";
54
56
  import { verifyClient as verifyWsClient2 } from "@wrongstack/webui-server/server/ws-auth";
55
57
  import { WebSocketServer } from "ws";
56
58
 
59
+ // src/webui-client-observability.ts
60
+ import { startWebUILiveStatusLogger } from "@wrongstack/webui-server";
61
+
57
62
  // src/webui-server/client-registration.ts
58
63
  import { mailboxSessionTag } from "@wrongstack/core/coordination";
59
64
  import { createWebuiClientPresence } from "@wrongstack/webui-server";
@@ -104,6 +109,87 @@ function createWebuiClientRegistration(deps) {
104
109
  });
105
110
  }
106
111
 
112
+ // src/webui-client-observability.ts
113
+ function createEmbeddedClientRegistration(opts, clients, abortControllers, getSessionAgents) {
114
+ return createWebuiClientRegistration({
115
+ projectRoot: opts.projectRoot,
116
+ appConfig: opts.appConfig,
117
+ events: opts.events,
118
+ hqSessionId: opts.session.id,
119
+ getSessionId: () => opts.agent.ctx.session?.id ?? opts.session.id,
120
+ // One HQ session per open tab. The set is the same one the terminal
121
+ // panel lists: every session a connected browser is displaying.
122
+ listSessions: () => {
123
+ const ids = /* @__PURE__ */ new Set();
124
+ for (const client of clients.values()) {
125
+ if (client.sessionId) ids.add(client.sessionId);
126
+ for (const id of client.sessionIds ?? []) ids.add(id);
127
+ }
128
+ return [...ids];
129
+ },
130
+ // `cli-main` already runs a tracker and a bridge for the boot session.
131
+ // Announcing it here too would put two trackers on one bus flushing the
132
+ // same agent list.
133
+ isSessionOwnedElsewhere: (sessionId) => sessionId === opts.session.id,
134
+ // The tab's own journal, so HQ takes its turns from the write path
135
+ // instead of tailing the file.
136
+ getSessionWriter: (sessionId) => getSessionAgents()?.peek(sessionId)?.ctx.session,
137
+ hqControl: {
138
+ // HQ speaks for the LEADER — the boot session, the one it registered
139
+ // itself under (`hqSessionId`) — not for whatever else the browser
140
+ // has open. This used to abort every controller in the map and clear
141
+ // it, so a remote "interrupt" issued against the leader also killed
142
+ // the three other tabs' in-flight runs. Deleting the entries was
143
+ // wrong on its own terms too: the run's own `end()` owns removal, and
144
+ // clearing early makes `isRunActive` lie to every tab still running.
145
+ // Every open tab is its own session with its own abort controller, so
146
+ // the command's session is the one that gets stopped. Falling back to
147
+ // the boot session keeps a dashboard that sends no session — every one
148
+ // before this existed — behaving exactly as before.
149
+ interruptLeader: (sessionId) => {
150
+ const leaderId = sessionId ?? opts.session.id;
151
+ const controller = abortControllers.get(leaderId);
152
+ if (!controller) return false;
153
+ controller.abort();
154
+ try {
155
+ void Promise.resolve(opts.stopSessionFleet?.(leaderId)).catch(() => void 0);
156
+ } catch {
157
+ }
158
+ return true;
159
+ },
160
+ allowRunCommand: () => opts.hqAllowExec === true,
161
+ // A command naming a tab this process no longer holds is refused, not
162
+ // redirected onto the boot session: the operator picked a terminal,
163
+ // and steering a different one is worse than not steering at all.
164
+ ownsSession: (sessionId) => sessionId === opts.session.id || getSessionAgents()?.has(sessionId) === true
165
+ }
166
+ });
167
+ }
168
+ function startEmbeddedLiveStatusLogger(opts, clients, abortControllers, getSessionAgents, terminalLogView) {
169
+ return startWebUILiveStatusLogger({
170
+ events: opts.events,
171
+ dashboard: terminalLogView,
172
+ getSessionList: () => {
173
+ const ids = /* @__PURE__ */ new Set();
174
+ for (const client of clients.values()) {
175
+ if (client.sessionId) ids.add(client.sessionId);
176
+ for (const id of client.sessionIds ?? []) ids.add(id);
177
+ }
178
+ const currentId = opts.agent.ctx.session?.id ?? opts.session.id;
179
+ if (ids.size === 0 && currentId) ids.add(currentId);
180
+ return Array.from(ids).map((id) => {
181
+ const ctx = getSessionAgents()?.peek(id)?.ctx;
182
+ return {
183
+ id,
184
+ model: ctx?.model ?? opts.agent.ctx.model ?? "",
185
+ provider: ctx?.provider?.id ?? opts.agent.ctx.provider?.id ?? "",
186
+ isRunning: abortControllers.has(id)
187
+ };
188
+ });
189
+ }
190
+ });
191
+ }
192
+
107
193
  // src/webui-server/connection-handler.ts
108
194
  import { deriveSessionAgents } from "@wrongstack/core/storage";
109
195
  import { buildReplayPayload, decodeProtocolFrame } from "@wrongstack/webui-protocol";
@@ -239,6 +325,8 @@ import { makeProviderFromConfig } from "@wrongstack/providers";
239
325
  // src/webui-server/provider-config.ts
240
326
  import * as path from "node:path";
241
327
  import { DefaultSecretVault } from "@wrongstack/core/security";
328
+ import { ProviderConfigSnapshots } from "@wrongstack/providers";
329
+ var snapshots = new ProviderConfigSnapshots();
242
330
  function getVault(globalConfigPath) {
243
331
  const configDir = path.dirname(globalConfigPath ?? "");
244
332
  const parentDir = path.dirname(configDir);
@@ -248,7 +336,7 @@ function getVault(globalConfigPath) {
248
336
  }
249
337
  async function loadSavedProviders(globalConfigPath) {
250
338
  if (!globalConfigPath) return {};
251
- return loadConfigProviders(globalConfigPath, getVault(globalConfigPath));
339
+ return snapshots.track(await loadConfigProviders(globalConfigPath, getVault(globalConfigPath)));
252
340
  }
253
341
  async function saveProviders(globalConfigPath, providers) {
254
342
  if (!globalConfigPath) return;
@@ -256,14 +344,56 @@ async function saveProviders(globalConfigPath, providers) {
256
344
  globalConfigPath,
257
345
  getVault(globalConfigPath),
258
346
  (existing) => {
347
+ const merged = snapshots.merge(existing, providers);
259
348
  for (const key of Object.keys(existing)) delete existing[key];
260
- Object.assign(existing, providers);
349
+ Object.assign(existing, merged);
350
+ for (const key of Object.keys(providers)) delete providers[key];
351
+ Object.assign(providers, merged);
261
352
  }
262
353
  );
354
+ snapshots.track(providers);
263
355
  }
264
356
  function createProviderConfigStore(globalConfigPath, configProvidersRef) {
357
+ if (configProvidersRef && globalConfigPath) {
358
+ const views = /* @__PURE__ */ new WeakMap();
359
+ const equal = (a, b) => JSON.stringify(a) === JSON.stringify(b);
360
+ return {
361
+ load: async () => {
362
+ const disk = await loadSavedProviders(globalConfigPath);
363
+ const providers = structuredClone(configProvidersRef());
364
+ views.set(providers, { view: structuredClone(providers), disk });
365
+ return providers;
366
+ },
367
+ save: async (providers) => {
368
+ const baseline = views.get(providers);
369
+ if (!baseline) {
370
+ throw new Error("Load the provider list before saving. Refresh and try again.");
371
+ }
372
+ const pending = structuredClone(baseline.disk);
373
+ snapshots.track(pending);
374
+ for (const id of /* @__PURE__ */ new Set([...Object.keys(baseline.view), ...Object.keys(providers)])) {
375
+ if (equal(baseline.view[id], providers[id])) continue;
376
+ if (!equal(baseline.view[id], baseline.disk[id])) {
377
+ throw new Error(
378
+ `Provider "${id}" comes from another config file. Edit its source config or create a new auth profile alias.`
379
+ );
380
+ }
381
+ if (Object.hasOwn(providers, id)) pending[id] = structuredClone(providers[id]);
382
+ else delete pending[id];
383
+ }
384
+ await saveProviders(globalConfigPath, pending);
385
+ for (const id of Object.keys(providers)) {
386
+ if (equal(baseline.view[id], baseline.disk[id])) delete providers[id];
387
+ }
388
+ for (const [id, record] of Object.entries(pending)) {
389
+ if (equal(baseline.view[id], baseline.disk[id])) providers[id] = record;
390
+ }
391
+ views.set(providers, { view: structuredClone(providers), disk: structuredClone(pending) });
392
+ }
393
+ };
394
+ }
265
395
  return {
266
- load: () => configProvidersRef ? Promise.resolve(configProvidersRef()) : loadSavedProviders(globalConfigPath),
396
+ load: () => configProvidersRef ? Promise.resolve(snapshots.track(structuredClone(configProvidersRef()))) : loadSavedProviders(globalConfigPath),
267
397
  save: (providers) => saveProviders(globalConfigPath, providers)
268
398
  };
269
399
  }
@@ -410,6 +540,7 @@ import { existsSync } from "node:fs";
410
540
  import { createRequire } from "node:module";
411
541
  import * as path2 from "node:path";
412
542
  import { fileURLToPath } from "node:url";
543
+ import { isStandaloneBinary } from "@wrongstack/core/utils";
413
544
  import { repairNodePtySpawnHelper } from "@wrongstack/webui-server";
414
545
  function createNodePtyLoader(importMetaUrl, logger) {
415
546
  const requireFromCli = createRequire(importMetaUrl);
@@ -421,6 +552,10 @@ function createNodePtyLoader(importMetaUrl, logger) {
421
552
  };
422
553
  return () => {
423
554
  if (cachedNodePty !== void 0) return cachedNodePty;
555
+ if (isStandaloneBinary()) {
556
+ cachedNodePty = null;
557
+ return null;
558
+ }
424
559
  try {
425
560
  const webuiEntry = requireFromCli.resolve("@wrongstack/webui");
426
561
  const webuiDir = webuiEntry.replace(/[\\/]dist.*$/, "");
@@ -607,10 +742,10 @@ function createCliKanbanHostRoutes(deps) {
607
742
  });
608
743
  return;
609
744
  }
610
- const snapshots = await deps.kanbanSupervisor.auditNow(boardId);
745
+ const snapshots2 = await deps.kanbanSupervisor.auditNow(boardId);
611
746
  send(ws, {
612
747
  type: "kanban.supervisor.audit",
613
- payload: { success: true, data: boardId ? snapshots[0] ?? null : snapshots }
748
+ payload: { success: true, data: boardId ? snapshots2[0] ?? null : snapshots2 }
614
749
  });
615
750
  },
616
751
  runStart: async (ws, msg) => {
@@ -702,11 +837,6 @@ function createCliKanbanHostRoutes(deps) {
702
837
  };
703
838
  }
704
839
 
705
- // src/webui-server/kanban-supervisor.ts
706
- import {
707
- createKanbanSupervisor
708
- } from "@wrongstack/webui-server";
709
-
710
840
  // src/webui-server/lifecycle.ts
711
841
  import {
712
842
  announceWebuiReady,
@@ -1436,59 +1566,7 @@ async function runWebUI(opts) {
1436
1566
  // for a session id that arrived from a stale browser tab.
1437
1567
  getSessionContext: (sessionId) => sessionAgentsRef?.peek(sessionId)?.ctx
1438
1568
  });
1439
- const { register: registerWebuiClient, unregister: unregisterWebuiClient } = createWebuiClientRegistration({
1440
- projectRoot: opts.projectRoot,
1441
- appConfig: opts.appConfig,
1442
- events: opts.events,
1443
- hqSessionId: opts.session.id,
1444
- getSessionId: () => opts.agent.ctx.session?.id ?? opts.session.id,
1445
- // One HQ session per open tab. The set is the same one the terminal
1446
- // panel lists: every session a connected browser is displaying.
1447
- listSessions: () => {
1448
- const ids = /* @__PURE__ */ new Set();
1449
- for (const client of clients.values()) {
1450
- if (client.sessionId) ids.add(client.sessionId);
1451
- for (const id of client.sessionIds ?? []) ids.add(id);
1452
- }
1453
- return [...ids];
1454
- },
1455
- // `cli-main` already runs a tracker and a bridge for the boot session.
1456
- // Announcing it here too would put two trackers on one bus flushing the
1457
- // same agent list.
1458
- isSessionOwnedElsewhere: (sessionId) => sessionId === opts.session.id,
1459
- // The tab's own journal, so HQ takes its turns from the write path
1460
- // instead of tailing the file.
1461
- getSessionWriter: (sessionId) => sessionAgentsRef?.peek(sessionId)?.ctx.session,
1462
- hqControl: {
1463
- // HQ speaks for the LEADER — the boot session, the one it registered
1464
- // itself under (`hqSessionId`) — not for whatever else the browser
1465
- // has open. This used to abort every controller in the map and clear
1466
- // it, so a remote "interrupt" issued against the leader also killed
1467
- // the three other tabs' in-flight runs. Deleting the entries was
1468
- // wrong on its own terms too: the run's own `end()` owns removal, and
1469
- // clearing early makes `isRunActive` lie to every tab still running.
1470
- // Every open tab is its own session with its own abort controller, so
1471
- // the command's session is the one that gets stopped. Falling back to
1472
- // the boot session keeps a dashboard that sends no session — every one
1473
- // before this existed — behaving exactly as before.
1474
- interruptLeader: (sessionId) => {
1475
- const leaderId = sessionId ?? opts.session.id;
1476
- const controller = abortControllers.get(leaderId);
1477
- if (!controller) return false;
1478
- controller.abort();
1479
- try {
1480
- void Promise.resolve(opts.stopSessionFleet?.(leaderId)).catch(() => void 0);
1481
- } catch {
1482
- }
1483
- return true;
1484
- },
1485
- allowRunCommand: () => opts.hqAllowExec === true,
1486
- // A command naming a tab this process no longer holds is refused, not
1487
- // redirected onto the boot session: the operator picked a terminal,
1488
- // and steering a different one is worse than not steering at all.
1489
- ownsSession: (sessionId) => sessionId === opts.session.id || sessionAgentsRef?.has(sessionId) === true
1490
- }
1491
- });
1569
+ const { register: registerWebuiClient, unregister: unregisterWebuiClient } = createEmbeddedClientRegistration(opts, clients, abortControllers, () => sessionAgentsRef);
1492
1570
  registerWebuiClient();
1493
1571
  const wsToken = resolveAuthToken(opts.accessToken);
1494
1572
  const publicHostnames = [publicUrl, publicWsUrl].map((value) => {
@@ -1728,28 +1806,13 @@ async function runWebUI(opts) {
1728
1806
  broadcast,
1729
1807
  logger: { warn: (message) => consoleLogger.warn(message) }
1730
1808
  }) : void 0;
1731
- const stopLiveStatusLogger = startWebUILiveStatusLogger({
1732
- events: opts.events,
1733
- dashboard: terminalLogView,
1734
- getSessionList: () => {
1735
- const ids = /* @__PURE__ */ new Set();
1736
- for (const client of clients.values()) {
1737
- if (client.sessionId) ids.add(client.sessionId);
1738
- for (const id of client.sessionIds ?? []) ids.add(id);
1739
- }
1740
- const currentId = opts.agent.ctx.session?.id ?? opts.session.id;
1741
- if (ids.size === 0 && currentId) ids.add(currentId);
1742
- return Array.from(ids).map((id) => {
1743
- const ctx = sessionAgentsRef?.peek(id)?.ctx;
1744
- return {
1745
- id,
1746
- model: ctx?.model ?? opts.agent.ctx.model ?? "",
1747
- provider: ctx?.provider?.id ?? opts.agent.ctx.provider?.id ?? "",
1748
- isRunning: abortControllers.has(id)
1749
- };
1750
- });
1751
- }
1752
- });
1809
+ const stopLiveStatusLogger = startEmbeddedLiveStatusLogger(
1810
+ opts,
1811
+ clients,
1812
+ abortControllers,
1813
+ () => sessionAgentsRef,
1814
+ terminalLogView
1815
+ );
1753
1816
  const releaseSessionSalvage = addFatalSalvageHook(() => {
1754
1817
  try {
1755
1818
  sessionAgents.flushAllSync();
@@ -1837,6 +1900,7 @@ async function runWebUI(opts) {
1837
1900
  const shutdown = () => signalShutdown?.();
1838
1901
  let embeddedAutoHealDispose = null;
1839
1902
  const handleMessage = createEmbeddedMessageRouter({
1903
+ jevVault: getVault(opts.globalConfigPath ?? opts.profileConfigPath),
1840
1904
  trustBoundary,
1841
1905
  opts,
1842
1906
  logger: consoleLogger,
@@ -2030,4 +2094,4 @@ async function runWebUI(opts) {
2030
2094
  export {
2031
2095
  runWebUI
2032
2096
  };
2033
- //# sourceMappingURL=webui-server-MRPGTTKL.js.map
2097
+ //# sourceMappingURL=webui-server-L2SICPTB.js.map
@@ -262,6 +262,17 @@ export interface CliWebUIOptions {
262
262
  fallbackProfile?: string | undefined;
263
263
  skills?: string[] | undefined;
264
264
  tools?: string[] | undefined;
265
+ signal?: AbortSignal | undefined;
266
+ context?: {
267
+ sessionId?: string;
268
+ kanban?: {
269
+ boardId?: string;
270
+ taskId?: string;
271
+ projectRoot?: string;
272
+ leaseId?: string;
273
+ managementToken?: string;
274
+ };
275
+ } | undefined;
265
276
  name?: string | undefined;
266
277
  allowedCapabilities?: readonly string[] | undefined;
267
278
  onDone?: ((result: {
@@ -1,7 +1,21 @@
1
+ /**
2
+ * CLI embedded WebUI server — the backend behind `wrongstack --webui`.
3
+ *
4
+ * `runWebUI(opts)` boots a WebSocket bridge (and, when the webui package
5
+ * is built, the static HTTP frontend) over the *same* agent/events/
6
+ * session instances the REPL and eternal-autonomy loop use, then routes
7
+ * browser messages through a `handleMessage` switch.
8
+ *
9
+ * Most self-contained concerns live under `webui-server/*`; this file now
10
+ * assembles CLI-owned instances, route contexts, WebSocket lifecycle, and the
11
+ * embedded shared router.
12
+ *
13
+ * Public surface: `runWebUI` plus WS message shapes.
14
+ */
1
15
  import type { WSClientMessage as EmbeddedWSClientMessage, WSServerMessage as EmbeddedWSServerMessage } from './webui-server/contracts.js';
16
+ import type { CliWebUIOptions } from './webui-server-options.js';
2
17
  export type WSClientMessage = EmbeddedWSClientMessage;
3
18
  export type WSServerMessage = EmbeddedWSServerMessage;
4
- import type { CliWebUIOptions } from './webui-server-options.js';
5
19
  export type { CliWebUIOptions } from './webui-server-options.js';
6
20
  export declare function runWebUI(opts: CliWebUIOptions): Promise<void>;
7
21
  //# sourceMappingURL=webui-server.d.ts.map
@@ -14,10 +14,11 @@
14
14
  * build, which is exactly what the glossary block was supposed to
15
15
  * avoid.
16
16
  *
17
- * Instead, we ask SAGE for only the `domain-term`-tagged subset using
18
- * the typed `SageServiceLike.searchSage({ query: 'domain-term', limit })`
19
- * op (which performs the tag/keyword filter at the SQL layer), then map
20
- * the resulting `Sage[]` into the canonical `MemoryEntry` shape that
17
+ * Instead, we ask SAGE for rows the `domain-term` query matches using the
18
+ * typed `SageServiceLike.searchSage({ query: 'domain-term', limit })` op
19
+ * (an FTS keyword match over text+tags+audience — NOT a tag filter), keep
20
+ * only rows that actually carry the `domain-term` tag, then map the
21
+ * resulting `Sage[]` into the canonical `MemoryEntry` shape that
21
22
  * `renderDomainGlossary` in `packages/core/src/core/system-prompt-glossary.ts`
22
23
  * is typed against.
23
24
  *
@@ -96,7 +96,7 @@ export interface PluginsWiringDeps {
96
96
  configDir: string;
97
97
  /**
98
98
  * Per-project root (`~/.wrongstack/projects/<slug>/`). Plugins that
99
- * need project-scoped state (todo-tracker, etc.) should put their
99
+ * need project-scoped state (context-pins, etc.) should put their
100
100
  * files here so they follow the same lifecycle as goals/SDD
101
101
  * boards/tasks.
102
102
  */
@@ -0,0 +1,24 @@
1
+ import type { Config, Logger, SecretVault } from '@wrongstack/core/types';
2
+ import type { WstackPaths } from '@wrongstack/core/utils';
3
+ export { applyProviderOAuthRefresh } from '@wrongstack/providers';
4
+ /**
5
+ * Install the process-wide provider persisters: rotated OAuth tokens and a
6
+ * subscription provider's live model list, both written back to the active
7
+ * profile config.
8
+ *
9
+ * Installed at TWO points on purpose. The interactive path installs them after
10
+ * the launch menu, but `boot()` dispatches subcommands before that — and one
11
+ * of those subcommands is `wstack acp`, the long-lived server an editor spawns
12
+ * (Zed, JetBrains, VS Code). Without an installed persister its refreshes
13
+ * rotated the token in memory only: Codex and Claude invalidate the previous
14
+ * refresh token on use, so the config kept a dead one and the next launch
15
+ * demanded a fresh sign-in. Re-installing later is harmless — the second call
16
+ * replaces the first with an equivalent writer.
17
+ */
18
+ export declare function installProviderPersisters(args: {
19
+ config: Pick<Config, 'activeProfile'>;
20
+ paths: Pick<WstackPaths, 'profileConfig'>;
21
+ vault: SecretVault;
22
+ logger?: Pick<Logger, 'warn'> | undefined;
23
+ }): void;
24
+ //# sourceMappingURL=provider-persisters.d.ts.map
@@ -41,7 +41,15 @@ interface ResolvedProviderCfg {
41
41
  */
42
42
  factoryType: string;
43
43
  }
44
- export declare function resolveProviderCfg(config: Pick<Config, 'providers' | 'apiKey' | 'baseUrl'>, providerId: string, opts?: {
44
+ type ProviderConnectionConfig = Pick<Config, 'providers' | 'apiKey' | 'baseUrl'> & {
45
+ provider?: string;
46
+ };
47
+ /** Resolve account-owned connection values before any proxy rewriting. */
48
+ export declare function resolveRawProviderConnection(config: ProviderConnectionConfig, providerId: string): {
49
+ apiKey: string | undefined;
50
+ baseUrl: string | undefined;
51
+ };
52
+ export declare function resolveProviderCfg(config: ProviderConnectionConfig, providerId: string, opts?: {
45
53
  /**
46
54
  * Log the rewrite decision for this provider build. Structural
47
55
  * (info only) so hosts can pass core's Logger, a child logger, or a
@@ -2,7 +2,7 @@
2
2
  import type { Agent, Context } from '@wrongstack/core/agent';
3
3
  import type { EventBus } from '@wrongstack/core/kernel';
4
4
  import type { ToolRegistry } from '@wrongstack/core/registry';
5
- import type { Config, ConfigStore, MemoryPort } from '@wrongstack/core/types';
5
+ import type { Config, ConfigStore, MemoryPort, SkillLoader } from '@wrongstack/core/types';
6
6
  import type { PluginPickerItem, ToolPickerItem } from '../execute-deps.js';
7
7
  import { setupSage } from './sage.js';
8
8
  interface RuntimeDispatchStateInput {
@@ -12,6 +12,8 @@ interface RuntimeDispatchStateInput {
12
12
  profileConfigPath: string;
13
13
  pipelines: Parameters<typeof setupSage>[0]['pipelines'];
14
14
  memoryStore: MemoryPort;
15
+ /** Roster the skill suggester ranks. Undefined when skills are disabled. */
16
+ skillLoader: SkillLoader | undefined;
15
17
  logger: Parameters<typeof setupSage>[0]['logger'];
16
18
  events: EventBus;
17
19
  agent: Agent;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wrongstack/cli",
3
- "version": "1.0.19",
3
+ "version": "1.0.24",
4
4
  "license": "MIT",
5
5
  "description": "WrongStack CLI — terminal AI coding agent with provider catalog from models.dev. Provides `wrongstack` and `wstack` binaries.",
6
6
  "keywords": [
@@ -41,36 +41,36 @@
41
41
  "data"
42
42
  ],
43
43
  "dependencies": {
44
- "@wrongstack/acp": "1.0.19",
45
- "@wrongstack/bench": "1.0.19",
46
- "@wrongstack/core": "1.0.19",
47
- "@wrongstack/kanban": "1.0.19",
48
- "@wrongstack/mcp": "1.0.19",
49
- "@wrongstack/persistence": "1.0.19",
50
- "@wrongstack/plug-lsp": "1.0.19",
51
- "@wrongstack/plugins": "1.0.19",
52
- "@wrongstack/primitives": "1.0.19",
53
- "@wrongstack/providers": "1.0.19",
54
- "@wrongstack/requirement-intake": "1.0.19",
55
- "@wrongstack/runtime": "1.0.19",
56
- "@wrongstack/sage": "1.0.19",
57
- "@wrongstack/sdd": "1.0.19",
58
- "@wrongstack/security-scanner": "1.0.19",
59
- "@wrongstack/simpleui": "1.0.19",
60
- "@wrongstack/techstack": "1.0.19",
61
- "@wrongstack/telegram": "1.0.19",
62
- "@wrongstack/tools": "1.0.19",
63
- "@wrongstack/tui": "1.0.19",
64
- "@wrongstack/vector-memory": "1.0.19",
65
- "@wrongstack/webui": "1.0.19",
66
- "@wrongstack/webui-hq": "1.0.19",
67
- "@wrongstack/webui-protocol": "1.0.19",
68
- "@wrongstack/webui-server": "1.0.19",
69
- "@wrongstack/wrongtrace": "1.0.19",
44
+ "@wrongstack/acp": "1.0.24",
45
+ "@wrongstack/bench": "1.0.24",
46
+ "@wrongstack/core": "1.0.24",
47
+ "@wrongstack/kanban": "1.0.24",
48
+ "@wrongstack/mcp": "1.0.24",
49
+ "@wrongstack/persistence": "1.0.24",
50
+ "@wrongstack/plug-lsp": "1.0.24",
51
+ "@wrongstack/plugins": "1.0.24",
52
+ "@wrongstack/primitives": "1.0.24",
53
+ "@wrongstack/providers": "1.0.24",
54
+ "@wrongstack/requirement-intake": "1.0.24",
55
+ "@wrongstack/runtime": "1.0.24",
56
+ "@wrongstack/sage": "1.0.24",
57
+ "@wrongstack/sdd": "1.0.24",
58
+ "@wrongstack/security-scanner": "1.0.24",
59
+ "@wrongstack/simpleui": "1.0.24",
60
+ "@wrongstack/techstack": "1.0.24",
61
+ "@wrongstack/telegram": "1.0.24",
62
+ "@wrongstack/tools": "1.0.24",
63
+ "@wrongstack/tui": "1.0.24",
64
+ "@wrongstack/vector-memory": "1.0.24",
65
+ "@wrongstack/webui": "1.0.24",
66
+ "@wrongstack/webui-hq": "1.0.24",
67
+ "@wrongstack/webui-protocol": "1.0.24",
68
+ "@wrongstack/webui-server": "1.0.24",
69
+ "@wrongstack/wrongtrace": "1.0.24",
70
70
  "ws": "^8.21.3"
71
71
  },
72
72
  "optionalDependencies": {
73
- "@wrongstack/desktop": "1.0.19"
73
+ "@wrongstack/desktop": "1.0.24"
74
74
  },
75
75
  "devDependencies": {
76
76
  "@types/node": "^26.5.1",
@@ -1,54 +0,0 @@
1
-
2
- // src/subcommands/index.ts
3
- var loaders = {
4
- acp: async () => (await import("./acp-INCNOH42.js")).acpCmd,
5
- init: async () => (await import("./init-DRMMFG2G.js")).initCmd,
6
- auth: async () => (await import("./auth-YXK3EDUL.js")).authCmd,
7
- update: async () => (await import("./update-5DPB4YD4.js")).updateCmd,
8
- sessions: async () => (await import("./sessions-config-UL45XKX7.js")).sessionsCmd,
9
- config: async () => (await import("./sessions-config-UL45XKX7.js")).configCmd,
10
- "config-export": async () => (await import("./config-transfer-2YF3CRTN.js")).configExportCmd,
11
- "config-import": async () => (await import("./config-transfer-2YF3CRTN.js")).configImportCmd,
12
- rewind: async () => (await import("./rewind-JA3ZLCNM.js")).rewindCmd,
13
- replay: async () => (await import("./replay-JJ2NOWD6.js")).replayCmd,
14
- audit: async () => (await import("./audit-46YK5DSC.js")).auditCmd,
15
- tools: async () => (await import("./tools-skills-GH24UCBY.js")).toolsCmd,
16
- skills: async () => (await import("./tools-skills-GH24UCBY.js")).skillsCmd,
17
- providers: async () => (await import("./providers-models-LFNZ5WI7.js")).providersCmd,
18
- models: async () => (await import("./providers-models-LFNZ5WI7.js")).modelsCmd,
19
- mcp: async () => (await import("./mcp-DC5WSBOO.js")).mcpCmd,
20
- plugin: async () => (await import("./plugin-usage-M6KET4OZ.js")).pluginCmd,
21
- plugins: async () => (await import("./plugin-usage-M6KET4OZ.js")).pluginCmd,
22
- diag: async () => (await import("./diag-doctor-ANPRUYFM.js")).diagCmd,
23
- doctor: async () => (await import("./diag-doctor-ANPRUYFM.js")).doctorCmd,
24
- "proxy-status": async () => (await import("./diag-doctor-ANPRUYFM.js")).proxyCmd,
25
- export: async () => (await import("./export-VVRIOWFV.js")).exportCmd,
26
- usage: async () => (await import("./plugin-usage-M6KET4OZ.js")).usageCmd,
27
- version: async () => (await import("./version-help-WXI42PZ3.js")).versionCmd,
28
- help: async () => (await import("./version-help-WXI42PZ3.js")).helpCmd,
29
- projects: async () => (await import("./projects-LMNAGGEU.js")).projectsCmd,
30
- modeldiag: async () => (await import("./modeldiag-CJSFHZ3J.js")).modeldiagCmd,
31
- quick: async () => (await import("./quick-CNB4Z3HS.js")).quickCmd,
32
- bench: async () => (await import("./bench-YBU6BVQP.js")).benchCmd,
33
- chronicle: async () => (await import("./chronicle-UTFETHP6.js")).chronicleCmd,
34
- hq: async () => (await import("./hq-XQWQTRDA.js")).hqCmd,
35
- mailbox: async () => (await import("./mailbox-serve-3GFOK2I7.js")).mailboxServeCmd,
36
- permissions: async () => (await import("./permissions-CFDLXETM.js")).permissionsCmd,
37
- project: async () => (await import("./project-AOQI5XTK.js")).projectCmd,
38
- governance: async () => (await import("./governance-RYSHV675.js")).governanceCmd
39
- };
40
- var subcommands = Object.fromEntries(
41
- Object.entries(loaders).map(
42
- ([name, load]) => [
43
- name,
44
- async (args, deps) => (await load())(args, deps)
45
- ]
46
- )
47
- );
48
- var subcommandNames = Object.keys(loaders);
49
-
50
- export {
51
- subcommands,
52
- subcommandNames
53
- };
54
- //# sourceMappingURL=chunk-2CZEORLV.js.map