nomoreide 0.1.31 → 0.1.33

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.
@@ -1,4 +1,18 @@
1
1
  import type { ApprovalBroker } from "./approval-broker.js";
2
+ export type AgentChatProviderId = "claude" | "codex";
3
+ export type DetectedAgentName = "claude-code" | "codex" | "gemini" | "unknown";
4
+ export interface AgentChatProvider {
5
+ id: AgentChatProviderId;
6
+ label: string;
7
+ commandName: string;
8
+ bin: string;
9
+ installHint: string;
10
+ intro: string;
11
+ }
12
+ export interface AgentInvocation {
13
+ bin: string;
14
+ args: string[];
15
+ }
2
16
  /** Streamed back to the route, which forwards each as an SSE event. */
3
17
  export type AgentStreamEvent = {
4
18
  type: "session";
@@ -30,8 +44,10 @@ export type AgentStreamEvent = {
30
44
  message: string;
31
45
  };
32
46
  export interface AgentRuntimeDeps {
33
- /** Working directory the Claude Code session runs in (the workspace root). */
47
+ /** Working directory the agent session runs in (the workspace root). */
34
48
  cwd: string;
49
+ /** CLI provider selected from the agent that started NoMoreIDE. */
50
+ provider?: AgentChatProvider;
35
51
  }
36
52
  export interface AgentRunOptions {
37
53
  signal?: AbortSignal;
@@ -41,10 +57,20 @@ export interface AgentRunOptions {
41
57
  url: string;
42
58
  };
43
59
  }
44
- /** True when the `claude` CLI is installed and runnable. Memoized. */
45
- export declare function isAgentAvailable(): Promise<boolean>;
60
+ /** Pick the in-dock chat provider from the same detected-agent signal as /agent. */
61
+ export declare function resolveChatProvider(detectedName: DetectedAgentName): AgentChatProvider;
62
+ export declare function publicProviderInfo(provider: AgentChatProvider): {
63
+ id: AgentChatProviderId;
64
+ label: string;
65
+ commandName: string;
66
+ installHint: string;
67
+ intro: string;
68
+ };
69
+ /** True when the selected agent CLI is installed and runnable. Memoized. */
70
+ export declare function isAgentAvailable(provider?: AgentChatProvider): Promise<boolean>;
46
71
  /** Whether tool calls are gated behind dock approval (vs. fully autonomous). */
47
- export declare function approvalsEnabled(): boolean;
72
+ export declare function approvalsEnabled(provider?: AgentChatProvider): boolean;
73
+ export declare function buildAgentInvocation(provider: AgentChatProvider, message: string, resumeSessionId: string | undefined, gating: boolean): AgentInvocation;
48
74
  export declare class AgentRuntime {
49
75
  private readonly deps;
50
76
  constructor(deps: AgentRuntimeDeps);
@@ -54,3 +80,10 @@ export declare class AgentRuntime {
54
80
  */
55
81
  run(message: string, resumeSessionId: string | undefined, onEvent: (event: AgentStreamEvent) => void, options?: AgentRunOptions): Promise<void>;
56
82
  }
83
+ /**
84
+ * Parse one NDJSON line from Claude Code's stream-json output, emitting the
85
+ * relevant dock events. Returns the session id when this line is the init event.
86
+ */
87
+ export declare function handleClaudeLine(line: string, toolNames: Map<string, string>, onEvent: (event: AgentStreamEvent) => void): string | undefined;
88
+ /** Parse one JSONL event from `codex exec --json`. */
89
+ export declare function handleCodexLine(line: string, toolNames: Map<string, string>, onEvent: (event: AgentStreamEvent) => void): string | undefined;
@@ -3,42 +3,102 @@ import { mkdtempSync, writeFileSync } from "node:fs";
3
3
  import { tmpdir } from "node:os";
4
4
  import { join } from "node:path";
5
5
  /**
6
- * In-dashboard AI agent backed by the real Claude Code CLI. We drive the
7
- * installed `claude` binary in headless streaming mode (`--output-format
8
- * stream-json`) rather than the Anthropic API directly, so the dock gets the
9
- * full Claude Code agent — its tools, this project's .mcp.json / CLAUDE.md, and
10
- * the user's existing Claude Code login (no separate API key).
6
+ * In-dashboard AI agent backed by the real local agent CLI. NoMoreIDE selects
7
+ * Claude Code or Codex from the same startup-agent detection used by /agent,
8
+ * then drives that CLI in a machine-readable headless mode rather than calling
9
+ * a vendor API directly.
11
10
  *
12
- * Conversation continuity uses Claude Code's own session store: the first turn
13
- * returns a `session_id`, which the client sends back as `resumeSessionId` on
14
- * the next turn (`--resume`). The server holds no transcript state.
11
+ * Conversation continuity uses the selected CLI's own session store: the first
12
+ * turn returns a session id, which the client sends back as `resumeSessionId` on
13
+ * the next turn. The server holds no transcript state.
15
14
  *
16
15
  * Tool permissions: unless NOMOREIDE_AGENT_PERMISSION_MODE=bypassPermissions,
17
16
  * the agent runs in `default` mode with a PreToolUse hook on mutating tools.
18
17
  * The hook blocks and asks the dock (via ApprovalBroker) for an Allow/Deny.
19
18
  */
20
19
  const CLAUDE_BIN = process.env.NOMOREIDE_CLAUDE_BIN || "claude";
20
+ const CODEX_BIN = process.env.NOMOREIDE_CODEX_BIN || "codex";
21
21
  /** "bypassPermissions" runs fully autonomous (no approval prompts). */
22
22
  const PERMISSION_MODE = process.env.NOMOREIDE_AGENT_PERMISSION_MODE || "default";
23
+ const CODEX_APPROVAL_POLICY = process.env.NOMOREIDE_CODEX_APPROVAL_POLICY || "never";
23
24
  /** Tools that trigger an approval prompt (mutating / side-effecting ones). */
24
25
  const GATED_TOOLS = "Bash|Edit|Write|MultiEdit|NotebookEdit";
25
26
  /** Truncate tool-result previews shown in the dock. */
26
27
  const PREVIEW_LIMIT = 400;
27
- let availabilityProbe = null;
28
- /** True when the `claude` CLI is installed and runnable. Memoized. */
29
- export function isAgentAvailable() {
30
- if (!availabilityProbe) {
31
- availabilityProbe = new Promise((resolve) => {
32
- const child = spawn(CLAUDE_BIN, ["--version"], { stdio: "ignore" });
33
- child.on("error", () => resolve(false));
34
- child.on("close", (code) => resolve(code === 0));
35
- }).catch(() => false);
36
- }
37
- return availabilityProbe;
28
+ const CLAUDE_PROVIDER = {
29
+ id: "claude",
30
+ label: "Claude Code",
31
+ commandName: "claude",
32
+ bin: CLAUDE_BIN,
33
+ installHint: "Install Claude Code (and run `claude login`) so it is on NoMoreIDE's PATH, then reload.",
34
+ intro: "This is real Claude Code, running in your workspace with full tools - e.g. \"restart the api and tail its logs\", \"what changed in git and why?\", \"fix the failing test\".",
35
+ };
36
+ const CODEX_PROVIDER = {
37
+ id: "codex",
38
+ label: "Codex",
39
+ commandName: "codex",
40
+ bin: CODEX_BIN,
41
+ installHint: "Install Codex CLI (and run `codex login`) so it is on NoMoreIDE's PATH, then reload.",
42
+ intro: "This is real Codex CLI, running in your workspace with full tools - e.g. \"restart the api and tail its logs\", \"what changed in git and why?\", \"fix the failing test\".",
43
+ };
44
+ const availabilityProbes = new Map();
45
+ /** Pick the in-dock chat provider from the same detected-agent signal as /agent. */
46
+ export function resolveChatProvider(detectedName) {
47
+ return detectedName === "codex" ? CODEX_PROVIDER : CLAUDE_PROVIDER;
48
+ }
49
+ export function publicProviderInfo(provider) {
50
+ return {
51
+ id: provider.id,
52
+ label: provider.label,
53
+ commandName: provider.commandName,
54
+ installHint: provider.installHint,
55
+ intro: provider.intro,
56
+ };
57
+ }
58
+ /** True when the selected agent CLI is installed and runnable. Memoized. */
59
+ export function isAgentAvailable(provider = CLAUDE_PROVIDER) {
60
+ const existing = availabilityProbes.get(provider.id);
61
+ if (existing)
62
+ return existing;
63
+ const probe = new Promise((resolve) => {
64
+ const child = spawn(provider.bin, ["--version"], { stdio: "ignore" });
65
+ child.on("error", () => resolve(false));
66
+ child.on("close", (code) => resolve(code === 0));
67
+ }).catch(() => false);
68
+ availabilityProbes.set(provider.id, probe);
69
+ return probe;
38
70
  }
39
71
  /** Whether tool calls are gated behind dock approval (vs. fully autonomous). */
40
- export function approvalsEnabled() {
41
- return PERMISSION_MODE !== "bypassPermissions";
72
+ export function approvalsEnabled(provider = CLAUDE_PROVIDER) {
73
+ return provider.id === "claude" && PERMISSION_MODE !== "bypassPermissions";
74
+ }
75
+ export function buildAgentInvocation(provider, message, resumeSessionId, gating) {
76
+ if (provider.id === "codex") {
77
+ const args = ["-a", CODEX_APPROVAL_POLICY, "exec"];
78
+ if (resumeSessionId) {
79
+ args.push("resume", "--json", "--skip-git-repo-check", resumeSessionId, message);
80
+ }
81
+ else {
82
+ args.push("--json", "--skip-git-repo-check", message);
83
+ }
84
+ return { bin: provider.bin, args };
85
+ }
86
+ const args = [
87
+ "--print",
88
+ "--output-format",
89
+ "stream-json",
90
+ "--verbose",
91
+ "--include-partial-messages",
92
+ "--permission-mode",
93
+ gating ? "default" : PERMISSION_MODE,
94
+ ];
95
+ if (gating) {
96
+ args.push("--settings", approvalSettings());
97
+ }
98
+ if (resumeSessionId)
99
+ args.push("--resume", resumeSessionId);
100
+ args.push(message);
101
+ return { bin: provider.bin, args };
42
102
  }
43
103
  export class AgentRuntime {
44
104
  deps;
@@ -51,27 +111,18 @@ export class AgentRuntime {
51
111
  */
52
112
  async run(message, resumeSessionId, onEvent, options = {}) {
53
113
  const { signal, approval } = options;
54
- const gating = Boolean(approval) && approvalsEnabled();
55
- const args = [
56
- "--print",
57
- "--output-format",
58
- "stream-json",
59
- "--verbose",
60
- "--include-partial-messages",
61
- "--permission-mode",
62
- gating ? "default" : PERMISSION_MODE,
63
- ];
64
- if (gating) {
65
- args.push("--settings", approvalSettings());
66
- }
67
- if (resumeSessionId)
68
- args.push("--resume", resumeSessionId);
69
- args.push(message);
70
- const env = gating
114
+ const provider = this.deps.provider ?? CLAUDE_PROVIDER;
115
+ const gating = Boolean(approval) && approvalsEnabled(provider);
116
+ const invocation = buildAgentInvocation(provider, message, resumeSessionId, gating);
117
+ const env = gating && approval
71
118
  ? { ...process.env, NOMOREIDE_APPROVAL_URL: approval.url }
72
119
  : process.env;
73
120
  await new Promise((resolve) => {
74
- const child = spawn(CLAUDE_BIN, args, { cwd: this.deps.cwd, env });
121
+ const child = spawn(invocation.bin, invocation.args, {
122
+ cwd: this.deps.cwd,
123
+ env,
124
+ stdio: ["ignore", "pipe", "pipe"],
125
+ });
75
126
  const toolNames = new Map();
76
127
  let stdout = "";
77
128
  let stderr = "";
@@ -88,8 +139,10 @@ export class AgentRuntime {
88
139
  // Bridge the broker's approval requests onto the SSE stream the moment
89
140
  // we learn this run's session id.
90
141
  const onLine = (line) => {
91
- const sessionId = handleLine(line, toolNames, onEvent);
92
- if (sessionId && gating && !openedSession) {
142
+ const sessionId = provider.id === "codex"
143
+ ? handleCodexLine(line, toolNames, onEvent)
144
+ : handleClaudeLine(line, toolNames, onEvent);
145
+ if (sessionId && gating && approval && !openedSession) {
93
146
  openedSession = sessionId;
94
147
  approval.broker.openRun(sessionId, (request) => onEvent({
95
148
  type: "approval_request",
@@ -109,7 +162,7 @@ export class AgentRuntime {
109
162
  onEvent({
110
163
  type: "error",
111
164
  message: error.code === "ENOENT"
112
- ? `Could not run "${CLAUDE_BIN}". Install Claude Code or set NOMOREIDE_CLAUDE_BIN.`
165
+ ? `Could not run "${provider.bin}". ${provider.installHint}`
113
166
  : error.message,
114
167
  });
115
168
  finish();
@@ -139,7 +192,7 @@ export class AgentRuntime {
139
192
  if (code !== 0) {
140
193
  onEvent({
141
194
  type: "error",
142
- message: stderr.trim() || `Claude Code exited with code ${code}.`,
195
+ message: stderr.trim() || `${provider.label} exited with code ${code}.`,
143
196
  });
144
197
  }
145
198
  finish();
@@ -151,7 +204,7 @@ export class AgentRuntime {
151
204
  * Parse one NDJSON line from Claude Code's stream-json output, emitting the
152
205
  * relevant dock events. Returns the session id when this line is the init event.
153
206
  */
154
- function handleLine(line, toolNames, onEvent) {
207
+ export function handleClaudeLine(line, toolNames, onEvent) {
155
208
  let obj;
156
209
  try {
157
210
  obj = JSON.parse(line);
@@ -206,6 +259,55 @@ function handleLine(line, toolNames, onEvent) {
206
259
  return undefined;
207
260
  }
208
261
  }
262
+ /** Parse one JSONL event from `codex exec --json`. */
263
+ export function handleCodexLine(line, toolNames, onEvent) {
264
+ let obj;
265
+ try {
266
+ obj = JSON.parse(line);
267
+ }
268
+ catch {
269
+ return undefined;
270
+ }
271
+ if (obj.type === "thread.started" && typeof obj.thread_id === "string") {
272
+ onEvent({ type: "session", sessionId: obj.thread_id });
273
+ return obj.thread_id;
274
+ }
275
+ if (obj.type === "item.started" || obj.type === "item.completed") {
276
+ const item = obj.item;
277
+ if (!item || typeof item.id !== "string" || typeof item.type !== "string") {
278
+ return undefined;
279
+ }
280
+ if (item.type === "command_execution") {
281
+ const name = "command";
282
+ toolNames.set(item.id, name);
283
+ const command = typeof item.command === "string" ? item.command : "";
284
+ if (obj.type === "item.started") {
285
+ onEvent({ type: "tool_use", id: item.id, name, input: { command } });
286
+ return undefined;
287
+ }
288
+ onEvent({
289
+ type: "tool_result",
290
+ id: item.id,
291
+ name,
292
+ preview: previewOf(item.aggregated_output),
293
+ isError: typeof item.exit_code === "number"
294
+ ? item.exit_code !== 0
295
+ : item.status === "failed",
296
+ });
297
+ return undefined;
298
+ }
299
+ if (item.type === "agent_message" && obj.type === "item.completed") {
300
+ const text = typeof item.text === "string" ? item.text : "";
301
+ if (text)
302
+ onEvent({ type: "text", text });
303
+ return undefined;
304
+ }
305
+ }
306
+ if (obj.type === "turn.completed") {
307
+ onEvent({ type: "done", stopReason: null });
308
+ }
309
+ return undefined;
310
+ }
209
311
  function messageContent(message) {
210
312
  const content = message?.content;
211
313
  return Array.isArray(content) ? content : [];
@@ -1 +1 @@
1
- {"version":3,"file":"agent-runtime.js","sourceRoot":"","sources":["../../src/core/agent-runtime.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"agent-runtime.js","sourceRoot":"","sources":["../../src/core/agent-runtime.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAC3C,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACrD,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAGjC;;;;;;;;;;;;;GAaG;AAEH,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,CAAC,oBAAoB,IAAI,QAAQ,CAAC;AAChE,MAAM,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,mBAAmB,IAAI,OAAO,CAAC;AAC7D,uEAAuE;AACvE,MAAM,eAAe,GAAG,OAAO,CAAC,GAAG,CAAC,+BAA+B,IAAI,SAAS,CAAC;AACjF,MAAM,qBAAqB,GAAG,OAAO,CAAC,GAAG,CAAC,+BAA+B,IAAI,OAAO,CAAC;AACrF,8EAA8E;AAC9E,MAAM,WAAW,GAAG,wCAAwC,CAAC;AAC7D,uDAAuD;AACvD,MAAM,aAAa,GAAG,GAAG,CAAC;AAmB1B,MAAM,eAAe,GAAsB;IACzC,EAAE,EAAE,QAAQ;IACZ,KAAK,EAAE,aAAa;IACpB,WAAW,EAAE,QAAQ;IACrB,GAAG,EAAE,UAAU;IACf,WAAW,EACT,yFAAyF;IAC3F,KAAK,EACH,+KAA+K;CAClL,CAAC;AAEF,MAAM,cAAc,GAAsB;IACxC,EAAE,EAAE,OAAO;IACX,KAAK,EAAE,OAAO;IACd,WAAW,EAAE,OAAO;IACpB,GAAG,EAAE,SAAS;IACd,WAAW,EACT,sFAAsF;IACxF,KAAK,EACH,6KAA6K;CAChL,CAAC;AAyBF,MAAM,kBAAkB,GAAG,IAAI,GAAG,EAAyC,CAAC;AAE5E,oFAAoF;AACpF,MAAM,UAAU,mBAAmB,CAAC,YAA+B;IACjE,OAAO,YAAY,KAAK,OAAO,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,eAAe,CAAC;AACrE,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,QAA2B;IAC5D,OAAO;QACL,EAAE,EAAE,QAAQ,CAAC,EAAE;QACf,KAAK,EAAE,QAAQ,CAAC,KAAK;QACrB,WAAW,EAAE,QAAQ,CAAC,WAAW;QACjC,WAAW,EAAE,QAAQ,CAAC,WAAW;QACjC,KAAK,EAAE,QAAQ,CAAC,KAAK;KACtB,CAAC;AACJ,CAAC;AAED,4EAA4E;AAC5E,MAAM,UAAU,gBAAgB,CAC9B,WAA8B,eAAe;IAE7C,MAAM,QAAQ,GAAG,kBAAkB,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;IACrD,IAAI,QAAQ;QAAE,OAAO,QAAQ,CAAC;IAE9B,MAAM,KAAK,GAAG,IAAI,OAAO,CAAU,CAAC,OAAO,EAAE,EAAE;QAC7C,MAAM,KAAK,GAAG,KAAK,CAAC,QAAQ,CAAC,GAAG,EAAE,CAAC,WAAW,CAAC,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC;QACpE,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC;QACxC,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC;IACrD,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,CAAC;IACtB,kBAAkB,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC;IAC3C,OAAO,KAAK,CAAC;AACf,CAAC;AAED,gFAAgF;AAChF,MAAM,UAAU,gBAAgB,CAAC,WAA8B,eAAe;IAC5E,OAAO,QAAQ,CAAC,EAAE,KAAK,QAAQ,IAAI,eAAe,KAAK,mBAAmB,CAAC;AAC7E,CAAC;AAED,MAAM,UAAU,oBAAoB,CAClC,QAA2B,EAC3B,OAAe,EACf,eAAmC,EACnC,MAAe;IAEf,IAAI,QAAQ,CAAC,EAAE,KAAK,OAAO,EAAE,CAAC;QAC5B,MAAM,IAAI,GAAG,CAAC,IAAI,EAAE,qBAAqB,EAAE,MAAM,CAAC,CAAC;QACnD,IAAI,eAAe,EAAE,CAAC;YACpB,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,QAAQ,EAAE,uBAAuB,EAAE,eAAe,EAAE,OAAO,CAAC,CAAC;QACnF,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,uBAAuB,EAAE,OAAO,CAAC,CAAC;QACxD,CAAC;QACD,OAAO,EAAE,GAAG,EAAE,QAAQ,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC;IACrC,CAAC;IAED,MAAM,IAAI,GAAG;QACX,SAAS;QACT,iBAAiB;QACjB,aAAa;QACb,WAAW;QACX,4BAA4B;QAC5B,mBAAmB;QACnB,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,eAAe;KACrC,CAAC;IACF,IAAI,MAAM,EAAE,CAAC;QACX,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,gBAAgB,EAAE,CAAC,CAAC;IAC9C,CAAC;IACD,IAAI,eAAe;QAAE,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,eAAe,CAAC,CAAC;IAC5D,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACnB,OAAO,EAAE,GAAG,EAAE,QAAQ,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC;AACrC,CAAC;AAED,MAAM,OAAO,YAAY;IACM;IAA7B,YAA6B,IAAsB;QAAtB,SAAI,GAAJ,IAAI,CAAkB;IAAG,CAAC;IAEvD;;;OAGG;IACH,KAAK,CAAC,GAAG,CACP,OAAe,EACf,eAAmC,EACnC,OAA0C,EAC1C,UAA2B,EAAE;QAE7B,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAC;QACrC,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,IAAI,eAAe,CAAC;QACvD,MAAM,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC,IAAI,gBAAgB,CAAC,QAAQ,CAAC,CAAC;QAC/D,MAAM,UAAU,GAAG,oBAAoB,CAAC,QAAQ,EAAE,OAAO,EAAE,eAAe,EAAE,MAAM,CAAC,CAAC;QAEpF,MAAM,GAAG,GAAG,MAAM,IAAI,QAAQ;YAC5B,CAAC,CAAC,EAAE,GAAG,OAAO,CAAC,GAAG,EAAE,sBAAsB,EAAE,QAAQ,CAAC,GAAG,EAAE;YAC1D,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC;QAEhB,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE;YAClC,MAAM,KAAK,GAAG,KAAK,CAAC,UAAU,CAAC,GAAG,EAAE,UAAU,CAAC,IAAI,EAAE;gBACnD,GAAG,EAAE,IAAI,CAAC,IAAI,CAAC,GAAG;gBAClB,GAAG;gBACH,KAAK,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC;aAClC,CAAC,CAAC;YACH,MAAM,SAAS,GAAG,IAAI,GAAG,EAAkB,CAAC;YAC5C,IAAI,MAAM,GAAG,EAAE,CAAC;YAChB,IAAI,MAAM,GAAG,EAAE,CAAC;YAChB,IAAI,QAAQ,GAAG,KAAK,CAAC;YACrB,IAAI,aAAiC,CAAC;YAEtC,MAAM,MAAM,GAAG,GAAG,EAAE;gBAClB,IAAI,QAAQ;oBAAE,OAAO;gBACrB,QAAQ,GAAG,IAAI,CAAC;gBAChB,IAAI,aAAa;oBAAE,QAAQ,EAAE,MAAM,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC;gBAC5D,OAAO,EAAE,CAAC;YACZ,CAAC,CAAC;YAEF,uEAAuE;YACvE,kCAAkC;YAClC,MAAM,MAAM,GAAG,CAAC,IAAY,EAAE,EAAE;gBAC9B,MAAM,SAAS,GACb,QAAQ,CAAC,EAAE,KAAK,OAAO;oBACrB,CAAC,CAAC,eAAe,CAAC,IAAI,EAAE,SAAS,EAAE,OAAO,CAAC;oBAC3C,CAAC,CAAC,gBAAgB,CAAC,IAAI,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC;gBACjD,IAAI,SAAS,IAAI,MAAM,IAAI,QAAQ,IAAI,CAAC,aAAa,EAAE,CAAC;oBACtD,aAAa,GAAG,SAAS,CAAC;oBAC1B,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC,SAAS,EAAE,CAAC,OAAO,EAAE,EAAE,CAC7C,OAAO,CAAC;wBACN,IAAI,EAAE,kBAAkB;wBACxB,SAAS,EAAE,OAAO,CAAC,SAAS;wBAC5B,IAAI,EAAE,OAAO,CAAC,IAAI;wBAClB,KAAK,EAAE,OAAO,CAAC,KAAK;qBACrB,CAAC,CACH,CAAC;gBACJ,CAAC;YACH,CAAC,CAAC;YAEF,IAAI,MAAM,EAAE,CAAC;gBACX,IAAI,MAAM,CAAC,OAAO;oBAAE,KAAK,CAAC,IAAI,EAAE,CAAC;;oBAC5B,MAAM,CAAC,gBAAgB,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,IAAI,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;YAC5E,CAAC;YAED,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE;gBAC1B,OAAO,CAAC;oBACN,IAAI,EAAE,OAAO;oBACb,OAAO,EACJ,KAA+B,CAAC,IAAI,KAAK,QAAQ;wBAChD,CAAC,CAAC,kBAAkB,QAAQ,CAAC,GAAG,MAAM,QAAQ,CAAC,WAAW,EAAE;wBAC5D,CAAC,CAAC,KAAK,CAAC,OAAO;iBACpB,CAAC,CAAC;gBACH,MAAM,EAAE,CAAC;YACX,CAAC,CAAC,CAAC;YAEH,KAAK,CAAC,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;YACjC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAa,EAAE,EAAE;gBACxC,MAAM,IAAI,KAAK,CAAC;gBAChB,IAAI,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;gBACnC,OAAO,OAAO,KAAK,CAAC,CAAC,EAAE,CAAC;oBACtB,MAAM,IAAI,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC;oBAC7C,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC;oBACnC,IAAI,IAAI;wBAAE,MAAM,CAAC,IAAI,CAAC,CAAC;oBACvB,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;gBACjC,CAAC;YACH,CAAC,CAAC,CAAC;YAEH,KAAK,CAAC,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;YACjC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAa,EAAE,EAAE;gBACxC,MAAM,IAAI,KAAK,CAAC;YAClB,CAAC,CAAC,CAAC;YAEH,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,EAAE;gBACzB,IAAI,MAAM,EAAE,OAAO;oBAAE,OAAO,MAAM,EAAE,CAAC;gBACrC,MAAM,QAAQ,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC;gBAC/B,IAAI,QAAQ;oBAAE,MAAM,CAAC,QAAQ,CAAC,CAAC;gBAC/B,IAAI,IAAI,KAAK,CAAC,EAAE,CAAC;oBACf,OAAO,CAAC;wBACN,IAAI,EAAE,OAAO;wBACb,OAAO,EAAE,MAAM,CAAC,IAAI,EAAE,IAAI,GAAG,QAAQ,CAAC,KAAK,qBAAqB,IAAI,GAAG;qBACxE,CAAC,CAAC;gBACL,CAAC;gBACD,MAAM,EAAE,CAAC;YACX,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;IACL,CAAC;CACF;AAED;;;GAGG;AACH,MAAM,UAAU,gBAAgB,CAC9B,IAAY,EACZ,SAA8B,EAC9B,OAA0C;IAE1C,IAAI,GAA4B,CAAC;IACjC,IAAI,CAAC;QACH,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IACzB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,QAAQ,GAAG,CAAC,IAAI,EAAE,CAAC;QACjB,KAAK,QAAQ,CAAC,CAAC,CAAC;YACd,IAAI,GAAG,CAAC,OAAO,KAAK,MAAM,IAAI,OAAO,GAAG,CAAC,UAAU,KAAK,QAAQ,EAAE,CAAC;gBACjE,OAAO,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,SAAS,EAAE,GAAG,CAAC,UAAU,EAAE,CAAC,CAAC;gBACxD,OAAO,GAAG,CAAC,UAAU,CAAC;YACxB,CAAC;YACD,OAAO,SAAS,CAAC;QACnB,CAAC;QACD,KAAK,cAAc,CAAC,CAAC,CAAC;YACpB,6DAA6D;YAC7D,MAAM,KAAK,GAAG,GAAG,CAAC,KAAoE,CAAC;YACvF,IAAI,KAAK,EAAE,IAAI,KAAK,qBAAqB,IAAI,KAAK,CAAC,KAAK,EAAE,IAAI,KAAK,YAAY,EAAE,CAAC;gBAChF,OAAO,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,CAAC,KAAK,CAAC,IAAI,IAAI,EAAE,EAAE,CAAC,CAAC;YAC1D,CAAC;YACD,OAAO,SAAS,CAAC;QACnB,CAAC;QACD,KAAK,WAAW,CAAC,CAAC,CAAC;YACjB,KAAK,MAAM,KAAK,IAAI,cAAc,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC;gBAChD,IAAI,KAAK,CAAC,IAAI,KAAK,UAAU,IAAI,OAAO,KAAK,CAAC,EAAE,KAAK,QAAQ,EAAE,CAAC;oBAC9D,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,EAAE,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;oBAC5C,OAAO,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,EAAE,EAAE,KAAK,CAAC,EAAE,EAAE,IAAI,EAAE,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC;gBAC5F,CAAC;YACH,CAAC;YACD,OAAO,SAAS,CAAC;QACnB,CAAC;QACD,KAAK,MAAM,CAAC,CAAC,CAAC;YACZ,KAAK,MAAM,KAAK,IAAI,cAAc,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC;gBAChD,IAAI,KAAK,CAAC,IAAI,KAAK,aAAa,IAAI,OAAO,KAAK,CAAC,WAAW,KAAK,QAAQ,EAAE,CAAC;oBAC1E,OAAO,CAAC;wBACN,IAAI,EAAE,aAAa;wBACnB,EAAE,EAAE,KAAK,CAAC,WAAW;wBACrB,IAAI,EAAE,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,WAAW,CAAC,IAAI,MAAM;wBAChD,OAAO,EAAE,SAAS,CAAC,KAAK,CAAC,OAAO,CAAC;wBACjC,OAAO,EAAE,OAAO,CAAC,KAAK,CAAC,QAAQ,CAAC;qBACjC,CAAC,CAAC;gBACL,CAAC;YACH,CAAC;YACD,OAAO,SAAS,CAAC;QACnB,CAAC;QACD,KAAK,QAAQ,CAAC,CAAC,CAAC;YACd,OAAO,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,OAAO,GAAG,CAAC,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;YAC5F,OAAO,SAAS,CAAC;QACnB,CAAC;QACD;YACE,OAAO,SAAS,CAAC;IACrB,CAAC;AACH,CAAC;AAED,sDAAsD;AACtD,MAAM,UAAU,eAAe,CAC7B,IAAY,EACZ,SAA8B,EAC9B,OAA0C;IAE1C,IAAI,GAA4B,CAAC;IACjC,IAAI,CAAC;QACH,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IACzB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,IAAI,GAAG,CAAC,IAAI,KAAK,gBAAgB,IAAI,OAAO,GAAG,CAAC,SAAS,KAAK,QAAQ,EAAE,CAAC;QACvE,OAAO,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,SAAS,EAAE,GAAG,CAAC,SAAS,EAAE,CAAC,CAAC;QACvD,OAAO,GAAG,CAAC,SAAS,CAAC;IACvB,CAAC;IAED,IAAI,GAAG,CAAC,IAAI,KAAK,cAAc,IAAI,GAAG,CAAC,IAAI,KAAK,gBAAgB,EAAE,CAAC;QACjE,MAAM,IAAI,GAAG,GAAG,CAAC,IAA2C,CAAC;QAC7D,IAAI,CAAC,IAAI,IAAI,OAAO,IAAI,CAAC,EAAE,KAAK,QAAQ,IAAI,OAAO,IAAI,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YAC1E,OAAO,SAAS,CAAC;QACnB,CAAC;QAED,IAAI,IAAI,CAAC,IAAI,KAAK,mBAAmB,EAAE,CAAC;YACtC,MAAM,IAAI,GAAG,SAAS,CAAC;YACvB,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;YAC7B,MAAM,OAAO,GAAG,OAAO,IAAI,CAAC,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;YACrE,IAAI,GAAG,CAAC,IAAI,KAAK,cAAc,EAAE,CAAC;gBAChC,OAAO,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,EAAE,EAAE,IAAI,CAAC,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,OAAO,EAAE,EAAE,CAAC,CAAC;gBACrE,OAAO,SAAS,CAAC;YACnB,CAAC;YACD,OAAO,CAAC;gBACN,IAAI,EAAE,aAAa;gBACnB,EAAE,EAAE,IAAI,CAAC,EAAE;gBACX,IAAI;gBACJ,OAAO,EAAE,SAAS,CAAC,IAAI,CAAC,iBAAiB,CAAC;gBAC1C,OAAO,EACL,OAAO,IAAI,CAAC,SAAS,KAAK,QAAQ;oBAChC,CAAC,CAAC,IAAI,CAAC,SAAS,KAAK,CAAC;oBACtB,CAAC,CAAC,IAAI,CAAC,MAAM,KAAK,QAAQ;aAC/B,CAAC,CAAC;YACH,OAAO,SAAS,CAAC;QACnB,CAAC;QAED,IAAI,IAAI,CAAC,IAAI,KAAK,eAAe,IAAI,GAAG,CAAC,IAAI,KAAK,gBAAgB,EAAE,CAAC;YACnE,MAAM,IAAI,GAAG,OAAO,IAAI,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;YAC5D,IAAI,IAAI;gBAAE,OAAO,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;YAC1C,OAAO,SAAS,CAAC;QACnB,CAAC;IACH,CAAC;IAED,IAAI,GAAG,CAAC,IAAI,KAAK,gBAAgB,EAAE,CAAC;QAClC,OAAO,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC,CAAC;IAC9C,CAAC;IAED,OAAO,SAAS,CAAC;AACnB,CAAC;AAYD,SAAS,cAAc,CAAC,OAAgB;IACtC,MAAM,OAAO,GAAI,OAAiC,EAAE,OAAO,CAAC;IAC5D,OAAO,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,CAAE,OAA0B,CAAC,CAAC,CAAC,EAAE,CAAC;AACnE,CAAC;AAED,SAAS,SAAS,CAAC,OAAgB;IACjC,IAAI,IAAY,CAAC;IACjB,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;QAChC,IAAI,GAAG,OAAO,CAAC;IACjB,CAAC;SAAM,IAAI,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;QAClC,IAAI,GAAG,OAAO;aACX,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CACb,OAAO,KAAK,KAAK,QAAQ;YACvB,CAAC,CAAC,KAAK;YACP,CAAC,CAAC,OAAQ,KAA4B,CAAC,IAAI,KAAK,QAAQ;gBACtD,CAAC,CAAE,KAA0B,CAAC,IAAI;gBAClC,CAAC,CAAC,EAAE,CACT;aACA,IAAI,CAAC,GAAG,CAAC,CAAC;IACf,CAAC;SAAM,CAAC;QACN,IAAI,GAAG,EAAE,CAAC;IACZ,CAAC;IACD,IAAI,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;IACnB,OAAO,IAAI,CAAC,MAAM,GAAG,aAAa,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC;AACjF,CAAC;AAED,IAAI,QAA4B,CAAC;AACjC,IAAI,YAAgC,CAAC;AAErC,gFAAgF;AAChF,SAAS,gBAAgB;IACvB,IAAI,CAAC,YAAY,EAAE,CAAC;QAClB,MAAM,OAAO,GAAG,QAAQ,IAAI,CAAC,SAAS,CAAC,gBAAgB,EAAE,CAAC,EAAE,CAAC;QAC7D,YAAY,GAAG,IAAI,CAAC,SAAS,CAAC;YAC5B,KAAK,EAAE;gBACL,UAAU,EAAE,CAAC,EAAE,OAAO,EAAE,WAAW,EAAE,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC;aAC9E;SACF,CAAC,CAAC;IACL,CAAC;IACD,OAAO,YAAY,CAAC;AACtB,CAAC;AAED;;;;;GAKG;AACH,SAAS,gBAAgB;IACvB,IAAI,QAAQ;QAAE,OAAO,QAAQ,CAAC;IAC9B,MAAM,GAAG,GAAG,WAAW,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,kBAAkB,CAAC,CAAC,CAAC;IAC5D,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,mBAAmB,CAAC,CAAC;IAC1C,aAAa,CAAC,QAAQ,EAAE,WAAW,EAAE,MAAM,CAAC,CAAC;IAC7C,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,MAAM,WAAW,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA4DnB,CAAC"}
@@ -1,6 +1,7 @@
1
1
  import type { ConfigStore } from "./config-store.js";
2
2
  import type { LogStore } from "./log-store.js";
3
3
  import { type PortHolder } from "./port-utils.js";
4
+ import { type ServiceRegistry } from "./service-registry.js";
4
5
  import type { TimelineStore } from "./timeline-store.js";
5
6
  import type { ServiceStatus } from "./types.js";
6
7
  interface ProcessManagerOptions {
@@ -8,6 +9,13 @@ interface ProcessManagerOptions {
8
9
  logStore: LogStore;
9
10
  stopTimeoutMs?: number;
10
11
  timelineStore?: TimelineStore;
12
+ /**
13
+ * Shared cross-session view of running services. When provided, the manager
14
+ * adopts services started by other sessions instead of spawning duplicates,
15
+ * and can stop services it did not spawn itself. Omit for an isolated manager
16
+ * (e.g. in tests) — behavior is then identical to a single-session manager.
17
+ */
18
+ registry?: ServiceRegistry;
11
19
  }
12
20
  export interface NoMoreIdeStatus {
13
21
  services: Record<string, ServiceStatus>;
@@ -28,6 +36,7 @@ export declare class ProcessManager {
28
36
  private readonly logStore;
29
37
  private readonly stopTimeoutMs;
30
38
  private readonly timelineStore?;
39
+ private readonly registry?;
31
40
  constructor(options: ProcessManagerOptions);
32
41
  startService(name: string, options?: StartServiceOptions): Promise<ServiceStatus>;
33
42
  stopService(name: string): Promise<ServiceStatus>;
@@ -45,6 +54,12 @@ export declare class ProcessManager {
45
54
  installShutdownHandlers(): () => void;
46
55
  status(): NoMoreIdeStatus;
47
56
  statusWithResources(): Promise<NoMoreIdeStatus>;
57
+ /**
58
+ * Fold in services started by sibling sessions. A registry entry wins only
59
+ * when this session has no running view of that service, so a locally-owned
60
+ * "running" status is never overwritten by the shared snapshot.
61
+ */
62
+ private mergeRegistry;
48
63
  private startDockerComposeService;
49
64
  private stopDockerComposeService;
50
65
  readDockerServiceLogs(name: string, tail?: number): Promise<string>;
@@ -3,6 +3,7 @@ import { readDockerServiceLogs, readDockerServiceStatus, startDockerService, sto
3
3
  import { startHttpInspector, } from "./http-inspector.js";
4
4
  import { getPortHolder, isPortAvailable } from "./port-utils.js";
5
5
  import { readProcessTree } from "./process-tree.js";
6
+ import { isPidAlive, } from "./service-registry.js";
6
7
  import { createSshCommand } from "./ssh-service-runner.js";
7
8
  export class PortConflictError extends Error {
8
9
  code = "PORT_IN_USE";
@@ -24,11 +25,13 @@ export class ProcessManager {
24
25
  logStore;
25
26
  stopTimeoutMs;
26
27
  timelineStore;
28
+ registry;
27
29
  constructor(options) {
28
30
  this.configStore = options.configStore;
29
31
  this.logStore = options.logStore;
30
32
  this.stopTimeoutMs = options.stopTimeoutMs ?? 3000;
31
33
  this.timelineStore = options.timelineStore;
34
+ this.registry = options.registry;
32
35
  }
33
36
  async startService(name, options = {}) {
34
37
  const service = await this.getService(name);
@@ -40,6 +43,13 @@ export class ProcessManager {
40
43
  if (kind === "docker-compose") {
41
44
  return this.startDockerComposeService(name, service);
42
45
  }
46
+ // Another session may already be running this exact service. Adopt its
47
+ // status instead of spawning a duplicate — this also covers portless
48
+ // services, where the port check below cannot detect the conflict.
49
+ const tracked = this.registry?.get(name);
50
+ if (tracked) {
51
+ return registryEntryToStatus(tracked);
52
+ }
43
53
  if (service.port && !(await isPortAvailable(service.port))) {
44
54
  const holder = await getPortHolder(service.port);
45
55
  if (options.killHolder && holder) {
@@ -66,6 +76,18 @@ export class ProcessManager {
66
76
  },
67
77
  };
68
78
  this.runtimes.set(name, runtime);
79
+ if (child.pid) {
80
+ this.registry?.record({
81
+ name,
82
+ pid: child.pid,
83
+ pgid: child.pid, // detached spawn → child.pid is the process-group leader
84
+ port: service.port,
85
+ kind,
86
+ host: kind === "ssh" ? service.host : undefined,
87
+ startedAt: runtime.status.startedAt ?? new Date().toISOString(),
88
+ ownerPid: process.pid,
89
+ });
90
+ }
69
91
  void this.appendTimeline({
70
92
  kind: "service.lifecycle",
71
93
  service: name,
@@ -87,6 +109,7 @@ export class ProcessManager {
87
109
  signal,
88
110
  };
89
111
  runtime.child = undefined;
112
+ this.registry?.remove(name);
90
113
  void this.stopInspector(runtime);
91
114
  void this.appendTimeline({
92
115
  kind: "service.lifecycle",
@@ -107,6 +130,7 @@ export class ProcessManager {
107
130
  exitCode: 1,
108
131
  signal: null,
109
132
  };
133
+ this.registry?.remove(name);
110
134
  void this.logStore.append(name, "stderr", error.message);
111
135
  void this.appendTimeline({
112
136
  kind: "service.lifecycle",
@@ -124,6 +148,13 @@ export class ProcessManager {
124
148
  return this.stopDockerComposeService(name, runtime);
125
149
  }
126
150
  if (!runtime?.child || runtime.status.state !== "running") {
151
+ // No live child in this session — a sibling session may own it. If the
152
+ // registry has a live entry, signal its process group to stop it.
153
+ const tracked = this.registry?.get(name);
154
+ if (tracked) {
155
+ await stopByPid(tracked.pid, tracked.pgid, this.stopTimeoutMs);
156
+ this.registry?.remove(name);
157
+ }
127
158
  const stopped = { name, state: "stopped" };
128
159
  this.runtimes.set(name, { status: stopped, stopping: false });
129
160
  void this.appendTimeline({
@@ -262,6 +293,9 @@ export class ProcessManager {
262
293
  continue;
263
294
  signalProcessTree(runtime.child, signal);
264
295
  }
296
+ // Drop this session's entries synchronously; the async exit handlers above
297
+ // may not run before the host process exits.
298
+ this.registry?.removeOwnedBy(process.pid);
265
299
  }
266
300
  installShutdownHandlers() {
267
301
  let firing = false;
@@ -289,12 +323,12 @@ export class ProcessManager {
289
323
  };
290
324
  }
291
325
  status() {
292
- return {
293
- services: Object.fromEntries([...this.runtimes.entries()].map(([name, runtime]) => [
294
- name,
295
- { ...runtime.status },
296
- ])),
297
- };
326
+ const services = {};
327
+ for (const [name, runtime] of this.runtimes.entries()) {
328
+ services[name] = { ...runtime.status };
329
+ }
330
+ this.mergeRegistry(services);
331
+ return { services };
298
332
  }
299
333
  async statusWithResources() {
300
334
  const services = {};
@@ -306,8 +340,29 @@ export class ProcessManager {
306
340
  status.inspector = this.inspectorStatus(runtime);
307
341
  services[name] = status;
308
342
  }
343
+ this.mergeRegistry(services);
344
+ for (const status of Object.values(services)) {
345
+ if (status.pid && status.state === "running" && !status.processTree) {
346
+ status.processTree = await readProcessTree(status.pid);
347
+ }
348
+ }
309
349
  return { services };
310
350
  }
351
+ /**
352
+ * Fold in services started by sibling sessions. A registry entry wins only
353
+ * when this session has no running view of that service, so a locally-owned
354
+ * "running" status is never overwritten by the shared snapshot.
355
+ */
356
+ mergeRegistry(services) {
357
+ if (!this.registry)
358
+ return;
359
+ for (const entry of this.registry.list()) {
360
+ const local = services[entry.name];
361
+ if (!local || local.state !== "running") {
362
+ services[entry.name] = registryEntryToStatus(entry);
363
+ }
364
+ }
365
+ }
311
366
  async startDockerComposeService(name, service) {
312
367
  const target = toDockerTarget(name, service);
313
368
  const info = await startDockerService(target);
@@ -392,6 +447,7 @@ export class ProcessManager {
392
447
  const runtime = this.runtimes.get(service);
393
448
  if (runtime) {
394
449
  runtime.status = { ...runtime.status, url };
450
+ this.registry?.update(service, { url });
395
451
  void this.maybeStartInspector(service);
396
452
  }
397
453
  void this.appendTimeline({
@@ -422,6 +478,49 @@ export class ProcessManager {
422
478
  function resolveKind(service) {
423
479
  return service.kind ?? "local";
424
480
  }
481
+ function registryEntryToStatus(entry) {
482
+ return {
483
+ name: entry.name,
484
+ state: "running",
485
+ kind: entry.kind,
486
+ pid: entry.pid,
487
+ url: entry.url,
488
+ host: entry.host,
489
+ startedAt: entry.startedAt,
490
+ };
491
+ }
492
+ /**
493
+ * Stop a process by pid when we hold no ChildProcess handle for it (it was
494
+ * spawned by another session). Signals the whole process group, then escalates
495
+ * to SIGKILL if it has not exited within the timeout.
496
+ */
497
+ async function stopByPid(pid, pgid, timeoutMs) {
498
+ signalPid(pid, pgid, "SIGTERM");
499
+ const deadline = Date.now() + timeoutMs;
500
+ while (Date.now() < deadline) {
501
+ if (!isPidAlive(pid))
502
+ return;
503
+ await new Promise((resolve) => setTimeout(resolve, 50));
504
+ }
505
+ signalPid(pid, pgid, "SIGKILL");
506
+ }
507
+ function signalPid(pid, pgid, signal) {
508
+ const group = pgid ?? pid;
509
+ try {
510
+ // Negative pid signals the whole process group (detached spawn → pgid===pid).
511
+ process.kill(-group, signal);
512
+ }
513
+ catch (error) {
514
+ if (error.code === "ESRCH")
515
+ return;
516
+ try {
517
+ process.kill(pid, signal);
518
+ }
519
+ catch {
520
+ // ignore
521
+ }
522
+ }
523
+ }
425
524
  function toDockerTarget(name, service) {
426
525
  if (!service.cwd || !service.composeService) {
427
526
  throw new Error(`Service "${name}" is missing docker-compose cwd or composeService.`);