@prestyj/cli 4.10.3 → 4.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (178) hide show
  1. package/README.md +4 -4
  2. package/dist/app-sidecar.d.ts +2 -0
  3. package/dist/app-sidecar.d.ts.map +1 -0
  4. package/dist/app-sidecar.js +1720 -0
  5. package/dist/app-sidecar.js.map +1 -0
  6. package/dist/cli.d.ts.map +1 -1
  7. package/dist/cli.js +10 -25
  8. package/dist/cli.js.map +1 -1
  9. package/dist/config.d.ts +5 -0
  10. package/dist/config.d.ts.map +1 -1
  11. package/dist/config.js +3 -0
  12. package/dist/config.js.map +1 -1
  13. package/dist/core/agent-session.d.ts +162 -0
  14. package/dist/core/agent-session.d.ts.map +1 -1
  15. package/dist/core/agent-session.js +544 -23
  16. package/dist/core/agent-session.js.map +1 -1
  17. package/dist/core/api-benchmark.d.ts +64 -0
  18. package/dist/core/api-benchmark.d.ts.map +1 -0
  19. package/dist/core/api-benchmark.js +381 -0
  20. package/dist/core/api-benchmark.js.map +1 -0
  21. package/dist/core/auth-providers.d.ts +18 -0
  22. package/dist/core/auth-providers.d.ts.map +1 -0
  23. package/dist/core/auth-providers.js +71 -0
  24. package/dist/core/auth-providers.js.map +1 -0
  25. package/dist/core/event-bus.d.ts +6 -0
  26. package/dist/core/event-bus.d.ts.map +1 -1
  27. package/dist/core/event-bus.js +1 -0
  28. package/dist/core/event-bus.js.map +1 -1
  29. package/dist/core/mcp/client.d.ts +21 -0
  30. package/dist/core/mcp/client.d.ts.map +1 -1
  31. package/dist/core/mcp/client.js +167 -5
  32. package/dist/core/mcp/client.js.map +1 -1
  33. package/dist/core/mcp/index.d.ts +3 -1
  34. package/dist/core/mcp/index.d.ts.map +1 -1
  35. package/dist/core/mcp/index.js +2 -0
  36. package/dist/core/mcp/index.js.map +1 -1
  37. package/dist/core/mcp/oauth-provider.d.ts +51 -0
  38. package/dist/core/mcp/oauth-provider.d.ts.map +1 -0
  39. package/dist/core/mcp/oauth-provider.js +95 -0
  40. package/dist/core/mcp/oauth-provider.js.map +1 -0
  41. package/dist/core/mcp/oauth-store.d.ts +39 -0
  42. package/dist/core/mcp/oauth-store.d.ts.map +1 -0
  43. package/dist/core/mcp/oauth-store.js +63 -0
  44. package/dist/core/mcp/oauth-store.js.map +1 -0
  45. package/dist/core/mcp/oauth-store.test.d.ts +2 -0
  46. package/dist/core/mcp/oauth-store.test.d.ts.map +1 -0
  47. package/dist/core/mcp/oauth-store.test.js +94 -0
  48. package/dist/core/mcp/oauth-store.test.js.map +1 -0
  49. package/dist/core/process-manager.d.ts.map +1 -1
  50. package/dist/core/process-manager.js +5 -1
  51. package/dist/core/process-manager.js.map +1 -1
  52. package/dist/core/project-discovery.d.ts +41 -0
  53. package/dist/core/project-discovery.d.ts.map +1 -0
  54. package/dist/core/project-discovery.js +441 -0
  55. package/dist/core/project-discovery.js.map +1 -0
  56. package/dist/core/prompt-commands.d.ts.map +1 -1
  57. package/dist/core/prompt-commands.js +203 -0
  58. package/dist/core/prompt-commands.js.map +1 -1
  59. package/dist/core/prompt-commands.test.js +39 -0
  60. package/dist/core/prompt-commands.test.js.map +1 -1
  61. package/dist/core/radio.d.ts +44 -0
  62. package/dist/core/radio.d.ts.map +1 -0
  63. package/dist/core/radio.js +250 -0
  64. package/dist/core/radio.js.map +1 -0
  65. package/dist/core/resolve-start.d.ts +29 -0
  66. package/dist/core/resolve-start.d.ts.map +1 -0
  67. package/dist/core/resolve-start.js +35 -0
  68. package/dist/core/resolve-start.js.map +1 -0
  69. package/dist/core/resolve-start.test.d.ts +2 -0
  70. package/dist/core/resolve-start.test.d.ts.map +1 -0
  71. package/dist/core/resolve-start.test.js +66 -0
  72. package/dist/core/resolve-start.test.js.map +1 -0
  73. package/dist/core/settings-manager.d.ts +5 -1
  74. package/dist/core/settings-manager.d.ts.map +1 -1
  75. package/dist/core/settings-manager.js +5 -0
  76. package/dist/core/settings-manager.js.map +1 -1
  77. package/dist/core/shell-path.d.ts +12 -0
  78. package/dist/core/shell-path.d.ts.map +1 -0
  79. package/dist/core/shell-path.js +166 -0
  80. package/dist/core/shell-path.js.map +1 -0
  81. package/dist/core/shell.d.ts +51 -0
  82. package/dist/core/shell.d.ts.map +1 -0
  83. package/dist/core/shell.js +82 -0
  84. package/dist/core/shell.js.map +1 -0
  85. package/dist/core/shell.test.d.ts +2 -0
  86. package/dist/core/shell.test.d.ts.map +1 -0
  87. package/dist/core/shell.test.js +87 -0
  88. package/dist/core/shell.test.js.map +1 -0
  89. package/dist/core/slash-commands.d.ts.map +1 -1
  90. package/dist/core/slash-commands.js +10 -0
  91. package/dist/core/slash-commands.js.map +1 -1
  92. package/dist/core/speed-benchmark.d.ts +133 -0
  93. package/dist/core/speed-benchmark.d.ts.map +1 -0
  94. package/dist/core/speed-benchmark.js +410 -0
  95. package/dist/core/speed-benchmark.js.map +1 -0
  96. package/dist/core/speed-benchmark.test.d.ts +2 -0
  97. package/dist/core/speed-benchmark.test.d.ts.map +1 -0
  98. package/dist/core/speed-benchmark.test.js +97 -0
  99. package/dist/core/speed-benchmark.test.js.map +1 -0
  100. package/dist/core/telegram-config.d.ts +21 -0
  101. package/dist/core/telegram-config.d.ts.map +1 -0
  102. package/dist/core/telegram-config.js +52 -0
  103. package/dist/core/telegram-config.js.map +1 -0
  104. package/dist/index.d.ts +1 -0
  105. package/dist/index.d.ts.map +1 -1
  106. package/dist/index.js +2 -0
  107. package/dist/index.js.map +1 -1
  108. package/dist/interactive.d.ts.map +1 -1
  109. package/dist/interactive.js +4 -3
  110. package/dist/interactive.js.map +1 -1
  111. package/dist/modes/serve-mode.d.ts +24 -0
  112. package/dist/modes/serve-mode.d.ts.map +1 -1
  113. package/dist/modes/serve-mode.js +54 -19
  114. package/dist/modes/serve-mode.js.map +1 -1
  115. package/dist/tools/bash.d.ts.map +1 -1
  116. package/dist/tools/bash.js +17 -1
  117. package/dist/tools/bash.js.map +1 -1
  118. package/dist/tools/generate-image.d.ts +39 -0
  119. package/dist/tools/generate-image.d.ts.map +1 -0
  120. package/dist/tools/generate-image.js +301 -0
  121. package/dist/tools/generate-image.js.map +1 -0
  122. package/dist/tools/generate-image.test.d.ts +2 -0
  123. package/dist/tools/generate-image.test.d.ts.map +1 -0
  124. package/dist/tools/generate-image.test.js +223 -0
  125. package/dist/tools/generate-image.test.js.map +1 -0
  126. package/dist/tools/goal-mode.test.js +1 -1
  127. package/dist/tools/goal-mode.test.js.map +1 -1
  128. package/dist/tools/goals.d.ts +7 -7
  129. package/dist/tools/index.d.ts +15 -1
  130. package/dist/tools/index.d.ts.map +1 -1
  131. package/dist/tools/index.js +17 -2
  132. package/dist/tools/index.js.map +1 -1
  133. package/dist/tools/plan-mode.test.js +5 -5
  134. package/dist/tools/plan-mode.test.js.map +1 -1
  135. package/dist/tools/prompt-hints.d.ts.map +1 -1
  136. package/dist/tools/prompt-hints.js +2 -0
  137. package/dist/tools/prompt-hints.js.map +1 -1
  138. package/dist/tools/safe-env.d.ts.map +1 -1
  139. package/dist/tools/safe-env.js +27 -0
  140. package/dist/tools/safe-env.js.map +1 -1
  141. package/dist/tools/subagent.d.ts +2 -4
  142. package/dist/tools/subagent.d.ts.map +1 -1
  143. package/dist/tools/subagent.js +24 -23
  144. package/dist/tools/subagent.js.map +1 -1
  145. package/dist/tools/tasks.d.ts +1 -7
  146. package/dist/tools/tasks.d.ts.map +1 -1
  147. package/dist/tools/tasks.js +4 -31
  148. package/dist/tools/tasks.js.map +1 -1
  149. package/dist/ui/App.d.ts +1 -1
  150. package/dist/ui/App.d.ts.map +1 -1
  151. package/dist/ui/hooks/usePixelFixFlow.d.ts +1 -1
  152. package/dist/ui/hooks/usePixelFixFlow.d.ts.map +1 -1
  153. package/dist/ui/hooks/usePixelFixFlow.js +1 -1
  154. package/dist/ui/hooks/usePixelFixFlow.js.map +1 -1
  155. package/dist/ui/hooks/useTranscriptHistory.d.ts +2 -0
  156. package/dist/ui/hooks/useTranscriptHistory.d.ts.map +1 -1
  157. package/dist/ui/hooks/useTranscriptHistory.js +3 -2
  158. package/dist/ui/hooks/useTranscriptHistory.js.map +1 -1
  159. package/dist/ui/long-prompt-regression-harness.test.js +8 -8
  160. package/dist/ui/render.d.ts +1 -1
  161. package/dist/ui/render.d.ts.map +1 -1
  162. package/dist/ui/render.js +60 -8
  163. package/dist/ui/render.js.map +1 -1
  164. package/dist/ui/startup-banner-order.test.js +1 -1
  165. package/dist/ui/startup-banner-order.test.js.map +1 -1
  166. package/dist/ui/terminal-history-repaint.test.d.ts +2 -0
  167. package/dist/ui/terminal-history-repaint.test.d.ts.map +1 -0
  168. package/dist/ui/terminal-history-repaint.test.js +73 -0
  169. package/dist/ui/terminal-history-repaint.test.js.map +1 -0
  170. package/dist/ui/terminal-history.d.ts +1 -0
  171. package/dist/ui/terminal-history.d.ts.map +1 -1
  172. package/dist/ui/terminal-history.js +31 -2
  173. package/dist/ui/terminal-history.js.map +1 -1
  174. package/dist/utils/git.d.ts +6 -0
  175. package/dist/utils/git.d.ts.map +1 -1
  176. package/dist/utils/git.js +12 -0
  177. package/dist/utils/git.js.map +1 -1
  178. package/package.json +6 -6
