codeam-cli 2.4.29 → 2.4.31
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 +12 -0
- package/dist/index.js +132 -114
- package/dist/vendor/node-pty/lib/conpty_console_list_agent.js +16 -0
- package/dist/vendor/node-pty/lib/eventEmitter2.js +47 -0
- package/dist/vendor/node-pty/lib/index.js +52 -0
- package/dist/vendor/node-pty/lib/interfaces.js +7 -0
- package/dist/vendor/node-pty/lib/shared/conout.js +11 -0
- package/dist/vendor/node-pty/lib/terminal.js +190 -0
- package/dist/vendor/node-pty/lib/types.js +7 -0
- package/dist/vendor/node-pty/lib/unixTerminal.js +346 -0
- package/dist/vendor/node-pty/lib/utils.js +39 -0
- package/dist/vendor/node-pty/lib/windowsConoutConnection.js +125 -0
- package/dist/vendor/node-pty/lib/windowsPtyAgent.js +320 -0
- package/dist/vendor/node-pty/lib/windowsTerminal.js +199 -0
- package/dist/vendor/node-pty/lib/worker/conoutSocketWorker.js +22 -0
- package/dist/vendor/node-pty/package.json +64 -0
- package/dist/vendor/node-pty/prebuilds/win32-arm64/conpty/OpenConsole.exe +0 -0
- package/dist/vendor/node-pty/prebuilds/win32-arm64/conpty/conpty.dll +0 -0
- package/dist/vendor/node-pty/prebuilds/win32-arm64/conpty.node +0 -0
- package/dist/vendor/node-pty/prebuilds/win32-arm64/conpty_console_list.node +0 -0
- package/dist/vendor/node-pty/prebuilds/win32-arm64/pty.node +0 -0
- package/dist/vendor/node-pty/prebuilds/win32-arm64/winpty-agent.exe +0 -0
- package/dist/vendor/node-pty/prebuilds/win32-arm64/winpty.dll +0 -0
- package/dist/vendor/node-pty/prebuilds/win32-x64/conpty/OpenConsole.exe +0 -0
- package/dist/vendor/node-pty/prebuilds/win32-x64/conpty/conpty.dll +0 -0
- package/dist/vendor/node-pty/prebuilds/win32-x64/conpty.node +0 -0
- package/dist/vendor/node-pty/prebuilds/win32-x64/conpty_console_list.node +0 -0
- package/dist/vendor/node-pty/prebuilds/win32-x64/pty.node +0 -0
- package/dist/vendor/node-pty/prebuilds/win32-x64/winpty-agent.exe +0 -0
- package/dist/vendor/node-pty/prebuilds/win32-x64/winpty.dll +0 -0
- package/package.json +3 -5
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,18 @@ 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.30] — 2026-05-05
|
|
8
|
+
|
|
9
|
+
### Fixed
|
|
10
|
+
|
|
11
|
+
- **cli:** Pin node-pty ^1.1.0 + graceful pipe fallback if ConPTY fails (v2.4.30)
|
|
12
|
+
|
|
13
|
+
## [2.4.29] — 2026-05-05
|
|
14
|
+
|
|
15
|
+
### Added
|
|
16
|
+
|
|
17
|
+
- **cli:** Auto-install Claude Code if missing on first launch (v2.4.29)
|
|
18
|
+
|
|
7
19
|
## [2.4.28] — 2026-05-05
|
|
8
20
|
|
|
9
21
|
### 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 path15 = 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 = path15.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(path15.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 path15 = 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 = path15.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 path9 = __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.31",
|
|
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: {
|
|
@@ -1495,7 +1495,7 @@ var package_default = {
|
|
|
1495
1495
|
"LICENSE"
|
|
1496
1496
|
],
|
|
1497
1497
|
scripts: {
|
|
1498
|
-
build: "tsup",
|
|
1498
|
+
build: "tsup && node scripts/vendor-node-pty.js",
|
|
1499
1499
|
dev: "tsup --watch",
|
|
1500
1500
|
test: "vitest run",
|
|
1501
1501
|
typecheck: "tsc --noEmit",
|
|
@@ -1556,14 +1556,12 @@ var package_default = {
|
|
|
1556
1556
|
ws: "^8.18.0",
|
|
1557
1557
|
zod: "^4.3.6"
|
|
1558
1558
|
},
|
|
1559
|
-
optionalDependencies: {
|
|
1560
|
-
"node-pty": "^1.0.0"
|
|
1561
|
-
},
|
|
1562
1559
|
devDependencies: {
|
|
1563
1560
|
"@codeagent/shared": "*",
|
|
1564
1561
|
"@types/node": "^22.0.0",
|
|
1565
1562
|
"@types/qrcode-terminal": "^0.12.0",
|
|
1566
1563
|
"@types/ws": "^8.5.0",
|
|
1564
|
+
"node-pty": "^1.1.0",
|
|
1567
1565
|
tsup: "^8.0.0",
|
|
1568
1566
|
typescript: "^6.0.3",
|
|
1569
1567
|
vitest: "^4.1.5"
|
|
@@ -2262,11 +2260,18 @@ var WindowsPtyStrategy = class {
|
|
|
2262
2260
|
};
|
|
2263
2261
|
|
|
2264
2262
|
// src/services/pty/windows-conpty.strategy.ts
|
|
2263
|
+
var path4 = __toESM(require("path"));
|
|
2265
2264
|
function loadNodePty() {
|
|
2265
|
+
const vendoredPath = path4.join(__dirname, "vendor", "node-pty");
|
|
2266
2266
|
try {
|
|
2267
|
-
return
|
|
2268
|
-
} catch {
|
|
2269
|
-
|
|
2267
|
+
return require(vendoredPath);
|
|
2268
|
+
} catch (vendorErr) {
|
|
2269
|
+
try {
|
|
2270
|
+
return require_lib();
|
|
2271
|
+
} catch {
|
|
2272
|
+
void vendorErr;
|
|
2273
|
+
return null;
|
|
2274
|
+
}
|
|
2270
2275
|
}
|
|
2271
2276
|
}
|
|
2272
2277
|
var WindowsConPtyStrategy = class _WindowsConPtyStrategy {
|
|
@@ -2291,31 +2296,19 @@ var WindowsConPtyStrategy = class _WindowsConPtyStrategy {
|
|
|
2291
2296
|
return new _WindowsConPtyStrategy(opts, lib);
|
|
2292
2297
|
}
|
|
2293
2298
|
spawn(cmd, cwd, args2 = []) {
|
|
2294
|
-
|
|
2295
|
-
|
|
2296
|
-
|
|
2297
|
-
|
|
2298
|
-
|
|
2299
|
-
|
|
2300
|
-
env
|
|
2301
|
-
|
|
2302
|
-
|
|
2303
|
-
|
|
2304
|
-
|
|
2305
|
-
|
|
2306
|
-
|
|
2307
|
-
});
|
|
2308
|
-
} catch (err) {
|
|
2309
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
2310
|
-
console.error(
|
|
2311
|
-
`
|
|
2312
|
-
\u2717 Failed to launch Claude Code via ConPTY: ${msg}
|
|
2313
|
-
Make sure claude is installed: npm install -g @anthropic-ai/claude-code
|
|
2314
|
-
`
|
|
2315
|
-
);
|
|
2316
|
-
this.opts.onExit(1);
|
|
2317
|
-
return;
|
|
2318
|
-
}
|
|
2299
|
+
this.pty = this.lib.spawn(cmd, args2, {
|
|
2300
|
+
name: "xterm-256color",
|
|
2301
|
+
cols: 220,
|
|
2302
|
+
rows: 50,
|
|
2303
|
+
cwd,
|
|
2304
|
+
env: {
|
|
2305
|
+
...process.env,
|
|
2306
|
+
TERM: "xterm-256color",
|
|
2307
|
+
FORCE_COLOR: "1"
|
|
2308
|
+
},
|
|
2309
|
+
useConpty: true,
|
|
2310
|
+
conptyInheritCursor: false
|
|
2311
|
+
});
|
|
2319
2312
|
this.dataSub = this.pty.onData((data) => {
|
|
2320
2313
|
process.stdout.write(data);
|
|
2321
2314
|
this.opts.onData(data);
|
|
@@ -2367,7 +2360,7 @@ var WindowsConPtyStrategy = class _WindowsConPtyStrategy {
|
|
|
2367
2360
|
|
|
2368
2361
|
// src/services/claude-installer.ts
|
|
2369
2362
|
var import_child_process3 = require("child_process");
|
|
2370
|
-
var
|
|
2363
|
+
var path5 = __toESM(require("path"));
|
|
2371
2364
|
var os4 = __toESM(require("os"));
|
|
2372
2365
|
|
|
2373
2366
|
// ../../node_modules/@clack/prompts/dist/index.mjs
|
|
@@ -4285,14 +4278,14 @@ function probeInstallDirs() {
|
|
|
4285
4278
|
const home = os4.homedir();
|
|
4286
4279
|
if (process.platform === "win32") {
|
|
4287
4280
|
return [
|
|
4288
|
-
|
|
4289
|
-
|
|
4290
|
-
|
|
4281
|
+
path5.join(home, ".claude", "local"),
|
|
4282
|
+
path5.join(home, "AppData", "Local", "AnthropicClaude"),
|
|
4283
|
+
path5.join(home, "AppData", "Local", "Programs", "AnthropicClaude")
|
|
4291
4284
|
];
|
|
4292
4285
|
}
|
|
4293
4286
|
return [
|
|
4294
|
-
|
|
4295
|
-
|
|
4287
|
+
path5.join(home, ".local", "bin"),
|
|
4288
|
+
path5.join(home, ".claude", "local"),
|
|
4296
4289
|
"/usr/local/bin"
|
|
4297
4290
|
];
|
|
4298
4291
|
}
|
|
@@ -4301,7 +4294,7 @@ function isAvailable() {
|
|
|
4301
4294
|
}
|
|
4302
4295
|
function augmentPath() {
|
|
4303
4296
|
const dirs = probeInstallDirs();
|
|
4304
|
-
const sep2 =
|
|
4297
|
+
const sep2 = path5.delimiter;
|
|
4305
4298
|
const current = process.env.PATH ?? "";
|
|
4306
4299
|
const existing = new Set(current.split(sep2).filter(Boolean));
|
|
4307
4300
|
const additions = dirs.filter((d3) => !existing.has(d3));
|
|
@@ -4362,27 +4355,18 @@ async function ensureClaudeInstalled() {
|
|
|
4362
4355
|
var ClaudeService = class {
|
|
4363
4356
|
constructor(opts) {
|
|
4364
4357
|
this.opts = opts;
|
|
4365
|
-
|
|
4358
|
+
this.strategyOpts = {
|
|
4366
4359
|
onData: opts.onData ?? (() => {
|
|
4367
4360
|
}),
|
|
4368
4361
|
onExit: opts.onExit
|
|
4369
4362
|
};
|
|
4370
|
-
if (process.platform === "win32") {
|
|
4371
|
-
const conpty = WindowsConPtyStrategy.tryCreate(strategyOpts);
|
|
4372
|
-
if (conpty) {
|
|
4373
|
-
this.strategy = conpty;
|
|
4374
|
-
} else {
|
|
4375
|
-
console.error(
|
|
4376
|
-
'\n \u26A0 Windows: node-pty unavailable, falling back to pipe mode.\n Claude Code may exit immediately with "no stdin data" / "--print" errors.\n Install build tools or run codeam-cli inside WSL for the best experience.\n'
|
|
4377
|
-
);
|
|
4378
|
-
this.strategy = new WindowsPtyStrategy(strategyOpts);
|
|
4379
|
-
}
|
|
4380
|
-
} else {
|
|
4381
|
-
this.strategy = new UnixPtyStrategy(strategyOpts);
|
|
4382
|
-
}
|
|
4383
4363
|
}
|
|
4384
4364
|
opts;
|
|
4385
|
-
|
|
4365
|
+
// Strategy is selected lazily inside spawn() so we can fall back from
|
|
4366
|
+
// ConPTY → legacy pipe at runtime if the native binding fails to load.
|
|
4367
|
+
// Methods called before spawn() (e.g. early kill/SIGINT) no-op safely.
|
|
4368
|
+
strategy = null;
|
|
4369
|
+
strategyOpts;
|
|
4386
4370
|
async spawn() {
|
|
4387
4371
|
if (!findInPath("claude") && !findInPath("claude-code")) {
|
|
4388
4372
|
const installed = await ensureClaudeInstalled();
|
|
@@ -4399,7 +4383,36 @@ var ClaudeService = class {
|
|
|
4399
4383
|
}
|
|
4400
4384
|
}
|
|
4401
4385
|
const claudeCmd = findInPath("claude") ? "claude" : "claude-code";
|
|
4402
|
-
|
|
4386
|
+
if (process.platform === "win32") {
|
|
4387
|
+
const conpty = WindowsConPtyStrategy.tryCreate(this.strategyOpts);
|
|
4388
|
+
if (conpty) {
|
|
4389
|
+
try {
|
|
4390
|
+
conpty.spawn(claudeCmd, this.opts.cwd);
|
|
4391
|
+
this.strategy = conpty;
|
|
4392
|
+
return;
|
|
4393
|
+
} catch (err) {
|
|
4394
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
4395
|
+
try {
|
|
4396
|
+
conpty.dispose();
|
|
4397
|
+
} catch {
|
|
4398
|
+
}
|
|
4399
|
+
console.error(`
|
|
4400
|
+
\u26A0 ConPTY launch failed (${msg.split("\n")[0]})`);
|
|
4401
|
+
console.error(" Falling back to pipe mode (limited interactivity)\u2026\n");
|
|
4402
|
+
}
|
|
4403
|
+
} else {
|
|
4404
|
+
console.error(
|
|
4405
|
+
'\n \u26A0 Windows: node-pty unavailable, falling back to pipe mode.\n Claude may exit with "no stdin data" / "--print" errors.\n Reinstall the CLI to fetch the prebuilt ConPTY binary, or run inside WSL.\n'
|
|
4406
|
+
);
|
|
4407
|
+
}
|
|
4408
|
+
const pipe = new WindowsPtyStrategy(this.strategyOpts);
|
|
4409
|
+
pipe.spawn(claudeCmd, this.opts.cwd);
|
|
4410
|
+
this.strategy = pipe;
|
|
4411
|
+
return;
|
|
4412
|
+
}
|
|
4413
|
+
const unix = new UnixPtyStrategy(this.strategyOpts);
|
|
4414
|
+
unix.spawn(claudeCmd, this.opts.cwd);
|
|
4415
|
+
this.strategy = unix;
|
|
4403
4416
|
}
|
|
4404
4417
|
/**
|
|
4405
4418
|
* Send a command to Claude's stdin (remote control from mobile).
|
|
@@ -4415,8 +4428,10 @@ var ClaudeService = class {
|
|
|
4415
4428
|
* a fresh event-loop tick, after React has flushed the text into input state.
|
|
4416
4429
|
*/
|
|
4417
4430
|
sendCommand(text) {
|
|
4418
|
-
this.strategy
|
|
4419
|
-
|
|
4431
|
+
if (!this.strategy) return;
|
|
4432
|
+
const s = this.strategy;
|
|
4433
|
+
s.write(text);
|
|
4434
|
+
setTimeout(() => s.write("\r"), 50);
|
|
4420
4435
|
}
|
|
4421
4436
|
/**
|
|
4422
4437
|
* Navigate a React Ink selector to the given 0-based target index and confirm.
|
|
@@ -4437,40 +4452,43 @@ var ClaudeService = class {
|
|
|
4437
4452
|
* ENTER_MS after the last arrow.
|
|
4438
4453
|
*/
|
|
4439
4454
|
selectOption(targetIndex, fromIndex = 0) {
|
|
4455
|
+
if (!this.strategy) return;
|
|
4456
|
+
const s = this.strategy;
|
|
4440
4457
|
const delta = targetIndex - fromIndex;
|
|
4441
4458
|
const steps = Math.abs(delta);
|
|
4442
4459
|
const arrow = delta >= 0 ? "\x1B[B" : "\x1B[A";
|
|
4443
4460
|
const ARROW_MS = 80;
|
|
4444
4461
|
const ENTER_MS = 200;
|
|
4445
4462
|
if (steps === 0) {
|
|
4446
|
-
|
|
4463
|
+
s.write("\r");
|
|
4447
4464
|
return;
|
|
4448
4465
|
}
|
|
4449
4466
|
for (let i = 0; i < steps; i++) {
|
|
4450
4467
|
setTimeout(() => {
|
|
4451
|
-
|
|
4468
|
+
s.write(arrow);
|
|
4452
4469
|
}, i * ARROW_MS);
|
|
4453
4470
|
}
|
|
4454
4471
|
setTimeout(() => {
|
|
4455
|
-
|
|
4472
|
+
s.write("\r");
|
|
4456
4473
|
}, steps * ARROW_MS + ENTER_MS);
|
|
4457
4474
|
}
|
|
4458
4475
|
/** Send Escape key to Claude (cancels interactive prompts). */
|
|
4459
4476
|
sendEscape() {
|
|
4460
|
-
this.strategy
|
|
4477
|
+
this.strategy?.write("\x1B");
|
|
4461
4478
|
}
|
|
4462
4479
|
/** Send Ctrl+C to Claude. */
|
|
4463
4480
|
interrupt() {
|
|
4464
|
-
this.strategy
|
|
4481
|
+
this.strategy?.write("");
|
|
4465
4482
|
}
|
|
4466
4483
|
kill() {
|
|
4467
|
-
this.strategy
|
|
4484
|
+
this.strategy?.kill();
|
|
4468
4485
|
}
|
|
4469
4486
|
/**
|
|
4470
4487
|
* Kill the current Claude process and relaunch it resuming the given session.
|
|
4471
4488
|
* Pass auto=true to add --dangerously-skip-permissions (no confirmation prompts).
|
|
4472
4489
|
*/
|
|
4473
4490
|
restart(sessionId, auto = false) {
|
|
4491
|
+
if (!this.strategy) return;
|
|
4474
4492
|
const claudeCmd = findInPath("claude") ? "claude" : "claude-code";
|
|
4475
4493
|
this.strategy.kill();
|
|
4476
4494
|
const args2 = ["--resume", sessionId];
|
|
@@ -5157,7 +5175,7 @@ function _sendOutputChunk(url, headers, payload) {
|
|
|
5157
5175
|
|
|
5158
5176
|
// src/services/history.service.ts
|
|
5159
5177
|
var fs4 = __toESM(require("fs"));
|
|
5160
|
-
var
|
|
5178
|
+
var path6 = __toESM(require("path"));
|
|
5161
5179
|
var os5 = __toESM(require("os"));
|
|
5162
5180
|
var https3 = __toESM(require("https"));
|
|
5163
5181
|
var http3 = __toESM(require("http"));
|
|
@@ -5313,7 +5331,7 @@ var HistoryService = class {
|
|
|
5313
5331
|
return this._quotaPercent === null || Date.now() - this._quotaFetchedAt > ttlMs;
|
|
5314
5332
|
}
|
|
5315
5333
|
get projectDir() {
|
|
5316
|
-
return
|
|
5334
|
+
return path6.join(os5.homedir(), ".claude", "projects", encodeCwd(this.cwd));
|
|
5317
5335
|
}
|
|
5318
5336
|
/** Set the current Claude conversation ID (extracted from /cost command or session start) */
|
|
5319
5337
|
setCurrentConversationId(id) {
|
|
@@ -5325,7 +5343,7 @@ var HistoryService = class {
|
|
|
5325
5343
|
/** Return the current message count in the active conversation. */
|
|
5326
5344
|
getCurrentMessageCount() {
|
|
5327
5345
|
if (!this.currentConversationId) return 0;
|
|
5328
|
-
const filePath =
|
|
5346
|
+
const filePath = path6.join(this.projectDir, `${this.currentConversationId}.jsonl`);
|
|
5329
5347
|
return parseJsonl(filePath).length;
|
|
5330
5348
|
}
|
|
5331
5349
|
/**
|
|
@@ -5336,7 +5354,7 @@ var HistoryService = class {
|
|
|
5336
5354
|
const deadline = Date.now() + timeoutMs;
|
|
5337
5355
|
while (Date.now() < deadline) {
|
|
5338
5356
|
if (!this.currentConversationId) return null;
|
|
5339
|
-
const filePath =
|
|
5357
|
+
const filePath = path6.join(this.projectDir, `${this.currentConversationId}.jsonl`);
|
|
5340
5358
|
const messages = parseJsonl(filePath);
|
|
5341
5359
|
if (messages.length > previousCount) {
|
|
5342
5360
|
for (let i = messages.length - 1; i >= previousCount; i--) {
|
|
@@ -5353,13 +5371,13 @@ var HistoryService = class {
|
|
|
5353
5371
|
try {
|
|
5354
5372
|
const files = fs4.readdirSync(dir, { withFileTypes: true }).filter((e) => e.isFile() && e.name.endsWith(".jsonl")).map((e) => {
|
|
5355
5373
|
try {
|
|
5356
|
-
return { name: e.name, mtime: fs4.statSync(
|
|
5374
|
+
return { name: e.name, mtime: fs4.statSync(path6.join(dir, e.name)).mtimeMs };
|
|
5357
5375
|
} catch {
|
|
5358
5376
|
return { name: e.name, mtime: 0 };
|
|
5359
5377
|
}
|
|
5360
5378
|
}).sort((a, b) => b.mtime - a.mtime);
|
|
5361
5379
|
if (files.length > 0) {
|
|
5362
|
-
this.currentConversationId =
|
|
5380
|
+
this.currentConversationId = path6.basename(files[0].name, ".jsonl");
|
|
5363
5381
|
}
|
|
5364
5382
|
} catch {
|
|
5365
5383
|
}
|
|
@@ -5397,7 +5415,7 @@ var HistoryService = class {
|
|
|
5397
5415
|
}
|
|
5398
5416
|
const files = entries.filter((e) => e.isFile() && e.name.endsWith(".jsonl")).map((e) => {
|
|
5399
5417
|
try {
|
|
5400
|
-
return { name: e.name, mtime: fs4.statSync(
|
|
5418
|
+
return { name: e.name, mtime: fs4.statSync(path6.join(dir, e.name)).mtimeMs };
|
|
5401
5419
|
} catch {
|
|
5402
5420
|
return { name: e.name, mtime: 0 };
|
|
5403
5421
|
}
|
|
@@ -5405,7 +5423,7 @@ var HistoryService = class {
|
|
|
5405
5423
|
if (files.length === 0) return null;
|
|
5406
5424
|
const targetFile = this.currentConversationId ? `${this.currentConversationId}.jsonl` : files[0].name;
|
|
5407
5425
|
if (!files.some((f) => f.name === targetFile)) return null;
|
|
5408
|
-
return this.extractUsageFromFile(
|
|
5426
|
+
return this.extractUsageFromFile(path6.join(dir, targetFile));
|
|
5409
5427
|
}
|
|
5410
5428
|
extractUsageFromFile(filePath) {
|
|
5411
5429
|
let raw;
|
|
@@ -5457,7 +5475,7 @@ var HistoryService = class {
|
|
|
5457
5475
|
try {
|
|
5458
5476
|
files = fs4.readdirSync(projectDir).filter((f) => f.endsWith(".jsonl")).filter((f) => {
|
|
5459
5477
|
try {
|
|
5460
|
-
return fs4.statSync(
|
|
5478
|
+
return fs4.statSync(path6.join(projectDir, f)).mtimeMs >= monthStartMs;
|
|
5461
5479
|
} catch {
|
|
5462
5480
|
return false;
|
|
5463
5481
|
}
|
|
@@ -5468,7 +5486,7 @@ var HistoryService = class {
|
|
|
5468
5486
|
for (const file of files) {
|
|
5469
5487
|
let raw;
|
|
5470
5488
|
try {
|
|
5471
|
-
raw = fs4.readFileSync(
|
|
5489
|
+
raw = fs4.readFileSync(path6.join(projectDir, file), "utf8");
|
|
5472
5490
|
} catch {
|
|
5473
5491
|
continue;
|
|
5474
5492
|
}
|
|
@@ -5510,8 +5528,8 @@ var HistoryService = class {
|
|
|
5510
5528
|
const sessions2 = [];
|
|
5511
5529
|
for (const entry of entries) {
|
|
5512
5530
|
if (!entry.isFile() || !entry.name.endsWith(".jsonl")) continue;
|
|
5513
|
-
const id =
|
|
5514
|
-
const filePath =
|
|
5531
|
+
const id = path6.basename(entry.name, ".jsonl");
|
|
5532
|
+
const filePath = path6.join(dir, entry.name);
|
|
5515
5533
|
let mtime = Date.now();
|
|
5516
5534
|
try {
|
|
5517
5535
|
mtime = fs4.statSync(filePath).mtimeMs;
|
|
@@ -5552,7 +5570,7 @@ var HistoryService = class {
|
|
|
5552
5570
|
* showing an empty conversation.
|
|
5553
5571
|
*/
|
|
5554
5572
|
async loadConversation(sessionId) {
|
|
5555
|
-
const filePath =
|
|
5573
|
+
const filePath = path6.join(this.projectDir, `${sessionId}.jsonl`);
|
|
5556
5574
|
const messages = parseJsonl(filePath);
|
|
5557
5575
|
if (messages.length === 0) return;
|
|
5558
5576
|
const totalBatches = Math.ceil(messages.length / CONVERSATION_BATCH_SIZE);
|
|
@@ -5608,7 +5626,7 @@ function parsePayload(schema, raw) {
|
|
|
5608
5626
|
|
|
5609
5627
|
// src/services/file-ops.service.ts
|
|
5610
5628
|
var fs5 = __toESM(require("fs/promises"));
|
|
5611
|
-
var
|
|
5629
|
+
var path7 = __toESM(require("path"));
|
|
5612
5630
|
var MAX_FILE_BYTES = 5 * 1024 * 1024;
|
|
5613
5631
|
var MAX_WALK_DEPTH = 6;
|
|
5614
5632
|
var MAX_VISITED_DIRS = 5e3;
|
|
@@ -5643,8 +5661,8 @@ var SUBDIR_IGNORE = /* @__PURE__ */ new Set([
|
|
|
5643
5661
|
"__pycache__"
|
|
5644
5662
|
]);
|
|
5645
5663
|
function isUnder(parent, candidate) {
|
|
5646
|
-
const rel =
|
|
5647
|
-
return rel === "" || !rel.startsWith("..") && !
|
|
5664
|
+
const rel = path7.relative(parent, candidate);
|
|
5665
|
+
return rel === "" || !rel.startsWith("..") && !path7.isAbsolute(rel);
|
|
5648
5666
|
}
|
|
5649
5667
|
async function isExistingFile(absPath) {
|
|
5650
5668
|
try {
|
|
@@ -5667,7 +5685,7 @@ async function walkForSuffix(dir, needleVariants, depth, ctx) {
|
|
|
5667
5685
|
}
|
|
5668
5686
|
for (const e of entries) {
|
|
5669
5687
|
if (!e.isFile()) continue;
|
|
5670
|
-
const full =
|
|
5688
|
+
const full = path7.join(dir, e.name);
|
|
5671
5689
|
if (needleVariants.some((needle) => full.endsWith(needle))) {
|
|
5672
5690
|
ctx.matches.push(full);
|
|
5673
5691
|
if (ctx.matches.length >= ctx.cap) return;
|
|
@@ -5677,21 +5695,21 @@ async function walkForSuffix(dir, needleVariants, depth, ctx) {
|
|
|
5677
5695
|
if (!e.isDirectory()) continue;
|
|
5678
5696
|
if (SUBDIR_IGNORE.has(e.name)) continue;
|
|
5679
5697
|
if (e.name.startsWith(".") && SUBDIR_IGNORE.has(e.name)) continue;
|
|
5680
|
-
await walkForSuffix(
|
|
5698
|
+
await walkForSuffix(path7.join(dir, e.name), needleVariants, depth + 1, ctx);
|
|
5681
5699
|
if (ctx.matches.length >= ctx.cap) return;
|
|
5682
5700
|
}
|
|
5683
5701
|
}
|
|
5684
5702
|
async function findFile(rawPath) {
|
|
5685
5703
|
const cwd = process.cwd();
|
|
5686
|
-
if (
|
|
5687
|
-
const abs =
|
|
5704
|
+
if (path7.isAbsolute(rawPath)) {
|
|
5705
|
+
const abs = path7.normalize(rawPath);
|
|
5688
5706
|
if (isUnder(cwd, abs) && await isExistingFile(abs)) return abs;
|
|
5689
5707
|
}
|
|
5690
|
-
const direct =
|
|
5708
|
+
const direct = path7.resolve(cwd, rawPath);
|
|
5691
5709
|
if (isUnder(cwd, direct) && await isExistingFile(direct)) return direct;
|
|
5692
|
-
const normalized =
|
|
5710
|
+
const normalized = path7.normalize(rawPath).replace(/^[./\\]+/, "");
|
|
5693
5711
|
const needles = [
|
|
5694
|
-
`${
|
|
5712
|
+
`${path7.sep}${normalized}`,
|
|
5695
5713
|
`/${normalized}`
|
|
5696
5714
|
].filter((v, i, a) => a.indexOf(v) === i);
|
|
5697
5715
|
const ctx = { visited: 0, matches: [], cap: 16 };
|
|
@@ -5705,7 +5723,7 @@ async function findWriteTarget(rawPath) {
|
|
|
5705
5723
|
const found = await findFile(rawPath);
|
|
5706
5724
|
if (found) return found;
|
|
5707
5725
|
const cwd = process.cwd();
|
|
5708
|
-
const fallback =
|
|
5726
|
+
const fallback = path7.isAbsolute(rawPath) ? path7.normalize(rawPath) : path7.resolve(cwd, rawPath);
|
|
5709
5727
|
if (!isUnder(cwd, fallback)) return null;
|
|
5710
5728
|
return fallback;
|
|
5711
5729
|
}
|
|
@@ -5745,7 +5763,7 @@ async function writeProjectFile(rawPath, content) {
|
|
|
5745
5763
|
if (Buffer.byteLength(content, "utf-8") > MAX_FILE_BYTES) {
|
|
5746
5764
|
return { error: "Content too large." };
|
|
5747
5765
|
}
|
|
5748
|
-
await fs5.mkdir(
|
|
5766
|
+
await fs5.mkdir(path7.dirname(abs), { recursive: true });
|
|
5749
5767
|
await fs5.writeFile(abs, content, "utf-8");
|
|
5750
5768
|
return { ok: true };
|
|
5751
5769
|
} catch (e) {
|
|
@@ -5758,7 +5776,7 @@ async function writeProjectFile(rawPath, content) {
|
|
|
5758
5776
|
var import_child_process4 = require("child_process");
|
|
5759
5777
|
var import_util = require("util");
|
|
5760
5778
|
var fs6 = __toESM(require("fs/promises"));
|
|
5761
|
-
var
|
|
5779
|
+
var path8 = __toESM(require("path"));
|
|
5762
5780
|
var execFileP = (0, import_util.promisify)(import_child_process4.execFile);
|
|
5763
5781
|
var PROJECT_IGNORE = /* @__PURE__ */ new Set([
|
|
5764
5782
|
"node_modules",
|
|
@@ -5816,12 +5834,12 @@ async function listProjectFiles(opts = {}) {
|
|
|
5816
5834
|
return;
|
|
5817
5835
|
}
|
|
5818
5836
|
if (PROJECT_IGNORE.has(e.name)) continue;
|
|
5819
|
-
const full =
|
|
5837
|
+
const full = path8.join(dir, e.name);
|
|
5820
5838
|
if (e.isDirectory()) {
|
|
5821
5839
|
if (depth >= 12) continue;
|
|
5822
5840
|
await walk(full, depth + 1);
|
|
5823
5841
|
} else if (e.isFile()) {
|
|
5824
|
-
const rel =
|
|
5842
|
+
const rel = path8.relative(root, full);
|
|
5825
5843
|
if (q2 && !rel.toLowerCase().includes(q2) && !e.name.toLowerCase().includes(q2)) {
|
|
5826
5844
|
continue;
|
|
5827
5845
|
}
|
|
@@ -5929,7 +5947,7 @@ async function gitStatus(cwd) {
|
|
|
5929
5947
|
let hasMergeInProgress = false;
|
|
5930
5948
|
try {
|
|
5931
5949
|
const gitDir = (await git(["rev-parse", "--git-dir"], root)).stdout.trim();
|
|
5932
|
-
const mergeHead =
|
|
5950
|
+
const mergeHead = path8.isAbsolute(gitDir) ? path8.join(gitDir, "MERGE_HEAD") : path8.join(root, gitDir, "MERGE_HEAD");
|
|
5933
5951
|
await fs6.access(mergeHead);
|
|
5934
5952
|
hasMergeInProgress = true;
|
|
5935
5953
|
} catch {
|
|
@@ -6007,7 +6025,7 @@ async function gitResolve(file, side, cwd) {
|
|
|
6007
6025
|
function saveFilesTemp(files) {
|
|
6008
6026
|
return files.filter(({ base64 }) => base64 && base64.length > 0).map(({ filename, base64 }) => {
|
|
6009
6027
|
const safeName = filename.replace(/[^a-zA-Z0-9._-]/g, "_").slice(0, 80);
|
|
6010
|
-
const tmpPath =
|
|
6028
|
+
const tmpPath = path9.join(os6.tmpdir(), `codeam-${(0, import_crypto.randomUUID)()}-${safeName}`);
|
|
6011
6029
|
fs7.writeFileSync(tmpPath, Buffer.from(base64, "base64"));
|
|
6012
6030
|
return tmpPath;
|
|
6013
6031
|
});
|
|
@@ -6081,7 +6099,7 @@ try:
|
|
|
6081
6099
|
sys.exit((st>>8)&0xFF)
|
|
6082
6100
|
except Exception:sys.exit(0)
|
|
6083
6101
|
`;
|
|
6084
|
-
const helperPath =
|
|
6102
|
+
const helperPath = path9.join(os6.tmpdir(), "codeam-quota-helper.py");
|
|
6085
6103
|
fs7.writeFileSync(helperPath, helperScript, { mode: 420 });
|
|
6086
6104
|
const python = findInPath("python3") ?? findInPath("python");
|
|
6087
6105
|
if (!python) {
|
|
@@ -6684,7 +6702,7 @@ async function logout() {
|
|
|
6684
6702
|
var import_child_process10 = require("child_process");
|
|
6685
6703
|
var fs8 = __toESM(require("fs"));
|
|
6686
6704
|
var os7 = __toESM(require("os"));
|
|
6687
|
-
var
|
|
6705
|
+
var path14 = __toESM(require("path"));
|
|
6688
6706
|
var import_util6 = require("util");
|
|
6689
6707
|
var import_picocolors9 = __toESM(require("picocolors"));
|
|
6690
6708
|
|
|
@@ -6692,7 +6710,7 @@ var import_picocolors9 = __toESM(require("picocolors"));
|
|
|
6692
6710
|
var import_child_process6 = require("child_process");
|
|
6693
6711
|
var import_util2 = require("util");
|
|
6694
6712
|
var import_picocolors7 = __toESM(require("picocolors"));
|
|
6695
|
-
var
|
|
6713
|
+
var path10 = __toESM(require("path"));
|
|
6696
6714
|
var execFileP2 = (0, import_util2.promisify)(import_child_process6.execFile);
|
|
6697
6715
|
var MAX_BUFFER = 8 * 1024 * 1024;
|
|
6698
6716
|
function resetStdinForChild() {
|
|
@@ -7181,7 +7199,7 @@ var GitHubCodespacesProvider = class {
|
|
|
7181
7199
|
});
|
|
7182
7200
|
}
|
|
7183
7201
|
async uploadFile(workspaceId, remotePath, contents, options = {}) {
|
|
7184
|
-
const remoteDir =
|
|
7202
|
+
const remoteDir = path10.posix.dirname(remotePath);
|
|
7185
7203
|
const parts = [
|
|
7186
7204
|
`mkdir -p ${shellQuote(remoteDir)}`,
|
|
7187
7205
|
`cat > ${shellQuote(remotePath)}`
|
|
@@ -7251,7 +7269,7 @@ function shellQuote(s) {
|
|
|
7251
7269
|
// src/services/providers/gitpod.ts
|
|
7252
7270
|
var import_child_process7 = require("child_process");
|
|
7253
7271
|
var import_util3 = require("util");
|
|
7254
|
-
var
|
|
7272
|
+
var path11 = __toESM(require("path"));
|
|
7255
7273
|
var import_picocolors8 = __toESM(require("picocolors"));
|
|
7256
7274
|
var execFileP3 = (0, import_util3.promisify)(import_child_process7.execFile);
|
|
7257
7275
|
var MAX_BUFFER2 = 8 * 1024 * 1024;
|
|
@@ -7491,7 +7509,7 @@ var GitpodProvider = class {
|
|
|
7491
7509
|
});
|
|
7492
7510
|
}
|
|
7493
7511
|
async uploadFile(workspaceId, remotePath, contents, options = {}) {
|
|
7494
|
-
const remoteDir =
|
|
7512
|
+
const remoteDir = path11.posix.dirname(remotePath);
|
|
7495
7513
|
const parts = [
|
|
7496
7514
|
`mkdir -p ${shellQuote2(remoteDir)}`,
|
|
7497
7515
|
`cat > ${shellQuote2(remotePath)}`
|
|
@@ -7527,7 +7545,7 @@ function shellQuote2(s) {
|
|
|
7527
7545
|
// src/services/providers/gitlab-workspaces.ts
|
|
7528
7546
|
var import_child_process8 = require("child_process");
|
|
7529
7547
|
var import_util4 = require("util");
|
|
7530
|
-
var
|
|
7548
|
+
var path12 = __toESM(require("path"));
|
|
7531
7549
|
var execFileP4 = (0, import_util4.promisify)(import_child_process8.execFile);
|
|
7532
7550
|
var MAX_BUFFER3 = 8 * 1024 * 1024;
|
|
7533
7551
|
var GITLAB_API_BASE = process.env.CODEAM_GITLAB_API_URL ?? "https://gitlab.com/api/v4";
|
|
@@ -7787,7 +7805,7 @@ Docs: https://docs.gitlab.com/ee/user/workspace/configuration.html`
|
|
|
7787
7805
|
}
|
|
7788
7806
|
async uploadFile(workspaceId, remotePath, contents, options = {}) {
|
|
7789
7807
|
const sshHost = process.env.CODEAM_GITLAB_SSH_HOST ?? "workspaces.gitlab.com";
|
|
7790
|
-
const remoteDir =
|
|
7808
|
+
const remoteDir = path12.posix.dirname(remotePath);
|
|
7791
7809
|
const parts = [`mkdir -p ${shellQuote3(remoteDir)}`, `cat > ${shellQuote3(remotePath)}`];
|
|
7792
7810
|
if (options.mode != null) {
|
|
7793
7811
|
parts.push(`chmod ${options.mode.toString(8)} ${shellQuote3(remotePath)}`);
|
|
@@ -7855,7 +7873,7 @@ function shellQuote3(s) {
|
|
|
7855
7873
|
// src/services/providers/railway.ts
|
|
7856
7874
|
var import_child_process9 = require("child_process");
|
|
7857
7875
|
var import_util5 = require("util");
|
|
7858
|
-
var
|
|
7876
|
+
var path13 = __toESM(require("path"));
|
|
7859
7877
|
var execFileP5 = (0, import_util5.promisify)(import_child_process9.execFile);
|
|
7860
7878
|
var MAX_BUFFER4 = 8 * 1024 * 1024;
|
|
7861
7879
|
function resetStdinForChild4() {
|
|
@@ -8091,7 +8109,7 @@ var RailwayProvider = class {
|
|
|
8091
8109
|
if (!projectId || !serviceId) {
|
|
8092
8110
|
throw new Error("Invalid Railway workspace id (expected projectId/serviceId).");
|
|
8093
8111
|
}
|
|
8094
|
-
const remoteDir =
|
|
8112
|
+
const remoteDir = path13.posix.dirname(remotePath);
|
|
8095
8113
|
const parts = [`mkdir -p ${shellQuote4(remoteDir)}`, `cat > ${shellQuote4(remotePath)}`];
|
|
8096
8114
|
if (options.mode != null) {
|
|
8097
8115
|
parts.push(`chmod ${options.mode.toString(8)} ${shellQuote4(remotePath)}`);
|
|
@@ -8283,7 +8301,7 @@ async function deploy() {
|
|
|
8283
8301
|
process.exit(1);
|
|
8284
8302
|
}
|
|
8285
8303
|
}
|
|
8286
|
-
const localClaudeDir =
|
|
8304
|
+
const localClaudeDir = path14.join(os7.homedir(), ".claude");
|
|
8287
8305
|
const localCredsKind = await detectLocalClaudeCredentials(localClaudeDir);
|
|
8288
8306
|
let bridged = "none";
|
|
8289
8307
|
if (localCredsKind !== "none") {
|
|
@@ -8381,7 +8399,7 @@ async function deploy() {
|
|
|
8381
8399
|
}
|
|
8382
8400
|
}
|
|
8383
8401
|
if (bridged !== "none") {
|
|
8384
|
-
const localClaudeJson =
|
|
8402
|
+
const localClaudeJson = path14.join(os7.homedir(), ".claude.json");
|
|
8385
8403
|
if (fs8.existsSync(localClaudeJson)) {
|
|
8386
8404
|
try {
|
|
8387
8405
|
const contents = fs8.readFileSync(localClaudeJson);
|
|
@@ -8574,7 +8592,7 @@ async function runRemoteClaudeLogin(provider, workspaceId) {
|
|
|
8574
8592
|
}
|
|
8575
8593
|
}
|
|
8576
8594
|
async function detectLocalClaudeCredentials(localClaudeDir) {
|
|
8577
|
-
if (fs8.existsSync(
|
|
8595
|
+
if (fs8.existsSync(path14.join(localClaudeDir, ".credentials.json"))) {
|
|
8578
8596
|
return "flat-file";
|
|
8579
8597
|
}
|
|
8580
8598
|
if (process.platform === "darwin") {
|
|
@@ -8607,7 +8625,7 @@ async function verifyClaudeAuth(provider, workspaceId) {
|
|
|
8607
8625
|
}
|
|
8608
8626
|
}
|
|
8609
8627
|
async function bridgeClaudeCredentials(provider, workspaceId, localClaudeDir) {
|
|
8610
|
-
const fileBased =
|
|
8628
|
+
const fileBased = path14.join(localClaudeDir, ".credentials.json");
|
|
8611
8629
|
if (fs8.existsSync(fileBased)) return "flat-file";
|
|
8612
8630
|
if (process.platform === "darwin") {
|
|
8613
8631
|
try {
|