codeam-cli 2.61.80 → 2.61.82

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 (3) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dist/index.js +841 -330
  3. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -89,6 +89,165 @@ var require_src = __commonJS({
89
89
  }
90
90
  });
91
91
 
92
+ // src/integrations/convex-admin-mcp.ts
93
+ var convex_admin_mcp_exports = {};
94
+ __export(convex_admin_mcp_exports, {
95
+ callConvexTool: () => callConvexTool,
96
+ deploymentNameFromKey: () => deploymentNameFromKey,
97
+ runConvexAdminMcp: () => runConvexAdminMcp
98
+ });
99
+ function deploymentNameFromKey(key) {
100
+ const prefix = key.split("|")[0];
101
+ const segs = prefix.split(":");
102
+ if ((segs[0] === "dev" || segs[0] === "prod" || segs[0] === "preview") && segs[1]) {
103
+ return segs[1];
104
+ }
105
+ return null;
106
+ }
107
+ async function adminQuery(baseUrl, key, api, body, fetchImpl = fetch) {
108
+ const res = await fetchImpl(`${baseUrl}/api/${api}`, {
109
+ method: "POST",
110
+ headers: { Authorization: `Convex ${key}`, "Content-Type": "application/json" },
111
+ body: JSON.stringify(body)
112
+ });
113
+ const text = await res.text();
114
+ const ok = res.ok && !/"status"\s*:\s*"error"/.test(text);
115
+ return { ok, text };
116
+ }
117
+ async function callConvexTool(baseUrl, key, tool, args2, fetchImpl = fetch) {
118
+ switch (tool) {
119
+ case "tables":
120
+ return adminQuery(baseUrl, key, "query", {
121
+ path: "_system/frontend/getTableMapping",
122
+ args: {},
123
+ format: "json"
124
+ }, fetchImpl);
125
+ case "schema":
126
+ return adminQuery(baseUrl, key, "query", {
127
+ path: "_system/frontend/getSchemas",
128
+ args: {},
129
+ format: "json"
130
+ }, fetchImpl);
131
+ case "data":
132
+ return adminQuery(baseUrl, key, "query", {
133
+ path: "_system/cli/queryTable",
134
+ args: { tableName: String(args2.table ?? ""), order: "desc", limit: Number(args2.limit ?? 50) },
135
+ format: "json"
136
+ }, fetchImpl);
137
+ case "run_query":
138
+ return adminQuery(baseUrl, key, "query", {
139
+ path: String(args2.functionPath ?? ""),
140
+ args: args2.args ?? {},
141
+ format: "json"
142
+ }, fetchImpl);
143
+ case "run_mutation":
144
+ return adminQuery(baseUrl, key, "mutation", {
145
+ path: String(args2.functionPath ?? ""),
146
+ args: args2.args ?? {},
147
+ format: "json"
148
+ }, fetchImpl);
149
+ default:
150
+ return { ok: false, text: `Unknown tool: ${tool}` };
151
+ }
152
+ }
153
+ async function runConvexAdminMcp(client3, id) {
154
+ const token = await client3.getToken(id);
155
+ const key = token.accessToken;
156
+ const name = deploymentNameFromKey(key);
157
+ if (!name) {
158
+ process.stderr.write(
159
+ `[codeam mcp-run convex] could not derive a deployment from the deploy key (expected a dev/prod deploy key like dev:name|\u2026 \u2014 got prefix "${key.split(":")[0]}"). Generate a deploy key at Convex Dashboard \u2192 Project Settings \u2192 Deploy Keys.
160
+ `
161
+ );
162
+ process.exit(1);
163
+ }
164
+ const baseUrl = `https://${name}.convex.cloud`;
165
+ const { Server } = await import("@modelcontextprotocol/sdk/server/index.js");
166
+ const { StdioServerTransport } = await import("@modelcontextprotocol/sdk/server/stdio.js");
167
+ const { ListToolsRequestSchema, CallToolRequestSchema } = await import("@modelcontextprotocol/sdk/types.js");
168
+ const server = new Server(
169
+ { name: "convex", version: "1.0.0" },
170
+ { capabilities: { tools: {} } }
171
+ );
172
+ server.setRequestHandler(ListToolsRequestSchema, async () => ({ tools: TOOLS }));
173
+ server.setRequestHandler(CallToolRequestSchema, async (req) => {
174
+ const tool = req.params.name;
175
+ const args2 = req.params.arguments ?? {};
176
+ try {
177
+ const { ok, text } = await callConvexTool(baseUrl, key, tool, args2);
178
+ return { content: [{ type: "text", text }], isError: !ok };
179
+ } catch (err) {
180
+ return {
181
+ content: [
182
+ {
183
+ type: "text",
184
+ text: `Convex admin API request failed: ${err instanceof Error ? err.message : String(err)}`
185
+ }
186
+ ],
187
+ isError: true
188
+ };
189
+ }
190
+ });
191
+ await server.connect(new StdioServerTransport());
192
+ }
193
+ var TOOLS;
194
+ var init_convex_admin_mcp = __esm({
195
+ "src/integrations/convex-admin-mcp.ts"() {
196
+ "use strict";
197
+ TOOLS = [
198
+ {
199
+ name: "tables",
200
+ description: "List the tables in the connected Convex deployment (name + id). Start here to discover the schema.",
201
+ inputSchema: { type: "object", properties: {}, additionalProperties: false }
202
+ },
203
+ {
204
+ name: "schema",
205
+ description: "Get the deployed schema (table definitions + validators) of the Convex deployment.",
206
+ inputSchema: { type: "object", properties: {}, additionalProperties: false }
207
+ },
208
+ {
209
+ name: "data",
210
+ description: "Read documents from a table (most-recent first). Provide the table name.",
211
+ inputSchema: {
212
+ type: "object",
213
+ properties: {
214
+ table: { type: "string", description: "The table name (from `tables`)." },
215
+ limit: { type: "number", description: "Max documents to return (default 50)." }
216
+ },
217
+ required: ["table"],
218
+ additionalProperties: false
219
+ }
220
+ },
221
+ {
222
+ name: "run_query",
223
+ description: 'Run a read-only Convex query function by its path (e.g. "messages:list") with JSON args.',
224
+ inputSchema: {
225
+ type: "object",
226
+ properties: {
227
+ functionPath: { type: "string", description: 'Function path, e.g. "messages:list".' },
228
+ args: { type: "object", description: "Arguments object for the function (default {})." }
229
+ },
230
+ required: ["functionPath"],
231
+ additionalProperties: false
232
+ }
233
+ },
234
+ {
235
+ name: "run_mutation",
236
+ description: "Run a Convex mutation function by its path with JSON args (writes data).",
237
+ inputSchema: {
238
+ type: "object",
239
+ properties: {
240
+ functionPath: { type: "string" },
241
+ args: { type: "object" }
242
+ },
243
+ required: ["functionPath"],
244
+ additionalProperties: false
245
+ }
246
+ }
247
+ ];
248
+ }
249
+ });
250
+
92
251
  // src/integrations/http-relay.ts
93
252
  var http_relay_exports = {};
