@code-yeongyu/senpi 2026.8.31 → 2026.9.2

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 (93) hide show
  1. package/CHANGELOG.md +32 -0
  2. package/dist/core/extensions/builtin/compaction/context-pipeline.d.ts +6 -0
  3. package/dist/core/extensions/builtin/compaction/context-pipeline.d.ts.map +1 -1
  4. package/dist/core/extensions/builtin/compaction/context-pipeline.js +11 -0
  5. package/dist/core/extensions/builtin/compaction/context-pipeline.js.map +1 -1
  6. package/dist/core/extensions/builtin/compaction/index.js +4 -4
  7. package/dist/core/extensions/builtin/compaction/index.js.map +1 -1
  8. package/dist/core/extensions/builtin/prompt-preset/claude-fable-5-1.d.ts +3 -0
  9. package/dist/core/extensions/builtin/prompt-preset/claude-fable-5-1.d.ts.map +1 -0
  10. package/dist/core/extensions/builtin/prompt-preset/claude-fable-5-1.js +108 -0
  11. package/dist/core/extensions/builtin/prompt-preset/claude-fable-5-1.js.map +1 -0
  12. package/dist/core/extensions/builtin/prompt-preset/presets.d.ts.map +1 -1
  13. package/dist/core/extensions/builtin/prompt-preset/presets.js +11 -0
  14. package/dist/core/extensions/builtin/prompt-preset/presets.js.map +1 -1
  15. package/dist/core/extensions/builtin/prompt-preset/settings.d.ts +1 -1
  16. package/dist/core/extensions/builtin/prompt-preset/settings.d.ts.map +1 -1
  17. package/dist/core/extensions/builtin/prompt-preset/settings.js +1 -0
  18. package/dist/core/extensions/builtin/prompt-preset/settings.js.map +1 -1
  19. package/dist/core/extensions/builtin/recommended-models/index.d.ts +1 -1
  20. package/dist/core/extensions/builtin/recommended-models/index.d.ts.map +1 -1
  21. package/dist/core/extensions/builtin/recommended-models/index.js +1 -1
  22. package/dist/core/extensions/builtin/recommended-models/index.js.map +1 -1
  23. package/dist/core/retry-fallback/settings.d.ts.map +1 -1
  24. package/dist/core/retry-fallback/settings.js +1 -0
  25. package/dist/core/retry-fallback/settings.js.map +1 -1
  26. package/dist/main.d.ts +4 -4
  27. package/dist/main.d.ts.map +1 -1
  28. package/dist/main.js +10 -6
  29. package/dist/main.js.map +1 -1
  30. package/dist/modes/app-server/daemon/process.d.ts +13 -2
  31. package/dist/modes/app-server/daemon/process.d.ts.map +1 -1
  32. package/dist/modes/app-server/daemon/process.js +58 -12
  33. package/dist/modes/app-server/daemon/process.js.map +1 -1
  34. package/dist/modes/app-server/daemon.js +62 -4
  35. package/dist/modes/app-server/daemon.js.map +1 -1
  36. package/dist/modes/interactive/interactive-mode.d.ts +11 -1
  37. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  38. package/dist/modes/interactive/interactive-mode.js +35 -6
  39. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  40. package/dist/modes/interactive/tips/catalog/ethos-tips.js +1 -1
  41. package/dist/modes/interactive/tips/catalog/ethos-tips.js.map +1 -1
  42. package/dist/modes/rpc/connection-handler.d.ts.map +1 -1
  43. package/dist/modes/rpc/connection-handler.js +8 -3
  44. package/dist/modes/rpc/connection-handler.js.map +1 -1
  45. package/dist/modes/rpc/custom-capability.d.ts +1 -0
  46. package/dist/modes/rpc/custom-capability.d.ts.map +1 -1
  47. package/dist/modes/rpc/custom-capability.js +1 -0
  48. package/dist/modes/rpc/custom-capability.js.map +1 -1
  49. package/dist/modes/rpc/host-ensure.d.ts.map +1 -1
  50. package/dist/modes/rpc/host-ensure.js +93 -17
  51. package/dist/modes/rpc/host-ensure.js.map +1 -1
  52. package/dist/modes/rpc/host-lifecycle.d.ts +15 -0
  53. package/dist/modes/rpc/host-lifecycle.d.ts.map +1 -1
  54. package/dist/modes/rpc/host-lifecycle.js +180 -55
  55. package/dist/modes/rpc/host-lifecycle.js.map +1 -1
  56. package/dist/modes/rpc/host-watchdog.d.ts +2 -2
  57. package/dist/modes/rpc/host-watchdog.d.ts.map +1 -1
  58. package/dist/modes/rpc/host-watchdog.js +89 -21
  59. package/dist/modes/rpc/host-watchdog.js.map +1 -1
  60. package/dist/modes/rpc/multi-session-host.d.ts.map +1 -1
  61. package/dist/modes/rpc/multi-session-host.js +94 -56
  62. package/dist/modes/rpc/multi-session-host.js.map +1 -1
  63. package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
  64. package/dist/modes/rpc/rpc-client.js +8 -1
  65. package/dist/modes/rpc/rpc-client.js.map +1 -1
  66. package/dist/modes/rpc/session-command-router.d.ts.map +1 -1
  67. package/dist/modes/rpc/session-command-router.js +7 -2
  68. package/dist/modes/rpc/session-command-router.js.map +1 -1
  69. package/dist/modes/rpc/socket-transport.d.ts +13 -0
  70. package/dist/modes/rpc/socket-transport.d.ts.map +1 -0
  71. package/dist/modes/rpc/socket-transport.js +92 -0
  72. package/dist/modes/rpc/socket-transport.js.map +1 -0
  73. package/docs/extensions.md +1 -1
  74. package/docs/rpc.md +5 -1
  75. package/docs/settings.md +4 -4
  76. package/node_modules/@code-yeongyu/senpi-codemode/CHANGELOG.md +12 -0
  77. package/node_modules/@code-yeongyu/senpi-codemode/package.json +4 -4
  78. package/node_modules/@earendil-works/pi-agent-core/package.json +3 -3
  79. package/node_modules/@earendil-works/pi-ai/dist/providers/data/.manifest.json +1 -1
  80. package/node_modules/@earendil-works/pi-ai/dist/providers/data/amazon-bedrock.json +1 -1
  81. package/node_modules/@earendil-works/pi-ai/dist/providers/data/anthropic.json +1 -1
  82. package/node_modules/@earendil-works/pi-ai/dist/providers/data/fireworks.json +1 -1
  83. package/node_modules/@earendil-works/pi-ai/dist/providers/data/google.json +1 -1
  84. package/node_modules/@earendil-works/pi-ai/dist/providers/data/groq.json +1 -1
  85. package/node_modules/@earendil-works/pi-ai/dist/providers/data/nvidia.json +1 -1
  86. package/node_modules/@earendil-works/pi-ai/dist/providers/data/opengateway.json +1 -1
  87. package/node_modules/@earendil-works/pi-ai/dist/providers/data/openrouter.json +1 -1
  88. package/node_modules/@earendil-works/pi-ai/dist/providers/data/vercel-ai-gateway.json +1 -1
  89. package/node_modules/@earendil-works/pi-ai/package.json +2 -2
  90. package/node_modules/@earendil-works/pi-pty/package.json +1 -1
  91. package/node_modules/@earendil-works/pi-telemetry/package.json +1 -1
  92. package/node_modules/@earendil-works/pi-tui/package.json +1 -1
  93. package/package.json +7 -7
