codeam-cli 2.75.2 → 2.75.4
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.
- package/CHANGELOG.md +30 -0
- package/dist/index.js +232 -66
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,36 @@ All notable changes to `codeam-cli` are documented here.
|
|
|
4
4
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
6
6
|
|
|
7
|
+
## [2.75.3] — 2026-09-16
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
- **cli:** The agent can deploy, without ever seeing the deploy key (#758)
|
|
12
|
+
|
|
13
|
+
### Fixed
|
|
14
|
+
|
|
15
|
+
- **shared:** Gemini solo acepta API key — Google retiró el nivel OAuth (#761)
|
|
16
|
+
|
|
17
|
+
## [2.75.2] — 2026-09-15
|
|
18
|
+
|
|
19
|
+
### Added
|
|
20
|
+
|
|
21
|
+
- **shared:** Declare the credits_changed user event
|
|
22
|
+
|
|
23
|
+
### CI
|
|
24
|
+
|
|
25
|
+
- **release:** Wait up to 7.5 min for npm to serve the published version (#754)
|
|
26
|
+
|
|
27
|
+
### Fixed
|
|
28
|
+
|
|
29
|
+
- **cli:** A managed-rail outage must never be blamed on Anthropic (#757)
|
|
30
|
+
|
|
31
|
+
## [2.75.1] — 2026-09-12
|
|
32
|
+
|
|
33
|
+
### Fixed
|
|
34
|
+
|
|
35
|
+
- **cli:** Managed sessions announce the managed agent, not the Claude Code runtime (#753)
|
|
36
|
+
|
|
7
37
|
## [2.75.0] — 2026-09-12
|
|
8
38
|
|
|
9
39
|
### Added
|
package/dist/index.js
CHANGED
|
@@ -271,8 +271,8 @@ var init_stdio_proxy = __esm({
|
|
|
271
271
|
}
|
|
272
272
|
async spawnChild(stdout, preResolved) {
|
|
273
273
|
const spec = preResolved ?? await this.opts.spawnSpec();
|
|
274
|
-
const
|
|
275
|
-
const child =
|
|
274
|
+
const spawn49 = this.opts.spawnImpl ?? import_node_child_process33.spawn;
|
|
275
|
+
const child = spawn49(spec.command, spec.args, {
|
|
276
276
|
env: { ...process.env, ...spec.env },
|
|
277
277
|
// env only — never argv
|
|
278
278
|
stdio: ["pipe", "pipe", "inherit"]
|
|
@@ -300,7 +300,9 @@ var convex_admin_mcp_exports = {};
|
|
|
300
300
|
__export(convex_admin_mcp_exports, {
|
|
301
301
|
callConvexTool: () => callConvexTool,
|
|
302
302
|
deploymentNameFromKey: () => deploymentNameFromKey,
|
|
303
|
-
|
|
303
|
+
resolveConvexBin: () => resolveConvexBin,
|
|
304
|
+
runConvexAdminMcp: () => runConvexAdminMcp,
|
|
305
|
+
runConvexDeploy: () => runConvexDeploy
|
|
304
306
|
});
|
|
305
307
|
function deploymentNameFromKey(key) {
|
|
306
308
|
const prefix = key.split("|")[0];
|
|
@@ -310,6 +312,81 @@ function deploymentNameFromKey(key) {
|
|
|
310
312
|
}
|
|
311
313
|
return null;
|
|
312
314
|
}
|
|
315
|
+
function defaultSpawn(timeoutMs) {
|
|
316
|
+
return (cmd, args2, opts) => new Promise((resolve11) => {
|
|
317
|
+
let out2 = "";
|
|
318
|
+
let err = "";
|
|
319
|
+
let done = false;
|
|
320
|
+
const finish = (code) => {
|
|
321
|
+
if (done) return;
|
|
322
|
+
done = true;
|
|
323
|
+
resolve11({ code, stdout: out2, stderr: err });
|
|
324
|
+
};
|
|
325
|
+
let child;
|
|
326
|
+
try {
|
|
327
|
+
child = (0, import_node_child_process34.spawn)(cmd, args2, { cwd: opts.cwd, env: opts.env, stdio: ["ignore", "pipe", "pipe"] });
|
|
328
|
+
} catch (e) {
|
|
329
|
+
finish(1);
|
|
330
|
+
err = e instanceof Error ? e.message : String(e);
|
|
331
|
+
return;
|
|
332
|
+
}
|
|
333
|
+
const timer = setTimeout(() => {
|
|
334
|
+
try {
|
|
335
|
+
child.kill("SIGKILL");
|
|
336
|
+
} catch {
|
|
337
|
+
}
|
|
338
|
+
err += `
|
|
339
|
+
[codeam] convex deploy timed out after ${Math.round(timeoutMs / 1e3)}s`;
|
|
340
|
+
finish(124);
|
|
341
|
+
}, timeoutMs);
|
|
342
|
+
child.stdout?.on("data", (c2) => {
|
|
343
|
+
out2 += c2.toString();
|
|
344
|
+
});
|
|
345
|
+
child.stderr?.on("data", (c2) => {
|
|
346
|
+
err += c2.toString();
|
|
347
|
+
});
|
|
348
|
+
child.on("error", (e) => {
|
|
349
|
+
clearTimeout(timer);
|
|
350
|
+
err += (err ? "\n" : "") + e.message;
|
|
351
|
+
finish(1);
|
|
352
|
+
});
|
|
353
|
+
child.on("close", (code) => {
|
|
354
|
+
clearTimeout(timer);
|
|
355
|
+
finish(code ?? 1);
|
|
356
|
+
});
|
|
357
|
+
});
|
|
358
|
+
}
|
|
359
|
+
function resolveConvexBin(cwd) {
|
|
360
|
+
const local = path95.join(cwd, "node_modules", ".bin", process.platform === "win32" ? "convex.cmd" : "convex");
|
|
361
|
+
if (fs83.existsSync(local)) return { cmd: local, args: [] };
|
|
362
|
+
return { cmd: "npx", args: ["--yes", "convex"] };
|
|
363
|
+
}
|
|
364
|
+
function redact(text, key) {
|
|
365
|
+
if (!key) return text;
|
|
366
|
+
return text.split(key).join("***");
|
|
367
|
+
}
|
|
368
|
+
async function runConvexDeploy(key, args2, opts = {}) {
|
|
369
|
+
const cwd = args2.projectDir ?? opts.cwd ?? process.cwd();
|
|
370
|
+
const timeoutMs = opts.timeoutMs ?? 3e5;
|
|
371
|
+
const run = opts.spawnImpl ?? defaultSpawn(timeoutMs);
|
|
372
|
+
const bin = resolveConvexBin(cwd);
|
|
373
|
+
const argv = [...bin.args, "deploy"];
|
|
374
|
+
if (args2.previewName) argv.push("--preview-create", String(args2.previewName));
|
|
375
|
+
const { code, stdout, stderr } = await run(bin.cmd, argv, {
|
|
376
|
+
cwd,
|
|
377
|
+
// The ONLY place the secret travels.
|
|
378
|
+
env: { ...process.env, CONVEX_DEPLOY_KEY: key }
|
|
379
|
+
});
|
|
380
|
+
const body = redact([stdout, stderr].filter(Boolean).join("\n").trim(), key);
|
|
381
|
+
if (code === 0) {
|
|
382
|
+
return { ok: true, text: body || "Convex deploy completed." };
|
|
383
|
+
}
|
|
384
|
+
return {
|
|
385
|
+
ok: false,
|
|
386
|
+
text: `Convex deploy failed (exit ${code}).
|
|
387
|
+
${body}`
|
|
388
|
+
};
|
|
389
|
+
}
|
|
313
390
|
async function adminQuery(baseUrl, key, api, body, fetchImpl = fetch) {
|
|
314
391
|
const res = await fetchImpl(`${baseUrl}/api/${api}`, {
|
|
315
392
|
method: "POST",
|
|
@@ -320,7 +397,24 @@ async function adminQuery(baseUrl, key, api, body, fetchImpl = fetch) {
|
|
|
320
397
|
const ok = res.ok && !/"status"\s*:\s*"error"/.test(text);
|
|
321
398
|
return { ok, text };
|
|
322
399
|
}
|
|
323
|
-
async function callConvexTool(baseUrl, key, tool, args2, fetchImpl = fetch) {
|
|
400
|
+
async function callConvexTool(baseUrl, key, tool, args2, fetchImpl = fetch, deployOpts = {}) {
|
|
401
|
+
switch (tool) {
|
|
402
|
+
case "deploy":
|
|
403
|
+
return runConvexDeploy(
|
|
404
|
+
key,
|
|
405
|
+
{
|
|
406
|
+
projectDir: typeof args2.projectDir === "string" ? args2.projectDir : void 0,
|
|
407
|
+
previewName: typeof args2.previewName === "string" ? args2.previewName : void 0
|
|
408
|
+
},
|
|
409
|
+
deployOpts
|
|
410
|
+
);
|
|
411
|
+
}
|
|
412
|
+
if (!baseUrl) {
|
|
413
|
+
return {
|
|
414
|
+
ok: false,
|
|
415
|
+
text: `The connected Convex deploy key is a PROJECT key, which names no single deployment, so '${tool}' (and the other data tools) cannot reach one. Use the 'deploy' tool \u2014 it resolves the target from the key itself \u2014 or reconnect Convex with a dev/prod deploy key (Convex Dashboard \u2192 Project Settings \u2192 Deploy Keys) to enable the data tools.`
|
|
416
|
+
};
|
|
417
|
+
}
|
|
324
418
|
switch (tool) {
|
|
325
419
|
case "tables":
|
|
326
420
|
return adminQuery(baseUrl, key, "query", {
|
|
@@ -362,12 +456,11 @@ async function runConvexAdminMcp(client3, id) {
|
|
|
362
456
|
const name = deploymentNameFromKey(key);
|
|
363
457
|
if (!name) {
|
|
364
458
|
process.stderr.write(
|
|
365
|
-
`[codeam mcp-run convex]
|
|
459
|
+
`[codeam mcp-run convex] the deploy key names no single deployment (prefix "${key.split(":")[0]}"): the data tools are unavailable, 'deploy' still works. For the data tools, reconnect with a dev/prod deploy key (Convex Dashboard \u2192 Project Settings \u2192 Deploy Keys).
|
|
366
460
|
`
|
|
367
461
|
);
|
|
368
|
-
process.exit(1);
|
|
369
462
|
}
|
|
370
|
-
const baseUrl = `https://${name}.convex.cloud
|
|
463
|
+
const baseUrl = name ? `https://${name}.convex.cloud` : "";
|
|
371
464
|
const { Server } = await import("@modelcontextprotocol/sdk/server/index.js");
|
|
372
465
|
const { StdioServerTransport } = await import("@modelcontextprotocol/sdk/server/stdio.js");
|
|
373
466
|
const { ListToolsRequestSchema, CallToolRequestSchema } = await import("@modelcontextprotocol/sdk/types.js");
|
|
@@ -396,10 +489,13 @@ async function runConvexAdminMcp(client3, id) {
|
|
|
396
489
|
});
|
|
397
490
|
await server.connect(new StdioServerTransport());
|
|
398
491
|
}
|
|
399
|
-
var TOOLS;
|
|
492
|
+
var import_node_child_process34, fs83, path95, TOOLS;
|
|
400
493
|
var init_convex_admin_mcp = __esm({
|
|
401
494
|
"src/integrations/convex-admin-mcp.ts"() {
|
|
402
495
|
"use strict";
|
|
496
|
+
import_node_child_process34 = require("child_process");
|
|
497
|
+
fs83 = __toESM(require("fs"));
|
|
498
|
+
path95 = __toESM(require("path"));
|
|
403
499
|
TOOLS = [
|
|
404
500
|
{
|
|
405
501
|
name: "tables",
|
|
@@ -449,6 +545,24 @@ var init_convex_admin_mcp = __esm({
|
|
|
449
545
|
required: ["functionPath"],
|
|
450
546
|
additionalProperties: false
|
|
451
547
|
}
|
|
548
|
+
},
|
|
549
|
+
{
|
|
550
|
+
name: "deploy",
|
|
551
|
+
description: 'Deploy this repo\'s `convex/` functions, schema and indexes to the Convex deployment this integration is connected to. Use this after editing anything under `convex/` \u2014 a function you just wrote does NOT exist for the running app until it is deployed ("Could not find public function for ..." means exactly this). Do NOT run `npx convex deploy` or `npx convex dev` in the shell: those need an interactive login, and this tool already holds the credential.',
|
|
552
|
+
inputSchema: {
|
|
553
|
+
type: "object",
|
|
554
|
+
properties: {
|
|
555
|
+
projectDir: {
|
|
556
|
+
type: "string",
|
|
557
|
+
description: "Repo root holding the `convex/` directory. Defaults to the session cwd."
|
|
558
|
+
},
|
|
559
|
+
previewName: {
|
|
560
|
+
type: "string",
|
|
561
|
+
description: "Only for a PREVIEW deploy key: name the preview deployment to create (e.g. a branch name)."
|
|
562
|
+
}
|
|
563
|
+
},
|
|
564
|
+
additionalProperties: false
|
|
565
|
+
}
|
|
452
566
|
}
|
|
453
567
|
];
|
|
454
568
|
}
|
|
@@ -889,12 +1003,34 @@ var AGENT_REGISTRY = {
|
|
|
889
1003
|
displayName: "Gemini CLI",
|
|
890
1004
|
binaryName: "gemini",
|
|
891
1005
|
enabled: true,
|
|
892
|
-
//
|
|
893
|
-
//
|
|
894
|
-
//
|
|
895
|
-
//
|
|
896
|
-
|
|
897
|
-
|
|
1006
|
+
// ⚠️ API KEY ONLY since 2026-06-18, when Google stopped Gemini CLI (and the
|
|
1007
|
+
// Gemini Code Assist IDE extensions) serving requests for AI Pro, AI Ultra
|
|
1008
|
+
// and free users, in the move to Antigravity CLI. Its announcement is
|
|
1009
|
+
// explicit about what survives: "Gemini CLI will remain accessible via paid
|
|
1010
|
+
// Gemini and Gemini Enterprise Agent Platform API keys."
|
|
1011
|
+
//
|
|
1012
|
+
// So the agent stays — `@google/gemini-cli` is NOT deprecated, it still
|
|
1013
|
+
// ships weekly — but the OAuth door has to go: it captures a
|
|
1014
|
+
// `~/.gemini/oauth_creds.json` from a CONSUMER Google account, which is
|
|
1015
|
+
// exactly the tier that no longer serves requests. We used to PREFER that
|
|
1016
|
+
// path, so it was the one we recommended first; on 2026-09-15 prod held 63
|
|
1017
|
+
// Gemini links, 46 of them OAuth, 19 created after 2026-09-01 and the
|
|
1018
|
+
// newest that same day. Three months of sending people through a bricked
|
|
1019
|
+
// door — each one landing on `isGeminiIneligibleTier` at first use.
|
|
1020
|
+
//
|
|
1021
|
+
// ⚠️ Antigravity CLI is NOT a drop-in replacement for us: no official ACP
|
|
1022
|
+
// mode (google-antigravity/antigravity-cli#31 open, 192 comments, zero
|
|
1023
|
+
// `acp` hits in the repo as of 2026-09-15), and every third-party ACP
|
|
1024
|
+
// adapter warns that driving `agy` that way matches what Google's FAQ calls
|
|
1025
|
+
// a ToS violation — risking the USER's Google account. Our whole Gemini
|
|
1026
|
+
// path is ACP, so adopting it would mean shipping that risk. Revisit only
|
|
1027
|
+
// when #31 ships an official mode.
|
|
1028
|
+
//
|
|
1029
|
+
// Existing OAuth rows are NOT migrated: `supportedAuthMethods` gates the
|
|
1030
|
+
// LINK call only, so the 46 stay readable and simply keep failing at the
|
|
1031
|
+
// provider, where the ineligible-tier message already explains why.
|
|
1032
|
+
supportedAuthKinds: ["api_key"],
|
|
1033
|
+
preferredAuthKind: "api_key",
|
|
898
1034
|
// Not listed by `headroom wrap --help` — runs native.
|
|
899
1035
|
headroomWrappable: false,
|
|
900
1036
|
// Native ACP server: `gemini --skip-trust --acp`.
|
|
@@ -2058,6 +2194,16 @@ var INTEGRATION_REGISTRY = {
|
|
|
2058
2194
|
// tools ourselves via a BUILT-IN MCP (delivery.builtin) against that admin
|
|
2059
2195
|
// API — see apps/cli/src/integrations/convex-admin-mcp.ts. The user still
|
|
2060
2196
|
// pastes a deploy key (Dashboard → Project Settings → Deploy Keys).
|
|
2197
|
+
//
|
|
2198
|
+
// ⚠️ That built-in ALSO owns `deploy`, and it is the only way an agent can
|
|
2199
|
+
// push `convex/` changes. Deploying is bundle + push, not a REST call, so
|
|
2200
|
+
// that one tool drives Convex's own CLI with the deploy key injected into
|
|
2201
|
+
// THAT CHILD's env — the agent's shell never sees the credential. Before
|
|
2202
|
+
// it existed the agent had the credential's power through the MCP but no
|
|
2203
|
+
// way to deploy, so it looped on `npx convex dev` (interactive login) and
|
|
2204
|
+
// asked the user to paste the token into the chat; the user ended up
|
|
2205
|
+
// re-entering the SAME key by hand in Environment Variables, after burning
|
|
2206
|
+
// real credits (2026-09-15).
|
|
2061
2207
|
enabled: true,
|
|
2062
2208
|
auth: {
|
|
2063
2209
|
kind: "api_key",
|
|
@@ -2658,6 +2804,26 @@ var AGENT_STANDARD_TEXT = `# Working standard
|
|
|
2658
2804
|
|
|
2659
2805
|
You are an AI coding agent working on the user's project through CodeAgent Mobile. Follow this standard on every task.
|
|
2660
2806
|
|
|
2807
|
+
## How to answer \u2014 you are being read on a PHONE
|
|
2808
|
+
|
|
2809
|
+
Your reply is read on a narrow screen, often one-handed, often while the user is doing something else. Length is a cost they pay. Write accordingly.
|
|
2810
|
+
|
|
2811
|
+
- **Lead with the answer.** First line = the result, the decision, or what changed. No preamble, no restating the request, no "Great question!", no narrating what you are about to do.
|
|
2812
|
+
- **Default to a few sentences.** Most replies fit in 1-2 short paragraphs or 3-6 tight bullets. A long reply is a deliberate choice you make because the task genuinely needs it \u2014 not the default.
|
|
2813
|
+
- **Say it once.** No summary of the summary, no closing paragraph that repeats the opening, no "let me know if you need anything else".
|
|
2814
|
+
- **Cut every word that carries no information** \u2014 hedges, filler adverbs, throat-clearing, and praise for the question.
|
|
2815
|
+
- **Expand when asked.** "Explain in detail", "walk me through it", "why?" are requests for depth: give it fully. Brevity is the default, not a ceiling.
|
|
2816
|
+
|
|
2817
|
+
**Formatting for a narrow screen:**
|
|
2818
|
+
- Short paragraphs (1-3 sentences). Bullets over prose for anything that is a list. Never a wall of text.
|
|
2819
|
+
- **No wide tables** \u2014 they force horizontal scrolling and become unreadable. Use bullets, or at most two columns.
|
|
2820
|
+
- Code blocks only when the user needs the exact characters (a command to run, the changed lines). Show the relevant lines, not the whole file. Keep lines short so they don't wrap badly.
|
|
2821
|
+
- File references as \`path/to/file.ts:42\`, not pasted paths inside long prose.
|
|
2822
|
+
- Bold sparingly, for the one thing that matters in a block. Headings only when the reply genuinely has multiple sections.
|
|
2823
|
+
- No ASCII art, no banners, no decorative separators, no emoji unless the user uses them first.
|
|
2824
|
+
|
|
2825
|
+
**Compress evidence, don't drop it.** Report the outcome, not the transcript: "tests: 128/128 green", "build failed \u2014 \`TS2322\` in \`api/client.ts:80\`". Paste raw output only when the user needs to read it themselves, and only the relevant lines.
|
|
2826
|
+
|
|
2661
2827
|
## How to work
|
|
2662
2828
|
- **Understand before acting.** Restate the goal, read the relevant code, and be clear on what "done" looks like before changing anything.
|
|
2663
2829
|
- **Plan first for anything non-trivial** (3+ steps or a design decision): outline the approach and the files you'll touch, and share it before implementing. Skip the ceremony for small, obvious fixes.
|
|
@@ -3256,11 +3422,11 @@ function quiet(fn) {
|
|
|
3256
3422
|
log.debug(TAG, "ignored sync error", err);
|
|
3257
3423
|
}
|
|
3258
3424
|
}
|
|
3259
|
-
function rmIfExistsQuiet(
|
|
3425
|
+
function rmIfExistsQuiet(path97) {
|
|
3260
3426
|
try {
|
|
3261
|
-
fs2.rmSync(
|
|
3427
|
+
fs2.rmSync(path97, { force: true });
|
|
3262
3428
|
} catch (err) {
|
|
3263
|
-
log.debug(TAG, `rmIfExists failed for ${
|
|
3429
|
+
log.debug(TAG, `rmIfExists failed for ${path97}`, err);
|
|
3264
3430
|
}
|
|
3265
3431
|
}
|
|
3266
3432
|
function killQuiet(target, signal = "SIGTERM") {
|
|
@@ -3467,8 +3633,8 @@ function createGetModuleFromFilename(basePath = process.argv[1] ? (0, import_pat
|
|
|
3467
3633
|
return decodedFile;
|
|
3468
3634
|
};
|
|
3469
3635
|
}
|
|
3470
|
-
function normalizeWindowsPath(
|
|
3471
|
-
return
|
|
3636
|
+
function normalizeWindowsPath(path97) {
|
|
3637
|
+
return path97.replace(/^[A-Z]:/, "").replace(/\\/g, "/");
|
|
3472
3638
|
}
|
|
3473
3639
|
|
|
3474
3640
|
// ../../node_modules/@posthog/core/dist/error-tracking/index.mjs
|
|
@@ -6201,13 +6367,13 @@ var PostHogCoreStateless = class {
|
|
|
6201
6367
|
sentFromRoute += batchMessages.length;
|
|
6202
6368
|
}
|
|
6203
6369
|
}
|
|
6204
|
-
async _sendOtlpBatch({ path:
|
|
6370
|
+
async _sendOtlpBatch({ path: path97, payload }) {
|
|
6205
6371
|
if (this.disabled) return {
|
|
6206
6372
|
kind: "fatal",
|
|
6207
6373
|
error: new Error("The client is disabled")
|
|
6208
6374
|
};
|
|
6209
6375
|
const serialized = JSON.stringify(payload);
|
|
6210
|
-
const url2 = `${this.host}/i/v1/${
|
|
6376
|
+
const url2 = `${this.host}/i/v1/${path97}?token=${encodeURIComponent(this.apiKey)}`;
|
|
6211
6377
|
const gzippedPayload = this.disableCompression ? null : await this.compressPayload(serialized);
|
|
6212
6378
|
const fetchOptions = {
|
|
6213
6379
|
method: "POST",
|
|
@@ -7447,14 +7613,14 @@ async function addSourceContext(frames, openSourceFile = import_promises.open, l
|
|
|
7447
7613
|
LRU_FILE_CONTENTS_CACHE.reduce();
|
|
7448
7614
|
return frames;
|
|
7449
7615
|
}
|
|
7450
|
-
async function openRegularSourceFile(
|
|
7616
|
+
async function openRegularSourceFile(path97, openSourceFile, logger) {
|
|
7451
7617
|
let fileHandle;
|
|
7452
7618
|
let isValid = false;
|
|
7453
7619
|
try {
|
|
7454
|
-
fileHandle = await openSourceFile(
|
|
7620
|
+
fileHandle = await openSourceFile(path97, import_node_fs.constants.O_RDONLY | import_node_fs.constants.O_NONBLOCK);
|
|
7455
7621
|
const fileStat = await fileHandle.stat();
|
|
7456
7622
|
if (!fileStat.isFile()) return;
|
|
7457
|
-
if (fileStat.size > MAX_CONTEXTLINES_FILE_SIZE) return void logger?.debug(`Skipping source context for oversized file ${
|
|
7623
|
+
if (fileStat.size > MAX_CONTEXTLINES_FILE_SIZE) return void logger?.debug(`Skipping source context for oversized file ${path97}: ${fileStat.size} bytes exceeds ${MAX_CONTEXTLINES_FILE_SIZE}`);
|
|
7458
7624
|
isValid = true;
|
|
7459
7625
|
return fileHandle;
|
|
7460
7626
|
} catch {
|
|
@@ -7464,8 +7630,8 @@ async function openRegularSourceFile(path96, openSourceFile, logger) {
|
|
|
7464
7630
|
});
|
|
7465
7631
|
}
|
|
7466
7632
|
}
|
|
7467
|
-
async function getContextLinesFromFile(
|
|
7468
|
-
const fileHandle = await openRegularSourceFile(
|
|
7633
|
+
async function getContextLinesFromFile(path97, ranges, output, cacheKey, openSourceFile, logger) {
|
|
7634
|
+
const fileHandle = await openRegularSourceFile(path97, openSourceFile, logger);
|
|
7469
7635
|
if (void 0 === fileHandle) return void LRU_FILE_CONTENTS_FS_READ_FAILED.set(cacheKey, 1);
|
|
7470
7636
|
const openedFileHandle = fileHandle;
|
|
7471
7637
|
return new Promise((resolve11) => {
|
|
@@ -7567,22 +7733,22 @@ function clearLineContext(frame) {
|
|
|
7567
7733
|
delete frame.context_line;
|
|
7568
7734
|
delete frame.post_context;
|
|
7569
7735
|
}
|
|
7570
|
-
function shouldSkipContextLinesForFile(
|
|
7571
|
-
return
|
|
7736
|
+
function shouldSkipContextLinesForFile(path97) {
|
|
7737
|
+
return path97.startsWith("node:") || path97.endsWith(".min.js") || path97.endsWith(".min.cjs") || path97.endsWith(".min.mjs") || path97.startsWith("data:");
|
|
7572
7738
|
}
|
|
7573
7739
|
function shouldSkipContextLinesForFrame(frame) {
|
|
7574
7740
|
if (void 0 !== frame.lineno && frame.lineno > MAX_CONTEXTLINES_LINENO) return true;
|
|
7575
7741
|
if (void 0 !== frame.colno && frame.colno > MAX_CONTEXTLINES_COLNO) return true;
|
|
7576
7742
|
return false;
|
|
7577
7743
|
}
|
|
7578
|
-
function makeSourceCacheKey(
|
|
7579
|
-
if ((0, import_node_path.isAbsolute)(
|
|
7744
|
+
function makeSourceCacheKey(path97, basePath) {
|
|
7745
|
+
if ((0, import_node_path.isAbsolute)(path97)) return JSON.stringify([
|
|
7580
7746
|
null,
|
|
7581
|
-
|
|
7747
|
+
path97
|
|
7582
7748
|
]);
|
|
7583
7749
|
return void 0 === basePath ? void 0 : JSON.stringify([
|
|
7584
7750
|
basePath,
|
|
7585
|
-
|
|
7751
|
+
path97
|
|
7586
7752
|
]);
|
|
7587
7753
|
}
|
|
7588
7754
|
function rangeExistsInContentCache(cacheKey, range) {
|
|
@@ -10243,7 +10409,7 @@ function readAnonId() {
|
|
|
10243
10409
|
}
|
|
10244
10410
|
function superProperties() {
|
|
10245
10411
|
return {
|
|
10246
|
-
cliVersion: true ? "2.75.
|
|
10412
|
+
cliVersion: true ? "2.75.4" : "0.0.0-dev",
|
|
10247
10413
|
nodeVersion: process.version,
|
|
10248
10414
|
platform: process.platform,
|
|
10249
10415
|
arch: process.arch,
|
|
@@ -10485,7 +10651,7 @@ var http = __toESM(require("http"));
|
|
|
10485
10651
|
// package.json
|
|
10486
10652
|
var package_default = {
|
|
10487
10653
|
name: "codeam-cli",
|
|
10488
|
-
version: "2.75.
|
|
10654
|
+
version: "2.75.4",
|
|
10489
10655
|
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.",
|
|
10490
10656
|
type: "commonjs",
|
|
10491
10657
|
main: "dist/index.js",
|
|
@@ -12176,7 +12342,7 @@ var CommandRelayService = class _CommandRelayService {
|
|
|
12176
12342
|
// fresh + clear the "CLI update available" banner after a self-update
|
|
12177
12343
|
// (a codespace that reinstalls @latest reconnects via heartbeat, not
|
|
12178
12344
|
// pair/reconnect). Older backends ignore the extra field.
|
|
12179
|
-
..."2.75.
|
|
12345
|
+
..."2.75.4" ? { ideVersion: "2.75.4" } : {}
|
|
12180
12346
|
}).then(() => log.trace("relay", `heartbeat ok online=${online}`)).catch((err) => log.trace("relay", `heartbeat failed online=${online}`, err));
|
|
12181
12347
|
}
|
|
12182
12348
|
/**
|
|
@@ -19812,8 +19978,8 @@ function pickLine(obj) {
|
|
|
19812
19978
|
function toHunk(raw, groupSeverity) {
|
|
19813
19979
|
if (!raw || typeof raw !== "object") return null;
|
|
19814
19980
|
const o = raw;
|
|
19815
|
-
const
|
|
19816
|
-
if (!
|
|
19981
|
+
const path97 = asString(pick(o, ["file_path", "filePath", "file", "path", "filename", "fileName"])) ?? asString(pick(o, ["location"])?.path);
|
|
19982
|
+
if (!path97) return null;
|
|
19817
19983
|
const message = asString(
|
|
19818
19984
|
pick(o, [
|
|
19819
19985
|
"comment",
|
|
@@ -19830,7 +19996,7 @@ function toHunk(raw, groupSeverity) {
|
|
|
19830
19996
|
const severity = normSeverity(pick(o, ["severity", "level", "priority", "impact"])) ?? normSeverity(groupSeverity);
|
|
19831
19997
|
const locObj = pick(o, ["location"]) ?? o;
|
|
19832
19998
|
return {
|
|
19833
|
-
path:
|
|
19999
|
+
path: path97.trim(),
|
|
19834
20000
|
line: pickLine(o) ?? pickLine(locObj),
|
|
19835
20001
|
severity,
|
|
19836
20002
|
message: (title && message ? `${title}: ${message}` : title || message).trim() || "(no message)"
|
|
@@ -19913,10 +20079,10 @@ function parsePlain(stdout) {
|
|
|
19913
20079
|
for (const line of stdout.split(/\r?\n/)) {
|
|
19914
20080
|
const m = line.match(HUNK_LINE_RE);
|
|
19915
20081
|
if (!m) continue;
|
|
19916
|
-
const [,
|
|
19917
|
-
if (!
|
|
20082
|
+
const [, path97, lineNo, sevToken, message] = m;
|
|
20083
|
+
if (!path97 || !lineNo || !message) continue;
|
|
19918
20084
|
hunks.push({
|
|
19919
|
-
path:
|
|
20085
|
+
path: path97.trim(),
|
|
19920
20086
|
line: Number(lineNo),
|
|
19921
20087
|
severity: sevToken ? SEVERITY_MAP[sevToken.toLowerCase()] : void 0,
|
|
19922
20088
|
message: message.trim().replace(/^[*-]\s+/, "")
|
|
@@ -20634,14 +20800,14 @@ function defaultSdkDir() {
|
|
|
20634
20800
|
return resolveSdkDirViaRequire();
|
|
20635
20801
|
}
|
|
20636
20802
|
function resolveClaudeNativeBinary(deps = {}) {
|
|
20637
|
-
const
|
|
20803
|
+
const existsSync30 = deps.existsSync ?? import_fs.default.existsSync;
|
|
20638
20804
|
const platformKey = deps.platformKey ?? currentPlatformKey();
|
|
20639
20805
|
const sdkDir = deps.sdkDir !== void 0 ? deps.sdkDir : defaultSdkDir();
|
|
20640
20806
|
if (!sdkDir) return null;
|
|
20641
20807
|
const scopeDir = import_path4.default.dirname(sdkDir);
|
|
20642
20808
|
const binName = platformKey.startsWith("win32-") ? "claude.exe" : "claude";
|
|
20643
20809
|
const candidate = import_path4.default.join(scopeDir, `claude-agent-sdk-${platformKey}`, binName);
|
|
20644
|
-
return
|
|
20810
|
+
return existsSync30(candidate) ? candidate : null;
|
|
20645
20811
|
}
|
|
20646
20812
|
var realSleep = (ms) => new Promise((resolve11) => setTimeout(resolve11, ms));
|
|
20647
20813
|
async function waitForClaudeNativeBinary(opts = {}) {
|
|
@@ -20723,18 +20889,18 @@ function augmentUserLocalBinPaths(deps = {}) {
|
|
|
20723
20889
|
env.PATH = [...additions, ...parts].join(p2.delimiter);
|
|
20724
20890
|
}
|
|
20725
20891
|
function resolveCursorAgentBinary(deps = {}) {
|
|
20726
|
-
const
|
|
20892
|
+
const existsSync30 = deps.existsSync ?? import_fs.default.existsSync;
|
|
20727
20893
|
const platform3 = deps.platform ?? process.platform;
|
|
20728
20894
|
const env = deps.env ?? process.env;
|
|
20729
20895
|
if (platform3 === "win32") {
|
|
20730
20896
|
const localAppData = env.LOCALAPPDATA;
|
|
20731
20897
|
if (!localAppData) return null;
|
|
20732
20898
|
const exe = import_path4.default.win32.join(localAppData, "cursor-agent", "cursor-agent.exe");
|
|
20733
|
-
return
|
|
20899
|
+
return existsSync30(exe) ? exe : null;
|
|
20734
20900
|
}
|
|
20735
20901
|
const home = deps.homedir ?? import_os4.default.homedir();
|
|
20736
20902
|
const unix = import_path4.default.posix.join(home, ".local", "bin", "cursor-agent");
|
|
20737
|
-
return
|
|
20903
|
+
return existsSync30(unix) ? unix : null;
|
|
20738
20904
|
}
|
|
20739
20905
|
async function waitForCursorAgent(opts = {}) {
|
|
20740
20906
|
const timeoutMs = opts.timeoutMs ?? 18e4;
|
|
@@ -24510,7 +24676,7 @@ async function autoUpgradeBeforeCriticalCommand() {
|
|
|
24510
24676
|
if (process.env.NODE_ENV === "test") return;
|
|
24511
24677
|
if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
|
|
24512
24678
|
if (process.env.CI) return;
|
|
24513
|
-
const current2 = true ? "2.75.
|
|
24679
|
+
const current2 = true ? "2.75.4" : null;
|
|
24514
24680
|
if (!current2) return;
|
|
24515
24681
|
const cache = readCache();
|
|
24516
24682
|
const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
|
|
@@ -24527,7 +24693,7 @@ function checkForUpdates() {
|
|
|
24527
24693
|
if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
|
|
24528
24694
|
if (process.env.CI) return;
|
|
24529
24695
|
if (!process.stdout.isTTY) return;
|
|
24530
|
-
const current2 = true ? "2.75.
|
|
24696
|
+
const current2 = true ? "2.75.4" : null;
|
|
24531
24697
|
if (!current2) return;
|
|
24532
24698
|
const cache = readCache();
|
|
24533
24699
|
const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
|
|
@@ -24550,7 +24716,7 @@ var SELF_UPDATE_INSTALL_TIMEOUT_MS = 18e4;
|
|
|
24550
24716
|
var SELF_UPDATE_LS_TIMEOUT_MS = 15e3;
|
|
24551
24717
|
var SUDO_PREFLIGHT_TIMEOUT_MS = 5e3;
|
|
24552
24718
|
function currentCliVersion() {
|
|
24553
|
-
return true ? "2.75.
|
|
24719
|
+
return true ? "2.75.4" : null;
|
|
24554
24720
|
}
|
|
24555
24721
|
async function installedVersion(deps) {
|
|
24556
24722
|
const ls = await deps.run(
|
|
@@ -26527,7 +26693,7 @@ async function defaultFetchJson(url2) {
|
|
|
26527
26693
|
async function readUsageReport(deps = {}) {
|
|
26528
26694
|
const port = deps.port ?? HEADROOM_PROXY_PORT;
|
|
26529
26695
|
const base = `http://127.0.0.1:${port}`;
|
|
26530
|
-
const get4 = deps.fetchJson ?? ((
|
|
26696
|
+
const get4 = deps.fetchJson ?? ((path97) => defaultFetchJson(`${base}${path97}`));
|
|
26531
26697
|
let history;
|
|
26532
26698
|
try {
|
|
26533
26699
|
history = await get4("/stats-history");
|
|
@@ -32301,11 +32467,11 @@ function resolveTokenValue(args2) {
|
|
|
32301
32467
|
}
|
|
32302
32468
|
const fileFlag = args2.find((a) => a.startsWith("--token-file="));
|
|
32303
32469
|
if (fileFlag) {
|
|
32304
|
-
const
|
|
32470
|
+
const path97 = fileFlag.slice("--token-file=".length);
|
|
32305
32471
|
try {
|
|
32306
|
-
const content = fs66.readFileSync(
|
|
32307
|
-
if (content.length === 0) fail(`--token-file ${
|
|
32308
|
-
rmIfExistsQuiet(
|
|
32472
|
+
const content = fs66.readFileSync(path97, "utf8").trim();
|
|
32473
|
+
if (content.length === 0) fail(`--token-file ${path97} is empty`);
|
|
32474
|
+
rmIfExistsQuiet(path97);
|
|
32309
32475
|
return content;
|
|
32310
32476
|
} catch (err) {
|
|
32311
32477
|
fail(`Could not read --token-file: ${err.message}`);
|
|
@@ -39238,12 +39404,12 @@ function buildRelaunchProxyEnv(baseEnv) {
|
|
|
39238
39404
|
return env;
|
|
39239
39405
|
}
|
|
39240
39406
|
var relaunchProxyWithoutBudget = async () => {
|
|
39241
|
-
const { spawn:
|
|
39407
|
+
const { spawn: spawn49 } = await import("child_process");
|
|
39242
39408
|
killHeadroomProxy();
|
|
39243
39409
|
await new Promise((r) => setTimeout(r, 500));
|
|
39244
39410
|
const proxyEnv = buildRelaunchProxyEnv(process.env);
|
|
39245
39411
|
try {
|
|
39246
|
-
const proxy =
|
|
39412
|
+
const proxy = spawn49(
|
|
39247
39413
|
"headroom",
|
|
39248
39414
|
["proxy", "--port", "8787"],
|
|
39249
39415
|
{ stdio: "ignore", detached: true, env: proxyEnv }
|
|
@@ -40775,7 +40941,7 @@ function defaultRunGit(cwd, args2) {
|
|
|
40775
40941
|
});
|
|
40776
40942
|
}
|
|
40777
40943
|
async function discoverRepos(workingDir, maxDepth = 4) {
|
|
40778
|
-
const
|
|
40944
|
+
const fs84 = await import("fs/promises");
|
|
40779
40945
|
const out2 = [];
|
|
40780
40946
|
await walk(workingDir, 0);
|
|
40781
40947
|
return out2;
|
|
@@ -40783,7 +40949,7 @@ async function discoverRepos(workingDir, maxDepth = 4) {
|
|
|
40783
40949
|
if (depth > maxDepth) return;
|
|
40784
40950
|
let entries = [];
|
|
40785
40951
|
try {
|
|
40786
|
-
const dirents = await
|
|
40952
|
+
const dirents = await fs84.readdir(dir, { withFileTypes: true });
|
|
40787
40953
|
entries = dirents.filter((d3) => !d3.name.startsWith(".") || d3.name === ".git").map((d3) => ({ name: d3.name, isDirectory: d3.isDirectory() }));
|
|
40788
40954
|
} catch {
|
|
40789
40955
|
return;
|
|
@@ -49989,7 +50155,7 @@ function checkChokidar() {
|
|
|
49989
50155
|
}
|
|
49990
50156
|
async function doctor(args2 = []) {
|
|
49991
50157
|
const json = args2.includes("--json");
|
|
49992
|
-
const cliVersion = true ? "2.75.
|
|
50158
|
+
const cliVersion = true ? "2.75.4" : "0.0.0-dev";
|
|
49993
50159
|
const apiBase2 = resolveApiBaseUrl();
|
|
49994
50160
|
const diagnosticId = (0, import_node_crypto13.randomUUID)();
|
|
49995
50161
|
log.info("doctor", `run id=${diagnosticId} cli=${cliVersion}`);
|
|
@@ -50186,7 +50352,7 @@ async function completion(args2) {
|
|
|
50186
50352
|
}
|
|
50187
50353
|
|
|
50188
50354
|
// src/integrations/mcp-run.ts
|
|
50189
|
-
var
|
|
50355
|
+
var import_node_child_process35 = require("child_process");
|
|
50190
50356
|
|
|
50191
50357
|
// src/integrations/launcher-env.ts
|
|
50192
50358
|
var LAUNCHER_ENV = Object.freeze({
|
|
@@ -50270,7 +50436,7 @@ function resolveDelivery(id) {
|
|
|
50270
50436
|
function commandExists(command2) {
|
|
50271
50437
|
try {
|
|
50272
50438
|
const probe = process.platform === "win32" ? "where" : "which";
|
|
50273
|
-
(0,
|
|
50439
|
+
(0, import_node_child_process35.execFileSync)(probe, [command2], { stdio: "ignore" });
|
|
50274
50440
|
return true;
|
|
50275
50441
|
} catch {
|
|
50276
50442
|
return false;
|
|
@@ -50303,7 +50469,7 @@ function ensureCommand(command2) {
|
|
|
50303
50469
|
}
|
|
50304
50470
|
if (command2 === "uvx") {
|
|
50305
50471
|
try {
|
|
50306
|
-
(0,
|
|
50472
|
+
(0, import_node_child_process35.execSync)("curl -LsSf https://astral.sh/uv/install.sh | sh", {
|
|
50307
50473
|
stdio: ["ignore", process.stderr, process.stderr],
|
|
50308
50474
|
timeout: 18e4,
|
|
50309
50475
|
env: { ...process.env, UV_NO_MODIFY_PATH: "1" }
|
|
@@ -50312,7 +50478,7 @@ function ensureCommand(command2) {
|
|
|
50312
50478
|
}
|
|
50313
50479
|
if (resolveLauncherPath(command2) !== command2) return;
|
|
50314
50480
|
try {
|
|
50315
|
-
(0,
|
|
50481
|
+
(0, import_node_child_process35.execSync)("python3 -m pip install --user --quiet uv", {
|
|
50316
50482
|
stdio: ["ignore", process.stderr, process.stderr],
|
|
50317
50483
|
timeout: 18e4
|
|
50318
50484
|
});
|
|
@@ -50390,7 +50556,7 @@ async function mcpRun(args2) {
|
|
|
50390
50556
|
}
|
|
50391
50557
|
|
|
50392
50558
|
// src/integrations/mcp-warm.ts
|
|
50393
|
-
var
|
|
50559
|
+
var import_node_child_process36 = require("child_process");
|
|
50394
50560
|
function specOf(delivery) {
|
|
50395
50561
|
if (!delivery.command) return null;
|
|
50396
50562
|
const spec = (delivery.args ?? []).find((a) => !a.startsWith("-"));
|
|
@@ -50434,7 +50600,7 @@ var WARM_TOTAL_BUDGET_MS = 10 * 6e4;
|
|
|
50434
50600
|
var WARM_CONCURRENCY = 4;
|
|
50435
50601
|
function runCapturing(command2, args2, timeoutMs) {
|
|
50436
50602
|
return new Promise((resolve11) => {
|
|
50437
|
-
const child = (0,
|
|
50603
|
+
const child = (0, import_node_child_process36.spawn)(command2, args2, {
|
|
50438
50604
|
env: { ...process.env, ...LAUNCHER_ENV },
|
|
50439
50605
|
stdio: ["ignore", "ignore", "pipe"],
|
|
50440
50606
|
// `npx`/`uv` are `.cmd` shims on Windows; Node ≥ 20.12 refuses to spawn a
|
|
@@ -50513,7 +50679,7 @@ async function mcpWarm(argv = [], opts = {}) {
|
|
|
50513
50679
|
// src/commands/version.ts
|
|
50514
50680
|
var import_picocolors15 = __toESM(require("picocolors"));
|
|
50515
50681
|
function version2() {
|
|
50516
|
-
const v = true ? "2.75.
|
|
50682
|
+
const v = true ? "2.75.4" : "unknown";
|
|
50517
50683
|
console.log(`${import_picocolors15.default.bold("codeam-cli")} ${import_picocolors15.default.cyan(v)}`);
|
|
50518
50684
|
}
|
|
50519
50685
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "codeam-cli",
|
|
3
|
-
"version": "2.75.
|
|
3
|
+
"version": "2.75.4",
|
|
4
4
|
"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 — async. The terminal companion for CodeAgent Mobile.",
|
|
5
5
|
"type": "commonjs",
|
|
6
6
|
"main": "dist/index.js",
|