codeam-cli 2.20.1 → 2.20.2
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 +10 -0
- package/dist/index.js +223 -174
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,16 @@ 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.20.1] — 2026-05-25
|
|
8
|
+
|
|
9
|
+
### Documentation
|
|
10
|
+
|
|
11
|
+
- Document CODEAM_TEST_MODE + CODEAM_API_URL env vars in README (#177)
|
|
12
|
+
|
|
13
|
+
### Fixed
|
|
14
|
+
|
|
15
|
+
- **cli:** Finalize turn on content-stable + ready-prompt, not just PTY-idle (#178)
|
|
16
|
+
|
|
7
17
|
## [2.20.0] — 2026-05-24
|
|
8
18
|
|
|
9
19
|
### Added
|
package/dist/index.js
CHANGED
|
@@ -441,7 +441,7 @@ var import_qrcode_terminal = __toESM(require("qrcode-terminal"));
|
|
|
441
441
|
// package.json
|
|
442
442
|
var package_default = {
|
|
443
443
|
name: "codeam-cli",
|
|
444
|
-
version: "2.20.
|
|
444
|
+
version: "2.20.2",
|
|
445
445
|
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.",
|
|
446
446
|
type: "commonjs",
|
|
447
447
|
main: "dist/index.js",
|
|
@@ -735,7 +735,7 @@ async function postLinkCredential(input) {
|
|
|
735
735
|
}
|
|
736
736
|
}
|
|
737
737
|
async function _postJsonAuthed(url, body, pluginAuthToken) {
|
|
738
|
-
return new Promise((
|
|
738
|
+
return new Promise((resolve4, reject) => {
|
|
739
739
|
const data = JSON.stringify(body);
|
|
740
740
|
const u2 = new URL(url);
|
|
741
741
|
const transport = u2.protocol === "https:" ? https : http;
|
|
@@ -767,9 +767,9 @@ async function _postJsonAuthed(url, body, pluginAuthToken) {
|
|
|
767
767
|
return;
|
|
768
768
|
}
|
|
769
769
|
try {
|
|
770
|
-
|
|
770
|
+
resolve4(JSON.parse(responseBody));
|
|
771
771
|
} catch {
|
|
772
|
-
|
|
772
|
+
resolve4(null);
|
|
773
773
|
}
|
|
774
774
|
});
|
|
775
775
|
}
|
|
@@ -784,7 +784,7 @@ async function _postJsonAuthed(url, body, pluginAuthToken) {
|
|
|
784
784
|
});
|
|
785
785
|
}
|
|
786
786
|
async function _postJson(url, body) {
|
|
787
|
-
return new Promise((
|
|
787
|
+
return new Promise((resolve4, reject) => {
|
|
788
788
|
const data = JSON.stringify(body);
|
|
789
789
|
const u2 = new URL(url);
|
|
790
790
|
const transport = u2.protocol === "https:" ? https : http;
|
|
@@ -813,9 +813,9 @@ async function _postJson(url, body) {
|
|
|
813
813
|
return;
|
|
814
814
|
}
|
|
815
815
|
try {
|
|
816
|
-
|
|
816
|
+
resolve4(JSON.parse(body2));
|
|
817
817
|
} catch {
|
|
818
|
-
|
|
818
|
+
resolve4(null);
|
|
819
819
|
}
|
|
820
820
|
});
|
|
821
821
|
}
|
|
@@ -830,7 +830,7 @@ async function _postJson(url, body) {
|
|
|
830
830
|
});
|
|
831
831
|
}
|
|
832
832
|
async function _getJson(url) {
|
|
833
|
-
return new Promise((
|
|
833
|
+
return new Promise((resolve4, reject) => {
|
|
834
834
|
const u2 = new URL(url);
|
|
835
835
|
const transport = u2.protocol === "https:" ? https : http;
|
|
836
836
|
const req = transport.request(
|
|
@@ -854,9 +854,9 @@ async function _getJson(url) {
|
|
|
854
854
|
return;
|
|
855
855
|
}
|
|
856
856
|
try {
|
|
857
|
-
|
|
857
|
+
resolve4(JSON.parse(body));
|
|
858
858
|
} catch {
|
|
859
|
-
|
|
859
|
+
resolve4(null);
|
|
860
860
|
}
|
|
861
861
|
});
|
|
862
862
|
}
|
|
@@ -3508,14 +3508,14 @@ async function addSourceContext(frames) {
|
|
|
3508
3508
|
return frames;
|
|
3509
3509
|
}
|
|
3510
3510
|
function getContextLinesFromFile(path37, ranges, output) {
|
|
3511
|
-
return new Promise((
|
|
3511
|
+
return new Promise((resolve4) => {
|
|
3512
3512
|
const stream = (0, import_node_fs.createReadStream)(path37);
|
|
3513
3513
|
const lineReaded = (0, import_node_readline.createInterface)({
|
|
3514
3514
|
input: stream
|
|
3515
3515
|
});
|
|
3516
3516
|
function destroyStreamAndResolve() {
|
|
3517
3517
|
stream.destroy();
|
|
3518
|
-
|
|
3518
|
+
resolve4();
|
|
3519
3519
|
}
|
|
3520
3520
|
let lineNumber = 0;
|
|
3521
3521
|
let currentRangeIndex = 0;
|
|
@@ -4802,9 +4802,9 @@ var PostHogBackendClient = class extends PostHogCoreStateless {
|
|
|
4802
4802
|
if (!waitUntil) return;
|
|
4803
4803
|
if (this.disabled || this.optedOut) return;
|
|
4804
4804
|
if (!this._waitUntilCycle) {
|
|
4805
|
-
let
|
|
4805
|
+
let resolve4;
|
|
4806
4806
|
const promise = new Promise((r) => {
|
|
4807
|
-
|
|
4807
|
+
resolve4 = r;
|
|
4808
4808
|
});
|
|
4809
4809
|
try {
|
|
4810
4810
|
waitUntil(promise);
|
|
@@ -4812,7 +4812,7 @@ var PostHogBackendClient = class extends PostHogCoreStateless {
|
|
|
4812
4812
|
return;
|
|
4813
4813
|
}
|
|
4814
4814
|
this._waitUntilCycle = {
|
|
4815
|
-
resolve:
|
|
4815
|
+
resolve: resolve4,
|
|
4816
4816
|
startedAt: Date.now(),
|
|
4817
4817
|
timer: void 0
|
|
4818
4818
|
};
|
|
@@ -4836,12 +4836,12 @@ var PostHogBackendClient = class extends PostHogCoreStateless {
|
|
|
4836
4836
|
return cycle?.resolve;
|
|
4837
4837
|
}
|
|
4838
4838
|
async resolveWaitUntilFlush() {
|
|
4839
|
-
const
|
|
4839
|
+
const resolve4 = this._consumeWaitUntilCycle();
|
|
4840
4840
|
try {
|
|
4841
4841
|
await super.flush();
|
|
4842
4842
|
} catch {
|
|
4843
4843
|
} finally {
|
|
4844
|
-
|
|
4844
|
+
resolve4?.();
|
|
4845
4845
|
}
|
|
4846
4846
|
}
|
|
4847
4847
|
getPersistedProperty(key) {
|
|
@@ -4933,15 +4933,15 @@ var PostHogBackendClient = class extends PostHogCoreStateless {
|
|
|
4933
4933
|
async waitForLocalEvaluationReady(timeoutMs = THIRTY_SECONDS) {
|
|
4934
4934
|
if (this.isLocalEvaluationReady()) return true;
|
|
4935
4935
|
if (void 0 === this.featureFlagsPoller) return false;
|
|
4936
|
-
return new Promise((
|
|
4936
|
+
return new Promise((resolve4) => {
|
|
4937
4937
|
const timeout = setTimeout(() => {
|
|
4938
4938
|
cleanup();
|
|
4939
|
-
|
|
4939
|
+
resolve4(false);
|
|
4940
4940
|
}, timeoutMs);
|
|
4941
4941
|
const cleanup = this._events.on("localEvaluationFlagsLoaded", (count) => {
|
|
4942
4942
|
clearTimeout(timeout);
|
|
4943
4943
|
cleanup();
|
|
4944
|
-
|
|
4944
|
+
resolve4(count > 0);
|
|
4945
4945
|
});
|
|
4946
4946
|
});
|
|
4947
4947
|
}
|
|
@@ -5378,13 +5378,13 @@ var PostHogBackendClient = class extends PostHogCoreStateless {
|
|
|
5378
5378
|
this.context?.enter(data, options);
|
|
5379
5379
|
}
|
|
5380
5380
|
async _shutdown(shutdownTimeoutMs) {
|
|
5381
|
-
const
|
|
5381
|
+
const resolve4 = this._consumeWaitUntilCycle();
|
|
5382
5382
|
await this.featureFlagsPoller?.stopPoller(shutdownTimeoutMs);
|
|
5383
5383
|
this.errorTracking.shutdown();
|
|
5384
5384
|
try {
|
|
5385
5385
|
return await super._shutdown(shutdownTimeoutMs);
|
|
5386
5386
|
} finally {
|
|
5387
|
-
|
|
5387
|
+
resolve4?.();
|
|
5388
5388
|
}
|
|
5389
5389
|
}
|
|
5390
5390
|
async _requestRemoteConfigPayload(flagKey) {
|
|
@@ -5740,7 +5740,7 @@ function readAnonId() {
|
|
|
5740
5740
|
}
|
|
5741
5741
|
function superProperties() {
|
|
5742
5742
|
return {
|
|
5743
|
-
cliVersion: true ? "2.20.
|
|
5743
|
+
cliVersion: true ? "2.20.2" : "0.0.0-dev",
|
|
5744
5744
|
nodeVersion: process.version,
|
|
5745
5745
|
platform: process.platform,
|
|
5746
5746
|
arch: process.arch,
|
|
@@ -8874,15 +8874,15 @@ function runInstaller() {
|
|
|
8874
8874
|
"-Command",
|
|
8875
8875
|
"irm https://claude.ai/install.ps1 | iex"
|
|
8876
8876
|
] : ["-c", "curl -fsSL https://claude.ai/install.sh | bash"];
|
|
8877
|
-
return new Promise((
|
|
8877
|
+
return new Promise((resolve4) => {
|
|
8878
8878
|
const proc = (0, import_child_process4.spawn)(cmd, args2, { stdio: "inherit" });
|
|
8879
8879
|
proc.on("error", (err) => {
|
|
8880
8880
|
console.error(`
|
|
8881
8881
|
\u2717 Installer failed to launch: ${err.message}`);
|
|
8882
|
-
|
|
8882
|
+
resolve4(false);
|
|
8883
8883
|
});
|
|
8884
8884
|
proc.on("exit", (code) => {
|
|
8885
|
-
|
|
8885
|
+
resolve4(code === 0);
|
|
8886
8886
|
});
|
|
8887
8887
|
});
|
|
8888
8888
|
}
|
|
@@ -9045,17 +9045,17 @@ function parseUsageOutput(raw) {
|
|
|
9045
9045
|
return { percent, resetAt };
|
|
9046
9046
|
}
|
|
9047
9047
|
async function fetchClaudeQuota() {
|
|
9048
|
-
return new Promise((
|
|
9048
|
+
return new Promise((resolve4) => {
|
|
9049
9049
|
const claudeCmd = findInPath("claude") ? "claude" : "claude-code";
|
|
9050
9050
|
if (!claudeCmd) {
|
|
9051
|
-
|
|
9051
|
+
resolve4(null);
|
|
9052
9052
|
return;
|
|
9053
9053
|
}
|
|
9054
9054
|
const helperPath = path11.join(os10.tmpdir(), "codeam-quota-helper.py");
|
|
9055
9055
|
fs8.writeFileSync(helperPath, HELPER_SCRIPT, { mode: 420 });
|
|
9056
9056
|
const python = findInPath("python3") ?? findInPath("python");
|
|
9057
9057
|
if (!python) {
|
|
9058
|
-
|
|
9058
|
+
resolve4(null);
|
|
9059
9059
|
return;
|
|
9060
9060
|
}
|
|
9061
9061
|
const proc = (0, import_child_process5.spawn)(python, [helperPath, claudeCmd, "--tools", ""], {
|
|
@@ -9082,13 +9082,13 @@ async function fetchClaudeQuota() {
|
|
|
9082
9082
|
fs8.unlinkSync(helperPath);
|
|
9083
9083
|
} catch {
|
|
9084
9084
|
}
|
|
9085
|
-
|
|
9085
|
+
resolve4(result);
|
|
9086
9086
|
}, 5e3);
|
|
9087
9087
|
}, 8e3);
|
|
9088
9088
|
setTimeout(() => {
|
|
9089
9089
|
if (!resolved) {
|
|
9090
9090
|
resolved = true;
|
|
9091
|
-
|
|
9091
|
+
resolve4(null);
|
|
9092
9092
|
}
|
|
9093
9093
|
try {
|
|
9094
9094
|
proc.kill();
|
|
@@ -10428,12 +10428,12 @@ function resolveNpm(os26) {
|
|
|
10428
10428
|
return os26.id === "win32" ? "npm.cmd" : "npm";
|
|
10429
10429
|
}
|
|
10430
10430
|
async function installCodexViaNpm(os26) {
|
|
10431
|
-
return new Promise((
|
|
10431
|
+
return new Promise((resolve4, reject) => {
|
|
10432
10432
|
const proc = (0, import_node_child_process4.spawn)(resolveNpm(os26), ["install", "-g", "@openai/codex"], {
|
|
10433
10433
|
stdio: "inherit"
|
|
10434
10434
|
});
|
|
10435
10435
|
proc.on("close", (code) => {
|
|
10436
|
-
if (code === 0)
|
|
10436
|
+
if (code === 0) resolve4();
|
|
10437
10437
|
else reject(new Error(`npm install -g @openai/codex exited ${code}`));
|
|
10438
10438
|
});
|
|
10439
10439
|
proc.on("error", (err) => {
|
|
@@ -10548,12 +10548,12 @@ async function ensureCoderabbitInstalled(os26) {
|
|
|
10548
10548
|
return false;
|
|
10549
10549
|
}
|
|
10550
10550
|
console.log("\n CodeRabbit CLI not found \u2014 installing via the official script\u2026\n");
|
|
10551
|
-
const ok = await new Promise((
|
|
10551
|
+
const ok = await new Promise((resolve4) => {
|
|
10552
10552
|
const proc = (0, import_node_child_process5.spawn)("sh", ["-c", `curl -fsSL ${INSTALL_URL} | sh`], {
|
|
10553
10553
|
stdio: "inherit"
|
|
10554
10554
|
});
|
|
10555
|
-
proc.on("close", (code) =>
|
|
10556
|
-
proc.on("error", () =>
|
|
10555
|
+
proc.on("close", (code) => resolve4(code === 0));
|
|
10556
|
+
proc.on("error", () => resolve4(false));
|
|
10557
10557
|
});
|
|
10558
10558
|
if (!ok) return false;
|
|
10559
10559
|
os26.augmentPath([`${os26.homeDir()}/.local/bin`, "/opt/homebrew/bin"]);
|
|
@@ -10672,7 +10672,7 @@ var CoderabbitRuntimeStrategy = class {
|
|
|
10672
10672
|
}
|
|
10673
10673
|
async runOneShot(input) {
|
|
10674
10674
|
const launch = await this.prepareInvocation(input);
|
|
10675
|
-
return new Promise((
|
|
10675
|
+
return new Promise((resolve4, reject) => {
|
|
10676
10676
|
const stdoutBuf = [];
|
|
10677
10677
|
const stderrBuf = [];
|
|
10678
10678
|
const proc = (0, import_node_child_process7.spawn)(launch.cmd, launch.args, {
|
|
@@ -10683,7 +10683,7 @@ var CoderabbitRuntimeStrategy = class {
|
|
|
10683
10683
|
proc.stderr?.on("data", (b) => stderrBuf.push(b));
|
|
10684
10684
|
proc.on("error", (err) => reject(err));
|
|
10685
10685
|
proc.on("close", (code) => {
|
|
10686
|
-
|
|
10686
|
+
resolve4(
|
|
10687
10687
|
this.parseOutput({
|
|
10688
10688
|
exitCode: code ?? 0,
|
|
10689
10689
|
stdout: Buffer.concat(stdoutBuf).toString("utf8"),
|
|
@@ -11216,14 +11216,14 @@ var ChunkEmitter = class {
|
|
|
11216
11216
|
"chunkEmitter",
|
|
11217
11217
|
`send type=${body.type ?? "(clear)"} bytes=${payload.length} done=${body.done === true}`
|
|
11218
11218
|
);
|
|
11219
|
-
return new Promise((
|
|
11219
|
+
return new Promise((resolve4) => {
|
|
11220
11220
|
const attempt = (attemptsLeft) => {
|
|
11221
11221
|
_transport2.post(this.url, this.headers, payload).then(({ statusCode, body: resBody }) => {
|
|
11222
11222
|
const tookMs = Date.now() - t0;
|
|
11223
11223
|
if (statusCode === 410 || statusCode === 404 && /SESSION_NOT_FOUND|SESSION_GONE/.test(resBody)) {
|
|
11224
11224
|
process.stderr.write("[codeam] session was deleted/disconnected \u2014 stopping output stream.\n");
|
|
11225
11225
|
log.info("chunkEmitter", `dead status=${statusCode} took=${tookMs}ms`);
|
|
11226
|
-
|
|
11226
|
+
resolve4({ dead: true });
|
|
11227
11227
|
return;
|
|
11228
11228
|
}
|
|
11229
11229
|
if (statusCode >= 400) {
|
|
@@ -11233,7 +11233,7 @@ var ChunkEmitter = class {
|
|
|
11233
11233
|
} else {
|
|
11234
11234
|
log.info("chunkEmitter", `ok status=${statusCode} took=${tookMs}ms`);
|
|
11235
11235
|
}
|
|
11236
|
-
|
|
11236
|
+
resolve4({ dead: false });
|
|
11237
11237
|
}).catch((err) => {
|
|
11238
11238
|
log.warn(
|
|
11239
11239
|
"chunkEmitter",
|
|
@@ -11244,7 +11244,7 @@ var ChunkEmitter = class {
|
|
|
11244
11244
|
const delay = 200 * (maxRetries - attemptsLeft + 1);
|
|
11245
11245
|
setTimeout(() => attempt(attemptsLeft - 1), delay);
|
|
11246
11246
|
} else {
|
|
11247
|
-
|
|
11247
|
+
resolve4({ dead: false });
|
|
11248
11248
|
}
|
|
11249
11249
|
});
|
|
11250
11250
|
};
|
|
@@ -11256,7 +11256,7 @@ var _transport2 = {
|
|
|
11256
11256
|
post: _post
|
|
11257
11257
|
};
|
|
11258
11258
|
function _post(url, headers, payload) {
|
|
11259
|
-
return new Promise((
|
|
11259
|
+
return new Promise((resolve4, reject) => {
|
|
11260
11260
|
let settled = false;
|
|
11261
11261
|
const u2 = new URL(url);
|
|
11262
11262
|
const transport = u2.protocol === "https:" ? https3 : http3;
|
|
@@ -11280,7 +11280,7 @@ function _post(url, headers, payload) {
|
|
|
11280
11280
|
res.on("end", () => {
|
|
11281
11281
|
if (settled) return;
|
|
11282
11282
|
settled = true;
|
|
11283
|
-
|
|
11283
|
+
resolve4({ statusCode: res.statusCode ?? 0, body: resData });
|
|
11284
11284
|
});
|
|
11285
11285
|
}
|
|
11286
11286
|
);
|
|
@@ -11781,7 +11781,7 @@ function parseJsonl(filePath) {
|
|
|
11781
11781
|
return messages;
|
|
11782
11782
|
}
|
|
11783
11783
|
function post(endpoint, body) {
|
|
11784
|
-
return new Promise((
|
|
11784
|
+
return new Promise((resolve4) => {
|
|
11785
11785
|
const payload = JSON.stringify(body);
|
|
11786
11786
|
const u2 = new URL(`${API_BASE4}${endpoint}`);
|
|
11787
11787
|
const transport = u2.protocol === "https:" ? https4 : http4;
|
|
@@ -11802,17 +11802,17 @@ function post(endpoint, body) {
|
|
|
11802
11802
|
res.resume();
|
|
11803
11803
|
const ok = res.statusCode !== void 0 && res.statusCode >= 200 && res.statusCode < 300;
|
|
11804
11804
|
if (!ok) log.warn("history:post", `${endpoint} \u2192 HTTP ${res.statusCode}`);
|
|
11805
|
-
|
|
11805
|
+
resolve4(ok);
|
|
11806
11806
|
}
|
|
11807
11807
|
);
|
|
11808
11808
|
req.on("error", (err) => {
|
|
11809
11809
|
log.warn("history:post", `${endpoint} network error`, err);
|
|
11810
|
-
|
|
11810
|
+
resolve4(false);
|
|
11811
11811
|
});
|
|
11812
11812
|
req.on("timeout", () => {
|
|
11813
11813
|
log.warn("history:post", `${endpoint} timeout after 15s`);
|
|
11814
11814
|
req.destroy();
|
|
11815
|
-
|
|
11815
|
+
resolve4(false);
|
|
11816
11816
|
});
|
|
11817
11817
|
req.write(payload);
|
|
11818
11818
|
req.end();
|
|
@@ -12206,6 +12206,7 @@ var HistoryService = class _HistoryService {
|
|
|
12206
12206
|
|
|
12207
12207
|
// src/services/file-watcher.service.ts
|
|
12208
12208
|
var import_child_process7 = require("child_process");
|
|
12209
|
+
var fs21 = __toESM(require("fs"));
|
|
12209
12210
|
var os22 = __toESM(require("os"));
|
|
12210
12211
|
var path25 = __toESM(require("path"));
|
|
12211
12212
|
|
|
@@ -12295,7 +12296,7 @@ var _transport3 = {
|
|
|
12295
12296
|
post: _post2
|
|
12296
12297
|
};
|
|
12297
12298
|
function _post2(url, headers, payload) {
|
|
12298
|
-
return new Promise((
|
|
12299
|
+
return new Promise((resolve4, reject) => {
|
|
12299
12300
|
let settled = false;
|
|
12300
12301
|
const u2 = new URL(url);
|
|
12301
12302
|
const lib = u2.protocol === "https:" ? https5 : http5;
|
|
@@ -12320,7 +12321,7 @@ function _post2(url, headers, payload) {
|
|
|
12320
12321
|
res.on("end", () => {
|
|
12321
12322
|
if (settled) return;
|
|
12322
12323
|
settled = true;
|
|
12323
|
-
|
|
12324
|
+
resolve4({ statusCode: res.statusCode ?? 0, body });
|
|
12324
12325
|
});
|
|
12325
12326
|
}
|
|
12326
12327
|
);
|
|
@@ -12380,6 +12381,30 @@ var _chokidarSeam = {
|
|
|
12380
12381
|
}
|
|
12381
12382
|
}
|
|
12382
12383
|
};
|
|
12384
|
+
function findGitRoot(startDir) {
|
|
12385
|
+
return _findGitRootSeam.resolve(startDir);
|
|
12386
|
+
}
|
|
12387
|
+
var _findGitRootSeam = {
|
|
12388
|
+
resolve: _defaultFindGitRoot
|
|
12389
|
+
};
|
|
12390
|
+
function _defaultFindGitRoot(startDir) {
|
|
12391
|
+
let dir = path25.resolve(startDir);
|
|
12392
|
+
const seen = /* @__PURE__ */ new Set();
|
|
12393
|
+
for (let i = 0; i < 256; i++) {
|
|
12394
|
+
if (seen.has(dir)) return null;
|
|
12395
|
+
seen.add(dir);
|
|
12396
|
+
try {
|
|
12397
|
+
const gitPath = path25.join(dir, ".git");
|
|
12398
|
+
const stat3 = fs21.statSync(gitPath, { throwIfNoEntry: false });
|
|
12399
|
+
if (stat3 && (stat3.isDirectory() || stat3.isFile())) return dir;
|
|
12400
|
+
} catch {
|
|
12401
|
+
}
|
|
12402
|
+
const parent = path25.dirname(dir);
|
|
12403
|
+
if (parent === dir) return null;
|
|
12404
|
+
dir = parent;
|
|
12405
|
+
}
|
|
12406
|
+
return null;
|
|
12407
|
+
}
|
|
12383
12408
|
var FileWatcherService = class {
|
|
12384
12409
|
constructor(opts) {
|
|
12385
12410
|
this.opts = opts;
|
|
@@ -12389,6 +12414,13 @@ var FileWatcherService = class {
|
|
|
12389
12414
|
watcher = null;
|
|
12390
12415
|
pending = /* @__PURE__ */ new Map();
|
|
12391
12416
|
apiBase;
|
|
12417
|
+
/**
|
|
12418
|
+
* Cache of (file directory → git root). Resolved lazily on each
|
|
12419
|
+
* file event so brand-new sub-repos under the workingDir light up
|
|
12420
|
+
* automatically; cached so a hot session with thousands of writes
|
|
12421
|
+
* doesn't hammer `fs.statSync` for every event.
|
|
12422
|
+
*/
|
|
12423
|
+
gitRootByDir = /* @__PURE__ */ new Map();
|
|
12392
12424
|
stopped = false;
|
|
12393
12425
|
/**
|
|
12394
12426
|
* Start watching `opts.workingDir`. Idempotent (second call is a
|
|
@@ -12531,67 +12563,82 @@ var FileWatcherService = class {
|
|
|
12531
12563
|
}
|
|
12532
12564
|
async emitForFile(absPath, changeType) {
|
|
12533
12565
|
if (this.stopped) return;
|
|
12534
|
-
const
|
|
12535
|
-
|
|
12566
|
+
const fileDir = path25.dirname(absPath);
|
|
12567
|
+
let gitRoot = this.gitRootByDir.get(fileDir);
|
|
12568
|
+
if (gitRoot === void 0) {
|
|
12569
|
+
gitRoot = findGitRoot(fileDir);
|
|
12570
|
+
this.gitRootByDir.set(fileDir, gitRoot);
|
|
12571
|
+
}
|
|
12572
|
+
if (!gitRoot) {
|
|
12573
|
+
log.trace(
|
|
12574
|
+
"fileWatcher",
|
|
12575
|
+
`no enclosing git repo for ${absPath} \u2014 suppressing emit`
|
|
12576
|
+
);
|
|
12536
12577
|
return;
|
|
12537
12578
|
}
|
|
12579
|
+
const relPathInRepo = path25.relative(gitRoot, absPath);
|
|
12580
|
+
if (!relPathInRepo || relPathInRepo.startsWith("..")) return;
|
|
12581
|
+
const repoPath = path25.relative(this.opts.workingDir, gitRoot);
|
|
12582
|
+
const repoName = path25.basename(gitRoot);
|
|
12538
12583
|
let diffText = "";
|
|
12539
12584
|
let fileStatus = "modified";
|
|
12540
12585
|
if (changeType === "unlink") {
|
|
12541
|
-
const diff = await this.gitDiff(
|
|
12586
|
+
const diff = await this.gitDiff(gitRoot, relPathInRepo);
|
|
12542
12587
|
if (diff !== null && diff.trim().length > 0) {
|
|
12543
12588
|
diffText = diff;
|
|
12544
12589
|
} else {
|
|
12545
12590
|
await this.postFileChanged({
|
|
12546
12591
|
sessionId: this.opts.sessionId,
|
|
12547
12592
|
pluginId: this.opts.pluginId,
|
|
12548
|
-
filePath:
|
|
12593
|
+
filePath: relPathInRepo,
|
|
12549
12594
|
fileStatus: "deleted",
|
|
12550
12595
|
linesAdded: 0,
|
|
12551
12596
|
linesRemoved: 0,
|
|
12552
|
-
hunkCount: 0
|
|
12597
|
+
hunkCount: 0,
|
|
12598
|
+
repoPath,
|
|
12599
|
+
repoName
|
|
12553
12600
|
});
|
|
12554
12601
|
return;
|
|
12555
12602
|
}
|
|
12556
12603
|
fileStatus = "deleted";
|
|
12557
12604
|
} else {
|
|
12558
|
-
const diff = await this.gitDiff(
|
|
12605
|
+
const diff = await this.gitDiff(gitRoot, relPathInRepo);
|
|
12559
12606
|
if (diff === null) {
|
|
12560
12607
|
log.warn(
|
|
12561
12608
|
"fileWatcher",
|
|
12562
|
-
`git diff failed for ${
|
|
12609
|
+
`git diff failed for ${relPathInRepo} in ${gitRoot} \u2014 suppressing emit`
|
|
12563
12610
|
);
|
|
12564
|
-
await this.postFileChanged({
|
|
12565
|
-
sessionId: this.opts.sessionId,
|
|
12566
|
-
pluginId: this.opts.pluginId,
|
|
12567
|
-
filePath: relPath,
|
|
12568
|
-
fileStatus: changeType === "add" ? "added" : "modified",
|
|
12569
|
-
linesAdded: 0,
|
|
12570
|
-
linesRemoved: 0,
|
|
12571
|
-
hunkCount: 0
|
|
12572
|
-
});
|
|
12573
12611
|
return;
|
|
12574
12612
|
}
|
|
12575
12613
|
diffText = diff;
|
|
12576
12614
|
}
|
|
12577
12615
|
const parsed = parseUnifiedDiff(diffText);
|
|
12616
|
+
if (changeType !== "unlink" && parsed.totalLinesAdded === 0 && parsed.totalLinesRemoved === 0 && parsed.hunks.length === 0) {
|
|
12617
|
+
log.trace(
|
|
12618
|
+
"fileWatcher",
|
|
12619
|
+
`no content delta for ${relPathInRepo} in ${repoName} \u2014 suppressing emit`
|
|
12620
|
+
);
|
|
12621
|
+
return;
|
|
12622
|
+
}
|
|
12578
12623
|
const finalStatus = parsed.fileStatus !== "modified" ? parsed.fileStatus : changeType === "add" ? "added" : changeType === "unlink" ? "deleted" : fileStatus;
|
|
12579
12624
|
const reviewStatus = parsed.hunks.length > 0 ? "awaiting_review" : void 0;
|
|
12580
12625
|
await this.postFileChanged({
|
|
12581
12626
|
sessionId: this.opts.sessionId,
|
|
12582
12627
|
pluginId: this.opts.pluginId,
|
|
12583
|
-
filePath:
|
|
12628
|
+
filePath: relPathInRepo,
|
|
12584
12629
|
fileStatus: finalStatus,
|
|
12585
12630
|
linesAdded: parsed.totalLinesAdded,
|
|
12586
12631
|
linesRemoved: parsed.totalLinesRemoved,
|
|
12587
12632
|
hunkCount: parsed.hunks.length,
|
|
12588
|
-
reviewStatus
|
|
12633
|
+
reviewStatus,
|
|
12634
|
+
repoPath,
|
|
12635
|
+
repoName
|
|
12589
12636
|
});
|
|
12590
12637
|
for (const hunk of parsed.hunks) {
|
|
12591
12638
|
await this.postReviewHunk({
|
|
12592
12639
|
sessionId: this.opts.sessionId,
|
|
12593
12640
|
pluginId: this.opts.pluginId,
|
|
12594
|
-
filePath:
|
|
12641
|
+
filePath: relPathInRepo,
|
|
12595
12642
|
fileStatus: finalStatus,
|
|
12596
12643
|
hunkHeader: hunk.header,
|
|
12597
12644
|
lines: hunk.lines,
|
|
@@ -12602,9 +12649,11 @@ var FileWatcherService = class {
|
|
|
12602
12649
|
}
|
|
12603
12650
|
/**
|
|
12604
12651
|
* Compute the unified diff for a single path relative to the
|
|
12605
|
-
*
|
|
12606
|
-
*
|
|
12607
|
-
*
|
|
12652
|
+
* enclosing git repo (NOT the CLI's workingDir — see
|
|
12653
|
+
* `emitForFile`'s walk-up). Returns `null` when git is unavailable
|
|
12654
|
+
* or the discovered repo root is no longer a repo (race with
|
|
12655
|
+
* external removal). Returns `''` when there's no diff (a touch
|
|
12656
|
+
* that didn't change content).
|
|
12608
12657
|
*
|
|
12609
12658
|
* For tracked files we use `git diff --no-color -- <path>` which
|
|
12610
12659
|
* compares the worktree against HEAD's blob.
|
|
@@ -12612,16 +12661,16 @@ var FileWatcherService = class {
|
|
|
12612
12661
|
* zero) we use `git diff --no-color --no-index /dev/null <path>`,
|
|
12613
12662
|
* which produces an "added"-shaped diff against an empty source.
|
|
12614
12663
|
*/
|
|
12615
|
-
async gitDiff(relPath) {
|
|
12664
|
+
async gitDiff(repoRoot, relPath) {
|
|
12616
12665
|
const tracked = await runGit(
|
|
12617
|
-
|
|
12666
|
+
repoRoot,
|
|
12618
12667
|
["diff", "--no-color", "--", relPath]
|
|
12619
12668
|
);
|
|
12620
12669
|
if (tracked === null) return null;
|
|
12621
12670
|
if (tracked.trim().length > 0) return tracked;
|
|
12622
12671
|
const devNull = process.platform === "win32" ? "NUL" : "/dev/null";
|
|
12623
12672
|
const untracked = await runGit(
|
|
12624
|
-
|
|
12673
|
+
repoRoot,
|
|
12625
12674
|
["diff", "--no-color", "--no-index", "--", devNull, relPath],
|
|
12626
12675
|
{ allowNonZeroExit: true }
|
|
12627
12676
|
);
|
|
@@ -12689,12 +12738,12 @@ var _gitSeam = {
|
|
|
12689
12738
|
run: _runGitImpl
|
|
12690
12739
|
};
|
|
12691
12740
|
async function _runGitImpl(cwd, args2, opts = {}) {
|
|
12692
|
-
return new Promise((
|
|
12741
|
+
return new Promise((resolve4) => {
|
|
12693
12742
|
let proc;
|
|
12694
12743
|
try {
|
|
12695
12744
|
proc = (0, import_child_process7.spawn)("git", args2, { cwd, env: process.env });
|
|
12696
12745
|
} catch {
|
|
12697
|
-
|
|
12746
|
+
resolve4(null);
|
|
12698
12747
|
return;
|
|
12699
12748
|
}
|
|
12700
12749
|
let stdout = "";
|
|
@@ -12705,13 +12754,13 @@ async function _runGitImpl(cwd, args2, opts = {}) {
|
|
|
12705
12754
|
proc.stderr?.on("data", (c2) => {
|
|
12706
12755
|
stderr += c2.toString();
|
|
12707
12756
|
});
|
|
12708
|
-
proc.on("error", () =>
|
|
12757
|
+
proc.on("error", () => resolve4(null));
|
|
12709
12758
|
proc.on("close", (code) => {
|
|
12710
12759
|
if (code === 0 || opts.allowNonZeroExit) {
|
|
12711
|
-
|
|
12760
|
+
resolve4(stdout);
|
|
12712
12761
|
} else {
|
|
12713
12762
|
log.trace("fileWatcher", `git ${args2.join(" ")} exited ${code} stderr=${stderr.slice(0, 200)}`);
|
|
12714
|
-
|
|
12763
|
+
resolve4(null);
|
|
12715
12764
|
}
|
|
12716
12765
|
});
|
|
12717
12766
|
});
|
|
@@ -12731,7 +12780,7 @@ var _transport4 = {
|
|
|
12731
12780
|
get: _get
|
|
12732
12781
|
};
|
|
12733
12782
|
function _post3(url, headers, payload) {
|
|
12734
|
-
return new Promise((
|
|
12783
|
+
return new Promise((resolve4, reject) => {
|
|
12735
12784
|
let settled = false;
|
|
12736
12785
|
const u2 = new URL(url);
|
|
12737
12786
|
const lib = u2.protocol === "https:" ? https6 : http6;
|
|
@@ -12756,7 +12805,7 @@ function _post3(url, headers, payload) {
|
|
|
12756
12805
|
res.on("end", () => {
|
|
12757
12806
|
if (settled) return;
|
|
12758
12807
|
settled = true;
|
|
12759
|
-
|
|
12808
|
+
resolve4({ statusCode: res.statusCode ?? 0, body });
|
|
12760
12809
|
});
|
|
12761
12810
|
}
|
|
12762
12811
|
);
|
|
@@ -12773,7 +12822,7 @@ function _post3(url, headers, payload) {
|
|
|
12773
12822
|
});
|
|
12774
12823
|
}
|
|
12775
12824
|
function _get(url, headers) {
|
|
12776
|
-
return new Promise((
|
|
12825
|
+
return new Promise((resolve4, reject) => {
|
|
12777
12826
|
let settled = false;
|
|
12778
12827
|
const u2 = new URL(url);
|
|
12779
12828
|
const lib = u2.protocol === "https:" ? https6 : http6;
|
|
@@ -12797,7 +12846,7 @@ function _get(url, headers) {
|
|
|
12797
12846
|
res.on("end", () => {
|
|
12798
12847
|
if (settled) return;
|
|
12799
12848
|
settled = true;
|
|
12800
|
-
|
|
12849
|
+
resolve4({ statusCode: res.statusCode ?? 0, body });
|
|
12801
12850
|
});
|
|
12802
12851
|
}
|
|
12803
12852
|
);
|
|
@@ -13180,7 +13229,7 @@ function buildKeepAlive(ctx) {
|
|
|
13180
13229
|
let timer = null;
|
|
13181
13230
|
async function setIdleTimeout(minutes) {
|
|
13182
13231
|
if (!ctx.inCodespace || !ctx.codespaceName) return;
|
|
13183
|
-
await new Promise((
|
|
13232
|
+
await new Promise((resolve4) => {
|
|
13184
13233
|
const proc = (0, import_child_process8.spawn)(
|
|
13185
13234
|
"gh",
|
|
13186
13235
|
[
|
|
@@ -13194,8 +13243,8 @@ function buildKeepAlive(ctx) {
|
|
|
13194
13243
|
{ stdio: "ignore", detached: true }
|
|
13195
13244
|
);
|
|
13196
13245
|
proc.unref();
|
|
13197
|
-
proc.on("exit", () =>
|
|
13198
|
-
proc.on("error", () =>
|
|
13246
|
+
proc.on("exit", () => resolve4());
|
|
13247
|
+
proc.on("error", () => resolve4());
|
|
13199
13248
|
});
|
|
13200
13249
|
}
|
|
13201
13250
|
return {
|
|
@@ -13218,7 +13267,7 @@ function buildKeepAlive(ctx) {
|
|
|
13218
13267
|
}
|
|
13219
13268
|
|
|
13220
13269
|
// src/commands/start/handlers.ts
|
|
13221
|
-
var
|
|
13270
|
+
var fs24 = __toESM(require("fs"));
|
|
13222
13271
|
var os23 = __toESM(require("os"));
|
|
13223
13272
|
var path29 = __toESM(require("path"));
|
|
13224
13273
|
var import_crypto4 = require("crypto");
|
|
@@ -13278,7 +13327,7 @@ function parsePayload2(schema, raw) {
|
|
|
13278
13327
|
}
|
|
13279
13328
|
|
|
13280
13329
|
// src/services/file-ops.service.ts
|
|
13281
|
-
var
|
|
13330
|
+
var fs22 = __toESM(require("fs/promises"));
|
|
13282
13331
|
var path26 = __toESM(require("path"));
|
|
13283
13332
|
var MAX_FILE_BYTES = 5 * 1024 * 1024;
|
|
13284
13333
|
var MAX_WALK_DEPTH = 6;
|
|
@@ -13319,7 +13368,7 @@ function isUnder(parent, candidate) {
|
|
|
13319
13368
|
}
|
|
13320
13369
|
async function isExistingFile(absPath) {
|
|
13321
13370
|
try {
|
|
13322
|
-
const stat3 = await
|
|
13371
|
+
const stat3 = await fs22.stat(absPath);
|
|
13323
13372
|
return stat3.isFile();
|
|
13324
13373
|
} catch {
|
|
13325
13374
|
return false;
|
|
@@ -13332,7 +13381,7 @@ async function walkForSuffix(dir, needleVariants, depth, ctx) {
|
|
|
13332
13381
|
ctx.visited++;
|
|
13333
13382
|
let entries = [];
|
|
13334
13383
|
try {
|
|
13335
|
-
entries = await
|
|
13384
|
+
entries = await fs22.readdir(dir, { withFileTypes: true });
|
|
13336
13385
|
} catch {
|
|
13337
13386
|
return;
|
|
13338
13387
|
}
|
|
@@ -13393,11 +13442,11 @@ async function readProjectFile(rawPath) {
|
|
|
13393
13442
|
if (!abs) {
|
|
13394
13443
|
return { error: `File not found in the project tree: ${rawPath}` };
|
|
13395
13444
|
}
|
|
13396
|
-
const stat3 = await
|
|
13445
|
+
const stat3 = await fs22.stat(abs);
|
|
13397
13446
|
if (stat3.size > MAX_FILE_BYTES) {
|
|
13398
13447
|
return { error: `File too large (${(stat3.size / 1024 / 1024).toFixed(1)} MB > ${MAX_FILE_BYTES / 1024 / 1024} MB).` };
|
|
13399
13448
|
}
|
|
13400
|
-
const buf = await
|
|
13449
|
+
const buf = await fs22.readFile(abs);
|
|
13401
13450
|
if (looksBinary(buf)) {
|
|
13402
13451
|
return { error: "Binary file \u2014 refusing to open in a code editor." };
|
|
13403
13452
|
}
|
|
@@ -13416,8 +13465,8 @@ async function writeProjectFile(rawPath, content) {
|
|
|
13416
13465
|
if (Buffer.byteLength(content, "utf-8") > MAX_FILE_BYTES) {
|
|
13417
13466
|
return { error: "Content too large." };
|
|
13418
13467
|
}
|
|
13419
|
-
await
|
|
13420
|
-
await
|
|
13468
|
+
await fs22.mkdir(path26.dirname(abs), { recursive: true });
|
|
13469
|
+
await fs22.writeFile(abs, content, "utf-8");
|
|
13421
13470
|
return { ok: true };
|
|
13422
13471
|
} catch (e) {
|
|
13423
13472
|
const msg = e instanceof Error ? e.message : "Write failed";
|
|
@@ -13428,7 +13477,7 @@ async function writeProjectFile(rawPath, content) {
|
|
|
13428
13477
|
// src/services/project-ops.service.ts
|
|
13429
13478
|
var import_child_process9 = require("child_process");
|
|
13430
13479
|
var import_util2 = require("util");
|
|
13431
|
-
var
|
|
13480
|
+
var fs23 = __toESM(require("fs/promises"));
|
|
13432
13481
|
var path27 = __toESM(require("path"));
|
|
13433
13482
|
var execFileP3 = (0, import_util2.promisify)(import_child_process9.execFile);
|
|
13434
13483
|
var PROJECT_IGNORE = /* @__PURE__ */ new Set([
|
|
@@ -13477,7 +13526,7 @@ async function listProjectFiles(opts = {}) {
|
|
|
13477
13526
|
}
|
|
13478
13527
|
let entries = [];
|
|
13479
13528
|
try {
|
|
13480
|
-
entries = await
|
|
13529
|
+
entries = await fs23.readdir(dir, { withFileTypes: true });
|
|
13481
13530
|
} catch {
|
|
13482
13531
|
return;
|
|
13483
13532
|
}
|
|
@@ -13498,7 +13547,7 @@ async function listProjectFiles(opts = {}) {
|
|
|
13498
13547
|
}
|
|
13499
13548
|
let size = 0;
|
|
13500
13549
|
try {
|
|
13501
|
-
const st3 = await
|
|
13550
|
+
const st3 = await fs23.stat(full);
|
|
13502
13551
|
size = st3.size;
|
|
13503
13552
|
} catch {
|
|
13504
13553
|
}
|
|
@@ -13601,7 +13650,7 @@ async function gitStatus(cwd) {
|
|
|
13601
13650
|
try {
|
|
13602
13651
|
const gitDir = (await git(["rev-parse", "--git-dir"], root)).stdout.trim();
|
|
13603
13652
|
const mergeHead = path27.isAbsolute(gitDir) ? path27.join(gitDir, "MERGE_HEAD") : path27.join(root, gitDir, "MERGE_HEAD");
|
|
13604
|
-
await
|
|
13653
|
+
await fs23.access(mergeHead);
|
|
13605
13654
|
hasMergeInProgress = true;
|
|
13606
13655
|
} catch {
|
|
13607
13656
|
}
|
|
@@ -13747,7 +13796,7 @@ async function jsSearchFiles(opts, cwd, cap) {
|
|
|
13747
13796
|
}
|
|
13748
13797
|
let content = "";
|
|
13749
13798
|
try {
|
|
13750
|
-
content = await
|
|
13799
|
+
content = await fs23.readFile(path27.join(cwd, f.path), "utf8");
|
|
13751
13800
|
} catch {
|
|
13752
13801
|
continue;
|
|
13753
13802
|
}
|
|
@@ -14031,7 +14080,7 @@ var pendingAttachmentFiles = /* @__PURE__ */ new Set();
|
|
|
14031
14080
|
function cleanupAttachmentTempFiles() {
|
|
14032
14081
|
for (const p2 of pendingAttachmentFiles) {
|
|
14033
14082
|
try {
|
|
14034
|
-
|
|
14083
|
+
fs24.unlinkSync(p2);
|
|
14035
14084
|
} catch {
|
|
14036
14085
|
}
|
|
14037
14086
|
}
|
|
@@ -14041,7 +14090,7 @@ function saveFilesTemp(files) {
|
|
|
14041
14090
|
return files.filter(({ base64 }) => base64 && base64.length > 0).map(({ filename, base64 }) => {
|
|
14042
14091
|
const safeName = filename.replace(/[^a-zA-Z0-9._-]/g, "_").slice(0, 80);
|
|
14043
14092
|
const tmpPath = path29.join(os23.tmpdir(), `codeam-${(0, import_crypto4.randomUUID)()}-${safeName}`);
|
|
14044
|
-
|
|
14093
|
+
fs24.writeFileSync(tmpPath, Buffer.from(base64, "base64"));
|
|
14045
14094
|
pendingAttachmentFiles.add(tmpPath);
|
|
14046
14095
|
return tmpPath;
|
|
14047
14096
|
});
|
|
@@ -14061,7 +14110,7 @@ var startTask = (ctx, _cmd, parsed) => {
|
|
|
14061
14110
|
setTimeout(() => {
|
|
14062
14111
|
for (const p2 of paths) {
|
|
14063
14112
|
try {
|
|
14064
|
-
|
|
14113
|
+
fs24.unlinkSync(p2);
|
|
14065
14114
|
} catch {
|
|
14066
14115
|
}
|
|
14067
14116
|
pendingAttachmentFiles.delete(p2);
|
|
@@ -14627,7 +14676,7 @@ async function pair(args2 = []) {
|
|
|
14627
14676
|
waitSpin.message(waitMessage());
|
|
14628
14677
|
}, 1e3);
|
|
14629
14678
|
countdownInterval.unref?.();
|
|
14630
|
-
await new Promise((
|
|
14679
|
+
await new Promise((resolve4) => {
|
|
14631
14680
|
let stopPolling = null;
|
|
14632
14681
|
function sigintHandler() {
|
|
14633
14682
|
clearInterval(countdownInterval);
|
|
@@ -14667,7 +14716,7 @@ async function pair(args2 = []) {
|
|
|
14667
14716
|
});
|
|
14668
14717
|
showSuccess(`Paired with ${info.userName} (${info.plan})`);
|
|
14669
14718
|
console.log("");
|
|
14670
|
-
|
|
14719
|
+
resolve4();
|
|
14671
14720
|
},
|
|
14672
14721
|
() => {
|
|
14673
14722
|
clearInterval(countdownInterval);
|
|
@@ -14683,7 +14732,7 @@ async function pair(args2 = []) {
|
|
|
14683
14732
|
}
|
|
14684
14733
|
|
|
14685
14734
|
// src/commands/pair-auto.ts
|
|
14686
|
-
var
|
|
14735
|
+
var fs25 = __toESM(require("fs"));
|
|
14687
14736
|
var os24 = __toESM(require("os"));
|
|
14688
14737
|
var import_crypto6 = require("crypto");
|
|
14689
14738
|
var API_BASE7 = resolveApiBaseUrl();
|
|
@@ -14703,10 +14752,10 @@ function readTokenFromArgs(args2) {
|
|
|
14703
14752
|
if (fileFlag) {
|
|
14704
14753
|
const path37 = fileFlag.slice("--token-file=".length);
|
|
14705
14754
|
try {
|
|
14706
|
-
const content =
|
|
14755
|
+
const content = fs25.readFileSync(path37, "utf8").trim();
|
|
14707
14756
|
if (content.length === 0) fail(`--token-file ${path37} is empty`);
|
|
14708
14757
|
try {
|
|
14709
|
-
|
|
14758
|
+
fs25.unlinkSync(path37);
|
|
14710
14759
|
} catch {
|
|
14711
14760
|
}
|
|
14712
14761
|
return content;
|
|
@@ -15003,12 +15052,12 @@ var GitHubCodespacesProvider = class {
|
|
|
15003
15052
|
}
|
|
15004
15053
|
if (!isAuthed) {
|
|
15005
15054
|
resetStdinForChild();
|
|
15006
|
-
await new Promise((
|
|
15055
|
+
await new Promise((resolve4, reject) => {
|
|
15007
15056
|
const proc = (0, import_child_process12.spawn)("gh", ["auth", "login", "-s", "codespace,repo,read:user"], {
|
|
15008
15057
|
stdio: "inherit"
|
|
15009
15058
|
});
|
|
15010
15059
|
proc.on("exit", (code) => {
|
|
15011
|
-
if (code === 0)
|
|
15060
|
+
if (code === 0) resolve4();
|
|
15012
15061
|
else reject(new Error("gh auth login failed."));
|
|
15013
15062
|
});
|
|
15014
15063
|
proc.on("error", reject);
|
|
@@ -15037,13 +15086,13 @@ var GitHubCodespacesProvider = class {
|
|
|
15037
15086
|
}
|
|
15038
15087
|
wt(noteLines.join("\n"), "One more permission needed");
|
|
15039
15088
|
resetStdinForChild();
|
|
15040
|
-
const refreshCode = await new Promise((
|
|
15089
|
+
const refreshCode = await new Promise((resolve4, reject) => {
|
|
15041
15090
|
const proc = (0, import_child_process12.spawn)(
|
|
15042
15091
|
"gh",
|
|
15043
15092
|
["auth", "refresh", "-h", "github.com", "-s", "codespace"],
|
|
15044
15093
|
{ stdio: "inherit" }
|
|
15045
15094
|
);
|
|
15046
|
-
proc.on("exit", (code) =>
|
|
15095
|
+
proc.on("exit", (code) => resolve4(code ?? 1));
|
|
15047
15096
|
proc.on("error", reject);
|
|
15048
15097
|
});
|
|
15049
15098
|
if (refreshCode !== 0) {
|
|
@@ -15187,10 +15236,10 @@ var GitHubCodespacesProvider = class {
|
|
|
15187
15236
|
if (q(proceed) || !proceed) return;
|
|
15188
15237
|
O2.step(`Installing gh via ${installCmd.describe}\u2026`);
|
|
15189
15238
|
resetStdinForChild();
|
|
15190
|
-
const ok = await new Promise((
|
|
15239
|
+
const ok = await new Promise((resolve4) => {
|
|
15191
15240
|
const proc = (0, import_child_process12.spawn)(installCmd.exe, installCmd.args, { stdio: "inherit" });
|
|
15192
|
-
proc.on("exit", (code) =>
|
|
15193
|
-
proc.on("error", () =>
|
|
15241
|
+
proc.on("exit", (code) => resolve4(code === 0));
|
|
15242
|
+
proc.on("error", () => resolve4(false));
|
|
15194
15243
|
});
|
|
15195
15244
|
if (ok) O2.success("gh installed");
|
|
15196
15245
|
else O2.error("gh install failed");
|
|
@@ -15214,14 +15263,14 @@ var GitHubCodespacesProvider = class {
|
|
|
15214
15263
|
"Expanding GitHub scopes"
|
|
15215
15264
|
);
|
|
15216
15265
|
resetStdinForChild();
|
|
15217
|
-
await new Promise((
|
|
15266
|
+
await new Promise((resolve4, reject) => {
|
|
15218
15267
|
const proc = (0, import_child_process12.spawn)(
|
|
15219
15268
|
"gh",
|
|
15220
15269
|
["auth", "refresh", "-h", "github.com", "-s", "repo,read:org"],
|
|
15221
15270
|
{ stdio: "inherit" }
|
|
15222
15271
|
);
|
|
15223
15272
|
proc.on("exit", (code) => {
|
|
15224
|
-
if (code === 0)
|
|
15273
|
+
if (code === 0) resolve4();
|
|
15225
15274
|
else reject(new Error(
|
|
15226
15275
|
"gh auth refresh failed. Re-run `gh auth refresh -h github.com -s repo,read:org` manually."
|
|
15227
15276
|
));
|
|
@@ -15392,13 +15441,13 @@ var GitHubCodespacesProvider = class {
|
|
|
15392
15441
|
}
|
|
15393
15442
|
async streamCommand(workspaceId, command2) {
|
|
15394
15443
|
resetStdinForChild();
|
|
15395
|
-
return new Promise((
|
|
15444
|
+
return new Promise((resolve4, reject) => {
|
|
15396
15445
|
const proc = (0, import_child_process12.spawn)(
|
|
15397
15446
|
"gh",
|
|
15398
15447
|
["codespace", "ssh", "-c", workspaceId, "--", "-tt", command2],
|
|
15399
15448
|
{ stdio: "inherit" }
|
|
15400
15449
|
);
|
|
15401
|
-
proc.on("exit", (code) =>
|
|
15450
|
+
proc.on("exit", (code) => resolve4({ code: code ?? 0 }));
|
|
15402
15451
|
proc.on("error", reject);
|
|
15403
15452
|
});
|
|
15404
15453
|
}
|
|
@@ -15419,7 +15468,7 @@ var GitHubCodespacesProvider = class {
|
|
|
15419
15468
|
"--",
|
|
15420
15469
|
`mkdir -p ${shellQuote(remoteDir)} && tar -xzf - -C ${shellQuote(remoteDir)}`
|
|
15421
15470
|
];
|
|
15422
|
-
await new Promise((
|
|
15471
|
+
await new Promise((resolve4, reject) => {
|
|
15423
15472
|
const tar = (0, import_child_process12.spawn)("tar", tarArgs, {
|
|
15424
15473
|
stdio: ["ignore", "pipe", "pipe"],
|
|
15425
15474
|
env: tarEnv
|
|
@@ -15439,7 +15488,7 @@ var GitHubCodespacesProvider = class {
|
|
|
15439
15488
|
ssh.on("error", reject);
|
|
15440
15489
|
ssh.on("exit", (code) => {
|
|
15441
15490
|
if (code === 0) {
|
|
15442
|
-
|
|
15491
|
+
resolve4();
|
|
15443
15492
|
} else {
|
|
15444
15493
|
const reason = (sshErr || tarErr || `exit ${code}`).trim().slice(0, 500);
|
|
15445
15494
|
reject(new Error(`Remote tar failed: ${reason}`));
|
|
@@ -15457,7 +15506,7 @@ var GitHubCodespacesProvider = class {
|
|
|
15457
15506
|
parts.push(`chmod ${options.mode.toString(8)} ${shellQuote(remotePath)}`);
|
|
15458
15507
|
}
|
|
15459
15508
|
const cmd = parts.join(" && ");
|
|
15460
|
-
await new Promise((
|
|
15509
|
+
await new Promise((resolve4, reject) => {
|
|
15461
15510
|
const proc = (0, import_child_process12.spawn)(
|
|
15462
15511
|
"gh",
|
|
15463
15512
|
["codespace", "ssh", "-c", workspaceId, "--", cmd],
|
|
@@ -15469,7 +15518,7 @@ var GitHubCodespacesProvider = class {
|
|
|
15469
15518
|
});
|
|
15470
15519
|
proc.on("error", reject);
|
|
15471
15520
|
proc.on("exit", (code) => {
|
|
15472
|
-
if (code === 0)
|
|
15521
|
+
if (code === 0) resolve4();
|
|
15473
15522
|
else reject(new Error(`Remote write failed: ${(stderr || `exit ${code}`).trim().slice(0, 500)}`));
|
|
15474
15523
|
});
|
|
15475
15524
|
proc.stdin?.write(contents);
|
|
@@ -15559,10 +15608,10 @@ var GitpodProvider = class {
|
|
|
15559
15608
|
"Authenticating Gitpod"
|
|
15560
15609
|
);
|
|
15561
15610
|
resetStdinForChild2();
|
|
15562
|
-
await new Promise((
|
|
15611
|
+
await new Promise((resolve4, reject) => {
|
|
15563
15612
|
const proc = (0, import_child_process13.spawn)("gitpod", ["login"], { stdio: "inherit" });
|
|
15564
15613
|
proc.on("exit", (code) => {
|
|
15565
|
-
if (code === 0)
|
|
15614
|
+
if (code === 0) resolve4();
|
|
15566
15615
|
else reject(new Error("gitpod login failed."));
|
|
15567
15616
|
});
|
|
15568
15617
|
proc.on("error", reject);
|
|
@@ -15711,13 +15760,13 @@ var GitpodProvider = class {
|
|
|
15711
15760
|
}
|
|
15712
15761
|
async streamCommand(workspaceId, command2) {
|
|
15713
15762
|
resetStdinForChild2();
|
|
15714
|
-
return new Promise((
|
|
15763
|
+
return new Promise((resolve4, reject) => {
|
|
15715
15764
|
const proc = (0, import_child_process13.spawn)(
|
|
15716
15765
|
"gitpod",
|
|
15717
15766
|
["workspace", "ssh", workspaceId, "--", "-tt", command2],
|
|
15718
15767
|
{ stdio: "inherit" }
|
|
15719
15768
|
);
|
|
15720
|
-
proc.on("exit", (code) =>
|
|
15769
|
+
proc.on("exit", (code) => resolve4({ code: code ?? 0 }));
|
|
15721
15770
|
proc.on("error", reject);
|
|
15722
15771
|
});
|
|
15723
15772
|
}
|
|
@@ -15731,7 +15780,7 @@ var GitpodProvider = class {
|
|
|
15731
15780
|
tarArgs.push(".");
|
|
15732
15781
|
const tarEnv = { ...process.env, COPYFILE_DISABLE: "1" };
|
|
15733
15782
|
const remoteCmd = `mkdir -p ${shellQuote2(remoteDir)} && tar -xzf - -C ${shellQuote2(remoteDir)}`;
|
|
15734
|
-
await new Promise((
|
|
15783
|
+
await new Promise((resolve4, reject) => {
|
|
15735
15784
|
const tar = (0, import_child_process13.spawn)("tar", tarArgs, {
|
|
15736
15785
|
stdio: ["ignore", "pipe", "pipe"],
|
|
15737
15786
|
env: tarEnv
|
|
@@ -15752,7 +15801,7 @@ var GitpodProvider = class {
|
|
|
15752
15801
|
tar.on("error", reject);
|
|
15753
15802
|
ssh.on("error", reject);
|
|
15754
15803
|
ssh.on("exit", (code) => {
|
|
15755
|
-
if (code === 0)
|
|
15804
|
+
if (code === 0) resolve4();
|
|
15756
15805
|
else reject(new Error(`Remote tar failed: ${(sshErr || tarErr || `exit ${code}`).trim().slice(0, 500)}`));
|
|
15757
15806
|
});
|
|
15758
15807
|
});
|
|
@@ -15767,7 +15816,7 @@ var GitpodProvider = class {
|
|
|
15767
15816
|
parts.push(`chmod ${options.mode.toString(8)} ${shellQuote2(remotePath)}`);
|
|
15768
15817
|
}
|
|
15769
15818
|
const cmd = parts.join(" && ");
|
|
15770
|
-
await new Promise((
|
|
15819
|
+
await new Promise((resolve4, reject) => {
|
|
15771
15820
|
const proc = (0, import_child_process13.spawn)(
|
|
15772
15821
|
"gitpod",
|
|
15773
15822
|
["workspace", "ssh", workspaceId, "--", cmd],
|
|
@@ -15779,7 +15828,7 @@ var GitpodProvider = class {
|
|
|
15779
15828
|
});
|
|
15780
15829
|
proc.on("error", reject);
|
|
15781
15830
|
proc.on("exit", (code) => {
|
|
15782
|
-
if (code === 0)
|
|
15831
|
+
if (code === 0) resolve4();
|
|
15783
15832
|
else reject(new Error(`Remote write failed: ${(stderr || `exit ${code}`).trim().slice(0, 500)}`));
|
|
15784
15833
|
});
|
|
15785
15834
|
proc.stdin?.write(contents);
|
|
@@ -15836,14 +15885,14 @@ var GitLabWorkspacesProvider = class {
|
|
|
15836
15885
|
"Authenticating GitLab"
|
|
15837
15886
|
);
|
|
15838
15887
|
resetStdinForChild3();
|
|
15839
|
-
await new Promise((
|
|
15888
|
+
await new Promise((resolve4, reject) => {
|
|
15840
15889
|
const proc = (0, import_child_process14.spawn)(
|
|
15841
15890
|
"glab",
|
|
15842
15891
|
["auth", "login", "--scopes", "api,read_user,read_repository"],
|
|
15843
15892
|
{ stdio: "inherit" }
|
|
15844
15893
|
);
|
|
15845
15894
|
proc.on("exit", (code) => {
|
|
15846
|
-
if (code === 0)
|
|
15895
|
+
if (code === 0) resolve4();
|
|
15847
15896
|
else reject(new Error("glab auth login failed."));
|
|
15848
15897
|
});
|
|
15849
15898
|
proc.on("error", reject);
|
|
@@ -16008,13 +16057,13 @@ Docs: https://docs.gitlab.com/ee/user/workspace/configuration.html`
|
|
|
16008
16057
|
async streamCommand(workspaceId, command2) {
|
|
16009
16058
|
const sshHost = process.env.CODEAM_GITLAB_SSH_HOST ?? "workspaces.gitlab.com";
|
|
16010
16059
|
resetStdinForChild3();
|
|
16011
|
-
return new Promise((
|
|
16060
|
+
return new Promise((resolve4, reject) => {
|
|
16012
16061
|
const proc = (0, import_child_process14.spawn)(
|
|
16013
16062
|
"ssh",
|
|
16014
16063
|
["-tt", "-o", "StrictHostKeyChecking=accept-new", `${workspaceId}@${sshHost}`, command2],
|
|
16015
16064
|
{ stdio: "inherit" }
|
|
16016
16065
|
);
|
|
16017
|
-
proc.on("exit", (code) =>
|
|
16066
|
+
proc.on("exit", (code) => resolve4({ code: code ?? 0 }));
|
|
16018
16067
|
proc.on("error", reject);
|
|
16019
16068
|
});
|
|
16020
16069
|
}
|
|
@@ -16029,7 +16078,7 @@ Docs: https://docs.gitlab.com/ee/user/workspace/configuration.html`
|
|
|
16029
16078
|
tarArgs.push(".");
|
|
16030
16079
|
const tarEnv = { ...process.env, COPYFILE_DISABLE: "1" };
|
|
16031
16080
|
const remoteCmd = `mkdir -p ${shellQuote3(remoteDir)} && tar -xzf - -C ${shellQuote3(remoteDir)}`;
|
|
16032
|
-
await new Promise((
|
|
16081
|
+
await new Promise((resolve4, reject) => {
|
|
16033
16082
|
const tar = (0, import_child_process14.spawn)("tar", tarArgs, { stdio: ["ignore", "pipe", "pipe"], env: tarEnv });
|
|
16034
16083
|
const ssh = (0, import_child_process14.spawn)(
|
|
16035
16084
|
"ssh",
|
|
@@ -16047,7 +16096,7 @@ Docs: https://docs.gitlab.com/ee/user/workspace/configuration.html`
|
|
|
16047
16096
|
tar.on("error", reject);
|
|
16048
16097
|
ssh.on("error", reject);
|
|
16049
16098
|
ssh.on("exit", (code) => {
|
|
16050
|
-
if (code === 0)
|
|
16099
|
+
if (code === 0) resolve4();
|
|
16051
16100
|
else reject(new Error(`Remote tar failed: ${(sshErr || tarErr || `exit ${code}`).trim().slice(0, 500)}`));
|
|
16052
16101
|
});
|
|
16053
16102
|
});
|
|
@@ -16060,7 +16109,7 @@ Docs: https://docs.gitlab.com/ee/user/workspace/configuration.html`
|
|
|
16060
16109
|
parts.push(`chmod ${options.mode.toString(8)} ${shellQuote3(remotePath)}`);
|
|
16061
16110
|
}
|
|
16062
16111
|
const cmd = parts.join(" && ");
|
|
16063
|
-
await new Promise((
|
|
16112
|
+
await new Promise((resolve4, reject) => {
|
|
16064
16113
|
const proc = (0, import_child_process14.spawn)(
|
|
16065
16114
|
"ssh",
|
|
16066
16115
|
["-o", "StrictHostKeyChecking=accept-new", `${workspaceId}@${sshHost}`, cmd],
|
|
@@ -16072,7 +16121,7 @@ Docs: https://docs.gitlab.com/ee/user/workspace/configuration.html`
|
|
|
16072
16121
|
});
|
|
16073
16122
|
proc.on("error", reject);
|
|
16074
16123
|
proc.on("exit", (code) => {
|
|
16075
|
-
if (code === 0)
|
|
16124
|
+
if (code === 0) resolve4();
|
|
16076
16125
|
else reject(new Error(`Remote write failed: ${(stderr || `exit ${code}`).trim().slice(0, 500)}`));
|
|
16077
16126
|
});
|
|
16078
16127
|
proc.stdin?.write(contents);
|
|
@@ -16163,10 +16212,10 @@ var RailwayProvider = class {
|
|
|
16163
16212
|
"Authenticating Railway"
|
|
16164
16213
|
);
|
|
16165
16214
|
resetStdinForChild4();
|
|
16166
|
-
await new Promise((
|
|
16215
|
+
await new Promise((resolve4, reject) => {
|
|
16167
16216
|
const proc = (0, import_child_process15.spawn)("railway", ["login"], { stdio: "inherit" });
|
|
16168
16217
|
proc.on("exit", (code) => {
|
|
16169
|
-
if (code === 0)
|
|
16218
|
+
if (code === 0) resolve4();
|
|
16170
16219
|
else reject(new Error("railway login failed."));
|
|
16171
16220
|
});
|
|
16172
16221
|
proc.on("error", reject);
|
|
@@ -16306,13 +16355,13 @@ var RailwayProvider = class {
|
|
|
16306
16355
|
throw new Error("Invalid Railway workspace id (expected projectId/serviceId).");
|
|
16307
16356
|
}
|
|
16308
16357
|
resetStdinForChild4();
|
|
16309
|
-
return new Promise((
|
|
16358
|
+
return new Promise((resolve4, reject) => {
|
|
16310
16359
|
const proc = (0, import_child_process15.spawn)(
|
|
16311
16360
|
"railway",
|
|
16312
16361
|
["shell", "--project", projectId, "--service", serviceId, "--command", command2],
|
|
16313
16362
|
{ stdio: "inherit" }
|
|
16314
16363
|
);
|
|
16315
|
-
proc.on("exit", (code) =>
|
|
16364
|
+
proc.on("exit", (code) => resolve4({ code: code ?? 0 }));
|
|
16316
16365
|
proc.on("error", reject);
|
|
16317
16366
|
});
|
|
16318
16367
|
}
|
|
@@ -16330,7 +16379,7 @@ var RailwayProvider = class {
|
|
|
16330
16379
|
tarArgs.push(".");
|
|
16331
16380
|
const tarEnv = { ...process.env, COPYFILE_DISABLE: "1" };
|
|
16332
16381
|
const remoteCmd = `mkdir -p ${shellQuote4(remoteDir)} && tar -xzf - -C ${shellQuote4(remoteDir)}`;
|
|
16333
|
-
await new Promise((
|
|
16382
|
+
await new Promise((resolve4, reject) => {
|
|
16334
16383
|
const tar = (0, import_child_process15.spawn)("tar", tarArgs, { stdio: ["ignore", "pipe", "pipe"], env: tarEnv });
|
|
16335
16384
|
const sh = (0, import_child_process15.spawn)(
|
|
16336
16385
|
"railway",
|
|
@@ -16348,7 +16397,7 @@ var RailwayProvider = class {
|
|
|
16348
16397
|
tar.on("error", reject);
|
|
16349
16398
|
sh.on("error", reject);
|
|
16350
16399
|
sh.on("exit", (code) => {
|
|
16351
|
-
if (code === 0)
|
|
16400
|
+
if (code === 0) resolve4();
|
|
16352
16401
|
else reject(new Error(`Remote tar failed: ${(shErr || tarErr || `exit ${code}`).trim().slice(0, 500)}`));
|
|
16353
16402
|
});
|
|
16354
16403
|
});
|
|
@@ -16364,7 +16413,7 @@ var RailwayProvider = class {
|
|
|
16364
16413
|
parts.push(`chmod ${options.mode.toString(8)} ${shellQuote4(remotePath)}`);
|
|
16365
16414
|
}
|
|
16366
16415
|
const cmd = parts.join(" && ");
|
|
16367
|
-
await new Promise((
|
|
16416
|
+
await new Promise((resolve4, reject) => {
|
|
16368
16417
|
const proc = (0, import_child_process15.spawn)(
|
|
16369
16418
|
"railway",
|
|
16370
16419
|
["shell", "--project", projectId, "--service", serviceId, "--command", cmd],
|
|
@@ -16376,7 +16425,7 @@ var RailwayProvider = class {
|
|
|
16376
16425
|
});
|
|
16377
16426
|
proc.on("error", reject);
|
|
16378
16427
|
proc.on("exit", (code) => {
|
|
16379
|
-
if (code === 0)
|
|
16428
|
+
if (code === 0) resolve4();
|
|
16380
16429
|
else reject(new Error(`Remote write failed: ${(stderr || `exit ${code}`).trim().slice(0, 500)}`));
|
|
16381
16430
|
});
|
|
16382
16431
|
proc.stdin?.write(contents);
|
|
@@ -16899,7 +16948,7 @@ async function stopWorkspaceFromLocal(target) {
|
|
|
16899
16948
|
|
|
16900
16949
|
// src/commands/link.ts
|
|
16901
16950
|
var import_node_crypto4 = require("crypto");
|
|
16902
|
-
var
|
|
16951
|
+
var fs26 = __toESM(require("fs"));
|
|
16903
16952
|
var path34 = __toESM(require("path"));
|
|
16904
16953
|
var import_chokidar = __toESM(require("chokidar"));
|
|
16905
16954
|
var import_picocolors11 = __toESM(require("picocolors"));
|
|
@@ -16938,7 +16987,7 @@ function parseLinkArgs(args2) {
|
|
|
16938
16987
|
if (apiKeyFileArg) {
|
|
16939
16988
|
const filePath = apiKeyFileArg.slice("--api-key-file=".length);
|
|
16940
16989
|
try {
|
|
16941
|
-
apiKey =
|
|
16990
|
+
apiKey = fs26.readFileSync(path34.resolve(filePath), "utf8").trim();
|
|
16942
16991
|
} catch (err) {
|
|
16943
16992
|
throw new Error(`Could not read --api-key-file ${filePath}: ${err.message}`);
|
|
16944
16993
|
}
|
|
@@ -16983,7 +17032,7 @@ async function link(args2 = []) {
|
|
|
16983
17032
|
waitSpin.start(waitMsg());
|
|
16984
17033
|
const countdown = setInterval(() => waitSpin.message(waitMsg()), 1e3);
|
|
16985
17034
|
countdown.unref?.();
|
|
16986
|
-
const paired = await new Promise((
|
|
17035
|
+
const paired = await new Promise((resolve4, reject) => {
|
|
16987
17036
|
let stopPoll = null;
|
|
16988
17037
|
const sigint = () => {
|
|
16989
17038
|
clearInterval(countdown);
|
|
@@ -16996,7 +17045,7 @@ async function link(args2 = []) {
|
|
|
16996
17045
|
process.removeListener("SIGINT", sigint);
|
|
16997
17046
|
clearInterval(countdown);
|
|
16998
17047
|
waitSpin.stop("Paired");
|
|
16999
|
-
|
|
17048
|
+
resolve4(info);
|
|
17000
17049
|
},
|
|
17001
17050
|
() => {
|
|
17002
17051
|
clearInterval(countdown);
|
|
@@ -17032,7 +17081,7 @@ async function link(args2 = []) {
|
|
|
17032
17081
|
return;
|
|
17033
17082
|
}
|
|
17034
17083
|
if (parsed.tokenFile) {
|
|
17035
|
-
const credential =
|
|
17084
|
+
const credential = fs26.readFileSync(path34.resolve(parsed.tokenFile), "utf8").trim();
|
|
17036
17085
|
if (!credential) {
|
|
17037
17086
|
showError(`--token-file ${parsed.tokenFile} is empty.`);
|
|
17038
17087
|
process.exit(1);
|
|
@@ -17102,14 +17151,14 @@ async function captureFreshCredentials(ctx) {
|
|
|
17102
17151
|
}
|
|
17103
17152
|
};
|
|
17104
17153
|
try {
|
|
17105
|
-
const token = await new Promise((
|
|
17154
|
+
const token = await new Promise((resolve4, reject) => {
|
|
17106
17155
|
let settled = false;
|
|
17107
17156
|
const tryExtract = async () => {
|
|
17108
17157
|
if (settled) return;
|
|
17109
17158
|
const t2 = await ctx.locator.extract();
|
|
17110
17159
|
if (t2 && !settled) {
|
|
17111
17160
|
settled = true;
|
|
17112
|
-
|
|
17161
|
+
resolve4(t2);
|
|
17113
17162
|
}
|
|
17114
17163
|
};
|
|
17115
17164
|
watcher.on("add", () => void tryExtract());
|
|
@@ -17221,7 +17270,7 @@ async function linkDryRunPreflight(ctx) {
|
|
|
17221
17270
|
var import_node_dns = require("dns");
|
|
17222
17271
|
var import_node_util4 = require("util");
|
|
17223
17272
|
var import_node_crypto5 = require("crypto");
|
|
17224
|
-
var
|
|
17273
|
+
var fs27 = __toESM(require("fs"));
|
|
17225
17274
|
var path35 = __toESM(require("path"));
|
|
17226
17275
|
var import_picocolors12 = __toESM(require("picocolors"));
|
|
17227
17276
|
var dnsResolveP = (0, import_node_util4.promisify)(import_node_dns.resolve);
|
|
@@ -17280,11 +17329,11 @@ async function checkHealth(apiBase) {
|
|
|
17280
17329
|
function checkConfigDir() {
|
|
17281
17330
|
const dir = path35.join(require("os").homedir(), ".codeam");
|
|
17282
17331
|
try {
|
|
17283
|
-
|
|
17332
|
+
fs27.mkdirSync(dir, { recursive: true, mode: 448 });
|
|
17284
17333
|
const probe = path35.join(dir, ".doctor-probe");
|
|
17285
|
-
|
|
17286
|
-
const read =
|
|
17287
|
-
|
|
17334
|
+
fs27.writeFileSync(probe, "ok", { mode: 384 });
|
|
17335
|
+
const read = fs27.readFileSync(probe, "utf8");
|
|
17336
|
+
fs27.unlinkSync(probe);
|
|
17288
17337
|
if (read !== "ok") throw new Error("write/read round-trip mismatch");
|
|
17289
17338
|
return {
|
|
17290
17339
|
id: "config-dir",
|
|
@@ -17390,7 +17439,7 @@ function checkChokidar() {
|
|
|
17390
17439
|
}
|
|
17391
17440
|
async function doctor(args2 = []) {
|
|
17392
17441
|
const json = args2.includes("--json");
|
|
17393
|
-
const cliVersion = true ? "2.20.
|
|
17442
|
+
const cliVersion = true ? "2.20.2" : "0.0.0-dev";
|
|
17394
17443
|
const apiBase = resolveApiBaseUrl();
|
|
17395
17444
|
const diagnosticId = (0, import_node_crypto5.randomUUID)();
|
|
17396
17445
|
log.info("doctor", `run id=${diagnosticId} cli=${cliVersion}`);
|
|
@@ -17589,7 +17638,7 @@ async function completion(args2) {
|
|
|
17589
17638
|
// src/commands/version.ts
|
|
17590
17639
|
var import_picocolors13 = __toESM(require("picocolors"));
|
|
17591
17640
|
function version2() {
|
|
17592
|
-
const v = true ? "2.20.
|
|
17641
|
+
const v = true ? "2.20.2" : "unknown";
|
|
17593
17642
|
console.log(`${import_picocolors13.default.bold("codeam-cli")} ${import_picocolors13.default.cyan(v)}`);
|
|
17594
17643
|
}
|
|
17595
17644
|
|
|
@@ -17717,7 +17766,7 @@ function tryShowSubcommandHelp(cmd, args2) {
|
|
|
17717
17766
|
var _subcommandHelpKeys = Object.keys(HELPS);
|
|
17718
17767
|
|
|
17719
17768
|
// src/lib/updateNotifier.ts
|
|
17720
|
-
var
|
|
17769
|
+
var fs28 = __toESM(require("fs"));
|
|
17721
17770
|
var os25 = __toESM(require("os"));
|
|
17722
17771
|
var path36 = __toESM(require("path"));
|
|
17723
17772
|
var https7 = __toESM(require("https"));
|
|
@@ -17732,7 +17781,7 @@ function cachePath() {
|
|
|
17732
17781
|
}
|
|
17733
17782
|
function readCache() {
|
|
17734
17783
|
try {
|
|
17735
|
-
const raw =
|
|
17784
|
+
const raw = fs28.readFileSync(cachePath(), "utf8");
|
|
17736
17785
|
const parsed = JSON.parse(raw);
|
|
17737
17786
|
if (typeof parsed.fetchedAt !== "number" || typeof parsed.latest !== "string") return null;
|
|
17738
17787
|
return parsed;
|
|
@@ -17743,10 +17792,10 @@ function readCache() {
|
|
|
17743
17792
|
function writeCache(cache) {
|
|
17744
17793
|
try {
|
|
17745
17794
|
const file = cachePath();
|
|
17746
|
-
|
|
17795
|
+
fs28.mkdirSync(path36.dirname(file), { recursive: true });
|
|
17747
17796
|
const tmp = `${file}.${process.pid}.tmp`;
|
|
17748
|
-
|
|
17749
|
-
|
|
17797
|
+
fs28.writeFileSync(tmp, JSON.stringify(cache));
|
|
17798
|
+
fs28.renameSync(tmp, file);
|
|
17750
17799
|
} catch {
|
|
17751
17800
|
}
|
|
17752
17801
|
}
|
|
@@ -17764,14 +17813,14 @@ function compareSemver(a, b) {
|
|
|
17764
17813
|
return 0;
|
|
17765
17814
|
}
|
|
17766
17815
|
function fetchLatest() {
|
|
17767
|
-
return new Promise((
|
|
17816
|
+
return new Promise((resolve4) => {
|
|
17768
17817
|
const req = https7.get(
|
|
17769
17818
|
REGISTRY_URL,
|
|
17770
17819
|
{ headers: { Accept: "application/json" }, timeout: REQUEST_TIMEOUT_MS },
|
|
17771
17820
|
(res) => {
|
|
17772
17821
|
if (res.statusCode !== 200) {
|
|
17773
17822
|
res.resume();
|
|
17774
|
-
|
|
17823
|
+
resolve4(null);
|
|
17775
17824
|
return;
|
|
17776
17825
|
}
|
|
17777
17826
|
let buf = "";
|
|
@@ -17783,21 +17832,21 @@ function fetchLatest() {
|
|
|
17783
17832
|
try {
|
|
17784
17833
|
const json = JSON.parse(buf);
|
|
17785
17834
|
if (typeof json.version === "string") {
|
|
17786
|
-
|
|
17835
|
+
resolve4(json.version);
|
|
17787
17836
|
} else {
|
|
17788
|
-
|
|
17837
|
+
resolve4(null);
|
|
17789
17838
|
}
|
|
17790
17839
|
} catch {
|
|
17791
|
-
|
|
17840
|
+
resolve4(null);
|
|
17792
17841
|
}
|
|
17793
17842
|
});
|
|
17794
17843
|
}
|
|
17795
17844
|
);
|
|
17796
17845
|
req.on("timeout", () => {
|
|
17797
17846
|
req.destroy();
|
|
17798
|
-
|
|
17847
|
+
resolve4(null);
|
|
17799
17848
|
});
|
|
17800
|
-
req.on("error", () =>
|
|
17849
|
+
req.on("error", () => resolve4(null));
|
|
17801
17850
|
});
|
|
17802
17851
|
}
|
|
17803
17852
|
function notifyIfStale(currentVersion, latest) {
|
|
@@ -17817,7 +17866,7 @@ function checkForUpdates() {
|
|
|
17817
17866
|
if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
|
|
17818
17867
|
if (process.env.CI) return;
|
|
17819
17868
|
if (!process.stdout.isTTY) return;
|
|
17820
|
-
const current = true ? "2.20.
|
|
17869
|
+
const current = true ? "2.20.2" : null;
|
|
17821
17870
|
if (!current) return;
|
|
17822
17871
|
const cache = readCache();
|
|
17823
17872
|
const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "codeam-cli",
|
|
3
|
-
"version": "2.20.
|
|
3
|
+
"version": "2.20.2",
|
|
4
4
|
"description": "Workflow-continuity bridge for AI coding agents. Wrap Claude Code or Codex in a PTY and supervise, approve, and redirect the session from any device — async. The terminal companion for CodeAgent Mobile.",
|
|
5
5
|
"type": "commonjs",
|
|
6
6
|
"main": "dist/index.js",
|