@@ -1 +1 @@
1
- {"version":3,"file":"host-ensure.d.ts","sourceRoot":"","sources":["../../../src/modes/rpc/host-ensure.ts"],"names":[],"mappings":"AAmBA,OAAO,EAEN,KAAK,aAAa,EAClB,KAAK,wBAAwB,EAE7B,MAAM,qBAAqB,CAAC;AAG7B,YAAY,EAAE,aAAa,EAAE,wBAAwB,EAAE,CAAC;AAExD,MAAM,WAAW,eAAe;IAC/B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,iBAAiB;IACjC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,sFAAsF;IACtF,QAAQ,CAAC,MAAM,CAAC,EAAE,wBAAwB,CAAC;IAC3C,QAAQ,CAAC,KAAK,CAAC,EAAE;QAChB,QAAQ,CAAC,kBAAkB,CAAC,EAAE,MAAM,CAAC;QACrC,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;QAChC,QAAQ,CAAC,KAAK,CAAC,EAAE;YAAE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;YAAC,QAAQ,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,CAAA;SAAE,CAAC;QAChF,wFAAwF;QACxF,QAAQ,CAAC,GAAG,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;QAChD,2EAA2E;QAC3E,QAAQ,CAAC,QAAQ,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;QACtC,oFAAoF;QACpF,QAAQ,CAAC,iBAAiB,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;KACjD,CAAC;CACF;AAED,MAAM,WAAW,WAAW;IAC3B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;CACzB;AASD;;;;GAIG;AACH,eAAO,MAAM,+BAA+B,qDAAwE,CAAC;AAErH,wBAAgB,qBAAqB,CAAC,QAAQ,SAAgB,GAAG,eAAe,CAS/E;AAED,wBAAsB,UAAU,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,WAAW,CAAC,CAgBjF;AAqPD;;;;;;;;;;;;GAYG;AACH,wBAAgB,iBAAiB,CAChC,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,SAAS,MAAM,EAAE,EAC3B,QAAQ,GAAE,OAAqB,GAC7B;IACF,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,EAAE,CAAC;CACf,CAWA"}
1
+ {"version":3,"file":"host-ensure.d.ts","sourceRoot":"","sources":["../../../src/modes/rpc/host-ensure.ts"],"names":[],"mappings":"AAmBA,OAAO,EAEN,KAAK,aAAa,EAClB,KAAK,wBAAwB,EAE7B,MAAM,qBAAqB,CAAC;AAU7B,YAAY,EAAE,aAAa,EAAE,wBAAwB,EAAE,CAAC;AAExD,MAAM,WAAW,eAAe;IAC/B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,iBAAiB;IACjC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,sFAAsF;IACtF,QAAQ,CAAC,MAAM,CAAC,EAAE,wBAAwB,CAAC;IAC3C,QAAQ,CAAC,KAAK,CAAC,EAAE;QAChB,QAAQ,CAAC,kBAAkB,CAAC,EAAE,MAAM,CAAC;QACrC,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;QAChC,QAAQ,CAAC,KAAK,CAAC,EAAE;YAAE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;YAAC,QAAQ,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,CAAA;SAAE,CAAC;QAChF,wFAAwF;QACxF,QAAQ,CAAC,GAAG,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;QAChD,2EAA2E;QAC3E,QAAQ,CAAC,QAAQ,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;QACtC,oFAAoF;QACpF,QAAQ,CAAC,iBAAiB,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;KACjD,CAAC;CACF;AAED,MAAM,WAAW,WAAW;IAC3B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;CACzB;AAWD;;;;GAIG;AACH,eAAO,MAAM,+BAA+B,qDAAwE,CAAC;AAErH,wBAAgB,qBAAqB,CAAC,QAAQ,SAAgB,GAAG,eAAe,CAS/E;AAED,wBAAsB,UAAU,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,WAAW,CAAC,CAiBjF;AAgUD;;;;;;;;;;;;GAYG;AACH,wBAAgB,iBAAiB,CAChC,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,SAAS,MAAM,EAAE,EAC3B,QAAQ,GAAE,OAAqB,GAC7B;IACF,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,EAAE,CAAC;CACf,CAWA"}
@@ -1,6 +1,6 @@
1
1
  import { spawn } from "node:child_process";
2
2
  import { createHash } from "node:crypto";
3
- import { mkdir, open, readFile, rm, writeFile } from "node:fs/promises";
3
+ import { mkdir, open, readdir, readFile, rm, writeFile } from "node:fs/promises";
4
4
  import { createConnection } from "node:net";
5
5
  import { tmpdir } from "node:os";
6
6
  import { dirname, join, resolve } from "node:path";
@@ -10,8 +10,11 @@ import { parseDaemonPidFile, processMatchesPidFile, waitForStartTime, } from "..
10
10
  import { CUSTOM_UNSUPPORTED_CAPABILITY, EXTENSION_EVENTS_CAPABILITY, RPC_CLIENT_CAPABILITIES_ENV, } from "./custom-capability.js";
11
11
  import { DEFAULT_HOST_IDLE_EXIT_MS, INTERNAL_SUPERVISOR_FLAG, } from "./host-lifecycle.js";
12
12
  import { acquireOwnershipSafeLock } from "./ownership-safe-lock.js";
13
+ import { createSocketSecret, readSocketSecret, resolveSocketTransportAddress, sendSocketHandshake, socketSecretPath, } from "./socket-transport.js";
13
14
  const lockOptions = { retries: { retries: 100, minTimeout: 20, maxTimeout: 100 } };
14
15
  const REQUIRED_CAPABILITIES = ["multi_session", EXTENSION_EVENTS_CAPABILITY];
