@wrongstack/cli 1.0.1 → 1.0.4

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 (109) hide show
  1. package/data/providers.json +21 -21
  2. package/dist/{acp-3LARESEO.js → acp-AB54FWM2.js} +122 -39
  3. package/dist/acp-agent-list.d.ts +14 -0
  4. package/dist/acp-hq-telemetry.d.ts +9 -2
  5. package/dist/acp-mcp-servers.d.ts +49 -0
  6. package/dist/acp-server-agent.d.ts +18 -6
  7. package/dist/{auth-ZUMCDNE5.js → auth-WDMSNZ3S.js} +79 -55
  8. package/dist/auth-menu/index.d.ts +1 -0
  9. package/dist/auth-menu/oauth-menu.d.ts +3 -1
  10. package/dist/auth-menu/panel-service.d.ts +2 -0
  11. package/dist/auth-menu/provider-auth-login.d.ts +12 -0
  12. package/dist/auth-menu/types.d.ts +3 -0
  13. package/dist/auto-discover-providers-DXR25GTG.js +7 -0
  14. package/dist/boot/dispatch-webui.d.ts +1 -0
  15. package/dist/boot/short-circuit-hq.d.ts +2 -0
  16. package/dist/boot/system-prompt-builder.d.ts +7 -0
  17. package/dist/boot/system-prompt.d.ts +2 -1
  18. package/dist/boot/tool-registry.d.ts +18 -1
  19. package/dist/chimera-reviewer-policy.d.ts +1 -1
  20. package/dist/{chunk-C2E24IXZ.js → chunk-3I5ZJXM5.js} +147 -241
  21. package/dist/{chunk-JHPXJRRI.js → chunk-4XCBEUBX.js} +13 -3
  22. package/dist/{chunk-FPIWTJ2G.js → chunk-6WRKAACA.js} +4 -4
  23. package/dist/chunk-AUQDGU5D.js +32 -0
  24. package/dist/{chunk-D2VCUN7M.js → chunk-BIWE22O5.js} +17 -17
  25. package/dist/{chunk-VOTTENR5.js → chunk-CDY4D5QK.js} +2 -2
  26. package/dist/chunk-D5GB5MHA.js +87 -0
  27. package/dist/chunk-DAKVBMD4.js +36 -0
  28. package/dist/{chunk-E6RFXHWD.js → chunk-EK2P53GL.js} +3 -2
  29. package/dist/chunk-I7V2OYVH.js +242 -0
  30. package/dist/{chunk-MXEJEYT7.js → chunk-JX6KL7OF.js} +15 -5
  31. package/dist/{chunk-ZSZ3EYWH.js → chunk-KEPABQYT.js} +109 -6
  32. package/dist/{chunk-IMWXXF4J.js → chunk-KNMIBKLV.js} +79 -1
  33. package/dist/{chunk-MNQQ4ZNF.js → chunk-ONOT5OJ2.js} +290 -687
  34. package/dist/chunk-Q7E3BPDU.js +62 -0
  35. package/dist/chunk-SIGUWXAA.js +43 -0
  36. package/dist/{chunk-TEBMCYZN.js → chunk-SIS37L3W.js} +58 -2
  37. package/dist/{chunk-KHWDTNBZ.js → chunk-U6PGWDMZ.js} +5 -5
  38. package/dist/{chunk-5IA5337I.js → chunk-XJ7K67PP.js} +8 -2
  39. package/dist/{cli-context-7X3M6U73.js → cli-context-WFC3BNGM.js} +131 -25
  40. package/dist/{cli-main-53KG6HAV.js → cli-main-GU3YZLMO.js} +3986 -2827
  41. package/dist/{diag-doctor-7LYUYU35.js → diag-doctor-PCER6KHH.js} +2 -2
  42. package/dist/execute-deps.d.ts +1 -0
  43. package/dist/{execution-MIBWBYB6.js → execution-RAZDDQFC.js} +115 -16
  44. package/dist/execution-specialist-trigger.d.ts +28 -0
  45. package/dist/fleet/acp-live-progress.d.ts +19 -0
  46. package/dist/fleet/host-acp-runner-cache.d.ts +3 -1
  47. package/dist/fleet/host-acp.d.ts +14 -2
  48. package/dist/fleet/host.d.ts +1 -0
  49. package/dist/{hq-IG3YRGCO.js → hq-5XHEIIH6.js} +127 -8
  50. package/dist/hq-command-controller.d.ts +31 -2
  51. package/dist/hq-server/client-address.d.ts +2 -0
  52. package/dist/hq-server/ip-allowlist.d.ts +16 -0
  53. package/dist/hq-server/preflight.d.ts +1 -0
  54. package/dist/hq-server/routes/auth/password-routes.d.ts +1 -1
  55. package/dist/hq-server/routes.d.ts +5 -4
  56. package/dist/hq-server/secret-input.d.ts +7 -0
  57. package/dist/hq-server/types.d.ts +3 -2
  58. package/dist/hq-server/upgrade-handler.d.ts +2 -0
  59. package/dist/hq-server/utils.d.ts +6 -0
  60. package/dist/{hq-server-OILU3NPI.js → hq-server-CNUTBWTK.js} +4 -3
  61. package/dist/hq-server.d.ts +4 -0
  62. package/dist/hq-service-L5INQFM4.js +507 -0
  63. package/dist/hq-service.d.ts +22 -0
  64. package/dist/index.js +4 -4
  65. package/dist/ip-allowlist-NHXO6AKJ.js +9 -0
  66. package/dist/live-settings-input.d.ts +4 -0
  67. package/dist/{mailbox-serve-VUCWZ2SJ.js → mailbox-serve-X3CR6VFW.js} +4 -3
  68. package/dist/{modeldiag-FMJT37SN.js → modeldiag-46CMWUNM.js} +31 -24
  69. package/dist/{per-subcommand-help-BWBHYVJO.js → per-subcommand-help-DHTYU524.js} +2 -2
  70. package/dist/{plugin-usage-HFBI3TFT.js → plugin-usage-M6KET4OZ.js} +2 -2
  71. package/dist/{plugins-PZ2VZL7V.js → plugins-WJLW6ULV.js} +3 -3
  72. package/dist/projects-LMNAGGEU.js +36 -0
  73. package/dist/{providers-models-YVMVYWRS.js → providers-models-6MOGAOVK.js} +2 -2
  74. package/dist/{proxy-wiring-MGRSKZZB.js → proxy-wiring-K2DORFFL.js} +3 -3
  75. package/dist/short-circuit-flags-YDMLAQ5R.js +10 -0
  76. package/dist/slash-commands/acp.d.ts +3 -0
  77. package/dist/slash-commands/codebase-map.d.ts +11 -0
  78. package/dist/slash-commands/command-context.d.ts +29 -0
  79. package/dist/slash-commands/context.d.ts +10 -0
  80. package/dist/slash-commands/ensemble.d.ts +1 -1
  81. package/dist/slash-commands/openai-quota.d.ts +31 -0
  82. package/dist/slash-commands/profile.d.ts +7 -0
  83. package/dist/subcommands/handlers/hq.d.ts +1 -0
  84. package/dist/subcommands/handlers/projects.d.ts +14 -0
  85. package/dist/{subcommands-WJLBHVKC.js → subcommands-7N4RIK6H.js} +2 -2
  86. package/dist/{version-help-MYKF724O.js → version-help-WXI42PZ3.js} +2 -2
  87. package/dist/{webui-server-5R35BHWZ.js → webui-server-OBV5JYJV.js} +27 -4
  88. package/dist/webui-server-options.d.ts +1 -0
  89. package/dist/wiring/atlas-prompt-contributor.d.ts +54 -0
  90. package/dist/wiring/cli-execute-builder.d.ts +1 -0
  91. package/dist/wiring/cli-slash-commands-setup.d.ts +7 -0
  92. package/dist/wiring/codebase-embeddings.d.ts +31 -0
  93. package/dist/wiring/command-host-state.d.ts +9 -0
  94. package/dist/wiring/concept-summarizer.d.ts +32 -0
  95. package/dist/wiring/external-plugins.d.ts +1 -0
  96. package/dist/wiring/lifecycle-plugins.d.ts +2 -1
  97. package/dist/wiring/pipeline.d.ts +2 -0
  98. package/dist/wiring/plugins.d.ts +2 -1
  99. package/dist/wiring/provider-runtime-setup.d.ts +1 -1
  100. package/dist/wiring/provider.d.ts +2 -1
  101. package/dist/wiring/session-command-handlers.d.ts +2 -1
  102. package/dist/wiring/slash-commands.d.ts +1 -0
  103. package/package.json +29 -29
  104. package/dist/auto-discover-providers-VQU3IZMR.js +0 -7
  105. package/dist/chunk-52C7PD2H.js +0 -61
  106. package/dist/chunk-Q5GTM25S.js +0 -17
  107. package/dist/chunk-TNK6237M.js +0 -262
  108. package/dist/projects-L6C6XLDY.js +0 -37
  109. package/dist/short-circuit-flags-UREFSYBL.js +0 -10
