@sentropic/h2a-runtime 0.98.1 → 0.98.3

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 (130) hide show
  1. package/dist/agent-launch-args.d.ts +1 -1
  2. package/dist/agent-launch-args.d.ts.map +1 -1
  3. package/dist/agent-launch-args.js +16 -1
  4. package/dist/agent-launch-args.js.map +1 -1
  5. package/dist/auth-bundle.d.ts.map +1 -1
  6. package/dist/auth-bundle.js +1 -0
  7. package/dist/auth-bundle.js.map +1 -1
  8. package/dist/cli-help-groups.d.ts.map +1 -1
  9. package/dist/cli-help-groups.js +1 -0
  10. package/dist/cli-help-groups.js.map +1 -1
  11. package/dist/delegate.d.ts.map +1 -1
  12. package/dist/delegate.js +14 -2
  13. package/dist/delegate.js.map +1 -1
  14. package/dist/gateway-host/config-file.d.ts +19 -0
  15. package/dist/gateway-host/config-file.d.ts.map +1 -0
  16. package/dist/gateway-host/config-file.js +54 -0
  17. package/dist/gateway-host/config-file.js.map +1 -0
  18. package/dist/gateway-host/daemon.d.ts +61 -0
  19. package/dist/gateway-host/daemon.d.ts.map +1 -0
  20. package/dist/gateway-host/daemon.js +274 -0
  21. package/dist/gateway-host/daemon.js.map +1 -0
  22. package/dist/gateway-host/host.d.ts +34 -0
  23. package/dist/gateway-host/host.d.ts.map +1 -0
  24. package/dist/gateway-host/host.js +228 -0
  25. package/dist/gateway-host/host.js.map +1 -0
  26. package/dist/{llm-gateway-runtime/session-ledger.d.ts → gateway-host/ledger.d.ts} +4 -4
  27. package/dist/gateway-host/ledger.d.ts.map +1 -0
  28. package/dist/{llm-gateway-runtime/session-ledger.js → gateway-host/ledger.js} +1 -1
  29. package/dist/gateway-host/ledger.js.map +1 -0
  30. package/dist/{llm-gateway-runtime/sticky.d.ts → gateway-host/sessions.d.ts} +3 -1
  31. package/dist/gateway-host/sessions.d.ts.map +1 -0
  32. package/dist/{llm-gateway-runtime/sticky.js → gateway-host/sessions.js} +6 -1
  33. package/dist/gateway-host/sessions.js.map +1 -0
  34. package/dist/index.d.ts.map +1 -1
  35. package/dist/index.js +38 -18
  36. package/dist/index.js.map +1 -1
  37. package/dist/llm-mesh-accounts.d.ts +55 -0
  38. package/dist/llm-mesh-accounts.d.ts.map +1 -0
  39. package/dist/llm-mesh-accounts.js +188 -0
  40. package/dist/llm-mesh-accounts.js.map +1 -0
  41. package/dist/native-host.d.ts +1 -1
  42. package/dist/native-host.d.ts.map +1 -1
  43. package/dist/native-host.js +84 -21
  44. package/dist/native-host.js.map +1 -1
  45. package/dist/native-terminal/attach-recovery.d.ts +9 -0
  46. package/dist/native-terminal/attach-recovery.d.ts.map +1 -0
  47. package/dist/native-terminal/attach-recovery.js +54 -0
  48. package/dist/native-terminal/attach-recovery.js.map +1 -0
  49. package/dist/native-terminal/fleet.d.ts +2 -1
  50. package/dist/native-terminal/fleet.d.ts.map +1 -1
  51. package/dist/native-terminal/fleet.js +10 -1
  52. package/dist/native-terminal/fleet.js.map +1 -1
  53. package/dist/native-terminal/host.d.ts +1 -0
  54. package/dist/native-terminal/host.d.ts.map +1 -1
  55. package/dist/native-terminal/host.js +5 -2
  56. package/dist/native-terminal/host.js.map +1 -1
  57. package/dist/native-terminal/journal.d.ts +48 -0
  58. package/dist/native-terminal/journal.d.ts.map +1 -0
  59. package/dist/native-terminal/journal.js +305 -0
  60. package/dist/native-terminal/journal.js.map +1 -0
  61. package/dist/native-terminal/op.d.ts +3 -0
  62. package/dist/native-terminal/op.d.ts.map +1 -1
  63. package/dist/native-terminal/op.js +148 -33
  64. package/dist/native-terminal/op.js.map +1 -1
  65. package/dist/native-terminal/process.d.ts.map +1 -1
  66. package/dist/native-terminal/process.js +134 -46
  67. package/dist/native-terminal/process.js.map +1 -1
  68. package/dist/native-terminal/replay-buffer.d.ts +3 -0
  69. package/dist/native-terminal/replay-buffer.d.ts.map +1 -1
  70. package/dist/native-terminal/replay-buffer.js +11 -0
  71. package/dist/native-terminal/replay-buffer.js.map +1 -1
  72. package/dist/native-terminal/reset-relay.d.ts +11 -0
  73. package/dist/native-terminal/reset-relay.d.ts.map +1 -0
  74. package/dist/native-terminal/reset-relay.js +38 -0
  75. package/dist/native-terminal/reset-relay.js.map +1 -0
  76. package/dist/native-terminal/server.d.ts +8 -0
  77. package/dist/native-terminal/server.d.ts.map +1 -1
  78. package/dist/native-terminal/server.js +535 -58
  79. package/dist/native-terminal/server.js.map +1 -1
  80. package/dist/native-terminal/terminal-modes.d.ts +15 -0
  81. package/dist/native-terminal/terminal-modes.d.ts.map +1 -0
  82. package/dist/native-terminal/terminal-modes.js +180 -0
  83. package/dist/native-terminal/terminal-modes.js.map +1 -0
  84. package/dist/profile-menu.d.ts.map +1 -1
  85. package/dist/profile-menu.js +2 -0
  86. package/dist/profile-menu.js.map +1 -1
  87. package/dist/profiles.d.ts +2 -0
  88. package/dist/profiles.d.ts.map +1 -1
  89. package/dist/profiles.js +6 -0
  90. package/dist/profiles.js.map +1 -1
  91. package/dist/protocol-local.d.ts +1 -1
  92. package/dist/protocol-local.d.ts.map +1 -1
  93. package/dist/protocol-local.js +1 -0
  94. package/dist/protocol-local.js.map +1 -1
  95. package/dist/registry.d.ts +1 -1
  96. package/dist/registry.d.ts.map +1 -1
  97. package/dist/registry.js +4 -1
  98. package/dist/registry.js.map +1 -1
  99. package/dist/restore.d.ts +1 -1
  100. package/dist/restore.d.ts.map +1 -1
  101. package/dist/{llm-routing-config.d.ts → routing-preferences.d.ts} +2 -2
  102. package/dist/routing-preferences.d.ts.map +1 -0
  103. package/dist/{llm-routing-config.js → routing-preferences.js} +16 -13
  104. package/dist/routing-preferences.js.map +1 -0
  105. package/dist/sentropic/auth-token.d.ts +1 -1
  106. package/dist/sentropic/auth-token.js +1 -1
  107. package/dist/status-projection.d.ts +1 -1
  108. package/dist/status-projection.d.ts.map +1 -1
  109. package/dist/throttle-signatures.d.ts.map +1 -1
  110. package/dist/throttle-signatures.js +3 -0
  111. package/dist/throttle-signatures.js.map +1 -1
  112. package/dist/tmux.d.ts +17 -1
  113. package/dist/tmux.d.ts.map +1 -1
  114. package/dist/tmux.js +10 -4
  115. package/dist/tmux.js.map +1 -1
  116. package/package.json +8 -4
  117. package/dist/llm-gateway-runtime/index.d.ts +0 -10
  118. package/dist/llm-gateway-runtime/index.d.ts.map +0 -1
  119. package/dist/llm-gateway-runtime/index.js +0 -147
  120. package/dist/llm-gateway-runtime/index.js.map +0 -1
  121. package/dist/llm-gateway-runtime/session-ledger.d.ts.map +0 -1
  122. package/dist/llm-gateway-runtime/session-ledger.js.map +0 -1
  123. package/dist/llm-gateway-runtime/sticky.d.ts.map +0 -1
  124. package/dist/llm-gateway-runtime/sticky.js.map +0 -1
  125. package/dist/llm-mesh.d.ts +0 -154
  126. package/dist/llm-mesh.d.ts.map +0 -1
  127. package/dist/llm-mesh.js +0 -490
  128. package/dist/llm-mesh.js.map +0 -1
  129. package/dist/llm-routing-config.d.ts.map +0 -1
  130. package/dist/llm-routing-config.js.map +0 -1