16
+ const SPAWNED_HOST_PROBE_TIMEOUT_MS = 10_000;
17
+ const EXISTING_HOST_PROBE_TIMEOUT_MS = 10_000;
15
18
  /**
16
19
  * Every ensured host starts with this installation-wide profile, independent of
17
20
  * the first caller. In particular, extension_events must remain available when
@@ -39,6 +42,7 @@ export async function ensureHost(options) {
39
42
  await writeFile(lockTarget, "", { flag: "a", mode: 0o600 });
40
43
  const release = await acquireOwnershipSafeLock(`${lockTarget}.lock`, lockOptions);
41
44
  try {
45
+ await reapOrphanedInternalHostDirs();
42
46
  await options._test?.afterLockAcquired?.();
43
47
  return await ensureHostLocked(paths, socket, options.agentDir ?? getAgentDir(), options.policy, options._test);
44
48
  }
@@ -48,7 +52,7 @@ export async function ensureHost(options) {
48
52
  }
49
53
  async function ensureHostLocked(paths, socket, agentDir, policy, testOptions) {
50
54
  const pidFile = await readPidFile(paths);
51
- const protocol = await probeProtocolInfo(socket, 1_000);
55
+ const protocol = await probeProtocolInfo(socket, EXISTING_HOST_PROBE_TIMEOUT_MS);
52
56
  const pidMatches = pidFile ? await processMatchesPidFile(pidFile) : false;
53
57
  if (isCompatible(protocol)) {
54
58
  // A compatible socket is attachable even when another client surface
@@ -67,6 +71,8 @@ async function ensureHostLocked(paths, socket, agentDir, policy, testOptions) {
67
71
  async function startHost(paths, socket, agentDir, policy, testOptions) {
68
72
  // The settings file must exist before the supervisor reads it at boot, so it
69
73
  // records the policy before the spawn instead of beside the pidfile.
74
+ if (process.platform === "win32")
75
+ await createSocketSecret(socketSecretPath(socket));
70
76
  await writeFile(paths.settingsFile, `${JSON.stringify({
71
77
  socket,
72
78
  capabilities: PINNED_HOST_CLIENT_CAPABILITIES,
@@ -82,6 +88,7 @@ async function startHost(paths, socket, agentDir, policy, testOptions) {
82
88
  const launch = testOptions?.spawn ?? defaultHostLaunch(socket, testOptions?.hostArgs ?? []);
83
89
  child = spawn(launch.command, [...launch.args], {
84
90
  detached: true,
91
+ windowsHide: true,
85
92
  env: {
86
93
  ...process.env,
87
94
  ...(testOptions?.env ?? {}),
@@ -96,21 +103,40 @@ async function startHost(paths, socket, agentDir, policy, testOptions) {
96
103
  resolveExit(exitedEarly);
97
104
  });
98
105
  });
99
- child.unref();
100
106
  if (child.pid === undefined)
101
107
  throw new Error("failed to spawn RPC socket host");
102
108
  const processStartTime = await Promise.race([
103
- waitForStartTime(child.pid, 2_000),
109
+ waitForStartTime(child.pid, 10_000),
104
110
  childExit.then(() => {
105
111
  throw new Error("RPC socket host exited before its start time could be read");
106
112
  }),
107
113
  ]);
108
114
  pidFile = { pid: child.pid, processStartTime };
109
115
  await writeFile(paths.pidFile, `${JSON.stringify(pidFile)}\n`, { mode: 0o600 });
116
+ child.unref();
110
117
  }
111
118
  catch (error) {
112
- if (!exitedEarly)
119
+ // Keep the ChildProcess handle owned until registration succeeds. If startup
120
+ // fails before the pidfile is written, terminate this exact child through
121
+ // its still-attached handle rather than leaving an unmanaged daemon behind.
122
+ if (!exitedEarly && child && child.exitCode === null && child.signalCode === null) {
123
+ try {
124
+ child.kill("SIGTERM");
125
+ }
126
+ catch { }
127
+ if (childExit)
128
+ await Promise.race([childExit, delay(2_000)]);
129
+ if (child.exitCode === null && child.signalCode === null) {
130
+ try {
131
+ child.kill("SIGKILL");
132
+ }
133
+ catch { }
134
+ }
135
+ }
136
+ if (!exitedEarly) {
137
+ await cleanupState(paths);
113
138
  throw error;
139
+ }
114
140
  const diagnostic = await appendStderr(paths, `RPC socket host exited with code ${exitedEarly.code ?? "null"}${exitedEarly.signal ? ` (${exitedEarly.signal})` : ""} before answering get_protocol_info`);
115
141
  await cleanupState(paths);
116
142
  throw new Error(diagnostic);
@@ -162,20 +188,34 @@ async function waitForGone(pidFile, timeoutMs) {
162
188
  return true;
163
189
  await delay(50);
164
190
  }
165
- return false;
191
+ return !(await processMatchesPidFile(pidFile));
166
192
  }
167
193
  async function pollProtocolInfo(socket, timeoutMs, childExit) {
168
194
  const deadline = Date.now() + timeoutMs;
169
195
  let lastProtocol;
170
196
  while (Date.now() <= deadline) {
171
- const probe = probeProtocolInfo(socket, Math.min(500, Math.max(1, deadline - Date.now())));
172
- const info = childExit ? await Promise.race([probe, childExit]) : await probe;
173
- if (isChildExit(info))
174
- return { protocol: lastProtocol, exited: info };
175
- if (info) {
176
- lastProtocol = info;
177
- if (isCompatible(info))
178
- return { protocol: info };
197
+ const probe = probeProtocolInfo(socket, Math.min(SPAWNED_HOST_PROBE_TIMEOUT_MS, Math.max(1, deadline - Date.now())));
198
+ const raced = childExit ? await Promise.race([probe, childExit]) : await probe;
199
+ if (isChildExit(raced)) {
200
+ // A supervisor exit can be triggered by the Windows identity watchdog
201
+ // while a named-pipe client is still composing its protocol reply. Do
202
+ // not terminate the host based solely on that exit until this probe has
203
+ // had a chance to deliver an answer. A host that never answers still
204
+ // resolves through probeProtocolInfo's bounded timeout/close handling.
205
+ const info = await probe;
206
+ if (info) {
207
+ lastProtocol = info;
208
+ if (isCompatible(info))
209
+ return { protocol: info };
210
+ }
211
+ else {
212
+ return { protocol: lastProtocol, exited: raced };
213
+ }
214
+ }
215
+ else if (raced) {
216
+ lastProtocol = raced;
217
+ if (isCompatible(raced))
218
+ return { protocol: raced };
179
219
  }
180
220
  await delay(50);
181
221
  }
@@ -184,9 +224,20 @@ async function pollProtocolInfo(socket, timeoutMs, childExit) {
184
224
  function isChildExit(value) {
185
225
  return !!value && "code" in value && "signal" in value;
186
226
  }
187
- function probeProtocolInfo(socketPath, timeoutMs) {
227
+ async function probeProtocolInfo(socketPath, timeoutMs) {
228
+ let secret;
229
+ if (process.platform === "win32") {
230
+ try {
231
+ secret = await readSocketSecret(socketSecretPath(socketPath));
232
+ }
233
+ catch {
234
+ return undefined;
235
+ }
236
+ }
188
237
  return new Promise((resolveProbe) => {
189
- const socket = createConnection(socketPath);
238
+ const socket = createConnection(resolveSocketTransportAddress(socketPath, process.platform, secret));
239
+ if (secret)
240
+ sendSocketHandshake(socket, secret);
190
241
  let buffer = "";
191
242
  let settled = false;
192
243
  const finish = (value) => {
@@ -244,6 +295,28 @@ async function readPidFile(paths) {
244
295
  throw error;
245
296
  }
246
297
  }
298
+ async function reapOrphanedInternalHostDirs() {
299
+ try {
300
+ const entries = await readdir(tmpdir(), { withFileTypes: true });
301
+ await Promise.all(entries
302
+ .filter((entry) => entry.isDirectory() && entry.name.startsWith("senpi-rpc-host-internal-"))
303
+ .map(async (entry) => {
304
+ try {
305
+ const owner = JSON.parse(await readFile(join(tmpdir(), entry.name, ".owner"), "utf8"));
306
+ if (typeof owner.pid === "number" &&
307
+ typeof owner.processStartTime === "string" &&
308
+ typeof owner.createdAt === "number" &&
309
+ owner.processStartTime.length > 0 &&
310
+ owner.createdAt < Date.now() - 60_000 &&
311
+ (await readdir(join(tmpdir(), entry.name))).length === 1 &&
312
+ !(await processMatchesPidFile({ pid: owner.pid, processStartTime: owner.processStartTime })))
313
+ await rm(join(tmpdir(), entry.name), { recursive: true, force: true });
314
+ }
315
+ catch { }
316
+ }));
317
+ }
318
+ catch { }
319
+ }
247
320
  async function cleanupState(paths) {
248
321
  await rm(paths.pidFile, { force: true });
249
322
  await rm(paths.settingsFile, { force: true });
@@ -260,7 +333,10 @@ async function appendStderr(paths, message) {
260
333
  }
261
334
  }
262
335
  function createSocketLockName(socket) {
263
- return createHash("sha256").update(socket).digest("hex").slice(0, 32);
336
+ return createHash("sha256")
337
+ .update(resolveSocketTransportAddress(socket, process.platform), "utf8")
338
+ .digest("hex")
339
+ .slice(0, 32);
264
340
  }
265
341
  function normalizeSocketPath(value) {
266
342
  if (value.startsWith("unix://"))
@@ -1 +1 @@
1
- {"version":3,"file":"host-ensure.js","sourceRoot":"","sources":["../../../src/modes/rpc/host-ensure.ts"],"names":[],"mappings":"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","sourcesContent":["import { spawn } from \"node:child_process\";\nimport { createHash } from \"node:crypto\";\nimport { mkdir, open, readFile, rm, writeFile } from \"node:fs/promises\";\nimport { createConnection } from \"node:net\";\nimport { tmpdir } from \"node:os\";\nimport { dirname, join, resolve } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { ENV_AGENT_DIR, getAgentDir, isBunBinary, VERSION } from \"../../config.ts\";\nimport {\n\ttype DaemonPidFile,\n\tparseDaemonPidFile,\n\tprocessMatchesPidFile,\n\twaitForStartTime,\n} from \"../app-server/daemon/process.ts\";\nimport {\n\tCUSTOM_UNSUPPORTED_CAPABILITY,\n\tEXTENSION_EVENTS_CAPABILITY,\n\tRPC_CLIENT_CAPABILITIES_ENV,\n} from \"./custom-capability.ts\";\nimport {\n\tDEFAULT_HOST_IDLE_EXIT_MS,\n\ttype HostColdStart,\n\ttype HostLifecyclePolicyInput,\n\tINTERNAL_SUPERVISOR_FLAG,\n} from \"./host-lifecycle.ts\";\nimport { acquireOwnershipSafeLock } from \"./ownership-safe-lock.ts\";\n\nexport type { HostColdStart, HostLifecyclePolicyInput };\n\nexport interface HostDaemonPaths {\n\treadonly dir: string;\n\treadonly pidFile: string;\n\treadonly lockFile: string;\n\treadonly settingsFile: string;\n\treadonly stderrLog: string;\n}\n\nexport interface EnsureHostOptions {\n\treadonly socket: string;\n\treadonly agentDir?: string;\n\t/** Host lifecycle policy recorded in settings.json (env overrides win at runtime). */\n\treadonly policy?: HostLifecyclePolicyInput;\n\treadonly _test?: {\n\t\treadonly readinessTimeoutMs?: number;\n\t\treadonly stopTimeoutMs?: number;\n\t\treadonly spawn?: { readonly command: string; readonly args: readonly string[] };\n\t\t/** Extra env merged over process.env for the spawned host (hermetic test/QA wiring). */\n\t\treadonly env?: Readonly<Record<string, string>>;\n\t\t/** Extra CLI args forwarded through the supervisor to the host process. */\n\t\treadonly hostArgs?: readonly string[];\n\t\t/** Runs after endpoint ownership is locked; deterministic concurrency-test gate. */\n\t\treadonly afterLockAcquired?: () => Promise<void>;\n\t};\n}\n\nexport interface EnsuredHost {\n\treadonly pid: number;\n\treadonly socket: string;\n\treadonly reused: boolean;\n}\n\ntype ProtocolInfo = {\n\treadonly serverVersion: string;\n\treadonly capabilities: readonly string[];\n};\n\nconst lockOptions = { retries: { retries: 100, minTimeout: 20, maxTimeout: 100 } } as const;\nconst REQUIRED_CAPABILITIES = [\"multi_session\", EXTENSION_EVENTS_CAPABILITY] as const;\n/**\n * Every ensured host starts with this installation-wide profile, independent of\n * the first caller. In particular, extension_events must remain available when\n * a terminal client starts the shared host before the desktop connects.\n */\nexport const PINNED_HOST_CLIENT_CAPABILITIES = [EXTENSION_EVENTS_CAPABILITY, CUSTOM_UNSUPPORTED_CAPABILITY] as const;\n\nexport function createHostDaemonPaths(agentDir = getAgentDir()): HostDaemonPaths {\n\tconst dir = join(agentDir, \"rpc-host-daemon\");\n\treturn {\n\t\tdir,\n\t\tpidFile: join(dir, \"host.pid\"),\n\t\tlockFile: join(dir, \"daemon.lock\"),\n\t\tsettingsFile: join(dir, \"settings.json\"),\n\t\tstderrLog: join(dir, \"stderr.log\"),\n\t};\n}\n\nexport async function ensureHost(options: EnsureHostOptions): Promise<EnsuredHost> {\n\tconst socket = normalizeSocketPath(options.socket);\n\tconst paths = createHostDaemonPaths(options.agentDir);\n\tawait mkdir(paths.dir, { recursive: true });\n\t// The public socket is the shared resource; agent directories are not a\n\t// sufficient lock scope when two installations target the same endpoint.\n\tconst lockTarget = join(tmpdir(), \"senpi-rpc-host-locks\", createSocketLockName(socket));\n\tawait mkdir(dirname(lockTarget), { recursive: true });\n\tawait writeFile(lockTarget, \"\", { flag: \"a\", mode: 0o600 });\n\tconst release = await acquireOwnershipSafeLock(`${lockTarget}.lock`, lockOptions);\n\ttry {\n\t\tawait options._test?.afterLockAcquired?.();\n\t\treturn await ensureHostLocked(paths, socket, options.agentDir ?? getAgentDir(), options.policy, options._test);\n\t} finally {\n\t\tawait release();\n\t}\n}\n\nasync function ensureHostLocked(\n\tpaths: HostDaemonPaths,\n\tsocket: string,\n\tagentDir: string,\n\tpolicy: HostLifecyclePolicyInput | undefined,\n\ttestOptions: EnsureHostOptions[\"_test\"],\n): Promise<EnsuredHost> {\n\tconst pidFile = await readPidFile(paths);\n\tconst protocol = await probeProtocolInfo(socket, 1_000);\n\tconst pidMatches = pidFile ? await processMatchesPidFile(pidFile) : false;\n\tif (isCompatible(protocol)) {\n\t\t// A compatible socket is attachable even when another client surface\n\t\t// started it. Only hosts we spawned are eligible for lifecycle management.\n\t\treturn { pid: pidFile?.pid ?? 0, socket, reused: true };\n\t}\n\tif (protocol && !pidMatches) {\n\t\tthrow new Error(`RPC socket ${socket} is owned by an unmanaged host`);\n\t}\n\tif (pidFile && pidMatches) {\n\t\tawait stopManagedHost(pidFile, testOptions?.stopTimeoutMs ?? 10_000);\n\t}\n\tawait cleanupState(paths);\n\treturn startHost(paths, socket, agentDir, policy, testOptions);\n}\n\nasync function startHost(\n\tpaths: HostDaemonPaths,\n\tsocket: string,\n\tagentDir: string,\n\tpolicy: HostLifecyclePolicyInput | undefined,\n\ttestOptions: EnsureHostOptions[\"_test\"],\n): Promise<EnsuredHost> {\n\t// The settings file must exist before the supervisor reads it at boot, so it\n\t// records the policy before the spawn instead of beside the pidfile.\n\tawait writeFile(\n\t\tpaths.settingsFile,\n\t\t`${JSON.stringify({\n\t\t\tsocket,\n\t\t\tcapabilities: PINNED_HOST_CLIENT_CAPABILITIES,\n\t\t\tcoldStart: policy?.coldStart ?? \"transient\",\n\t\t\tidleExitMs: policy?.idleExitMs ?? DEFAULT_HOST_IDLE_EXIT_MS,\n\t\t})}\\n`,\n\t\t{ mode: 0o600 },\n\t);\n\tconst stderr = await open(paths.stderrLog, \"w\", 0o600);\n\tlet pidFile: DaemonPidFile | undefined;\n\tlet child: ReturnType<typeof spawn> | undefined;\n\tlet exitedEarly: ChildExit | undefined;\n\tlet childExit: Promise<ChildExit> | undefined;\n\ttry {\n\t\tconst launch = testOptions?.spawn ?? defaultHostLaunch(socket, testOptions?.hostArgs ?? []);\n\t\tchild = spawn(launch.command, [...launch.args], {\n\t\t\tdetached: true,\n\t\t\tenv: {\n\t\t\t\t...process.env,\n\t\t\t\t...(testOptions?.env ?? {}),\n\t\t\t\t[ENV_AGENT_DIR]: agentDir,\n\t\t\t\t[RPC_CLIENT_CAPABILITIES_ENV]: PINNED_HOST_CLIENT_CAPABILITIES.join(\",\"),\n\t\t\t},\n\t\t\tstdio: [\"ignore\", \"ignore\", stderr.fd],\n\t\t});\n\t\tchildExit = new Promise((resolveExit) => {\n\t\t\tchild!.once(\"exit\", (code, signal) => {\n\t\t\t\texitedEarly = { code, signal };\n\t\t\t\tresolveExit(exitedEarly);\n\t\t\t});\n\t\t});\n\t\tchild.unref();\n\t\tif (child.pid === undefined) throw new Error(\"failed to spawn RPC socket host\");\n\t\tconst processStartTime = await Promise.race([\n\t\t\twaitForStartTime(child.pid, 2_000),\n\t\t\tchildExit.then(() => {\n\t\t\t\tthrow new Error(\"RPC socket host exited before its start time could be read\");\n\t\t\t}),\n\t\t]);\n\t\tpidFile = { pid: child.pid, processStartTime };\n\t\tawait writeFile(paths.pidFile, `${JSON.stringify(pidFile)}\\n`, { mode: 0o600 });\n\t} catch (error: unknown) {\n\t\tif (!exitedEarly) throw error;\n\t\tconst diagnostic = await appendStderr(\n\t\t\tpaths,\n\t\t\t`RPC socket host exited with code ${exitedEarly.code ?? \"null\"}${exitedEarly.signal ? ` (${exitedEarly.signal})` : \"\"} before answering get_protocol_info`,\n\t\t);\n\t\tawait cleanupState(paths);\n\t\tthrow new Error(diagnostic);\n\t} finally {\n\t\tawait stderr.close();\n\t}\n\tconst readinessTimeoutMs = testOptions?.readinessTimeoutMs ?? 10_000;\n\tconst result = await pollProtocolInfo(socket, readinessTimeoutMs, childExit);\n\tif (isCompatible(result.protocol)) return { pid: pidFile.pid, socket, reused: false };\n\tawait stopManagedHost(pidFile, testOptions?.stopTimeoutMs ?? 10_000);\n\tconst message = result.protocol\n\t\t? `RPC socket host answered get_protocol_info with serverVersion ${result.protocol.serverVersion} and capabilities ${JSON.stringify(result.protocol.capabilities)}, but is incompatible with serverVersion ${VERSION} and required capabilities ${JSON.stringify(REQUIRED_CAPABILITIES)}`\n\t\t: result.exited\n\t\t\t? `RPC socket host exited with code ${result.exited.code ?? \"null\"}${result.exited.signal ? ` (${result.exited.signal})` : \"\"} before answering get_protocol_info`\n\t\t\t: `spawned RPC socket host did not answer get_protocol_info within ${readinessTimeoutMs}ms`;\n\tconst diagnostic = await appendStderr(paths, message);\n\tawait cleanupState(paths);\n\t// The supervisor may have failed before binding, or another owner may have\n\t// appeared while readiness was being checked. Never unlink an endpoint we\n\t// cannot prove this start owned.\n\tthrow new Error(diagnostic);\n}\n\nasync function stopManagedHost(pidFile: DaemonPidFile, termTimeoutMs: number): Promise<void> {\n\tawait signalValidated(pidFile, \"SIGTERM\");\n\tif (await waitForGone(pidFile, termTimeoutMs)) return;\n\tawait signalValidated(pidFile, \"SIGKILL\");\n\tif (!(await waitForGone(pidFile, 2_000))) {\n\t\tthrow new Error(`RPC socket host pid ${pidFile.pid} remained alive after SIGKILL`);\n\t}\n}\n\nasync function signalValidated(pidFile: DaemonPidFile, signal: NodeJS.Signals): Promise<void> {\n\tif (!(await processMatchesPidFile(pidFile))) return;\n\ttry {\n\t\tprocess.kill(pidFile.pid, signal);\n\t} catch (error: unknown) {\n\t\tif (!isNodeErrorCode(error, \"ESRCH\")) throw error;\n\t}\n}\n\nasync function waitForGone(pidFile: DaemonPidFile, timeoutMs: number): Promise<boolean> {\n\tconst deadline = Date.now() + timeoutMs;\n\twhile (Date.now() <= deadline) {\n\t\tif (!(await processMatchesPidFile(pidFile))) return true;\n\t\tawait delay(50);\n\t}\n\treturn false;\n}\n\ntype ChildExit = { readonly code: number | null; readonly signal: NodeJS.Signals | null };\n\ntype ProtocolPollResult = { readonly protocol?: ProtocolInfo; readonly exited?: ChildExit };\n\nasync function pollProtocolInfo(\n\tsocket: string,\n\ttimeoutMs: number,\n\tchildExit?: Promise<ChildExit>,\n): Promise<ProtocolPollResult> {\n\tconst deadline = Date.now() + timeoutMs;\n\tlet lastProtocol: ProtocolInfo | undefined;\n\twhile (Date.now() <= deadline) {\n\t\tconst probe = probeProtocolInfo(socket, Math.min(500, Math.max(1, deadline - Date.now())));\n\t\tconst info = childExit ? await Promise.race([probe, childExit]) : await probe;\n\t\tif (isChildExit(info)) return { protocol: lastProtocol, exited: info };\n\t\tif (info) {\n\t\t\tlastProtocol = info;\n\t\t\tif (isCompatible(info)) return { protocol: info };\n\t\t}\n\t\tawait delay(50);\n\t}\n\treturn { protocol: lastProtocol };\n}\n\nfunction isChildExit(value: ProtocolInfo | ChildExit | undefined): value is ChildExit {\n\treturn !!value && \"code\" in value && \"signal\" in value;\n}\n\nfunction probeProtocolInfo(socketPath: string, timeoutMs: number): Promise<ProtocolInfo | undefined> {\n\treturn new Promise((resolveProbe) => {\n\t\tconst socket = createConnection(socketPath);\n\t\tlet buffer = \"\";\n\t\tlet settled = false;\n\t\tconst finish = (value?: ProtocolInfo): void => {\n\t\t\tif (settled) return;\n\t\t\tsettled = true;\n\t\t\tclearTimeout(timeout);\n\t\t\tsocket.destroy();\n\t\t\tresolveProbe(value);\n\t\t};\n\t\tconst timeout = setTimeout(() => finish(), timeoutMs);\n\t\tsocket.once(\"connect\", () => {\n\t\t\tsocket.write('{\"id\":\"ensure-host-probe\",\"type\":\"get_protocol_info\"}\\n');\n\t\t});\n\t\tsocket.on(\"data\", (chunk) => {\n\t\t\tbuffer += chunk.toString(\"utf8\");\n\t\t\tconst newline = buffer.indexOf(\"\\n\");\n\t\t\tif (newline === -1) return;\n\t\t\tfinish(readProtocolInfo(buffer.slice(0, newline)));\n\t\t});\n\t\tsocket.once(\"error\", () => finish());\n\t\tsocket.once(\"close\", () => finish());\n\t});\n}\n\nfunction readProtocolInfo(text: string): ProtocolInfo | undefined {\n\tlet parsed: unknown;\n\ttry {\n\t\tparsed = JSON.parse(text);\n\t} catch {\n\t\treturn undefined;\n\t}\n\tif (!isRecord(parsed) || parsed.id !== \"ensure-host-probe\" || parsed.success !== true || !isRecord(parsed.data)) {\n\t\treturn undefined;\n\t}\n\tconst { serverVersion, capabilities } = parsed.data;\n\tif (typeof serverVersion !== \"string\" || !Array.isArray(capabilities)) return undefined;\n\tif (!capabilities.every((capability) => typeof capability === \"string\")) return undefined;\n\treturn { serverVersion, capabilities };\n}\n\nfunction isCompatible(protocol: ProtocolInfo | undefined): boolean {\n\treturn (\n\t\tprotocol?.serverVersion === VERSION &&\n\t\tREQUIRED_CAPABILITIES.every((capability) => protocol.capabilities.includes(capability))\n\t);\n}\n\nasync function readPidFile(paths: HostDaemonPaths): Promise<DaemonPidFile | undefined> {\n\ttry {\n\t\treturn parseDaemonPidFile(await readFile(paths.pidFile, \"utf8\"));\n\t} catch (error: unknown) {\n\t\tif (isNodeErrorCode(error, \"ENOENT\")) return undefined;\n\t\tthrow error;\n\t}\n}\n\nasync function cleanupState(paths: HostDaemonPaths): Promise<void> {\n\tawait rm(paths.pidFile, { force: true });\n\tawait rm(paths.settingsFile, { force: true });\n}\n\nasync function appendStderr(paths: HostDaemonPaths, message: string): Promise<string> {\n\ttry {\n\t\tconst stderr = (await readFile(paths.stderrLog, \"utf8\")).trim();\n\t\treturn stderr ? `${message}\\n${stderr}` : message;\n\t} catch (error: unknown) {\n\t\tif (isNodeErrorCode(error, \"ENOENT\")) return message;\n\t\tthrow error;\n\t}\n}\n\nfunction createSocketLockName(socket: string): string {\n\treturn createHash(\"sha256\").update(socket).digest(\"hex\").slice(0, 32);\n}\n\nfunction normalizeSocketPath(value: string): string {\n\tif (value.startsWith(\"unix://\")) return value.slice(\"unix://\".length);\n\treturn value;\n}\n\n/**\n * Default launch: the host-lifecycle supervisor owns the public socket and the\n * idle-exit policy; it spawns the committed RPC socket host itself. Any extra\n * hostArgs are forwarded verbatim to the host CLI (e.g. provider pinning).\n *\n * A compiled standalone binary cannot re-enter itself through a script path:\n * bun executables always boot their embedded entrypoint and parse the whole\n * argv as CLI arguments, so `host-lifecycle.ts --socket <path>` dies with\n * \"Unknown option: --socket\" before the host ever answers get_protocol_info.\n * Compiled binaries therefore re-enter through the hidden\n * `--internal-rpc-host-supervisor` route that main() dispatches before\n * argument parsing. Exported for tests.\n */\nexport function defaultHostLaunch(\n\tsocket: string,\n\thostArgs: readonly string[],\n\tcompiled: boolean = isBunBinary,\n): {\n\tcommand: string;\n\targs: string[];\n} {\n\tif (compiled) {\n\t\treturn {\n\t\t\tcommand: process.execPath,\n\t\t\targs: [INTERNAL_SUPERVISOR_FLAG, \"--socket\", socket, ...hostArgs],\n\t\t};\n\t}\n\treturn {\n\t\tcommand: process.execPath,\n\t\targs: [...process.execArgv, resolveHostLifecycleEntryPath(), \"--socket\", socket, ...hostArgs],\n\t};\n}\n\nfunction resolveHostLifecycleEntryPath(): string {\n\tconst modulePath = fileURLToPath(import.meta.url);\n\tconst extension = modulePath.endsWith(\".ts\") ? \".ts\" : \".js\";\n\treturn resolve(dirname(modulePath), `host-lifecycle${extension}`);\n}\n\nfunction delay(ms: number): Promise<void> {\n\treturn new Promise((resolveDelay) => setTimeout(resolveDelay, ms));\n}\n\nfunction isRecord(value: unknown): value is Readonly<Record<string, unknown>> {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction isNodeErrorCode(error: unknown, code: string): boolean {\n\treturn error instanceof Error && \"code\" in error && error.code === code;\n}\n"]}
1
+ {"version":3,"file":"host-ensure.js","sourceRoot":"","sources":["../../../src/modes/rpc/host-ensure.ts"],"names":[],"mappings":"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","sourcesContent":["import { spawn } from \"node:child_process\";\nimport { createHash } from \"node:crypto\";\nimport { mkdir, open, readdir, readFile, rm, writeFile } from \"node:fs/promises\";\nimport { createConnection } from \"node:net\";\nimport { tmpdir } from \"node:os\";\nimport { dirname, join, resolve } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { ENV_AGENT_DIR, getAgentDir, isBunBinary, VERSION } from \"../../config.ts\";\nimport {\n\ttype DaemonPidFile,\n\tparseDaemonPidFile,\n\tprocessMatchesPidFile,\n\twaitForStartTime,\n} from \"../app-server/daemon/process.ts\";\nimport {\n\tCUSTOM_UNSUPPORTED_CAPABILITY,\n\tEXTENSION_EVENTS_CAPABILITY,\n\tRPC_CLIENT_CAPABILITIES_ENV,\n} from \"./custom-capability.ts\";\nimport {\n\tDEFAULT_HOST_IDLE_EXIT_MS,\n\ttype HostColdStart,\n\ttype HostLifecyclePolicyInput,\n\tINTERNAL_SUPERVISOR_FLAG,\n} from \"./host-lifecycle.ts\";\nimport { acquireOwnershipSafeLock } from \"./ownership-safe-lock.ts\";\nimport {\n\tcreateSocketSecret,\n\treadSocketSecret,\n\tresolveSocketTransportAddress,\n\tsendSocketHandshake,\n\tsocketSecretPath,\n} from \"./socket-transport.ts\";\n\nexport type { HostColdStart, HostLifecyclePolicyInput };\n\nexport interface HostDaemonPaths {\n\treadonly dir: string;\n\treadonly pidFile: string;\n\treadonly lockFile: string;\n\treadonly settingsFile: string;\n\treadonly stderrLog: string;\n}\n\nexport interface EnsureHostOptions {\n\treadonly socket: string;\n\treadonly agentDir?: string;\n\t/** Host lifecycle policy recorded in settings.json (env overrides win at runtime). */\n\treadonly policy?: HostLifecyclePolicyInput;\n\treadonly _test?: {\n\t\treadonly readinessTimeoutMs?: number;\n\t\treadonly stopTimeoutMs?: number;\n\t\treadonly spawn?: { readonly command: string; readonly args: readonly string[] };\n\t\t/** Extra env merged over process.env for the spawned host (hermetic test/QA wiring). */\n\t\treadonly env?: Readonly<Record<string, string>>;\n\t\t/** Extra CLI args forwarded through the supervisor to the host process. */\n\t\treadonly hostArgs?: readonly string[];\n\t\t/** Runs after endpoint ownership is locked; deterministic concurrency-test gate. */\n\t\treadonly afterLockAcquired?: () => Promise<void>;\n\t};\n}\n\nexport interface EnsuredHost {\n\treadonly pid: number;\n\treadonly socket: string;\n\treadonly reused: boolean;\n}\n\ntype ProtocolInfo = {\n\treadonly serverVersion: string;\n\treadonly capabilities: readonly string[];\n};\n\nconst lockOptions = { retries: { retries: 100, minTimeout: 20, maxTimeout: 100 } } as const;\nconst REQUIRED_CAPABILITIES = [\"multi_session\", EXTENSION_EVENTS_CAPABILITY] as const;\nconst SPAWNED_HOST_PROBE_TIMEOUT_MS = 10_000;\nconst EXISTING_HOST_PROBE_TIMEOUT_MS = 10_000;\n/**\n * Every ensured host starts with this installation-wide profile, independent of\n * the first caller. In particular, extension_events must remain available when\n * a terminal client starts the shared host before the desktop connects.\n */\nexport const PINNED_HOST_CLIENT_CAPABILITIES = [EXTENSION_EVENTS_CAPABILITY, CUSTOM_UNSUPPORTED_CAPABILITY] as const;\n\nexport function createHostDaemonPaths(agentDir = getAgentDir()): HostDaemonPaths {\n\tconst dir = join(agentDir, \"rpc-host-daemon\");\n\treturn {\n\t\tdir,\n\t\tpidFile: join(dir, \"host.pid\"),\n\t\tlockFile: join(dir, \"daemon.lock\"),\n\t\tsettingsFile: join(dir, \"settings.json\"),\n\t\tstderrLog: join(dir, \"stderr.log\"),\n\t};\n}\n\nexport async function ensureHost(options: EnsureHostOptions): Promise<EnsuredHost> {\n\tconst socket = normalizeSocketPath(options.socket);\n\tconst paths = createHostDaemonPaths(options.agentDir);\n\tawait mkdir(paths.dir, { recursive: true });\n\t// The public socket is the shared resource; agent directories are not a\n\t// sufficient lock scope when two installations target the same endpoint.\n\tconst lockTarget = join(tmpdir(), \"senpi-rpc-host-locks\", createSocketLockName(socket));\n\tawait mkdir(dirname(lockTarget), { recursive: true });\n\tawait writeFile(lockTarget, \"\", { flag: \"a\", mode: 0o600 });\n\tconst release = await acquireOwnershipSafeLock(`${lockTarget}.lock`, lockOptions);\n\ttry {\n\t\tawait reapOrphanedInternalHostDirs();\n\t\tawait options._test?.afterLockAcquired?.();\n\t\treturn await ensureHostLocked(paths, socket, options.agentDir ?? getAgentDir(), options.policy, options._test);\n\t} finally {\n\t\tawait release();\n\t}\n}\n\nasync function ensureHostLocked(\n\tpaths: HostDaemonPaths,\n\tsocket: string,\n\tagentDir: string,\n\tpolicy: HostLifecyclePolicyInput | undefined,\n\ttestOptions: EnsureHostOptions[\"_test\"],\n): Promise<EnsuredHost> {\n\tconst pidFile = await readPidFile(paths);\n\tconst protocol = await probeProtocolInfo(socket, EXISTING_HOST_PROBE_TIMEOUT_MS);\n\tconst pidMatches = pidFile ? await processMatchesPidFile(pidFile) : false;\n\tif (isCompatible(protocol)) {\n\t\t// A compatible socket is attachable even when another client surface\n\t\t// started it. Only hosts we spawned are eligible for lifecycle management.\n\t\treturn { pid: pidFile?.pid ?? 0, socket, reused: true };\n\t}\n\tif (protocol && !pidMatches) {\n\t\tthrow new Error(`RPC socket ${socket} is owned by an unmanaged host`);\n\t}\n\tif (pidFile && pidMatches) {\n\t\tawait stopManagedHost(pidFile, testOptions?.stopTimeoutMs ?? 10_000);\n\t}\n\tawait cleanupState(paths);\n\treturn startHost(paths, socket, agentDir, policy, testOptions);\n}\n\nasync function startHost(\n\tpaths: HostDaemonPaths,\n\tsocket: string,\n\tagentDir: string,\n\tpolicy: HostLifecyclePolicyInput | undefined,\n\ttestOptions: EnsureHostOptions[\"_test\"],\n): Promise<EnsuredHost> {\n\t// The settings file must exist before the supervisor reads it at boot, so it\n\t// records the policy before the spawn instead of beside the pidfile.\n\tif (process.platform === \"win32\") await createSocketSecret(socketSecretPath(socket));\n\tawait writeFile(\n\t\tpaths.settingsFile,\n\t\t`${JSON.stringify({\n\t\t\tsocket,\n\t\t\tcapabilities: PINNED_HOST_CLIENT_CAPABILITIES,\n\t\t\tcoldStart: policy?.coldStart ?? \"transient\",\n\t\t\tidleExitMs: policy?.idleExitMs ?? DEFAULT_HOST_IDLE_EXIT_MS,\n\t\t})}\\n`,\n\t\t{ mode: 0o600 },\n\t);\n\tconst stderr = await open(paths.stderrLog, \"w\", 0o600);\n\tlet pidFile: DaemonPidFile | undefined;\n\tlet child: ReturnType<typeof spawn> | undefined;\n\tlet exitedEarly: ChildExit | undefined;\n\tlet childExit: Promise<ChildExit> | undefined;\n\ttry {\n\t\tconst launch = testOptions?.spawn ?? defaultHostLaunch(socket, testOptions?.hostArgs ?? []);\n\t\tchild = spawn(launch.command, [...launch.args], {\n\t\t\tdetached: true,\n\t\t\twindowsHide: true,\n\t\t\tenv: {\n\t\t\t\t...process.env,\n\t\t\t\t...(testOptions?.env ?? {}),\n\t\t\t\t[ENV_AGENT_DIR]: agentDir,\n\t\t\t\t[RPC_CLIENT_CAPABILITIES_ENV]: PINNED_HOST_CLIENT_CAPABILITIES.join(\",\"),\n\t\t\t},\n\t\t\tstdio: [\"ignore\", \"ignore\", stderr.fd],\n\t\t});\n\t\tchildExit = new Promise((resolveExit) => {\n\t\t\tchild!.once(\"exit\", (code, signal) => {\n\t\t\t\texitedEarly = { code, signal };\n\t\t\t\tresolveExit(exitedEarly);\n\t\t\t});\n\t\t});\n\t\tif (child.pid === undefined) throw new Error(\"failed to spawn RPC socket host\");\n\t\tconst processStartTime = await Promise.race([\n\t\t\twaitForStartTime(child.pid, 10_000),\n\t\t\tchildExit.then(() => {\n\t\t\t\tthrow new Error(\"RPC socket host exited before its start time could be read\");\n\t\t\t}),\n\t\t]);\n\t\tpidFile = { pid: child.pid, processStartTime };\n\t\tawait writeFile(paths.pidFile, `${JSON.stringify(pidFile)}\\n`, { mode: 0o600 });\n\t\tchild.unref();\n\t} catch (error: unknown) {\n\t\t// Keep the ChildProcess handle owned until registration succeeds. If startup\n\t\t// fails before the pidfile is written, terminate this exact child through\n\t\t// its still-attached handle rather than leaving an unmanaged daemon behind.\n\t\tif (!exitedEarly && child && child.exitCode === null && child.signalCode === null) {\n\t\t\ttry {\n\t\t\t\tchild.kill(\"SIGTERM\");\n\t\t\t} catch {}\n\t\t\tif (childExit) await Promise.race([childExit, delay(2_000)]);\n\t\t\tif (child.exitCode === null && child.signalCode === null) {\n\t\t\t\ttry {\n\t\t\t\t\tchild.kill(\"SIGKILL\");\n\t\t\t\t} catch {}\n\t\t\t}\n\t\t}\n\t\tif (!exitedEarly) {\n\t\t\tawait cleanupState(paths);\n\t\t\tthrow error;\n\t\t}\n\t\tconst diagnostic = await appendStderr(\n\t\t\tpaths,\n\t\t\t`RPC socket host exited with code ${exitedEarly.code ?? \"null\"}${exitedEarly.signal ? ` (${exitedEarly.signal})` : \"\"} before answering get_protocol_info`,\n\t\t);\n\t\tawait cleanupState(paths);\n\t\tthrow new Error(diagnostic);\n\t} finally {\n\t\tawait stderr.close();\n\t}\n\tconst readinessTimeoutMs = testOptions?.readinessTimeoutMs ?? 10_000;\n\tconst result = await pollProtocolInfo(socket, readinessTimeoutMs, childExit);\n\tif (isCompatible(result.protocol)) return { pid: pidFile.pid, socket, reused: false };\n\tawait stopManagedHost(pidFile, testOptions?.stopTimeoutMs ?? 10_000);\n\tconst message = result.protocol\n\t\t? `RPC socket host answered get_protocol_info with serverVersion ${result.protocol.serverVersion} and capabilities ${JSON.stringify(result.protocol.capabilities)}, but is incompatible with serverVersion ${VERSION} and required capabilities ${JSON.stringify(REQUIRED_CAPABILITIES)}`\n\t\t: result.exited\n\t\t\t? `RPC socket host exited with code ${result.exited.code ?? \"null\"}${result.exited.signal ? ` (${result.exited.signal})` : \"\"} before answering get_protocol_info`\n\t\t\t: `spawned RPC socket host did not answer get_protocol_info within ${readinessTimeoutMs}ms`;\n\tconst diagnostic = await appendStderr(paths, message);\n\tawait cleanupState(paths);\n\t// The supervisor may have failed before binding, or another owner may have\n\t// appeared while readiness was being checked. Never unlink an endpoint we\n\t// cannot prove this start owned.\n\tthrow new Error(diagnostic);\n}\n\nasync function stopManagedHost(pidFile: DaemonPidFile, termTimeoutMs: number): Promise<void> {\n\tawait signalValidated(pidFile, \"SIGTERM\");\n\tif (await waitForGone(pidFile, termTimeoutMs)) return;\n\tawait signalValidated(pidFile, \"SIGKILL\");\n\tif (!(await waitForGone(pidFile, 2_000))) {\n\t\tthrow new Error(`RPC socket host pid ${pidFile.pid} remained alive after SIGKILL`);\n\t}\n}\n\nasync function signalValidated(pidFile: DaemonPidFile, signal: NodeJS.Signals): Promise<void> {\n\tif (!(await processMatchesPidFile(pidFile))) return;\n\ttry {\n\t\tprocess.kill(pidFile.pid, signal);\n\t} catch (error: unknown) {\n\t\tif (!isNodeErrorCode(error, \"ESRCH\")) throw error;\n\t}\n}\n\nasync function waitForGone(pidFile: DaemonPidFile, timeoutMs: number): Promise<boolean> {\n\tconst deadline = Date.now() + timeoutMs;\n\twhile (Date.now() <= deadline) {\n\t\tif (!(await processMatchesPidFile(pidFile))) return true;\n\t\tawait delay(50);\n\t}\n\treturn !(await processMatchesPidFile(pidFile));\n}\n\ntype ChildExit = { readonly code: number | null; readonly signal: NodeJS.Signals | null };\n\ntype ProtocolPollResult = { readonly protocol?: ProtocolInfo; readonly exited?: ChildExit };\n\nasync function pollProtocolInfo(\n\tsocket: string,\n\ttimeoutMs: number,\n\tchildExit?: Promise<ChildExit>,\n): Promise<ProtocolPollResult> {\n\tconst deadline = Date.now() + timeoutMs;\n\tlet lastProtocol: ProtocolInfo | undefined;\n\twhile (Date.now() <= deadline) {\n\t\tconst probe = probeProtocolInfo(\n\t\t\tsocket,\n\t\t\tMath.min(SPAWNED_HOST_PROBE_TIMEOUT_MS, Math.max(1, deadline - Date.now())),\n\t\t);\n\t\tconst raced = childExit ? await Promise.race([probe, childExit]) : await probe;\n\t\tif (isChildExit(raced)) {\n\t\t\t// A supervisor exit can be triggered by the Windows identity watchdog\n\t\t\t// while a named-pipe client is still composing its protocol reply. Do\n\t\t\t// not terminate the host based solely on that exit until this probe has\n\t\t\t// had a chance to deliver an answer. A host that never answers still\n\t\t\t// resolves through probeProtocolInfo's bounded timeout/close handling.\n\t\t\tconst info = await probe;\n\t\t\tif (info) {\n\t\t\t\tlastProtocol = info;\n\t\t\t\tif (isCompatible(info)) return { protocol: info };\n\t\t\t} else {\n\t\t\t\treturn { protocol: lastProtocol, exited: raced };\n\t\t\t}\n\t\t} else if (raced) {\n\t\t\tlastProtocol = raced;\n\t\t\tif (isCompatible(raced)) return { protocol: raced };\n\t\t}\n\t\tawait delay(50);\n\t}\n\treturn { protocol: lastProtocol };\n}\n\nfunction isChildExit(value: ProtocolInfo | ChildExit | undefined): value is ChildExit {\n\treturn !!value && \"code\" in value && \"signal\" in value;\n}\n\nasync function probeProtocolInfo(socketPath: string, timeoutMs: number): Promise<ProtocolInfo | undefined> {\n\tlet secret: Buffer | undefined;\n\tif (process.platform === \"win32\") {\n\t\ttry {\n\t\t\tsecret = await readSocketSecret(socketSecretPath(socketPath));\n\t\t} catch {\n\t\t\treturn undefined;\n\t\t}\n\t}\n\treturn new Promise((resolveProbe) => {\n\t\tconst socket = createConnection(resolveSocketTransportAddress(socketPath, process.platform, secret));\n\t\tif (secret) sendSocketHandshake(socket, secret);\n\t\tlet buffer = \"\";\n\t\tlet settled = false;\n\t\tconst finish = (value?: ProtocolInfo): void => {\n\t\t\tif (settled) return;\n\t\t\tsettled = true;\n\t\t\tclearTimeout(timeout);\n\t\t\tsocket.destroy();\n\t\t\tresolveProbe(value);\n\t\t};\n\t\tconst timeout = setTimeout(() => finish(), timeoutMs);\n\t\tsocket.once(\"connect\", () => {\n\t\t\tsocket.write('{\"id\":\"ensure-host-probe\",\"type\":\"get_protocol_info\"}\\n');\n\t\t});\n\t\tsocket.on(\"data\", (chunk) => {\n\t\t\tbuffer += chunk.toString(\"utf8\");\n\t\t\tconst newline = buffer.indexOf(\"\\n\");\n\t\t\tif (newline === -1) return;\n\t\t\tfinish(readProtocolInfo(buffer.slice(0, newline)));\n\t\t});\n\t\tsocket.once(\"error\", () => finish());\n\t\tsocket.once(\"close\", () => finish());\n\t});\n}\n\nfunction readProtocolInfo(text: string): ProtocolInfo | undefined {\n\tlet parsed: unknown;\n\ttry {\n\t\tparsed = JSON.parse(text);\n\t} catch {\n\t\treturn undefined;\n\t}\n\tif (!isRecord(parsed) || parsed.id !== \"ensure-host-probe\" || parsed.success !== true || !isRecord(parsed.data)) {\n\t\treturn undefined;\n\t}\n\tconst { serverVersion, capabilities } = parsed.data;\n\tif (typeof serverVersion !== \"string\" || !Array.isArray(capabilities)) return undefined;\n\tif (!capabilities.every((capability) => typeof capability === \"string\")) return undefined;\n\treturn { serverVersion, capabilities };\n}\n\nfunction isCompatible(protocol: ProtocolInfo | undefined): boolean {\n\treturn (\n\t\tprotocol?.serverVersion === VERSION &&\n\t\tREQUIRED_CAPABILITIES.every((capability) => protocol.capabilities.includes(capability))\n\t);\n}\n\nasync function readPidFile(paths: HostDaemonPaths): Promise<DaemonPidFile | undefined> {\n\ttry {\n\t\treturn parseDaemonPidFile(await readFile(paths.pidFile, \"utf8\"));\n\t} catch (error: unknown) {\n\t\tif (isNodeErrorCode(error, \"ENOENT\")) return undefined;\n\t\tthrow error;\n\t}\n}\n\nasync function reapOrphanedInternalHostDirs(): Promise<void> {\n\ttry {\n\t\tconst entries = await readdir(tmpdir(), { withFileTypes: true });\n\t\tawait Promise.all(\n\t\t\tentries\n\t\t\t\t.filter((entry) => entry.isDirectory() && entry.name.startsWith(\"senpi-rpc-host-internal-\"))\n\t\t\t\t.map(async (entry) => {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst owner = JSON.parse(await readFile(join(tmpdir(), entry.name, \".owner\"), \"utf8\")) as {\n\t\t\t\t\t\t\tpid?: unknown;\n\t\t\t\t\t\t\tprocessStartTime?: unknown;\n\t\t\t\t\t\t\tcreatedAt?: unknown;\n\t\t\t\t\t\t};\n\t\t\t\t\t\tif (\n\t\t\t\t\t\t\ttypeof owner.pid === \"number\" &&\n\t\t\t\t\t\t\ttypeof owner.processStartTime === \"string\" &&\n\t\t\t\t\t\t\ttypeof owner.createdAt === \"number\" &&\n\t\t\t\t\t\t\towner.processStartTime.length > 0 &&\n\t\t\t\t\t\t\towner.createdAt < Date.now() - 60_000 &&\n\t\t\t\t\t\t\t(await readdir(join(tmpdir(), entry.name))).length === 1 &&\n\t\t\t\t\t\t\t!(await processMatchesPidFile({ pid: owner.pid, processStartTime: owner.processStartTime }))\n\t\t\t\t\t\t)\n\t\t\t\t\t\t\tawait rm(join(tmpdir(), entry.name), { recursive: true, force: true });\n\t\t\t\t\t} catch {}\n\t\t\t\t}),\n\t\t);\n\t} catch {}\n}\n\nasync function cleanupState(paths: HostDaemonPaths): Promise<void> {\n\tawait rm(paths.pidFile, { force: true });\n\tawait rm(paths.settingsFile, { force: true });\n}\n\nasync function appendStderr(paths: HostDaemonPaths, message: string): Promise<string> {\n\ttry {\n\t\tconst stderr = (await readFile(paths.stderrLog, \"utf8\")).trim();\n\t\treturn stderr ? `${message}\\n${stderr}` : message;\n\t} catch (error: unknown) {\n\t\tif (isNodeErrorCode(error, \"ENOENT\")) return message;\n\t\tthrow error;\n\t}\n}\n\nfunction createSocketLockName(socket: string): string {\n\treturn createHash(\"sha256\")\n\t\t.update(resolveSocketTransportAddress(socket, process.platform), \"utf8\")\n\t\t.digest(\"hex\")\n\t\t.slice(0, 32);\n}\n\nfunction normalizeSocketPath(value: string): string {\n\tif (value.startsWith(\"unix://\")) return value.slice(\"unix://\".length);\n\treturn value;\n}\n\n/**\n * Default launch: the host-lifecycle supervisor owns the public socket and the\n * idle-exit policy; it spawns the committed RPC socket host itself. Any extra\n * hostArgs are forwarded verbatim to the host CLI (e.g. provider pinning).\n *\n * A compiled standalone binary cannot re-enter itself through a script path:\n * bun executables always boot their embedded entrypoint and parse the whole\n * argv as CLI arguments, so `host-lifecycle.ts --socket <path>` dies with\n * \"Unknown option: --socket\" before the host ever answers get_protocol_info.\n * Compiled binaries therefore re-enter through the hidden\n * `--internal-rpc-host-supervisor` route that main() dispatches before\n * argument parsing. Exported for tests.\n */\nexport function defaultHostLaunch(\n\tsocket: string,\n\thostArgs: readonly string[],\n\tcompiled: boolean = isBunBinary,\n): {\n\tcommand: string;\n\targs: string[];\n} {\n\tif (compiled) {\n\t\treturn {\n\t\t\tcommand: process.execPath,\n\t\t\targs: [INTERNAL_SUPERVISOR_FLAG, \"--socket\", socket, ...hostArgs],\n\t\t};\n\t}\n\treturn {\n\t\tcommand: process.execPath,\n\t\targs: [...process.execArgv, resolveHostLifecycleEntryPath(), \"--socket\", socket, ...hostArgs],\n\t};\n}\n\nfunction resolveHostLifecycleEntryPath(): string {\n\tconst modulePath = fileURLToPath(import.meta.url);\n\tconst extension = modulePath.endsWith(\".ts\") ? \".ts\" : \".js\";\n\treturn resolve(dirname(modulePath), `host-lifecycle${extension}`);\n}\n\nfunction delay(ms: number): Promise<void> {\n\treturn new Promise((resolveDelay) => setTimeout(resolveDelay, ms));\n}\n\nfunction isRecord(value: unknown): value is Readonly<Record<string, unknown>> {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction isNodeErrorCode(error: unknown, code: string): boolean {\n\treturn error instanceof Error && \"code\" in error && error.code === code;\n}\n"]}
@@ -92,5 +92,20 @@ export declare function resolveHostChildLaunch(launch: SupervisorLaunch, interna
92
92
  command: string;
93
93
  args: string[];
94
94
  };
