codeam-cli 2.4.31 → 2.4.33
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +6 -0
- package/dist/index.js +119 -73
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,12 @@ 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.4.31] — 2026-05-05
|
|
8
|
+
|
|
9
|
+
### Fixed
|
|
10
|
+
|
|
11
|
+
- **cli:** Vendor node-pty into dist/ — guarantees ConPTY binary on Windows (v2.4.31)
|
|
12
|
+
|
|
7
13
|
## [2.4.30] — 2026-05-05
|
|
8
14
|
|
|
9
15
|
### Fixed
|
package/dist/index.js
CHANGED
|
@@ -521,7 +521,7 @@ var require_windowsPtyAgent = __commonJS({
|
|
|
521
521
|
exports2.argsToCommandLine = exports2.WindowsPtyAgent = void 0;
|
|
522
522
|
var fs9 = require("fs");
|
|
523
523
|
var os8 = require("os");
|
|
524
|
-
var
|
|
524
|
+
var path16 = require("path");
|
|
525
525
|
var child_process_1 = require("child_process");
|
|
526
526
|
var net_1 = require("net");
|
|
527
527
|
var windowsConoutConnection_1 = require_windowsConoutConnection();
|
|
@@ -557,7 +557,7 @@ var require_windowsPtyAgent = __commonJS({
|
|
|
557
557
|
}
|
|
558
558
|
}
|
|
559
559
|
this._ptyNative = this._useConpty ? conptyNative : winptyNative;
|
|
560
|
-
cwd =
|
|
560
|
+
cwd = path16.resolve(cwd);
|
|
561
561
|
var commandLine = argsToCommandLine(file, args2);
|
|
562
562
|
var term;
|
|
563
563
|
if (this._useConpty) {
|
|
@@ -679,7 +679,7 @@ var require_windowsPtyAgent = __commonJS({
|
|
|
679
679
|
WindowsPtyAgent2.prototype._getConsoleProcessList = function() {
|
|
680
680
|
var _this = this;
|
|
681
681
|
return new Promise(function(resolve2) {
|
|
682
|
-
var agent = child_process_1.fork(
|
|
682
|
+
var agent = child_process_1.fork(path16.join(__dirname, "conpty_console_list_agent"), [_this._innerPid.toString()]);
|
|
683
683
|
agent.on("message", function(message) {
|
|
684
684
|
clearTimeout(timeout);
|
|
685
685
|
resolve2(message.consoleProcessList);
|
|
@@ -1013,14 +1013,14 @@ var require_unixTerminal = __commonJS({
|
|
|
1013
1013
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
1014
1014
|
exports2.UnixTerminal = void 0;
|
|
1015
1015
|
var fs9 = require("fs");
|
|
1016
|
-
var
|
|
1016
|
+
var path16 = require("path");
|
|
1017
1017
|
var tty = require("tty");
|
|
1018
1018
|
var terminal_1 = require_terminal();
|
|
1019
1019
|
var utils_1 = require_utils();
|
|
1020
1020
|
var native = utils_1.loadNativeModule("pty");
|
|
1021
1021
|
var pty = native.module;
|
|
1022
1022
|
var helperPath = native.dir + "/spawn-helper";
|
|
1023
|
-
helperPath =
|
|
1023
|
+
helperPath = path16.resolve(__dirname, helperPath);
|
|
1024
1024
|
helperPath = helperPath.replace("app.asar", "app.asar.unpacked");
|
|
1025
1025
|
helperPath = helperPath.replace("node_modules.asar", "node_modules.asar.unpacked");
|
|
1026
1026
|
var DEFAULT_FILE = "sh";
|
|
@@ -1392,7 +1392,7 @@ var require_src = __commonJS({
|
|
|
1392
1392
|
// src/commands/start.ts
|
|
1393
1393
|
var fs7 = __toESM(require("fs"));
|
|
1394
1394
|
var os6 = __toESM(require("os"));
|
|
1395
|
-
var
|
|
1395
|
+
var path10 = __toESM(require("path"));
|
|
1396
1396
|
var import_crypto = require("crypto");
|
|
1397
1397
|
var import_child_process5 = require("child_process");
|
|
1398
1398
|
var import_picocolors2 = __toESM(require("picocolors"));
|
|
@@ -1482,7 +1482,7 @@ var import_qrcode_terminal = __toESM(require("qrcode-terminal"));
|
|
|
1482
1482
|
// package.json
|
|
1483
1483
|
var package_default = {
|
|
1484
1484
|
name: "codeam-cli",
|
|
1485
|
-
version: "2.4.
|
|
1485
|
+
version: "2.4.33",
|
|
1486
1486
|
description: "Remote control Claude Code (and other AI coding agents) from your mobile phone. Pair your device, send prompts, stream responses in real-time, and approve commands \u2014 from anywhere.",
|
|
1487
1487
|
main: "dist/index.js",
|
|
1488
1488
|
bin: {
|
|
@@ -1963,27 +1963,35 @@ var CommandRelayService = class {
|
|
|
1963
1963
|
}
|
|
1964
1964
|
};
|
|
1965
1965
|
|
|
1966
|
+
// src/services/pty/unix.strategy.ts
|
|
1967
|
+
var import_child_process = require("child_process");
|
|
1968
|
+
var fs3 = __toESM(require("fs"));
|
|
1969
|
+
var os3 = __toESM(require("os"));
|
|
1970
|
+
var path3 = __toESM(require("path"));
|
|
1971
|
+
|
|
1966
1972
|
// src/services/pty/types.ts
|
|
1967
1973
|
var fs2 = __toESM(require("fs"));
|
|
1968
1974
|
var path2 = __toESM(require("path"));
|
|
1969
1975
|
function findInPath(name) {
|
|
1970
|
-
const
|
|
1976
|
+
const isWin = process.platform === "win32";
|
|
1977
|
+
const dirs = (process.env.PATH ?? "").split(path2.delimiter).filter(Boolean);
|
|
1978
|
+
const hasExt = path2.extname(name).length > 0;
|
|
1979
|
+
const candidates = isWin && !hasExt ? [`${name}.exe`, `${name}.cmd`, `${name}.bat`, `${name}.ps1`, name] : [name];
|
|
1980
|
+
const accessFlag = isWin ? fs2.constants.F_OK : fs2.constants.X_OK;
|
|
1971
1981
|
for (const dir of dirs) {
|
|
1972
|
-
const
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
1982
|
+
for (const candidate of candidates) {
|
|
1983
|
+
const full = path2.join(dir, candidate);
|
|
1984
|
+
try {
|
|
1985
|
+
fs2.accessSync(full, accessFlag);
|
|
1986
|
+
return full;
|
|
1987
|
+
} catch {
|
|
1988
|
+
}
|
|
1977
1989
|
}
|
|
1978
1990
|
}
|
|
1979
1991
|
return null;
|
|
1980
1992
|
}
|
|
1981
1993
|
|
|
1982
1994
|
// src/services/pty/unix.strategy.ts
|
|
1983
|
-
var import_child_process = require("child_process");
|
|
1984
|
-
var fs3 = __toESM(require("fs"));
|
|
1985
|
-
var os3 = __toESM(require("os"));
|
|
1986
|
-
var path3 = __toESM(require("path"));
|
|
1987
1995
|
var PYTHON_PTY_HELPER = `import os,pty,sys,select,signal,struct,fcntl,termios,errno
|
|
1988
1996
|
m,s=pty.openpty()
|
|
1989
1997
|
try:
|
|
@@ -2285,6 +2293,7 @@ var WindowsConPtyStrategy = class _WindowsConPtyStrategy {
|
|
|
2285
2293
|
dataSub = null;
|
|
2286
2294
|
exitSub = null;
|
|
2287
2295
|
rawModeSet = false;
|
|
2296
|
+
resizeHandler = null;
|
|
2288
2297
|
/**
|
|
2289
2298
|
* Factory that returns a working ConPTY strategy or `null` if
|
|
2290
2299
|
* node-pty can't load. The caller (claude.service.ts) decides
|
|
@@ -2296,10 +2305,12 @@ var WindowsConPtyStrategy = class _WindowsConPtyStrategy {
|
|
|
2296
2305
|
return new _WindowsConPtyStrategy(opts, lib);
|
|
2297
2306
|
}
|
|
2298
2307
|
spawn(cmd, cwd, args2 = []) {
|
|
2308
|
+
const cols = process.stdout.columns && process.stdout.columns > 0 ? process.stdout.columns : 120;
|
|
2309
|
+
const rows = process.stdout.rows && process.stdout.rows > 0 ? process.stdout.rows : 30;
|
|
2299
2310
|
this.pty = this.lib.spawn(cmd, args2, {
|
|
2300
2311
|
name: "xterm-256color",
|
|
2301
|
-
cols
|
|
2302
|
-
rows
|
|
2312
|
+
cols,
|
|
2313
|
+
rows,
|
|
2303
2314
|
cwd,
|
|
2304
2315
|
env: {
|
|
2305
2316
|
...process.env,
|
|
@@ -2326,6 +2337,15 @@ var WindowsConPtyStrategy = class _WindowsConPtyStrategy {
|
|
|
2326
2337
|
}
|
|
2327
2338
|
process.stdin.resume();
|
|
2328
2339
|
process.stdin.on("data", this.stdinHandler);
|
|
2340
|
+
this.resizeHandler = () => {
|
|
2341
|
+
const c2 = process.stdout.columns && process.stdout.columns > 0 ? process.stdout.columns : cols;
|
|
2342
|
+
const r = process.stdout.rows && process.stdout.rows > 0 ? process.stdout.rows : rows;
|
|
2343
|
+
try {
|
|
2344
|
+
this.pty?.resize(c2, r);
|
|
2345
|
+
} catch {
|
|
2346
|
+
}
|
|
2347
|
+
};
|
|
2348
|
+
process.stdout.on("resize", this.resizeHandler);
|
|
2329
2349
|
}
|
|
2330
2350
|
write(data) {
|
|
2331
2351
|
if (!this.pty) return;
|
|
@@ -2344,6 +2364,10 @@ var WindowsConPtyStrategy = class _WindowsConPtyStrategy {
|
|
|
2344
2364
|
this.dataSub = null;
|
|
2345
2365
|
this.exitSub = null;
|
|
2346
2366
|
process.stdin.removeListener("data", this.stdinHandler);
|
|
2367
|
+
if (this.resizeHandler) {
|
|
2368
|
+
process.stdout.removeListener("resize", this.resizeHandler);
|
|
2369
|
+
this.resizeHandler = null;
|
|
2370
|
+
}
|
|
2347
2371
|
if (this.rawModeSet && process.stdin.isTTY) {
|
|
2348
2372
|
try {
|
|
2349
2373
|
process.stdin.setRawMode(false);
|
|
@@ -4351,6 +4375,26 @@ async function ensureClaudeInstalled() {
|
|
|
4351
4375
|
return true;
|
|
4352
4376
|
}
|
|
4353
4377
|
|
|
4378
|
+
// src/services/claude-resolver.ts
|
|
4379
|
+
var path6 = __toESM(require("path"));
|
|
4380
|
+
function buildClaudeLaunch(extraArgs = []) {
|
|
4381
|
+
const found = findInPath("claude") ?? findInPath("claude-code");
|
|
4382
|
+
if (!found) return null;
|
|
4383
|
+
if (process.platform === "win32") {
|
|
4384
|
+
const ext = path6.extname(found).toLowerCase();
|
|
4385
|
+
if (ext === ".cmd" || ext === ".bat") {
|
|
4386
|
+
return { cmd: "cmd.exe", args: ["/c", found, ...extraArgs] };
|
|
4387
|
+
}
|
|
4388
|
+
if (ext === ".ps1") {
|
|
4389
|
+
return {
|
|
4390
|
+
cmd: "powershell.exe",
|
|
4391
|
+
args: ["-NoProfile", "-ExecutionPolicy", "Bypass", "-File", found, ...extraArgs]
|
|
4392
|
+
};
|
|
4393
|
+
}
|
|
4394
|
+
}
|
|
4395
|
+
return { cmd: found, args: extraArgs };
|
|
4396
|
+
}
|
|
4397
|
+
|
|
4354
4398
|
// src/services/claude.service.ts
|
|
4355
4399
|
var ClaudeService = class {
|
|
4356
4400
|
constructor(opts) {
|
|
@@ -4368,9 +4412,11 @@ var ClaudeService = class {
|
|
|
4368
4412
|
strategy = null;
|
|
4369
4413
|
strategyOpts;
|
|
4370
4414
|
async spawn() {
|
|
4371
|
-
|
|
4415
|
+
let launch = buildClaudeLaunch();
|
|
4416
|
+
if (!launch) {
|
|
4372
4417
|
const installed = await ensureClaudeInstalled();
|
|
4373
|
-
if (
|
|
4418
|
+
if (installed) launch = buildClaudeLaunch();
|
|
4419
|
+
if (!launch) {
|
|
4374
4420
|
const cmd = process.platform === "win32" ? "irm https://claude.ai/install.ps1 | iex" : "curl -fsSL https://claude.ai/install.sh | bash";
|
|
4375
4421
|
console.error(
|
|
4376
4422
|
`
|
|
@@ -4382,12 +4428,11 @@ var ClaudeService = class {
|
|
|
4382
4428
|
process.exit(1);
|
|
4383
4429
|
}
|
|
4384
4430
|
}
|
|
4385
|
-
const claudeCmd = findInPath("claude") ? "claude" : "claude-code";
|
|
4386
4431
|
if (process.platform === "win32") {
|
|
4387
4432
|
const conpty = WindowsConPtyStrategy.tryCreate(this.strategyOpts);
|
|
4388
4433
|
if (conpty) {
|
|
4389
4434
|
try {
|
|
4390
|
-
conpty.spawn(
|
|
4435
|
+
conpty.spawn(launch.cmd, this.opts.cwd, launch.args);
|
|
4391
4436
|
this.strategy = conpty;
|
|
4392
4437
|
return;
|
|
4393
4438
|
} catch (err) {
|
|
@@ -4406,12 +4451,12 @@ var ClaudeService = class {
|
|
|
4406
4451
|
);
|
|
4407
4452
|
}
|
|
4408
4453
|
const pipe = new WindowsPtyStrategy(this.strategyOpts);
|
|
4409
|
-
pipe.spawn(
|
|
4454
|
+
pipe.spawn(launch.cmd, this.opts.cwd, launch.args);
|
|
4410
4455
|
this.strategy = pipe;
|
|
4411
4456
|
return;
|
|
4412
4457
|
}
|
|
4413
4458
|
const unix = new UnixPtyStrategy(this.strategyOpts);
|
|
4414
|
-
unix.spawn(
|
|
4459
|
+
unix.spawn(launch.cmd, this.opts.cwd, launch.args);
|
|
4415
4460
|
this.strategy = unix;
|
|
4416
4461
|
}
|
|
4417
4462
|
/**
|
|
@@ -4489,11 +4534,12 @@ var ClaudeService = class {
|
|
|
4489
4534
|
*/
|
|
4490
4535
|
restart(sessionId, auto = false) {
|
|
4491
4536
|
if (!this.strategy) return;
|
|
4492
|
-
const
|
|
4537
|
+
const extraArgs = ["--resume", sessionId];
|
|
4538
|
+
if (auto) extraArgs.push("--dangerously-skip-permissions");
|
|
4539
|
+
const launch = buildClaudeLaunch(extraArgs);
|
|
4540
|
+
if (!launch) return;
|
|
4493
4541
|
this.strategy.kill();
|
|
4494
|
-
|
|
4495
|
-
if (auto) args2.push("--dangerously-skip-permissions");
|
|
4496
|
-
this.strategy.spawn(claudeCmd, this.opts.cwd, args2);
|
|
4542
|
+
this.strategy.spawn(launch.cmd, this.opts.cwd, launch.args);
|
|
4497
4543
|
}
|
|
4498
4544
|
};
|
|
4499
4545
|
|
|
@@ -5175,7 +5221,7 @@ function _sendOutputChunk(url, headers, payload) {
|
|
|
5175
5221
|
|
|
5176
5222
|
// src/services/history.service.ts
|
|
5177
5223
|
var fs4 = __toESM(require("fs"));
|
|
5178
|
-
var
|
|
5224
|
+
var path7 = __toESM(require("path"));
|
|
5179
5225
|
var os5 = __toESM(require("os"));
|
|
5180
5226
|
var https3 = __toESM(require("https"));
|
|
5181
5227
|
var http3 = __toESM(require("http"));
|
|
@@ -5331,7 +5377,7 @@ var HistoryService = class {
|
|
|
5331
5377
|
return this._quotaPercent === null || Date.now() - this._quotaFetchedAt > ttlMs;
|
|
5332
5378
|
}
|
|
5333
5379
|
get projectDir() {
|
|
5334
|
-
return
|
|
5380
|
+
return path7.join(os5.homedir(), ".claude", "projects", encodeCwd(this.cwd));
|
|
5335
5381
|
}
|
|
5336
5382
|
/** Set the current Claude conversation ID (extracted from /cost command or session start) */
|
|
5337
5383
|
setCurrentConversationId(id) {
|
|
@@ -5343,7 +5389,7 @@ var HistoryService = class {
|
|
|
5343
5389
|
/** Return the current message count in the active conversation. */
|
|
5344
5390
|
getCurrentMessageCount() {
|
|
5345
5391
|
if (!this.currentConversationId) return 0;
|
|
5346
|
-
const filePath =
|
|
5392
|
+
const filePath = path7.join(this.projectDir, `${this.currentConversationId}.jsonl`);
|
|
5347
5393
|
return parseJsonl(filePath).length;
|
|
5348
5394
|
}
|
|
5349
5395
|
/**
|
|
@@ -5354,7 +5400,7 @@ var HistoryService = class {
|
|
|
5354
5400
|
const deadline = Date.now() + timeoutMs;
|
|
5355
5401
|
while (Date.now() < deadline) {
|
|
5356
5402
|
if (!this.currentConversationId) return null;
|
|
5357
|
-
const filePath =
|
|
5403
|
+
const filePath = path7.join(this.projectDir, `${this.currentConversationId}.jsonl`);
|
|
5358
5404
|
const messages = parseJsonl(filePath);
|
|
5359
5405
|
if (messages.length > previousCount) {
|
|
5360
5406
|
for (let i = messages.length - 1; i >= previousCount; i--) {
|
|
@@ -5371,13 +5417,13 @@ var HistoryService = class {
|
|
|
5371
5417
|
try {
|
|
5372
5418
|
const files = fs4.readdirSync(dir, { withFileTypes: true }).filter((e) => e.isFile() && e.name.endsWith(".jsonl")).map((e) => {
|
|
5373
5419
|
try {
|
|
5374
|
-
return { name: e.name, mtime: fs4.statSync(
|
|
5420
|
+
return { name: e.name, mtime: fs4.statSync(path7.join(dir, e.name)).mtimeMs };
|
|
5375
5421
|
} catch {
|
|
5376
5422
|
return { name: e.name, mtime: 0 };
|
|
5377
5423
|
}
|
|
5378
5424
|
}).sort((a, b) => b.mtime - a.mtime);
|
|
5379
5425
|
if (files.length > 0) {
|
|
5380
|
-
this.currentConversationId =
|
|
5426
|
+
this.currentConversationId = path7.basename(files[0].name, ".jsonl");
|
|
5381
5427
|
}
|
|
5382
5428
|
} catch {
|
|
5383
5429
|
}
|
|
@@ -5415,7 +5461,7 @@ var HistoryService = class {
|
|
|
5415
5461
|
}
|
|
5416
5462
|
const files = entries.filter((e) => e.isFile() && e.name.endsWith(".jsonl")).map((e) => {
|
|
5417
5463
|
try {
|
|
5418
|
-
return { name: e.name, mtime: fs4.statSync(
|
|
5464
|
+
return { name: e.name, mtime: fs4.statSync(path7.join(dir, e.name)).mtimeMs };
|
|
5419
5465
|
} catch {
|
|
5420
5466
|
return { name: e.name, mtime: 0 };
|
|
5421
5467
|
}
|
|
@@ -5423,7 +5469,7 @@ var HistoryService = class {
|
|
|
5423
5469
|
if (files.length === 0) return null;
|
|
5424
5470
|
const targetFile = this.currentConversationId ? `${this.currentConversationId}.jsonl` : files[0].name;
|
|
5425
5471
|
if (!files.some((f) => f.name === targetFile)) return null;
|
|
5426
|
-
return this.extractUsageFromFile(
|
|
5472
|
+
return this.extractUsageFromFile(path7.join(dir, targetFile));
|
|
5427
5473
|
}
|
|
5428
5474
|
extractUsageFromFile(filePath) {
|
|
5429
5475
|
let raw;
|
|
@@ -5475,7 +5521,7 @@ var HistoryService = class {
|
|
|
5475
5521
|
try {
|
|
5476
5522
|
files = fs4.readdirSync(projectDir).filter((f) => f.endsWith(".jsonl")).filter((f) => {
|
|
5477
5523
|
try {
|
|
5478
|
-
return fs4.statSync(
|
|
5524
|
+
return fs4.statSync(path7.join(projectDir, f)).mtimeMs >= monthStartMs;
|
|
5479
5525
|
} catch {
|
|
5480
5526
|
return false;
|
|
5481
5527
|
}
|
|
@@ -5486,7 +5532,7 @@ var HistoryService = class {
|
|
|
5486
5532
|
for (const file of files) {
|
|
5487
5533
|
let raw;
|
|
5488
5534
|
try {
|
|
5489
|
-
raw = fs4.readFileSync(
|
|
5535
|
+
raw = fs4.readFileSync(path7.join(projectDir, file), "utf8");
|
|
5490
5536
|
} catch {
|
|
5491
5537
|
continue;
|
|
5492
5538
|
}
|
|
@@ -5528,8 +5574,8 @@ var HistoryService = class {
|
|
|
5528
5574
|
const sessions2 = [];
|
|
5529
5575
|
for (const entry of entries) {
|
|
5530
5576
|
if (!entry.isFile() || !entry.name.endsWith(".jsonl")) continue;
|
|
5531
|
-
const id =
|
|
5532
|
-
const filePath =
|
|
5577
|
+
const id = path7.basename(entry.name, ".jsonl");
|
|
5578
|
+
const filePath = path7.join(dir, entry.name);
|
|
5533
5579
|
let mtime = Date.now();
|
|
5534
5580
|
try {
|
|
5535
5581
|
mtime = fs4.statSync(filePath).mtimeMs;
|
|
@@ -5570,7 +5616,7 @@ var HistoryService = class {
|
|
|
5570
5616
|
* showing an empty conversation.
|
|
5571
5617
|
*/
|
|
5572
5618
|
async loadConversation(sessionId) {
|
|
5573
|
-
const filePath =
|
|
5619
|
+
const filePath = path7.join(this.projectDir, `${sessionId}.jsonl`);
|
|
5574
5620
|
const messages = parseJsonl(filePath);
|
|
5575
5621
|
if (messages.length === 0) return;
|
|
5576
5622
|
const totalBatches = Math.ceil(messages.length / CONVERSATION_BATCH_SIZE);
|
|
@@ -5626,7 +5672,7 @@ function parsePayload(schema, raw) {
|
|
|
5626
5672
|
|
|
5627
5673
|
// src/services/file-ops.service.ts
|
|
5628
5674
|
var fs5 = __toESM(require("fs/promises"));
|
|
5629
|
-
var
|
|
5675
|
+
var path8 = __toESM(require("path"));
|
|
5630
5676
|
var MAX_FILE_BYTES = 5 * 1024 * 1024;
|
|
5631
5677
|
var MAX_WALK_DEPTH = 6;
|
|
5632
5678
|
var MAX_VISITED_DIRS = 5e3;
|
|
@@ -5661,8 +5707,8 @@ var SUBDIR_IGNORE = /* @__PURE__ */ new Set([
|
|
|
5661
5707
|
"__pycache__"
|
|
5662
5708
|
]);
|
|
5663
5709
|
function isUnder(parent, candidate) {
|
|
5664
|
-
const rel =
|
|
5665
|
-
return rel === "" || !rel.startsWith("..") && !
|
|
5710
|
+
const rel = path8.relative(parent, candidate);
|
|
5711
|
+
return rel === "" || !rel.startsWith("..") && !path8.isAbsolute(rel);
|
|
5666
5712
|
}
|
|
5667
5713
|
async function isExistingFile(absPath) {
|
|
5668
5714
|
try {
|
|
@@ -5685,7 +5731,7 @@ async function walkForSuffix(dir, needleVariants, depth, ctx) {
|
|
|
5685
5731
|
}
|
|
5686
5732
|
for (const e of entries) {
|
|
5687
5733
|
if (!e.isFile()) continue;
|
|
5688
|
-
const full =
|
|
5734
|
+
const full = path8.join(dir, e.name);
|
|
5689
5735
|
if (needleVariants.some((needle) => full.endsWith(needle))) {
|
|
5690
5736
|
ctx.matches.push(full);
|
|
5691
5737
|
if (ctx.matches.length >= ctx.cap) return;
|
|
@@ -5695,21 +5741,21 @@ async function walkForSuffix(dir, needleVariants, depth, ctx) {
|
|
|
5695
5741
|
if (!e.isDirectory()) continue;
|
|
5696
5742
|
if (SUBDIR_IGNORE.has(e.name)) continue;
|
|
5697
5743
|
if (e.name.startsWith(".") && SUBDIR_IGNORE.has(e.name)) continue;
|
|
5698
|
-
await walkForSuffix(
|
|
5744
|
+
await walkForSuffix(path8.join(dir, e.name), needleVariants, depth + 1, ctx);
|
|
5699
5745
|
if (ctx.matches.length >= ctx.cap) return;
|
|
5700
5746
|
}
|
|
5701
5747
|
}
|
|
5702
5748
|
async function findFile(rawPath) {
|
|
5703
5749
|
const cwd = process.cwd();
|
|
5704
|
-
if (
|
|
5705
|
-
const abs =
|
|
5750
|
+
if (path8.isAbsolute(rawPath)) {
|
|
5751
|
+
const abs = path8.normalize(rawPath);
|
|
5706
5752
|
if (isUnder(cwd, abs) && await isExistingFile(abs)) return abs;
|
|
5707
5753
|
}
|
|
5708
|
-
const direct =
|
|
5754
|
+
const direct = path8.resolve(cwd, rawPath);
|
|
5709
5755
|
if (isUnder(cwd, direct) && await isExistingFile(direct)) return direct;
|
|
5710
|
-
const normalized =
|
|
5756
|
+
const normalized = path8.normalize(rawPath).replace(/^[./\\]+/, "");
|
|
5711
5757
|
const needles = [
|
|
5712
|
-
`${
|
|
5758
|
+
`${path8.sep}${normalized}`,
|
|
5713
5759
|
`/${normalized}`
|
|
5714
5760
|
].filter((v, i, a) => a.indexOf(v) === i);
|
|
5715
5761
|
const ctx = { visited: 0, matches: [], cap: 16 };
|
|
@@ -5723,7 +5769,7 @@ async function findWriteTarget(rawPath) {
|
|
|
5723
5769
|
const found = await findFile(rawPath);
|
|
5724
5770
|
if (found) return found;
|
|
5725
5771
|
const cwd = process.cwd();
|
|
5726
|
-
const fallback =
|
|
5772
|
+
const fallback = path8.isAbsolute(rawPath) ? path8.normalize(rawPath) : path8.resolve(cwd, rawPath);
|
|
5727
5773
|
if (!isUnder(cwd, fallback)) return null;
|
|
5728
5774
|
return fallback;
|
|
5729
5775
|
}
|
|
@@ -5763,7 +5809,7 @@ async function writeProjectFile(rawPath, content) {
|
|
|
5763
5809
|
if (Buffer.byteLength(content, "utf-8") > MAX_FILE_BYTES) {
|
|
5764
5810
|
return { error: "Content too large." };
|
|
5765
5811
|
}
|
|
5766
|
-
await fs5.mkdir(
|
|
5812
|
+
await fs5.mkdir(path8.dirname(abs), { recursive: true });
|
|
5767
5813
|
await fs5.writeFile(abs, content, "utf-8");
|
|
5768
5814
|
return { ok: true };
|
|
5769
5815
|
} catch (e) {
|
|
@@ -5776,7 +5822,7 @@ async function writeProjectFile(rawPath, content) {
|
|
|
5776
5822
|
var import_child_process4 = require("child_process");
|
|
5777
5823
|
var import_util = require("util");
|
|
5778
5824
|
var fs6 = __toESM(require("fs/promises"));
|
|
5779
|
-
var
|
|
5825
|
+
var path9 = __toESM(require("path"));
|
|
5780
5826
|
var execFileP = (0, import_util.promisify)(import_child_process4.execFile);
|
|
5781
5827
|
var PROJECT_IGNORE = /* @__PURE__ */ new Set([
|
|
5782
5828
|
"node_modules",
|
|
@@ -5834,12 +5880,12 @@ async function listProjectFiles(opts = {}) {
|
|
|
5834
5880
|
return;
|
|
5835
5881
|
}
|
|
5836
5882
|
if (PROJECT_IGNORE.has(e.name)) continue;
|
|
5837
|
-
const full =
|
|
5883
|
+
const full = path9.join(dir, e.name);
|
|
5838
5884
|
if (e.isDirectory()) {
|
|
5839
5885
|
if (depth >= 12) continue;
|
|
5840
5886
|
await walk(full, depth + 1);
|
|
5841
5887
|
} else if (e.isFile()) {
|
|
5842
|
-
const rel =
|
|
5888
|
+
const rel = path9.relative(root, full);
|
|
5843
5889
|
if (q2 && !rel.toLowerCase().includes(q2) && !e.name.toLowerCase().includes(q2)) {
|
|
5844
5890
|
continue;
|
|
5845
5891
|
}
|
|
@@ -5947,7 +5993,7 @@ async function gitStatus(cwd) {
|
|
|
5947
5993
|
let hasMergeInProgress = false;
|
|
5948
5994
|
try {
|
|
5949
5995
|
const gitDir = (await git(["rev-parse", "--git-dir"], root)).stdout.trim();
|
|
5950
|
-
const mergeHead =
|
|
5996
|
+
const mergeHead = path9.isAbsolute(gitDir) ? path9.join(gitDir, "MERGE_HEAD") : path9.join(root, gitDir, "MERGE_HEAD");
|
|
5951
5997
|
await fs6.access(mergeHead);
|
|
5952
5998
|
hasMergeInProgress = true;
|
|
5953
5999
|
} catch {
|
|
@@ -6025,7 +6071,7 @@ async function gitResolve(file, side, cwd) {
|
|
|
6025
6071
|
function saveFilesTemp(files) {
|
|
6026
6072
|
return files.filter(({ base64 }) => base64 && base64.length > 0).map(({ filename, base64 }) => {
|
|
6027
6073
|
const safeName = filename.replace(/[^a-zA-Z0-9._-]/g, "_").slice(0, 80);
|
|
6028
|
-
const tmpPath =
|
|
6074
|
+
const tmpPath = path10.join(os6.tmpdir(), `codeam-${(0, import_crypto.randomUUID)()}-${safeName}`);
|
|
6029
6075
|
fs7.writeFileSync(tmpPath, Buffer.from(base64, "base64"));
|
|
6030
6076
|
return tmpPath;
|
|
6031
6077
|
});
|
|
@@ -6099,7 +6145,7 @@ try:
|
|
|
6099
6145
|
sys.exit((st>>8)&0xFF)
|
|
6100
6146
|
except Exception:sys.exit(0)
|
|
6101
6147
|
`;
|
|
6102
|
-
const helperPath =
|
|
6148
|
+
const helperPath = path10.join(os6.tmpdir(), "codeam-quota-helper.py");
|
|
6103
6149
|
fs7.writeFileSync(helperPath, helperScript, { mode: 420 });
|
|
6104
6150
|
const python = findInPath("python3") ?? findInPath("python");
|
|
6105
6151
|
if (!python) {
|
|
@@ -6702,7 +6748,7 @@ async function logout() {
|
|
|
6702
6748
|
var import_child_process10 = require("child_process");
|
|
6703
6749
|
var fs8 = __toESM(require("fs"));
|
|
6704
6750
|
var os7 = __toESM(require("os"));
|
|
6705
|
-
var
|
|
6751
|
+
var path15 = __toESM(require("path"));
|
|
6706
6752
|
var import_util6 = require("util");
|
|
6707
6753
|
var import_picocolors9 = __toESM(require("picocolors"));
|
|
6708
6754
|
|
|
@@ -6710,7 +6756,7 @@ var import_picocolors9 = __toESM(require("picocolors"));
|
|
|
6710
6756
|
var import_child_process6 = require("child_process");
|
|
6711
6757
|
var import_util2 = require("util");
|
|
6712
6758
|
var import_picocolors7 = __toESM(require("picocolors"));
|
|
6713
|
-
var
|
|
6759
|
+
var path11 = __toESM(require("path"));
|
|
6714
6760
|
var execFileP2 = (0, import_util2.promisify)(import_child_process6.execFile);
|
|
6715
6761
|
var MAX_BUFFER = 8 * 1024 * 1024;
|
|
6716
6762
|
function resetStdinForChild() {
|
|
@@ -7199,7 +7245,7 @@ var GitHubCodespacesProvider = class {
|
|
|
7199
7245
|
});
|
|
7200
7246
|
}
|
|
7201
7247
|
async uploadFile(workspaceId, remotePath, contents, options = {}) {
|
|
7202
|
-
const remoteDir =
|
|
7248
|
+
const remoteDir = path11.posix.dirname(remotePath);
|
|
7203
7249
|
const parts = [
|
|
7204
7250
|
`mkdir -p ${shellQuote(remoteDir)}`,
|
|
7205
7251
|
`cat > ${shellQuote(remotePath)}`
|
|
@@ -7269,7 +7315,7 @@ function shellQuote(s) {
|
|
|
7269
7315
|
// src/services/providers/gitpod.ts
|
|
7270
7316
|
var import_child_process7 = require("child_process");
|
|
7271
7317
|
var import_util3 = require("util");
|
|
7272
|
-
var
|
|
7318
|
+
var path12 = __toESM(require("path"));
|
|
7273
7319
|
var import_picocolors8 = __toESM(require("picocolors"));
|
|
7274
7320
|
var execFileP3 = (0, import_util3.promisify)(import_child_process7.execFile);
|
|
7275
7321
|
var MAX_BUFFER2 = 8 * 1024 * 1024;
|
|
@@ -7509,7 +7555,7 @@ var GitpodProvider = class {
|
|
|
7509
7555
|
});
|
|
7510
7556
|
}
|
|
7511
7557
|
async uploadFile(workspaceId, remotePath, contents, options = {}) {
|
|
7512
|
-
const remoteDir =
|
|
7558
|
+
const remoteDir = path12.posix.dirname(remotePath);
|
|
7513
7559
|
const parts = [
|
|
7514
7560
|
`mkdir -p ${shellQuote2(remoteDir)}`,
|
|
7515
7561
|
`cat > ${shellQuote2(remotePath)}`
|
|
@@ -7545,7 +7591,7 @@ function shellQuote2(s) {
|
|
|
7545
7591
|
// src/services/providers/gitlab-workspaces.ts
|
|
7546
7592
|
var import_child_process8 = require("child_process");
|
|
7547
7593
|
var import_util4 = require("util");
|
|
7548
|
-
var
|
|
7594
|
+
var path13 = __toESM(require("path"));
|
|
7549
7595
|
var execFileP4 = (0, import_util4.promisify)(import_child_process8.execFile);
|
|
7550
7596
|
var MAX_BUFFER3 = 8 * 1024 * 1024;
|
|
7551
7597
|
var GITLAB_API_BASE = process.env.CODEAM_GITLAB_API_URL ?? "https://gitlab.com/api/v4";
|
|
@@ -7805,7 +7851,7 @@ Docs: https://docs.gitlab.com/ee/user/workspace/configuration.html`
|
|
|
7805
7851
|
}
|
|
7806
7852
|
async uploadFile(workspaceId, remotePath, contents, options = {}) {
|
|
7807
7853
|
const sshHost = process.env.CODEAM_GITLAB_SSH_HOST ?? "workspaces.gitlab.com";
|
|
7808
|
-
const remoteDir =
|
|
7854
|
+
const remoteDir = path13.posix.dirname(remotePath);
|
|
7809
7855
|
const parts = [`mkdir -p ${shellQuote3(remoteDir)}`, `cat > ${shellQuote3(remotePath)}`];
|
|
7810
7856
|
if (options.mode != null) {
|
|
7811
7857
|
parts.push(`chmod ${options.mode.toString(8)} ${shellQuote3(remotePath)}`);
|
|
@@ -7873,7 +7919,7 @@ function shellQuote3(s) {
|
|
|
7873
7919
|
// src/services/providers/railway.ts
|
|
7874
7920
|
var import_child_process9 = require("child_process");
|
|
7875
7921
|
var import_util5 = require("util");
|
|
7876
|
-
var
|
|
7922
|
+
var path14 = __toESM(require("path"));
|
|
7877
7923
|
var execFileP5 = (0, import_util5.promisify)(import_child_process9.execFile);
|
|
7878
7924
|
var MAX_BUFFER4 = 8 * 1024 * 1024;
|
|
7879
7925
|
function resetStdinForChild4() {
|
|
@@ -8109,7 +8155,7 @@ var RailwayProvider = class {
|
|
|
8109
8155
|
if (!projectId || !serviceId) {
|
|
8110
8156
|
throw new Error("Invalid Railway workspace id (expected projectId/serviceId).");
|
|
8111
8157
|
}
|
|
8112
|
-
const remoteDir =
|
|
8158
|
+
const remoteDir = path14.posix.dirname(remotePath);
|
|
8113
8159
|
const parts = [`mkdir -p ${shellQuote4(remoteDir)}`, `cat > ${shellQuote4(remotePath)}`];
|
|
8114
8160
|
if (options.mode != null) {
|
|
8115
8161
|
parts.push(`chmod ${options.mode.toString(8)} ${shellQuote4(remotePath)}`);
|
|
@@ -8301,7 +8347,7 @@ async function deploy() {
|
|
|
8301
8347
|
process.exit(1);
|
|
8302
8348
|
}
|
|
8303
8349
|
}
|
|
8304
|
-
const localClaudeDir =
|
|
8350
|
+
const localClaudeDir = path15.join(os7.homedir(), ".claude");
|
|
8305
8351
|
const localCredsKind = await detectLocalClaudeCredentials(localClaudeDir);
|
|
8306
8352
|
let bridged = "none";
|
|
8307
8353
|
if (localCredsKind !== "none") {
|
|
@@ -8399,7 +8445,7 @@ async function deploy() {
|
|
|
8399
8445
|
}
|
|
8400
8446
|
}
|
|
8401
8447
|
if (bridged !== "none") {
|
|
8402
|
-
const localClaudeJson =
|
|
8448
|
+
const localClaudeJson = path15.join(os7.homedir(), ".claude.json");
|
|
8403
8449
|
if (fs8.existsSync(localClaudeJson)) {
|
|
8404
8450
|
try {
|
|
8405
8451
|
const contents = fs8.readFileSync(localClaudeJson);
|
|
@@ -8592,7 +8638,7 @@ async function runRemoteClaudeLogin(provider, workspaceId) {
|
|
|
8592
8638
|
}
|
|
8593
8639
|
}
|
|
8594
8640
|
async function detectLocalClaudeCredentials(localClaudeDir) {
|
|
8595
|
-
if (fs8.existsSync(
|
|
8641
|
+
if (fs8.existsSync(path15.join(localClaudeDir, ".credentials.json"))) {
|
|
8596
8642
|
return "flat-file";
|
|
8597
8643
|
}
|
|
8598
8644
|
if (process.platform === "darwin") {
|
|
@@ -8625,7 +8671,7 @@ async function verifyClaudeAuth(provider, workspaceId) {
|
|
|
8625
8671
|
}
|
|
8626
8672
|
}
|
|
8627
8673
|
async function bridgeClaudeCredentials(provider, workspaceId, localClaudeDir) {
|
|
8628
|
-
const fileBased =
|
|
8674
|
+
const fileBased = path15.join(localClaudeDir, ".credentials.json");
|
|
8629
8675
|
if (fs8.existsSync(fileBased)) return "flat-file";
|
|
8630
8676
|
if (process.platform === "darwin") {
|
|
8631
8677
|
try {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "codeam-cli",
|
|
3
|
-
"version": "2.4.
|
|
3
|
+
"version": "2.4.33",
|
|
4
4
|
"description": "Remote control Claude Code (and other AI coding agents) from your mobile phone. Pair your device, send prompts, stream responses in real-time, and approve commands — from anywhere.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"bin": {
|