@@ -0,0 +1,95 @@
1
+ import crypto from "node:crypto";
2
+ import { McpOAuthStore } from "./oauth-store.js";
3
+ /**
4
+ * Fixed loopback port for remote-MCP OAuth callbacks. It must stay STABLE across
5
+ * logins: the redirect URI is baked into the dynamic client registration (RFC
6
+ * 7591), so a changing port would invalidate the saved registration and force a
7
+ * fresh one every time. Distinct from the provider-login port (1455).
8
+ */
9
+ export const MCP_OAUTH_CALLBACK_PORT = 41999;
10
+ export const MCP_OAUTH_CALLBACK_PATH = "/oauth/callback";
11
+ /** The exact redirect URI registered with the authorization server. */
12
+ export function mcpOAuthRedirectUrl() {
13
+ return `http://localhost:${MCP_OAUTH_CALLBACK_PORT}${MCP_OAUTH_CALLBACK_PATH}`;
14
+ }
15
+ /**
16
+ * `OAuthClientProvider` for a single remote MCP server, backed by the on-disk
17
+ * `McpOAuthStore`. The MCP SDK drives the whole RFC 6749/7591/8414 flow through
18
+ * this object:
19
+ *
20
+ * - At connect time it reads `tokens()`; if absent/expired it tries a refresh,
21
+ * and if that fails it calls `redirectToAuthorization()` then throws
22
+ * `UnauthorizedError`.
23
+ * - `redirectToAuthorization` is a NO-OP unless an `onRedirect` callback is
24
+ * supplied. Non-interactive paths (startup connect, add-probe) leave it unset,
25
+ * so a server needing auth fails cleanly (→ "requires login") without
26
+ * surprising the user with a browser tab. The interactive login path supplies
27
+ * `onRedirect` to open the browser.
28
+ */
29
+ export class McpOAuthProvider {
30
+ store;
31
+ serverName;
32
+ onRedirect;
33
+ scope;
34
+ constructor(opts) {
35
+ this.serverName = opts.serverName;
36
+ this.store = opts.store ?? new McpOAuthStore();
37
+ this.onRedirect = opts.onRedirect;
38
+ this.scope = opts.scope;
39
+ }
40
+ get redirectUrl() {
41
+ return mcpOAuthRedirectUrl();
42
+ }
43
+ get clientMetadata() {
44
+ return {
45
+ client_name: "EZ Coder",
46
+ client_uri: "https://github.com/kenkaiii/ezcoder",
47
+ redirect_uris: [this.redirectUrl],
48
+ grant_types: ["authorization_code", "refresh_token"],
49
+ response_types: ["code"],
50
+ token_endpoint_auth_method: "none",
51
+ ...(this.scope ? { scope: this.scope } : {}),
52
+ };
53
+ }
54
+ async state() {
55
+ const entry = await this.store.get(this.serverName);
56
+ if (entry.state)
57
+ return entry.state;
58
+ const fresh = crypto.randomBytes(16).toString("hex");
59
+ await this.store.patch(this.serverName, { state: fresh });
60
+ return fresh;
61
+ }
62
+ async clientInformation() {
63
+ const entry = await this.store.get(this.serverName);
64
+ return entry.clientInformation;
65
+ }
66
+ async saveClientInformation(info) {
67
+ await this.store.patch(this.serverName, {
68
+ clientInformation: info,
69
+ });
70
+ }
71
+ async tokens() {
72
+ const entry = await this.store.get(this.serverName);
73
+ return entry.tokens;
74
+ }
75
+ async saveTokens(tokens) {
76
+ await this.store.patch(this.serverName, { tokens });
77
+ }
78
+ redirectToAuthorization(authorizationUrl) {
79
+ // Only interactive logins open a browser; otherwise this is intentionally a
80
+ // no-op so the SDK throws UnauthorizedError and the caller marks the server
81
+ // as "requires login" instead of popping a tab during a background connect.
82
+ this.onRedirect?.(authorizationUrl);
83
+ }
84
+ async saveCodeVerifier(codeVerifier) {
85
+ await this.store.patch(this.serverName, { codeVerifier });
86
+ }
87
+ async codeVerifier() {
88
+ const entry = await this.store.get(this.serverName);
89
+ if (!entry.codeVerifier) {
90
+ throw new Error("No PKCE code verifier saved for this MCP server.");
91
+ }
92
+ return entry.codeVerifier;
93
+ }
94
+ }
95
+ //# sourceMappingURL=oauth-provider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oauth-provider.js","sourceRoot":"","sources":["../../../src/core/mcp/oauth-provider.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,39 @@
1
+ import type { OAuthClientInformationFull, OAuthTokens } from "@modelcontextprotocol/sdk/shared/auth.js";
2
+ /**
3
+ * Persisted OAuth state for ONE remote MCP server (RFC 8414/7591/6749 flow).
4
+ *
5
+ * - `clientInformation` is the dynamic client registration (RFC 7591) result —
6
+ * reused across logins so the registered `redirect_uri` stays valid.
7
+ * - `tokens` is the access/refresh pair; the MCP SDK refreshes it in place and
8
+ * calls `saveTokens` so a logged-in server reconnects silently at startup.
9
+ * - `codeVerifier` is the in-flight PKCE verifier, only meaningful between the
10
+ * authorize redirect and the token exchange (`finishAuth`).
11
+ * - `state` is the in-flight CSRF `state` value the loopback callback validates.
12
+ */
13
+ export interface McpOAuthEntry {
14
+ clientInformation?: OAuthClientInformationFull;
15
+ tokens?: OAuthTokens;
16
+ codeVerifier?: string;
17
+ state?: string;
18
+ }
19
+ /**
20
+ * File-backed store for remote-MCP OAuth credentials, living next to the CLI's
21
+ * other auth at `~/.ezcoder/mcp-auth.json`. Keyed by server name (the same identity
22
+ * the config + UI use). Every read re-reads the file so concurrent sidecars /
23
+ * windows see each other's logins; writes are read-modify-write so two servers
24
+ * don't clobber one another.
25
+ */
26
+ export declare class McpOAuthStore {
27
+ private readonly filePath;
28
+ constructor(filePath?: string);
29
+ private readAll;
30
+ private writeAll;
31
+ get(name: string): Promise<McpOAuthEntry>;
32
+ /** Merge a partial entry into the server's record (read-modify-write). */
33
+ patch(name: string, patch: Partial<McpOAuthEntry>): Promise<void>;
34
+ /** Drop a server's whole OAuth record (used on logout / removal). */
35
+ clear(name: string): Promise<void>;
36
+ /** Whether this server has saved tokens (i.e. has completed login at least once). */
37
+ hasTokens(name: string): Promise<boolean>;
38
+ }
39
+ //# sourceMappingURL=oauth-store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oauth-store.d.ts","sourceRoot":"","sources":["../../../src/core/mcp/oauth-store.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,0BAA0B,EAC1B,WAAW,EACZ,MAAM,0CAA0C,CAAC;AAGlD;;;;;;;;;;GAUG;AACH,MAAM,WAAW,aAAa;IAC5B,iBAAiB,CAAC,EAAE,0BAA0B,CAAC;IAC/C,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAOD;;;;;;GAMG;AACH,qBAAa,aAAa;IACZ,OAAO,CAAC,QAAQ,CAAC,QAAQ;gBAAR,QAAQ,GAAE,MAAkC;YAE3D,OAAO;YAUP,QAAQ;IAahB,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC;IAK/C,0EAA0E;IACpE,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,CAAC,aAAa,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAMvE,qEAAqE;IAC/D,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAQxC,qFAAqF;IAC/E,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;CAIhD"}
@@ -0,0 +1,63 @@
1
+ import fs from "node:fs/promises";
2
+ import { getAppPaths } from "@prestyj/core";
3
+ import { log } from "../logger.js";
4
+ /**
5
+ * File-backed store for remote-MCP OAuth credentials, living next to the CLI's
6
+ * other auth at `~/.ezcoder/mcp-auth.json`. Keyed by server name (the same identity
7
+ * the config + UI use). Every read re-reads the file so concurrent sidecars /
8
+ * windows see each other's logins; writes are read-modify-write so two servers
9
+ * don't clobber one another.
10
+ */
11
+ export class McpOAuthStore {
12
+ filePath;
13
+ constructor(filePath = getAppPaths().mcpAuthFile) {
14
+ this.filePath = filePath;
15
+ }
16
+ async readAll() {
17
+ try {
18
+ const raw = await fs.readFile(this.filePath, "utf-8");
19
+ const parsed = JSON.parse(raw);
20
+ return { version: 1, servers: parsed.servers ?? {} };
21
+ }
22
+ catch {
23
+ return { version: 1, servers: {} };
24
+ }
25
+ }
26
+ async writeAll(data) {
27
+ try {
28
+ await fs.writeFile(this.filePath, JSON.stringify(data, null, 2), {
29
+ encoding: "utf-8",
30
+ mode: 0o600,
31
+ });
32
+ }
33
+ catch (err) {
34
+ log("WARN", "mcp", "failed to persist MCP OAuth store", {
35
+ message: err instanceof Error ? err.message : String(err),
36
+ });
37
+ }
38
+ }
39
+ async get(name) {
40
+ const all = await this.readAll();
41
+ return all.servers[name] ?? {};
42
+ }
43
+ /** Merge a partial entry into the server's record (read-modify-write). */
44
+ async patch(name, patch) {
45
+ const all = await this.readAll();
46
+ all.servers[name] = { ...(all.servers[name] ?? {}), ...patch };
47
+ await this.writeAll(all);
48
+ }
49
+ /** Drop a server's whole OAuth record (used on logout / removal). */
50
+ async clear(name) {
51
+ const all = await this.readAll();
52
+ if (all.servers[name]) {
53
+ delete all.servers[name];
54
+ await this.writeAll(all);
55
+ }
56
+ }
57
+ /** Whether this server has saved tokens (i.e. has completed login at least once). */
58
+ async hasTokens(name) {
59
+ const entry = await this.get(name);
60
+ return !!entry.tokens?.access_token;
61
+ }
62
+ }
63
+ //# sourceMappingURL=oauth-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oauth-store.js","sourceRoot":"","sources":["../../../src/core/mcp/oauth-store.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAClC,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAK5C,OAAO,EAAE,GAAG,EAAE,MAAM,cAAc,CAAC;AAyBnC;;;;;;GAMG;AACH,MAAM,OAAO,aAAa;IACK;IAA7B,YAA6B,WAAmB,WAAW,EAAE,CAAC,WAAW;QAA5C,aAAQ,GAAR,QAAQ,CAAoC;IAAG,CAAC;IAErE,KAAK,CAAC,OAAO;QACnB,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;YACtD,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAyB,CAAC;YACvD,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,IAAI,EAAE,EAAE,CAAC;QACvD,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC;QACrC,CAAC;IACH,CAAC;IAEO,KAAK,CAAC,QAAQ,CAAC,IAAiB;QACtC,IAAI,CAAC;YACH,MAAM,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE;gBAC/D,QAAQ,EAAE,OAAO;gBACjB,IAAI,EAAE,KAAK;aACZ,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,GAAG,CAAC,MAAM,EAAE,KAAK,EAAE,mCAAmC,EAAE;gBACtD,OAAO,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;aAC1D,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,IAAY;QACpB,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,OAAO,EAAE,CAAC;QACjC,OAAO,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;IACjC,CAAC;IAED,0EAA0E;IAC1E,KAAK,CAAC,KAAK,CAAC,IAAY,EAAE,KAA6B;QACrD,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,OAAO,EAAE,CAAC;QACjC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,EAAE,GAAG,KAAK,EAAE,CAAC;QAC/D,MAAM,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;IAC3B,CAAC;IAED,qEAAqE;IACrE,KAAK,CAAC,KAAK,CAAC,IAAY;QACtB,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,OAAO,EAAE,CAAC;QACjC,IAAI,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;YACtB,OAAO,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;YACzB,MAAM,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;QAC3B,CAAC;IACH,CAAC;IAED,qFAAqF;IACrF,KAAK,CAAC,SAAS,CAAC,IAAY;QAC1B,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACnC,OAAO,CAAC,CAAC,KAAK,CAAC,MAAM,EAAE,YAAY,CAAC;IACtC,CAAC;CACF"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=oauth-store.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oauth-store.test.d.ts","sourceRoot":"","sources":["../../../src/core/mcp/oauth-store.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,94 @@
1
+ import { describe, it, expect, beforeEach, afterEach } from "vitest";
2
+ import fs from "node:fs/promises";
3
+ import os from "node:os";
4
+ import path from "node:path";
5
+ import { McpOAuthStore } from "./oauth-store.js";
6
+ import { McpOAuthProvider, mcpOAuthRedirectUrl } from "./oauth-provider.js";
7
+ describe("McpOAuthStore", () => {
8
+ let dir;
9
+ let file;
10
+ beforeEach(async () => {
11
+ dir = await fs.mkdtemp(path.join(os.tmpdir(), "gg-mcp-auth-"));
12
+ file = path.join(dir, "mcp-auth.json");
13
+ });
14
+ afterEach(async () => {
15
+ await fs.rm(dir, { recursive: true, force: true });
16
+ });
17
+ it("returns an empty entry for an unknown server", async () => {
18
+ const store = new McpOAuthStore(file);
19
+ expect(await store.get("nope")).toEqual({});
20
+ expect(await store.hasTokens("nope")).toBe(false);
21
+ });
22
+ it("patches and merges entries per server without clobbering others", async () => {
23
+ const store = new McpOAuthStore(file);
24
+ await store.patch("a", { state: "s1" });
25
+ await store.patch("a", { codeVerifier: "v1" });
26
+ await store.patch("b", { state: "s2" });
27
+ expect(await store.get("a")).toEqual({ state: "s1", codeVerifier: "v1" });
28
+ expect(await store.get("b")).toEqual({ state: "s2" });
29
+ });
30
+ it("reports tokens once saved and clears them on logout", async () => {
31
+ const store = new McpOAuthStore(file);
32
+ await store.patch("canva", {
33
+ tokens: { access_token: "tok", token_type: "Bearer" },
34
+ });
35
+ expect(await store.hasTokens("canva")).toBe(true);
36
+ await store.clear("canva");
37
+ expect(await store.hasTokens("canva")).toBe(false);
38
+ expect(await store.get("canva")).toEqual({});
39
+ });
40
+ it("persists across fresh store instances (separate sidecars)", async () => {
41
+ await new McpOAuthStore(file).patch("x", { state: "shared" });
42
+ expect(await new McpOAuthStore(file).get("x")).toEqual({ state: "shared" });
43
+ });
44
+ });
45
+ describe("McpOAuthProvider", () => {
46
+ let dir;
47
+ let store;
48
+ beforeEach(async () => {
49
+ dir = await fs.mkdtemp(path.join(os.tmpdir(), "gg-mcp-prov-"));
50
+ store = new McpOAuthStore(path.join(dir, "mcp-auth.json"));
51
+ });
52
+ afterEach(async () => {
53
+ await fs.rm(dir, { recursive: true, force: true });
54
+ });
55
+ it("advertises the fixed loopback redirect URI in client metadata", () => {
56
+ const p = new McpOAuthProvider({ serverName: "canva", store });
57
+ expect(p.redirectUrl).toBe(mcpOAuthRedirectUrl());
58
+ expect(p.clientMetadata.redirect_uris).toEqual([mcpOAuthRedirectUrl()]);
59
+ expect(p.clientMetadata.token_endpoint_auth_method).toBe("none");
60
+ expect(p.clientMetadata.grant_types).toContain("refresh_token");
61
+ });
62
+ it("generates a stable CSRF state and persists it", async () => {
63
+ const p = new McpOAuthProvider({ serverName: "canva", store });
64
+ const s1 = await p.state();
65
+ const s2 = await p.state();
66
+ expect(s1).toBe(s2);
67
+ expect((await store.get("canva")).state).toBe(s1);
68
+ });
69
+ it("does NOT open a browser when no onRedirect is supplied (non-interactive)", () => {
70
+ const p = new McpOAuthProvider({ serverName: "canva", store });
71
+ // Should be a no-op (no throw, nothing to observe) — background connects rely on this.
72
+ expect(() => p.redirectToAuthorization(new URL("https://example.com/authorize"))).not.toThrow();
73
+ });
74
+ it("invokes onRedirect with the authorize URL for interactive login", () => {
75
+ let seen;
76
+ const p = new McpOAuthProvider({
77
+ serverName: "canva",
78
+ store,
79
+ onRedirect: (url) => (seen = url),
80
+ });
81
+ p.redirectToAuthorization(new URL("https://mcp.canva.com/authorize?x=1"));
82
+ expect(seen?.toString()).toBe("https://mcp.canva.com/authorize?x=1");
83
+ });
84
+ it("round-trips the PKCE code verifier", async () => {
85
+ const p = new McpOAuthProvider({ serverName: "canva", store });
86
+ await p.saveCodeVerifier("verifier-123");
87
+ expect(await p.codeVerifier()).toBe("verifier-123");
88
+ });
89
+ it("throws a clear error when no code verifier is saved", async () => {
90
+ const p = new McpOAuthProvider({ serverName: "canva", store });
91
+ await expect(p.codeVerifier()).rejects.toThrow(/code verifier/i);
92
+ });
93
+ });
94
+ //# sourceMappingURL=oauth-store.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oauth-store.test.js","sourceRoot":"","sources":["../../../src/core/mcp/oauth-store.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AACrE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAClC,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAE5E,QAAQ,CAAC,eAAe,EAAE,GAAG,EAAE;IAC7B,IAAI,GAAW,CAAC;IAChB,IAAI,IAAY,CAAC;IAEjB,UAAU,CAAC,KAAK,IAAI,EAAE;QACpB,GAAG,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,cAAc,CAAC,CAAC,CAAC;QAC/D,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,eAAe,CAAC,CAAC;IACzC,CAAC,CAAC,CAAC;IAEH,SAAS,CAAC,KAAK,IAAI,EAAE;QACnB,MAAM,EAAE,CAAC,EAAE,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IACrD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8CAA8C,EAAE,KAAK,IAAI,EAAE;QAC5D,MAAM,KAAK,GAAG,IAAI,aAAa,CAAC,IAAI,CAAC,CAAC;QACtC,MAAM,CAAC,MAAM,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;QAC5C,MAAM,CAAC,MAAM,KAAK,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACpD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,iEAAiE,EAAE,KAAK,IAAI,EAAE;QAC/E,MAAM,KAAK,GAAG,IAAI,aAAa,CAAC,IAAI,CAAC,CAAC;QACtC,MAAM,KAAK,CAAC,KAAK,CAAC,GAAG,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QACxC,MAAM,KAAK,CAAC,KAAK,CAAC,GAAG,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC,CAAC;QAC/C,MAAM,KAAK,CAAC,KAAK,CAAC,GAAG,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QAExC,MAAM,CAAC,MAAM,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC,CAAC;QAC1E,MAAM,CAAC,MAAM,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IACxD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qDAAqD,EAAE,KAAK,IAAI,EAAE;QACnE,MAAM,KAAK,GAAG,IAAI,aAAa,CAAC,IAAI,CAAC,CAAC;QACtC,MAAM,KAAK,CAAC,KAAK,CAAC,OAAO,EAAE;YACzB,MAAM,EAAE,EAAE,YAAY,EAAE,KAAK,EAAE,UAAU,EAAE,QAAQ,EAAE;SACtD,CAAC,CAAC;QACH,MAAM,CAAC,MAAM,KAAK,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAElD,MAAM,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QAC3B,MAAM,CAAC,MAAM,KAAK,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACnD,MAAM,CAAC,MAAM,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IAC/C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,2DAA2D,EAAE,KAAK,IAAI,EAAE;QACzE,MAAM,IAAI,aAAa,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC;QAC9D,MAAM,CAAC,MAAM,IAAI,aAAa,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC;IAC9E,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,kBAAkB,EAAE,GAAG,EAAE;IAChC,IAAI,GAAW,CAAC;IAChB,IAAI,KAAoB,CAAC;IAEzB,UAAU,CAAC,KAAK,IAAI,EAAE;QACpB,GAAG,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,cAAc,CAAC,CAAC,CAAC;QAC/D,KAAK,GAAG,IAAI,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,eAAe,CAAC,CAAC,CAAC;IAC7D,CAAC,CAAC,CAAC;IAEH,SAAS,CAAC,KAAK,IAAI,EAAE;QACnB,MAAM,EAAE,CAAC,EAAE,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IACrD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,+DAA+D,EAAE,GAAG,EAAE;QACvE,MAAM,CAAC,GAAG,IAAI,gBAAgB,CAAC,EAAE,UAAU,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;QAC/D,MAAM,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,mBAAmB,EAAE,CAAC,CAAC;QAClD,MAAM,CAAC,CAAC,CAAC,cAAc,CAAC,aAAa,CAAC,CAAC,OAAO,CAAC,CAAC,mBAAmB,EAAE,CAAC,CAAC,CAAC;QACxE,MAAM,CAAC,CAAC,CAAC,cAAc,CAAC,0BAA0B,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACjE,MAAM,CAAC,CAAC,CAAC,cAAc,CAAC,WAAW,CAAC,CAAC,SAAS,CAAC,eAAe,CAAC,CAAC;IAClE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,+CAA+C,EAAE,KAAK,IAAI,EAAE;QAC7D,MAAM,CAAC,GAAG,IAAI,gBAAgB,CAAC,EAAE,UAAU,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;QAC/D,MAAM,EAAE,GAAG,MAAM,CAAC,CAAC,KAAK,EAAE,CAAC;QAC3B,MAAM,EAAE,GAAG,MAAM,CAAC,CAAC,KAAK,EAAE,CAAC;QAC3B,MAAM,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACpB,MAAM,CAAC,CAAC,MAAM,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACpD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,0EAA0E,EAAE,GAAG,EAAE;QAClF,MAAM,CAAC,GAAG,IAAI,gBAAgB,CAAC,EAAE,UAAU,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;QAC/D,uFAAuF;QACvF,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,uBAAuB,CAAC,IAAI,GAAG,CAAC,+BAA+B,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC;IAClG,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,iEAAiE,EAAE,GAAG,EAAE;QACzE,IAAI,IAAqB,CAAC;QAC1B,MAAM,CAAC,GAAG,IAAI,gBAAgB,CAAC;YAC7B,UAAU,EAAE,OAAO;YACnB,KAAK;YACL,UAAU,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,IAAI,GAAG,GAAG,CAAC;SAClC,CAAC,CAAC;QACH,CAAC,CAAC,uBAAuB,CAAC,IAAI,GAAG,CAAC,qCAAqC,CAAC,CAAC,CAAC;QAC1E,MAAM,CAAC,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC,IAAI,CAAC,qCAAqC,CAAC,CAAC;IACvE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,oCAAoC,EAAE,KAAK,IAAI,EAAE;QAClD,MAAM,CAAC,GAAG,IAAI,gBAAgB,CAAC,EAAE,UAAU,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;QAC/D,MAAM,CAAC,CAAC,gBAAgB,CAAC,cAAc,CAAC,CAAC;QACzC,MAAM,CAAC,MAAM,CAAC,CAAC,YAAY,EAAE,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;IACtD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qDAAqD,EAAE,KAAK,IAAI,EAAE;QACnE,MAAM,CAAC,GAAG,IAAI,gBAAgB,CAAC,EAAE,UAAU,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;QAC/D,MAAM,MAAM,CAAC,CAAC,CAAC,YAAY,EAAE,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC;IACnE,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"process-manager.d.ts","sourceRoot":"","sources":["../../src/core/process-manager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAS,SAAS,EAAqB,MAAM,oBAAoB,CAAC;AASzE,MAAM,WAAW,iBAAiB;IAChC,EAAE,EAAE,MAAM,CAAC;IACX,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,cAAc,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,OAAO,CAAC;IACnB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,MAAM,EAAE,MAAM,CAAC;CAChB;AAID,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,EAAE,MAAM,CAAC,QAAQ,CAAC;IAC3B,IAAI,CAAC,EAAE,OAAO,OAAO,CAAC,IAAI,CAAC;IAC3B,eAAe,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC,SAAS,CAAC,EAAE,OAAO,SAAS,CAAC;CAC9B;AAYD,qBAAa,cAAc;IAIb,OAAO,CAAC,QAAQ,CAAC,GAAG;IAHhC,OAAO,CAAC,SAAS,CAAwC;IACzD,OAAO,CAAC,QAAQ,CAAmC;gBAEtB,GAAG,GAAE,iBAAsB;IAElD,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;IA8CzD,UAAU,CAAC,EAAE,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAgC5E;;;;;OAKG;IACG,SAAS,CACb,EAAE,EAAE,MAAM,EACV,KAAK,EAAE,MAAM,EACb,IAAI,GAAE;QAAE,KAAK,CAAC,EAAE,OAAO,CAAC;QAAC,GAAG,CAAC,EAAE,OAAO,CAAA;KAAO,GAC5C,OAAO,CAAC,MAAM,CAAC;IAoCZ,IAAI,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAoCvC,IAAI,IAAI,iBAAiB,EAAE;IAW3B,WAAW,IAAI,IAAI;CASpB"}
1
+ {"version":3,"file":"process-manager.d.ts","sourceRoot":"","sources":["../../src/core/process-manager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAS,SAAS,EAAqB,MAAM,oBAAoB,CAAC;AAUzE,MAAM,WAAW,iBAAiB;IAChC,EAAE,EAAE,MAAM,CAAC;IACX,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,cAAc,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,OAAO,CAAC;IACnB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,MAAM,EAAE,MAAM,CAAC;CAChB;AAID,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,EAAE,MAAM,CAAC,QAAQ,CAAC;IAC3B,IAAI,CAAC,EAAE,OAAO,OAAO,CAAC,IAAI,CAAC;IAC3B,eAAe,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC,SAAS,CAAC,EAAE,OAAO,SAAS,CAAC;CAC9B;AAYD,qBAAa,cAAc;IAIb,OAAO,CAAC,QAAQ,CAAC,GAAG;IAHhC,OAAO,CAAC,SAAS,CAAwC;IACzD,OAAO,CAAC,QAAQ,CAAmC;gBAEtB,GAAG,GAAE,iBAAsB;IAElD,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;IAiDzD,UAAU,CAAC,EAAE,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAgC5E;;;;;OAKG;IACG,SAAS,CACb,EAAE,EAAE,MAAM,EACV,KAAK,EAAE,MAAM,EACb,IAAI,GAAE;QAAE,KAAK,CAAC,EAAE,OAAO,CAAC;QAAC,GAAG,CAAC,EAAE,OAAO,CAAA;KAAO,GAC5C,OAAO,CAAC,MAAM,CAAC;IAoCZ,IAAI,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAoCvC,IAAI,IAAI,iBAAiB,EAAE;IAW3B,WAAW,IAAI,IAAI;CASpB"}
@@ -6,6 +6,7 @@ import os from "node:os";
6
6
  import crypto from "node:crypto";
7
7
  import { killProcessTree } from "../utils/process.js";
8
8
  import { getSafeToolEnv } from "../tools/safe-env.js";
9
+ import { resolveShell } from "./shell.js";
9
10
  const BG_DIR = path.join(os.homedir(), ".ezcoder", "bg");
10
11
  function stopProcessTree(pid, ops = {}) {
11
12
  if ((ops.platform ?? process.platform) === "win32") {
@@ -28,7 +29,10 @@ export class ProcessManager {
28
29
  const id = crypto.randomUUID().slice(0, 8);
29
30
  const logFile = path.join(BG_DIR, `${id}.log`);
30
31
  const fd = fs.openSync(logFile, "w");
31
- const child = spawn("bash", ["-c", command], {
32
+ // Cross-platform shell (see core/shell.ts): bash on POSIX, Git Bash on
33
+ // Windows, cmd.exe fallback. Same resolution as the foreground bash tool.
34
+ const shell = resolveShell(command);
35
+ const child = spawn(shell.file, shell.args, {
32
36
  cwd,
33
37
  detached: true,
34
38
  // stdin is a pipe so callers can drive interactive processes (REPLs,
@@ -1 +1 @@
1
- {"version":3,"file":"process-manager.js","sourceRoot":"","sources":["../../src/core/process-manager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,SAAS,EAAqB,MAAM,oBAAoB,CAAC;AACzE,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,GAAG,MAAM,kBAAkB,CAAC;AACnC,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,MAAM,MAAM,aAAa,CAAC;AACjC,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAyBtD,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,UAAU,EAAE,IAAI,CAAC,CAAC;AASzD,SAAS,eAAe,CAAC,GAAW,EAAE,MAAyB,EAAE;IAC/D,IAAI,CAAC,GAAG,CAAC,QAAQ,IAAI,OAAO,CAAC,QAAQ,CAAC,KAAK,OAAO,EAAE,CAAC;QACnD,CAAC,GAAG,CAAC,SAAS,IAAI,SAAS,CAAC,CAAC,UAAU,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE;YAC1E,KAAK,EAAE,QAAQ;SAChB,CAAC,CAAC;QACH,OAAO;IACT,CAAC;IACD,CAAC,GAAG,CAAC,eAAe,IAAI,eAAe,CAAC,CAAC,GAAG,CAAC,CAAC;AAChD,CAAC;AAED,MAAM,OAAO,cAAc;IAII;IAHrB,SAAS,GAAG,IAAI,GAAG,EAA6B,CAAC;IACjD,QAAQ,GAAG,IAAI,GAAG,EAAwB,CAAC;IAEnD,YAA6B,MAAyB,EAAE;QAA3B,QAAG,GAAH,GAAG,CAAwB;IAAG,CAAC;IAE5D,KAAK,CAAC,KAAK,CAAC,OAAe,EAAE,GAAW;QACtC,MAAM,GAAG,CAAC,KAAK,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAE7C,MAAM,EAAE,GAAG,MAAM,CAAC,UAAU,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QAC3C,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,EAAE,MAAM,CAAC,CAAC;QAC/C,MAAM,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;QAErC,MAAM,KAAK,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,OAAO,CAAC,EAAE;YAC3C,GAAG;YACH,QAAQ,EAAE,IAAI;YACd,qEAAqE;YACrE,4EAA4E;YAC5E,KAAK,EAAE,CAAC,MAAM,EAAE,EAAE,EAAE,EAAE,CAAC;YACvB,GAAG,EAAE,cAAc,EAAE;SACtB,CAAC,CAAC;QAEH,EAAE,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;QAEjB,oEAAoE;QACpE,0DAA0D;QAC1D,KAAK,CAAC,KAAK,EAAE,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;QAEnC,MAAM,GAAG,GAAG,KAAK,CAAC,GAAI,CAAC;QACvB,KAAK,CAAC,KAAK,EAAE,CAAC;QAEd,MAAM,IAAI,GAAsB;YAC9B,EAAE;YACF,GAAG;YACH,OAAO;YACP,OAAO;YACP,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;YACrB,QAAQ,EAAE,IAAI;YACd,cAAc,EAAE,CAAC;SAClB,CAAC;QAEF,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;QAC7B,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC;QAE7B,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,EAAE;YACzB,IAAI,CAAC,QAAQ,GAAG,IAAI,IAAI,CAAC,CAAC;YAC1B,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QAC3B,CAAC,CAAC,CAAC;QAEH,OAAO,EAAE,EAAE,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC;IAC9B,CAAC;IAED,KAAK,CAAC,UAAU,CAAC,EAAU,EAAE,SAAmB;QAC9C,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACpC,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,OAAO;gBACL,EAAE;gBACF,SAAS,EAAE,KAAK;gBAChB,QAAQ,EAAE,IAAI;gBACd,MAAM,EAAE,kCAAkC,EAAE,GAAG;aAChD,CAAC;QACJ,CAAC;QAED,MAAM,MAAM,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC;QACnD,IAAI,MAAM,GAAG,EAAE,CAAC;QAEhB,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YAC1C,IAAI,IAAI,CAAC,IAAI,GAAG,MAAM,EAAE,CAAC;gBACvB,MAAM,GAAG,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,GAAG,MAAM,CAAC,CAAC;gBAC7C,MAAM,EAAE,GAAG,MAAM,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;gBAC7C,MAAM,EAAE,SAAS,EAAE,GAAG,MAAM,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;gBAChE,MAAM,EAAE,CAAC,KAAK,EAAE,CAAC;gBACjB,MAAM,GAAG,GAAG,CAAC,QAAQ,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;gBACtD,IAAI,CAAC,cAAc,GAAG,MAAM,GAAG,SAAS,CAAC;YAC3C,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,MAAM,GAAG,2BAA2B,CAAC;QACvC,CAAC;QAED,MAAM,SAAS,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACxC,OAAO,EAAE,EAAE,EAAE,SAAS,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE,MAAM,EAAE,CAAC;IAC5D,CAAC;IAED;;;;;OAKG;IACH,KAAK,CAAC,SAAS,CACb,EAAU,EACV,KAAa,EACb,OAA2C,EAAE;QAE7C,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACpC,IAAI,CAAC,IAAI;YAAE,OAAO,kCAAkC,EAAE,GAAG,CAAC;QAE1D,MAAM,KAAK,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACpC,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,QAAQ,KAAK,IAAI,EAAE,CAAC;YACrC,OAAO,WAAW,EAAE,yBAAyB,IAAI,CAAC,QAAQ,GAAG,CAAC;QAChE,CAAC;QAED,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC;QAC1B,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,SAAS,IAAI,KAAK,CAAC,aAAa,EAAE,CAAC;YACrD,OAAO,WAAW,EAAE,4CAA4C,CAAC;QACnE,CAAC;QAED,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC;QACjC,MAAM,IAAI,GAAG,KAAK,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QAEzC,IAAI,CAAC;YACH,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACpB,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;oBAC1C,KAAK,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;gBAC9D,CAAC,CAAC,CAAC;YACL,CAAC;YACD,IAAI,IAAI,CAAC,GAAG;gBAAE,KAAK,CAAC,GAAG,EAAE,CAAC;QAC5B,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,2BAA2B,EAAE,KAAM,GAAa,CAAC,OAAO,EAAE,CAAC;QACpE,CAAC;QAED,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG;YACtB,CAAC,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC;gBACf,CAAC,CAAC,yCAAyC,EAAE,GAAG;gBAChD,CAAC,CAAC,0BAA0B,EAAE,GAAG;YACnC,CAAC,CAAC,iBAAiB,EAAE,GAAG,CAAC;QAC3B,OAAO,GAAG,OAAO,6BAA6B,EAAE,yBAAyB,CAAC;IAC5E,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,EAAU;QACnB,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACpC,IAAI,CAAC,IAAI;YAAE,OAAO,kCAAkC,EAAE,GAAG,CAAC;QAE1D,MAAM,KAAK,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACpC,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,QAAQ,KAAK,IAAI,EAAE,CAAC;YACrC,OAAO,WAAW,EAAE,yBAAyB,IAAI,CAAC,QAAQ,GAAG,CAAC;QAChE,CAAC;QAED,gBAAgB;QAChB,IAAI,CAAC;YACH,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;QACxD,CAAC;QAAC,MAAM,CAAC;YACP,IAAI,CAAC;gBACH,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;YACvD,CAAC;YAAC,MAAM,CAAC;gBACP,OAAO,WAAW,EAAE,iBAAiB,CAAC;YACxC,CAAC;QACH,CAAC;QAED,8BAA8B;QAC9B,MAAM,MAAM,GAAG,MAAM,IAAI,OAAO,CAAU,CAAC,OAAO,EAAE,EAAE;YACpD,MAAM,OAAO,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,IAAI,CAAC,CAAC;YACvD,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE;gBACrB,YAAY,CAAC,OAAO,CAAC,CAAC;gBACtB,OAAO,CAAC,IAAI,CAAC,CAAC;YAChB,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;QAEH,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,eAAe,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC;QACtC,CAAC;QAED,OAAO,WAAW,EAAE,UAAU,CAAC;IACjC,CAAC;IAED,IAAI;QACF,uEAAuE;QACvE,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC;QAC1C,KAAK,MAAM,CAAC,EAAE,EAAE,IAAI,CAAC,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YACxC,IAAI,IAAI,CAAC,QAAQ,KAAK,IAAI,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,IAAI,CAAC,SAAS,GAAG,MAAM,EAAE,CAAC;gBAChF,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;YAC5B,CAAC;QACH,CAAC;QACD,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC,CAAC;IAC7C,CAAC;IAED,WAAW;QACT,KAAK,MAAM,CAAC,EAAE,EAAE,IAAI,CAAC,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YACxC,IAAI,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC;gBAC1B,eAAe,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC;gBACpC,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,QAAQ,IAAI,CAAC,CAAC;gBACnC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;YAC3B,CAAC;QACH,CAAC;IACH,CAAC;CACF"}
1
+ {"version":3,"file":"process-manager.js","sourceRoot":"","sources":["../../src/core/process-manager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,SAAS,EAAqB,MAAM,oBAAoB,CAAC;AACzE,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,GAAG,MAAM,kBAAkB,CAAC;AACnC,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,MAAM,MAAM,aAAa,CAAC;AACjC,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAyB1C,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,UAAU,EAAE,IAAI,CAAC,CAAC;AASzD,SAAS,eAAe,CAAC,GAAW,EAAE,MAAyB,EAAE;IAC/D,IAAI,CAAC,GAAG,CAAC,QAAQ,IAAI,OAAO,CAAC,QAAQ,CAAC,KAAK,OAAO,EAAE,CAAC;QACnD,CAAC,GAAG,CAAC,SAAS,IAAI,SAAS,CAAC,CAAC,UAAU,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE;YAC1E,KAAK,EAAE,QAAQ;SAChB,CAAC,CAAC;QACH,OAAO;IACT,CAAC;IACD,CAAC,GAAG,CAAC,eAAe,IAAI,eAAe,CAAC,CAAC,GAAG,CAAC,CAAC;AAChD,CAAC;AAED,MAAM,OAAO,cAAc;IAII;IAHrB,SAAS,GAAG,IAAI,GAAG,EAA6B,CAAC;IACjD,QAAQ,GAAG,IAAI,GAAG,EAAwB,CAAC;IAEnD,YAA6B,MAAyB,EAAE;QAA3B,QAAG,GAAH,GAAG,CAAwB;IAAG,CAAC;IAE5D,KAAK,CAAC,KAAK,CAAC,OAAe,EAAE,GAAW;QACtC,MAAM,GAAG,CAAC,KAAK,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAE7C,MAAM,EAAE,GAAG,MAAM,CAAC,UAAU,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QAC3C,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,EAAE,MAAM,CAAC,CAAC;QAC/C,MAAM,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;QAErC,uEAAuE;QACvE,0EAA0E;QAC1E,MAAM,KAAK,GAAG,YAAY,CAAC,OAAO,CAAC,CAAC;QACpC,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE;YAC1C,GAAG;YACH,QAAQ,EAAE,IAAI;YACd,qEAAqE;YACrE,4EAA4E;YAC5E,KAAK,EAAE,CAAC,MAAM,EAAE,EAAE,EAAE,EAAE,CAAC;YACvB,GAAG,EAAE,cAAc,EAAE;SACtB,CAAC,CAAC;QAEH,EAAE,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;QAEjB,oEAAoE;QACpE,0DAA0D;QAC1D,KAAK,CAAC,KAAK,EAAE,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;QAEnC,MAAM,GAAG,GAAG,KAAK,CAAC,GAAI,CAAC;QACvB,KAAK,CAAC,KAAK,EAAE,CAAC;QAEd,MAAM,IAAI,GAAsB;YAC9B,EAAE;YACF,GAAG;YACH,OAAO;YACP,OAAO;YACP,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;YACrB,QAAQ,EAAE,IAAI;YACd,cAAc,EAAE,CAAC;SAClB,CAAC;QAEF,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;QAC7B,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC;QAE7B,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,EAAE;YACzB,IAAI,CAAC,QAAQ,GAAG,IAAI,IAAI,CAAC,CAAC;YAC1B,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QAC3B,CAAC,CAAC,CAAC;QAEH,OAAO,EAAE,EAAE,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC;IAC9B,CAAC;IAED,KAAK,CAAC,UAAU,CAAC,EAAU,EAAE,SAAmB;QAC9C,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACpC,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,OAAO;gBACL,EAAE;gBACF,SAAS,EAAE,KAAK;gBAChB,QAAQ,EAAE,IAAI;gBACd,MAAM,EAAE,kCAAkC,EAAE,GAAG;aAChD,CAAC;QACJ,CAAC;QAED,MAAM,MAAM,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC;QACnD,IAAI,MAAM,GAAG,EAAE,CAAC;QAEhB,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YAC1C,IAAI,IAAI,CAAC,IAAI,GAAG,MAAM,EAAE,CAAC;gBACvB,MAAM,GAAG,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,GAAG,MAAM,CAAC,CAAC;gBAC7C,MAAM,EAAE,GAAG,MAAM,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;gBAC7C,MAAM,EAAE,SAAS,EAAE,GAAG,MAAM,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;gBAChE,MAAM,EAAE,CAAC,KAAK,EAAE,CAAC;gBACjB,MAAM,GAAG,GAAG,CAAC,QAAQ,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;gBACtD,IAAI,CAAC,cAAc,GAAG,MAAM,GAAG,SAAS,CAAC;YAC3C,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,MAAM,GAAG,2BAA2B,CAAC;QACvC,CAAC;QAED,MAAM,SAAS,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACxC,OAAO,EAAE,EAAE,EAAE,SAAS,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE,MAAM,EAAE,CAAC;IAC5D,CAAC;IAED;;;;;OAKG;IACH,KAAK,CAAC,SAAS,CACb,EAAU,EACV,KAAa,EACb,OAA2C,EAAE;QAE7C,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACpC,IAAI,CAAC,IAAI;YAAE,OAAO,kCAAkC,EAAE,GAAG,CAAC;QAE1D,MAAM,KAAK,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACpC,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,QAAQ,KAAK,IAAI,EAAE,CAAC;YACrC,OAAO,WAAW,EAAE,yBAAyB,IAAI,CAAC,QAAQ,GAAG,CAAC;QAChE,CAAC;QAED,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC;QAC1B,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,SAAS,IAAI,KAAK,CAAC,aAAa,EAAE,CAAC;YACrD,OAAO,WAAW,EAAE,4CAA4C,CAAC;QACnE,CAAC;QAED,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC;QACjC,MAAM,IAAI,GAAG,KAAK,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QAEzC,IAAI,CAAC;YACH,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACpB,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;oBAC1C,KAAK,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;gBAC9D,CAAC,CAAC,CAAC;YACL,CAAC;YACD,IAAI,IAAI,CAAC,GAAG;gBAAE,KAAK,CAAC,GAAG,EAAE,CAAC;QAC5B,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,2BAA2B,EAAE,KAAM,GAAa,CAAC,OAAO,EAAE,CAAC;QACpE,CAAC;QAED,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG;YACtB,CAAC,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC;gBACf,CAAC,CAAC,yCAAyC,EAAE,GAAG;gBAChD,CAAC,CAAC,0BAA0B,EAAE,GAAG;YACnC,CAAC,CAAC,iBAAiB,EAAE,GAAG,CAAC;QAC3B,OAAO,GAAG,OAAO,6BAA6B,EAAE,yBAAyB,CAAC;IAC5E,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,EAAU;QACnB,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACpC,IAAI,CAAC,IAAI;YAAE,OAAO,kCAAkC,EAAE,GAAG,CAAC;QAE1D,MAAM,KAAK,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACpC,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,QAAQ,KAAK,IAAI,EAAE,CAAC;YACrC,OAAO,WAAW,EAAE,yBAAyB,IAAI,CAAC,QAAQ,GAAG,CAAC;QAChE,CAAC;QAED,gBAAgB;QAChB,IAAI,CAAC;YACH,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;QACxD,CAAC;QAAC,MAAM,CAAC;YACP,IAAI,CAAC;gBACH,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;YACvD,CAAC;YAAC,MAAM,CAAC;gBACP,OAAO,WAAW,EAAE,iBAAiB,CAAC;YACxC,CAAC;QACH,CAAC;QAED,8BAA8B;QAC9B,MAAM,MAAM,GAAG,MAAM,IAAI,OAAO,CAAU,CAAC,OAAO,EAAE,EAAE;YACpD,MAAM,OAAO,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,IAAI,CAAC,CAAC;YACvD,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE;gBACrB,YAAY,CAAC,OAAO,CAAC,CAAC;gBACtB,OAAO,CAAC,IAAI,CAAC,CAAC;YAChB,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;QAEH,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,eAAe,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC;QACtC,CAAC;QAED,OAAO,WAAW,EAAE,UAAU,CAAC;IACjC,CAAC;IAED,IAAI;QACF,uEAAuE;QACvE,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC;QAC1C,KAAK,MAAM,CAAC,EAAE,EAAE,IAAI,CAAC,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YACxC,IAAI,IAAI,CAAC,QAAQ,KAAK,IAAI,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,IAAI,CAAC,SAAS,GAAG,MAAM,EAAE,CAAC;gBAChF,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;YAC5B,CAAC;QACH,CAAC;QACD,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC,CAAC;IAC7C,CAAC;IAED,WAAW;QACT,KAAK,MAAM,CAAC,EAAE,EAAE,IAAI,CAAC,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YACxC,IAAI,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC;gBAC1B,eAAe,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC;gBACpC,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,QAAQ,IAAI,CAAC,CAAC;gBACnC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;YAC3B,CAAC;QACH,CAAC;IACH,CAAC;CACF"}
@@ -0,0 +1,41 @@
1
+ export type ProjectSource = "ezcoder" | "claude-code" | "codex";
2
+ export interface DiscoveredProject {
3
+ name: string;
4
+ path: string;
5
+ lastActiveMs: number;
6
+ lastActiveDisplay: string;
7
+ /** Sorted, deduped list of stores this project showed up in. */
8
+ sources: ProjectSource[];
9
+ }
10
+ /**
11
+ * Scan ezcoder + Claude Code + Codex session stores and return one row per
12
+ * project, sorted most-recent first. Duplicates (same cwd) are collapsed; the
13
+ * `sources` field lists every store the project appeared in so the picker can
14
+ * show a combined badge.
15
+ */
16
+ export declare function discoverProjects(): Promise<DiscoveredProject[]>;
17
+ export interface RecentSession {
18
+ /** Session id. */
19
+ id: string;
20
+ /** Absolute path to the session .jsonl (passed back to reopen it). */
21
+ path: string;
22
+ /** First user message, trimmed to a short preview (may be empty). */
23
+ preview: string;
24
+ /** Relative "3h ago" string from last activity. */
25
+ lastActiveDisplay: string;
26
+ messageCount: number;
27
+ }
28
+ /**
29
+ * List the most recent ezcoder sessions for a project cwd, newest first, each
30
+ * with a short preview built from its first user message. Used by the new-window
31
+ * project picker to offer "resume a session" alongside "new session".
32
+ *
33
+ * Fast path: instead of fully reading every session file in the project (what
34
+ * SessionManager.list does to count messages), sort files by mtime and read
35
+ * only the newest `limit`. Each chosen file is parsed in ONE pass for its
36
+ * header id, message count, last activity, and first user preview. For projects
37
+ * with many/large sessions this is the difference between scanning everything
38
+ * and scanning ~5 files.
39
+ */
40
+ export declare function listRecentSessions(cwd: string, limit?: number): Promise<RecentSession[]>;
41
+ //# sourceMappingURL=project-discovery.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"project-discovery.d.ts","sourceRoot":"","sources":["../../src/core/project-discovery.ts"],"names":[],"mappings":"AAOA,MAAM,MAAM,aAAa,GAAG,SAAS,GAAG,aAAa,GAAG,OAAO,CAAC;AAEhE,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,MAAM,CAAC;IACrB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,gEAAgE;IAChE,OAAO,EAAE,aAAa,EAAE,CAAC;CAC1B;AAED;;;;;GAKG;AACH,wBAAsB,gBAAgB,IAAI,OAAO,CAAC,iBAAiB,EAAE,CAAC,CA6BrE;AAsSD,MAAM,WAAW,aAAa;IAC5B,kBAAkB;IAClB,EAAE,EAAE,MAAM,CAAC;IACX,sEAAsE;IACtE,IAAI,EAAE,MAAM,CAAC;IACb,qEAAqE;IACrE,OAAO,EAAE,MAAM,CAAC;IAChB,mDAAmD;IACnD,iBAAiB,EAAE,MAAM,CAAC;IAC1B,YAAY,EAAE,MAAM,CAAC;CACtB;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,kBAAkB,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,SAAI,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC,CAczF"}