95
+ /**
96
+ * Windows refuses to spawn a `.cmd`/`.bat` without a shell, and Node's
97
+ * `shell: true` concatenates argv without escaping it. Escape each original
98
+ * value before adding the surrounding quotes so `.cmd`/`.bat` launchers survive
99
+ * cmd.exe parsing without double-escaping.
100
+ * Exported for tests.
101
+ */
102
+ export declare function spawnableChildLaunch(launch: {
103
+ command: string;
104
+ args: string[];
105
+ }, platform?: NodeJS.Platform): {
106
+ command: string;
107
+ args: string[];
108
+ shell: boolean;
109
+ };
95
110
  export declare function runHostSupervisor(launch: SupervisorLaunch): Promise<void>;
96
111
  //# sourceMappingURL=host-lifecycle.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"host-lifecycle.d.ts","sourceRoot":"","sources":["../../../src/modes/rpc/host-lifecycle.ts"],"names":[],"mappings":";AAyDA,MAAM,MAAM,aAAa,GAAG,WAAW,GAAG,YAAY,CAAC;AAEvD,mFAAmF;AACnF,eAAO,MAAM,mBAAmB,8BAA8B,CAAC;AAC/D,qEAAqE;AACrE,eAAO,MAAM,qBAAqB,gCAAgC,CAAC;AACnE,sFAAsF;AACtF,eAAO,MAAM,yBAAyB,QAAc,CAAC;AAErD,+EAA+E;AAC/E,MAAM,WAAW,wBAAwB;IACxC,QAAQ,CAAC,SAAS,CAAC,EAAE,aAAa,CAAC;IACnC,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED,MAAM,WAAW,mBAAmB;IACnC,QAAQ,CAAC,SAAS,EAAE,aAAa,CAAC;IAClC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;CAC5B;AAuBD,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,aAAa,GAAG,SAAS,CAEnF;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAI7E;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAChC,QAAQ,EAAE,OAAO,EACjB,GAAG,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC,GAC/C,mBAAmB,CASrB;AAED,MAAM,WAAW,YAAY;IAC5B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;CAC7B;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAChC,IAAI,EAAE,MAAM,GAAG,IAAI,EACnB,MAAM,EAAE,MAAM,CAAC,OAAO,GAAG,IAAI,GAC3B;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAGtC;AAED,MAAM,MAAM,gBAAgB,GAAG,QAAQ,GAAG,MAAM,GAAG,MAAM,CAAC;AAE1D;;;;GAIG;AACH,qBAAa,eAAe;IAC3B,OAAO,CAAC,SAAS,CAAqB;IACtC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAe;IACnC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;gBAEhB,UAAU,EAAE,MAAM,EAAE,GAAG,GAAE,MAAM,MAAiB;IAK5D,MAAM,CAAC,QAAQ,EAAE,YAAY,GAAG,gBAAgB;CAchD;AAED,MAAM,WAAW,gBAAgB;IAChC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;IACrC,kEAAkE;IAClE,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,SAAS,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACvC,qFAAqF;IACrF,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,gGAAgG;AAChG,eAAO,MAAM,wBAAwB,mCAAmC,CAAC;AASzE;;;;;;;;;;;;;GAaG;AACH,wBAAgB,0BAA0B,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,MAAM,EAAE,GAAG,SAAS,CASjG;AAED,sGAAsG;AACtG,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,gBAAgB,GAAG,SAAS,CAgCzF;AAED,0FAA0F;AAC1F,wBAAgB,kBAAkB,IAAI,MAAM,CAI3C;AAED;;;;;;;GAOG;AACH,wBAAgB,sBAAsB,CACrC,MAAM,EAAE,gBAAgB,EACxB,cAAc,EAAE,MAAM,EACtB,QAAQ,GAAE,OAAqB,GAC7B;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,EAAE,CAAA;CAAE,CAmBrC;AAED,wBAAsB,iBAAiB,CAAC,MAAM,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CA0K/E"}
1
+ {"version":3,"file":"host-lifecycle.d.ts","sourceRoot":"","sources":["../../../src/modes/rpc/host-lifecycle.ts"],"names":[],"mappings":"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"}