@sentropic/h2a-runtime 0.81.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (253) hide show
  1. package/dist/account-pool.d.ts +168 -0
  2. package/dist/account-pool.d.ts.map +1 -0
  3. package/dist/account-pool.js +385 -0
  4. package/dist/account-pool.js.map +1 -0
  5. package/dist/agents-projection.d.ts +56 -0
  6. package/dist/agents-projection.d.ts.map +1 -0
  7. package/dist/agents-projection.js +82 -0
  8. package/dist/agents-projection.js.map +1 -0
  9. package/dist/attach.d.ts +75 -0
  10. package/dist/attach.d.ts.map +1 -0
  11. package/dist/attach.js +432 -0
  12. package/dist/attach.js.map +1 -0
  13. package/dist/auth-bundle.d.ts +21 -0
  14. package/dist/auth-bundle.d.ts.map +1 -0
  15. package/dist/auth-bundle.js +112 -0
  16. package/dist/auth-bundle.js.map +1 -0
  17. package/dist/auth-diagnostics.d.ts +18 -0
  18. package/dist/auth-diagnostics.d.ts.map +1 -0
  19. package/dist/auth-diagnostics.js +23 -0
  20. package/dist/auth-diagnostics.js.map +1 -0
  21. package/dist/auth-login.d.ts +9 -0
  22. package/dist/auth-login.d.ts.map +1 -0
  23. package/dist/auth-login.js +21 -0
  24. package/dist/auth-login.js.map +1 -0
  25. package/dist/auth-refresh.d.ts +32 -0
  26. package/dist/auth-refresh.d.ts.map +1 -0
  27. package/dist/auth-refresh.js +83 -0
  28. package/dist/auth-refresh.js.map +1 -0
  29. package/dist/auth-tools.d.ts +55 -0
  30. package/dist/auth-tools.d.ts.map +1 -0
  31. package/dist/auth-tools.js +163 -0
  32. package/dist/auth-tools.js.map +1 -0
  33. package/dist/browser-bridge-local.d.ts +27 -0
  34. package/dist/browser-bridge-local.d.ts.map +1 -0
  35. package/dist/browser-bridge-local.js +51 -0
  36. package/dist/browser-bridge-local.js.map +1 -0
  37. package/dist/browser.d.ts +53 -0
  38. package/dist/browser.d.ts.map +1 -0
  39. package/dist/browser.js +61 -0
  40. package/dist/browser.js.map +1 -0
  41. package/dist/conductor-launch.d.ts +179 -0
  42. package/dist/conductor-launch.d.ts.map +1 -0
  43. package/dist/conductor-launch.js +414 -0
  44. package/dist/conductor-launch.js.map +1 -0
  45. package/dist/config.d.ts +182 -0
  46. package/dist/config.d.ts.map +1 -0
  47. package/dist/config.js +334 -0
  48. package/dist/config.js.map +1 -0
  49. package/dist/conv-guard.d.ts +76 -0
  50. package/dist/conv-guard.d.ts.map +1 -0
  51. package/dist/conv-guard.js +131 -0
  52. package/dist/conv-guard.js.map +1 -0
  53. package/dist/convsync.d.ts +24 -0
  54. package/dist/convsync.d.ts.map +1 -0
  55. package/dist/convsync.js +108 -0
  56. package/dist/convsync.js.map +1 -0
  57. package/dist/cred-health.d.ts +96 -0
  58. package/dist/cred-health.d.ts.map +1 -0
  59. package/dist/cred-health.js +170 -0
  60. package/dist/cred-health.js.map +1 -0
  61. package/dist/delegate.d.ts +406 -0
  62. package/dist/delegate.d.ts.map +1 -0
  63. package/dist/delegate.js +739 -0
  64. package/dist/delegate.js.map +1 -0
  65. package/dist/enroll.d.ts +91 -0
  66. package/dist/enroll.d.ts.map +1 -0
  67. package/dist/enroll.js +248 -0
  68. package/dist/enroll.js.map +1 -0
  69. package/dist/fanout.d.ts +63 -0
  70. package/dist/fanout.d.ts.map +1 -0
  71. package/dist/fanout.js +115 -0
  72. package/dist/fanout.js.map +1 -0
  73. package/dist/forward.d.ts +66 -0
  74. package/dist/forward.d.ts.map +1 -0
  75. package/dist/forward.js +141 -0
  76. package/dist/forward.js.map +1 -0
  77. package/dist/gitdiff.d.ts +31 -0
  78. package/dist/gitdiff.d.ts.map +1 -0
  79. package/dist/gitdiff.js +133 -0
  80. package/dist/gitdiff.js.map +1 -0
  81. package/dist/h2a-bridge.d.ts +102 -0
  82. package/dist/h2a-bridge.d.ts.map +1 -0
  83. package/dist/h2a-bridge.js +333 -0
  84. package/dist/h2a-bridge.js.map +1 -0
  85. package/dist/h2a-jobs.d.ts +235 -0
  86. package/dist/h2a-jobs.d.ts.map +1 -0
  87. package/dist/h2a-jobs.js +388 -0
  88. package/dist/h2a-jobs.js.map +1 -0
  89. package/dist/h2a-ping.d.ts +38 -0
  90. package/dist/h2a-ping.d.ts.map +1 -0
  91. package/dist/h2a-ping.js +58 -0
  92. package/dist/h2a-ping.js.map +1 -0
  93. package/dist/index.d.ts +98 -0
  94. package/dist/index.d.ts.map +1 -0
  95. package/dist/index.js +5887 -0
  96. package/dist/index.js.map +1 -0
  97. package/dist/interactive-throttle.d.ts +164 -0
  98. package/dist/interactive-throttle.d.ts.map +1 -0
  99. package/dist/interactive-throttle.js +194 -0
  100. package/dist/interactive-throttle.js.map +1 -0
  101. package/dist/lineage-client.d.ts +77 -0
  102. package/dist/lineage-client.d.ts.map +1 -0
  103. package/dist/lineage-client.js +117 -0
  104. package/dist/lineage-client.js.map +1 -0
  105. package/dist/lineage-lease.d.ts +152 -0
  106. package/dist/lineage-lease.d.ts.map +1 -0
  107. package/dist/lineage-lease.js +303 -0
  108. package/dist/lineage-lease.js.map +1 -0
  109. package/dist/llm-gateway-runtime/accounts.d.ts +48 -0
  110. package/dist/llm-gateway-runtime/accounts.d.ts.map +1 -0
  111. package/dist/llm-gateway-runtime/accounts.js +226 -0
  112. package/dist/llm-gateway-runtime/accounts.js.map +1 -0
  113. package/dist/llm-gateway-runtime/index.d.ts +4 -0
  114. package/dist/llm-gateway-runtime/index.d.ts.map +1 -0
  115. package/dist/llm-gateway-runtime/index.js +58 -0
  116. package/dist/llm-gateway-runtime/index.js.map +1 -0
  117. package/dist/llm-gateway-runtime/model-catalog.d.ts +36 -0
  118. package/dist/llm-gateway-runtime/model-catalog.d.ts.map +1 -0
  119. package/dist/llm-gateway-runtime/model-catalog.js +146 -0
  120. package/dist/llm-gateway-runtime/model-catalog.js.map +1 -0
  121. package/dist/llm-gateway-runtime/proxy-anthropic.d.ts +3 -0
  122. package/dist/llm-gateway-runtime/proxy-anthropic.d.ts.map +1 -0
  123. package/dist/llm-gateway-runtime/proxy-anthropic.js +139 -0
  124. package/dist/llm-gateway-runtime/proxy-anthropic.js.map +1 -0
  125. package/dist/llm-gateway-runtime/proxy-openai.d.ts +117 -0
  126. package/dist/llm-gateway-runtime/proxy-openai.d.ts.map +1 -0
  127. package/dist/llm-gateway-runtime/proxy-openai.js +1132 -0
  128. package/dist/llm-gateway-runtime/proxy-openai.js.map +1 -0
  129. package/dist/llm-gateway-runtime/session-ledger.d.ts +32 -0
  130. package/dist/llm-gateway-runtime/session-ledger.d.ts.map +1 -0
  131. package/dist/llm-gateway-runtime/session-ledger.js +62 -0
  132. package/dist/llm-gateway-runtime/session-ledger.js.map +1 -0
  133. package/dist/llm-gateway-runtime/sticky.d.ts +40 -0
  134. package/dist/llm-gateway-runtime/sticky.d.ts.map +1 -0
  135. package/dist/llm-gateway-runtime/sticky.js +254 -0
  136. package/dist/llm-gateway-runtime/sticky.js.map +1 -0
  137. package/dist/llm-mesh.d.ts +102 -0
  138. package/dist/llm-mesh.d.ts.map +1 -0
  139. package/dist/llm-mesh.js +433 -0
  140. package/dist/llm-mesh.js.map +1 -0
  141. package/dist/migrate-candidates.d.ts +35 -0
  142. package/dist/migrate-candidates.d.ts.map +1 -0
  143. package/dist/migrate-candidates.js +128 -0
  144. package/dist/migrate-candidates.js.map +1 -0
  145. package/dist/migrate.d.ts +125 -0
  146. package/dist/migrate.d.ts.map +1 -0
  147. package/dist/migrate.js +561 -0
  148. package/dist/migrate.js.map +1 -0
  149. package/dist/plugin-manifest.d.ts +143 -0
  150. package/dist/plugin-manifest.d.ts.map +1 -0
  151. package/dist/plugin-manifest.js +233 -0
  152. package/dist/plugin-manifest.js.map +1 -0
  153. package/dist/plugin.d.ts +274 -0
  154. package/dist/plugin.d.ts.map +1 -0
  155. package/dist/plugin.js +919 -0
  156. package/dist/plugin.js.map +1 -0
  157. package/dist/pod-liveness.d.ts +51 -0
  158. package/dist/pod-liveness.d.ts.map +1 -0
  159. package/dist/pod-liveness.js +80 -0
  160. package/dist/pod-liveness.js.map +1 -0
  161. package/dist/profile-menu.d.ts +7 -0
  162. package/dist/profile-menu.d.ts.map +1 -0
  163. package/dist/profile-menu.js +52 -0
  164. package/dist/profile-menu.js.map +1 -0
  165. package/dist/profiles.d.ts +23 -0
  166. package/dist/profiles.d.ts.map +1 -0
  167. package/dist/profiles.js +66 -0
  168. package/dist/profiles.js.map +1 -0
  169. package/dist/protocol-local.d.ts +27 -0
  170. package/dist/protocol-local.d.ts.map +1 -0
  171. package/dist/protocol-local.js +12 -0
  172. package/dist/protocol-local.js.map +1 -0
  173. package/dist/pty.d.ts +26 -0
  174. package/dist/pty.d.ts.map +1 -0
  175. package/dist/pty.js +45 -0
  176. package/dist/pty.js.map +1 -0
  177. package/dist/readiness.d.ts +38 -0
  178. package/dist/readiness.d.ts.map +1 -0
  179. package/dist/readiness.js +169 -0
  180. package/dist/readiness.js.map +1 -0
  181. package/dist/registry.d.ts +258 -0
  182. package/dist/registry.d.ts.map +1 -0
  183. package/dist/registry.js +570 -0
  184. package/dist/registry.js.map +1 -0
  185. package/dist/relaunch.d.ts +52 -0
  186. package/dist/relaunch.d.ts.map +1 -0
  187. package/dist/relaunch.js +76 -0
  188. package/dist/relaunch.js.map +1 -0
  189. package/dist/restore.d.ts +165 -0
  190. package/dist/restore.d.ts.map +1 -0
  191. package/dist/restore.js +530 -0
  192. package/dist/restore.js.map +1 -0
  193. package/dist/run.d.ts +29 -0
  194. package/dist/run.d.ts.map +1 -0
  195. package/dist/run.js +206 -0
  196. package/dist/run.js.map +1 -0
  197. package/dist/secrets.d.ts +25 -0
  198. package/dist/secrets.d.ts.map +1 -0
  199. package/dist/secrets.js +98 -0
  200. package/dist/secrets.js.map +1 -0
  201. package/dist/session-restore.d.ts +26 -0
  202. package/dist/session-restore.d.ts.map +1 -0
  203. package/dist/session-restore.js +122 -0
  204. package/dist/session-restore.js.map +1 -0
  205. package/dist/skills-sync.d.ts +126 -0
  206. package/dist/skills-sync.d.ts.map +1 -0
  207. package/dist/skills-sync.js +255 -0
  208. package/dist/skills-sync.js.map +1 -0
  209. package/dist/smoke.d.ts +23 -0
  210. package/dist/smoke.d.ts.map +1 -0
  211. package/dist/smoke.js +138 -0
  212. package/dist/smoke.js.map +1 -0
  213. package/dist/soft-refresh.d.ts +107 -0
  214. package/dist/soft-refresh.d.ts.map +1 -0
  215. package/dist/soft-refresh.js +426 -0
  216. package/dist/soft-refresh.js.map +1 -0
  217. package/dist/sync-status.d.ts +22 -0
  218. package/dist/sync-status.d.ts.map +1 -0
  219. package/dist/sync-status.js +41 -0
  220. package/dist/sync-status.js.map +1 -0
  221. package/dist/sync.d.ts +77 -0
  222. package/dist/sync.d.ts.map +1 -0
  223. package/dist/sync.js +302 -0
  224. package/dist/sync.js.map +1 -0
  225. package/dist/throttle-signatures.d.ts +43 -0
  226. package/dist/throttle-signatures.d.ts.map +1 -0
  227. package/dist/throttle-signatures.js +116 -0
  228. package/dist/throttle-signatures.js.map +1 -0
  229. package/dist/tmux.d.ts +286 -0
  230. package/dist/tmux.d.ts.map +1 -0
  231. package/dist/tmux.js +970 -0
  232. package/dist/tmux.js.map +1 -0
  233. package/dist/tunnel.d.ts +25 -0
  234. package/dist/tunnel.d.ts.map +1 -0
  235. package/dist/tunnel.js +127 -0
  236. package/dist/tunnel.js.map +1 -0
  237. package/dist/workspace-merge.d.ts +17 -0
  238. package/dist/workspace-merge.d.ts.map +1 -0
  239. package/dist/workspace-merge.js +153 -0
  240. package/dist/workspace-merge.js.map +1 -0
  241. package/dist/workspace-sync-incremental.d.ts +64 -0
  242. package/dist/workspace-sync-incremental.d.ts.map +1 -0
  243. package/dist/workspace-sync-incremental.js +199 -0
  244. package/dist/workspace-sync-incremental.js.map +1 -0
  245. package/dist/workspace-sync.d.ts +3 -0
  246. package/dist/workspace-sync.d.ts.map +1 -0
  247. package/dist/workspace-sync.js +187 -0
  248. package/dist/workspace-sync.js.map +1 -0
  249. package/dist/workspace.d.ts +70 -0
  250. package/dist/workspace.d.ts.map +1 -0
  251. package/dist/workspace.js +173 -0
  252. package/dist/workspace.js.map +1 -0
  253. package/package.json +44 -0