94
253
  __export(http_relay_exports, {
@@ -1521,15 +1680,19 @@ var INTEGRATION_REGISTRY = {
1521
1680
  name: "Convex",
1522
1681
  icon: "convex",
1523
1682
  category: "database",
1524
- // LIVE — api_key rail (the user pastes a Convex DEPLOY KEY).
1525
- // ⚠️ Convex's OAuth application token was tried first and DOES NOT WORK with
1526
- // the MCP: it's a narrow Management-API credential — verified live it fails
1527
- // `convex mcp start` as BOTH CONVEX_DEPLOY_KEY and CONVEX_OVERRIDE_ACCESS_TOKEN,
1528
- // and can't even enumerate the team's deployments ("requires a Personal
1529
- // Access Token"). The Convex MCP's DOCUMENTED headless credential is a
1530
- // DEPLOY KEY (CONVEX_DEPLOY_KEY=dev:…|… / prod:… / project:…), so the user
1531
- // pastes one (Convex Dashboard Project Settings Deploy Keys), exactly
1532
- // like Azure DevOps / Datadog / Trello. No OAuth app, no GSM secret.
1683
+ // LIVE — api_key rail (the user pastes a Convex DEPLOY KEY) + a BUILT-IN MCP.
1684
+ // ⚠️ Convex's OWN `convex mcp start` server CANNOT work headlessly: it
1685
+ // categorically requires an INTERACTIVE `npx convex dev`/`login`
1686
+ // personal-access-token and REJECTS every headless credential OAuth token,
1687
+ // dev/prod deploy key, self-hosted admin key, with every flag
1688
+ // (--deployment/--prod/--project-dir) all return "Not Authorized: Run
1689
+ // `npx convex dev` to login" (verified LIVE, exhaustively, 2026-08-03; it
1690
+ // also HANGS on the failed auth = the mareado/no-Stop wedge). BUT the
1691
+ // deployment's own HTTP admin API accepts the deploy key directly
1692
+ // (`Authorization: Convex <deployKey>` → 200; verified). So we serve Convex's
1693
+ // tools ourselves via a BUILT-IN MCP (delivery.builtin) against that admin
1694
+ // API — see apps/cli/src/integrations/convex-admin-mcp.ts. The user still
1695
+ // pastes a deploy key (Dashboard → Project Settings → Deploy Keys).
1533
1696
  enabled: true,
1534
1697
  auth: {
1535
1698
  kind: "api_key",
@@ -1545,15 +1708,14 @@ var INTEGRATION_REGISTRY = {
1545
1708
  },
1546
1709
  delivery: {
1547
1710
  mcp: {
1548
- // Convex's OFFICIAL MCP server ships inside the `convex` npm package
1549
- // (`convex mcp start`). The pasted deploy key is fed via CONVEX_DEPLOY_KEY
1550
- // (env only, never argv)its documented non-interactive credential.
1551
- // Version PINNED; bump only after re-verifying headless.
1552
- command: "npx",
1553
- args: ["-y", "convex@1.42.3", "mcp", "start"],
1554
- envMapping: {
1555
- CONVEX_DEPLOY_KEY: "accessToken"
1556
- }
1711
+ // BUILT-IN MCP: the CLI serves Convex's tools itself against the
1712
+ // deployment admin REST API with the brokered deploy key (Convex's own
1713
+ // `convex mcp start` rejects all headless creds see the note above).
1714
+ // No spawned child, no npx. command/args/envMapping are empty.
1715
+ builtin: "convex-admin",
1716
+ command: "",
1717
+ args: [],
1718
+ envMapping: {}
1557
1719
  }
1558
1720
  }
1559
1721
  },
@@ -2462,11 +2624,11 @@ function quiet(fn) {
2462
2624
  log.debug(TAG, "ignored sync error", err);
2463
2625
  }
2464
2626
  }
2465
- function rmIfExistsQuiet(path82) {
2627
+ function rmIfExistsQuiet(path84) {
2466
2628
  try {
2467
- fs2.rmSync(path82, { force: true });
2629
+ fs2.rmSync(path84, { force: true });
2468
2630
  } catch (err) {
2469
- log.debug(TAG, `rmIfExists failed for ${path82}`, err);
2631
+ log.debug(TAG, `rmIfExists failed for ${path84}`, err);
2470
2632
  }
2471
2633
  }
2472
2634
  function killQuiet(target, signal = "SIGTERM") {
@@ -2612,9 +2774,9 @@ var _default = makeConfig();
2612
2774
  var { getConfig, ensurePluginId, addSession, removeSession, setActiveSession, getActiveSession, getActiveSessionForAgent, setDisable1mContext, clearAll, saveCliConfig, loadCliConfig } = _default;
2613
2775
 
2614
2776
  // src/commands/pair-auto.ts
2615
- var fs59 = __toESM(require("fs"));
2777
+ var fs61 = __toESM(require("fs"));
2616
2778
  var os49 = __toESM(require("os"));
2617
- var path63 = __toESM(require("path"));
2779
+ var path65 = __toESM(require("path"));
2618
2780
  var import_crypto4 = require("crypto");
2619
2781
 
2620
2782
  // src/services/telemetry.service.ts
@@ -2650,8 +2812,8 @@ function createGetModuleFromFilename(basePath = process.argv[1] ? (0, import_pat
2650
2812
  return decodedFile;
2651
2813
  };
2652
2814
  }
2653
- function normalizeWindowsPath(path82) {
2654
- return path82.replace(/^[A-Z]:/, "").replace(/\\/g, "/");
2815
+ function normalizeWindowsPath(path84) {
2816
+ return path84.replace(/^[A-Z]:/, "").replace(/\\/g, "/");
2655
2817
  }
2656
2818
 
2657
2819
  // ../../node_modules/@posthog/core/dist/featureFlagUtils.mjs
@@ -5131,9 +5293,9 @@ async function addSourceContext(frames) {
5131
5293
  LRU_FILE_CONTENTS_CACHE.reduce();
5132
5294
  return frames;
5133
5295
  }
5134
- function getContextLinesFromFile(path82, ranges, output) {
5296
+ function getContextLinesFromFile(path84, ranges, output) {
5135
5297
  return new Promise((resolve9) => {
5136
- const stream = (0, import_node_fs.createReadStream)(path82);
5298
+ const stream = (0, import_node_fs.createReadStream)(path84);
5137
5299
  const lineReaded = (0, import_node_readline.createInterface)({
5138
5300
  input: stream
5139
5301
  });
@@ -5148,7 +5310,7 @@ function getContextLinesFromFile(path82, ranges, output) {
5148
5310
  let rangeStart = range[0];
5149
5311
  let rangeEnd = range[1];
5150
5312
  function onStreamError() {
5151
- LRU_FILE_CONTENTS_FS_READ_FAILED.set(path82, 1);
5313
+ LRU_FILE_CONTENTS_FS_READ_FAILED.set(path84, 1);
5152
5314
  lineReaded.close();
5153
5315
  lineReaded.removeAllListeners();
5154
5316
  destroyStreamAndResolve();
@@ -5209,8 +5371,8 @@ function clearLineContext(frame) {
5209
5371
  delete frame.context_line;
5210
5372
  delete frame.post_context;
5211
5373
  }
5212
- function shouldSkipContextLinesForFile(path82) {
5213
- return path82.startsWith("node:") || path82.endsWith(".min.js") || path82.endsWith(".min.cjs") || path82.endsWith(".min.mjs") || path82.startsWith("data:");
5374
+ function shouldSkipContextLinesForFile(path84) {
5375
+ return path84.startsWith("node:") || path84.endsWith(".min.js") || path84.endsWith(".min.cjs") || path84.endsWith(".min.mjs") || path84.startsWith("data:");
5214
5376
  }
5215
5377
  function shouldSkipContextLinesForFrame(frame) {
5216
5378
  if (void 0 !== frame.lineno && frame.lineno > MAX_CONTEXTLINES_LINENO) return true;
@@ -7364,7 +7526,7 @@ function readAnonId() {
7364
7526
  }
7365
7527
  function superProperties() {
7366
7528
  return {
7367
- cliVersion: true ? "2.61.80" : "0.0.0-dev",
7529
+ cliVersion: true ? "2.61.82" : "0.0.0-dev",
7368
7530
  nodeVersion: process.version,
7369
7531
  platform: process.platform,
7370
7532
  arch: process.arch,
@@ -7545,7 +7707,7 @@ var os4 = __toESM(require("os"));
7545
7707
  // package.json
7546
7708
  var package_default = {
7547
7709
  name: "codeam-cli",
7548
- version: "2.61.80",
7710
+ version: "2.61.82",
7549
7711
  description: "Workflow-continuity bridge for AI coding agents. Wrap Claude Code or Codex in a PTY and supervise, approve, and redirect the session from any device \u2014 async. The terminal companion for CodeAgent Mobile.",
7550
7712
  type: "commonjs",
7551
7713
  main: "dist/index.js",
@@ -7828,6 +7990,50 @@ async function postPreviewEvent(input) {
7828
7990
  };
7829
7991
  }
7830
7992
  }
7993
+ async function pushProjectEnv(input) {
7994
+ try {
7995
+ await _transport.postJsonAuthed(
7996
+ `${API_BASE}/api/project-env/push`,
7997
+ {
7998
+ sessionId: input.sessionId,
7999
+ pluginId: input.pluginId,
8000
+ projectKey: input.projectKey,
8001
+ projectLabel: input.projectLabel,
8002
+ content: input.content,
8003
+ keyCount: input.keyCount
8004
+ },
8005
+ input.pluginAuthToken
8006
+ );
8007
+ return { ok: true };
8008
+ } catch (err) {
8009
+ const e = err;
8010
+ return {
8011
+ ok: false,
8012
+ status: typeof e.statusCode === "number" ? e.statusCode : 0,
8013
+ message: e.message || "unknown"
8014
+ };
8015
+ }
8016
+ }
8017
+ async function pullProjectEnv(input) {
8018
+ try {
8019
+ const res = await _transport.postJsonAuthed(
8020
+ `${API_BASE}/api/project-env/pull`,
8021
+ {
8022
+ sessionId: input.sessionId,
8023
+ pluginId: input.pluginId,
8024
+ projectKey: input.projectKey
8025
+ },
8026
+ input.pluginAuthToken
8027
+ );
8028
+ if (res && res.exists === true && typeof res.content === "string") {
8029
+ const keyCount = typeof res.keyCount === "number" ? res.keyCount : 0;
8030
+ return { content: res.content, keyCount };
8031
+ }
8032
+ return null;
8033
+ } catch {
8034
+ return null;
8035
+ }
8036
+ }
7831
8037
  async function postBatonEvent(input) {
7832
8038
  try {
7833
8039
  await _transport.postJsonAuthed(
@@ -8777,7 +8983,7 @@ var CommandRelayService = class _CommandRelayService {
8777
8983
  // fresh + clear the "CLI update available" banner after a self-update
8778
8984
  // (a codespace that reinstalls @latest reconnects via heartbeat, not
8779
8985
  // pair/reconnect). Older backends ignore the extra field.
8780
- ..."2.61.80" ? { ideVersion: "2.61.80" } : {}
8986
+ ..."2.61.82" ? { ideVersion: "2.61.82" } : {}
8781
8987
  }).then(() => log.trace("relay", `heartbeat ok online=${online}`)).catch((err) => log.trace("relay", `heartbeat failed online=${online}`, err));
8782
8988
  }
8783
8989
  /**
@@ -10151,9 +10357,9 @@ function closeAllTerminals() {
10151
10357
  }
10152
10358
 
10153
10359
  // src/commands/start/handlers.ts
10154
- var fs58 = __toESM(require("fs"));
10360
+ var fs60 = __toESM(require("fs"));
10155
10361
  var os48 = __toESM(require("os"));
10156
- var path62 = __toESM(require("path"));
10362
+ var path64 = __toESM(require("path"));
10157
10363
  var import_crypto3 = require("crypto");
10158
10364
  var import_child_process24 = require("child_process");
10159
10365
 
@@ -15386,8 +15592,8 @@ function pickLine(obj) {
15386
15592
  function toHunk(raw, groupSeverity) {
15387
15593
  if (!raw || typeof raw !== "object") return null;
15388
15594
  const o = raw;
15389
- const path82 = asString(pick(o, ["file_path", "filePath", "file", "path", "filename", "fileName"])) ?? asString(pick(o, ["location"])?.path);
15390
- if (!path82) return null;
15595
+ const path84 = asString(pick(o, ["file_path", "filePath", "file", "path", "filename", "fileName"])) ?? asString(pick(o, ["location"])?.path);
15596
+ if (!path84) return null;
15391
15597
  const message = asString(
15392
15598
  pick(o, [
15393
15599
  "comment",
@@ -15404,7 +15610,7 @@ function toHunk(raw, groupSeverity) {
15404
15610
  const severity = normSeverity(pick(o, ["severity", "level", "priority", "impact"])) ?? normSeverity(groupSeverity);
15405
15611
  const locObj = pick(o, ["location"]) ?? o;
15406
15612
  return {
15407
- path: path82.trim(),
15613
+ path: path84.trim(),
15408
15614
  line: pickLine(o) ?? pickLine(locObj),
15409
15615
  severity,
15410
15616
  message: (title && message ? `${title}: ${message}` : title || message).trim() || "(no message)"
@@ -15487,10 +15693,10 @@ function parsePlain(stdout) {
15487
15693
  for (const line of stdout.split(/\r?\n/)) {
15488
15694
  const m = line.match(HUNK_LINE_RE);
15489
15695
  if (!m) continue;
15490
- const [, path82, lineNo, sevToken, message] = m;
15491
- if (!path82 || !lineNo || !message) continue;
15696
+ const [, path84, lineNo, sevToken, message] = m;
15697
+ if (!path84 || !lineNo || !message) continue;
15492
15698
  hunks.push({
15493
- path: path82.trim(),
15699
+ path: path84.trim(),
15494
15700
  line: Number(lineNo),
15495
15701
  severity: sevToken ? SEVERITY_MAP[sevToken.toLowerCase()] : void 0,
15496
15702
  message: message.trim().replace(/^[*-]\s+/, "")
@@ -19891,7 +20097,7 @@ async function autoUpgradeBeforeCriticalCommand() {
19891
20097
  if (process.env.NODE_ENV === "test") return;
19892
20098
  if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
19893
20099
  if (process.env.CI) return;
19894
- const current = true ? "2.61.80" : null;
20100
+ const current = true ? "2.61.82" : null;
19895
20101
  if (!current) return;
19896
20102
  const cache = readCache();
19897
20103
  const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
@@ -19908,7 +20114,7 @@ function checkForUpdates() {
19908
20114
  if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
19909
20115
  if (process.env.CI) return;
19910
20116
  if (!process.stdout.isTTY) return;
19911
- const current = true ? "2.61.80" : null;
20117
+ const current = true ? "2.61.82" : null;
19912
20118
  if (!current) return;
19913
20119
  const cache = readCache();
19914
20120
  const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
@@ -19928,7 +20134,7 @@ var SELF_UPDATE_INTERVAL_MS = 60 * 60 * 1e3;
19928
20134
  var SELF_UPDATE_VIEW_TIMEOUT_MS = 3e4;
19929
20135
  var SELF_UPDATE_INSTALL_TIMEOUT_MS = 18e4;
19930
20136
  function currentCliVersion() {
19931
- return true ? "2.61.80" : null;
20137
+ return true ? "2.61.82" : null;
19932
20138
  }
19933
20139
  function runCmd(cmd, args2, timeoutMs) {
19934
20140
  return new Promise((resolve9) => {
@@ -21588,9 +21794,213 @@ function reclaimOwnOrphanPort(port) {
21588
21794
  return true;
21589
21795
  }
21590
21796
 
21797
+ // src/services/preview/host-allow.ts
21798
+ var import_fs = require("fs");
21799
+ var path50 = __toESM(require("path"));
21800
+ var NEXT_ALLOWED_ORIGINS = [
21801
+ "*.trycloudflare.com",
21802
+ "*.preview.codeagent-mobile.com",
21803
+ "*.codeagent-mobile.com"
21804
+ ];
21805
+ var VITE_ALLOWED_HOSTS = [
21806
+ ".trycloudflare.com",
21807
+ ".preview.codeagent-mobile.com",
21808
+ ".codeagent-mobile.com"
21809
+ ];
21810
+ var CONFIG_BASENAMES = {
21811
+ next: "next.config",
21812
+ vite: "vite.config"
21813
+ };
21814
+ var CONFIG_EXTS = [".ts", ".mjs", ".js", ".cjs", ".mts"];
21815
+ var MARKER_DIR = ".codeam";
21816
+ var MARKER_FILE = "preview-host-allow.json";
21817
+ var ORIG_INFIX = ".codeam-orig";
21818
+ function markerPath(cwd) {
21819
+ return path50.join(cwd, MARKER_DIR, MARKER_FILE);
21820
+ }
21821
+ async function fileExists(p2) {
21822
+ try {
21823
+ await import_fs.promises.access(p2);
21824
+ return true;
21825
+ } catch {
21826
+ return false;
21827
+ }
21828
+ }
21829
+ async function findConfigFile(cwd, framework) {
21830
+ const base = CONFIG_BASENAMES[framework];
21831
+ for (const ext of CONFIG_EXTS) {
21832
+ if (await fileExists(path50.join(cwd, `${base}${ext}`))) return `${base}${ext}`;
21833
+ }
21834
+ return null;
21835
+ }
21836
+ async function dependsOn(cwd, pkgName) {
21837
+ try {
21838
+ const raw = await import_fs.promises.readFile(path50.join(cwd, "package.json"), "utf8");
21839
+ const pkg = JSON.parse(raw);
21840
+ return !!(pkg.dependencies?.[pkgName] ?? pkg.devDependencies?.[pkgName]);
21841
+ } catch {
21842
+ return false;
21843
+ }
21844
+ }
21845
+ async function isEsmConfig(cwd, configFile) {
21846
+ const ext = path50.extname(configFile);
21847
+ if (ext === ".mjs" || ext === ".mts" || ext === ".ts") return true;
21848
+ if (ext === ".cjs") return false;
21849
+ try {
21850
+ const raw = await import_fs.promises.readFile(path50.join(cwd, "package.json"), "utf8");
21851
+ return JSON.parse(raw).type === "module";
21852
+ } catch {
21853
+ return false;
21854
+ }
21855
+ }
21856
+ function nextShim(origBasename, esm) {
21857
+ const list = JSON.stringify(NEXT_ALLOWED_ORIGINS);
21858
+ const merge = `
21859
+ function __codeamWithAllow(cfg) {
21860
+ var c = cfg && typeof cfg === 'object' ? Object.assign({}, cfg) : {};
21861
+ var existing = Array.isArray(c.allowedDevOrigins) ? c.allowedDevOrigins : [];
21862
+ c.allowedDevOrigins = Array.from(new Set(existing.concat(${list})));
21863
+ return c;
21864
+ }
21865
+ function __codeamMerge(base) {
21866
+ if (typeof base === 'function') {
21867
+ return function () {
21868
+ var r = base.apply(null, arguments);
21869
+ return r && typeof r.then === 'function' ? r.then(__codeamWithAllow) : __codeamWithAllow(r);
21870
+ };
21871
+ }
21872
+ return base && typeof base.then === 'function' ? base.then(__codeamWithAllow) : __codeamWithAllow(base);
21873
+ }`;
21874
+ if (origBasename) {
21875
+ return esm ? `// codeam preview host-allow shim \u2014 auto-generated, restored on preview stop.
21876
+ import __codeamUser from './${origBasename}';
21877
+ ${merge}
21878
+ export default __codeamMerge(__codeamUser);
21879
+ ` : `// codeam preview host-allow shim \u2014 auto-generated, restored on preview stop.
21880
+ var __codeamUser = require('./${origBasename}');
21881
+ ${merge}
21882
+ module.exports = __codeamMerge(__codeamUser && __codeamUser.default ? __codeamUser.default : __codeamUser);
21883
+ `;
21884
+ }
21885
+ return esm ? `// codeam preview host-allow shim \u2014 auto-generated, removed on preview stop.
21886
+ export default { allowedDevOrigins: ${list} };
21887
+ ` : `// codeam preview host-allow shim \u2014 auto-generated, removed on preview stop.
21888
+ module.exports = { allowedDevOrigins: ${list} };
21889
+ `;
21890
+ }
21891
+ function viteShim(origBasename, esm) {
21892
+ const list = JSON.stringify(VITE_ALLOWED_HOSTS);
21893
+ const merge = `
21894
+ function __codeamWithAllow(cfg) {
21895
+ var c = cfg && typeof cfg === 'object' ? Object.assign({}, cfg) : {};
21896
+ var server = Object.assign({}, c.server || {});
21897
+ if (server.allowedHosts === true) { c.server = server; return c; }
21898
+ var existing = Array.isArray(server.allowedHosts) ? server.allowedHosts : [];
21899
+ server.allowedHosts = Array.from(new Set(existing.concat(${list})));
21900
+ c.server = server;
21901
+ return c;
21902
+ }
21903
+ function __codeamMerge(base) {
21904
+ if (typeof base === 'function') {
21905
+ return function () {
21906
+ var r = base.apply(null, arguments);
21907
+ return r && typeof r.then === 'function' ? r.then(__codeamWithAllow) : __codeamWithAllow(r);
21908
+ };
21909
+ }
21910
+ return base && typeof base.then === 'function' ? base.then(__codeamWithAllow) : __codeamWithAllow(base);
21911
+ }`;
21912
+ if (origBasename) {
21913
+ return esm ? `// codeam preview host-allow shim \u2014 auto-generated, restored on preview stop.
21914
+ import __codeamUser from './${origBasename}';
21915
+ ${merge}
21916
+ export default __codeamMerge(__codeamUser);
21917
+ ` : `// codeam preview host-allow shim \u2014 auto-generated, restored on preview stop.
21918
+ var __codeamUser = require('./${origBasename}');
21919
+ ${merge}
21920
+ module.exports = __codeamMerge(__codeamUser && __codeamUser.default ? __codeamUser.default : __codeamUser);
21921
+ `;
21922
+ }
21923
+ return esm ? `// codeam preview host-allow shim \u2014 auto-generated, removed on preview stop.
21924
+ export default { server: { allowedHosts: ${list} } };
21925
+ ` : `// codeam preview host-allow shim \u2014 auto-generated, removed on preview stop.
21926
+ module.exports = { server: { allowedHosts: ${list} } };
21927
+ `;
21928
+ }
21929
+ function shimFor(framework, origBasename, esm) {
21930
+ return framework === "next" ? nextShim(origBasename, esm) : viteShim(origBasename, esm);
21931
+ }
21932
+ async function writeMarker(cwd, marker) {
21933
+ await import_fs.promises.mkdir(path50.join(cwd, MARKER_DIR), { recursive: true });
21934
+ await import_fs.promises.writeFile(markerPath(cwd), JSON.stringify(marker, null, 2), "utf8");
21935
+ }
21936
+ async function readMarker(cwd) {
21937
+ try {
21938
+ const parsed = JSON.parse(await import_fs.promises.readFile(markerPath(cwd), "utf8"));
21939
+ return parsed && parsed.configFile ? parsed : null;
21940
+ } catch {
21941
+ return null;
21942
+ }
21943
+ }
21944
+ async function restorePreviewHostAllow(cwd) {
21945
+ const marker = await readMarker(cwd);
21946
+ if (!marker) return;
21947
+ try {
21948
+ const configAbs = path50.join(cwd, marker.configFile);
21949
+ if (marker.backupFile) {
21950
+ const backupAbs = path50.join(cwd, marker.backupFile);
21951
+ if (await fileExists(backupAbs)) {
21952
+ await import_fs.promises.rm(configAbs, { force: true });
21953
+ await import_fs.promises.rename(backupAbs, configAbs);
21954
+ }
21955
+ } else {
21956
+ await import_fs.promises.rm(configAbs, { force: true });
21957
+ }
21958
+ } catch (err) {
21959
+ log.warn("preview", `host-allow restore failed: ${err instanceof Error ? err.message : err}`);
21960
+ } finally {
21961
+ await import_fs.promises.rm(markerPath(cwd), { force: true }).catch(() => void 0);
21962
+ }
21963
+ }
21964
+ async function applyPreviewHostAllow(cwd) {
21965
+ try {
21966
+ await restorePreviewHostAllow(cwd);
21967
+ let framework = null;
21968
+ let existing = null;
21969
+ for (const f of ["next", "vite"]) {
21970
+ const cfg = await findConfigFile(cwd, f);
21971
+ if (cfg) {
21972
+ framework = f;
21973
+ existing = cfg;
21974
+ break;
21975
+ }
21976
+ }
21977
+ if (!framework) {
21978
+ if (await dependsOn(cwd, "next")) framework = "next";
21979
+ else if (await dependsOn(cwd, "vite")) framework = "vite";
21980
+ }
21981
+ if (!framework) return;
21982
+ if (existing) {
21983
+ const ext = path50.extname(existing);
21984
+ const origBasename = `${CONFIG_BASENAMES[framework]}${ORIG_INFIX}${ext}`;
21985
+ const esm = await isEsmConfig(cwd, existing);
21986
+ await import_fs.promises.rename(path50.join(cwd, existing), path50.join(cwd, origBasename));
21987
+ await import_fs.promises.writeFile(path50.join(cwd, existing), shimFor(framework, origBasename, esm), "utf8");
21988
+ await writeMarker(cwd, { framework, configFile: existing, backupFile: origBasename });
21989
+ log.info("preview", `host-allow: wrapped ${existing} (${framework}) for tunnel access`);
21990
+ } else {
21991
+ const configFile = `${CONFIG_BASENAMES[framework]}.mjs`;
21992
+ await import_fs.promises.writeFile(path50.join(cwd, configFile), shimFor(framework, null, true), "utf8");
21993
+ await writeMarker(cwd, { framework, configFile, backupFile: null });
21994
+ log.info("preview", `host-allow: created ${configFile} (${framework}) for tunnel access`);
21995
+ }
21996
+ } catch (err) {
21997
+ log.warn("preview", `host-allow apply skipped: ${err instanceof Error ? err.message : err}`);
21998
+ }
21999
+ }
22000
+
21591
22001
  // src/services/preview/cloudflared.ts
21592
22002
  var import_child_process15 = require("child_process");
21593
- var import_fs = require("fs");
22003
+ var import_fs2 = require("fs");
21594
22004
  var import_promises = __toESM(require("fs/promises"));
21595
22005
  var import_os9 = __toESM(require("os"));
21596
22006
  var import_path4 = __toESM(require("path"));
@@ -21631,7 +22041,7 @@ async function downloadCloudflared(target) {
21631
22041
  const tmp = `${target}.download.tgz`;
21632
22042
  await (0, import_promises2.pipeline)(
21633
22043
  response.body,
21634
- (0, import_fs.createWriteStream)(tmp)
22044
+ (0, import_fs2.createWriteStream)(tmp)
21635
22045
  );
21636
22046
  try {
21637
22047
  await extractTgz(tmp, import_path4.default.dirname(target));
@@ -21648,7 +22058,7 @@ async function downloadCloudflared(target) {
21648
22058
  }
21649
22059
  await (0, import_promises2.pipeline)(
21650
22060
  response.body,
21651
- (0, import_fs.createWriteStream)(target, { mode: 493 })
22061
+ (0, import_fs2.createWriteStream)(target, { mode: 493 })
21652
22062
  );
21653
22063
  }
21654
22064
  async function isExecutableBinary(p2) {
@@ -21909,7 +22319,7 @@ async function waitForPortListening(port, opts) {
21909
22319
  }
21910
22320
 
21911
22321
  // src/services/preview/provision-deps.ts
21912
- var import_fs2 = require("fs");
22322
+ var import_fs3 = require("fs");
21913
22323
  var import_path6 = __toESM(require("path"));
21914
22324
 
21915
22325
  // src/services/preview/run-setup.ts
@@ -22057,7 +22467,7 @@ function pickMigrationScript(scripts) {
22057
22467
  }
22058
22468
  async function exists(p2) {
22059
22469
  try {
22060
- await import_fs2.promises.access(p2);
22470
+ await import_fs3.promises.access(p2);
22061
22471
  return true;
22062
22472
  } catch {
22063
22473
  return false;
@@ -22074,20 +22484,20 @@ async function ensureEnvFile(cwd, generated) {
22074
22484
  }
22075
22485
  const sample = await firstExisting(cwd, ENV_SAMPLES);
22076
22486
  if (sample) {
22077
- const body = await import_fs2.promises.readFile(import_path6.default.join(cwd, sample), "utf8");
22078
- await import_fs2.promises.writeFile(import_path6.default.join(cwd, ".env"), body);
22487
+ const body = await import_fs3.promises.readFile(import_path6.default.join(cwd, sample), "utf8");
22488
+ await import_fs3.promises.writeFile(import_path6.default.join(cwd, ".env"), body);
22079
22489
  log.info("provision", `wrote .env from ${sample}`);
22080
22490
  return;
22081
22491
  }
22082
22492
  if (generated.length > 0) {
22083
22493
  const body = "# Generated by codeam \u2014 points at the auto-provisioned local services.\n" + generated.flatMap((s) => s.envLines).join("\n") + "\n";
22084
- await import_fs2.promises.writeFile(import_path6.default.join(cwd, ".env"), body);
22494
+ await import_fs3.promises.writeFile(import_path6.default.join(cwd, ".env"), body);
22085
22495
  log.info("provision", `generated .env for ${generated.map((s) => s.name).join("+")}`);
22086
22496
  }
22087
22497
  }
22088
22498
  async function readPackageJson(cwd) {
22089
22499
  try {
22090
- return JSON.parse(await import_fs2.promises.readFile(import_path6.default.join(cwd, "package.json"), "utf8"));
22500
+ return JSON.parse(await import_fs3.promises.readFile(import_path6.default.join(cwd, "package.json"), "utf8"));
22091
22501
  } catch {
22092
22502
  return null;
22093
22503
  }
@@ -22128,9 +22538,9 @@ async function provisionProjectDependencies(cwd) {
22128
22538
  generated = detectServicesFromDeps(pkg);
22129
22539
  if (generated.length > 0) {
22130
22540
  const dir = import_path6.default.join(cwd, ".codeam", "provision");
22131
- await import_fs2.promises.mkdir(dir, { recursive: true });
22541
+ await import_fs3.promises.mkdir(dir, { recursive: true });
22132
22542
  const file = import_path6.default.join(dir, "compose.generated.yaml");
22133
- await import_fs2.promises.writeFile(file, renderComposeYaml(generated));
22543
+ await import_fs3.promises.writeFile(file, renderComposeYaml(generated));
22134
22544
  log.info(
22135
22545
  "provision",
22136
22546
  `no compose in repo \u2014 generated ${generated.map((s) => s.name).join("+")}`
@@ -22151,12 +22561,12 @@ async function provisionProjectDependencies(cwd) {
22151
22561
  }
22152
22562
 
22153
22563
  // src/services/preview/setup-deps.ts
22154
- var import_fs3 = __toESM(require("fs"));
22564
+ var import_fs4 = __toESM(require("fs"));
22155
22565
  var import_path7 = __toESM(require("path"));
22156
22566
  function detectMissingNodeDeps(cwd) {
22157
- if (!import_fs3.default.existsSync(import_path7.default.join(cwd, "package.json"))) return null;
22158
- if (import_fs3.default.existsSync(import_path7.default.join(cwd, "node_modules"))) return null;
22159
- if (import_fs3.default.existsSync(import_path7.default.join(cwd, "yarn.lock"))) {
22567
+ if (!import_fs4.default.existsSync(import_path7.default.join(cwd, "package.json"))) return null;
22568
+ if (import_fs4.default.existsSync(import_path7.default.join(cwd, "node_modules"))) return null;
22569
+ if (import_fs4.default.existsSync(import_path7.default.join(cwd, "yarn.lock"))) {
22160
22570
  return { cmd: "yarn", args: ["install"] };
22161
22571
  }
22162
22572
  return { cmd: "npm", args: ["install", "--legacy-peer-deps"] };
@@ -22248,6 +22658,7 @@ async function killPreview(sessionId) {
22248
22658
  if (preview.tunnel) killProcessTree(preview.tunnel, "SIGKILL");
22249
22659
  }, 250);
22250
22660
  sigkillTimer.unref?.();
22661
+ await restorePreviewHostAllow(preview.cwd);
22251
22662
  activePreviews.delete(sessionId);
22252
22663
  }
22253
22664
  async function killAllPreviews() {
@@ -22259,10 +22670,153 @@ function activePreviewSessionIds() {
22259
22670
  }
22260
22671
 
22261
22672
  // src/services/preview/start-orchestrator.ts
22262
- var import_child_process18 = require("child_process");
22263
- var fs51 = __toESM(require("fs"));
22264
- var path54 = __toESM(require("path"));
22673
+ var import_child_process19 = require("child_process");
22674
+ var fs54 = __toESM(require("fs"));
22675
+ var path57 = __toESM(require("path"));
22265
22676
  var import_which2 = __toESM(require("which"));
22677
+
22678
+ // src/services/project-env/index.ts
22679
+ var import_fs5 = require("fs");
22680
+ var path56 = __toESM(require("path"));
22681
+
22682
+ // src/beads/project-key.ts
22683
+ var import_child_process18 = require("child_process");
22684
+ var crypto2 = __toESM(require("crypto"));
22685
+ var fs52 = __toESM(require("fs"));
22686
+ var path55 = __toESM(require("path"));
22687
+ function normalizeOrigin(raw) {
22688
+ const trimmed = raw.trim();
22689
+ if (!trimmed) return null;
22690
+ let host2;
22691
+ let pathPart;
22692
+ const scpLike = /^[^/@]+@([^:]+):(.+)$/.exec(trimmed);
22693
+ if (scpLike && !trimmed.includes("://")) {
22694
+ host2 = scpLike[1];
22695
+ pathPart = scpLike[2];
22696
+ } else {
22697
+ let url2;
22698
+ try {
22699
+ url2 = new URL(trimmed);
22700
+ } catch {
22701
+ return null;
22702
+ }
22703
+ host2 = url2.hostname;
22704
+ pathPart = url2.pathname;
22705
+ }
22706
+ host2 = host2.toLowerCase();
22707
+ pathPart = pathPart.replace(/^\/+/, "").replace(/\.git$/i, "").replace(/\/+$/, "");
22708
+ if (!host2 || !pathPart) return null;
22709
+ return `${host2}/${pathPart}`;
22710
+ }
22711
+ function findRepoRoot(cwd) {
22712
+ let dir = path55.resolve(cwd);
22713
+ const seen = /* @__PURE__ */ new Set();
22714
+ for (let i = 0; i < 256; i++) {
22715
+ if (seen.has(dir)) return null;
22716
+ seen.add(dir);
22717
+ try {
22718
+ const stat3 = fs52.statSync(path55.join(dir, ".git"), { throwIfNoEntry: false });
22719
+ if (stat3 && (stat3.isDirectory() || stat3.isFile())) return dir;
22720
+ } catch {
22721
+ }
22722
+ const parent = path55.dirname(dir);
22723
+ if (parent === dir) return null;
22724
+ dir = parent;
22725
+ }
22726
+ return null;
22727
+ }
22728
+ var _execSeam2 = {
22729
+ exec: (file, args2, opts) => {
22730
+ const out2 = (0, import_child_process18.execFileSync)(file, args2, opts);
22731
+ return typeof out2 === "string" ? out2 : out2.toString("utf8");
22732
+ },
22733
+ realpath: (p2) => fs52.realpathSync(p2)
22734
+ };
22735
+ function readOrigin(cwd) {
22736
+ try {
22737
+ const raw = _execSeam2.exec("git", ["remote", "get-url", "origin"], {
22738
+ cwd,
22739
+ timeout: 1e3,
22740
+ stdio: ["ignore", "pipe", "ignore"],
22741
+ encoding: "utf8"
22742
+ });
22743
+ return raw.trim() || null;
22744
+ } catch {
22745
+ return null;
22746
+ }
22747
+ }
22748
+ function deriveProjectIdentity(cwd = process.cwd()) {
22749
+ const repoRoot = findRepoRoot(cwd) ?? cwd;
22750
+ const origin = readOrigin(repoRoot);
22751
+ const normalized = origin ? normalizeOrigin(origin) : null;
22752
+ if (normalized) {
22753
+ const label = normalized.split("/").pop() || normalized;
22754
+ return { projectKey: normalized, projectLabel: label };
22755
+ }
22756
+ let real = repoRoot;
22757
+ try {
22758
+ real = _execSeam2.realpath(repoRoot);
22759
+ } catch {
22760
+ }
22761
+ const hash = crypto2.createHash("sha256").update(real).digest("hex");
22762
+ return { projectKey: `path:${hash}`, projectLabel: path55.basename(real) || "project" };
22763
+ }
22764
+
22765
+ // src/services/project-env/index.ts
22766
+ async function readIfExists(p2) {
22767
+ try {
22768
+ return await import_fs5.promises.readFile(p2, "utf8");
22769
+ } catch {
22770
+ return null;
22771
+ }
22772
+ }
22773
+ async function syncProjectEnvUp(cwd, ctx) {
22774
+ if (!ctx.pluginAuthToken) return;
22775
+ const content = await readIfExists(path56.join(cwd, ".env"));
22776
+ if (content == null) return;
22777
+ try {
22778
+ const { projectKey, projectLabel } = deriveProjectIdentity(cwd);
22779
+ const keyCount = parseDotenv(content).length;
22780
+ const res = await pushProjectEnv({
22781
+ sessionId: ctx.sessionId,
22782
+ pluginId: ctx.pluginId,
22783
+ pluginAuthToken: ctx.pluginAuthToken,
22784
+ projectKey,
22785
+ projectLabel,
22786
+ content,
22787
+ keyCount
22788
+ });
22789
+ if (res.ok) log.info("project-env", `pushed .env (${keyCount} vars) for ${projectLabel}`);
22790
+ else log.debug("project-env", `push .env failed (${res.status}) \u2014 non-fatal`);
22791
+ } catch (err) {
22792
+ log.debug("project-env", `push .env skipped: ${err instanceof Error ? err.message : err}`);
22793
+ }
22794
+ }
22795
+ async function restoreProjectEnvIfMissing(cwd, ctx) {
22796
+ if (!ctx.pluginAuthToken) return false;
22797
+ const envPath = path56.join(cwd, ".env");
22798
+ if (await readIfExists(envPath) != null) return false;
22799
+ try {
22800
+ const { projectKey, projectLabel } = deriveProjectIdentity(cwd);
22801
+ const stored = await pullProjectEnv({
22802
+ sessionId: ctx.sessionId,
22803
+ pluginId: ctx.pluginId,
22804
+ pluginAuthToken: ctx.pluginAuthToken,
22805
+ projectKey
22806
+ });
22807
+ if (!stored) return false;
22808
+ const tmp = path56.join(cwd, ".env.codeam-restore.tmp");
22809
+ await import_fs5.promises.writeFile(tmp, stored.content, { encoding: "utf8", mode: 384 });
22810
+ await import_fs5.promises.rename(tmp, envPath);
22811
+ log.info("project-env", `restored .env (${stored.keyCount} vars) for ${projectLabel}`);
22812
+ return true;
22813
+ } catch (err) {
22814
+ log.debug("project-env", `restore .env skipped: ${err instanceof Error ? err.message : err}`);
22815
+ return false;
22816
+ }
22817
+ }
22818
+
22819
+ // src/services/preview/start-orchestrator.ts
22266
22820
  var INSTALL_TIMEOUT_MS = 5 * 6e4;
22267
22821
  var SETUP_TIMEOUT_MS = 2 * 6e4;
22268
22822
  var TUNNEL_REGISTER_DEADLINE_MS = 45e3;
@@ -22328,8 +22882,8 @@ function normalizeDetectionForSpawn(detection, cwd) {
22328
22882
  if (args2.length === 0) return detection;
22329
22883
  const binName = args2[0];
22330
22884
  if (binName.startsWith("-")) return detection;
22331
- const binPath = path54.join(cwd, "node_modules", ".bin", binName);
22332
- if (!fs51.existsSync(binPath)) return detection;
22885
+ const binPath = path57.join(cwd, "node_modules", ".bin", binName);
22886
+ if (!fs54.existsSync(binPath)) return detection;
22333
22887
  return {
22334
22888
  ...detection,
22335
22889
  command: binPath,
@@ -22375,7 +22929,8 @@ async function runPreviewStart(args2) {
22375
22929
  tunnel: tun.tunnel,
22376
22930
  url: tun.url,
22377
22931
  framework: detection.framework,
22378
- detection
22932
+ detection,
22933
+ cwd: ctx.cwd
22379
22934
  });
22380
22935
  recordPreviewPort(detection.port, dev.devServer.pid, sessionId, Date.now());
22381
22936
  log.info("preview", `ready: ${detection.framework} at ${tun.url}`);
@@ -22387,6 +22942,13 @@ async function runPreviewStart(args2) {
22387
22942
  }
22388
22943
  async function provisionDeps(ctx) {
22389
22944
  const { detection, cwd, emit: emit2, emitProgress } = ctx;
22945
+ if (ctx.projectEnvAuth?.pluginAuthToken) {
22946
+ await restoreProjectEnvIfMissing(cwd, {
22947
+ sessionId: ctx.sessionId,
22948
+ pluginId: ctx.projectEnvAuth.pluginId,
22949
+ pluginAuthToken: ctx.projectEnvAuth.pluginAuthToken
22950
+ });
22951
+ }
22390
22952
  const missingDeps = detectMissingNodeDeps(cwd);
22391
22953
  let preflightRan = false;
22392
22954
  if (missingDeps) {
@@ -22534,9 +23096,10 @@ async function startDevServer(ctx) {
22534
23096
  return null;
22535
23097
  }
22536
23098
  }
23099
+ await applyPreviewHostAllow(cwd);
22537
23100
  const spawnable = normalizeDetectionForSpawn(detection, cwd);
22538
23101
  emitProgress("BOOT_SEQUENCE", `${spawnable.command} ${spawnable.args.join(" ")}`);
22539
- const devServer = (0, import_child_process18.spawn)(spawnable.command, spawnable.args, {
23102
+ const devServer = (0, import_child_process19.spawn)(spawnable.command, spawnable.args, {
22540
23103
  cwd,
22541
23104
  env: { ...process.env, ...spawnable.env ?? {} },
22542
23105
  stdio: ["ignore", "pipe", "pipe"],
@@ -22661,7 +23224,7 @@ async function establishTunnel(ctx, dev) {
22661
23224
  `cloudflared quick tunnel (retry ${attempt}/${MAX_TUNNEL_ATTEMPTS})`
22662
23225
  );
22663
23226
  }
22664
- const candidate = (0, import_child_process18.spawn)(
23227
+ const candidate = (0, import_child_process19.spawn)(
22665
23228
  bin,
22666
23229
  ["tunnel", "--url", `http://localhost:${detection.port}`],
22667
23230
  { stdio: ["ignore", "pipe", "pipe"] }
@@ -22692,10 +23255,10 @@ async function establishTunnel(ctx, dev) {
22692
23255
  }
22693
23256
 
22694
23257
  // src/beads/bd-adapter.ts
22695
- var import_child_process19 = require("child_process");
22696
- var fs52 = __toESM(require("fs"));
23258
+ var import_child_process20 = require("child_process");
23259
+ var fs55 = __toESM(require("fs"));
22697
23260
  var os42 = __toESM(require("os"));
22698
- var path55 = __toESM(require("path"));
23261
+ var path58 = __toESM(require("path"));
22699
23262
  var BD_PACKAGE = "@beads/bd";
22700
23263
  function resolveBundledBdBinary() {
22701
23264
  return _resolveSeam.resolveBundled();
@@ -22707,11 +23270,11 @@ function _defaultResolveBundled() {
22707
23270
  } catch {
22708
23271
  return null;
22709
23272
  }
22710
- const binDir = path55.join(path55.dirname(pkgJsonPath), "bin");
23273
+ const binDir = path58.join(path58.dirname(pkgJsonPath), "bin");
22711
23274
  const binaryName = process.platform === "win32" ? "bd.exe" : "bd";
22712
- const binaryPath = path55.join(binDir, binaryName);
23275
+ const binaryPath = path58.join(binDir, binaryName);
22713
23276
  try {
22714
- fs52.accessSync(binaryPath, fs52.constants.F_OK);
23277
+ fs55.accessSync(binaryPath, fs55.constants.F_OK);
22715
23278
  return binaryPath;
22716
23279
  } catch {
22717
23280
  return null;
@@ -22721,13 +23284,13 @@ function resolveBdOnPath() {
22721
23284
  return _resolveSeam.resolveOnPath();
22722
23285
  }
22723
23286
  function _defaultResolveOnPath() {
22724
- const dirs = (process.env.PATH ?? "").split(path55.delimiter).filter(Boolean);
23287
+ const dirs = (process.env.PATH ?? "").split(path58.delimiter).filter(Boolean);
22725
23288
  const candidates = process.platform === "win32" ? ["bd.exe", "bd.cmd", "bd"] : ["bd"];
22726
23289
  for (const dir of dirs) {
22727
23290
  for (const candidate of candidates) {
22728
- const full = path55.join(dir, candidate);
23291
+ const full = path58.join(dir, candidate);
22729
23292
  try {
22730
- fs52.accessSync(full, fs52.constants.F_OK);
23293
+ fs55.accessSync(full, fs55.constants.F_OK);
22731
23294
  return full;
22732
23295
  } catch {
22733
23296
  }
@@ -22746,7 +23309,7 @@ function _defaultSpawn(binaryPath, args2, opts) {
22746
23309
  return new Promise((resolve9) => {
22747
23310
  let proc;
22748
23311
  try {
22749
- proc = (0, import_child_process19.spawn)(binaryPath, args2, { cwd: opts.cwd, env: opts.env });
23312
+ proc = (0, import_child_process20.spawn)(binaryPath, args2, { cwd: opts.cwd, env: opts.env });
22750
23313
  } catch (err) {
22751
23314
  resolve9({ code: -1, stdout: "", stderr: err.message });
22752
23315
  return;
@@ -22904,12 +23467,12 @@ function coerceIssue(row, projectKey) {
22904
23467
 
22905
23468
  // src/beads/provisioner.ts
22906
23469
  var import_child_process23 = require("child_process");
22907
- var fs55 = __toESM(require("fs"));
23470
+ var fs57 = __toESM(require("fs"));
22908
23471
  var os44 = __toESM(require("os"));
22909
- var path58 = __toESM(require("path"));
23472
+ var path60 = __toESM(require("path"));
22910
23473
 
22911
23474
  // src/beads/install-bd.ts
22912
- var import_child_process20 = require("child_process");
23475
+ var import_child_process21 = require("child_process");
22913
23476
  var INSTALL_SH_URL = "https://raw.githubusercontent.com/gastownhall/beads/main/scripts/install.sh";
22914
23477
  var INSTALL_PS1_URL = "https://raw.githubusercontent.com/gastownhall/beads/main/install.ps1";
22915
23478
  function resolveInstallStrategy(platform3) {
@@ -22940,7 +23503,7 @@ function _defaultInstallSpawn(strategy) {
22940
23503
  return new Promise((resolve9) => {
22941
23504
  let proc;
22942
23505
  try {
22943
- proc = (0, import_child_process20.spawn)(strategy.command, strategy.args, { env: process.env });
23506
+ proc = (0, import_child_process21.spawn)(strategy.command, strategy.args, { env: process.env });
22944
23507
  } catch (err) {
22945
23508
  resolve9({ ok: false, code: -1, stderr: err.message });
22946
23509
  return;
@@ -22970,10 +23533,10 @@ async function installBd(platform3 = process.platform) {
22970
23533
  }
22971
23534
 
22972
23535
  // src/beads/install-dolt.ts
22973
- var import_child_process21 = require("child_process");
22974
- var fs53 = __toESM(require("fs"));
23536
+ var import_child_process22 = require("child_process");
23537
+ var fs56 = __toESM(require("fs"));
22975
23538
  var os43 = __toESM(require("os"));
22976
- var path56 = __toESM(require("path"));
23539
+ var path59 = __toESM(require("path"));
22977
23540
  var DOLT_INSTALL_SH_URL = "https://github.com/dolthub/dolt/releases/latest/download/install.sh";
22978
23541
  var DOLT_MSI_URL = "https://github.com/dolthub/dolt/releases/latest/download/dolt-windows-amd64.msi";
22979
23542
  function resolveDoltInstallStrategy(platform3) {
@@ -23069,7 +23632,7 @@ var _doltPathSeam = {
23069
23632
  },
23070
23633
  exists: (p2) => {
23071
23634
  try {
23072
- fs53.accessSync(p2, fs53.constants.F_OK);
23635
+ fs56.accessSync(p2, fs56.constants.F_OK);
23073
23636
  return true;
23074
23637
  } catch {
23075
23638
  return false;
@@ -23080,7 +23643,7 @@ function doltBinaryNames(platform3) {
23080
23643
  return platform3 === "win32" ? ["dolt.exe", "dolt.cmd", "dolt"] : ["dolt"];
23081
23644
  }
23082
23645
  function knownDoltDirs(platform3) {
23083
- const P3 = platform3 === "win32" ? path56.win32 : path56.posix;
23646
+ const P3 = platform3 === "win32" ? path59.win32 : path59.posix;
23084
23647
  const home = _doltPathSeam.homedir();
23085
23648
  if (platform3 === "win32") {
23086
23649
  return [
@@ -23096,7 +23659,7 @@ function knownDoltDirs(platform3) {
23096
23659
  ].filter(Boolean);
23097
23660
  }
23098
23661
  function ensureDoltResolvable(platform3 = process.platform) {
23099
- const P3 = platform3 === "win32" ? path56.win32 : path56.posix;
23662
+ const P3 = platform3 === "win32" ? path59.win32 : path59.posix;
23100
23663
  const delim = platform3 === "win32" ? ";" : ":";
23101
23664
  const names = doltBinaryNames(platform3);
23102
23665
  const pathDirs = _doltPathSeam.getPath().split(delim).filter(Boolean);
@@ -23132,7 +23695,7 @@ function _defaultDoltInstallSpawn(strategy) {
23132
23695
  };
23133
23696
  let proc;
23134
23697
  try {
23135
- proc = (0, import_child_process21.spawn)(strategy.command, strategy.args, {
23698
+ proc = (0, import_child_process22.spawn)(strategy.command, strategy.args, {
23136
23699
  env: process.env,
23137
23700
  stdio: ["ignore", "pipe", "pipe"]
23138
23701
  });
@@ -23229,89 +23792,6 @@ async function ensureSharedServer(adapter, options = {}) {
23229
23792
  return { up: false, started: false };
23230
23793
  }
23231
23794
 
23232
- // src/beads/project-key.ts
23233
- var import_child_process22 = require("child_process");
23234
- var crypto2 = __toESM(require("crypto"));
23235
- var fs54 = __toESM(require("fs"));
23236
- var path57 = __toESM(require("path"));
23237
- function normalizeOrigin(raw) {
23238
- const trimmed = raw.trim();
23239
- if (!trimmed) return null;
23240
- let host2;
23241
- let pathPart;
23242
- const scpLike = /^[^/@]+@([^:]+):(.+)$/.exec(trimmed);
23243
- if (scpLike && !trimmed.includes("://")) {
23244
- host2 = scpLike[1];
23245
- pathPart = scpLike[2];
23246
- } else {
23247
- let url2;
23248
- try {
23249
- url2 = new URL(trimmed);
23250
- } catch {
23251
- return null;
23252
- }
23253
- host2 = url2.hostname;
23254
- pathPart = url2.pathname;
23255
- }
23256
- host2 = host2.toLowerCase();
23257
- pathPart = pathPart.replace(/^\/+/, "").replace(/\.git$/i, "").replace(/\/+$/, "");
23258
- if (!host2 || !pathPart) return null;
23259
- return `${host2}/${pathPart}`;
23260
- }
23261
- function findRepoRoot(cwd) {
23262
- let dir = path57.resolve(cwd);
23263
- const seen = /* @__PURE__ */ new Set();
23264
- for (let i = 0; i < 256; i++) {
23265
- if (seen.has(dir)) return null;
23266
- seen.add(dir);
23267
- try {
23268
- const stat3 = fs54.statSync(path57.join(dir, ".git"), { throwIfNoEntry: false });
23269
- if (stat3 && (stat3.isDirectory() || stat3.isFile())) return dir;
23270
- } catch {
23271
- }
23272
- const parent = path57.dirname(dir);
23273
- if (parent === dir) return null;
23274
- dir = parent;
23275
- }
23276
- return null;
23277
- }
23278
- var _execSeam2 = {
23279
- exec: (file, args2, opts) => {
23280
- const out2 = (0, import_child_process22.execFileSync)(file, args2, opts);
23281
- return typeof out2 === "string" ? out2 : out2.toString("utf8");
23282
- },
23283
- realpath: (p2) => fs54.realpathSync(p2)
23284
- };
23285
- function readOrigin(cwd) {
23286
- try {
23287
- const raw = _execSeam2.exec("git", ["remote", "get-url", "origin"], {
23288
- cwd,
23289
- timeout: 1e3,
23290
- stdio: ["ignore", "pipe", "ignore"],
23291
- encoding: "utf8"
23292
- });
23293
- return raw.trim() || null;
23294
- } catch {
23295
- return null;
23296
- }
23297
- }
23298
- function deriveProjectIdentity(cwd = process.cwd()) {
23299
- const repoRoot = findRepoRoot(cwd) ?? cwd;
23300
- const origin = readOrigin(repoRoot);
23301
- const normalized = origin ? normalizeOrigin(origin) : null;
23302
- if (normalized) {
23303
- const label = normalized.split("/").pop() || normalized;
23304
- return { projectKey: normalized, projectLabel: label };
23305
- }
23306
- let real = repoRoot;
23307
- try {
23308
- real = _execSeam2.realpath(repoRoot);
23309
- } catch {
23310
- }
23311
- const hash = crypto2.createHash("sha256").update(real).digest("hex");
23312
- return { projectKey: `path:${hash}`, projectLabel: path57.basename(real) || "project" };
23313
- }
23314
-
23315
23795
  // src/beads/project-prefix.ts
23316
23796
  var crypto3 = __toESM(require("crypto"));
23317
23797
  function prefixForProjectKey(projectKey) {
@@ -23359,14 +23839,14 @@ var _linkSeam = {
23359
23839
  homedir: () => os44.homedir(),
23360
23840
  isWritableDir: (dir) => {
23361
23841
  try {
23362
- fs55.accessSync(dir, fs55.constants.W_OK);
23842
+ fs57.accessSync(dir, fs57.constants.W_OK);
23363
23843
  return true;
23364
23844
  } catch {
23365
23845
  return false;
23366
23846
  }
23367
23847
  },
23368
23848
  ensureDir: (dir) => {
23369
- fs55.mkdirSync(dir, { recursive: true });
23849
+ fs57.mkdirSync(dir, { recursive: true });
23370
23850
  },
23371
23851
  /**
23372
23852
  * A directory to symlink `bd` into so the AGENT's shell + Claude Code's
@@ -23387,9 +23867,9 @@ var _linkSeam = {
23387
23867
  * which `linkBdOntoPath` creates if missing.
23388
23868
  */
23389
23869
  cliBinDir: () => {
23390
- const pathDirs = (process.env.PATH ?? "").split(path58.delimiter).filter(Boolean);
23870
+ const pathDirs = (process.env.PATH ?? "").split(path60.delimiter).filter(Boolean);
23391
23871
  const home = _linkSeam.homedir();
23392
- const localBin = home ? path58.join(home, ".local", "bin") : null;
23872
+ const localBin = home ? path60.join(home, ".local", "bin") : null;
23393
23873
  if (localBin) {
23394
23874
  try {
23395
23875
  _linkSeam.ensureDir(localBin);
@@ -23399,16 +23879,16 @@ var _linkSeam = {
23399
23879
  const candidates = [];
23400
23880
  if (localBin) candidates.push(localBin);
23401
23881
  try {
23402
- candidates.push(path58.dirname(process.execPath));
23882
+ candidates.push(path60.dirname(process.execPath));
23403
23883
  } catch {
23404
23884
  }
23405
23885
  candidates.push("/usr/local/bin");
23406
23886
  const entry = process.argv[1];
23407
23887
  if (entry) {
23408
23888
  try {
23409
- candidates.push(path58.dirname(fs55.realpathSync(entry)));
23889
+ candidates.push(path60.dirname(fs57.realpathSync(entry)));
23410
23890
  } catch {
23411
- candidates.push(path58.dirname(entry));
23891
+ candidates.push(path60.dirname(entry));
23412
23892
  }
23413
23893
  }
23414
23894
  const onPathWritable = candidates.find(
@@ -23420,20 +23900,20 @@ var _linkSeam = {
23420
23900
  /** Current symlink target at `linkPath`, or null when absent / not a link. */
23421
23901
  readlink: (linkPath) => {
23422
23902
  try {
23423
- return fs55.readlinkSync(linkPath);
23903
+ return fs57.readlinkSync(linkPath);
23424
23904
  } catch {
23425
23905
  return null;
23426
23906
  }
23427
23907
  },
23428
- unlink: (linkPath) => fs55.unlinkSync(linkPath),
23429
- symlink: (target, linkPath) => fs55.symlinkSync(target, linkPath)
23908
+ unlink: (linkPath) => fs57.unlinkSync(linkPath),
23909
+ symlink: (target, linkPath) => fs57.symlinkSync(target, linkPath)
23430
23910
  };
23431
23911
  function linkBdOntoPath(binaryPath) {
23432
23912
  if (_linkSeam.platform() === "win32") return;
23433
23913
  const binDir = _linkSeam.cliBinDir();
23434
23914
  if (!binDir) return;
23435
23915
  _linkSeam.ensureDir(binDir);
23436
- const linkPath = path58.join(binDir, "bd");
23916
+ const linkPath = path60.join(binDir, "bd");
23437
23917
  if (linkPath === binaryPath) return;
23438
23918
  const current = _linkSeam.readlink(linkPath);
23439
23919
  if (current === binaryPath) return;
@@ -23628,7 +24108,7 @@ function dedupeRecipes(agents) {
23628
24108
 
23629
24109
  // src/beads/watcher.ts
23630
24110
  var crypto4 = __toESM(require("crypto"));
23631
- var path59 = __toESM(require("path"));
24111
+ var path61 = __toESM(require("path"));
23632
24112
  var API_BASE6 = resolveApiBaseUrl();
23633
24113
  var DEBOUNCE_MS2 = 400;
23634
24114
  var ZERO_SUMMARY = {
@@ -23652,7 +24132,7 @@ var BeadsWatcher = class {
23652
24132
  constructor(opts) {
23653
24133
  this.opts = opts;
23654
24134
  this.bd = opts.adapter ?? new BdAdapter({ cwd: opts.cwd, beadsDir: opts.beadsDir });
23655
- this.feedPath = opts.feedPath ?? path59.join(opts.cwd ?? process.cwd(), ".beads", "last-touched");
24135
+ this.feedPath = opts.feedPath ?? path61.join(opts.cwd ?? process.cwd(), ".beads", "last-touched");
23656
24136
  this.apiBase = opts.apiBaseUrl ?? API_BASE6;
23657
24137
  }
23658
24138
  opts;
@@ -24151,8 +24631,8 @@ function cleanupAttachmentTempFiles() {
24151
24631
  function saveFilesTemp(files) {
24152
24632
  return files.filter(({ base64 }) => base64 && base64.length > 0).map(({ filename, base64 }) => {
24153
24633
  const safeName = filename.replace(/[^a-zA-Z0-9._-]/g, "_").slice(0, 80);
24154
- const tmpPath = path62.join(os48.tmpdir(), `codeam-${(0, import_crypto3.randomUUID)()}-${safeName}`);
24155
- fs58.writeFileSync(tmpPath, Buffer.from(base64, "base64"));
24634
+ const tmpPath = path64.join(os48.tmpdir(), `codeam-${(0, import_crypto3.randomUUID)()}-${safeName}`);
24635
+ fs60.writeFileSync(tmpPath, Buffer.from(base64, "base64"));
24156
24636
  pendingAttachmentFiles.add(tmpPath);
24157
24637
  return tmpPath;
24158
24638
  });
@@ -24364,9 +24844,10 @@ var listFiles = async (ctx, cmd, parsed) => {
24364
24844
  await ctx.relay.sendResult(cmd.id, "completed", result);
24365
24845
  };
24366
24846
  var envReadH = async (ctx, cmd) => {
24367
- const envPath = path62.join(process.cwd(), ".env");
24847
+ const envPath = path64.join(process.cwd(), ".env");
24848
+ await restoreProjectEnvIfMissing(process.cwd(), ctx);
24368
24849
  try {
24369
- const raw = await fs58.promises.readFile(envPath, "utf8");
24850
+ const raw = await fs60.promises.readFile(envPath, "utf8");
24370
24851
  await ctx.relay.sendResult(cmd.id, "completed", {
24371
24852
  exists: true,
24372
24853
  vars: parseDotenv(raw)
@@ -24397,14 +24878,15 @@ var envWriteH = async (ctx, cmd, parsed) => {
24397
24878
  }
24398
24879
  seen.add(v.key);
24399
24880
  }
24400
- const envPath = path62.join(process.cwd(), ".env");
24401
- const tmpPath = path62.join(process.cwd(), ".env.codeam.tmp");
24881
+ const envPath = path64.join(process.cwd(), ".env");
24882
+ const tmpPath = path64.join(process.cwd(), ".env.codeam.tmp");
24402
24883
  try {
24403
- await fs58.promises.writeFile(tmpPath, serializeDotenv(vars), "utf8");
24404
- await fs58.promises.rename(tmpPath, envPath);
24884
+ await fs60.promises.writeFile(tmpPath, serializeDotenv(vars), "utf8");
24885
+ await fs60.promises.rename(tmpPath, envPath);
24405
24886
  await ctx.relay.sendResult(cmd.id, "completed", { ok: true, count: vars.length });
24887
+ void syncProjectEnvUp(process.cwd(), ctx);
24406
24888
  } catch (err) {
24407
- await fs58.promises.rm(tmpPath, { force: true }).catch(() => void 0);
24889
+ await fs60.promises.rm(tmpPath, { force: true }).catch(() => void 0);
24408
24890
  await ctx.relay.sendResult(cmd.id, "failed", { error: err.message });
24409
24891
  }
24410
24892
  };
@@ -24453,7 +24935,7 @@ var headroomConfigureH = async (ctx, cmd, parsed) => {
24453
24935
  let configuredAgent = rawAgentId;
24454
24936
  if (!configuredAgent) {
24455
24937
  try {
24456
- const raw = JSON.parse(fs58.readFileSync(headroomConfigPath(), "utf8"));
24938
+ const raw = JSON.parse(fs60.readFileSync(headroomConfigPath(), "utf8"));
24457
24939
  configuredAgent = raw.agent ?? "";
24458
24940
  } catch {
24459
24941
  }
@@ -24487,7 +24969,7 @@ var headroomConfigureH = async (ctx, cmd, parsed) => {
24487
24969
  persist: persistHeadroomConfig,
24488
24970
  readEnabled: () => {
24489
24971
  try {
24490
- const raw = JSON.parse(fs58.readFileSync(headroomConfigPath(), "utf8"));
24972
+ const raw = JSON.parse(fs60.readFileSync(headroomConfigPath(), "utf8"));
24491
24973
  return raw.enabled === true;
24492
24974
  } catch {
24493
24975
  return false;
@@ -24791,7 +25273,7 @@ var headroomBudgetH = async (ctx, cmd) => {
24791
25273
  }
24792
25274
  let headroomActive = false;
24793
25275
  try {
24794
- const raw = JSON.parse(fs58.readFileSync(headroomConfigPath(), "utf8"));
25276
+ const raw = JSON.parse(fs60.readFileSync(headroomConfigPath(), "utf8"));
24795
25277
  headroomActive = raw.enabled === true;
24796
25278
  } catch {
24797
25279
  }
@@ -24801,7 +25283,7 @@ var headroomBudgetH = async (ctx, cmd) => {
24801
25283
  }
24802
25284
  let existingConfig = { enabled: true };
24803
25285
  try {
24804
- existingConfig = JSON.parse(fs58.readFileSync(headroomConfigPath(), "utf8"));
25286
+ existingConfig = JSON.parse(fs60.readFileSync(headroomConfigPath(), "utf8"));
24805
25287
  } catch {
24806
25288
  }
24807
25289
  if (payload.budgetEnabled && payload.budgetUsd != null) {
@@ -24914,9 +25396,9 @@ var CLI_UPDATE_MAX_ATTEMPTS = 3;
24914
25396
  function buildNpmInstallInvocation(opts) {
24915
25397
  const entryScript = opts?.entryScript ?? process.argv[1] ?? "";
24916
25398
  const execPath = opts?.execPath ?? process.execPath;
24917
- const exists2 = opts?.existsSync ?? fs58.existsSync;
25399
+ const exists2 = opts?.existsSync ?? fs60.existsSync;
24918
25400
  const platform3 = opts?.platform ?? process.platform;
24919
- const p2 = platform3 === "win32" ? path62.win32 : path62.posix;
25401
+ const p2 = platform3 === "win32" ? path64.win32 : path64.posix;
24920
25402
  const normalized = entryScript.split(/[\\/]/).join("/");
24921
25403
  const marker = "/lib/node_modules/codeam-cli/";
24922
25404
  const markerIdx = normalized.indexOf(marker);
@@ -24938,7 +25420,7 @@ function isPermissionError(stderr) {
24938
25420
  function resolveGlobalNodeModulesDir(opts) {
24939
25421
  const entryScript = opts?.entryScript ?? process.argv[1] ?? "";
24940
25422
  const platform3 = opts?.platform ?? process.platform;
24941
- const p2 = platform3 === "win32" ? path62.win32 : path62.posix;
25423
+ const p2 = platform3 === "win32" ? path64.win32 : path64.posix;
24942
25424
  const marker = "/lib/node_modules/codeam-cli/";
24943
25425
  const markerIdx = entryScript.split(/[\\/]/).join("/").indexOf(marker);
24944
25426
  if (markerIdx <= 0) return null;
@@ -24948,9 +25430,9 @@ function resolveGlobalNodeModulesDir(opts) {
24948
25430
  var STALE_STAGING_AGE_MS = CLI_UPDATE_INSTALL_TIMEOUT_MS;
24949
25431
  function sweepStaleCliStagingDirs(nodeModulesDir, now = Date.now(), deps) {
24950
25432
  if (!nodeModulesDir) return 0;
24951
- const readdirSync12 = deps?.readdirSync ?? fs58.readdirSync;
24952
- const statSync17 = deps?.statSync ?? fs58.statSync;
24953
- const rmSync8 = deps?.rmSync ?? fs58.rmSync;
25433
+ const readdirSync12 = deps?.readdirSync ?? fs60.readdirSync;
25434
+ const statSync17 = deps?.statSync ?? fs60.statSync;
25435
+ const rmSync8 = deps?.rmSync ?? fs60.rmSync;
24954
25436
  let removed = 0;
24955
25437
  let entries;
24956
25438
  try {
@@ -24960,7 +25442,7 @@ function sweepStaleCliStagingDirs(nodeModulesDir, now = Date.now(), deps) {
24960
25442
  }
24961
25443
  for (const name of entries) {
24962
25444
  if (!/^\.codeam-cli-/.test(name)) continue;
24963
- const full = path62.join(nodeModulesDir, name);
25445
+ const full = path64.join(nodeModulesDir, name);
24964
25446
  try {
24965
25447
  const st3 = statSync17(full);
24966
25448
  if (now - st3.mtimeMs < STALE_STAGING_AGE_MS) continue;
@@ -25449,7 +25931,12 @@ function startPreviewFromDetection(ctx, detection, pluginAuthToken) {
25449
25931
  sessionId: ctx.sessionId,
25450
25932
  detection,
25451
25933
  cwd: process.cwd(),
25452
- emit: emit2
25934
+ emit: emit2,
25935
+ // Auth for the per-repo `.env` vault restore, performed INSIDE the bring-up
25936
+ // (provisionDeps stage, after the reuse short-circuit) so a fresh session of
25937
+ // this repo picks up its saved `.env` before the dev server spawns. Optional
25938
+ // — a caller without a token just skips the restore.
25939
+ projectEnvAuth: { pluginId: ctx.pluginId, pluginAuthToken }
25453
25940
  }).catch((err) => {
25454
25941
  const message = err instanceof Error ? err.message : String(err);
25455
25942
  log.warn("preview", `start crashed before ready: ${message}`);
@@ -25822,11 +26309,11 @@ function resolveTokenValue(args2) {
25822
26309
  }
25823
26310
  const fileFlag = args2.find((a) => a.startsWith("--token-file="));
25824
26311
  if (fileFlag) {
25825
- const path82 = fileFlag.slice("--token-file=".length);
26312
+ const path84 = fileFlag.slice("--token-file=".length);
25826
26313
  try {
25827
- const content = fs59.readFileSync(path82, "utf8").trim();
25828
- if (content.length === 0) fail(`--token-file ${path82} is empty`);
25829
- rmIfExistsQuiet(path82);
26314
+ const content = fs61.readFileSync(path84, "utf8").trim();
26315
+ if (content.length === 0) fail(`--token-file ${path84} is empty`);
26316
+ rmIfExistsQuiet(path84);
25830
26317
  return content;
25831
26318
  } catch (err) {
25832
26319
  fail(`Could not read --token-file: ${err.message}`);
@@ -25916,7 +26403,7 @@ async function claim(token, pluginId, pluginSecretHash) {
25916
26403
  }
25917
26404
  }
25918
26405
  function pairAutoLockPath() {
25919
- return path63.join(os49.homedir(), ".codeam", "pair-auto.lock");
26406
+ return path65.join(os49.homedir(), ".codeam", "pair-auto.lock");
25920
26407
  }
25921
26408
  function isLivePairAuto(pid) {
25922
26409
  if (!Number.isInteger(pid) || pid <= 0 || pid === process.pid) return false;
@@ -25926,7 +26413,7 @@ function isLivePairAuto(pid) {
25926
26413
  if (e.code !== "EPERM") return false;
25927
26414
  }
25928
26415
  try {
25929
- return fs59.readFileSync(`/proc/${pid}/cmdline`, "utf8").includes("codeam");
26416
+ return fs61.readFileSync(`/proc/${pid}/cmdline`, "utf8").includes("codeam");
25930
26417
  } catch {
25931
26418
  return true;
25932
26419
  }
@@ -25936,24 +26423,24 @@ function isLiveCodeam(pid) {
25936
26423
  }
25937
26424
  function daemonLockPath(sessionId) {
25938
26425
  const safe = sessionId.replace(/[^a-zA-Z0-9_-]/g, "_");
25939
- return path63.join(os49.homedir(), ".codeam", `daemon-${safe}.lock`);
26426
+ return path65.join(os49.homedir(), ".codeam", `daemon-${safe}.lock`);
25940
26427
  }
25941
26428
  function acquireDaemonLock(sessionId) {
25942
26429
  const lockPath = daemonLockPath(sessionId);
25943
26430
  try {
25944
- fs59.mkdirSync(path63.dirname(lockPath), { recursive: true });
26431
+ fs61.mkdirSync(path65.dirname(lockPath), { recursive: true });
25945
26432
  try {
25946
- fs59.writeFileSync(lockPath, String(process.pid), { flag: "wx" });
26433
+ fs61.writeFileSync(lockPath, String(process.pid), { flag: "wx" });
25947
26434
  } catch (e) {
25948
26435
  if (e.code !== "EEXIST") throw e;
25949
- const holder = Number(fs59.readFileSync(lockPath, "utf8").trim());
26436
+ const holder = Number(fs61.readFileSync(lockPath, "utf8").trim());
25950
26437
  if (holder && holder !== process.pid && isLiveCodeam(holder)) return false;
25951
- fs59.writeFileSync(lockPath, String(process.pid));
26438
+ fs61.writeFileSync(lockPath, String(process.pid));
25952
26439
  }
25953
26440
  const release3 = () => {
25954
26441
  try {
25955
- if (fs59.existsSync(lockPath) && Number(fs59.readFileSync(lockPath, "utf8").trim()) === process.pid) {
25956
- fs59.unlinkSync(lockPath);
26442
+ if (fs61.existsSync(lockPath) && Number(fs61.readFileSync(lockPath, "utf8").trim()) === process.pid) {
26443
+ fs61.unlinkSync(lockPath);
25957
26444
  }
25958
26445
  } catch {
25959
26446
  }
@@ -25975,19 +26462,19 @@ function acquireDaemonLock(sessionId) {
25975
26462
  function acquireSingletonLock() {
25976
26463
  const lockPath = pairAutoLockPath();
25977
26464
  try {
25978
- fs59.mkdirSync(path63.dirname(lockPath), { recursive: true });
26465
+ fs61.mkdirSync(path65.dirname(lockPath), { recursive: true });
25979
26466
  try {
25980
- fs59.writeFileSync(lockPath, String(process.pid), { flag: "wx" });
26467
+ fs61.writeFileSync(lockPath, String(process.pid), { flag: "wx" });
25981
26468
  } catch (e) {
25982
26469
  if (e.code !== "EEXIST") throw e;
25983
- const holder = Number(fs59.readFileSync(lockPath, "utf8").trim());
26470
+ const holder = Number(fs61.readFileSync(lockPath, "utf8").trim());
25984
26471
  if (isLivePairAuto(holder)) return false;
25985
- fs59.writeFileSync(lockPath, String(process.pid));
26472
+ fs61.writeFileSync(lockPath, String(process.pid));
25986
26473
  }
25987
26474
  process.once("exit", () => {
25988
26475
  try {
25989
- if (fs59.existsSync(lockPath) && Number(fs59.readFileSync(lockPath, "utf8").trim()) === process.pid) {
25990
- fs59.unlinkSync(lockPath);
26476
+ if (fs61.existsSync(lockPath) && Number(fs61.readFileSync(lockPath, "utf8").trim()) === process.pid) {
26477
+ fs61.unlinkSync(lockPath);
25991
26478
  }
25992
26479
  } catch {
25993
26480
  }
@@ -26439,10 +26926,10 @@ var AgentService = class _AgentService {
26439
26926
  };
26440
26927
 
26441
26928
  // src/agents/acp/adapters.ts
26442
- var path65 = __toESM(require("path"));
26929
+ var path67 = __toESM(require("path"));
26443
26930
 
26444
26931
  // src/agents/acp/agent-binary.ts
26445
- var import_fs4 = __toESM(require("fs"));
26932
+ var import_fs6 = __toESM(require("fs"));
26446
26933
  var import_os11 = __toESM(require("os"));
26447
26934
  var import_path8 = __toESM(require("path"));
26448
26935
  var import_child_process26 = require("child_process");
@@ -26472,7 +26959,7 @@ function defaultSdkDir() {
26472
26959
  return resolveSdkDirViaRequire();
26473
26960
  }
26474
26961
  function resolveClaudeNativeBinary(deps = {}) {
26475
- const existsSync27 = deps.existsSync ?? import_fs4.default.existsSync;
26962
+ const existsSync27 = deps.existsSync ?? import_fs6.default.existsSync;
26476
26963
  const platformKey = deps.platformKey ?? currentPlatformKey();
26477
26964
  const sdkDir = deps.sdkDir !== void 0 ? deps.sdkDir : defaultSdkDir();
26478
26965
  if (!sdkDir) return null;
@@ -26530,7 +27017,7 @@ async function waitForCommandOnPath(cmd, opts = {}) {
26530
27017
  return check();
26531
27018
  }
26532
27019
  function resolveCursorAgentBinary(deps = {}) {
26533
- const existsSync27 = deps.existsSync ?? import_fs4.default.existsSync;
27020
+ const existsSync27 = deps.existsSync ?? import_fs6.default.existsSync;
26534
27021
  const platform3 = deps.platform ?? process.platform;
26535
27022
  const env = deps.env ?? process.env;
26536
27023
  if (platform3 === "win32") {
@@ -26729,13 +27216,13 @@ function resolveBin(pkgName, binName) {
26729
27216
  try {
26730
27217
  const manifestPath = require_.resolve(`${pkgName}/package.json`);
26731
27218
  const manifest = require_(`${pkgName}/package.json`);
26732
- const pkgDir = path65.dirname(manifestPath);
27219
+ const pkgDir = path67.dirname(manifestPath);
26733
27220
  const bin = manifest.bin;
26734
27221
  if (!bin) return null;
26735
- if (typeof bin === "string") return path65.resolve(pkgDir, bin);
27222
+ if (typeof bin === "string") return path67.resolve(pkgDir, bin);
26736
27223
  const target = binName ?? Object.keys(bin)[0];
26737
27224
  if (!target || !bin[target]) return null;
26738
- return path65.resolve(pkgDir, bin[target]);
27225
+ return path67.resolve(pkgDir, bin[target]);
26739
27226
  } catch {
26740
27227
  return null;
26741
27228
  }
@@ -26885,8 +27372,8 @@ async function resolveAcpAdapterWithRetry(agent, opts = {}) {
26885
27372
  var import_node_crypto11 = require("crypto");
26886
27373
 
26887
27374
  // src/services/history.service.ts
26888
- var fs61 = __toESM(require("fs"));
26889
- var path66 = __toESM(require("path"));
27375
+ var fs63 = __toESM(require("fs"));
27376
+ var path68 = __toESM(require("path"));
26890
27377
  var os51 = __toESM(require("os"));
26891
27378
  var https7 = __toESM(require("https"));
26892
27379
  var http6 = __toESM(require("http"));
@@ -26914,7 +27401,7 @@ function parseJsonl(filePath) {
26914
27401
  const messages = [];
26915
27402
  let raw;
26916
27403
  try {
26917
- raw = fs61.readFileSync(filePath, "utf8");
27404
+ raw = fs63.readFileSync(filePath, "utf8");
26918
27405
  } catch (err) {
26919
27406
  if (err.code !== "ENOENT") {
26920
27407
  log.warn("history:parseJsonl", `read failed for ${filePath}`, err);
@@ -27055,7 +27542,7 @@ var HistoryService = class _HistoryService {
27055
27542
  return this._quotaPercent === null || Date.now() - this._quotaFetchedAt > ttlMs;
27056
27543
  }
27057
27544
  get projectDir() {
27058
- return this.runtime.resolveHistoryDir(this.cwd) ?? path66.join(os51.homedir(), ".claude", "projects", encodeCwd(this.cwd));
27545
+ return this.runtime.resolveHistoryDir(this.cwd) ?? path68.join(os51.homedir(), ".claude", "projects", encodeCwd(this.cwd));
27059
27546
  }
27060
27547
  /** Set the current Claude conversation ID (extracted from /cost command or session start) */
27061
27548
  setCurrentConversationId(id) {
@@ -27067,7 +27554,7 @@ var HistoryService = class _HistoryService {
27067
27554
  /** Return the current message count in the active conversation. */
27068
27555
  getCurrentMessageCount() {
27069
27556
  if (!this.currentConversationId) return 0;
27070
- const filePath = path66.join(this.projectDir, `${this.currentConversationId}.jsonl`);
27557
+ const filePath = path68.join(this.projectDir, `${this.currentConversationId}.jsonl`);
27071
27558
  return parseJsonl(filePath).length;
27072
27559
  }
27073
27560
  /**
@@ -27078,7 +27565,7 @@ var HistoryService = class _HistoryService {
27078
27565
  const deadline = Date.now() + timeoutMs;
27079
27566
  while (Date.now() < deadline) {
27080
27567
  if (!this.currentConversationId) return null;
27081
- const filePath = path66.join(this.projectDir, `${this.currentConversationId}.jsonl`);
27568
+ const filePath = path68.join(this.projectDir, `${this.currentConversationId}.jsonl`);
27082
27569
  const messages = parseJsonl(filePath);
27083
27570
  if (messages.length > previousCount) {
27084
27571
  for (let i = messages.length - 1; i >= previousCount; i--) {
@@ -27104,16 +27591,16 @@ var HistoryService = class _HistoryService {
27104
27591
  const dir = this.projectDir;
27105
27592
  const cutoff = this.bootTimeMs - _HistoryService.BIRTHTIME_GRACE_MS;
27106
27593
  try {
27107
- const files = fs61.readdirSync(dir, { withFileTypes: true }).filter((e) => e.isFile() && e.name.endsWith(".jsonl")).map((e) => {
27594
+ const files = fs63.readdirSync(dir, { withFileTypes: true }).filter((e) => e.isFile() && e.name.endsWith(".jsonl")).map((e) => {
27108
27595
  try {
27109
- const stat3 = fs61.statSync(path66.join(dir, e.name));
27596
+ const stat3 = fs63.statSync(path68.join(dir, e.name));
27110
27597
  return { name: e.name, mtime: stat3.mtimeMs, birthtime: stat3.birthtimeMs };
27111
27598
  } catch {
27112
27599
  return { name: e.name, mtime: 0, birthtime: 0 };
27113
27600
  }
27114
27601
  }).filter((f) => f.birthtime >= cutoff).sort((a, b) => b.mtime - a.mtime);
27115
27602
  if (files.length > 0) {
27116
- this.currentConversationId = path66.basename(files[0].name, ".jsonl");
27603
+ this.currentConversationId = path68.basename(files[0].name, ".jsonl");
27117
27604
  }
27118
27605
  } catch {
27119
27606
  }
@@ -27147,13 +27634,13 @@ var HistoryService = class _HistoryService {
27147
27634
  const cutoff = this.bootTimeMs - _HistoryService.BIRTHTIME_GRACE_MS;
27148
27635
  let entries;
27149
27636
  try {
27150
- entries = fs61.readdirSync(dir, { withFileTypes: true });
27637
+ entries = fs63.readdirSync(dir, { withFileTypes: true });
27151
27638
  } catch {
27152
27639
  return null;
27153
27640
  }
27154
27641
  const files = entries.filter((e) => e.isFile() && e.name.endsWith(".jsonl")).map((e) => {
27155
27642
  try {
27156
- const stat3 = fs61.statSync(path66.join(dir, e.name));
27643
+ const stat3 = fs63.statSync(path68.join(dir, e.name));
27157
27644
  return { name: e.name, mtime: stat3.mtimeMs, birthtime: stat3.birthtimeMs };
27158
27645
  } catch {
27159
27646
  return { name: e.name, mtime: 0, birthtime: 0 };
@@ -27162,12 +27649,12 @@ var HistoryService = class _HistoryService {
27162
27649
  if (files.length === 0) return null;
27163
27650
  const targetFile = this.currentConversationId ? `${this.currentConversationId}.jsonl` : files[0].name;
27164
27651
  if (!files.some((f) => f.name === targetFile)) return null;
27165
- return this.extractUsageFromFile(path66.join(dir, targetFile));
27652
+ return this.extractUsageFromFile(path68.join(dir, targetFile));
27166
27653
  }
27167
27654
  extractUsageFromFile(filePath) {
27168
27655
  let raw;
27169
27656
  try {
27170
- raw = fs61.readFileSync(filePath, "utf8");
27657
+ raw = fs63.readFileSync(filePath, "utf8");
27171
27658
  } catch {
27172
27659
  return null;
27173
27660
  }
@@ -27212,9 +27699,9 @@ var HistoryService = class _HistoryService {
27212
27699
  let totalCost = 0;
27213
27700
  let files;
27214
27701
  try {
27215
- files = fs61.readdirSync(projectDir).filter((f) => f.endsWith(".jsonl")).filter((f) => {
27702
+ files = fs63.readdirSync(projectDir).filter((f) => f.endsWith(".jsonl")).filter((f) => {
27216
27703
  try {
27217
- return fs61.statSync(path66.join(projectDir, f)).mtimeMs >= monthStartMs;
27704
+ return fs63.statSync(path68.join(projectDir, f)).mtimeMs >= monthStartMs;
27218
27705
  } catch {
27219
27706
  return false;
27220
27707
  }
@@ -27225,7 +27712,7 @@ var HistoryService = class _HistoryService {
27225
27712
  for (const file of files) {
27226
27713
  let raw;
27227
27714
  try {
27228
- raw = fs61.readFileSync(path66.join(projectDir, file), "utf8");
27715
+ raw = fs63.readFileSync(path68.join(projectDir, file), "utf8");
27229
27716
  } catch {
27230
27717
  continue;
27231
27718
  }
@@ -27304,7 +27791,7 @@ var HistoryService = class _HistoryService {
27304
27791
  if (this.runtime.resolveHistoryFile) {
27305
27792
  return this.runtime.resolveHistoryFile(this.cwd, sessionId);
27306
27793
  }
27307
- return path66.join(this.projectDir, `${sessionId}.jsonl`);
27794
+ return path68.join(this.projectDir, `${sessionId}.jsonl`);
27308
27795
  }
27309
27796
  /**
27310
27797
  * Parse a conversation's messages from disk, agent-aware. Claude uses the
@@ -27338,7 +27825,7 @@ var HistoryService = class _HistoryService {
27338
27825
  };
27339
27826
  });
27340
27827
  }
27341
- return parseJsonl(path66.join(this.projectDir, `${sessionId}.jsonl`));
27828
+ return parseJsonl(path68.join(this.projectDir, `${sessionId}.jsonl`));
27342
27829
  }
27343
27830
  async loadConversation(sessionId) {
27344
27831
  const messages = this.readConversation(sessionId);
@@ -27406,7 +27893,7 @@ var HistoryService = class _HistoryService {
27406
27893
  if (!filePath) return false;
27407
27894
  let mtimeMs;
27408
27895
  try {
27409
- mtimeMs = fs61.statSync(filePath).mtimeMs;
27896
+ mtimeMs = fs63.statSync(filePath).mtimeMs;
27410
27897
  } catch {
27411
27898
  return false;
27412
27899
  }
@@ -27481,10 +27968,10 @@ var HistoryService = class _HistoryService {
27481
27968
 
27482
27969
  // src/agents/acp/client.ts
27483
27970
  var import_node_child_process29 = require("child_process");
27484
- var fs62 = __toESM(require("fs/promises"));
27971
+ var fs64 = __toESM(require("fs/promises"));
27485
27972
  var fsSync = __toESM(require("fs"));
27486
27973
  var os53 = __toESM(require("os"));
27487
- var path68 = __toESM(require("path"));
27974
+ var path70 = __toESM(require("path"));
27488
27975
  var import_node_stream = require("stream");
27489
27976
 
27490
27977
  // ../../node_modules/@agentclientprotocol/sdk/dist/schema/index.js
@@ -31510,7 +31997,7 @@ function createIdleTimeout(idleMs, makeError, activeIdleMs = idleMs) {
31510
31997
  }
31511
31998
 
31512
31999
  // src/agents/acp/internal-paths.ts
31513
- var path67 = __toESM(require("path"));
32000
+ var path69 = __toESM(require("path"));
31514
32001
  var os52 = __toESM(require("os"));
31515
32002
  var INTERNAL_TOKENS = [".codeam", "house-claude"];
31516
32003
  function textReferencesInternal(text) {
@@ -31519,10 +32006,10 @@ function textReferencesInternal(text) {
31519
32006
  }
31520
32007
  function pathIsInternal(p2, homeDir2 = os52.homedir()) {
31521
32008
  if (!p2) return false;
31522
- const abs = path67.resolve(p2);
31523
- const home = path67.resolve(homeDir2);
31524
- const within = (root) => abs === root || abs.startsWith(root + path67.sep);
31525
- return within(path67.join(home, ".codeam")) || within(path67.join(home, ".beads")) || abs === path67.join(home, ".codeam-host.log") || abs.includes(`${path67.sep}house-claude${path67.sep}`) || abs.endsWith(`${path67.sep}house-claude`);
32009
+ const abs = path69.resolve(p2);
32010
+ const home = path69.resolve(homeDir2);
32011
+ const within = (root) => abs === root || abs.startsWith(root + path69.sep);
32012
+ return within(path69.join(home, ".codeam")) || within(path69.join(home, ".beads")) || abs === path69.join(home, ".codeam-host.log") || abs.includes(`${path69.sep}house-claude${path69.sep}`) || abs.endsWith(`${path69.sep}house-claude`);
31526
32013
  }
31527
32014
  function toolCallReferencesInternal(call) {
31528
32015
  if (textReferencesInternal(call.title)) return true;
@@ -32351,7 +32838,7 @@ var AcpClient = class {
32351
32838
  throw new RequestError(-32002, INTERNAL_BLOCK_REASON, { uri: params.path });
32352
32839
  }
32353
32840
  try {
32354
- const content = await fs62.readFile(params.path, "utf8");
32841
+ const content = await fs64.readFile(params.path, "utf8");
32355
32842
  return applyLineRange(content, params.line ?? null, params.limit ?? null);
32356
32843
  } catch (err) {
32357
32844
  const code = err.code;
@@ -32374,7 +32861,7 @@ var AcpClient = class {
32374
32861
  throw new RequestError(-32002, INTERNAL_BLOCK_REASON, { uri: params.path });
32375
32862
  }
32376
32863
  try {
32377
- await fs62.writeFile(params.path, params.content, "utf8");
32864
+ await fs64.writeFile(params.path, params.content, "utf8");
32378
32865
  return {};
32379
32866
  } catch (err) {
32380
32867
  const code = err.code;
@@ -32439,24 +32926,24 @@ function knownAgentBinaryDirs() {
32439
32926
  out2.push("/tmp/codeam-node20/bin");
32440
32927
  for (const root of [
32441
32928
  "/usr/local/share/nvm/versions/node",
32442
- path68.join(home, ".nvm/versions/node")
32929
+ path70.join(home, ".nvm/versions/node")
32443
32930
  ]) {
32444
32931
  try {
32445
32932
  for (const child of fsSync.readdirSync(root)) {
32446
- out2.push(path68.join(root, child, "bin"));
32933
+ out2.push(path70.join(root, child, "bin"));
32447
32934
  }
32448
32935
  } catch {
32449
32936
  }
32450
32937
  }
32451
- out2.push(path68.join(home, ".volta/bin"));
32938
+ out2.push(path70.join(home, ".volta/bin"));
32452
32939
  out2.push("/usr/local/bin");
32453
32940
  out2.push("/usr/bin");
32454
- out2.push(path68.join(home, ".local/bin"));
32455
- out2.push(path68.join(home, "bin"));
32941
+ out2.push(path70.join(home, ".local/bin"));
32942
+ out2.push(path70.join(home, "bin"));
32456
32943
  if (process.platform === "win32") {
32457
32944
  const { LOCALAPPDATA, APPDATA } = process.env;
32458
- if (LOCALAPPDATA) out2.push(path68.join(LOCALAPPDATA, "cursor-agent"));
32459
- if (APPDATA) out2.push(path68.join(APPDATA, "npm"));
32945
+ if (LOCALAPPDATA) out2.push(path70.join(LOCALAPPDATA, "cursor-agent"));
32946
+ if (APPDATA) out2.push(path70.join(APPDATA, "npm"));
32460
32947
  }
32461
32948
  return out2.filter((p2) => {
32462
32949
  try {
@@ -32468,7 +32955,7 @@ function knownAgentBinaryDirs() {
32468
32955
  }
32469
32956
  function expandPathForAgentBinaries(existingPath) {
32470
32957
  const existing = new Set(
32471
- existingPath.split(path68.delimiter).filter((p2) => p2.length > 0)
32958
+ existingPath.split(path70.delimiter).filter((p2) => p2.length > 0)
32472
32959
  );
32473
32960
  const additions = [];
32474
32961
  for (const dir of knownAgentBinaryDirs()) {
@@ -32478,7 +32965,7 @@ function expandPathForAgentBinaries(existingPath) {
32478
32965
  }
32479
32966
  }
32480
32967
  if (additions.length === 0) return existingPath;
32481
- return [...additions, existingPath].filter((p2) => p2.length > 0).join(path68.delimiter);
32968
+ return [...additions, existingPath].filter((p2) => p2.length > 0).join(path70.delimiter);
32482
32969
  }
32483
32970
 
32484
32971
  // src/agents/acp/headroom-budget-proxy.ts
@@ -32960,15 +33447,15 @@ function commonPrefixLength(a, b) {
32960
33447
 
32961
33448
  // src/agents/acp/onboarding.ts
32962
33449
  var import_child_process27 = require("child_process");
32963
- var fs63 = __toESM(require("fs"));
33450
+ var fs65 = __toESM(require("fs"));
32964
33451
  var os54 = __toESM(require("os"));
32965
- var path69 = __toESM(require("path"));
33452
+ var path71 = __toESM(require("path"));
32966
33453
  var _onboardingSeam = {
32967
- markerPath: (sessionId) => path69.join(os54.homedir(), ".codeam", "welcomed", `${sessionId}.done`),
32968
- exists: (p2) => fs63.existsSync(p2),
33454
+ markerPath: (sessionId) => path71.join(os54.homedir(), ".codeam", "welcomed", `${sessionId}.done`),
33455
+ exists: (p2) => fs65.existsSync(p2),
32969
33456
  write: (p2) => {
32970
- fs63.mkdirSync(path69.dirname(p2), { recursive: true });
32971
- fs63.writeFileSync(p2, "");
33457
+ fs65.mkdirSync(path71.dirname(p2), { recursive: true });
33458
+ fs65.writeFileSync(p2, "");
32972
33459
  },
32973
33460
  disabled: () => {
32974
33461
  const v = process.env.CODEAM_ONBOARDING_DISABLED;
@@ -33005,7 +33492,7 @@ function resolveRepoName(cwd) {
33005
33492
  if (name) return name;
33006
33493
  }
33007
33494
  }
33008
- const base = path69.basename(cwd || "");
33495
+ const base = path71.basename(cwd || "");
33009
33496
  if (base && !isUuid(base)) return base;
33010
33497
  return "this project";
33011
33498
  }
@@ -33263,13 +33750,13 @@ var import_crypto5 = require("crypto");
33263
33750
 
33264
33751
  // src/services/turn-files/git-changeset.ts
33265
33752
  var import_child_process28 = require("child_process");
33266
- var fs65 = __toESM(require("fs/promises"));
33267
- var path71 = __toESM(require("path"));
33753
+ var fs67 = __toESM(require("fs/promises"));
33754
+ var path73 = __toESM(require("path"));
33268
33755
 
33269
33756
  // src/services/turn-files/review-ignore.ts
33270
33757
  var import_ignore2 = __toESM(require("ignore"));
33271
- var fs64 = __toESM(require("fs"));
33272
- var path70 = __toESM(require("path"));
33758
+ var fs66 = __toESM(require("fs"));
33759
+ var path72 = __toESM(require("path"));
33273
33760
  var CURATED_REVIEW_IGNORE = [
33274
33761
  // Google Cloud SDK (the incident) — installs a huge python tree.
33275
33762
  "google-cloud-sdk/",
@@ -33308,7 +33795,7 @@ var CURATED_REVIEW_IGNORE = [
33308
33795
  function makeReviewIgnore(repoRoot) {
33309
33796
  const ig = (0, import_ignore2.default)().add(CURATED_REVIEW_IGNORE);
33310
33797
  try {
33311
- const custom = fs64.readFileSync(path70.join(repoRoot, ".codeam", "reviewignore"), "utf8");
33798
+ const custom = fs66.readFileSync(path72.join(repoRoot, ".codeam", "reviewignore"), "utf8");
33312
33799
  ig.add(custom);
33313
33800
  } catch {
33314
33801
  }
@@ -33353,7 +33840,7 @@ async function collectRepoChangeset(opts) {
33353
33840
  let stats;
33354
33841
  if (!truncated && row.fileStatus === "added" && numstatEntry === void 0) {
33355
33842
  const lineCount = await readUntrackedLineCount(
33356
- path71.join(opts.repoRoot, row.filePath)
33843
+ path73.join(opts.repoRoot, row.filePath)
33357
33844
  );
33358
33845
  stats = { added: lineCount, removed: 0 };
33359
33846
  } else {
@@ -33384,7 +33871,7 @@ function readUntrackedLineCount(absPath) {
33384
33871
  }
33385
33872
  async function defaultReadUntrackedLineCount(absPath) {
33386
33873
  try {
33387
- const content = await fs65.readFile(absPath, "utf8");
33874
+ const content = await fs67.readFile(absPath, "utf8");
33388
33875
  let count = 0;
33389
33876
  let pos = -1;
33390
33877
  while ((pos = content.indexOf("\n", pos + 1)) !== -1) {
@@ -33476,7 +33963,7 @@ function defaultRunGit(cwd, args2) {
33476
33963
  });
33477
33964
  }
33478
33965
  async function discoverRepos(workingDir, maxDepth = 4) {
33479
- const fs72 = await import("fs/promises");
33966
+ const fs74 = await import("fs/promises");
33480
33967
  const out2 = [];
33481
33968
  await walk(workingDir, 0);
33482
33969
  return out2;
@@ -33484,7 +33971,7 @@ async function discoverRepos(workingDir, maxDepth = 4) {
33484
33971
  if (depth > maxDepth) return;
33485
33972
  let entries = [];
33486
33973
  try {
33487
- const dirents = await fs72.readdir(dir, { withFileTypes: true });
33974
+ const dirents = await fs74.readdir(dir, { withFileTypes: true });
33488
33975
  entries = dirents.filter((d3) => !d3.name.startsWith(".") || d3.name === ".git").map((d3) => ({ name: d3.name, isDirectory: d3.isDirectory() }));
33489
33976
  } catch {
33490
33977
  return;
@@ -33495,8 +33982,8 @@ async function discoverRepos(workingDir, maxDepth = 4) {
33495
33982
  if (hasGit) {
33496
33983
  out2.push({
33497
33984
  repoRoot: dir,
33498
- repoPath: path71.relative(workingDir, dir),
33499
- repoName: path71.basename(dir)
33985
+ repoPath: path73.relative(workingDir, dir),
33986
+ repoName: path73.basename(dir)
33500
33987
  });
33501
33988
  return;
33502
33989
  }
@@ -33504,14 +33991,14 @@ async function discoverRepos(workingDir, maxDepth = 4) {
33504
33991
  if (!entry.isDirectory) continue;
33505
33992
  if (entry.name === "node_modules") continue;
33506
33993
  if (entry.name === "dist" || entry.name === "build") continue;
33507
- await walk(path71.join(dir, entry.name), depth + 1);
33994
+ await walk(path73.join(dir, entry.name), depth + 1);
33508
33995
  }
33509
33996
  }
33510
33997
  }
33511
33998
 
33512
33999
  // src/services/turn-files/files-outbox.ts
33513
- var fs66 = __toESM(require("fs/promises"));
33514
- var path72 = __toESM(require("path"));
34000
+ var fs68 = __toESM(require("fs/promises"));
34001
+ var path74 = __toESM(require("path"));
33515
34002
  var import_os12 = require("os");
33516
34003
  var HOME_OUTBOX_DIR = ".codeam/outbox";
33517
34004
  var MAX_AGE_MS = 24 * 60 * 60 * 1e3;
@@ -33544,16 +34031,16 @@ var FilesOutbox = class {
33544
34031
  backoffIndex = 0;
33545
34032
  stopped = false;
33546
34033
  constructor(opts) {
33547
- const base = opts.baseDir ?? path72.join(homeDir(), HOME_OUTBOX_DIR);
33548
- this.filePath = path72.join(base, `${opts.sessionId}.jsonl`);
34034
+ const base = opts.baseDir ?? path74.join(homeDir(), HOME_OUTBOX_DIR);
34035
+ this.filePath = path74.join(base, `${opts.sessionId}.jsonl`);
33549
34036
  this.post = opts.post;
33550
34037
  this.autoSchedule = opts.autoSchedule !== false;
33551
34038
  }
33552
34039
  /** Persist the entry to disk and trigger a flush. Returns once the
33553
34040
  * line is durable on disk (not once the POST succeeds). */
33554
34041
  async enqueue(entry) {
33555
- await fs66.mkdir(path72.dirname(this.filePath), { recursive: true });
33556
- await fs66.appendFile(this.filePath, JSON.stringify(entry) + "\n", "utf8");
34042
+ await fs68.mkdir(path74.dirname(this.filePath), { recursive: true });
34043
+ await fs68.appendFile(this.filePath, JSON.stringify(entry) + "\n", "utf8");
33557
34044
  this.backoffIndex = 0;
33558
34045
  if (this.autoSchedule) this.scheduleFlush(0);
33559
34046
  }
@@ -33644,7 +34131,7 @@ var FilesOutbox = class {
33644
34131
  async readAll() {
33645
34132
  let raw = "";
33646
34133
  try {
33647
- raw = await fs66.readFile(this.filePath, "utf8");
34134
+ raw = await fs68.readFile(this.filePath, "utf8");
33648
34135
  } catch {
33649
34136
  return [];
33650
34137
  }
@@ -33668,12 +34155,12 @@ var FilesOutbox = class {
33668
34155
  async rewrite(entries) {
33669
34156
  const tmpPath = `${this.filePath}.${process.pid}.tmp`;
33670
34157
  if (entries.length === 0) {
33671
- await fs66.unlink(this.filePath).catch(() => void 0);
34158
+ await fs68.unlink(this.filePath).catch(() => void 0);
33672
34159
  return;
33673
34160
  }
33674
34161
  const payload = entries.map((e) => JSON.stringify(e)).join("\n") + "\n";
33675
- await fs66.writeFile(tmpPath, payload, "utf8");
33676
- await fs66.rename(tmpPath, this.filePath);
34162
+ await fs68.writeFile(tmpPath, payload, "utf8");
34163
+ await fs68.rename(tmpPath, this.filePath);
33677
34164
  }
33678
34165
  };
33679
34166
  function applyJitter(ms) {
@@ -34418,11 +34905,13 @@ async function startTaskH(ctx) {
34418
34905
  }
34419
34906
  await streaming.beginTurn();
34420
34907
  history.appendUserPrompt(promptText);
34908
+ let turnClosed = false;
34421
34909
  try {
34422
34910
  const reply = await client3.prompt(blocks);
34423
34911
  const finalText = streaming.getCurrentText();
34424
34912
  if (agentHooks(opts.agent)?.classifyCompletedReply?.(finalText) === "upgrade_required") {
34425
34913
  await streaming.closeWithBubble(CURSOR_UPGRADE_MESSAGE);
34914
+ turnClosed = true;
34426
34915
  history.appendAgentReply(CURSOR_UPGRADE_MESSAGE);
34427
34916
  void history.flush();
34428
34917
  log.info("acpRunner", `start_task \u2190 cursor-plan-upgrade-required id=${cmd.id.slice(0, 8)}`);
@@ -34430,6 +34919,7 @@ async function startTaskH(ctx) {
34430
34919
  } else if (replyIsHouseAgentLimit(finalText)) {
34431
34920
  const houseBubble = houseAgentLimitMessage(finalText);
34432
34921
  await streaming.closeWithBubble(houseBubble);
34922
+ turnClosed = true;
34433
34923
  history.appendAgentReply(houseBubble);
34434
34924
  void history.flush();
34435
34925
  turnFiles.flushTurn().catch((err) => {
@@ -34441,6 +34931,7 @@ async function startTaskH(ctx) {
34441
34931
  });
34442
34932
  } else if (replyIsAuthFailure(finalText)) {
34443
34933
  await streaming.closeWithBubble(AUTH_FAILURE_MESSAGE);
34934
+ turnClosed = true;
34444
34935
  history.appendAgentReply(AUTH_FAILURE_MESSAGE);
34445
34936
  void history.flush();
34446
34937
  turnFiles.flushTurn().catch((err) => {
@@ -34451,6 +34942,7 @@ async function startTaskH(ctx) {
34451
34942
  await relay.sendResult(cmd.id, "failed", { error: "agent reply reported auth failure" });
34452
34943
  } else if (shouldOfferOneMRecovery({ detail: "", recentStderr: recentStderr.join("\n"), finalText })) {
34453
34944
  await streaming.closeWithBubble(ONE_M_CREDITS_MESSAGE);
34945
+ turnClosed = true;
34454
34946
  history.appendAgentReply(ONE_M_CREDITS_MESSAGE);
34455
34947
  void history.flush();
34456
34948
  turnFiles.flushTurn().catch((err) => {
@@ -34463,6 +34955,7 @@ async function startTaskH(ctx) {
34463
34955
  });
34464
34956
  } else {
34465
34957
  await streaming.closeTurnWithInteractiveDetection();
34958
+ turnClosed = true;
34466
34959
  const replyLine = formatAgentReplyLine(finalText);
34467
34960
  if (replyLine.length > 0) {
34468
34961
  showInfo(replyLine);
@@ -34481,6 +34974,13 @@ async function startTaskH(ctx) {
34481
34974
  await relay.sendResult(cmd.id, "completed", { stopReason: reply.stopReason });
34482
34975
  }
34483
34976
  } catch (err) {
34977
+ if (turnClosed) {
34978
+ log.warn(
34979
+ "acpRunner",
34980
+ `post-close ack failed (turn already delivered) id=${cmd.id.slice(0, 8)}: ${describeError(err)}`
34981
+ );
34982
+ return;
34983
+ }
34484
34984
  const hadText = streaming.hasVisibleProgress();
34485
34985
  const detail = describeError(err);
34486
34986
  log.warn("acpRunner", `prompt failed: ${detail}`);
@@ -36918,8 +37418,8 @@ function startClaudeCredentialSync(opts) {
36918
37418
  }
36919
37419
 
36920
37420
  // src/beads/workflow-hint.ts
36921
- var fs68 = __toESM(require("fs"));
36922
- var path74 = __toESM(require("path"));
37421
+ var fs70 = __toESM(require("fs"));
37422
+ var path76 = __toESM(require("path"));
36923
37423
  var os55 = __toESM(require("os"));
36924
37424
  var BEADS_HINT_MARKER = "<!-- codeam:beads-workflow -->";
36925
37425
  var BEADS_HINT = `${BEADS_HINT_MARKER}
@@ -36936,20 +37436,20 @@ This environment uses **bd (beads)** for issue/task tracking and persistent memo
36936
37436
  ${BEADS_HINT_MARKER}`;
36937
37437
  function ensureBeadsWorkflowHint(homeDir2 = os55.homedir()) {
36938
37438
  try {
36939
- const file = path74.join(homeDir2, ".claude", "CLAUDE.md");
37439
+ const file = path76.join(homeDir2, ".claude", "CLAUDE.md");
36940
37440
  let existing = "";
36941
37441
  try {
36942
- existing = fs68.readFileSync(file, "utf8");
37442
+ existing = fs70.readFileSync(file, "utf8");
36943
37443
  } catch {
36944
37444
  }
36945
37445
  if (existing.includes(BEADS_HINT_MARKER)) return;
36946
- fs68.mkdirSync(path74.dirname(file), { recursive: true });
37446
+ fs70.mkdirSync(path76.dirname(file), { recursive: true });
36947
37447
  const next = existing.trim() ? `${existing.trimEnd()}
36948
37448
 
36949
37449
  ${BEADS_HINT}
36950
37450
  ` : `${BEADS_HINT}
36951
37451
  `;
36952
- fs68.writeFileSync(file, next);
37452
+ fs70.writeFileSync(file, next);
36953
37453
  } catch {
36954
37454
  }
36955
37455
  }
@@ -37321,7 +37821,7 @@ var AcpDriver = class {
37321
37821
  };
37322
37822
 
37323
37823
  // src/baton/transcript-mirror.ts
37324
- var fs69 = __toESM(require("fs"));
37824
+ var fs71 = __toESM(require("fs"));
37325
37825
  var TranscriptMirror = class {
37326
37826
  constructor(deps) {
37327
37827
  this.deps = deps;
@@ -37388,7 +37888,7 @@ var TranscriptMirror = class {
37388
37888
  }
37389
37889
  };
37390
37890
  function defaultWatch(file, onChange) {
37391
- const w3 = fs69.watch(file, { persistent: false }, () => onChange());
37891
+ const w3 = fs71.watch(file, { persistent: false }, () => onChange());
37392
37892
  return () => w3.close();
37393
37893
  }
37394
37894
 
@@ -37650,16 +38150,16 @@ function toEpochMs(ts) {
37650
38150
  }
37651
38151
 
37652
38152
  // src/agents/claude/onboarding.ts
37653
- var fs70 = __toESM(require("fs"));
38153
+ var fs72 = __toESM(require("fs"));
37654
38154
  var os57 = __toESM(require("os"));
37655
- var path75 = __toESM(require("path"));
38155
+ var path77 = __toESM(require("path"));
37656
38156
  var ONBOARDING_VERSION_SENTINEL = "9999.0.0";
37657
38157
  function ensureClaudeOnboarded(cwd) {
37658
38158
  try {
37659
- const file = path75.join(os57.homedir(), ".claude.json");
38159
+ const file = path77.join(os57.homedir(), ".claude.json");
37660
38160
  let config = {};
37661
38161
  try {
37662
- config = JSON.parse(fs70.readFileSync(file, "utf8"));
38162
+ config = JSON.parse(fs72.readFileSync(file, "utf8"));
37663
38163
  } catch {
37664
38164
  }
37665
38165
  let changed = false;
@@ -37684,8 +38184,8 @@ function ensureClaudeOnboarded(cwd) {
37684
38184
  }
37685
38185
  }
37686
38186
  if (!changed) return;
37687
- fs70.mkdirSync(path75.dirname(file), { recursive: true });
37688
- fs70.writeFileSync(file, JSON.stringify(config, null, 2));
38187
+ fs72.mkdirSync(path77.dirname(file), { recursive: true });
38188
+ fs72.writeFileSync(file, JSON.stringify(config, null, 2));
37689
38189
  log.info(
37690
38190
  "claude",
37691
38191
  `pre-completed Claude onboarding${cwd ? ` + trusted workspace ${cwd}` : ""}`
@@ -38412,7 +38912,7 @@ var import_picocolors11 = __toESM(require("picocolors"));
38412
38912
  var import_child_process29 = require("child_process");
38413
38913
  var import_util4 = require("util");
38414
38914
  var import_picocolors9 = __toESM(require("picocolors"));
38415
- var path76 = __toESM(require("path"));
38915
+ var path78 = __toESM(require("path"));
38416
38916
  var execFileP6 = (0, import_util4.promisify)(import_child_process29.execFile);
38417
38917
  var MAX_BUFFER = 8 * 1024 * 1024;
38418
38918
  function resetStdinForChild() {
@@ -38901,7 +39401,7 @@ var GitHubCodespacesProvider = class {
38901
39401
  });
38902
39402
  }
38903
39403
  async uploadFile(workspaceId, remotePath, contents, options = {}) {
38904
- const remoteDir = path76.posix.dirname(remotePath);
39404
+ const remoteDir = path78.posix.dirname(remotePath);
38905
39405
  const parts = [
38906
39406
  `mkdir -p ${shellQuote(remoteDir)}`,
38907
39407
  `cat > ${shellQuote(remotePath)}`
@@ -38971,7 +39471,7 @@ function shellQuote(s) {
38971
39471
  // src/services/providers/gitpod.ts
38972
39472
  var import_child_process30 = require("child_process");
38973
39473
  var import_util5 = require("util");
38974
- var path77 = __toESM(require("path"));
39474
+ var path79 = __toESM(require("path"));
38975
39475
  var import_picocolors10 = __toESM(require("picocolors"));
38976
39476
  var execFileP7 = (0, import_util5.promisify)(import_child_process30.execFile);
38977
39477
  var MAX_BUFFER2 = 8 * 1024 * 1024;
@@ -39211,7 +39711,7 @@ var GitpodProvider = class {
39211
39711
  });
39212
39712
  }
39213
39713
  async uploadFile(workspaceId, remotePath, contents, options = {}) {
39214
- const remoteDir = path77.posix.dirname(remotePath);
39714
+ const remoteDir = path79.posix.dirname(remotePath);
39215
39715
  const parts = [
39216
39716
  `mkdir -p ${shellQuote2(remoteDir)}`,
39217
39717
  `cat > ${shellQuote2(remotePath)}`
@@ -39247,7 +39747,7 @@ function shellQuote2(s) {
39247
39747
  // src/services/providers/gitlab-workspaces.ts
39248
39748
  var import_child_process31 = require("child_process");
39249
39749
  var import_util6 = require("util");
39250
- var path78 = __toESM(require("path"));
39750
+ var path80 = __toESM(require("path"));
39251
39751
  var execFileP8 = (0, import_util6.promisify)(import_child_process31.execFile);
39252
39752
  var MAX_BUFFER3 = 8 * 1024 * 1024;
39253
39753
  var GITLAB_API_BASE = process.env.CODEAM_GITLAB_API_URL ?? "https://gitlab.com/api/v4";
@@ -39507,7 +40007,7 @@ Docs: https://docs.gitlab.com/ee/user/workspace/configuration.html`
39507
40007
  }
39508
40008
  async uploadFile(workspaceId, remotePath, contents, options = {}) {
39509
40009
  const sshHost = process.env.CODEAM_GITLAB_SSH_HOST ?? "workspaces.gitlab.com";
39510
- const remoteDir = path78.posix.dirname(remotePath);
40010
+ const remoteDir = path80.posix.dirname(remotePath);
39511
40011
  const parts = [`mkdir -p ${shellQuote3(remoteDir)}`, `cat > ${shellQuote3(remotePath)}`];
39512
40012
  if (options.mode != null) {
39513
40013
  parts.push(`chmod ${options.mode.toString(8)} ${shellQuote3(remotePath)}`);
@@ -39575,7 +40075,7 @@ function shellQuote3(s) {
39575
40075
  // src/services/providers/railway.ts
39576
40076
  var import_child_process32 = require("child_process");
39577
40077
  var import_util7 = require("util");
39578
- var path79 = __toESM(require("path"));
40078
+ var path81 = __toESM(require("path"));
39579
40079
  var execFileP9 = (0, import_util7.promisify)(import_child_process32.execFile);
39580
40080
  var MAX_BUFFER4 = 8 * 1024 * 1024;
39581
40081
  function resetStdinForChild4() {
@@ -39811,7 +40311,7 @@ var RailwayProvider = class {
39811
40311
  if (!projectId || !serviceId) {
39812
40312
  throw new Error("Invalid Railway workspace id (expected projectId/serviceId).");
39813
40313
  }
39814
- const remoteDir = path79.posix.dirname(remotePath);
40314
+ const remoteDir = path81.posix.dirname(remotePath);
39815
40315
  const parts = [`mkdir -p ${shellQuote4(remoteDir)}`, `cat > ${shellQuote4(remotePath)}`];
39816
40316
  if (options.mode != null) {
39817
40317
  parts.push(`chmod ${options.mode.toString(8)} ${shellQuote4(remotePath)}`);
@@ -40457,8 +40957,8 @@ async function invite() {
40457
40957
  var import_node_dns = require("dns");
40458
40958
  var import_node_util5 = require("util");
40459
40959
  var import_node_crypto13 = require("crypto");
40460
- var fs71 = __toESM(require("fs"));
40461
- var path80 = __toESM(require("path"));
40960
+ var fs73 = __toESM(require("fs"));
40961
+ var path82 = __toESM(require("path"));
40462
40962
  var import_picocolors14 = __toESM(require("picocolors"));
40463
40963
  var dnsResolveP = (0, import_node_util5.promisify)(import_node_dns.resolve);
40464
40964
  async function checkDns(apiBase2) {
@@ -40514,13 +41014,13 @@ async function checkHealth(apiBase2) {
40514
41014
  }
40515
41015
  }
40516
41016
  function checkConfigDir() {
40517
- const dir = path80.join(require("os").homedir(), ".codeam");
41017
+ const dir = path82.join(require("os").homedir(), ".codeam");
40518
41018
  try {
40519
- fs71.mkdirSync(dir, { recursive: true, mode: 448 });
40520
- const probe = path80.join(dir, ".doctor-probe");
40521
- fs71.writeFileSync(probe, "ok", { mode: 384 });
40522
- const read2 = fs71.readFileSync(probe, "utf8");
40523
- fs71.unlinkSync(probe);
41019
+ fs73.mkdirSync(dir, { recursive: true, mode: 448 });
41020
+ const probe = path82.join(dir, ".doctor-probe");
41021
+ fs73.writeFileSync(probe, "ok", { mode: 384 });
41022
+ const read2 = fs73.readFileSync(probe, "utf8");
41023
+ fs73.unlinkSync(probe);
40524
41024
  if (read2 !== "ok") throw new Error("write/read round-trip mismatch");
40525
41025
  return {
40526
41026
  id: "config-dir",
@@ -40584,7 +41084,7 @@ function checkNodePty() {
40584
41084
  detail: "not required on this platform"
40585
41085
  };
40586
41086
  }
40587
- const vendoredPath = path80.join(__dirname, "vendor", "node-pty");
41087
+ const vendoredPath = path82.join(__dirname, "vendor", "node-pty");
40588
41088
  for (const target of [vendoredPath, "node-pty"]) {
40589
41089
  try {
40590
41090
  require(target);
@@ -40626,7 +41126,7 @@ function checkChokidar() {
40626
41126
  }
40627
41127
  async function doctor(args2 = []) {
40628
41128
  const json = args2.includes("--json");
40629
- const cliVersion = true ? "2.61.80" : "0.0.0-dev";
41129
+ const cliVersion = true ? "2.61.82" : "0.0.0-dev";
40630
41130
  const apiBase2 = resolveApiBaseUrl();
40631
41131
  const diagnosticId = (0, import_node_crypto13.randomUUID)();
40632
41132
  log.info("doctor", `run id=${diagnosticId} cli=${cliVersion}`);
@@ -41167,6 +41667,17 @@ async function mcpRun(args2) {
41167
41667
  `);
41168
41668
  process.exit(1);
41169
41669
  }
41670
+ if (delivery.builtin === "convex-admin") {
41671
+ const client4 = new IntegrationTokenClient({
41672
+ sessionId,
41673
+ pluginId,
41674
+ pluginAuthToken,
41675
+ pollSecret: process.env.CODEAM_MCP_POLL_SECRET
41676
+ });
41677
+ const { runConvexAdminMcp: runConvexAdminMcp2 } = await Promise.resolve().then(() => (init_convex_admin_mcp(), convex_admin_mcp_exports));
41678
+ await runConvexAdminMcp2(client4, id);
41679
+ return;
41680
+ }
41170
41681
  if (delivery.httpUrl) {
41171
41682
  const httpClient = new IntegrationTokenClient({
41172
41683
  sessionId,
@@ -41205,7 +41716,7 @@ async function mcpRun(args2) {
41205
41716
  // src/commands/version.ts
41206
41717
  var import_picocolors15 = __toESM(require("picocolors"));
41207
41718
  function version2() {
41208
- const v = true ? "2.61.80" : "unknown";
41719
+ const v = true ? "2.61.82" : "unknown";
41209
41720
  console.log(`${import_picocolors15.default.bold("codeam-cli")} ${import_picocolors15.default.cyan(v)}`);
41210
41721
  }
41211
41722