@wrongstack/cli 1.0.3 → 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 (74) hide show
  1. package/dist/{acp-JK4ZQO3R.js → acp-AB54FWM2.js} +120 -38
  2. package/dist/acp-agent-list.d.ts +14 -0
  3. package/dist/acp-hq-telemetry.d.ts +9 -2
  4. package/dist/acp-mcp-servers.d.ts +49 -0
  5. package/dist/acp-server-agent.d.ts +18 -6
  6. package/dist/{auth-XD3GN5RJ.js → auth-WDMSNZ3S.js} +2 -2
  7. package/dist/boot/short-circuit-hq.d.ts +2 -0
  8. package/dist/boot/tool-registry.d.ts +18 -1
  9. package/dist/{chunk-C2E24IXZ.js → chunk-3I5ZJXM5.js} +147 -241
  10. package/dist/{chunk-JHPXJRRI.js → chunk-4XCBEUBX.js} +13 -3
  11. package/dist/{chunk-FPIWTJ2G.js → chunk-6WRKAACA.js} +4 -4
  12. package/dist/chunk-AUQDGU5D.js +32 -0
  13. package/dist/{chunk-IUEKNHPT.js → chunk-BIWE22O5.js} +10 -10
  14. package/dist/{chunk-VOTTENR5.js → chunk-CDY4D5QK.js} +2 -2
  15. package/dist/{chunk-E6RFXHWD.js → chunk-EK2P53GL.js} +3 -2
  16. package/dist/chunk-I7V2OYVH.js +242 -0
  17. package/dist/{chunk-MXEJEYT7.js → chunk-JX6KL7OF.js} +15 -5
  18. package/dist/{chunk-GMY45LO6.js → chunk-KEPABQYT.js} +101 -2
  19. package/dist/{chunk-IMWXXF4J.js → chunk-KNMIBKLV.js} +79 -1
  20. package/dist/chunk-Q7E3BPDU.js +62 -0
  21. package/dist/{chunk-4NHD5OXJ.js → chunk-U6PGWDMZ.js} +5 -5
  22. package/dist/{chunk-U6KCWRMC.js → chunk-XJ7K67PP.js} +5 -1
  23. package/dist/{cli-context-Q6QP534K.js → cli-context-WFC3BNGM.js} +116 -21
  24. package/dist/{cli-main-JQXCDZEA.js → cli-main-GU3YZLMO.js} +1221 -694
  25. package/dist/{diag-doctor-7LYUYU35.js → diag-doctor-PCER6KHH.js} +2 -2
  26. package/dist/{execution-KH7WJNAX.js → execution-RAZDDQFC.js} +107 -15
  27. package/dist/execution-specialist-trigger.d.ts +28 -0
  28. package/dist/fleet/acp-live-progress.d.ts +19 -0
  29. package/dist/fleet/host-acp-runner-cache.d.ts +3 -1
  30. package/dist/fleet/host-acp.d.ts +14 -2
  31. package/dist/fleet/host.d.ts +1 -0
  32. package/dist/{hq-IG3YRGCO.js → hq-5XHEIIH6.js} +127 -8
  33. package/dist/hq-command-controller.d.ts +31 -2
  34. package/dist/hq-server/client-address.d.ts +2 -0
  35. package/dist/hq-server/ip-allowlist.d.ts +16 -0
  36. package/dist/hq-server/preflight.d.ts +1 -0
  37. package/dist/hq-server/routes/auth/password-routes.d.ts +1 -1
  38. package/dist/hq-server/routes.d.ts +5 -4
  39. package/dist/hq-server/secret-input.d.ts +7 -0
  40. package/dist/hq-server/types.d.ts +3 -2
  41. package/dist/hq-server/upgrade-handler.d.ts +2 -0
  42. package/dist/hq-server/utils.d.ts +6 -0
  43. package/dist/{hq-server-OILU3NPI.js → hq-server-CNUTBWTK.js} +4 -3
  44. package/dist/hq-server.d.ts +4 -0
  45. package/dist/hq-service-L5INQFM4.js +507 -0
  46. package/dist/hq-service.d.ts +22 -0
  47. package/dist/index.js +4 -4
  48. package/dist/ip-allowlist-NHXO6AKJ.js +9 -0
  49. package/dist/live-settings-input.d.ts +2 -0
  50. package/dist/{per-subcommand-help-BWBHYVJO.js → per-subcommand-help-DHTYU524.js} +2 -2
  51. package/dist/{plugins-U7KGQAUG.js → plugins-WJLW6ULV.js} +2 -2
  52. package/dist/projects-LMNAGGEU.js +36 -0
  53. package/dist/{proxy-wiring-MGRSKZZB.js → proxy-wiring-K2DORFFL.js} +3 -3
  54. package/dist/short-circuit-flags-YDMLAQ5R.js +10 -0
  55. package/dist/slash-commands/acp.d.ts +3 -0
  56. package/dist/slash-commands/command-context.d.ts +22 -0
  57. package/dist/slash-commands/ensemble.d.ts +1 -1
  58. package/dist/slash-commands/profile.d.ts +7 -0
  59. package/dist/subcommands/handlers/hq.d.ts +1 -0
  60. package/dist/subcommands/handlers/projects.d.ts +14 -0
  61. package/dist/{subcommands-CUTGBDKP.js → subcommands-7N4RIK6H.js} +2 -2
  62. package/dist/{version-help-MYKF724O.js → version-help-WXI42PZ3.js} +2 -2
  63. package/dist/{webui-server-QWBUT7BO.js → webui-server-OBV5JYJV.js} +9 -3
  64. package/dist/wiring/cli-slash-commands-setup.d.ts +7 -0
  65. package/dist/wiring/codebase-embeddings.d.ts +2 -2
  66. package/dist/wiring/command-host-state.d.ts +7 -0
  67. package/dist/wiring/pipeline.d.ts +2 -0
  68. package/dist/wiring/provider-runtime-setup.d.ts +1 -1
  69. package/dist/wiring/session-command-handlers.d.ts +2 -1
  70. package/dist/wiring/slash-commands.d.ts +1 -0
  71. package/package.json +28 -28
  72. package/dist/chunk-Q5GTM25S.js +0 -17
  73. package/dist/projects-L6C6XLDY.js +0 -37
  74. package/dist/short-circuit-flags-ZNZX44MC.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