@@ -0,0 +1,51 @@
1
+ export const NOVNC_POD_PORT = 6080;
2
+ export function evaluateExposure(req) {
3
+ switch (req.policy) {
4
+ case "operator-only":
5
+ return req.requester === "operator"
6
+ ? { allowed: true }
7
+ : { allowed: false, reason: `policy "operator-only" forbids requester "${req.requester}" — only an operator may expose this browser` };
8
+ case "session-private":
9
+ if (req.requester === "anonymous") {
10
+ return { allowed: false, reason: 'policy "session-private" forbids an anonymous requester — only the session owner or an operator may expose this browser' };
11
+ }
12
+ if (!req.hasToken) {
13
+ return { allowed: false, reason: 'policy "session-private" requires a per-session access token on the route (none present)' };
14
+ }
15
+ return { allowed: true };
16
+ case "public-expiring":
17
+ if (!req.hasToken) {
18
+ return { allowed: false, reason: 'policy "public-expiring" requires a per-session access token on the route (none present)' };
19
+ }
20
+ if (req.expiresInMs === undefined || req.expiresInMs <= 0) {
21
+ return { allowed: false, reason: 'policy "public-expiring" requires a finite positive expiry (expiresInMs) — refusing an open-ended public route' };
22
+ }
23
+ return { allowed: true };
24
+ }
25
+ }
26
+ export function buildForwardCommand(sessionId, localPort) {
27
+ const tail = localPort === undefined ? "" : ` ${localPort}`;
28
+ return `remote forward ${sessionId} ${NOVNC_POD_PORT}${tail}`;
29
+ }
30
+ export function buildNoVncUrl(opts) {
31
+ const host = opts.host ?? "localhost";
32
+ const port = opts.localPort ?? NOVNC_POD_PORT;
33
+ const interactive = opts.interactive ?? true;
34
+ const autoconnect = opts.autoconnect ?? true;
35
+ const params = new URLSearchParams();
36
+ params.set("path", `websockify?token=${opts.token}`);
37
+ if (autoconnect)
38
+ params.set("autoconnect", "true");
39
+ if (!interactive)
40
+ params.set("view_only", "true");
41
+ return `http://${host}:${port}/vnc.html?${params.toString()}`;
42
+ }
43
+ const defaultRandomBytes = (length) => {
44
+ const out = new Uint8Array(length);
45
+ globalThis.crypto.getRandomValues(out);
46
+ return out;
47
+ };
48
+ export function mintNoVncToken(rng = defaultRandomBytes) {
49
+ return Array.from(rng(16), (b) => b.toString(16).padStart(2, "0")).join("");
50
+ }
51
+ //# sourceMappingURL=browser-bridge-local.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"browser-bridge-local.js","sourceRoot":"","sources":["../src/browser-bridge-local.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,53 @@
1
+ /**
2
+ * `remote browser open <sessionId>` — WP7 noVNC headful browser-in-pod.
3
+ *
4
+ * One command to open the headful browser view for a session so the user can
5
+ * complete a 2FA / login challenge visually. The heavy lifting (spawning the
6
+ * Xvfb+Chromium+x11vnc+websockify+noVNC sidecar) happens IN the Pod via the
7
+ * browser-bridge; this CLI surface is the user's entry point:
8
+ *
9
+ * 1. enforce the uat-exposure-policy locally (deny early with a reason);
10
+ * 2. mint the per-session noVNC token + build the forwardable noVNC URL;
11
+ * 3. print the exact `remote forward <id> 6080` command and the URL to open.
12
+ *
13
+ * The actual port-forward is delegated to the existing `remote forward`
14
+ * transport (forward.ts) — we don't duplicate kubectl wiring. The token is the
15
+ * only sensitive value; it is printed ONCE to the user's own terminal (so they
16
+ * can open the gated URL) and never logged elsewhere. The pure builder below is
17
+ * unit-tested; the action wiring lives in index.ts.
18
+ */
19
+ import { type ExposureRequester, type RandomBytes } from "./browser-bridge-local.js";
20
+ import type { UatExposurePolicy } from "./protocol-local.js";
21
+ export type BrowserOpenPlan = {
22
+ readonly ok: true;
23
+ readonly podPort: number;
24
+ readonly forwardCommand: string;
25
+ readonly url: string;
26
+ /** Human-facing multi-line instructions (token only in the URL). */
27
+ readonly instructions: string;
28
+ } | {
29
+ readonly ok: false;
30
+ readonly reason: string;
31
+ };
32
+ export type BuildBrowserOpenPlanOptions = {
33
+ readonly sessionId: string;
34
+ /** Default session-private — only the owner, token-gated. */
35
+ readonly exposurePolicy?: UatExposurePolicy;
36
+ /** Default session-owner (the user running the CLI owns the session). */
37
+ readonly requester?: ExposureRequester;
38
+ /** Local port the user will bind the forward to (optional). */
39
+ readonly localPort?: number;
40
+ /** Interactive (drive the 2FA) — default true. */
41
+ readonly interactive?: boolean;
42
+ /** Route TTL in ms (only required by the public-expiring policy). */
43
+ readonly ttlMs?: number;
44
+ /** Injectable RNG for the token (tests). */
45
+ readonly rng?: RandomBytes;
46
+ };
47
+ /**
48
+ * Build the open plan: policy-gate, then the forward command + noVNC URL the
49
+ * user runs/opens. Pure (token from the injected RNG) so the allow/deny and the
50
+ * exact command/URL are unit-tested without a cluster.
51
+ */
52
+ export declare function buildBrowserOpenPlan(opts: BuildBrowserOpenPlanOptions): BrowserOpenPlan;
53
+ //# sourceMappingURL=browser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"browser.d.ts","sourceRoot":"","sources":["../src/browser.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,EAML,KAAK,iBAAiB,EACtB,KAAK,WAAW,EACjB,MAAM,2BAA2B,CAAC;AACnC,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAE7D,MAAM,MAAM,eAAe,GACvB;IACE,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC;IAClB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,oEAAoE;IACpE,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;CAC/B,GACD;IAAE,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAEpD,MAAM,MAAM,2BAA2B,GAAG;IACxC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,6DAA6D;IAC7D,QAAQ,CAAC,cAAc,CAAC,EAAE,iBAAiB,CAAC;IAC5C,yEAAyE;IACzE,QAAQ,CAAC,SAAS,CAAC,EAAE,iBAAiB,CAAC;IACvC,+DAA+D;IAC/D,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,kDAAkD;IAClD,QAAQ,CAAC,WAAW,CAAC,EAAE,OAAO,CAAC;IAC/B,qEAAqE;IACrE,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,4CAA4C;IAC5C,QAAQ,CAAC,GAAG,CAAC,EAAE,WAAW,CAAC;CAC5B,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,2BAA2B,GAChC,eAAe,CAwCjB"}
@@ -0,0 +1,61 @@
1
+ /**
2
+ * `remote browser open <sessionId>` — WP7 noVNC headful browser-in-pod.
3
+ *
4
+ * One command to open the headful browser view for a session so the user can
5
+ * complete a 2FA / login challenge visually. The heavy lifting (spawning the
6
+ * Xvfb+Chromium+x11vnc+websockify+noVNC sidecar) happens IN the Pod via the
7
+ * browser-bridge; this CLI surface is the user's entry point:
8
+ *
9
+ * 1. enforce the uat-exposure-policy locally (deny early with a reason);
10
+ * 2. mint the per-session noVNC token + build the forwardable noVNC URL;
11
+ * 3. print the exact `remote forward <id> 6080` command and the URL to open.
12
+ *
13
+ * The actual port-forward is delegated to the existing `remote forward`
14
+ * transport (forward.ts) — we don't duplicate kubectl wiring. The token is the
15
+ * only sensitive value; it is printed ONCE to the user's own terminal (so they
16
+ * can open the gated URL) and never logged elsewhere. The pure builder below is
17
+ * unit-tested; the action wiring lives in index.ts.
18
+ */
19
+ import { buildForwardCommand, buildNoVncUrl, evaluateExposure, mintNoVncToken, NOVNC_POD_PORT, } from "./browser-bridge-local.js";
20
+ /**
21
+ * Build the open plan: policy-gate, then the forward command + noVNC URL the
22
+ * user runs/opens. Pure (token from the injected RNG) so the allow/deny and the
23
+ * exact command/URL are unit-tested without a cluster.
24
+ */
25
+ export function buildBrowserOpenPlan(opts) {
26
+ const policy = opts.exposurePolicy ?? "session-private";
27
+ const requester = opts.requester ?? "session-owner";
28
+ const interactive = opts.interactive ?? true;
29
+ const decision = evaluateExposure({
30
+ policy,
31
+ requester,
32
+ hasToken: true, // we always mint a token below
33
+ ...(policy === "public-expiring" && opts.ttlMs !== undefined
34
+ ? { expiresInMs: opts.ttlMs }
35
+ : {}),
36
+ });
37
+ if (!decision.allowed) {
38
+ return { ok: false, reason: decision.reason };
39
+ }
40
+ const token = mintNoVncToken(opts.rng);
41
+ const forwardCommand = buildForwardCommand(opts.sessionId, opts.localPort);
42
+ const url = buildNoVncUrl({
43
+ token,
44
+ interactive,
45
+ ...(opts.localPort !== undefined ? { localPort: opts.localPort } : {}),
46
+ });
47
+ const instructions = `[remote] headful browser for ${opts.sessionId} (noVNC, ${policy})\n` +
48
+ `[remote] 1. open the port-forward (foreground, Ctrl-C to stop):\n` +
49
+ ` ${forwardCommand}\n` +
50
+ `[remote] 2. then open this URL in your browser:\n` +
51
+ ` ${url}\n` +
52
+ `[remote] complete the 2FA/login in the desktop, then stop the forward.\n`;
53
+ return {
54
+ ok: true,
55
+ podPort: NOVNC_POD_PORT,
56
+ forwardCommand,
57
+ url,
58
+ instructions,
59
+ };
60
+ }
61
+ //# sourceMappingURL=browser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"browser.js","sourceRoot":"","sources":["../src/browser.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,EACL,mBAAmB,EACnB,aAAa,EACb,gBAAgB,EAChB,cAAc,EACd,cAAc,GAGf,MAAM,2BAA2B,CAAC;AA8BnC;;;;GAIG;AACH,MAAM,UAAU,oBAAoB,CAClC,IAAiC;IAEjC,MAAM,MAAM,GAAsB,IAAI,CAAC,cAAc,IAAI,iBAAiB,CAAC;IAC3E,MAAM,SAAS,GAAsB,IAAI,CAAC,SAAS,IAAI,eAAe,CAAC;IACvE,MAAM,WAAW,GAAG,IAAI,CAAC,WAAW,IAAI,IAAI,CAAC;IAE7C,MAAM,QAAQ,GAAG,gBAAgB,CAAC;QAChC,MAAM;QACN,SAAS;QACT,QAAQ,EAAE,IAAI,EAAE,+BAA+B;QAC/C,GAAG,CAAC,MAAM,KAAK,iBAAiB,IAAI,IAAI,CAAC,KAAK,KAAK,SAAS;YAC1D,CAAC,CAAC,EAAE,WAAW,EAAE,IAAI,CAAC,KAAK,EAAE;YAC7B,CAAC,CAAC,EAAE,CAAC;KACR,CAAC,CAAC;IACH,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC;QACtB,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,EAAE,CAAC;IAChD,CAAC;IAED,MAAM,KAAK,GAAG,cAAc,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACvC,MAAM,cAAc,GAAG,mBAAmB,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC;IAC3E,MAAM,GAAG,GAAG,aAAa,CAAC;QACxB,KAAK;QACL,WAAW;QACX,GAAG,CAAC,IAAI,CAAC,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KACvE,CAAC,CAAC;IAEH,MAAM,YAAY,GAChB,gCAAgC,IAAI,CAAC,SAAS,YAAY,MAAM,KAAK;QACrE,mEAAmE;QACnE,cAAc,cAAc,IAAI;QAChC,mDAAmD;QACnD,cAAc,GAAG,IAAI;QACrB,0EAA0E,CAAC;IAE7E,OAAO;QACL,EAAE,EAAE,IAAI;QACR,OAAO,EAAE,cAAc;QACvB,cAAc;QACd,GAAG;QACH,YAAY;KACb,CAAC;AACJ,CAAC"}
@@ -0,0 +1,179 @@
1
+ /**
2
+ * WP10 — handler for h2a `conductor-launch-request` envelopes (PURE core).
3
+ *
4
+ * The h2a maintainer (a2a-cli, h2a 0.68.0) owns the EMIT side: when a workspace
5
+ * has STALLED work AND no live conductor, h2a drops an envelope into `remote`'s
6
+ * h2a inbox. h2a NEVER spawns — `remote` is the executor. This module is the
7
+ * PURE decision core (parse + validate + select host + cooldown gate + task
8
+ * builder); the side-effecting wiring (PATH detection, registry/h2a probes,
9
+ * launch, inbox marking) lives in index.ts behind injectable seams.
10
+ *
11
+ * The on-disk envelope mirrors the standard h2a shape `{protocol, version, id,
12
+ * type, actor, to, body, createdAt}` (h2a-jobs.ts / h2a-bridge.ts README). The
13
+ * WP10 contract puts the payload on `body`:
14
+ * body.kind = "message"
15
+ * body.topic = "conductor-launch-request"
16
+ * body.request = { kind, workspaceId, hostPref, stalled[], reason }
17
+ * (we also tolerate the request fields spread directly onto `body` rather than
18
+ * nested under `body.request`, since the maintainer's exact nesting is not yet
19
+ * pinned — flagged for a2a-cli alignment).
20
+ *
21
+ * SECURITY: the conductor task is plain prose passed as a SINGLE argv token by
22
+ * the caller (buildDelegateArgs → startJob); it is NEVER concatenated into a
23
+ * `bash -lc` string. Nothing here shells out.
24
+ */
25
+ import type { DelegateType } from "./delegate.js";
26
+ /** The contract topic the maintainer emits under. */
27
+ export declare const CONDUCTOR_LAUNCH_TOPIC = "conductor-launch-request";
28
+ /**
29
+ * Default host preference order when the envelope omits one / lists only
30
+ * unknown hosts. Mirrors the maintainer's documented default
31
+ * (`['claude','codex','agy']`).
32
+ */
33
+ export declare const DEFAULT_HOST_PREF: ReadonlyArray<DelegateType>;
34
+ /** A stalled work item the conductor should pick up (best-effort fields). */
35
+ export type StalledItem = {
36
+ id: string;
37
+ title: string;
38
+ reason?: string;
39
+ since?: string;
40
+ };
41
+ /** The typed, validated payload of a `conductor-launch-request` envelope. */
42
+ export type ConductorLaunchRequest = {
43
+ kind: "conductor-launch-request";
44
+ /** Durable git-shared id: `ws:<hex>` (matchable via computeDurableWorkspaceId). */
45
+ workspaceId: string;
46
+ /** Ordered host preference (claude/codex/agy), normalized + filtered to known hosts. */
47
+ hostPref: DelegateType[];
48
+ stalled: StalledItem[];
49
+ reason: string;
50
+ };
51
+ /**
52
+ * Parse + validate an incoming `conductor-launch-request` envelope (a JSON
53
+ * string OR an already-parsed object) into a typed `ConductorLaunchRequest`.
54
+ * Returns undefined when the input is not a valid conductor-launch envelope:
55
+ * - not JSON / not an object,
56
+ * - body.kind !== "message" or body.topic !== "conductor-launch-request",
57
+ * - no workspaceId.
58
+ * Tolerates the request nested under `body.request` OR spread onto `body`.
59
+ * Pure (no fs / no clock), exported for tests.
60
+ */
61
+ export declare function parseConductorLaunchEnvelope(input: string | unknown): ConductorLaunchRequest | undefined;
62
+ /**
63
+ * Pick the host to launch: the FIRST entry of `hostPref` that is in
64
+ * `availableHosts` (the CLIs found on PATH). Honors the preference ORDER, not
65
+ * the set's. Returns undefined when none of the preferred hosts is available.
66
+ * Pure, exported for tests.
67
+ */
68
+ export declare function selectHost(hostPref: ReadonlyArray<DelegateType>, availableHosts: ReadonlySet<DelegateType>): DelegateType | undefined;
69
+ export type ShouldLaunchInput = {
70
+ request: ConductorLaunchRequest;
71
+ /** How many conductors we already know to be alive for this workspace (registry + h2a). */
72
+ liveConductors: number;
73
+ /** Epoch ms of the last launch for THIS workspace, or undefined when none. */
74
+ lastLaunchAt: number | undefined;
75
+ now: number;
76
+ cooldownMs: number;
77
+ };
78
+ export type ShouldLaunchResult = {
79
+ launch: boolean;
80
+ reason: string;
81
+ };
82
+ /**
83
+ * The launch gate, in priority order (each branch is mutually exclusive):
84
+ * 1. a conductor is already alive → SKIP (idempotency, the whole point),
85
+ * 2. there is no stalled work → SKIP (nothing to conduct),
86
+ * 3. a launch happened within the cooldown window → SKIP (watch-loop guard),
87
+ * 4. otherwise → LAUNCH.
88
+ * The live-conductor check wins over the cooldown so an idempotent skip is
89
+ * always reported as such. Pure (clock injected via `now`), exported for tests.
90
+ */
91
+ export declare function shouldLaunch(input: ShouldLaunchInput): ShouldLaunchResult;
92
+ /**
93
+ * The task prompt for the delegated conductor. It instructs the agent to CLAIM
94
+ * the conductor role at boot (`h2a conductor claim`, if available) then conduct
95
+ * the stalled items. Returned as plain prose — the caller passes it as a SINGLE
96
+ * argv token (buildDelegateArgs → startJob); it is NEVER shell-concatenated.
97
+ * Pure, exported for tests.
98
+ */
99
+ export declare function buildConductorTask(request: ConductorLaunchRequest): string;
100
+ /**
101
+ * Normalize the root-commit set into the canonical string a2a-cli/track hash:
102
+ * ALL root commits (`git rev-list --max-parents=0 HEAD`), trimmed, de-duped,
103
+ * sorted ascending, joined by ",". A mono-root repo collapses to its single
104
+ * SHA. Invariant across clone / fork / path / machine (unlike a remote url).
105
+ * Pure, exported for tests.
106
+ */
107
+ export declare function normalizeRootCommits(shas: ReadonlyArray<string>): string;
108
+ /**
109
+ * Durable, git-shared workspace id — byte-identical to track + h2a 0.68's
110
+ * `durableWorkspaceId`:
111
+ *
112
+ * workspaceId = "ws:" + sha256hex( rootCommitSHA + "\n" + worktreeRelPath )
113
+ *
114
+ * where `rootCommitSHA` is {@link normalizeRootCommits}' output and
115
+ * `worktreeRelPath` is "" for the primary worktree, else the basename of
116
+ * `git rev-parse --git-dir` (the `.git/worktrees/<name>` dir) for a linked
117
+ * worktree. Pinned vectors (shared with track): ("abc","") →
118
+ * ws:edeaaff3… ; ("abc","my-feature") → ws:81a25e53…. Pure, exported for tests.
119
+ */
120
+ export declare function computeDurableWorkspaceId(rootCommitSHA: string, worktreeRelPath: string): string;
121
+ /**
122
+ * Which delegate hosts (claude/codex/agy) are resolvable on PATH. The `which`
123
+ * seam is injectable; the default uses a login shell `command -v` (same probe
124
+ * as tmux.ts commandAvailable / delegate.ts defaultWhich), so it sees the same
125
+ * binaries the tmux windows would. Best-effort: a failing probe = not present.
126
+ */
127
+ export declare function detectAvailableHosts(which?: (bin: string) => boolean): Set<DelegateType>;
128
+ /**
129
+ * Thin seam over a live `h2a` call: returns the raw stdout, or undefined when
130
+ * the `h2a` binary is missing / errors (GRACEFUL DEGRADE — the caller treats an
131
+ * undefined result as "can't tell from h2a", falling back to our own registry).
132
+ * The runner is injectable so tests never shell out. Best-effort, never throws.
133
+ */
134
+ export type H2aRunner = (args: ReadonlyArray<string>) => string | undefined;
135
+ export declare function defaultH2aRunner(args: ReadonlyArray<string>): string | undefined;
136
+ /**
137
+ * Does h2a itself report a live conductor for `workspaceId`? Best-effort over
138
+ * `h2a discover` (whatever shape it prints — we only look for the durable id +
139
+ * a "conductor" mention near it). Returns:
140
+ * - true → h2a sees a conductor (definitely skip),
141
+ * - false → h2a ran and did NOT mention one,
142
+ * - undefined → h2a unavailable / unparseable (caller relies on the registry).
143
+ * Conservative substring match (the maintainer's discover output is not pinned
144
+ * — flagged for a2a-cli alignment). The runner is injectable.
145
+ */
146
+ export declare function h2aReportsLiveConductor(workspaceId: string, run?: H2aRunner): boolean | undefined;
147
+ export type LaunchEnvelopeFile = {
148
+ /** Absolute path of the envelope file. */
149
+ path: string;
150
+ /** mtime (epoch ms) — used to pick the FRESHEST unprocessed envelope. */
151
+ mtimeMs: number;
152
+ request: ConductorLaunchRequest;
153
+ };
154
+ /**
155
+ * Read every `conductor-launch-request` envelope under `<localRoot>/inbox/**`
156
+ * (one dir level deep, the h2a layout — same as h2a-jobs.readInboxEnvelopes),
157
+ * parsed + validated. Skips already-processed ones (a sibling `.processed`
158
+ * stamp, see markProcessed). Missing store → []. Never throws on a bad file.
159
+ * The fs is isolated here so the parsing above stays pure.
160
+ */
161
+ export declare function readLaunchEnvelopes(localRoot?: string): LaunchEnvelopeFile[];
162
+ /** The freshest (highest mtime) unprocessed launch envelope, or undefined. Pure. */
163
+ export declare function freshestLaunchEnvelope(envelopes: ReadonlyArray<LaunchEnvelopeFile>): LaunchEnvelopeFile | undefined;
164
+ /**
165
+ * Idempotently mark an envelope processed by dropping a sibling `.processed`
166
+ * stamp next to it (we never DELETE the envelope — the bridge/h2a own cleanup,
167
+ * exactly like dropEnvelope's non-destructive contract). Best-effort: returns
168
+ * false on any fs error. `note` is a short human reason (dry-run vs launched).
169
+ */
170
+ export declare function markLaunchEnvelopeProcessed(envelopePath: string, note: string, nowMs?: number): boolean;
171
+ /** Read the last-launch epoch ms for `workspaceId`, or undefined. Best-effort. */
172
+ export declare function readLastLaunchAt(workspaceId: string, localRoot?: string): number | undefined;
173
+ /**
174
+ * Record `nowMs` as the last launch for `workspaceId` (so a watch loop honors
175
+ * the per-workspace cooldown). Best-effort: returns false on any fs error.
176
+ * Atomic-ish (tmp + rename) like the registry.
177
+ */
178
+ export declare function recordLaunchAt(workspaceId: string, nowMs?: number, localRoot?: string): boolean;
179
+ //# sourceMappingURL=conductor-launch.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"conductor-launch.d.ts","sourceRoot":"","sources":["../src/conductor-launch.ts"],"names":[],"mappings":"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"}