codeam-cli 2.15.8 → 2.16.1
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 +18 -0
- package/dist/index.js +611 -164
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -6,6 +6,9 @@ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
|
6
6
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
7
7
|
var __getProtoOf = Object.getPrototypeOf;
|
|
8
8
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
9
|
+
var __esm = (fn, res) => function __init() {
|
|
10
|
+
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
11
|
+
};
|
|
9
12
|
var __commonJS = (cb, mod) => function __require() {
|
|
10
13
|
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
|
11
14
|
};
|
|
@@ -30,6 +33,38 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
30
33
|
mod
|
|
31
34
|
));
|
|
32
35
|
|
|
36
|
+
// src/services/pty/types.ts
|
|
37
|
+
var types_exports = {};
|
|
38
|
+
__export(types_exports, {
|
|
39
|
+
findInPath: () => findInPath
|
|
40
|
+
});
|
|
41
|
+
function findInPath(name) {
|
|
42
|
+
const isWin = process.platform === "win32";
|
|
43
|
+
const dirs = (process.env.PATH ?? "").split(path3.delimiter).filter(Boolean);
|
|
44
|
+
const hasExt = path3.extname(name).length > 0;
|
|
45
|
+
const candidates = isWin && !hasExt ? [`${name}.exe`, `${name}.cmd`, `${name}.bat`, `${name}.ps1`, name] : [name];
|
|
46
|
+
const accessFlag = isWin ? fs3.constants.F_OK : fs3.constants.X_OK;
|
|
47
|
+
for (const dir of dirs) {
|
|
48
|
+
for (const candidate of candidates) {
|
|
49
|
+
const full = path3.join(dir, candidate);
|
|
50
|
+
try {
|
|
51
|
+
fs3.accessSync(full, accessFlag);
|
|
52
|
+
return full;
|
|
53
|
+
} catch {
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
return null;
|
|
58
|
+
}
|
|
59
|
+
var fs3, path3;
|
|
60
|
+
var init_types = __esm({
|
|
61
|
+
"src/services/pty/types.ts"() {
|
|
62
|
+
"use strict";
|
|
63
|
+
fs3 = __toESM(require("fs"));
|
|
64
|
+
path3 = __toESM(require("path"));
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
|
|
33
68
|
// ../../node_modules/sisteransi/src/index.js
|
|
34
69
|
var require_src = __commonJS({
|
|
35
70
|
"../../node_modules/sisteransi/src/index.js"(exports2, module2) {
|
|
@@ -389,7 +424,7 @@ var import_qrcode_terminal = __toESM(require("qrcode-terminal"));
|
|
|
389
424
|
// package.json
|
|
390
425
|
var package_default = {
|
|
391
426
|
name: "codeam-cli",
|
|
392
|
-
version: "2.
|
|
427
|
+
version: "2.16.1",
|
|
393
428
|
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.",
|
|
394
429
|
type: "commonjs",
|
|
395
430
|
main: "dist/index.js",
|
|
@@ -646,10 +681,86 @@ function pollStatus(pluginId, onPaired, onTimeout) {
|
|
|
646
681
|
}
|
|
647
682
|
var _transport = {
|
|
648
683
|
postJson: _postJson,
|
|
649
|
-
getJson: _getJson
|
|
684
|
+
getJson: _getJson,
|
|
685
|
+
postJsonAuthed: _postJsonAuthed
|
|
650
686
|
};
|
|
687
|
+
async function postLinkCredential(input) {
|
|
688
|
+
const body = {
|
|
689
|
+
sessionId: input.sessionId,
|
|
690
|
+
pluginId: input.pluginId,
|
|
691
|
+
method: input.method,
|
|
692
|
+
credential: input.credential
|
|
693
|
+
};
|
|
694
|
+
if (input.modelPreference) {
|
|
695
|
+
body.modelPreference = input.modelPreference;
|
|
696
|
+
}
|
|
697
|
+
try {
|
|
698
|
+
await _transport.postJsonAuthed(
|
|
699
|
+
`${API_BASE}/api/plugin/agents/${input.agentId}/link`,
|
|
700
|
+
body,
|
|
701
|
+
input.pluginAuthToken
|
|
702
|
+
);
|
|
703
|
+
return { ok: true };
|
|
704
|
+
} catch (err) {
|
|
705
|
+
const e = err;
|
|
706
|
+
return {
|
|
707
|
+
ok: false,
|
|
708
|
+
status: typeof e.statusCode === "number" ? e.statusCode : 0,
|
|
709
|
+
message: e.message || "unknown"
|
|
710
|
+
};
|
|
711
|
+
}
|
|
712
|
+
}
|
|
713
|
+
async function _postJsonAuthed(url, body, pluginAuthToken) {
|
|
714
|
+
return new Promise((resolve3, reject) => {
|
|
715
|
+
const data = JSON.stringify(body);
|
|
716
|
+
const u2 = new URL(url);
|
|
717
|
+
const transport = u2.protocol === "https:" ? https : http;
|
|
718
|
+
const req = transport.request(
|
|
719
|
+
{
|
|
720
|
+
hostname: u2.hostname,
|
|
721
|
+
port: u2.port || (u2.protocol === "https:" ? 443 : 80),
|
|
722
|
+
path: u2.pathname + u2.search,
|
|
723
|
+
method: "POST",
|
|
724
|
+
headers: {
|
|
725
|
+
"Content-Type": "application/json",
|
|
726
|
+
"Content-Length": Buffer.byteLength(data),
|
|
727
|
+
"X-Plugin-Auth-Token": pluginAuthToken,
|
|
728
|
+
...vercelBypassHeader()
|
|
729
|
+
},
|
|
730
|
+
timeout: 15e3
|
|
731
|
+
},
|
|
732
|
+
(res) => {
|
|
733
|
+
res.on("error", reject);
|
|
734
|
+
let responseBody = "";
|
|
735
|
+
res.on("data", (chunk) => {
|
|
736
|
+
responseBody += chunk.toString();
|
|
737
|
+
});
|
|
738
|
+
res.on("end", () => {
|
|
739
|
+
if (res.statusCode && res.statusCode >= 400) {
|
|
740
|
+
const err = new Error(`HTTP ${res.statusCode}: ${responseBody.slice(0, 200)}`);
|
|
741
|
+
err.statusCode = res.statusCode;
|
|
742
|
+
reject(err);
|
|
743
|
+
return;
|
|
744
|
+
}
|
|
745
|
+
try {
|
|
746
|
+
resolve3(JSON.parse(responseBody));
|
|
747
|
+
} catch {
|
|
748
|
+
resolve3(null);
|
|
749
|
+
}
|
|
750
|
+
});
|
|
751
|
+
}
|
|
752
|
+
);
|
|
753
|
+
req.on("error", reject);
|
|
754
|
+
req.on("timeout", () => {
|
|
755
|
+
req.destroy();
|
|
756
|
+
reject(new Error("timeout"));
|
|
757
|
+
});
|
|
758
|
+
req.write(data);
|
|
759
|
+
req.end();
|
|
760
|
+
});
|
|
761
|
+
}
|
|
651
762
|
async function _postJson(url, body) {
|
|
652
|
-
return new Promise((
|
|
763
|
+
return new Promise((resolve3, reject) => {
|
|
653
764
|
const data = JSON.stringify(body);
|
|
654
765
|
const u2 = new URL(url);
|
|
655
766
|
const transport = u2.protocol === "https:" ? https : http;
|
|
@@ -678,9 +789,9 @@ async function _postJson(url, body) {
|
|
|
678
789
|
return;
|
|
679
790
|
}
|
|
680
791
|
try {
|
|
681
|
-
|
|
792
|
+
resolve3(JSON.parse(body2));
|
|
682
793
|
} catch {
|
|
683
|
-
|
|
794
|
+
resolve3(null);
|
|
684
795
|
}
|
|
685
796
|
});
|
|
686
797
|
}
|
|
@@ -695,7 +806,7 @@ async function _postJson(url, body) {
|
|
|
695
806
|
});
|
|
696
807
|
}
|
|
697
808
|
async function _getJson(url) {
|
|
698
|
-
return new Promise((
|
|
809
|
+
return new Promise((resolve3, reject) => {
|
|
699
810
|
const u2 = new URL(url);
|
|
700
811
|
const transport = u2.protocol === "https:" ? https : http;
|
|
701
812
|
const req = transport.request(
|
|
@@ -719,9 +830,9 @@ async function _getJson(url) {
|
|
|
719
830
|
return;
|
|
720
831
|
}
|
|
721
832
|
try {
|
|
722
|
-
|
|
833
|
+
resolve3(JSON.parse(body));
|
|
723
834
|
} catch {
|
|
724
|
-
|
|
835
|
+
resolve3(null);
|
|
725
836
|
}
|
|
726
837
|
});
|
|
727
838
|
}
|
|
@@ -1029,30 +1140,7 @@ var import_child_process2 = require("child_process");
|
|
|
1029
1140
|
var fs4 = __toESM(require("fs"));
|
|
1030
1141
|
var os4 = __toESM(require("os"));
|
|
1031
1142
|
var path4 = __toESM(require("path"));
|
|
1032
|
-
|
|
1033
|
-
// src/services/pty/types.ts
|
|
1034
|
-
var fs3 = __toESM(require("fs"));
|
|
1035
|
-
var path3 = __toESM(require("path"));
|
|
1036
|
-
function findInPath(name) {
|
|
1037
|
-
const isWin = process.platform === "win32";
|
|
1038
|
-
const dirs = (process.env.PATH ?? "").split(path3.delimiter).filter(Boolean);
|
|
1039
|
-
const hasExt = path3.extname(name).length > 0;
|
|
1040
|
-
const candidates = isWin && !hasExt ? [`${name}.exe`, `${name}.cmd`, `${name}.bat`, `${name}.ps1`, name] : [name];
|
|
1041
|
-
const accessFlag = isWin ? fs3.constants.F_OK : fs3.constants.X_OK;
|
|
1042
|
-
for (const dir of dirs) {
|
|
1043
|
-
for (const candidate of candidates) {
|
|
1044
|
-
const full = path3.join(dir, candidate);
|
|
1045
|
-
try {
|
|
1046
|
-
fs3.accessSync(full, accessFlag);
|
|
1047
|
-
return full;
|
|
1048
|
-
} catch {
|
|
1049
|
-
}
|
|
1050
|
-
}
|
|
1051
|
-
}
|
|
1052
|
-
return null;
|
|
1053
|
-
}
|
|
1054
|
-
|
|
1055
|
-
// src/services/pty/unix.strategy.ts
|
|
1143
|
+
init_types();
|
|
1056
1144
|
var PYTHON_PTY_HELPER = `import os,pty,sys,select,signal,struct,fcntl,termios,errno
|
|
1057
1145
|
m,s=pty.openpty()
|
|
1058
1146
|
try:
|
|
@@ -3365,6 +3453,7 @@ ${c2}
|
|
|
3365
3453
|
} }).prompt();
|
|
3366
3454
|
|
|
3367
3455
|
// src/services/claude-installer.ts
|
|
3456
|
+
init_types();
|
|
3368
3457
|
function probeInstallDirs() {
|
|
3369
3458
|
const home = os5.homedir();
|
|
3370
3459
|
if (process.platform === "win32") {
|
|
@@ -3402,15 +3491,15 @@ function runInstaller() {
|
|
|
3402
3491
|
"-Command",
|
|
3403
3492
|
"irm https://claude.ai/install.ps1 | iex"
|
|
3404
3493
|
] : ["-c", "curl -fsSL https://claude.ai/install.sh | bash"];
|
|
3405
|
-
return new Promise((
|
|
3494
|
+
return new Promise((resolve3) => {
|
|
3406
3495
|
const proc = (0, import_child_process4.spawn)(cmd, args2, { stdio: "inherit" });
|
|
3407
3496
|
proc.on("error", (err) => {
|
|
3408
3497
|
console.error(`
|
|
3409
3498
|
\u2717 Installer failed to launch: ${err.message}`);
|
|
3410
|
-
|
|
3499
|
+
resolve3(false);
|
|
3411
3500
|
});
|
|
3412
3501
|
proc.on("exit", (code) => {
|
|
3413
|
-
|
|
3502
|
+
resolve3(code === 0);
|
|
3414
3503
|
});
|
|
3415
3504
|
});
|
|
3416
3505
|
}
|
|
@@ -3444,6 +3533,7 @@ async function ensureClaudeInstalled() {
|
|
|
3444
3533
|
|
|
3445
3534
|
// src/services/claude-resolver.ts
|
|
3446
3535
|
var path7 = __toESM(require("path"));
|
|
3536
|
+
init_types();
|
|
3447
3537
|
function buildClaudeLaunch(extraArgs = []) {
|
|
3448
3538
|
const found = findInPath("claude") ?? findInPath("claude-code");
|
|
3449
3539
|
if (!found) return null;
|
|
@@ -3703,6 +3793,7 @@ var fs5 = __toESM(require("fs"));
|
|
|
3703
3793
|
var os6 = __toESM(require("os"));
|
|
3704
3794
|
var path8 = __toESM(require("path"));
|
|
3705
3795
|
var import_child_process5 = require("child_process");
|
|
3796
|
+
init_types();
|
|
3706
3797
|
var HELPER_SCRIPT = `import os,pty,sys,select,signal,struct,fcntl,termios,errno
|
|
3707
3798
|
m,s=pty.openpty()
|
|
3708
3799
|
try:
|
|
@@ -3758,17 +3849,17 @@ function parseUsageOutput(raw) {
|
|
|
3758
3849
|
return { percent, resetAt };
|
|
3759
3850
|
}
|
|
3760
3851
|
async function fetchClaudeQuota() {
|
|
3761
|
-
return new Promise((
|
|
3852
|
+
return new Promise((resolve3) => {
|
|
3762
3853
|
const claudeCmd = findInPath("claude") ? "claude" : "claude-code";
|
|
3763
3854
|
if (!claudeCmd) {
|
|
3764
|
-
|
|
3855
|
+
resolve3(null);
|
|
3765
3856
|
return;
|
|
3766
3857
|
}
|
|
3767
3858
|
const helperPath = path8.join(os6.tmpdir(), "codeam-quota-helper.py");
|
|
3768
3859
|
fs5.writeFileSync(helperPath, HELPER_SCRIPT, { mode: 420 });
|
|
3769
3860
|
const python = findInPath("python3") ?? findInPath("python");
|
|
3770
3861
|
if (!python) {
|
|
3771
|
-
|
|
3862
|
+
resolve3(null);
|
|
3772
3863
|
return;
|
|
3773
3864
|
}
|
|
3774
3865
|
const proc = (0, import_child_process5.spawn)(python, [helperPath, claudeCmd, "--tools", ""], {
|
|
@@ -3795,13 +3886,13 @@ async function fetchClaudeQuota() {
|
|
|
3795
3886
|
fs5.unlinkSync(helperPath);
|
|
3796
3887
|
} catch {
|
|
3797
3888
|
}
|
|
3798
|
-
|
|
3889
|
+
resolve3(result);
|
|
3799
3890
|
}, 5e3);
|
|
3800
3891
|
}, 8e3);
|
|
3801
3892
|
setTimeout(() => {
|
|
3802
3893
|
if (!resolved) {
|
|
3803
3894
|
resolved = true;
|
|
3804
|
-
|
|
3895
|
+
resolve3(null);
|
|
3805
3896
|
}
|
|
3806
3897
|
try {
|
|
3807
3898
|
proc.kill();
|
|
@@ -4446,6 +4537,7 @@ var ClaudeDeployStrategy = class {
|
|
|
4446
4537
|
|
|
4447
4538
|
// src/agents/codex/runtime.ts
|
|
4448
4539
|
var import_node_child_process = require("child_process");
|
|
4540
|
+
init_types();
|
|
4449
4541
|
|
|
4450
4542
|
// src/agents/codex/history.ts
|
|
4451
4543
|
var import_node_fs2 = __toESM(require("fs"));
|
|
@@ -5040,13 +5132,13 @@ var CodexRuntimeStrategy = class {
|
|
|
5040
5132
|
}
|
|
5041
5133
|
};
|
|
5042
5134
|
async function installCodexViaNpm() {
|
|
5043
|
-
return new Promise((
|
|
5135
|
+
return new Promise((resolve3, reject) => {
|
|
5044
5136
|
const npm = process.platform === "win32" ? "npm.cmd" : "npm";
|
|
5045
5137
|
const proc = (0, import_node_child_process.spawn)(npm, ["install", "-g", "@openai/codex"], {
|
|
5046
5138
|
stdio: "inherit"
|
|
5047
5139
|
});
|
|
5048
5140
|
proc.on("close", (code) => {
|
|
5049
|
-
if (code === 0)
|
|
5141
|
+
if (code === 0) resolve3();
|
|
5050
5142
|
else reject(new Error(`npm install -g @openai/codex exited ${code}`));
|
|
5051
5143
|
});
|
|
5052
5144
|
proc.on("error", reject);
|
|
@@ -5245,14 +5337,14 @@ var ChunkEmitter = class {
|
|
|
5245
5337
|
"chunkEmitter",
|
|
5246
5338
|
`send type=${body.type ?? "(clear)"} bytes=${payload.length} done=${body.done === true}`
|
|
5247
5339
|
);
|
|
5248
|
-
return new Promise((
|
|
5340
|
+
return new Promise((resolve3) => {
|
|
5249
5341
|
const attempt = (attemptsLeft) => {
|
|
5250
5342
|
_transport2.post(this.url, this.headers, payload).then(({ statusCode, body: resBody }) => {
|
|
5251
5343
|
const tookMs = Date.now() - t0;
|
|
5252
5344
|
if (statusCode === 410 || statusCode === 404 && /SESSION_NOT_FOUND|SESSION_GONE/.test(resBody)) {
|
|
5253
5345
|
process.stderr.write("[codeam] session was deleted/disconnected \u2014 stopping output stream.\n");
|
|
5254
5346
|
log.info("chunkEmitter", `dead status=${statusCode} took=${tookMs}ms`);
|
|
5255
|
-
|
|
5347
|
+
resolve3({ dead: true });
|
|
5256
5348
|
return;
|
|
5257
5349
|
}
|
|
5258
5350
|
if (statusCode >= 400) {
|
|
@@ -5262,7 +5354,7 @@ var ChunkEmitter = class {
|
|
|
5262
5354
|
} else {
|
|
5263
5355
|
log.info("chunkEmitter", `ok status=${statusCode} took=${tookMs}ms`);
|
|
5264
5356
|
}
|
|
5265
|
-
|
|
5357
|
+
resolve3({ dead: false });
|
|
5266
5358
|
}).catch((err) => {
|
|
5267
5359
|
log.warn(
|
|
5268
5360
|
"chunkEmitter",
|
|
@@ -5273,7 +5365,7 @@ var ChunkEmitter = class {
|
|
|
5273
5365
|
const delay = 200 * (maxRetries - attemptsLeft + 1);
|
|
5274
5366
|
setTimeout(() => attempt(attemptsLeft - 1), delay);
|
|
5275
5367
|
} else {
|
|
5276
|
-
|
|
5368
|
+
resolve3({ dead: false });
|
|
5277
5369
|
}
|
|
5278
5370
|
});
|
|
5279
5371
|
};
|
|
@@ -5285,7 +5377,7 @@ var _transport2 = {
|
|
|
5285
5377
|
post: _post
|
|
5286
5378
|
};
|
|
5287
5379
|
function _post(url, headers, payload) {
|
|
5288
|
-
return new Promise((
|
|
5380
|
+
return new Promise((resolve3, reject) => {
|
|
5289
5381
|
let settled = false;
|
|
5290
5382
|
const u2 = new URL(url);
|
|
5291
5383
|
const transport = u2.protocol === "https:" ? https3 : http3;
|
|
@@ -5309,7 +5401,7 @@ function _post(url, headers, payload) {
|
|
|
5309
5401
|
res.on("end", () => {
|
|
5310
5402
|
if (settled) return;
|
|
5311
5403
|
settled = true;
|
|
5312
|
-
|
|
5404
|
+
resolve3({ statusCode: res.statusCode ?? 0, body: resData });
|
|
5313
5405
|
});
|
|
5314
5406
|
}
|
|
5315
5407
|
);
|
|
@@ -5745,7 +5837,7 @@ function parseJsonl(filePath) {
|
|
|
5745
5837
|
return messages;
|
|
5746
5838
|
}
|
|
5747
5839
|
function post(endpoint, body) {
|
|
5748
|
-
return new Promise((
|
|
5840
|
+
return new Promise((resolve3) => {
|
|
5749
5841
|
const payload = JSON.stringify(body);
|
|
5750
5842
|
const u2 = new URL(`${API_BASE4}${endpoint}`);
|
|
5751
5843
|
const transport = u2.protocol === "https:" ? https4 : http4;
|
|
@@ -5766,17 +5858,17 @@ function post(endpoint, body) {
|
|
|
5766
5858
|
res.resume();
|
|
5767
5859
|
const ok = res.statusCode !== void 0 && res.statusCode >= 200 && res.statusCode < 300;
|
|
5768
5860
|
if (!ok) log.warn("history:post", `${endpoint} \u2192 HTTP ${res.statusCode}`);
|
|
5769
|
-
|
|
5861
|
+
resolve3(ok);
|
|
5770
5862
|
}
|
|
5771
5863
|
);
|
|
5772
5864
|
req.on("error", (err) => {
|
|
5773
5865
|
log.warn("history:post", `${endpoint} network error`, err);
|
|
5774
|
-
|
|
5866
|
+
resolve3(false);
|
|
5775
5867
|
});
|
|
5776
5868
|
req.on("timeout", () => {
|
|
5777
5869
|
log.warn("history:post", `${endpoint} timeout after 15s`);
|
|
5778
5870
|
req.destroy();
|
|
5779
|
-
|
|
5871
|
+
resolve3(false);
|
|
5780
5872
|
});
|
|
5781
5873
|
req.write(payload);
|
|
5782
5874
|
req.end();
|
|
@@ -6258,7 +6350,7 @@ var _transport3 = {
|
|
|
6258
6350
|
post: _post2
|
|
6259
6351
|
};
|
|
6260
6352
|
function _post2(url, headers, payload) {
|
|
6261
|
-
return new Promise((
|
|
6353
|
+
return new Promise((resolve3, reject) => {
|
|
6262
6354
|
let settled = false;
|
|
6263
6355
|
const u2 = new URL(url);
|
|
6264
6356
|
const lib = u2.protocol === "https:" ? https5 : http5;
|
|
@@ -6283,7 +6375,7 @@ function _post2(url, headers, payload) {
|
|
|
6283
6375
|
res.on("end", () => {
|
|
6284
6376
|
if (settled) return;
|
|
6285
6377
|
settled = true;
|
|
6286
|
-
|
|
6378
|
+
resolve3({ statusCode: res.statusCode ?? 0, body });
|
|
6287
6379
|
});
|
|
6288
6380
|
}
|
|
6289
6381
|
);
|
|
@@ -6327,9 +6419,9 @@ var FileWatcherService = class {
|
|
|
6327
6419
|
if (this.stopped) {
|
|
6328
6420
|
throw new Error("FileWatcherService has already been stopped \u2014 re-instantiate to restart.");
|
|
6329
6421
|
}
|
|
6330
|
-
let
|
|
6422
|
+
let chokidar2;
|
|
6331
6423
|
try {
|
|
6332
|
-
|
|
6424
|
+
chokidar2 = require("chokidar");
|
|
6333
6425
|
} catch (err) {
|
|
6334
6426
|
log.warn(
|
|
6335
6427
|
"fileWatcher",
|
|
@@ -6338,7 +6430,7 @@ var FileWatcherService = class {
|
|
|
6338
6430
|
);
|
|
6339
6431
|
return;
|
|
6340
6432
|
}
|
|
6341
|
-
const watcher =
|
|
6433
|
+
const watcher = chokidar2.watch(this.opts.workingDir, {
|
|
6342
6434
|
ignored: [
|
|
6343
6435
|
/(^|[\\/])\../,
|
|
6344
6436
|
// dot-files & dot-dirs (.git, .next, .expo, .DS_Store, …)
|
|
@@ -6591,12 +6683,12 @@ var _gitSeam = {
|
|
|
6591
6683
|
run: _runGitImpl
|
|
6592
6684
|
};
|
|
6593
6685
|
async function _runGitImpl(cwd, args2, opts = {}) {
|
|
6594
|
-
return new Promise((
|
|
6686
|
+
return new Promise((resolve3) => {
|
|
6595
6687
|
let proc;
|
|
6596
6688
|
try {
|
|
6597
6689
|
proc = (0, import_child_process7.spawn)("git", args2, { cwd, env: process.env });
|
|
6598
6690
|
} catch {
|
|
6599
|
-
|
|
6691
|
+
resolve3(null);
|
|
6600
6692
|
return;
|
|
6601
6693
|
}
|
|
6602
6694
|
let stdout = "";
|
|
@@ -6607,13 +6699,13 @@ async function _runGitImpl(cwd, args2, opts = {}) {
|
|
|
6607
6699
|
proc.stderr?.on("data", (c2) => {
|
|
6608
6700
|
stderr += c2.toString();
|
|
6609
6701
|
});
|
|
6610
|
-
proc.on("error", () =>
|
|
6702
|
+
proc.on("error", () => resolve3(null));
|
|
6611
6703
|
proc.on("close", (code) => {
|
|
6612
6704
|
if (code === 0 || opts.allowNonZeroExit) {
|
|
6613
|
-
|
|
6705
|
+
resolve3(stdout);
|
|
6614
6706
|
} else {
|
|
6615
6707
|
log.trace("fileWatcher", `git ${args2.join(" ")} exited ${code} stderr=${stderr.slice(0, 200)}`);
|
|
6616
|
-
|
|
6708
|
+
resolve3(null);
|
|
6617
6709
|
}
|
|
6618
6710
|
});
|
|
6619
6711
|
});
|
|
@@ -6633,7 +6725,7 @@ var _transport4 = {
|
|
|
6633
6725
|
get: _get
|
|
6634
6726
|
};
|
|
6635
6727
|
function _post3(url, headers, payload) {
|
|
6636
|
-
return new Promise((
|
|
6728
|
+
return new Promise((resolve3, reject) => {
|
|
6637
6729
|
let settled = false;
|
|
6638
6730
|
const u2 = new URL(url);
|
|
6639
6731
|
const lib = u2.protocol === "https:" ? https6 : http6;
|
|
@@ -6658,7 +6750,7 @@ function _post3(url, headers, payload) {
|
|
|
6658
6750
|
res.on("end", () => {
|
|
6659
6751
|
if (settled) return;
|
|
6660
6752
|
settled = true;
|
|
6661
|
-
|
|
6753
|
+
resolve3({ statusCode: res.statusCode ?? 0, body });
|
|
6662
6754
|
});
|
|
6663
6755
|
}
|
|
6664
6756
|
);
|
|
@@ -6675,7 +6767,7 @@ function _post3(url, headers, payload) {
|
|
|
6675
6767
|
});
|
|
6676
6768
|
}
|
|
6677
6769
|
function _get(url, headers) {
|
|
6678
|
-
return new Promise((
|
|
6770
|
+
return new Promise((resolve3, reject) => {
|
|
6679
6771
|
let settled = false;
|
|
6680
6772
|
const u2 = new URL(url);
|
|
6681
6773
|
const lib = u2.protocol === "https:" ? https6 : http6;
|
|
@@ -6699,7 +6791,7 @@ function _get(url, headers) {
|
|
|
6699
6791
|
res.on("end", () => {
|
|
6700
6792
|
if (settled) return;
|
|
6701
6793
|
settled = true;
|
|
6702
|
-
|
|
6794
|
+
resolve3({ statusCode: res.statusCode ?? 0, body });
|
|
6703
6795
|
});
|
|
6704
6796
|
}
|
|
6705
6797
|
);
|
|
@@ -7068,7 +7160,7 @@ function buildKeepAlive(ctx) {
|
|
|
7068
7160
|
let timer = null;
|
|
7069
7161
|
async function setIdleTimeout(minutes) {
|
|
7070
7162
|
if (!ctx.inCodespace || !ctx.codespaceName) return;
|
|
7071
|
-
await new Promise((
|
|
7163
|
+
await new Promise((resolve3) => {
|
|
7072
7164
|
const proc = (0, import_child_process8.spawn)(
|
|
7073
7165
|
"gh",
|
|
7074
7166
|
[
|
|
@@ -7082,8 +7174,8 @@ function buildKeepAlive(ctx) {
|
|
|
7082
7174
|
{ stdio: "ignore", detached: true }
|
|
7083
7175
|
);
|
|
7084
7176
|
proc.unref();
|
|
7085
|
-
proc.on("exit", () =>
|
|
7086
|
-
proc.on("error", () =>
|
|
7177
|
+
proc.on("exit", () => resolve3());
|
|
7178
|
+
proc.on("error", () => resolve3());
|
|
7087
7179
|
});
|
|
7088
7180
|
}
|
|
7089
7181
|
return {
|
|
@@ -8461,7 +8553,7 @@ async function pair(args2 = []) {
|
|
|
8461
8553
|
waitSpin.message(waitMessage());
|
|
8462
8554
|
}, 1e3);
|
|
8463
8555
|
countdownInterval.unref?.();
|
|
8464
|
-
await new Promise((
|
|
8556
|
+
await new Promise((resolve3) => {
|
|
8465
8557
|
let stopPolling = null;
|
|
8466
8558
|
function sigintHandler() {
|
|
8467
8559
|
clearInterval(countdownInterval);
|
|
@@ -8488,7 +8580,7 @@ async function pair(args2 = []) {
|
|
|
8488
8580
|
saveCliConfig({ ...loadCliConfig(), preferredAgent: agentId });
|
|
8489
8581
|
showSuccess(`Paired with ${info.userName} (${info.plan})`);
|
|
8490
8582
|
console.log("");
|
|
8491
|
-
|
|
8583
|
+
resolve3();
|
|
8492
8584
|
},
|
|
8493
8585
|
() => {
|
|
8494
8586
|
clearInterval(countdownInterval);
|
|
@@ -8521,12 +8613,12 @@ function readTokenFromArgs(args2) {
|
|
|
8521
8613
|
}
|
|
8522
8614
|
const fileFlag = args2.find((a) => a.startsWith("--token-file="));
|
|
8523
8615
|
if (fileFlag) {
|
|
8524
|
-
const
|
|
8616
|
+
const path28 = fileFlag.slice("--token-file=".length);
|
|
8525
8617
|
try {
|
|
8526
|
-
const content = fs15.readFileSync(
|
|
8527
|
-
if (content.length === 0) fail(`--token-file ${
|
|
8618
|
+
const content = fs15.readFileSync(path28, "utf8").trim();
|
|
8619
|
+
if (content.length === 0) fail(`--token-file ${path28} is empty`);
|
|
8528
8620
|
try {
|
|
8529
|
-
fs15.unlinkSync(
|
|
8621
|
+
fs15.unlinkSync(path28);
|
|
8530
8622
|
} catch {
|
|
8531
8623
|
}
|
|
8532
8624
|
return content;
|
|
@@ -8744,12 +8836,12 @@ var GitHubCodespacesProvider = class {
|
|
|
8744
8836
|
}
|
|
8745
8837
|
if (!isAuthed) {
|
|
8746
8838
|
resetStdinForChild();
|
|
8747
|
-
await new Promise((
|
|
8839
|
+
await new Promise((resolve3, reject) => {
|
|
8748
8840
|
const proc = (0, import_child_process12.spawn)("gh", ["auth", "login", "-s", "codespace,repo,read:user"], {
|
|
8749
8841
|
stdio: "inherit"
|
|
8750
8842
|
});
|
|
8751
8843
|
proc.on("exit", (code) => {
|
|
8752
|
-
if (code === 0)
|
|
8844
|
+
if (code === 0) resolve3();
|
|
8753
8845
|
else reject(new Error("gh auth login failed."));
|
|
8754
8846
|
});
|
|
8755
8847
|
proc.on("error", reject);
|
|
@@ -8778,13 +8870,13 @@ var GitHubCodespacesProvider = class {
|
|
|
8778
8870
|
}
|
|
8779
8871
|
wt(noteLines.join("\n"), "One more permission needed");
|
|
8780
8872
|
resetStdinForChild();
|
|
8781
|
-
const refreshCode = await new Promise((
|
|
8873
|
+
const refreshCode = await new Promise((resolve3, reject) => {
|
|
8782
8874
|
const proc = (0, import_child_process12.spawn)(
|
|
8783
8875
|
"gh",
|
|
8784
8876
|
["auth", "refresh", "-h", "github.com", "-s", "codespace"],
|
|
8785
8877
|
{ stdio: "inherit" }
|
|
8786
8878
|
);
|
|
8787
|
-
proc.on("exit", (code) =>
|
|
8879
|
+
proc.on("exit", (code) => resolve3(code ?? 1));
|
|
8788
8880
|
proc.on("error", reject);
|
|
8789
8881
|
});
|
|
8790
8882
|
if (refreshCode !== 0) {
|
|
@@ -8928,10 +9020,10 @@ var GitHubCodespacesProvider = class {
|
|
|
8928
9020
|
if (q(proceed) || !proceed) return;
|
|
8929
9021
|
O2.step(`Installing gh via ${installCmd.describe}\u2026`);
|
|
8930
9022
|
resetStdinForChild();
|
|
8931
|
-
const ok = await new Promise((
|
|
9023
|
+
const ok = await new Promise((resolve3) => {
|
|
8932
9024
|
const proc = (0, import_child_process12.spawn)(installCmd.exe, installCmd.args, { stdio: "inherit" });
|
|
8933
|
-
proc.on("exit", (code) =>
|
|
8934
|
-
proc.on("error", () =>
|
|
9025
|
+
proc.on("exit", (code) => resolve3(code === 0));
|
|
9026
|
+
proc.on("error", () => resolve3(false));
|
|
8935
9027
|
});
|
|
8936
9028
|
if (ok) O2.success("gh installed");
|
|
8937
9029
|
else O2.error("gh install failed");
|
|
@@ -8955,14 +9047,14 @@ var GitHubCodespacesProvider = class {
|
|
|
8955
9047
|
"Expanding GitHub scopes"
|
|
8956
9048
|
);
|
|
8957
9049
|
resetStdinForChild();
|
|
8958
|
-
await new Promise((
|
|
9050
|
+
await new Promise((resolve3, reject) => {
|
|
8959
9051
|
const proc = (0, import_child_process12.spawn)(
|
|
8960
9052
|
"gh",
|
|
8961
9053
|
["auth", "refresh", "-h", "github.com", "-s", "repo,read:org"],
|
|
8962
9054
|
{ stdio: "inherit" }
|
|
8963
9055
|
);
|
|
8964
9056
|
proc.on("exit", (code) => {
|
|
8965
|
-
if (code === 0)
|
|
9057
|
+
if (code === 0) resolve3();
|
|
8966
9058
|
else reject(new Error(
|
|
8967
9059
|
"gh auth refresh failed. Re-run `gh auth refresh -h github.com -s repo,read:org` manually."
|
|
8968
9060
|
));
|
|
@@ -9133,13 +9225,13 @@ var GitHubCodespacesProvider = class {
|
|
|
9133
9225
|
}
|
|
9134
9226
|
async streamCommand(workspaceId, command2) {
|
|
9135
9227
|
resetStdinForChild();
|
|
9136
|
-
return new Promise((
|
|
9228
|
+
return new Promise((resolve3, reject) => {
|
|
9137
9229
|
const proc = (0, import_child_process12.spawn)(
|
|
9138
9230
|
"gh",
|
|
9139
9231
|
["codespace", "ssh", "-c", workspaceId, "--", "-tt", command2],
|
|
9140
9232
|
{ stdio: "inherit" }
|
|
9141
9233
|
);
|
|
9142
|
-
proc.on("exit", (code) =>
|
|
9234
|
+
proc.on("exit", (code) => resolve3({ code: code ?? 0 }));
|
|
9143
9235
|
proc.on("error", reject);
|
|
9144
9236
|
});
|
|
9145
9237
|
}
|
|
@@ -9160,7 +9252,7 @@ var GitHubCodespacesProvider = class {
|
|
|
9160
9252
|
"--",
|
|
9161
9253
|
`mkdir -p ${shellQuote(remoteDir)} && tar -xzf - -C ${shellQuote(remoteDir)}`
|
|
9162
9254
|
];
|
|
9163
|
-
await new Promise((
|
|
9255
|
+
await new Promise((resolve3, reject) => {
|
|
9164
9256
|
const tar = (0, import_child_process12.spawn)("tar", tarArgs, {
|
|
9165
9257
|
stdio: ["ignore", "pipe", "pipe"],
|
|
9166
9258
|
env: tarEnv
|
|
@@ -9180,7 +9272,7 @@ var GitHubCodespacesProvider = class {
|
|
|
9180
9272
|
ssh.on("error", reject);
|
|
9181
9273
|
ssh.on("exit", (code) => {
|
|
9182
9274
|
if (code === 0) {
|
|
9183
|
-
|
|
9275
|
+
resolve3();
|
|
9184
9276
|
} else {
|
|
9185
9277
|
const reason = (sshErr || tarErr || `exit ${code}`).trim().slice(0, 500);
|
|
9186
9278
|
reject(new Error(`Remote tar failed: ${reason}`));
|
|
@@ -9198,7 +9290,7 @@ var GitHubCodespacesProvider = class {
|
|
|
9198
9290
|
parts.push(`chmod ${options.mode.toString(8)} ${shellQuote(remotePath)}`);
|
|
9199
9291
|
}
|
|
9200
9292
|
const cmd = parts.join(" && ");
|
|
9201
|
-
await new Promise((
|
|
9293
|
+
await new Promise((resolve3, reject) => {
|
|
9202
9294
|
const proc = (0, import_child_process12.spawn)(
|
|
9203
9295
|
"gh",
|
|
9204
9296
|
["codespace", "ssh", "-c", workspaceId, "--", cmd],
|
|
@@ -9210,7 +9302,7 @@ var GitHubCodespacesProvider = class {
|
|
|
9210
9302
|
});
|
|
9211
9303
|
proc.on("error", reject);
|
|
9212
9304
|
proc.on("exit", (code) => {
|
|
9213
|
-
if (code === 0)
|
|
9305
|
+
if (code === 0) resolve3();
|
|
9214
9306
|
else reject(new Error(`Remote write failed: ${(stderr || `exit ${code}`).trim().slice(0, 500)}`));
|
|
9215
9307
|
});
|
|
9216
9308
|
proc.stdin?.write(contents);
|
|
@@ -9300,10 +9392,10 @@ var GitpodProvider = class {
|
|
|
9300
9392
|
"Authenticating Gitpod"
|
|
9301
9393
|
);
|
|
9302
9394
|
resetStdinForChild2();
|
|
9303
|
-
await new Promise((
|
|
9395
|
+
await new Promise((resolve3, reject) => {
|
|
9304
9396
|
const proc = (0, import_child_process13.spawn)("gitpod", ["login"], { stdio: "inherit" });
|
|
9305
9397
|
proc.on("exit", (code) => {
|
|
9306
|
-
if (code === 0)
|
|
9398
|
+
if (code === 0) resolve3();
|
|
9307
9399
|
else reject(new Error("gitpod login failed."));
|
|
9308
9400
|
});
|
|
9309
9401
|
proc.on("error", reject);
|
|
@@ -9452,13 +9544,13 @@ var GitpodProvider = class {
|
|
|
9452
9544
|
}
|
|
9453
9545
|
async streamCommand(workspaceId, command2) {
|
|
9454
9546
|
resetStdinForChild2();
|
|
9455
|
-
return new Promise((
|
|
9547
|
+
return new Promise((resolve3, reject) => {
|
|
9456
9548
|
const proc = (0, import_child_process13.spawn)(
|
|
9457
9549
|
"gitpod",
|
|
9458
9550
|
["workspace", "ssh", workspaceId, "--", "-tt", command2],
|
|
9459
9551
|
{ stdio: "inherit" }
|
|
9460
9552
|
);
|
|
9461
|
-
proc.on("exit", (code) =>
|
|
9553
|
+
proc.on("exit", (code) => resolve3({ code: code ?? 0 }));
|
|
9462
9554
|
proc.on("error", reject);
|
|
9463
9555
|
});
|
|
9464
9556
|
}
|
|
@@ -9472,7 +9564,7 @@ var GitpodProvider = class {
|
|
|
9472
9564
|
tarArgs.push(".");
|
|
9473
9565
|
const tarEnv = { ...process.env, COPYFILE_DISABLE: "1" };
|
|
9474
9566
|
const remoteCmd = `mkdir -p ${shellQuote2(remoteDir)} && tar -xzf - -C ${shellQuote2(remoteDir)}`;
|
|
9475
|
-
await new Promise((
|
|
9567
|
+
await new Promise((resolve3, reject) => {
|
|
9476
9568
|
const tar = (0, import_child_process13.spawn)("tar", tarArgs, {
|
|
9477
9569
|
stdio: ["ignore", "pipe", "pipe"],
|
|
9478
9570
|
env: tarEnv
|
|
@@ -9493,7 +9585,7 @@ var GitpodProvider = class {
|
|
|
9493
9585
|
tar.on("error", reject);
|
|
9494
9586
|
ssh.on("error", reject);
|
|
9495
9587
|
ssh.on("exit", (code) => {
|
|
9496
|
-
if (code === 0)
|
|
9588
|
+
if (code === 0) resolve3();
|
|
9497
9589
|
else reject(new Error(`Remote tar failed: ${(sshErr || tarErr || `exit ${code}`).trim().slice(0, 500)}`));
|
|
9498
9590
|
});
|
|
9499
9591
|
});
|
|
@@ -9508,7 +9600,7 @@ var GitpodProvider = class {
|
|
|
9508
9600
|
parts.push(`chmod ${options.mode.toString(8)} ${shellQuote2(remotePath)}`);
|
|
9509
9601
|
}
|
|
9510
9602
|
const cmd = parts.join(" && ");
|
|
9511
|
-
await new Promise((
|
|
9603
|
+
await new Promise((resolve3, reject) => {
|
|
9512
9604
|
const proc = (0, import_child_process13.spawn)(
|
|
9513
9605
|
"gitpod",
|
|
9514
9606
|
["workspace", "ssh", workspaceId, "--", cmd],
|
|
@@ -9520,7 +9612,7 @@ var GitpodProvider = class {
|
|
|
9520
9612
|
});
|
|
9521
9613
|
proc.on("error", reject);
|
|
9522
9614
|
proc.on("exit", (code) => {
|
|
9523
|
-
if (code === 0)
|
|
9615
|
+
if (code === 0) resolve3();
|
|
9524
9616
|
else reject(new Error(`Remote write failed: ${(stderr || `exit ${code}`).trim().slice(0, 500)}`));
|
|
9525
9617
|
});
|
|
9526
9618
|
proc.stdin?.write(contents);
|
|
@@ -9577,14 +9669,14 @@ var GitLabWorkspacesProvider = class {
|
|
|
9577
9669
|
"Authenticating GitLab"
|
|
9578
9670
|
);
|
|
9579
9671
|
resetStdinForChild3();
|
|
9580
|
-
await new Promise((
|
|
9672
|
+
await new Promise((resolve3, reject) => {
|
|
9581
9673
|
const proc = (0, import_child_process14.spawn)(
|
|
9582
9674
|
"glab",
|
|
9583
9675
|
["auth", "login", "--scopes", "api,read_user,read_repository"],
|
|
9584
9676
|
{ stdio: "inherit" }
|
|
9585
9677
|
);
|
|
9586
9678
|
proc.on("exit", (code) => {
|
|
9587
|
-
if (code === 0)
|
|
9679
|
+
if (code === 0) resolve3();
|
|
9588
9680
|
else reject(new Error("glab auth login failed."));
|
|
9589
9681
|
});
|
|
9590
9682
|
proc.on("error", reject);
|
|
@@ -9749,13 +9841,13 @@ Docs: https://docs.gitlab.com/ee/user/workspace/configuration.html`
|
|
|
9749
9841
|
async streamCommand(workspaceId, command2) {
|
|
9750
9842
|
const sshHost = process.env.CODEAM_GITLAB_SSH_HOST ?? "workspaces.gitlab.com";
|
|
9751
9843
|
resetStdinForChild3();
|
|
9752
|
-
return new Promise((
|
|
9844
|
+
return new Promise((resolve3, reject) => {
|
|
9753
9845
|
const proc = (0, import_child_process14.spawn)(
|
|
9754
9846
|
"ssh",
|
|
9755
9847
|
["-tt", "-o", "StrictHostKeyChecking=accept-new", `${workspaceId}@${sshHost}`, command2],
|
|
9756
9848
|
{ stdio: "inherit" }
|
|
9757
9849
|
);
|
|
9758
|
-
proc.on("exit", (code) =>
|
|
9850
|
+
proc.on("exit", (code) => resolve3({ code: code ?? 0 }));
|
|
9759
9851
|
proc.on("error", reject);
|
|
9760
9852
|
});
|
|
9761
9853
|
}
|
|
@@ -9770,7 +9862,7 @@ Docs: https://docs.gitlab.com/ee/user/workspace/configuration.html`
|
|
|
9770
9862
|
tarArgs.push(".");
|
|
9771
9863
|
const tarEnv = { ...process.env, COPYFILE_DISABLE: "1" };
|
|
9772
9864
|
const remoteCmd = `mkdir -p ${shellQuote3(remoteDir)} && tar -xzf - -C ${shellQuote3(remoteDir)}`;
|
|
9773
|
-
await new Promise((
|
|
9865
|
+
await new Promise((resolve3, reject) => {
|
|
9774
9866
|
const tar = (0, import_child_process14.spawn)("tar", tarArgs, { stdio: ["ignore", "pipe", "pipe"], env: tarEnv });
|
|
9775
9867
|
const ssh = (0, import_child_process14.spawn)(
|
|
9776
9868
|
"ssh",
|
|
@@ -9788,7 +9880,7 @@ Docs: https://docs.gitlab.com/ee/user/workspace/configuration.html`
|
|
|
9788
9880
|
tar.on("error", reject);
|
|
9789
9881
|
ssh.on("error", reject);
|
|
9790
9882
|
ssh.on("exit", (code) => {
|
|
9791
|
-
if (code === 0)
|
|
9883
|
+
if (code === 0) resolve3();
|
|
9792
9884
|
else reject(new Error(`Remote tar failed: ${(sshErr || tarErr || `exit ${code}`).trim().slice(0, 500)}`));
|
|
9793
9885
|
});
|
|
9794
9886
|
});
|
|
@@ -9801,7 +9893,7 @@ Docs: https://docs.gitlab.com/ee/user/workspace/configuration.html`
|
|
|
9801
9893
|
parts.push(`chmod ${options.mode.toString(8)} ${shellQuote3(remotePath)}`);
|
|
9802
9894
|
}
|
|
9803
9895
|
const cmd = parts.join(" && ");
|
|
9804
|
-
await new Promise((
|
|
9896
|
+
await new Promise((resolve3, reject) => {
|
|
9805
9897
|
const proc = (0, import_child_process14.spawn)(
|
|
9806
9898
|
"ssh",
|
|
9807
9899
|
["-o", "StrictHostKeyChecking=accept-new", `${workspaceId}@${sshHost}`, cmd],
|
|
@@ -9813,7 +9905,7 @@ Docs: https://docs.gitlab.com/ee/user/workspace/configuration.html`
|
|
|
9813
9905
|
});
|
|
9814
9906
|
proc.on("error", reject);
|
|
9815
9907
|
proc.on("exit", (code) => {
|
|
9816
|
-
if (code === 0)
|
|
9908
|
+
if (code === 0) resolve3();
|
|
9817
9909
|
else reject(new Error(`Remote write failed: ${(stderr || `exit ${code}`).trim().slice(0, 500)}`));
|
|
9818
9910
|
});
|
|
9819
9911
|
proc.stdin?.write(contents);
|
|
@@ -9904,10 +9996,10 @@ var RailwayProvider = class {
|
|
|
9904
9996
|
"Authenticating Railway"
|
|
9905
9997
|
);
|
|
9906
9998
|
resetStdinForChild4();
|
|
9907
|
-
await new Promise((
|
|
9999
|
+
await new Promise((resolve3, reject) => {
|
|
9908
10000
|
const proc = (0, import_child_process15.spawn)("railway", ["login"], { stdio: "inherit" });
|
|
9909
10001
|
proc.on("exit", (code) => {
|
|
9910
|
-
if (code === 0)
|
|
10002
|
+
if (code === 0) resolve3();
|
|
9911
10003
|
else reject(new Error("railway login failed."));
|
|
9912
10004
|
});
|
|
9913
10005
|
proc.on("error", reject);
|
|
@@ -10047,13 +10139,13 @@ var RailwayProvider = class {
|
|
|
10047
10139
|
throw new Error("Invalid Railway workspace id (expected projectId/serviceId).");
|
|
10048
10140
|
}
|
|
10049
10141
|
resetStdinForChild4();
|
|
10050
|
-
return new Promise((
|
|
10142
|
+
return new Promise((resolve3, reject) => {
|
|
10051
10143
|
const proc = (0, import_child_process15.spawn)(
|
|
10052
10144
|
"railway",
|
|
10053
10145
|
["shell", "--project", projectId, "--service", serviceId, "--command", command2],
|
|
10054
10146
|
{ stdio: "inherit" }
|
|
10055
10147
|
);
|
|
10056
|
-
proc.on("exit", (code) =>
|
|
10148
|
+
proc.on("exit", (code) => resolve3({ code: code ?? 0 }));
|
|
10057
10149
|
proc.on("error", reject);
|
|
10058
10150
|
});
|
|
10059
10151
|
}
|
|
@@ -10071,7 +10163,7 @@ var RailwayProvider = class {
|
|
|
10071
10163
|
tarArgs.push(".");
|
|
10072
10164
|
const tarEnv = { ...process.env, COPYFILE_DISABLE: "1" };
|
|
10073
10165
|
const remoteCmd = `mkdir -p ${shellQuote4(remoteDir)} && tar -xzf - -C ${shellQuote4(remoteDir)}`;
|
|
10074
|
-
await new Promise((
|
|
10166
|
+
await new Promise((resolve3, reject) => {
|
|
10075
10167
|
const tar = (0, import_child_process15.spawn)("tar", tarArgs, { stdio: ["ignore", "pipe", "pipe"], env: tarEnv });
|
|
10076
10168
|
const sh = (0, import_child_process15.spawn)(
|
|
10077
10169
|
"railway",
|
|
@@ -10089,7 +10181,7 @@ var RailwayProvider = class {
|
|
|
10089
10181
|
tar.on("error", reject);
|
|
10090
10182
|
sh.on("error", reject);
|
|
10091
10183
|
sh.on("exit", (code) => {
|
|
10092
|
-
if (code === 0)
|
|
10184
|
+
if (code === 0) resolve3();
|
|
10093
10185
|
else reject(new Error(`Remote tar failed: ${(shErr || tarErr || `exit ${code}`).trim().slice(0, 500)}`));
|
|
10094
10186
|
});
|
|
10095
10187
|
});
|
|
@@ -10105,7 +10197,7 @@ var RailwayProvider = class {
|
|
|
10105
10197
|
parts.push(`chmod ${options.mode.toString(8)} ${shellQuote4(remotePath)}`);
|
|
10106
10198
|
}
|
|
10107
10199
|
const cmd = parts.join(" && ");
|
|
10108
|
-
await new Promise((
|
|
10200
|
+
await new Promise((resolve3, reject) => {
|
|
10109
10201
|
const proc = (0, import_child_process15.spawn)(
|
|
10110
10202
|
"railway",
|
|
10111
10203
|
["shell", "--project", projectId, "--service", serviceId, "--command", cmd],
|
|
@@ -10117,7 +10209,7 @@ var RailwayProvider = class {
|
|
|
10117
10209
|
});
|
|
10118
10210
|
proc.on("error", reject);
|
|
10119
10211
|
proc.on("exit", (code) => {
|
|
10120
|
-
if (code === 0)
|
|
10212
|
+
if (code === 0) resolve3();
|
|
10121
10213
|
else reject(new Error(`Remote write failed: ${(stderr || `exit ${code}`).trim().slice(0, 500)}`));
|
|
10122
10214
|
});
|
|
10123
10215
|
proc.stdin?.write(contents);
|
|
@@ -10630,74 +10722,427 @@ async function probeCodeamPair(provider, workspace) {
|
|
|
10630
10722
|
}
|
|
10631
10723
|
async function stopWorkspaceFromLocal(target) {
|
|
10632
10724
|
if (target.provider.id === "github-codespaces") {
|
|
10633
|
-
const { execFile:
|
|
10634
|
-
const { promisify:
|
|
10635
|
-
const
|
|
10636
|
-
await
|
|
10725
|
+
const { execFile: execFile8 } = await import("child_process");
|
|
10726
|
+
const { promisify: promisify8 } = await import("util");
|
|
10727
|
+
const execFileP8 = promisify8(execFile8);
|
|
10728
|
+
await execFileP8("gh", ["codespace", "stop", "-c", target.id], { maxBuffer: 8 * 1024 * 1024 });
|
|
10637
10729
|
return;
|
|
10638
10730
|
}
|
|
10639
10731
|
}
|
|
10640
10732
|
|
|
10641
|
-
// src/commands/
|
|
10733
|
+
// src/commands/link.ts
|
|
10734
|
+
var import_node_child_process3 = require("child_process");
|
|
10735
|
+
var import_node_crypto = require("crypto");
|
|
10736
|
+
var fs18 = __toESM(require("fs"));
|
|
10737
|
+
var path26 = __toESM(require("path"));
|
|
10738
|
+
var import_chokidar = __toESM(require("chokidar"));
|
|
10642
10739
|
var import_picocolors11 = __toESM(require("picocolors"));
|
|
10740
|
+
|
|
10741
|
+
// src/agents/claude/local-token.ts
|
|
10742
|
+
var import_node_child_process2 = require("child_process");
|
|
10743
|
+
var fs16 = __toESM(require("fs"));
|
|
10744
|
+
var os15 = __toESM(require("os"));
|
|
10745
|
+
var path24 = __toESM(require("path"));
|
|
10746
|
+
var import_node_util3 = require("util");
|
|
10747
|
+
var execFileP7 = (0, import_node_util3.promisify)(import_node_child_process2.execFile);
|
|
10748
|
+
var KEYCHAIN_SERVICE_NAMES = [
|
|
10749
|
+
"Claude Code-credentials",
|
|
10750
|
+
"claude-code-credentials",
|
|
10751
|
+
"Claude",
|
|
10752
|
+
"Anthropic Claude"
|
|
10753
|
+
];
|
|
10754
|
+
function claudeCredentialsPaths() {
|
|
10755
|
+
const home = os15.homedir();
|
|
10756
|
+
return [
|
|
10757
|
+
path24.join(home, ".claude", ".credentials.json"),
|
|
10758
|
+
path24.join(home, ".config", "claude", ".credentials.json")
|
|
10759
|
+
];
|
|
10760
|
+
}
|
|
10761
|
+
async function extractLocalClaudeToken() {
|
|
10762
|
+
for (const flat of claudeCredentialsPaths()) {
|
|
10763
|
+
if (!fs16.existsSync(flat)) continue;
|
|
10764
|
+
const credential = fs16.readFileSync(flat, "utf8").trim();
|
|
10765
|
+
if (credential.length > 0) {
|
|
10766
|
+
return { method: "oauth", credential, source: "flat-file" };
|
|
10767
|
+
}
|
|
10768
|
+
}
|
|
10769
|
+
if (process.platform === "darwin") {
|
|
10770
|
+
for (const service of KEYCHAIN_SERVICE_NAMES) {
|
|
10771
|
+
try {
|
|
10772
|
+
const { stdout } = await execFileP7(
|
|
10773
|
+
"security",
|
|
10774
|
+
["find-generic-password", "-s", service, "-w"],
|
|
10775
|
+
{ maxBuffer: 1024 * 1024 }
|
|
10776
|
+
);
|
|
10777
|
+
const credential = stdout.trim();
|
|
10778
|
+
if (credential.length > 0) {
|
|
10779
|
+
return { method: "oauth", credential, source: "macos-keychain" };
|
|
10780
|
+
}
|
|
10781
|
+
} catch {
|
|
10782
|
+
}
|
|
10783
|
+
}
|
|
10784
|
+
}
|
|
10785
|
+
return null;
|
|
10786
|
+
}
|
|
10787
|
+
|
|
10788
|
+
// src/agents/codex/local-token.ts
|
|
10789
|
+
var fs17 = __toESM(require("fs"));
|
|
10790
|
+
var os16 = __toESM(require("os"));
|
|
10791
|
+
var path25 = __toESM(require("path"));
|
|
10792
|
+
function codexCredentialsPath() {
|
|
10793
|
+
return path25.join(os16.homedir(), ".codex", "auth.json");
|
|
10794
|
+
}
|
|
10795
|
+
async function extractLocalCodexToken() {
|
|
10796
|
+
const file = codexCredentialsPath();
|
|
10797
|
+
if (!fs17.existsSync(file)) return null;
|
|
10798
|
+
const credential = fs17.readFileSync(file, "utf8").trim();
|
|
10799
|
+
if (credential.length === 0) return null;
|
|
10800
|
+
return { method: "oauth", credential, source: "flat-file" };
|
|
10801
|
+
}
|
|
10802
|
+
function codexCredentialsPaths() {
|
|
10803
|
+
return [codexCredentialsPath()];
|
|
10804
|
+
}
|
|
10805
|
+
|
|
10806
|
+
// src/commands/link.ts
|
|
10807
|
+
var AGENT_META = {
|
|
10808
|
+
claude: {
|
|
10809
|
+
internalId: "claude",
|
|
10810
|
+
publicId: "claude_code",
|
|
10811
|
+
binary: "claude",
|
|
10812
|
+
displayName: "Claude Code",
|
|
10813
|
+
vendor: "Anthropic",
|
|
10814
|
+
credentialsHint: "~/.claude/.credentials.json or the macOS Keychain",
|
|
10815
|
+
watchPaths: claudeCredentialsPaths,
|
|
10816
|
+
extract: extractLocalClaudeToken,
|
|
10817
|
+
ensureInstalled: ensureClaudeInstalled,
|
|
10818
|
+
launchLogin: () => {
|
|
10819
|
+
const child = (0, import_node_child_process3.spawn)("claude", [], { stdio: ["pipe", "inherit", "inherit"] });
|
|
10820
|
+
child.stdin?.write("/login\n");
|
|
10821
|
+
return child;
|
|
10822
|
+
}
|
|
10823
|
+
},
|
|
10824
|
+
codex: {
|
|
10825
|
+
internalId: "codex",
|
|
10826
|
+
publicId: "codex",
|
|
10827
|
+
binary: "codex",
|
|
10828
|
+
displayName: "Codex",
|
|
10829
|
+
vendor: "OpenAI",
|
|
10830
|
+
credentialsHint: "~/.codex/auth.json",
|
|
10831
|
+
watchPaths: codexCredentialsPaths,
|
|
10832
|
+
extract: extractLocalCodexToken,
|
|
10833
|
+
ensureInstalled: async () => {
|
|
10834
|
+
const { findInPath: findInPath2 } = await Promise.resolve().then(() => (init_types(), types_exports));
|
|
10835
|
+
if (findInPath2("codex")) return true;
|
|
10836
|
+
showError(
|
|
10837
|
+
"codex binary not found on PATH. Install it first (https://github.com/openai/codex-cli) then re-run `codeam link codex`."
|
|
10838
|
+
);
|
|
10839
|
+
return false;
|
|
10840
|
+
},
|
|
10841
|
+
launchLogin: () => {
|
|
10842
|
+
return (0, import_node_child_process3.spawn)("codex", ["login"], { stdio: "inherit" });
|
|
10843
|
+
}
|
|
10844
|
+
}
|
|
10845
|
+
};
|
|
10846
|
+
function parseLinkArgs(args2) {
|
|
10847
|
+
const positional = args2.find((a) => !a.startsWith("--"));
|
|
10848
|
+
if (!positional) {
|
|
10849
|
+
throw new Error(
|
|
10850
|
+
`Usage: codeam link <agent>
|
|
10851
|
+
agent: ${Object.keys(AGENT_META).join(" | ")}`
|
|
10852
|
+
);
|
|
10853
|
+
}
|
|
10854
|
+
const normalised = positional === "claude_code" ? "claude" : positional;
|
|
10855
|
+
if (normalised !== "claude" && normalised !== "codex") {
|
|
10856
|
+
throw new Error(
|
|
10857
|
+
`Unknown agent "${positional}". Valid: ${Object.keys(AGENT_META).join(", ")}`
|
|
10858
|
+
);
|
|
10859
|
+
}
|
|
10860
|
+
const reuseExisting = args2.includes("--reuse-existing");
|
|
10861
|
+
const apiKeyArg = args2.find((a) => a.startsWith("--api-key="));
|
|
10862
|
+
const apiKey = apiKeyArg ? apiKeyArg.slice("--api-key=".length) : null;
|
|
10863
|
+
const tokenFileArg = args2.find((a) => a.startsWith("--token-file="));
|
|
10864
|
+
const tokenFile = tokenFileArg ? tokenFileArg.slice("--token-file=".length) : null;
|
|
10865
|
+
return { agent: normalised, reuseExisting, apiKey, tokenFile };
|
|
10866
|
+
}
|
|
10867
|
+
async function link(args2 = []) {
|
|
10868
|
+
const parsed = parseLinkArgs(args2);
|
|
10869
|
+
const meta = AGENT_META[parsed.agent];
|
|
10870
|
+
showIntro();
|
|
10871
|
+
console.log(
|
|
10872
|
+
import_picocolors11.default.bold(` Link ${meta.displayName}`) + import_picocolors11.default.dim(` \xB7 ${meta.vendor}`)
|
|
10873
|
+
);
|
|
10874
|
+
console.log("");
|
|
10875
|
+
const pluginId = (0, import_node_crypto.randomUUID)();
|
|
10876
|
+
const spin = dist_exports.spinner();
|
|
10877
|
+
spin.start("Requesting pairing code...");
|
|
10878
|
+
const pairing = await requestCode(pluginId);
|
|
10879
|
+
if (!pairing) {
|
|
10880
|
+
spin.stop("Failed");
|
|
10881
|
+
showError("Could not reach the server. Check your connection and try again.");
|
|
10882
|
+
process.exit(1);
|
|
10883
|
+
}
|
|
10884
|
+
spin.stop("Got pairing code");
|
|
10885
|
+
showPairingCode(pairing.code);
|
|
10886
|
+
console.log(import_picocolors11.default.dim(" Scan the QR or enter the code in CodeAgent Mobile."));
|
|
10887
|
+
console.log("");
|
|
10888
|
+
const waitSpin = dist_exports.spinner();
|
|
10889
|
+
const waitMsg = () => `Waiting for mobile pair... \xB7 expires in ${formatRemaining(pairing.expiresAt)}`;
|
|
10890
|
+
waitSpin.start(waitMsg());
|
|
10891
|
+
const countdown = setInterval(() => waitSpin.message(waitMsg()), 1e3);
|
|
10892
|
+
countdown.unref?.();
|
|
10893
|
+
const paired = await new Promise((resolve3, reject) => {
|
|
10894
|
+
let stopPoll = null;
|
|
10895
|
+
const sigint = () => {
|
|
10896
|
+
clearInterval(countdown);
|
|
10897
|
+
stopPoll?.();
|
|
10898
|
+
reject(new Error("cancelled"));
|
|
10899
|
+
};
|
|
10900
|
+
stopPoll = pollStatus(
|
|
10901
|
+
pluginId,
|
|
10902
|
+
(info) => {
|
|
10903
|
+
process.removeListener("SIGINT", sigint);
|
|
10904
|
+
clearInterval(countdown);
|
|
10905
|
+
waitSpin.stop("Paired");
|
|
10906
|
+
resolve3(info);
|
|
10907
|
+
},
|
|
10908
|
+
() => {
|
|
10909
|
+
clearInterval(countdown);
|
|
10910
|
+
waitSpin.stop("Timed out");
|
|
10911
|
+
reject(new Error("Pairing timed out after 5 minutes. Run codeam link again."));
|
|
10912
|
+
}
|
|
10913
|
+
);
|
|
10914
|
+
process.once("SIGINT", sigint);
|
|
10915
|
+
});
|
|
10916
|
+
if (!paired.pluginAuthToken) {
|
|
10917
|
+
showError(
|
|
10918
|
+
"Backend did not return a pluginAuthToken \u2014 upgrade api-v2 (deploy includes the link endpoint)."
|
|
10919
|
+
);
|
|
10920
|
+
process.exit(1);
|
|
10921
|
+
}
|
|
10922
|
+
addSession({
|
|
10923
|
+
id: paired.sessionId,
|
|
10924
|
+
pluginId,
|
|
10925
|
+
userName: paired.userName,
|
|
10926
|
+
userEmail: paired.userEmail,
|
|
10927
|
+
plan: paired.plan,
|
|
10928
|
+
pairedAt: Date.now(),
|
|
10929
|
+
pluginAuthToken: paired.pluginAuthToken,
|
|
10930
|
+
agent: meta.internalId
|
|
10931
|
+
});
|
|
10932
|
+
saveCliConfig({ ...loadCliConfig(), preferredAgent: meta.internalId });
|
|
10933
|
+
if (parsed.apiKey) {
|
|
10934
|
+
await uploadAndSucceed(meta, paired, pluginId, {
|
|
10935
|
+
method: "api_key",
|
|
10936
|
+
credential: parsed.apiKey.trim(),
|
|
10937
|
+
source: "manual"
|
|
10938
|
+
});
|
|
10939
|
+
return;
|
|
10940
|
+
}
|
|
10941
|
+
if (parsed.tokenFile) {
|
|
10942
|
+
const credential = fs18.readFileSync(path26.resolve(parsed.tokenFile), "utf8").trim();
|
|
10943
|
+
if (!credential) {
|
|
10944
|
+
showError(`--token-file ${parsed.tokenFile} is empty.`);
|
|
10945
|
+
process.exit(1);
|
|
10946
|
+
}
|
|
10947
|
+
await uploadAndSucceed(meta, paired, pluginId, {
|
|
10948
|
+
method: "oauth",
|
|
10949
|
+
credential,
|
|
10950
|
+
source: "manual"
|
|
10951
|
+
});
|
|
10952
|
+
return;
|
|
10953
|
+
}
|
|
10954
|
+
const installSpin = dist_exports.spinner();
|
|
10955
|
+
installSpin.start(`Checking that ${meta.binary} is installed...`);
|
|
10956
|
+
const installed = await meta.ensureInstalled();
|
|
10957
|
+
if (!installed) {
|
|
10958
|
+
installSpin.stop("Failed");
|
|
10959
|
+
showError(`Could not install ${meta.displayName}. Install it manually then re-run.`);
|
|
10960
|
+
process.exit(1);
|
|
10961
|
+
}
|
|
10962
|
+
installSpin.stop(`${meta.displayName} is installed`);
|
|
10963
|
+
const existing = await meta.extract();
|
|
10964
|
+
if (existing) {
|
|
10965
|
+
showInfo(`Found existing ${meta.displayName} credentials at ${import_picocolors11.default.bold(existing.source)}.`);
|
|
10966
|
+
await uploadAndSucceed(meta, paired, pluginId, existing);
|
|
10967
|
+
return;
|
|
10968
|
+
}
|
|
10969
|
+
if (parsed.reuseExisting) {
|
|
10970
|
+
showError(
|
|
10971
|
+
`--reuse-existing set, but no local ${meta.displayName} credentials were found at ${meta.credentialsHint}.`
|
|
10972
|
+
);
|
|
10973
|
+
process.exit(1);
|
|
10974
|
+
}
|
|
10975
|
+
showInfo(
|
|
10976
|
+
`No local ${meta.displayName} credentials found. Launching the sign-in \u2014 complete it in your browser, the CLI will detect the new token and finish automatically.`
|
|
10977
|
+
);
|
|
10978
|
+
console.log("");
|
|
10979
|
+
const captured = await captureFreshCredentials(meta);
|
|
10980
|
+
console.log("");
|
|
10981
|
+
await uploadAndSucceed(meta, paired, pluginId, captured);
|
|
10982
|
+
}
|
|
10983
|
+
async function captureFreshCredentials(meta) {
|
|
10984
|
+
const watcher = import_chokidar.default.watch(meta.watchPaths(), {
|
|
10985
|
+
persistent: true,
|
|
10986
|
+
ignoreInitial: false,
|
|
10987
|
+
awaitWriteFinish: { stabilityThreshold: 500, pollInterval: 100 }
|
|
10988
|
+
});
|
|
10989
|
+
let child = null;
|
|
10990
|
+
let keychainPoll = null;
|
|
10991
|
+
const cleanup = () => {
|
|
10992
|
+
void watcher.close();
|
|
10993
|
+
if (keychainPoll) clearInterval(keychainPoll);
|
|
10994
|
+
if (child && !child.killed) {
|
|
10995
|
+
try {
|
|
10996
|
+
child.kill("SIGTERM");
|
|
10997
|
+
} catch {
|
|
10998
|
+
}
|
|
10999
|
+
}
|
|
11000
|
+
};
|
|
11001
|
+
try {
|
|
11002
|
+
const token = await new Promise((resolve3, reject) => {
|
|
11003
|
+
let settled = false;
|
|
11004
|
+
const tryExtract = async () => {
|
|
11005
|
+
if (settled) return;
|
|
11006
|
+
const t2 = await meta.extract();
|
|
11007
|
+
if (t2 && !settled) {
|
|
11008
|
+
settled = true;
|
|
11009
|
+
resolve3(t2);
|
|
11010
|
+
}
|
|
11011
|
+
};
|
|
11012
|
+
watcher.on("add", () => void tryExtract());
|
|
11013
|
+
watcher.on("change", () => void tryExtract());
|
|
11014
|
+
keychainPoll = setInterval(() => void tryExtract(), 2e3);
|
|
11015
|
+
keychainPoll.unref?.();
|
|
11016
|
+
const sigint = () => {
|
|
11017
|
+
if (settled) return;
|
|
11018
|
+
settled = true;
|
|
11019
|
+
reject(new Error("cancelled"));
|
|
11020
|
+
};
|
|
11021
|
+
process.once("SIGINT", sigint);
|
|
11022
|
+
setTimeout(() => {
|
|
11023
|
+
if (settled) return;
|
|
11024
|
+
settled = true;
|
|
11025
|
+
reject(new Error(`Timed out waiting for ${meta.displayName} sign-in (5 minutes).`));
|
|
11026
|
+
}, 5 * 6e4);
|
|
11027
|
+
child = meta.launchLogin();
|
|
11028
|
+
child.on("exit", () => {
|
|
11029
|
+
void tryExtract().then(() => {
|
|
11030
|
+
if (!settled) {
|
|
11031
|
+
settled = true;
|
|
11032
|
+
reject(
|
|
11033
|
+
new Error(
|
|
11034
|
+
`${meta.binary} exited but no credentials were written at ${meta.credentialsHint}.`
|
|
11035
|
+
)
|
|
11036
|
+
);
|
|
11037
|
+
}
|
|
11038
|
+
});
|
|
11039
|
+
});
|
|
11040
|
+
});
|
|
11041
|
+
cleanup();
|
|
11042
|
+
return token;
|
|
11043
|
+
} catch (err) {
|
|
11044
|
+
cleanup();
|
|
11045
|
+
throw err;
|
|
11046
|
+
}
|
|
11047
|
+
}
|
|
11048
|
+
async function uploadAndSucceed(meta, paired, pluginId, token) {
|
|
11049
|
+
if (!paired.pluginAuthToken) {
|
|
11050
|
+
showError("Missing pluginAuthToken; re-run codeam link.");
|
|
11051
|
+
process.exit(1);
|
|
11052
|
+
}
|
|
11053
|
+
const uploadSpin = dist_exports.spinner();
|
|
11054
|
+
uploadSpin.start("Sealing credential in your vault...");
|
|
11055
|
+
const result = await postLinkCredential({
|
|
11056
|
+
agentId: meta.publicId,
|
|
11057
|
+
sessionId: paired.sessionId,
|
|
11058
|
+
pluginId,
|
|
11059
|
+
pluginAuthToken: paired.pluginAuthToken,
|
|
11060
|
+
method: token.method,
|
|
11061
|
+
credential: token.credential
|
|
11062
|
+
});
|
|
11063
|
+
if (!result.ok) {
|
|
11064
|
+
uploadSpin.stop("Failed");
|
|
11065
|
+
if (result.status === 401) {
|
|
11066
|
+
showError("Pair token rejected by the backend (401). Re-run `codeam link`.");
|
|
11067
|
+
} else if (result.status === 404) {
|
|
11068
|
+
showError(
|
|
11069
|
+
`${meta.displayName} link endpoint not available on this backend (404). The api-v2 deployment may not yet include the route.`
|
|
11070
|
+
);
|
|
11071
|
+
} else {
|
|
11072
|
+
showError(`Upload failed: ${result.message}`);
|
|
11073
|
+
}
|
|
11074
|
+
process.exit(1);
|
|
11075
|
+
}
|
|
11076
|
+
uploadSpin.stop("Linked");
|
|
11077
|
+
console.log("");
|
|
11078
|
+
showSuccess(`${meta.displayName} is now linked to ${paired.userEmail || paired.userName}.`);
|
|
11079
|
+
showInfo(
|
|
11080
|
+
`Your codespaces and @codeagent mentions can now use ${meta.displayName} without you signing in again.`
|
|
11081
|
+
);
|
|
11082
|
+
console.log("");
|
|
11083
|
+
}
|
|
11084
|
+
|
|
11085
|
+
// src/commands/version.ts
|
|
11086
|
+
var import_picocolors12 = __toESM(require("picocolors"));
|
|
10643
11087
|
function version() {
|
|
10644
|
-
const v = true ? "2.
|
|
10645
|
-
console.log(`${
|
|
11088
|
+
const v = true ? "2.16.1" : "unknown";
|
|
11089
|
+
console.log(`${import_picocolors12.default.bold("codeam-cli")} ${import_picocolors12.default.cyan(v)}`);
|
|
10646
11090
|
}
|
|
10647
11091
|
|
|
10648
11092
|
// src/commands/help.ts
|
|
10649
|
-
var
|
|
11093
|
+
var import_picocolors13 = __toESM(require("picocolors"));
|
|
10650
11094
|
function help() {
|
|
10651
11095
|
const lines = [
|
|
10652
11096
|
"",
|
|
10653
|
-
` ${
|
|
11097
|
+
` ${import_picocolors13.default.bold(import_picocolors13.default.magenta("codeam-cli"))} ${import_picocolors13.default.dim("\u2014 remote-control AI coding agents from your phone")}`,
|
|
10654
11098
|
"",
|
|
10655
|
-
` ${
|
|
10656
|
-
` ${
|
|
11099
|
+
` ${import_picocolors13.default.bold("Usage")}`,
|
|
11100
|
+
` ${import_picocolors13.default.cyan("codeam")} ${import_picocolors13.default.dim("[command]")}`,
|
|
10657
11101
|
"",
|
|
10658
|
-
` ${
|
|
10659
|
-
` ${
|
|
10660
|
-
` ${
|
|
10661
|
-
` ${
|
|
10662
|
-
` ${
|
|
10663
|
-
` ${
|
|
10664
|
-
` ${
|
|
10665
|
-
` ${
|
|
10666
|
-
` ${
|
|
10667
|
-
` ${
|
|
10668
|
-
` ${
|
|
10669
|
-
` ${
|
|
10670
|
-
` ${
|
|
11102
|
+
` ${import_picocolors13.default.bold("Commands")}`,
|
|
11103
|
+
` ${import_picocolors13.default.white("codeam")} ${import_picocolors13.default.dim("start the active agent with mobile control")}`,
|
|
11104
|
+
` ${import_picocolors13.default.white("codeam <agent>")} ${import_picocolors13.default.dim("start a specific agent \u2014 e.g. claude, codex")}`,
|
|
11105
|
+
` ${import_picocolors13.default.white("codeam pair")} ${import_picocolors13.default.dim("pair a new mobile device (interactive)")}`,
|
|
11106
|
+
` ${import_picocolors13.default.white("codeam pair --agent <id>")} ${import_picocolors13.default.dim("pair non-interactively for a specific agent")}`,
|
|
11107
|
+
` ${import_picocolors13.default.white("codeam sessions")} ${import_picocolors13.default.dim("list paired devices")}`,
|
|
11108
|
+
` ${import_picocolors13.default.white("codeam sessions switch")} ${import_picocolors13.default.dim("switch the active paired session")}`,
|
|
11109
|
+
` ${import_picocolors13.default.white("codeam sessions delete <id>")} ${import_picocolors13.default.dim("remove a specific paired session")}`,
|
|
11110
|
+
` ${import_picocolors13.default.white("codeam status")} ${import_picocolors13.default.dim("show connection info")}`,
|
|
11111
|
+
` ${import_picocolors13.default.white("codeam logout")} ${import_picocolors13.default.dim("remove all paired sessions")}`,
|
|
11112
|
+
` ${import_picocolors13.default.white("codeam link <agent>")} ${import_picocolors13.default.dim("link an agent (claude, codex) to your CodeAgent account")}`,
|
|
11113
|
+
` ${import_picocolors13.default.white("codeam deploy")} ${import_picocolors13.default.dim("provision a cloud workspace (Codespaces) and pair it")}`,
|
|
11114
|
+
` ${import_picocolors13.default.white("codeam deploy ls | list")} ${import_picocolors13.default.dim("list deployed cloud workspaces")}`,
|
|
11115
|
+
` ${import_picocolors13.default.white("codeam deploy stop | remove")} ${import_picocolors13.default.dim("stop a deployed workspace session")}`,
|
|
10671
11116
|
"",
|
|
10672
|
-
` ${
|
|
10673
|
-
` ${
|
|
10674
|
-
` ${
|
|
11117
|
+
` ${import_picocolors13.default.bold("Flags")}`,
|
|
11118
|
+
` ${import_picocolors13.default.white("-v, --version")} ${import_picocolors13.default.dim("print the CLI version")}`,
|
|
11119
|
+
` ${import_picocolors13.default.white("-h, --help")} ${import_picocolors13.default.dim("show this help")}`,
|
|
10675
11120
|
"",
|
|
10676
|
-
` ${
|
|
10677
|
-
` ${
|
|
10678
|
-
` ${
|
|
11121
|
+
` ${import_picocolors13.default.bold("Links")}`,
|
|
11122
|
+
` ${import_picocolors13.default.dim("Docs:")} ${import_picocolors13.default.green("https://www.codeagent-mobile.com")}`,
|
|
11123
|
+
` ${import_picocolors13.default.dim("Issues:")} ${import_picocolors13.default.green("https://github.com/edgar-durand/codeagent-mobile-clients/issues")}`,
|
|
10679
11124
|
""
|
|
10680
11125
|
];
|
|
10681
11126
|
process.stdout.write(lines.join("\n") + "\n");
|
|
10682
11127
|
}
|
|
10683
11128
|
|
|
10684
11129
|
// src/lib/updateNotifier.ts
|
|
10685
|
-
var
|
|
10686
|
-
var
|
|
10687
|
-
var
|
|
11130
|
+
var fs19 = __toESM(require("fs"));
|
|
11131
|
+
var os17 = __toESM(require("os"));
|
|
11132
|
+
var path27 = __toESM(require("path"));
|
|
10688
11133
|
var https7 = __toESM(require("https"));
|
|
10689
|
-
var
|
|
11134
|
+
var import_picocolors14 = __toESM(require("picocolors"));
|
|
10690
11135
|
var PKG_NAME = "codeam-cli";
|
|
10691
11136
|
var REGISTRY_URL = `https://registry.npmjs.org/${PKG_NAME}/latest`;
|
|
10692
11137
|
var TTL_MS = 24 * 60 * 60 * 1e3;
|
|
10693
11138
|
var REQUEST_TIMEOUT_MS = 1500;
|
|
10694
11139
|
function cachePath() {
|
|
10695
|
-
const dir =
|
|
10696
|
-
return
|
|
11140
|
+
const dir = path27.join(os17.homedir(), ".codeam");
|
|
11141
|
+
return path27.join(dir, "update-check.json");
|
|
10697
11142
|
}
|
|
10698
11143
|
function readCache() {
|
|
10699
11144
|
try {
|
|
10700
|
-
const raw =
|
|
11145
|
+
const raw = fs19.readFileSync(cachePath(), "utf8");
|
|
10701
11146
|
const parsed = JSON.parse(raw);
|
|
10702
11147
|
if (typeof parsed.fetchedAt !== "number" || typeof parsed.latest !== "string") return null;
|
|
10703
11148
|
return parsed;
|
|
@@ -10708,8 +11153,8 @@ function readCache() {
|
|
|
10708
11153
|
function writeCache(cache) {
|
|
10709
11154
|
try {
|
|
10710
11155
|
const file = cachePath();
|
|
10711
|
-
|
|
10712
|
-
|
|
11156
|
+
fs19.mkdirSync(path27.dirname(file), { recursive: true });
|
|
11157
|
+
fs19.writeFileSync(file, JSON.stringify(cache));
|
|
10713
11158
|
} catch {
|
|
10714
11159
|
}
|
|
10715
11160
|
}
|
|
@@ -10727,14 +11172,14 @@ function compareSemver(a, b) {
|
|
|
10727
11172
|
return 0;
|
|
10728
11173
|
}
|
|
10729
11174
|
function fetchLatest() {
|
|
10730
|
-
return new Promise((
|
|
11175
|
+
return new Promise((resolve3) => {
|
|
10731
11176
|
const req = https7.get(
|
|
10732
11177
|
REGISTRY_URL,
|
|
10733
11178
|
{ headers: { Accept: "application/json" }, timeout: REQUEST_TIMEOUT_MS },
|
|
10734
11179
|
(res) => {
|
|
10735
11180
|
if (res.statusCode !== 200) {
|
|
10736
11181
|
res.resume();
|
|
10737
|
-
|
|
11182
|
+
resolve3(null);
|
|
10738
11183
|
return;
|
|
10739
11184
|
}
|
|
10740
11185
|
let buf = "";
|
|
@@ -10746,30 +11191,30 @@ function fetchLatest() {
|
|
|
10746
11191
|
try {
|
|
10747
11192
|
const json = JSON.parse(buf);
|
|
10748
11193
|
if (typeof json.version === "string") {
|
|
10749
|
-
|
|
11194
|
+
resolve3(json.version);
|
|
10750
11195
|
} else {
|
|
10751
|
-
|
|
11196
|
+
resolve3(null);
|
|
10752
11197
|
}
|
|
10753
11198
|
} catch {
|
|
10754
|
-
|
|
11199
|
+
resolve3(null);
|
|
10755
11200
|
}
|
|
10756
11201
|
});
|
|
10757
11202
|
}
|
|
10758
11203
|
);
|
|
10759
11204
|
req.on("timeout", () => {
|
|
10760
11205
|
req.destroy();
|
|
10761
|
-
|
|
11206
|
+
resolve3(null);
|
|
10762
11207
|
});
|
|
10763
|
-
req.on("error", () =>
|
|
11208
|
+
req.on("error", () => resolve3(null));
|
|
10764
11209
|
});
|
|
10765
11210
|
}
|
|
10766
11211
|
function notifyIfStale(currentVersion, latest) {
|
|
10767
11212
|
if (compareSemver(latest, currentVersion) <= 0) return;
|
|
10768
|
-
const arrow =
|
|
10769
|
-
const cmd =
|
|
11213
|
+
const arrow = import_picocolors14.default.dim("\u2192");
|
|
11214
|
+
const cmd = import_picocolors14.default.cyan("npm install -g codeam-cli");
|
|
10770
11215
|
const lines = [
|
|
10771
11216
|
"",
|
|
10772
|
-
` ${
|
|
11217
|
+
` ${import_picocolors14.default.yellow("\u25CF")} ${import_picocolors14.default.bold("Update available")} ${import_picocolors14.default.dim(currentVersion)} ${arrow} ${import_picocolors14.default.green(latest)}`,
|
|
10773
11218
|
` Run ${cmd} to upgrade.`,
|
|
10774
11219
|
""
|
|
10775
11220
|
];
|
|
@@ -10780,7 +11225,7 @@ function checkForUpdates() {
|
|
|
10780
11225
|
if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
|
|
10781
11226
|
if (process.env.CI) return;
|
|
10782
11227
|
if (!process.stdout.isTTY) return;
|
|
10783
|
-
const current = true ? "2.
|
|
11228
|
+
const current = true ? "2.16.1" : null;
|
|
10784
11229
|
if (!current) return;
|
|
10785
11230
|
const cache = readCache();
|
|
10786
11231
|
const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
|
|
@@ -10818,6 +11263,8 @@ async function main() {
|
|
|
10818
11263
|
return status();
|
|
10819
11264
|
case "logout":
|
|
10820
11265
|
return logout();
|
|
11266
|
+
case "link":
|
|
11267
|
+
return link(args);
|
|
10821
11268
|
case "deploy":
|
|
10822
11269
|
if (args[0] === "ls" || args[0] === "list") return deployList();
|
|
10823
11270
|
if (args[0] === "stop" || args[0] === "remove") return deployStop();
|