@wrongstack/cli 1.0.24 → 1.0.26

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/data/providers.json +44 -0
  2. package/dist/{acp-AJWSKWE5.js → acp-LI665LO2.js} +5 -5
  3. package/dist/ascii-mode-SG4PRNLP.js +7 -0
  4. package/dist/{auth-GRBZ7Y3D.js → auth-TE55JF4Z.js} +14 -14
  5. package/dist/{bench-N5K7Z5O3.js → bench-GTLPM22B.js} +2 -2
  6. package/dist/boot/append-system-prompt.d.ts +10 -0
  7. package/dist/boot/ascii-mode.d.ts +12 -0
  8. package/dist/boot/container-wiring.d.ts +4 -2
  9. package/dist/boot/dispatch-singleshot.d.ts +4 -1
  10. package/dist/boot/mcp-config-flag.d.ts +22 -0
  11. package/dist/boot/piped-stdin.d.ts +40 -0
  12. package/dist/boot/restricted-mode.d.ts +15 -0
  13. package/dist/boot/safe-mode.d.ts +30 -0
  14. package/dist/boot/single-shot-budget.d.ts +30 -0
  15. package/dist/boot/stream-json.d.ts +36 -0
  16. package/dist/boot/structured-output.d.ts +16 -0
  17. package/dist/boot/system-prompt-builder.d.ts +2 -0
  18. package/dist/boot/tool-restriction-flags.d.ts +36 -0
  19. package/dist/boot/worktree-sessions.d.ts +21 -0
  20. package/dist/boot-provider-selection.d.ts +67 -0
  21. package/dist/boot.d.ts +1 -38
  22. package/dist/{chunk-LFMVHT3R.js → chunk-2ERX3RPN.js} +11 -13
  23. package/dist/chunk-4TVYGG6G.js +62 -0
  24. package/dist/chunk-5JYDKG5B.js +154 -0
  25. package/dist/{chunk-3VXYY5JC.js → chunk-5UZBUV2H.js} +3 -19
  26. package/dist/chunk-BEHGRNOQ.js +58 -0
  27. package/dist/chunk-CZTXF6HY.js +140 -0
  28. package/dist/{chunk-SKPDE62W.js → chunk-EPR42SWM.js} +36 -6
  29. package/dist/{chunk-YBUCXXYZ.js → chunk-F5DCFAKI.js} +1 -1
  30. package/dist/chunk-HLSHFXTO.js +97 -0
  31. package/dist/{chunk-BLD5DSVA.js → chunk-KJS5543T.js} +2 -2
  32. package/dist/{chunk-QFPQXKCG.js → chunk-KOEO4CJG.js} +21 -6
  33. package/dist/chunk-LBPLTTZ6.js +105 -0
  34. package/dist/{chunk-3OCUS3VN.js → chunk-LDCGZJTC.js} +4 -4
  35. package/dist/chunk-LKPEBZBE.js +143 -0
  36. package/dist/{chunk-DRM7PSW7.js → chunk-OAVBM55Q.js} +3 -3
  37. package/dist/chunk-PZQBGUVZ.js +18 -0
  38. package/dist/{chunk-MHEBWVXL.js → chunk-Q4INH2DG.js} +46 -2
  39. package/dist/{chunk-ZZRSG7VK.js → chunk-RZ4ZDRYA.js} +3 -3
  40. package/dist/{chunk-U46QR4WR.js → chunk-TI7KLHYX.js} +132 -3
  41. package/dist/{chunk-PGKJ2OQP.js → chunk-WQV2NP57.js} +5 -5
  42. package/dist/chunk-X756ZS72.js +329 -0
  43. package/dist/{chunk-JF2MULWF.js → chunk-YHYINL47.js} +47 -15
  44. package/dist/{cli-context-34Q5IJRA.js → cli-context-UVGAN3NO.js} +407 -327
  45. package/dist/{cli-main-AELJDBGU.js → cli-main-TN3KZ2P6.js} +2652 -1978
  46. package/dist/cli-update-notice.d.ts +2 -1
  47. package/dist/config-doctor.d.ts +1 -1
  48. package/dist/{diag-doctor-WIFJH3XH.js → diag-doctor-BIZAFIAT.js} +2 -2
  49. package/dist/{execution-PYC5FCS4.js → execution-7QIP6GRY.js} +1948 -1666
  50. package/dist/fleet/host-types.d.ts +3 -1
  51. package/dist/goal-commands.d.ts +47 -0
  52. package/dist/goal-host.d.ts +1 -14
  53. package/dist/{hq-JTUTFI4L.js → hq-GLZ7QESM.js} +6 -6
  54. package/dist/{hq-server-PC7GZMPT.js → hq-server-YTKDVQPY.js} +2 -2
  55. package/dist/{hq-service-NW56MUP2.js → hq-service-BMMJAHRT.js} +4 -4
  56. package/dist/import-claude-code-32PCSIQI.js +236 -0
  57. package/dist/index.js +12 -8
  58. package/dist/{mailbox-serve-WDOCH6KR.js → mailbox-serve-NW5VZG7R.js} +3 -3
  59. package/dist/{modeldiag-36OGAL5C.js → modeldiag-36VODVIH.js} +8 -8
  60. package/dist/{per-subcommand-help-XE77MTGJ.js → per-subcommand-help-QDAQASPZ.js} +2 -2
  61. package/dist/permission-prompt.d.ts +14 -0
  62. package/dist/permission-rules-view.d.ts +18 -0
  63. package/dist/{permissions-CFDLXETM.js → permissions-PL27UHYD.js} +67 -45
  64. package/dist/{plugin-usage-S5LVGMBW.js → plugin-usage-CIGOOTX3.js} +2 -2
  65. package/dist/{plugins-RHBIVLI7.js → plugins-HQTXUD6A.js} +4 -2
  66. package/dist/preflight.d.ts +1 -1
  67. package/dist/{projects-LMNAGGEU.js → projects-T4CZCA25.js} +3 -6
  68. package/dist/provider-helpers.d.ts +7 -11
  69. package/dist/{providers-models-2CFG46RD.js → providers-models-5Z2PJTEW.js} +5 -5
  70. package/dist/release-asset-download.d.ts +10 -0
  71. package/dist/release-attestation.d.ts +28 -0
  72. package/dist/remote/remote-session.d.ts +64 -0
  73. package/dist/remote/remote-target.d.ts +69 -0
  74. package/dist/remote-O5WXHLWV.js +561 -0
  75. package/dist/{replay-Z3FTJEMM.js → replay-DEI566CW.js} +2 -2
  76. package/dist/services/commit-message.d.ts +2 -1
  77. package/dist/session-move-P2EC2COA.js +44 -0
  78. package/dist/session-move.d.ts +20 -0
  79. package/dist/session-stats.d.ts +10 -0
  80. package/dist/{sessions-config-IQUH2GXT.js → sessions-config-SXTTLNXA.js} +35 -5
  81. package/dist/short-circuit-flags-74Y5N6CF.js +10 -0
  82. package/dist/slash-commands/command-context.d.ts +15 -5
  83. package/dist/slash-commands/goal-refiner.d.ts +4 -49
  84. package/dist/slash-commands/mcp.d.ts +2 -1
  85. package/dist/slash-commands/permissions.d.ts +4 -0
  86. package/dist/slash-commands/settings-context-mutations.d.ts +5 -0
  87. package/dist/slash-commands/settings-limits-mutations.d.ts +12 -0
  88. package/dist/standalone-auto-update-TOTRGCSA.js +249 -0
  89. package/dist/standalone-auto-update.d.ts +65 -0
  90. package/dist/standalone-update-LZO3MNLH.js +24 -0
  91. package/dist/standalone-update.d.ts +37 -1
  92. package/dist/subcommands/handlers/import-claude-code.d.ts +42 -0
  93. package/dist/subcommands/handlers/permissions.d.ts +9 -3
  94. package/dist/subcommands/handlers/remote.d.ts +6 -0
  95. package/dist/subcommands/handlers/version-help.d.ts +5 -0
  96. package/dist/{subcommands-ZTSIN7LG.js → subcommands-Q6ORSB2E.js} +2 -2
  97. package/dist/tui-resume-callback.d.ts +18 -0
  98. package/dist/{typesafe-HVEVPA6R.js → typesafe-U7YB2RRV.js} +5 -5
  99. package/dist/{typesafe-topic-replay-4W73BOLV.js → typesafe-topic-replay-ZILIU3WS.js} +18 -2
  100. package/dist/{update-7XIOEXTD.js → update-TDZX4IL2.js} +4 -4
  101. package/dist/{update-check-2POMBHFB.js → update-check-J5ZVKS73.js} +3 -3
  102. package/dist/version-JB2UAV2A.js +11 -0
  103. package/dist/version-help-XJJQ7YSH.js +10 -0
  104. package/dist/webui-server/route-contexts.d.ts +1 -1
  105. package/dist/webui-server/session-start-payload.d.ts +5 -1
  106. package/dist/{webui-server-L2SICPTB.js → webui-server-YTHLRFD2.js} +509 -366
  107. package/dist/webui-server-lifecycle.d.ts +57 -0
  108. package/dist/webui-server.d.ts +0 -14
  109. package/dist/wiring/brain-and-orchestration.d.ts +3 -1
  110. package/dist/wiring/cli-prompt-and-tools-setup.d.ts +9 -0
  111. package/dist/wiring/cli-slash-commands-setup.d.ts +1 -0
  112. package/dist/wiring/lifecycle-plugins.d.ts +4 -2
  113. package/dist/wiring/metrics.d.ts +9 -1
  114. package/dist/wiring/pipeline.d.ts +2 -7
  115. package/dist/wiring/plugins.d.ts +3 -0
  116. package/dist/wiring/provider-status.d.ts +1 -0
  117. package/dist/wiring/provider-utility-tools.d.ts +3 -1
  118. package/package.json +28 -28
  119. package/dist/chunk-2BKFWIER.js +0 -98
  120. package/dist/chunk-424ORSE7.js +0 -56
  121. package/dist/chunk-QBBF7GIK.js +0 -65
  122. package/dist/short-circuit-flags-SDT53OML.js +0 -10
  123. package/dist/standalone-update-MW47J3AK.js +0 -164
  124. package/dist/version-help-WZ623NWM.js +0 -10