@@ -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-CUTGBDKP.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-4NHD5OXJ.js.map
46
+ //# sourceMappingURL=chunk-U6PGWDMZ.js.map
@@ -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();
@@ -263,4 +267,4 @@ export {
263
267
  BUILTIN_PLUGIN_FACTORIES,
264
268
  setupPlugins
265
269
  };
266
- //# sourceMappingURL=chunk-U6KCWRMC.js.map
270
+ //# sourceMappingURL=chunk-XJ7K67PP.js.map
@@ -9,29 +9,37 @@ 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-IUEKNHPT.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-4NHD5OXJ.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
45
  } from "./chunk-D5GB5MHA.js";
@@ -40,7 +48,7 @@ import {
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";
@@ -67,7 +75,7 @@ import {
67
75
  } from "./chunk-YMXXOOFN.js";
68
76
  import {
69
77
  parseArgs
70
- } from "./chunk-E6RFXHWD.js";
78
+ } from "./chunk-EK2P53GL.js";
71
79
  import "./chunk-DAKVBMD4.js";
72
80
  import {
73
81
  mutateConfigProviders,
@@ -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.")}
@@ -3128,4 +3223,4 @@ async function initializeCli(argv) {
3128
3223
  export {
3129
3224
  initializeCli
3130
3225
  };
3131
- //# sourceMappingURL=cli-context-Q6QP534K.js.map
3226
+ //# sourceMappingURL=cli-context-WFC3BNGM.js.map