@@ -0,0 +1,62 @@
1
+
2
+ // src/hq-server/ip-allowlist.ts
3
+ import { BlockList, isIP } from "node:net";
4
+ function normalizeAddress(value) {
5
+ return value.trim().replace(/^\[(.*)\]$/, "$1").replace(/^::ffff:/i, "");
6
+ }
7
+ function addRule(blockList, rawRule) {
8
+ const rule = rawRule.trim();
9
+ if (!rule) throw new TypeError("HQ IP allowlist contains an empty entry.");
10
+ const slash = rule.lastIndexOf("/");
11
+ if (slash === -1) {
12
+ const address2 = normalizeAddress(rule);
13
+ const family2 = isIP(address2);
14
+ if (family2 === 0) {
15
+ throw new TypeError(`Invalid HQ allowlist address: ${rule}`);
16
+ }
17
+ blockList.addAddress(address2, family2 === 4 ? "ipv4" : "ipv6");
18
+ return address2;
19
+ }
20
+ const address = normalizeAddress(rule.slice(0, slash));
21
+ const prefixText = rule.slice(slash + 1);
22
+ const family = isIP(address);
23
+ if (family === 0 || !/^\d+$/.test(prefixText)) {
24
+ throw new TypeError(`Invalid HQ allowlist network: ${rule}`);
25
+ }
26
+ const prefix = Number(prefixText);
27
+ const maximum = family === 4 ? 32 : 128;
28
+ if (!Number.isSafeInteger(prefix) || prefix < 0 || prefix > maximum) {
29
+ throw new TypeError(`Invalid HQ allowlist prefix: ${rule}`);
30
+ }
31
+ blockList.addSubnet(address, prefix, family === 4 ? "ipv4" : "ipv6");
32
+ return `${address}/${prefix}`;
33
+ }
34
+ function createHqIpAllowlist(rules) {
35
+ if (rules === void 0 || rules.length === 0) return void 0;
36
+ const blockList = new BlockList();
37
+ blockList.addSubnet("127.0.0.0", 8, "ipv4");
38
+ blockList.addAddress("::1", "ipv6");
39
+ const entries = [...new Set(rules.map((rule) => addRule(blockList, rule)))];
40
+ return {
41
+ entries,
42
+ allows(address) {
43
+ if (!address) return false;
44
+ const normalized = normalizeAddress(address);
45
+ const family = isIP(normalized);
46
+ if (family === 0) return false;
47
+ return blockList.check(normalized, family === 4 ? "ipv4" : "ipv6");
48
+ }
49
+ };
50
+ }
51
+ function parseHqIpAllowlist(value) {
52
+ if (value === void 0 || value.trim() === "") return void 0;
53
+ const rules = value.split(",").map((entry) => entry.trim());
54
+ createHqIpAllowlist(rules);
55
+ return rules;
56
+ }
57
+
58
+ export {
59
+ createHqIpAllowlist,
60
+ parseHqIpAllowlist
61
+ };
62
+ //# sourceMappingURL=chunk-Q7E3BPDU.js.map
@@ -0,0 +1,43 @@
1
+
2
+ // src/auth-menu/openai-codex-oauth.ts
3
+ import { color } from "@wrongstack/core/utils";
4
+ import {
5
+ buildCodexAuthorizeUrl,
6
+ CODEX_BASE_URL,
7
+ CODEX_FALLBACK_REDIRECT_PORT,
8
+ CODEX_PROVIDER_ID,
9
+ CODEX_REDIRECT_HOST,
10
+ CODEX_REDIRECT_PATH,
11
+ CODEX_REDIRECT_PORT,
12
+ CODEX_SCOPE,
13
+ codexRedirectUri,
14
+ createState,
15
+ exchangeCodexAuthorizationCode,
16
+ extractAccountId,
17
+ generatePkce,
18
+ parseAuthorizationInput,
19
+ refreshCodexTokens,
20
+ resolveCodexModels
21
+ } from "@wrongstack/providers/oauth";
22
+ import {
23
+ CODEX_BASE_URL as CODEX_BASE_URL2,
24
+ CODEX_CATALOG_FAMILIES,
25
+ CODEX_PROVIDER_ID as CODEX_PROVIDER_ID2,
26
+ extractAccountId as extractAccountId2,
27
+ FALLBACK_CODEX_MODELS,
28
+ fallbackCodexModelIds,
29
+ fallbackCodexProviderModels,
30
+ fetchCodexModels,
31
+ filterCurrentCodexModelIds,
32
+ generatePkce as generatePkce2,
33
+ isCodexCatalogModel,
34
+ parseAuthorizationInput as parseAuthorizationInput2,
35
+ resolveCodexModels as resolveCodexModels2
36
+ } from "@wrongstack/providers/oauth";
37
+
38
+ export {
39
+ fallbackCodexProviderModels,
40
+ filterCurrentCodexModelIds,
41
+ isCodexCatalogModel
42
+ };
43
+ //# sourceMappingURL=chunk-SIGUWXAA.js.map
@@ -13,6 +13,10 @@ import {
13
13
  resolvePluginTarget,
14
14
  verifyPluginTrust
15
15
  } from "@wrongstack/core/plugin";