@@ -1,23 +1,45 @@
1
+ import {
2
+ explainCall,
3
+ formatExplainedCall,
4
+ formatPermissionRules
5
+ } from "./chunk-4TVYGG6G.js";
1
6
 
2
7
  // src/subcommands/handlers/permissions.ts
3
- import { DefaultPermissionPolicy } from "@wrongstack/core/security";
8
+ import { compilePermissionRules } from "@wrongstack/core/security";
4
9
  import { resolveWstackPaths } from "@wrongstack/core/utils";
10
+ import { createProjectPermissionPolicy } from "@wrongstack/runtime";
5
11
  var permissionsCmd = async (args, deps) => {
6
12
  const subCmd = args[0];
7
13
  if (subCmd === "help" || subCmd === "--help" || subCmd === "-h" || !subCmd || subCmd === "explain" && !args[1]) {
8
- if (subCmd !== "explain" && subCmd !== "help" && subCmd !== void 0) {
9
- deps.renderer.writeError(`Unknown permissions subcommand: ${subCmd}
10
- `);
11
- }
12
14
  deps.renderer.write(usage());
13
- return subCmd && subCmd !== "explain" && subCmd !== "help" && subCmd !== void 0 ? 1 : 0;
15
+ return 0;
14
16
  }
15
- if (subCmd !== "explain") {
17
+ if (subCmd !== "explain" && subCmd !== "rules") {
16
18
  deps.renderer.writeError(`Unknown permissions subcommand: ${subCmd}
17
19
  `);
18
20
  deps.renderer.write(usage());
19
21
  return 1;
20
22
  }
23
+ const jsonOutput = deps.flags?.["json"] === true || args.includes("--json");
24
+ const built = buildPolicy(deps);
25
+ if (typeof built === "string") {
26
+ deps.renderer.writeError(`${built}
27
+ `);
28
+ return 1;
29
+ }
30
+ const { policy, ctx, yolo, yoloSource } = built;
31
+ if (subCmd === "rules") {
32
+ const rules = await compilePermissionRules(policy, ctx, { yolo });
33
+ if (jsonOutput) deps.renderer.write(`${JSON.stringify(rules, null, 2)}
34
+ `);
35
+ else
36
+ deps.renderer.writeLine(
37
+ `YOLO: ${yolo ? "on" : "off"} (${yoloSource})
38
+
39
+ ${formatPermissionRules(rules)}`
40
+ );
41
+ return 0;
42
+ }
21
43
  const toolName = args[1];
22
44
  if (!toolName) {
23
45
  deps.renderer.writeError("Missing tool name.\n");
@@ -27,7 +49,6 @@ var permissionsCmd = async (args, deps) => {
27
49
  const inputIdx = args.indexOf("--input");
28
50
  const flagInput = deps.flags?.["input"];
29
51
  const rawInput = typeof flagInput === "string" ? flagInput : inputIdx >= 0 && inputIdx + 1 < args.length ? args[inputIdx + 1] : void 0;
30
- const jsonOutput = deps.flags?.["json"] === true || args.includes("--json");
31
52
  let input = {};
32
53
  if (rawInput) {
33
54
  try {
@@ -50,67 +71,68 @@ var permissionsCmd = async (args, deps) => {
50
71
  );
51
72
  return 1;
52
73
  }
74
+ const explained = await explainCall(policy, tool, input, ctx, yolo);
75
+ if (jsonOutput) {
76
+ deps.renderer.write(
77
+ `${JSON.stringify({ ...explained.trace, rule: explained.rule }, null, 2)}
78
+ `
79
+ );
80
+ } else {
81
+ deps.renderer.writeLine(
82
+ `YOLO: ${yolo ? "on" : "off"} (${yoloSource})
83
+
84
+ ${formatExplainedCall(explained)}`
85
+ );
86
+ }
87
+ return 0;
88
+ };
89
+ function buildPolicy(deps) {
53
90
  const paths = resolveWstackPaths({ projectRoot: deps.projectRoot, userHome: deps.userHome });
54
- const trustFile = paths.projectTrust;
55
91
  const readSubjects = /* @__PURE__ */ new Set();
56
92
  const ctx = {
57
93
  projectRoot: deps.projectRoot,
58
94
  cwd: deps.cwd,
95
+ workingDir: deps.cwd,
96
+ meta: {},
97
+ provider: { id: deps.config.provider },
59
98
  hasRead(subject) {
60
99
  return readSubjects.has(subject);
61
100
  }
62
101
  };
63
- const policy = new DefaultPermissionPolicy({
64
- trustFile,
65
- yolo: deps.flags?.["yolo"] ?? false
66
- });
67
- await policy.reload();
68
- const trace = await policy.explain(tool, input, ctx);
69
- if (jsonOutput) {
70
- deps.renderer.write(JSON.stringify(trace, null, 2) + "\n");
71
- } else {
72
- deps.renderer.write(formatTrace(trace) + "\n");
102
+ const yoloFlag = deps.flags?.["yolo"];
103
+ const yolo = typeof yoloFlag === "boolean" ? yoloFlag : deps.config.yolo === true;
104
+ try {
105
+ const policy = createProjectPermissionPolicy({
106
+ projectRoot: deps.projectRoot,
107
+ trustFile: paths.projectTrust,
108
+ config: deps.config,
109
+ permission: { yolo }
110
+ })();
111
+ return { policy, ctx, yolo, yoloSource: typeof yoloFlag === "boolean" ? "--yolo" : "config" };
112
+ } catch (error) {
113
+ return error instanceof Error ? error.message : String(error);
73
114
  }
74
- return 0;
75
- };
76
- function formatTrace(trace) {
77
- const lines = [];
78
- lines.push(`Permission trace for "${trace.toolName}"`);
79
- lines.push(`Subject: ${trace.subject ?? "(none)"}`);
80
- lines.push("");
81
- for (let i = 0; i < trace.steps.length; i++) {
82
- const step = trace.steps[i];
83
- const winner = i === trace.winnerIndex ? " \u2190 WINNER" : "";
84
- const matched = step.matched ? "\u2713" : " ";
85
- lines.push(` ${matched} [${i}] ${step.rule}${winner}`);
86
- lines.push(` decision: ${step.decision} source: ${step.source}`);
87
- lines.push(` ${step.detail}`);
88
- if (i < trace.steps.length - 1) lines.push("");
89
- }
90
- lines.push("");
91
- lines.push(`Effective: ${trace.decision.permission} (source: ${trace.decision.source})`);
92
- if (trace.decision.reason) {
93
- lines.push(`Reason: ${trace.decision.reason}`);
94
- }
95
- if (trace.decision.riskTier) {
96
- lines.push(`Risk tier: ${trace.decision.riskTier}`);
97
- }
98
- return lines.join("\n");
99
115
  }
100
116
  function usage() {
101
117
  return `Usage:
118
+ wstack permissions rules [--json]
102
119
  wstack permissions explain <tool> --input '<json>' [--json]
103
120
 
104
121
  Examples:
122
+ wstack permissions rules
105
123
  wstack permissions explain bash --input '{"command":"rm -rf /"}'
106
124
  wstack permissions explain read --input '{"path":".env"}' --json
107
125
 
108
126
  Flags:
109
127
  --input <json> Tool input arguments as a JSON object
110
128
  --json Output as structured JSON instead of human-readable text
129
+ --yolo Show the rules as they apply with YOLO on
130
+
131
+ Inside a session, /permissions shows the same with that session\u2019s YOLO,
132
+ answers and /permissions allow|deny rules.
111
133
  `;
112
134
  }
113
135
  export {
114
136
  permissionsCmd
115
137
  };
116
- //# sourceMappingURL=permissions-CFDLXETM.js.map
138
+ //# sourceMappingURL=permissions-PL27UHYD.js.map
@@ -4,10 +4,10 @@ import {
4
4
  import {
5
5
  activeProfileConfigPath
6
6
  } from "./chunk-YMXXOOFN.js";
7
- import "./chunk-WSTVGC2C.js";
8
7
  import {
9
8
  restoreFlags
10
9
  } from "./chunk-CSAPOCBP.js";
10
+ import "./chunk-WSTVGC2C.js";
11
11
 
12
12
  // src/subcommands/handlers/plugin-usage.ts
13
13
  var pluginCmd = async (args, deps) => {
@@ -41,4 +41,4 @@ export {
41
41
  pluginCmd,
42
42
  usageCmd
43
43
  };
44
- //# sourceMappingURL=plugin-usage-S5LVGMBW.js.map
44
+ //# sourceMappingURL=plugin-usage-CIGOOTX3.js.map
@@ -1,17 +1,19 @@
1
1
  import {
2
2
  BUILTIN_PLUGIN_FACTORIES,
3
+ BUILTIN_PLUGIN_NAME_HINTS,
3
4
  DEPRECATED_PLUGIN_NAMES,
4
5
  _resetDeprecatedWarningsForTests,
5
6
  builtinPluginNameFromSpec,
6
7
  pluginNameFromSpec,
7
8
  setupPlugins,
8
9
  warnIfDeprecatedPluginName
9
- } from "./chunk-JF2MULWF.js";
10
+ } from "./chunk-YHYINL47.js";
10
11
  import "./chunk-EWKESL4L.js";
11
12
  import "./chunk-L2RVEQWO.js";
12
13
  import "./chunk-WSTVGC2C.js";
13
14
  export {
14
15
  BUILTIN_PLUGIN_FACTORIES,
16
+ BUILTIN_PLUGIN_NAME_HINTS,
15
17
  DEPRECATED_PLUGIN_NAMES,
16
18
  _resetDeprecatedWarningsForTests,
17
19
  builtinPluginNameFromSpec,
@@ -19,4 +21,4 @@ export {
19
21
  setupPlugins,
20
22
  warnIfDeprecatedPluginName
21
23
  };
22
- //# sourceMappingURL=plugins-RHBIVLI7.js.map
24
+ //# sourceMappingURL=plugins-HQTXUD6A.js.map
@@ -39,7 +39,7 @@ export declare function applySessionShellDefault(): void;
39
39
  * callers get back the (possibly refreshed) `UpdateInfo`
40
40
  * so version-aware UI can render without re-fetching.
41
41
  */
42
- export declare function applyPrintUpdateNotice(initialUpdateInfo: UpdateInfo | undefined): Promise<UpdateInfo | undefined>;
42
+ export declare function applyPrintUpdateNotice(initialUpdateInfo: UpdateInfo | undefined, config?: Config | undefined): Promise<UpdateInfo | undefined>;
43
43
  /**
44
44
  * Seed the stream-debug singleton from persisted config so
45
45
  * `WireAdapter` picks it up on construction. Runtime toggles
@@ -1,8 +1,8 @@
1
1
 
2
2
  // src/subcommands/handlers/projects.ts
3
+ import { color } from "@wrongstack/core/utils";
3
4
  import * as fs from "node:fs/promises";
4
5
  import * as path from "node:path";
5
- import { color } from "@wrongstack/core/utils";
6
6
  var projectsCmd = async (_args, deps) => {
7
7
  const manifestPath = path.join(deps.paths.globalRoot, "projects.json");
8
8
  let entries;
@@ -18,10 +18,7 @@ var projectsCmd = async (_args, deps) => {
18
18
  return 0;
19
19
  }
20
20
  const sorted = [...entries].sort((a, b) => (b.lastSeen ?? "").localeCompare(a.lastSeen ?? ""));
21
- const slugWidth = Math.min(
22
- Math.max(...sorted.map((entry) => (entry.slug ?? "").length), 4),
23
- 40
24
- );
21
+ const slugWidth = Math.min(Math.max(...sorted.map((entry) => (entry.slug ?? "").length), 4), 40);
25
22
  for (const entry of sorted) {
26
23
  const slug = (entry.slug ?? "?").padEnd(slugWidth);
27
24
  const seen = entry.lastSeen ?? "";
@@ -33,4 +30,4 @@ var projectsCmd = async (_args, deps) => {
33
30
  export {
34
31
  projectsCmd
35
32
  };
36
- //# sourceMappingURL=projects-LMNAGGEU.js.map
33
+ //# sourceMappingURL=projects-T4CZCA25.js.map
@@ -1,4 +1,11 @@
1
+ /**
2
+ * Shared provider-config helpers used by the picker, main boot sequence,
3
+ * and subcommands. Keeps provider key detection and alias resolution in
4
+ * one place so the logic doesn't drift between call sites.
5
+ */
6
+ import { isKeylessLocalProvider } from '@wrongstack/core/models';
1
7
  import type { Config, ModelsRegistry, ProviderConfig, ResolvedProvider } from '@wrongstack/core/types';
8
+ export { isKeylessLocalProvider };
2
9
  /** Return the provider's visible model ids: models.dev plus anything the saved
3
10
  * config names that the catalog does not carry.
4
11
  *
@@ -23,17 +30,6 @@ import type { Config, ModelsRegistry, ProviderConfig, ResolvedProvider } from '@
23
30
  * request time rather than being silently unselectable, which is the better
24
31
  * failure: visible and actionable. */
25
32
  export declare function visibleModelIds(providerId: string, config: Config, catalogModelIds: string[], cfg?: ProviderConfig | undefined): string[];
26
- /**
27
- * Is this a keyless local gateway — a server on a loopback address that
28
- * declares no API-key env vars (omniroute, LiteLLM/vLLM/LM Studio/Ollama
29
- * running locally, …)? These need no credential, so they belong in the
30
- * picker even though `hasApiKey` returns false for them. Accepts the
31
- * minimal shape both call sites can supply.
32
- */
33
- export declare function isKeylessLocalProvider(provider: {
34
- apiBase?: string | undefined;
35
- envVars?: string[] | undefined;
36
- }): boolean;
37
33
  /**
38
34
  * Does this provider have an API key available — either in the
39
35
  * environment (via one of its known env vars) or stored in config
@@ -1,12 +1,12 @@
1
1
  import {
2
2
  visibleModelIds
3
- } from "./chunk-3VXYY5JC.js";
4
- import {
5
- activeProfileConfigPath
6
- } from "./chunk-YMXXOOFN.js";
3
+ } from "./chunk-5UZBUV2H.js";
7
4
  import {
8
5
  mutateConfigProviders
9
6
  } from "./chunk-LUMETJFO.js";
7
+ import {
8
+ activeProfileConfigPath
9
+ } from "./chunk-YMXXOOFN.js";
10
10
 
11
11
  // src/subcommands/handlers/providers-models.ts
12
12
  import * as fs from "node:fs/promises";
@@ -670,4 +670,4 @@ export {
670
670
  modelsCmd,
671
671
  providersCmd
672
672
  };
673
- //# sourceMappingURL=providers-models-2CFG46RD.js.map
673
+ //# sourceMappingURL=providers-models-5Z2PJTEW.js.map
@@ -1,3 +1,13 @@
1
1
  /** Download one release asset without buffering beyond its configured ceiling. */
2
2
  export declare function downloadReleaseAsset(url: string, timeoutMs: number, maxBytes: number): Promise<Buffer>;
3
+ /**
4
+ * Stream one release asset into `file` (created exclusively) and return its
5
+ * SHA-256. The background self-update uses this so a 100+ MB executable never
6
+ * sits in the session's heap. `file` is removed when the download fails.
7
+ */
8
+ export declare function downloadReleaseAssetToFile(url: string, file: string, options: {
9
+ timeoutMs: number;
10
+ maxBytes: number;
11
+ signal?: AbortSignal | undefined;
12
+ }): Promise<string>;
3
13
  //# sourceMappingURL=release-asset-download.d.ts.map
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Build-provenance check for a downloaded standalone executable.
3
+ *
4
+ * SHA256SUMS comes from the same release as the binary, so it catches a
5
+ * corrupted download but not a forged one: whoever can upload the binary can
6
+ * upload a matching SHA256SUMS. The release workflow also attests every
7
+ * binary (`actions/attest-build-provenance`), and GitHub serves those
8
+ * attestations by digest. A binary is accepted only if one of them says this
9
+ * exact digest was built by `binaries.yml`, called from `release.yml`, for the
10
+ * push of the tag `v<version>` in this repository, on a GitHub-hosted runner.
11
+ * A build from a branch or a manual run is not a release and does not count.
12
+ *
13
+ * The Sigstore signature over the statement is not verified here: the
14
+ * statement is trusted as served by GitHub's API over TLS.
15
+ */
16
+ /** GitHub repository the standalone executables are released from. */
17
+ export declare const RELEASES_REPO = "WrongStack/WrongStack";
18
+ export interface AttestationSubject {
19
+ /** Release asset name, e.g. `wstack-windows-x64.exe`. */
20
+ assetName: string;
21
+ /** Lowercase hex SHA-256 of the downloaded bytes. */
22
+ sha256: string;
23
+ /** Release version without the `v`, e.g. `1.0.25`. */
24
+ version: string;
25
+ }
26
+ /** Throws unless GitHub holds a release attestation for `subject`. */
27
+ export declare function verifyReleaseAttestation(subject: AttestationSubject, signal?: AbortSignal): Promise<void>;
28
+ //# sourceMappingURL=release-attestation.d.ts.map
@@ -0,0 +1,64 @@
1
+ /**
2
+ * `wstack remote user@host:/path`: the agent, its tools and its project
3
+ * daemons run on the remote machine; the WebUI is opened locally through an
4
+ * SSH tunnel. WrongStack's own build is uploaded to the remote on first use
5
+ * (per version, next to nothing the user installed), the WebUI host is started
6
+ * detached so a dropped connection does not end it, and the tunnel is reopened
7
+ * when it drops.
8
+ *
9
+ * SSH is the system `ssh`, so the user's `~/.ssh/config`, agent and known
10
+ * hosts apply. Credentials are not copied: the remote WrongStack uses its own
11
+ * configuration, which the remote WebUI sets up like a local first run.
12
+ *
13
+ * @module remote/remote-session
14
+ */
15
+ import { type ChildProcess } from 'node:child_process';
16
+ import type { Readable } from 'node:stream';
17
+ import { type RemoteTarget } from './remote-target.js';
18
+ export interface SshResult {
19
+ code: number;
20
+ stdout: string;
21
+ }
22
+ /** Runs one command on the remote host; `input` is its stdin. */
23
+ export type SshRunner = (remoteCommand: string, input: string | Readable) => Promise<SshResult>;
24
+ /** Opens the tunnel; the returned process lives as long as the tunnel does. */
25
+ export type TunnelOpener = (localPort: number, remotePort: number) => ChildProcess;
26
+ export interface RemoteBinary {
27
+ file: string;
28
+ /** Names the build on the remote machine. */
29
+ version: string;
30
+ }
31
+ export interface RemoteSessionOptions {
32
+ target: RemoteTarget;
33
+ /** Preferred local port for the WebUI (the next free one is used). */
34
+ localPort: number;
35
+ /** Leave the remote WebUI running after this command ends. */
36
+ keep: boolean;
37
+ open: boolean;
38
+ signal: AbortSignal;
39
+ log: (line: string) => void;
40
+ ssh: SshRunner;
41
+ tunnel: TunnelOpener;
42
+ /** The build for a remote `buildTarget` (`bun-linux-x64`, …); may download it. */
43
+ resolveBinary: (buildTarget: string, installed: readonly string[]) => Promise<RemoteBinary>;
44
+ openUrl?: ((url: string) => void) | undefined;
45
+ /** Waits before a reconnect attempt; injected in tests. */
46
+ sleep?: ((ms: number) => Promise<void>) | undefined;
47
+ /** How long the WebUI gets to answer through a new tunnel. */
48
+ readyTimeoutMs?: number | undefined;
49
+ }
50
+ export declare function sha256File(file: string): Promise<string>;
51
+ /** The first free port at or above `start` on the local loopback. */
52
+ export declare function freeLocalPort(start: number): Promise<number>;
53
+ export declare function runRemoteSession(opts: RemoteSessionOptions): Promise<number>;
54
+ export declare function systemSsh(target: RemoteTarget, options: {
55
+ sshConfig?: string | undefined;
56
+ batch: boolean;
57
+ }): {
58
+ run: SshRunner;
59
+ tunnel: TunnelOpener;
60
+ };
61
+ /** Cached download location for release builds. */
62
+ export declare function releaseCacheFile(root: string, version: string, assetName: string): string;
63
+ export declare function cachedFile(file: string): Promise<string | undefined>;
64
+ //# sourceMappingURL=remote-session.d.ts.map
@@ -0,0 +1,69 @@
1
+ /**
2
+ * The pure half of `wstack remote`: where to connect, which build the remote
3
+ * machine needs, and the POSIX sh scripts run there. No process is started
4
+ * here, so all of it is testable without an SSH server.
5
+ *
6
+ * @module remote/remote-target
7
+ */
8
+ export interface RemoteTarget {
9
+ /** What `ssh` connects to: `user@host`, `host`, or a `~/.ssh/config` alias. */
10
+ destination: string;
11
+ port?: number | undefined;
12
+ /** Project directory on the remote machine. */
13
+ path: string;
14
+ }
15
+ /**
16
+ * `user@host:/path`, `host:~/path`, or `ssh://user@host:2222/path`. The path
17
+ * is required: it is the remote project the agent works in.
18
+ */
19
+ export declare function parseRemoteTarget(input: string): RemoteTarget;
20
+ /** One argument for a POSIX shell, single-quoted. */
21
+ export declare function shQuote(value: string): string;
22
+ /**
23
+ * The build for a machine, from `uname -s`, `uname -m` and whether its libc is
24
+ * musl. Windows hosts are not supported: the remote scripts are POSIX sh.
25
+ */
26
+ export declare function buildTargetFor(os: string, arch: string, musl: boolean): string;
27
+ export interface ProbeResult {
28
+ os: string;
29
+ arch: string;
30
+ musl: boolean;
31
+ pathExists: boolean;
32
+ /** Versions already installed under `~/.wrongstack/remote`. */
33
+ versions: string[];
34
+ /** A server a previous run left running for this path. */
35
+ server?: {
36
+ pid: number;
37
+ port: number;
38
+ version: string;
39
+ token: string;
40
+ } | undefined;
41
+ }
42
+ /** Reports the machine, the project path, the builds present and a running server. */
43
+ export declare function probeScript(path: string): string;
44
+ export declare function parseProbe(output: string): ProbeResult;
45
+ /** The remote file a version's build lives in. */
46
+ export declare function remoteBinaryPath(version: string): string;
47
+ /**
48
+ * Receives a build on stdin, makes it executable, and prints its SHA-256 so
49
+ * the caller can compare it with what it sent. Run with `sh -c`.
50
+ */
51
+ export declare function installScript(version: string): string;
52
+ /**
53
+ * Starts the WebUI host for `path` detached from the SSH session (a dropped
54
+ * connection must not end it), bound to the remote loopback only, and waits
55
+ * for it to report its port. The token travels inside this script, which is
56
+ * sent on stdin: it never appears on a command line another user can see.
57
+ *
58
+ * A remote machine WrongStack has not been set up on has no provider it can
59
+ * use; the host is then started in setup mode, and one is chosen in the WebUI.
60
+ */
61
+ export declare function startScript(options: {
62
+ path: string;
63
+ version: string;
64
+ token: string;
65
+ preferredPort: number;
66
+ }): string;
67
+ /** Stops the server a start left for `path`, if it is still running. */
68
+ export declare function stopScript(path: string): string;
69
+ //# sourceMappingURL=remote-target.d.ts.map