@@ -1,154 +0,0 @@
1
- /**
2
- * llm-mesh — local LLM gateway management for solo-dev mode.
3
- *
4
- * Enrollment: `h2a llm-mesh account enroll cloud-code|codex` delegates OAuth and
5
- * account persistence entirely to the sentropic-owned facade.
6
- *
7
- * Startup: `h2a llm-mesh start` reads public host config and starts the
8
- * embedded gateway runtime as a background process. Callers acquire an
9
- * opaque process-local bearer without printing it.
10
- *
11
- * Config path: ~/.sentropic/llm-mesh.json (0600, public metadata only)
12
- * PID file: ~/.sentropic/llm-mesh.pid
13
- * Runtime file: ~/.sentropic/llm-mesh-token.json (0600, base URL + PID only)
14
- */
15
- import { type LlmMeshAdministrativeFacade, type LlmMeshFacade } from "@sentropic/llm-mesh/facade";
16
- import type { AccountPublic } from "@sentropic/llm-mesh/enrollment";
17
- import { type LlmMeshRoutingConfig } from "./llm-routing-config.js";
18
- declare const ANTHROPIC_GATEWAY_ENV_KEYS: readonly ["ANTHROPIC_BASE_URL", "ANTHROPIC_AUTH_TOKEN", "ANTHROPIC_API_KEY"];
19
- /**
20
- * Temporarily replace the H2A gateway lane and return an exact restorer.
21
- * Direct launches preserve a user-owned ANTHROPIC_API_KEY. Gateway launches
22
- * hide it from Claude Code because the local gateway authenticates with the
23
- * opaque AUTH_TOKEN lane instead.
24
- */
25
- export declare function replaceAnthropicGatewayEnvironment(env: NodeJS.ProcessEnv, replacement?: Partial<Record<(typeof ANTHROPIC_GATEWAY_ENV_KEYS)[number], string>>): () => void;
26
- export interface LlmMeshConfig {
27
- /** Deprecated migration sinks. Never returned or persisted. */
28
- accounts?: readonly unknown[];
29
- meshAccounts?: readonly unknown[];
30
- /** Local port for the gateway. Default: 3002 */
31
- port?: number;
32
- /** Log file path (stdout+stderr of the gateway process). Default: ~/.sentropic/llm-mesh.log */
33
- logFile?: string;
34
- /** Public host routing policy. Provider/model knowledge remains in llm-mesh. */
35
- routing?: LlmMeshRoutingConfig;
36
- }
37
- export interface LlmMeshEnrollmentAccount {
38
- accountId: string;
39
- provider: "cloud-code" | "codex" | "muse" | "muse-code";
40
- label: string;
41
- }
42
- /**
43
- * Structural extension for facades that implement Muse CLI-store import
44
- * (MuseEnrollmentProvider mesh-side, BR75). Declared structurally — not taken
45
- * from @sentropic/llm-mesh types — so h2a keeps working against older
46
- * facades; the runtime guard below fails closed when the method is absent
47
- * instead of throwing a bare TypeError.
48
- */
49
- export interface LlmMeshFacadeWithMuseImport extends LlmMeshFacade {
50
- completeMuseImport(enrollmentId: string, code: string, ownerScopeRef: string): Promise<{
51
- accountId: string;
52
- label: string;
53
- }>;
54
- completeMuseDeviceImport(enrollmentId: string, ownerScopeRef: string, maxAttempts?: number): Promise<{
55
- accountId: string;
56
- label: string;
57
- }>;
58
- }
59
- export interface FacadeEnrollmentOptions {
60
- configRef?: string;
61
- ownerScope?: string;
62
- redirectUri?: string;
63
- /** Injection seam for CLI tests; production uses the opaque facade. */
64
- facade?: LlmMeshFacade;
65
- /** Injection seam that keeps enrollment tests from opening a real browser. */
66
- openBrowser?: (url: string) => void;
67
- }
68
- export interface FacadeAccountOptions {
69
- ownerScope?: string;
70
- /** Injection seam for account-administration tests. */
71
- facade?: Pick<LlmMeshAdministrativeFacade, "listAccounts" | "removeAccount">;
72
- }
73
- export declare function createCliLlmMeshFacade(): LlmMeshAdministrativeFacade;
74
- /** Stable local owner used both at enrollment and by gateway-authenticated routing. */
75
- export declare function llmMeshOwnerScopeRef(): string;
76
- /**
77
- * Enroll through the sentropic-owned OAuth state machine. H2A never receives
78
- * an authorization code or a provider token. Account records remain owned by
79
- * the facade/keyring and are not copied into h2a config.
80
- */
81
- export declare function enrollViaFacade(provider: "cloud-code" | "codex" | "muse" | "muse-code", options?: FacadeEnrollmentOptions): Promise<LlmMeshEnrollmentAccount>;
82
- export declare function listAccountsViaFacade(options?: FacadeAccountOptions): Promise<readonly AccountPublic[]>;
83
- export declare function removeAccountViaFacade(accountId: string, options?: FacadeAccountOptions): Promise<{
84
- accountId: string;
85
- removed: true;
86
- }>;
87
- export declare function formatLlmMeshAccountList(accounts: readonly AccountPublic[], json: boolean): string;
88
- export declare function formatLlmMeshAccountError(error: unknown, fallback: "account inventory unavailable" | "account removal failed"): string;
89
- export declare class LlmMeshManager {
90
- GetActiveConfig(dir?: string): LlmMeshConfig | null;
91
- SaveConfig(config: LlmMeshConfig, dir?: string): void;
92
- StartGateway(config: LlmMeshConfig, opts?: StartGatewayOptions): Promise<StartResult>;
93
- StopGateway(dir?: string): {
94
- stopped: boolean;
95
- pid?: number;
96
- };
97
- ResolveSession(dir?: string): Promise<Record<string, string> | null>;
98
- }
99
- export declare function sentropicDir(): string;
100
- export declare function llmMeshConfigPath(dir?: string): string;
101
- export declare function llmMeshPidPath(dir?: string): string;
102
- export declare function llmMeshTokenPath(dir?: string): string;
103
- export declare function llmMeshLogPath(config?: LlmMeshConfig, dir?: string): string;
104
- export declare function readLlmMeshConfig(dir?: string): LlmMeshConfig | null;
105
- export declare function writeLlmMeshConfig(config: LlmMeshConfig, dir?: string): void;
106
- export declare function updateLlmMeshRoutingConfig(routing: LlmMeshRoutingConfig | undefined, dir?: string): LlmMeshConfig;
107
- /** Resolve the embedded gateway runtime entry point relative to this package. */
108
- export declare function gatewayScriptPath(): string;
109
- export interface StartResult {
110
- pid: number;
111
- port: number;
112
- gatewayToken: string;
113
- }
114
- export interface StartGatewayOptions {
115
- readonly verbose?: boolean | undefined;
116
- readonly clientSessionId?: string | undefined;
117
- /**
118
- * Private runtime state root for the PID, session metadata, and gateway log.
119
- * The public routing configuration and the Sentropic-owned credential facade
120
- * remain at their normal locations, so an isolated probe can use enrolled
121
- * accounts without taking over the user's live gateway state.
122
- */
123
- readonly stateDir?: string | undefined;
124
- }
125
- /**
126
- * A gateway session is an account-affinity boundary, so a local CLI session
127
- * must never inherit a process-wide static identifier. Callers provide the
128
- * stable tmux/conversation identity when they have one; standalone gateway
129
- * management gets a fresh ephemeral identity instead.
130
- */
131
- export declare function gatewayClientSessionId(clientSessionId?: string): string;
132
- /**
133
- * Start the llm-gateway as a detached background process.
134
- * Returns the PID, port, and a gw-token for Claude Code.
135
- */
136
- export declare function startGateway(config: LlmMeshConfig, opts?: StartGatewayOptions): Promise<StartResult>;
137
- /** Read the running gateway's PID. Returns null if not running. */
138
- export declare function readGatewayPid(dir?: string): number | null;
139
- /**
140
- * Acquire a fresh in-memory gateway token from the running local gateway.
141
- * Gateway tokens are intentionally not durable. The runtime metadata file
142
- * contains only the base URL and PID; every caller reacquires its own bearer.
143
- */
144
- export declare function acquireLlmMeshSessionEnv(dir?: string, clientSessionId?: string): Promise<{
145
- ANTHROPIC_BASE_URL: string;
146
- ANTHROPIC_AUTH_TOKEN: string;
147
- } | null>;
148
- /** Stop the running gateway. */
149
- export declare function stopGateway(dir?: string): {
150
- stopped: boolean;
151
- pid?: number;
152
- };
153
- export {};
154
- //# sourceMappingURL=llm-mesh.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"llm-mesh.d.ts","sourceRoot":"","sources":["../src/llm-mesh.ts"],"names":[],"mappings":"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"}
package/dist/llm-mesh.js DELETED
@@ -1,490 +0,0 @@
1
- /**
2
- * llm-mesh — local LLM gateway management for solo-dev mode.
3
- *
4
- * Enrollment: `h2a llm-mesh account enroll cloud-code|codex` delegates OAuth and
5
- * account persistence entirely to the sentropic-owned facade.
6
- *
7
- * Startup: `h2a llm-mesh start` reads public host config and starts the
8
- * embedded gateway runtime as a background process. Callers acquire an
9
- * opaque process-local bearer without printing it.
10
- *
11
- * Config path: ~/.sentropic/llm-mesh.json (0600, public metadata only)
12
- * PID file: ~/.sentropic/llm-mesh.pid
13
- * Runtime file: ~/.sentropic/llm-mesh-token.json (0600, base URL + PID only)
14
- */
15
- import { chmodSync, existsSync, mkdirSync, readFileSync, renameSync, unlinkSync, writeFileSync, } from "node:fs";
16
- import { homedir, hostname } from "node:os";
17
- import { dirname, join } from "node:path";
18
- import { fileURLToPath } from "node:url";
19
- import { spawn } from "node:child_process";
20
- import { randomBytes } from "node:crypto";
21
- import { createLlmMeshFacade, } from "@sentropic/llm-mesh/facade";
22
- import { validateLlmMeshRoutingConfig, } from "./llm-routing-config.js";
23
- const ANTHROPIC_GATEWAY_ENV_KEYS = [
24
- "ANTHROPIC_BASE_URL",
25
- "ANTHROPIC_AUTH_TOKEN",
26
- "ANTHROPIC_API_KEY",
27
- ];
28
- /**
29
- * Temporarily replace the H2A gateway lane and return an exact restorer.
30
- * Direct launches preserve a user-owned ANTHROPIC_API_KEY. Gateway launches
31
- * hide it from Claude Code because the local gateway authenticates with the
32
- * opaque AUTH_TOKEN lane instead.
33
- */
34
- export function replaceAnthropicGatewayEnvironment(env, replacement) {
35
- const previous = new Map(ANTHROPIC_GATEWAY_ENV_KEYS.map((key) => [key, env[key]]));
36
- for (const key of ANTHROPIC_GATEWAY_ENV_KEYS) {
37
- if (key !== "ANTHROPIC_API_KEY" || replacement !== undefined) {
38
- delete env[key];
39
- }
40
- }
41
- for (const [key, value] of Object.entries(replacement ?? {})) {
42
- if (value !== undefined)
43
- env[key] = value;
44
- }
45
- return () => {
46
- for (const [key, value] of previous) {
47
- if (value === undefined)
48
- delete env[key];
49
- else
50
- env[key] = value;
51
- }
52
- };
53
- }
54
- function facadeConfigResolver() {
55
- return {
56
- async resolveConfig(configRef) {
57
- const raw = process.env.H2A_LLM_MESH_CONFIG_JSON;
58
- if (!raw)
59
- return {};
60
- try {
61
- const parsed = JSON.parse(raw);
62
- const scoped = parsed[configRef];
63
- return scoped && typeof scoped === "object" && !Array.isArray(scoped)
64
- ? scoped
65
- : parsed;
66
- }
67
- catch {
68
- return {};
69
- }
70
- },
71
- };
72
- }
73
- export function createCliLlmMeshFacade() {
74
- return createLlmMeshFacade({
75
- configResolver: facadeConfigResolver(),
76
- mode: "cli",
77
- legacyAccountOwnerScopeRef: llmMeshOwnerScopeRef(),
78
- });
79
- }
80
- /** Stable local owner used both at enrollment and by gateway-authenticated routing. */
81
- export function llmMeshOwnerScopeRef() {
82
- return process.env.H2A_LLM_MESH_OWNER_SCOPE?.trim() || `cli:${hostname()}`;
83
- }
84
- function openEnrollmentBrowser(url) {
85
- const command = process.platform === "darwin"
86
- ? "open"
87
- : process.platform === "win32"
88
- ? "cmd"
89
- : "xdg-open";
90
- const args = process.platform === "win32" ? ["/c", "start", "", url] : [url];
91
- try {
92
- const child = spawn(command, args, { detached: true, stdio: "ignore" });
93
- child.unref();
94
- }
95
- catch {
96
- // The URL is always printed, so a headless CLI can continue manually.
97
- }
98
- }
99
- /**
100
- * Enroll through the sentropic-owned OAuth state machine. H2A never receives
101
- * an authorization code or a provider token. Account records remain owned by
102
- * the facade/keyring and are not copied into h2a config.
103
- */
104
- export async function enrollViaFacade(provider, options = {}) {
105
- const facade = options.facade ?? createCliLlmMeshFacade();
106
- const ownerScope = options.ownerScope ?? llmMeshOwnerScopeRef();
107
- // The installed @sentropic/llm-mesh types predate the muse provider, but
108
- // enroll passes the id through opaquely — a muse-capable facade resolves
109
- // it, an older one fails with its own unknown-provider error. Cast is
110
- // load-bearing until the dep bump, not a lie about the contract.
111
- const session = await facade.enroll(provider, {
112
- configRef: options.configRef ?? process.env.H2A_LLM_MESH_CONFIG_REF ?? "default",
113
- mode: "cli",
114
- redirectUri: options.redirectUri ?? "http://127.0.0.1",
115
- ownerScope,
116
- });
117
- if (provider === "muse") {
118
- // Muse CLI-store import (BR75): no browser or device round-trip — the
119
- // owner act was the muse login itself. The ownerScope binds the enrolling
120
- // owner explicitly (never inferred); it doubles as the completion code
121
- // the mesh provider carries but does not validate.
122
- // Installed mesh types predate the local-import kind (same load-bearing
123
- // cast pattern as the enroll call above); runtime shape verified live.
124
- const museSession = session;
125
- if (museSession.kind !== "local-import") {
126
- throw new Error("Muse enrollment did not return a local-import session");
127
- }
128
- const completeMuseImport = facade.completeMuseImport;
129
- if (typeof completeMuseImport !== "function") {
130
- throw new Error("Muse enrollment needs facade.completeMuseImport — upgrade @sentropic/llm-mesh " +
131
- "to a version with the Muse enrollment provider");
132
- }
133
- process.stdout.write(`[h2a] llm-mesh: importing Muse CLI credentials from ${museSession.source} for ${ownerScope}\n`);
134
- const completed = await completeMuseImport.call(facade, museSession.enrollmentId, ownerScope, ownerScope);
135
- return { accountId: completed.accountId, provider, label: completed.label };
136
- }
137
- if (provider === "muse-code") {
138
- // Native Meta device flow (RFC 8628, MuseCodeEnrollmentProvider
139
- // mesh-side): print the user code + verification URL, then complete via
140
- // the muse-specific device import — NOT the generic pollForCompletion,
141
- // which the mesh service hard-wires to the codex provider.
142
- const deviceSession = session;
143
- if (deviceSession.kind !== "device-code") {
144
- throw new Error("Muse device-flow enrollment did not return a device code");
145
- }
146
- const completeMuseDeviceImport = facade.completeMuseDeviceImport;
147
- if (typeof completeMuseDeviceImport !== "function") {
148
- throw new Error("Muse device-flow enrollment needs facade.completeMuseDeviceImport — upgrade @sentropic/llm-mesh " +
149
- "to a version with the muse-code enrollment provider");
150
- }
151
- process.stdout.write(`[h2a] llm-mesh: enter code ${deviceSession.userCode} at ${deviceSession.verificationUrl}\n`);
152
- const completed = await completeMuseDeviceImport.call(facade, deviceSession.enrollmentId, ownerScope);
153
- return { accountId: completed.accountId, provider, label: completed.label };
154
- }
155
- const completed = provider === "cloud-code"
156
- ? await (async () => {
157
- if (session.kind !== "authorization-url") {
158
- throw new Error("Cloud Code enrollment did not return an authorization URL");
159
- }
160
- process.stdout.write(`[h2a] llm-mesh: open ${session.url}\n`);
161
- (options.openBrowser ?? openEnrollmentBrowser)(session.url);
162
- return facade.waitForCallback(session.enrollmentId);
163
- })()
164
- : await (async () => {
165
- if (session.kind !== "device-code") {
166
- throw new Error("Codex enrollment did not return a device code");
167
- }
168
- process.stdout.write(`[h2a] llm-mesh: enter code ${session.userCode} at ${session.verificationUrl}\n`);
169
- return facade.pollForCompletion(session.enrollmentId);
170
- })();
171
- return { accountId: completed.accountId, provider, label: completed.label };
172
- }
173
- export async function listAccountsViaFacade(options = {}) {
174
- const facade = options.facade ?? createCliLlmMeshFacade();
175
- return facade.listAccounts({
176
- ownerScope: options.ownerScope ?? llmMeshOwnerScopeRef(),
177
- });
178
- }
179
- export async function removeAccountViaFacade(accountId, options = {}) {
180
- const facade = options.facade ?? createCliLlmMeshFacade();
181
- return facade.removeAccount(accountId, {
182
- ownerScope: options.ownerScope ?? llmMeshOwnerScopeRef(),
183
- });
184
- }
185
- function publicAccountProjection(account) {
186
- return {
187
- accountId: account.accountId,
188
- ...(account.accountLabel ? { accountLabel: account.accountLabel } : {}),
189
- providerId: account.providerId,
190
- status: account.status,
191
- createdAt: account.createdAt,
192
- updatedAt: account.updatedAt,
193
- };
194
- }
195
- export function formatLlmMeshAccountList(accounts, json) {
196
- const publicAccounts = accounts.map(publicAccountProjection);
197
- if (json)
198
- return JSON.stringify(publicAccounts, null, 2);
199
- if (publicAccounts.length === 0) {
200
- return "[h2a] llm-mesh account: no accounts enrolled";
201
- }
202
- const rows = publicAccounts.map((account) => [
203
- account.accountId,
204
- account.providerId,
205
- account.accountLabel ?? "-",
206
- account.status,
207
- account.createdAt,
208
- ]);
209
- const headers = ["ID", "PROVIDER", "LABEL", "STATUS", "ENROLLED"];
210
- const widths = headers.map((header, index) => Math.max(header.length, ...rows.map((row) => row[index]?.length ?? 0)));
211
- return [headers, ...rows]
212
- .map((row) => row.map((value, index) => value.padEnd(widths[index] ?? value.length)).join(" ").trimEnd())
213
- .join("\n");
214
- }
215
- const SAFE_ACCOUNT_NOT_FOUND = /^Account '[A-Za-z0-9][A-Za-z0-9._:-]{0,127}' not found$/;
216
- export function formatLlmMeshAccountError(error, fallback) {
217
- const message = error instanceof Error ? error.message : String(error);
218
- return SAFE_ACCOUNT_NOT_FOUND.test(message) ? message : fallback;
219
- }
220
- // ---------------------------------------------------------------------------
221
- // Capitalized LlmMeshManager API
222
- // ---------------------------------------------------------------------------
223
- export class LlmMeshManager {
224
- GetActiveConfig(dir) {
225
- return readLlmMeshConfig(dir);
226
- }
227
- SaveConfig(config, dir) {
228
- writeLlmMeshConfig(config, dir);
229
- }
230
- async StartGateway(config, opts = {}) {
231
- return startGateway(config, opts);
232
- }
233
- StopGateway(dir) {
234
- return stopGateway(dir);
235
- }
236
- async ResolveSession(dir) {
237
- return acquireLlmMeshSessionEnv(dir);
238
- }
239
- }
240
- // ---------------------------------------------------------------------------
241
- // Paths
242
- // ---------------------------------------------------------------------------
243
- export function sentropicDir() {
244
- return join(homedir(), ".sentropic");
245
- }
246
- export function llmMeshConfigPath(dir) {
247
- return join(dir ?? sentropicDir(), "llm-mesh.json");
248
- }
249
- export function llmMeshPidPath(dir) {
250
- return join(dir ?? sentropicDir(), "llm-mesh.pid");
251
- }
252
- export function llmMeshTokenPath(dir) {
253
- return join(dir ?? sentropicDir(), "llm-mesh-token.json");
254
- }
255
- export function llmMeshLogPath(config, dir) {
256
- return config?.logFile ?? join(dir ?? sentropicDir(), "llm-mesh.log");
257
- }
258
- // ---------------------------------------------------------------------------
259
- // Config read/write
260
- // ---------------------------------------------------------------------------
261
- function readJson(path) {
262
- try {
263
- return JSON.parse(readFileSync(path, "utf8"));
264
- }
265
- catch {
266
- return null;
267
- }
268
- }
269
- function writeSecret(path, value) {
270
- mkdirSync(dirname(path), { recursive: true });
271
- const tmp = `${path}.tmp.${process.pid}`;
272
- writeFileSync(tmp, JSON.stringify(value, null, 2) + "\n", { mode: 0o600 });
273
- chmodSync(tmp, 0o600);
274
- renameSync(tmp, path);
275
- }
276
- export function readLlmMeshConfig(dir) {
277
- const config = readJson(llmMeshConfigPath(dir));
278
- if (!config)
279
- return null;
280
- const { accounts: _legacyAccounts, meshAccounts: _legacyPublicIds, ...publicConfig } = config;
281
- return publicConfig;
282
- }
283
- export function writeLlmMeshConfig(config, dir) {
284
- // The facade/keyring own credentials. Keep only public enrollment metadata
285
- // in llm-mesh.json, including when migrating a pre-facade configuration.
286
- const { accounts: _legacyCredentialRecords, meshAccounts: _legacyPublicIds, ...publicConfig } = config;
287
- if (publicConfig.routing)
288
- validateLlmMeshRoutingConfig(publicConfig.routing);
289
- writeSecret(llmMeshConfigPath(dir), publicConfig);
290
- }
291
- export function updateLlmMeshRoutingConfig(routing, dir) {
292
- const config = readLlmMeshConfig(dir) ?? {};
293
- const next = routing
294
- ? { ...config, routing: validateLlmMeshRoutingConfig(routing) }
295
- : (() => {
296
- const copy = { ...config };
297
- delete copy.routing;
298
- return copy;
299
- })();
300
- writeLlmMeshConfig(next, dir);
301
- return next;
302
- }
303
- // ---------------------------------------------------------------------------
304
- // Gateway process management
305
- // ---------------------------------------------------------------------------
306
- /** Resolve the embedded gateway runtime entry point relative to this package. */
307
- export function gatewayScriptPath() {
308
- const thisFile = fileURLToPath(import.meta.url);
309
- return join(dirname(thisFile), "llm-gateway-runtime", "index.js");
310
- }
311
- /**
312
- * A gateway session is an account-affinity boundary, so a local CLI session
313
- * must never inherit a process-wide static identifier. Callers provide the
314
- * stable tmux/conversation identity when they have one; standalone gateway
315
- * management gets a fresh ephemeral identity instead.
316
- */
317
- export function gatewayClientSessionId(clientSessionId) {
318
- const supplied = clientSessionId?.trim();
319
- return supplied || `local-${randomBytes(16).toString("hex")}`;
320
- }
321
- /**
322
- * Start the llm-gateway as a detached background process.
323
- * Returns the PID, port, and a gw-token for Claude Code.
324
- */
325
- export async function startGateway(config, opts = {}) {
326
- const port = config.port ?? 3002;
327
- const stateDir = opts.stateDir;
328
- // An explicitly isolated state root must not inherit a live gateway's log.
329
- const logFile = stateDir ? llmMeshLogPath(undefined, stateDir) : llmMeshLogPath(config);
330
- const gatewayScript = gatewayScriptPath();
331
- if (!existsSync(gatewayScript)) {
332
- throw new Error(`Gateway script not found: ${gatewayScript}\n` +
333
- `Run \`npm run build -w @sentropic/remote-cli\` first.`);
334
- }
335
- mkdirSync(stateDir ?? sentropicDir(), { recursive: true });
336
- const gatewayEnv = {
337
- ...process.env,
338
- PORT: String(port),
339
- H2A_LLM_MESH_OWNER_SCOPE: llmMeshOwnerScopeRef(),
340
- ...(config.routing
341
- ? { H2A_LLM_MESH_ROUTING_JSON: JSON.stringify(config.routing) }
342
- : {}),
343
- };
344
- // Start detached, piping stdout+stderr to logFile
345
- const { openSync } = await import("node:fs");
346
- const logFd = openSync(logFile, "a");
347
- const child = spawn("node", [gatewayScript], {
348
- detached: true,
349
- stdio: ["ignore", logFd, logFd],
350
- env: gatewayEnv,
351
- });
352
- child.unref();
353
- const pid = child.pid;
354
- // Write PID file
355
- writeFileSync(llmMeshPidPath(stateDir), String(pid) + "\n");
356
- // Wait for the gateway to be ready
357
- const baseUrl = `http://localhost:${port}`;
358
- await waitForHealth(baseUrl, 10_000);
359
- // Acquire a session token
360
- const sessionResp = await fetch(`${baseUrl}/v1/session`, {
361
- method: "POST",
362
- headers: { "content-type": "application/json" },
363
- body: JSON.stringify({
364
- sessionId: gatewayClientSessionId(opts.clientSessionId),
365
- clientSessionId: opts.clientSessionId,
366
- workspaceId: process.cwd(),
367
- }),
368
- });
369
- if (!sessionResp.ok) {
370
- throw new Error(`Session acquisition failed: ${sessionResp.status}`);
371
- }
372
- const session = (await sessionResp.json());
373
- const gatewayToken = session.gatewayToken;
374
- if (!gatewayToken)
375
- throw new Error("No gatewayToken in session response");
376
- // Persist only process metadata. The opaque bearer remains process-local and
377
- // is reacquired for each caller affinity.
378
- writeSecret(llmMeshTokenPath(stateDir), {
379
- baseUrl,
380
- pid,
381
- });
382
- return { pid, port, gatewayToken };
383
- }
384
- async function waitForHealth(baseUrl, timeoutMs) {
385
- const deadline = Date.now() + timeoutMs;
386
- while (Date.now() < deadline) {
387
- try {
388
- const resp = await fetch(`${baseUrl}/health`);
389
- if (resp.ok)
390
- return;
391
- }
392
- catch {
393
- // not ready yet
394
- }
395
- await new Promise((r) => setTimeout(r, 200));
396
- }
397
- throw new Error(`Gateway did not become healthy within ${timeoutMs}ms`);
398
- }
399
- /** Read the running gateway's PID. Returns null if not running. */
400
- export function readGatewayPid(dir) {
401
- try {
402
- const raw = readFileSync(llmMeshPidPath(dir), "utf8").trim();
403
- const pid = parseInt(raw, 10);
404
- if (isNaN(pid))
405
- return null;
406
- // Check if the process is still alive
407
- process.kill(pid, 0);
408
- return pid;
409
- }
410
- catch {
411
- return null;
412
- }
413
- }
414
- function configuredGatewayBaseUrl(dir) {
415
- const config = readLlmMeshConfig(dir);
416
- if (!config)
417
- return null;
418
- return `http://localhost:${config.port ?? 3002}`;
419
- }
420
- /**
421
- * Acquire a fresh in-memory gateway token from the running local gateway.
422
- * Gateway tokens are intentionally not durable. The runtime metadata file
423
- * contains only the base URL and PID; every caller reacquires its own bearer.
424
- */
425
- export async function acquireLlmMeshSessionEnv(dir, clientSessionId) {
426
- try {
427
- let baseUrl;
428
- let pid;
429
- try {
430
- const raw = readFileSync(llmMeshTokenPath(dir), "utf8");
431
- const tokenFile = JSON.parse(raw);
432
- baseUrl = tokenFile.baseUrl;
433
- pid = tokenFile.pid;
434
- }
435
- catch {
436
- baseUrl = configuredGatewayBaseUrl(dir) ?? undefined;
437
- pid = readGatewayPid(dir) ?? undefined;
438
- }
439
- if (!baseUrl || !pid)
440
- return null;
441
- try {
442
- process.kill(pid, 0);
443
- }
444
- catch {
445
- return null;
446
- }
447
- const workspaceId = dir ?? process.cwd();
448
- const sessionResp = await fetch(`${baseUrl}/v1/session`, {
449
- method: "POST",
450
- headers: { "content-type": "application/json" },
451
- body: JSON.stringify({
452
- sessionId: gatewayClientSessionId(clientSessionId),
453
- clientSessionId,
454
- workspaceId,
455
- }),
456
- });
457
- if (!sessionResp.ok)
458
- return null;
459
- const session = (await sessionResp.json());
460
- if (!session.gatewayToken)
461
- return null;
462
- return {
463
- ANTHROPIC_BASE_URL: baseUrl,
464
- ANTHROPIC_AUTH_TOKEN: session.gatewayToken,
465
- };
466
- }
467
- catch {
468
- return null;
469
- }
470
- }
471
- /** Stop the running gateway. */
472
- export function stopGateway(dir) {
473
- const pid = readGatewayPid(dir);
474
- if (!pid)
475
- return { stopped: false };
476
- try {
477
- process.kill(pid, "SIGTERM");
478
- }
479
- catch {
480
- // already dead
481
- }
482
- try {
483
- unlinkSync(llmMeshPidPath(dir));
484
- }
485
- catch {
486
- // best-effort cleanup
487
- }
488
- return { stopped: true, pid };
489
- }
490
- //# sourceMappingURL=llm-mesh.js.map