16
+ import { createHash } from "node:crypto";
17
+ import { readdir, stat } from "node:fs/promises";
18
+ import { basename, dirname, relative, sep } from "node:path";
19
+ import { readFile } from "node:fs/promises";
16
20
  function resolveExternalPluginTrustMode(raw) {
17
21
  if (raw === false) return "off";
18
22
  if (raw === "required") return "required";
@@ -228,7 +232,7 @@ async function gateExternalPluginTrust(args) {
228
232
  if (!store) return { ok: true, pinned: false };
229
233
  let integrity;
230
234
  try {
231
- integrity = await hashFileContents(entryPath);
235
+ integrity = await hashPluginClosure(entryPath);
232
236
  } catch (err) {
233
237
  const message = err instanceof Error ? err.message : String(err);
234
238
  if (mode === "required") {
@@ -271,6 +275,58 @@ async function gateExternalPluginTrust(args) {
271
275
  log.error(`[plugins] REFUSING external plugin "${label}" \u2014 ${changedMessage}`);
272
276
  return { ok: false, pinned: false };
273
277
  }
278
+ var CLOSURE_HASH_LIMIT = 2e3;
279
+ var CLOSURE_FILE_LIMIT = 16 * 1024 * 1024;
280
+ async function hashPluginClosure(entryPath) {
281
+ const dir = dirname(entryPath);
282
+ let dirStat;
283
+ try {
284
+ dirStat = await stat(dir);
285
+ } catch {
286
+ return hashFileContents(entryPath);
287
+ }
288
+ if (!dirStat.isDirectory()) return hashFileContents(entryPath);
289
+ const entryBase = basename(entryPath);
290
+ const files = [];
291
+ async function walk(d) {
292
+ if (files.length > CLOSURE_HASH_LIMIT) return;
293
+ const entries = await readdir(d, { withFileTypes: true }).catch(() => []);
294
+ for (const e of entries) {
295
+ const full = d + sep + e.name;
296
+ if (e.isDirectory()) {
297
+ if (e.name === "node_modules" || e.name.startsWith(".")) continue;
298
+ await walk(full);
299
+ } else if (e.isFile()) {
300
+ files.push(full);
301
+ }
302
+ }
303
+ }
304
+ await walk(dir);
305
+ files.sort();
306
+ const manifest = [];
307
+ for (const full of files) {
308
+ const rel = relative(dir, full).split(sep).join("/");
309
+ let bytes;
310
+ try {
311
+ const st = await stat(full);
312
+ if (!st.isFile() || st.size > CLOSURE_FILE_LIMIT) continue;
313
+ bytes = await readFile(full);
314
+ } catch {
315
+ continue;
316
+ }
317
+ const sha = createHash("sha256").update(bytes).digest("hex");
318
+ manifest.push(`${rel}\0${bytes.length}\0${sha}`);
319
+ }
320
+ if (!manifest.some((line) => line.startsWith(`${entryBase}\0`))) {
321
+ const entryBytes = await readFile(entryPath);
322
+ const entrySha = createHash("sha256").update(entryBytes).digest("hex");
323
+ manifest.push(`${entryBase}\0${entryBytes.length}\0${entrySha}`);
324
+ }
325
+ manifest.sort();
326
+ const outer = createHash("sha256");
327
+ outer.update(manifest.join("\n"));
328
+ return outer.digest("hex");
329
+ }
274
330
 
275
331
  // src/plugin-management.ts
276
332
  import { execFile } from "node:child_process";
@@ -1035,4 +1091,4 @@ export {
1035
1091
  PLUGIN_AUDIT_ENTRIES,
1036
1092
  runPluginManagementCommand
1037
1093
  };
1038
- //# sourceMappingURL=chunk-TEBMCYZN.js.map
1094
+ //# sourceMappingURL=chunk-SIS37L3W.js.map
@@ -1,10 +1,10 @@
1
1
  import {
2
2
  helpCmd,
3
3
  versionCmd
4
- } from "./chunk-FPIWTJ2G.js";
4
+ } from "./chunk-6WRKAACA.js";
5
5
  import {
6
6
  parseArgs
7
- } from "./chunk-E6RFXHWD.js";
7
+ } from "./chunk-EK2P53GL.js";
8
8
 
9
9
  // src/boot/short-circuit-flags.ts
10
10
  async function handleHelpVersionShortCircuit(argv) {
@@ -22,11 +22,11 @@ async function handleHelpVersionShortCircuit(argv) {
22
22
  }
23
23
  if (earlyFlags["help"] === true) {
24
24
  if (positional.length > 0) {
25
- const { subcommandNames } = await import("./subcommands-WJLBHVKC.js");
25
+ const { subcommandNames } = await import("./subcommands-7N4RIK6H.js");
26
26
  if (subcommandNames.includes(positional[0])) {
27
27
  const first = positional[0];
28
28
  const deep = positional[1];
29
- const { renderDeepHelp, renderFocusedHelp } = await import("./per-subcommand-help-BWBHYVJO.js");
29
+ const { renderDeepHelp, renderFocusedHelp } = await import("./per-subcommand-help-DHTYU524.js");
30
30
  if (deep && renderDeepHelp(`${first}:${deep}`, stubRenderer)) {
31
31
  return 0;
32
32
  }
@@ -43,4 +43,4 @@ async function handleHelpVersionShortCircuit(argv) {
43
43
  export {
44
44
  handleHelpVersionShortCircuit
45
45
  };
46
- //# sourceMappingURL=chunk-KHWDTNBZ.js.map
46
+ //# sourceMappingURL=chunk-U6PGWDMZ.js.map
@@ -4,7 +4,7 @@ import {
4
4
  import {
5
5
  PLUGIN_AUDIT_ENTRIES,
6
6
  loadExternalPlugins
7
- } from "./chunk-TEBMCYZN.js";
7
+ } from "./chunk-SIS37L3W.js";
8
8
 
9
9
  // src/wiring/plugins.ts
10
10
  import { join } from "node:path";
@@ -80,6 +80,10 @@ var BUILTIN_PLUGIN_FACTORIES = [
80
80
  const { createAutoReviewPlugin } = await import("@wrongstack/core/plugin");
81
81
  return createAutoReviewPlugin();
82
82
  },
83
+ async () => {
84
+ const { createSpecialistTriggerPlugin } = await import("@wrongstack/core/plugin");
85
+ return createSpecialistTriggerPlugin();
86
+ },
83
87
  async () => {
84
88
  const { createSkillsPlugin } = await import("@wrongstack/core/plugin");
85
89
  return createSkillsPlugin();
@@ -98,6 +102,7 @@ async function setupPlugins(params) {
98
102
  events,
99
103
  toolRegistry,
100
104
  providerRegistry,
105
+ providerAuthRegistry,
101
106
  slashCommandRegistry,
102
107
  mcpRegistry,
103
108
  log,
@@ -207,6 +212,7 @@ async function setupPlugins(params) {
207
212
  pipelines,
208
213
  toolRegistry,
209
214
  providerRegistry,
215
+ providerAuthRegistry,
210
216
  slashCommandRegistry,
211
217
  mcpRegistry,
212
218
  config: pluginConfig,
@@ -261,4 +267,4 @@ export {
261
267
  BUILTIN_PLUGIN_FACTORIES,
262
268
  setupPlugins
263
269
  };
264
- //# sourceMappingURL=chunk-5IA5337I.js.map
270
+ //# sourceMappingURL=chunk-XJ7K67PP.js.map
@@ -9,38 +9,46 @@ import {
9
9
  import {
10
10
  theme as theme2
11
11
  } from "./chunk-QD544J2B.js";
12
- import {
13
- parseWebuiSessionChildOptions,
14
- writeWebuiSessionChildError
15
- } from "./chunk-GPPRNAKW.js";
16
12
  import {
17
13
  fmtTok,
18
14
  patchConfig
19
15
  } from "./chunk-EWKESL4L.js";
16
+ import {
17
+ parseWebuiSessionChildOptions,
18
+ writeWebuiSessionChildError
19
+ } from "./chunk-GPPRNAKW.js";
20
20
  import {
21
21
  subcommands
22
- } from "./chunk-D2VCUN7M.js";
22
+ } from "./chunk-BIWE22O5.js";
23
23
  import {
24
24
  renderDeepHelp,
25
25
  renderFocusedHelp
26
- } from "./chunk-MXEJEYT7.js";
26
+ } from "./chunk-JX6KL7OF.js";
27
27
  import {
28
28
  handleHelpVersionShortCircuit
29
- } from "./chunk-KHWDTNBZ.js";
29
+ } from "./chunk-U6PGWDMZ.js";
30
30
  import {
31
31
  DEFAULT_PORT
32
- } from "./chunk-C2E24IXZ.js";
32
+ } from "./chunk-3I5ZJXM5.js";
33
33
  import "./chunk-HXJYHAR4.js";
34
- import "./chunk-Q5GTM25S.js";
34
+ import {
35
+ resolveHqPasswordInput
36
+ } from "./chunk-AUQDGU5D.js";
37
+ import {
38
+ normalizeHqPublicOrigin
39
+ } from "./chunk-I7V2OYVH.js";
40
+ import {
41
+ parseHqIpAllowlist
42
+ } from "./chunk-Q7E3BPDU.js";
35
43
  import {
36
44
  discoverAndMergeProviders
37
- } from "./chunk-52C7PD2H.js";
45
+ } from "./chunk-D5GB5MHA.js";
38
46
  import {
39
47
  applyNodeEnvDefault,
40
48
  applySessionShellDefault,
41
49
  runPreflight
42
50
  } from "./chunk-O4A3HHKD.js";
43
- import "./chunk-FPIWTJ2G.js";
51
+ import "./chunk-6WRKAACA.js";
44
52
  import {
45
53
  CLI_VERSION
46
54
  } from "./chunk-XJXDOF63.js";
@@ -55,7 +63,7 @@ import {
55
63
  runPicker,
56
64
  saveToGlobalConfig,
57
65
  theme
58
- } from "./chunk-MNQQ4ZNF.js";
66
+ } from "./chunk-ONOT5OJ2.js";
59
67
  import "./chunk-2VMJ3E5Z.js";
60
68
  import "./chunk-B4JLSXZB.js";
61
69
  import {
@@ -67,8 +75,8 @@ import {
67
75
  } from "./chunk-YMXXOOFN.js";
68
76
  import {
69
77
  parseArgs
70
- } from "./chunk-E6RFXHWD.js";
71
- import "./chunk-TNK6237M.js";
78
+ } from "./chunk-EK2P53GL.js";
79
+ import "./chunk-DAKVBMD4.js";
72
80
  import {
73
81
  mutateConfigProviders,
74
82
  normalizeKeys,
@@ -84,7 +92,7 @@ import "./chunk-YLQEGYV4.js";
84
92
  // src/cli-context.ts
85
93
  import { TOKENS as TOKENS3 } from "@wrongstack/core/kernel";
86
94
  import { writeErr as writeErr2 } from "@wrongstack/core/utils";
87
- import { setOAuthTokenPersister } from "@wrongstack/providers";
95
+ import { setOAuthTokenPersister, setProviderModelPersister } from "@wrongstack/providers";
88
96
 
89
97
  // src/boot/container-wiring.ts
90
98
  import { DefaultPathResolver } from "@wrongstack/core/infrastructure";
@@ -760,9 +768,13 @@ import {
760
768
  resolveHqDataDir
761
769
  } from "@wrongstack/core/hq";
762
770
  import { color as color3, isPidAlive } from "@wrongstack/core/utils";
771
+ function isReusedContainerPid(markerPid, containerMode, currentPid = process.pid) {
772
+ return containerMode === "1" && markerPid === currentPid;
773
+ }
763
774
  async function isHqAlreadyRunning(dataDir) {
764
775
  const marker = readHqRuntimeFileSync(dataDir);
765
776
  if (!marker) return null;
777
+ if (isReusedContainerPid(marker.pid, process.env.WRONGSTACK_HQ_CONTAINER)) return null;
766
778
  if (marker.pid && isPidAlive(marker.pid)) return marker;
767
779
  return null;
768
780
  }
@@ -784,12 +796,31 @@ async function isPortInUse(host, port) {
784
796
  }
785
797
  async function handleHqShortCircuit(flags) {
786
798
  if (flags["hq"] !== true) return null;
787
- const { startHqServer } = await import("./hq-server-OILU3NPI.js");
799
+ const { startHqServer } = await import("./hq-server-CNUTBWTK.js");
788
800
  const tunnelRequested = flags["tunnel"] === true;
789
- const host = typeof flags["host"] === "string" ? flags["host"] : tunnelRequested ? "127.0.0.1" : HQ_CLI_DEFAULT_HOST2;
790
- if (tunnelRequested && !isLoopbackHost(host)) {
801
+ const rawPublicUrl = typeof flags["hq-public-url"] === "string" ? flags["hq-public-url"] : process.env.WRONGSTACK_HQ_PUBLIC_URL;
802
+ let publicOrigin;
803
+ if (rawPublicUrl !== void 0 && rawPublicUrl.trim() !== "") {
804
+ try {
805
+ publicOrigin = normalizeHqPublicOrigin(rawPublicUrl);
806
+ } catch (cause) {
807
+ process.stderr.write(
808
+ `${color3.red("\u2717")} ${cause instanceof Error ? cause.message : String(cause)}
809
+ `
810
+ );
811
+ return 1;
812
+ }
813
+ }
814
+ if (tunnelRequested && publicOrigin !== void 0) {
815
+ process.stderr.write(`${color3.red("\u2717")} Use either --tunnel or --hq-public-url, not both.
816
+ `);
817
+ return 1;
818
+ }
819
+ const externallyPublished = tunnelRequested || publicOrigin !== void 0;
820
+ const host = typeof flags["host"] === "string" ? flags["host"] : externallyPublished ? "127.0.0.1" : HQ_CLI_DEFAULT_HOST2;
821
+ if (externallyPublished && !isLoopbackHost(host)) {
791
822
  process.stderr.write(
792
- `${color3.red("\u2717")} --tunnel requires a loopback origin. Remove --host or use --host 127.0.0.1.
823
+ `${color3.red("\u2717")} Public HQ publishing requires a loopback bind. Remove --host or use --host 127.0.0.1.
793
824
  `
794
825
  );
795
826
  return 1;
@@ -806,12 +837,51 @@ async function handleHqShortCircuit(flags) {
806
837
  }
807
838
  } else port = DEFAULT_PORT;
808
839
  const dataDir = typeof flags["data-dir"] === "string" ? flags["data-dir"] : void 0;
809
- const password = typeof flags["password"] === "string" ? flags["password"] : process.env.WRONGSTACK_HQ_PASSWORD;
840
+ let password;
841
+ try {
842
+ password = await resolveHqPasswordInput({
843
+ ...typeof flags["password"] === "string" ? { explicitPassword: flags["password"] } : {}
844
+ });
845
+ } catch (cause) {
846
+ process.stderr.write(
847
+ `${color3.red("\u2717")} ${cause instanceof Error ? cause.message : String(cause)}
848
+ `
849
+ );
850
+ return 1;
851
+ }
852
+ const bootstrapPasswordOnly = /^(?:1|true)$/i.test(
853
+ process.env.WRONGSTACK_HQ_BOOTSTRAP_PASSWORD_ONLY?.trim() ?? ""
854
+ );
855
+ let ipAllowlist;
856
+ try {
857
+ ipAllowlist = parseHqIpAllowlist(
858
+ typeof flags["hq-allowlist"] === "string" ? flags["hq-allowlist"] : process.env.WRONGSTACK_HQ_ALLOWLIST
859
+ );
860
+ } catch (cause) {
861
+ process.stderr.write(
862
+ `${color3.red("\u2717")} ${cause instanceof Error ? cause.message : String(cause)}
863
+ `
864
+ );
865
+ return 1;
866
+ }
810
867
  if (password !== void 0 && password.length < 8) {
811
868
  process.stderr.write(`${color3.red("\u2717")} HQ password must be at least 8 characters.
812
869
  `);
813
870
  return 1;
814
871
  }
872
+ const rawTrustedProxyHops = typeof flags["hq-trusted-proxy-hops"] === "string" ? flags["hq-trusted-proxy-hops"] : process.env.WRONGSTACK_HQ_TRUSTED_PROXY_HOPS;
873
+ let trustedProxyHops;
874
+ if (rawTrustedProxyHops !== void 0 && rawTrustedProxyHops.trim() !== "") {
875
+ const parsed = Number.parseInt(rawTrustedProxyHops, 10);
876
+ if (!Number.isFinite(parsed) || parsed < 0 || String(parsed) !== rawTrustedProxyHops.trim()) {
877
+ process.stderr.write(
878
+ `${color3.red("\u2717")} --hq-trusted-proxy-hops must be a non-negative integer.
879
+ `
880
+ );
881
+ return 1;
882
+ }
883
+ trustedProxyHops = parsed;
884
+ }
815
885
  const userProvidedPort = typeof flags["port"] === "string" && flags["port"].trim() !== "" || port !== DEFAULT_PORT;
816
886
  const resolvedDataDir = dataDir ?? resolveHqDataDir();
817
887
  const existing = await isHqAlreadyRunning(resolvedDataDir);
@@ -849,11 +919,14 @@ async function handleHqShortCircuit(flags) {
849
919
  strictPort: flags["strict-port"] === true,
850
920
  exactPort: userProvidedPort,
851
921
  allowInsecureOpen: flags["insecure-open"] === true,
852
- secureCookies: tunnelRequested,
853
- requireBrowserAuth: tunnelRequested,
922
+ secureCookies: externallyPublished,
923
+ requireBrowserAuth: externallyPublished,
854
924
  ...dataDir !== void 0 ? { dataDir } : {},
855
925
  ...password !== void 0 ? { password } : {},
856
- ...tokenTtlMs !== void 0 ? { tokenTtlMs } : {}
926
+ ...bootstrapPasswordOnly ? { bootstrapPasswordOnly: true } : {},
927
+ ...tokenTtlMs !== void 0 ? { tokenTtlMs } : {},
928
+ ...trustedProxyHops !== void 0 ? { trustedProxyHops } : {},
929
+ ...ipAllowlist !== void 0 ? { ipAllowlist } : {}
857
930
  });
858
931
  } catch (err) {
859
932
  const msg = err instanceof Error ? err.message : String(err);
@@ -868,8 +941,24 @@ async function handleHqShortCircuit(flags) {
868
941
  }
869
942
  return 1;
870
943
  }
944
+ if (publicOrigin !== void 0) {
945
+ if (handle.firstRunSetup?.passwordMode !== true) {
946
+ await handle.close();
947
+ process.stderr.write(
948
+ `${color3.red("\u2717")} Persistent public HQ requires password mode. Set WRONGSTACK_HQ_PASSWORD and retry.
949
+ `
950
+ );
951
+ return 1;
952
+ }
953
+ handle.trustPublicOrigin(publicOrigin);
954
+ process.stdout.write(`
955
+ ${color3.green("Persistent HQ origin ready:")} ${publicOrigin}/
956
+ `);
957
+ process.stdout.write(`${color3.green("Mobile:")} ${publicOrigin}/mobile
958
+ `);
959
+ }
871
960
  let tunnel;
872
- let browserUrl = handle.firstRunSetup?.browserUrl ?? `http://${handle.host}:${handle.port}`;
961
+ let browserUrl = publicOrigin ?? handle.firstRunSetup?.browserUrl ?? `http://${handle.host}:${handle.port}`;
873
962
  if (tunnelRequested) {
874
963
  if (handle.firstRunSetup !== void 0 && !handle.firstRunSetup.browserTokenMode && !handle.firstRunSetup.passwordMode) {
875
964
  await handle.close();
@@ -894,6 +983,12 @@ async function handleHqShortCircuit(flags) {
894
983
  );
895
984
  process.stdout.write(`
896
985
  ${color3.green("Cloudflare Quick Tunnel ready:")} ${browserUrl}
986
+ `);
987
+ const tunnelMobileUrl = new URL(tunnel.url);
988
+ tunnelMobileUrl.pathname = "/mobile";
989
+ tunnelMobileUrl.search = "";
990
+ tunnelMobileUrl.hash = "";
991
+ process.stdout.write(`${color3.green("Mobile:")} ${tunnelMobileUrl.toString()}
897
992
  `);
898
993
  process.stdout.write(
899
994
  `${color3.dim("Temporary development URL; DNS may need a few seconds, it changes on restart and ends when HQ stops.")}
@@ -3095,6 +3190,17 @@ async function initializeCli(argv) {
3095
3190
  }).catch(() => {
3096
3191
  });
3097
3192
  });
3193
+ setProviderModelPersister((providerId, models) => {
3194
+ if (models.length === 0) return;
3195
+ void mutateConfigProviders(profileConfigPath, vault, (all) => {
3196
+ const p = all[providerId];
3197
+ if (!p) return;
3198
+ const live = models.map((m) => m.id);
3199
+ if (p.models?.length === live.length && p.models.every((id, i) => id === live[i])) return;
3200
+ p.models = live;
3201
+ }).catch(() => {
3202
+ });
3203
+ });
3098
3204
  const { events, container } = wireContainer({
3099
3205
  config,
3100
3206
  wpaths,
@@ -3117,4 +3223,4 @@ async function initializeCli(argv) {
3117
3223
  export {
3118
3224
  initializeCli
3119
3225
  };
3120
- //# sourceMappingURL=cli-context-7X3M6U73.js.map
3226
+ //# sourceMappingURL=cli-context-WFC3BNGM.js.map