codeam-cli 2.69.0 → 2.71.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -0
- package/dist/index.js +465 -114
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,18 @@ All notable changes to `codeam-cli` are documented here.
|
|
|
4
4
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
6
6
|
|
|
7
|
+
## [2.70.0] — 2026-08-29
|
|
8
|
+
|
|
9
|
+
### Fixed
|
|
10
|
+
|
|
11
|
+
- **cli:** Distinguir una navegacion de un fetch, no solo mirar el Accept (#667)
|
|
12
|
+
|
|
13
|
+
## [2.69.0] — 2026-08-29
|
|
14
|
+
|
|
15
|
+
### Added
|
|
16
|
+
|
|
17
|
+
- **cli:** El inspector habla tambien dentro del WebView de la app movil (#666)
|
|
18
|
+
|
|
7
19
|
## [2.68.0] — 2026-08-29
|
|
8
20
|
|
|
9
21
|
### Added
|
package/dist/index.js
CHANGED
|
@@ -271,8 +271,8 @@ var init_stdio_proxy = __esm({
|
|
|
271
271
|
}
|
|
272
272
|
async spawnChild(stdout, preResolved) {
|
|
273
273
|
const spec = preResolved ?? await this.opts.spawnSpec();
|
|
274
|
-
const
|
|
275
|
-
const child =
|
|
274
|
+
const spawn47 = this.opts.spawnImpl ?? import_node_child_process33.spawn;
|
|
275
|
+
const child = spawn47(spec.command, spec.args, {
|
|
276
276
|
env: { ...process.env, ...spec.env },
|
|
277
277
|
// env only — never argv
|
|
278
278
|
stdio: ["pipe", "pipe", "inherit"]
|
|
@@ -8081,7 +8081,7 @@ function readAnonId() {
|
|
|
8081
8081
|
}
|
|
8082
8082
|
function superProperties() {
|
|
8083
8083
|
return {
|
|
8084
|
-
cliVersion: true ? "2.
|
|
8084
|
+
cliVersion: true ? "2.71.0" : "0.0.0-dev",
|
|
8085
8085
|
nodeVersion: process.version,
|
|
8086
8086
|
platform: process.platform,
|
|
8087
8087
|
arch: process.arch,
|
|
@@ -8323,7 +8323,7 @@ var http = __toESM(require("http"));
|
|
|
8323
8323
|
// package.json
|
|
8324
8324
|
var package_default = {
|
|
8325
8325
|
name: "codeam-cli",
|
|
8326
|
-
version: "2.
|
|
8326
|
+
version: "2.71.0",
|
|
8327
8327
|
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.",
|
|
8328
8328
|
type: "commonjs",
|
|
8329
8329
|
main: "dist/index.js",
|
|
@@ -9859,7 +9859,7 @@ var CommandRelayService = class _CommandRelayService {
|
|
|
9859
9859
|
// fresh + clear the "CLI update available" banner after a self-update
|
|
9860
9860
|
// (a codespace that reinstalls @latest reconnects via heartbeat, not
|
|
9861
9861
|
// pair/reconnect). Older backends ignore the extra field.
|
|
9862
|
-
..."2.
|
|
9862
|
+
..."2.71.0" ? { ideVersion: "2.71.0" } : {}
|
|
9863
9863
|
}).then(() => log.trace("relay", `heartbeat ok online=${online}`)).catch((err) => log.trace("relay", `heartbeat failed online=${online}`, err));
|
|
9864
9864
|
}
|
|
9865
9865
|
/**
|
|
@@ -11270,7 +11270,7 @@ var fs65 = __toESM(require("fs"));
|
|
|
11270
11270
|
var os54 = __toESM(require("os"));
|
|
11271
11271
|
var path71 = __toESM(require("path"));
|
|
11272
11272
|
var import_crypto3 = require("crypto");
|
|
11273
|
-
var
|
|
11273
|
+
var import_child_process28 = require("child_process");
|
|
11274
11274
|
|
|
11275
11275
|
// src/lib/payload.ts
|
|
11276
11276
|
var import_zod = require("zod");
|
|
@@ -14062,7 +14062,7 @@ function subscribeToPairCompletion(pluginId, onPaired, onTimeout, pollSecret) {
|
|
|
14062
14062
|
onPaired(info);
|
|
14063
14063
|
};
|
|
14064
14064
|
dispatchers.add(dispatch);
|
|
14065
|
-
const
|
|
14065
|
+
const connect4 = () => {
|
|
14066
14066
|
if (stopped) return;
|
|
14067
14067
|
const url2 = new URL(`${API_BASE5}/api/commands/pending/stream`);
|
|
14068
14068
|
url2.searchParams.set("pluginId", pluginId);
|
|
@@ -14088,7 +14088,7 @@ function subscribeToPairCompletion(pluginId, onPaired, onTimeout, pollSecret) {
|
|
|
14088
14088
|
`sse status=${res.statusCode}; will reconnect in 1s`
|
|
14089
14089
|
);
|
|
14090
14090
|
res.resume();
|
|
14091
|
-
setTimeout(
|
|
14091
|
+
setTimeout(connect4, 1e3);
|
|
14092
14092
|
return;
|
|
14093
14093
|
}
|
|
14094
14094
|
let buf = "";
|
|
@@ -14103,23 +14103,23 @@ function subscribeToPairCompletion(pluginId, onPaired, onTimeout, pollSecret) {
|
|
|
14103
14103
|
}
|
|
14104
14104
|
});
|
|
14105
14105
|
res.on("end", () => {
|
|
14106
|
-
if (!stopped) setTimeout(
|
|
14106
|
+
if (!stopped) setTimeout(connect4, 250);
|
|
14107
14107
|
});
|
|
14108
14108
|
res.on("error", () => {
|
|
14109
|
-
if (!stopped) setTimeout(
|
|
14109
|
+
if (!stopped) setTimeout(connect4, 1e3);
|
|
14110
14110
|
});
|
|
14111
14111
|
}
|
|
14112
14112
|
);
|
|
14113
14113
|
req.on("error", () => {
|
|
14114
|
-
if (!stopped) setTimeout(
|
|
14114
|
+
if (!stopped) setTimeout(connect4, 1e3);
|
|
14115
14115
|
});
|
|
14116
14116
|
req.on("timeout", () => {
|
|
14117
14117
|
req?.destroy();
|
|
14118
|
-
if (!stopped) setTimeout(
|
|
14118
|
+
if (!stopped) setTimeout(connect4, 250);
|
|
14119
14119
|
});
|
|
14120
14120
|
req.end();
|
|
14121
14121
|
};
|
|
14122
|
-
|
|
14122
|
+
connect4();
|
|
14123
14123
|
timeoutTimer = setTimeout(() => {
|
|
14124
14124
|
stop();
|
|
14125
14125
|
onTimeout();
|
|
@@ -17074,7 +17074,7 @@ async function ensurePythonInstaller(runner) {
|
|
|
17074
17074
|
return { ok: true, installer: { kind: "pip" } };
|
|
17075
17075
|
}
|
|
17076
17076
|
async function resolveHeadroomPython(runner) {
|
|
17077
|
-
const
|
|
17077
|
+
const PROBE_TIMEOUT_MS2 = 5e3;
|
|
17078
17078
|
const SUFFIXES = ["python3.13", "python3.12", "python3.11", "python3.10"];
|
|
17079
17079
|
const PREFIX_DIRS = ["/opt/homebrew/bin", "/usr/local/bin"];
|
|
17080
17080
|
const probe = async (candidate) => {
|
|
@@ -17082,7 +17082,7 @@ async function resolveHeadroomPython(runner) {
|
|
|
17082
17082
|
const r = await runner.run(
|
|
17083
17083
|
candidate,
|
|
17084
17084
|
["-c", 'import sys; print("%d.%d" % sys.version_info[:2])'],
|
|
17085
|
-
{ timeoutMs:
|
|
17085
|
+
{ timeoutMs: PROBE_TIMEOUT_MS2 }
|
|
17086
17086
|
);
|
|
17087
17087
|
if (r.code !== 0) return false;
|
|
17088
17088
|
const parts = (r.stdout ?? "").trim().split(".");
|
|
@@ -17090,7 +17090,7 @@ async function resolveHeadroomPython(runner) {
|
|
|
17090
17090
|
const minor = parseInt(parts[1] ?? "", 10);
|
|
17091
17091
|
if (!(major === 3 && minor >= 10)) return false;
|
|
17092
17092
|
const pipCheck = await runner.run(candidate, ["-m", "pip", "--version"], {
|
|
17093
|
-
timeoutMs:
|
|
17093
|
+
timeoutMs: PROBE_TIMEOUT_MS2
|
|
17094
17094
|
});
|
|
17095
17095
|
return pipCheck.code === 0;
|
|
17096
17096
|
} catch {
|
|
@@ -22118,7 +22118,7 @@ async function autoUpgradeBeforeCriticalCommand() {
|
|
|
22118
22118
|
if (process.env.NODE_ENV === "test") return;
|
|
22119
22119
|
if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
|
|
22120
22120
|
if (process.env.CI) return;
|
|
22121
|
-
const current2 = true ? "2.
|
|
22121
|
+
const current2 = true ? "2.71.0" : null;
|
|
22122
22122
|
if (!current2) return;
|
|
22123
22123
|
const cache = readCache();
|
|
22124
22124
|
const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
|
|
@@ -22135,7 +22135,7 @@ function checkForUpdates() {
|
|
|
22135
22135
|
if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
|
|
22136
22136
|
if (process.env.CI) return;
|
|
22137
22137
|
if (!process.stdout.isTTY) return;
|
|
22138
|
-
const current2 = true ? "2.
|
|
22138
|
+
const current2 = true ? "2.71.0" : null;
|
|
22139
22139
|
if (!current2) return;
|
|
22140
22140
|
const cache = readCache();
|
|
22141
22141
|
const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
|
|
@@ -22158,7 +22158,7 @@ var SELF_UPDATE_INSTALL_TIMEOUT_MS = 18e4;
|
|
|
22158
22158
|
var SELF_UPDATE_LS_TIMEOUT_MS = 15e3;
|
|
22159
22159
|
var SUDO_PREFLIGHT_TIMEOUT_MS = 5e3;
|
|
22160
22160
|
function currentCliVersion() {
|
|
22161
|
-
return true ? "2.
|
|
22161
|
+
return true ? "2.71.0" : null;
|
|
22162
22162
|
}
|
|
22163
22163
|
async function installedVersion(deps) {
|
|
22164
22164
|
const ls = await deps.run(
|
|
@@ -24029,17 +24029,17 @@ async function defaultFetchJson(url2) {
|
|
|
24029
24029
|
async function readUsageReport(deps = {}) {
|
|
24030
24030
|
const port = deps.port ?? HEADROOM_PROXY_PORT;
|
|
24031
24031
|
const base = `http://127.0.0.1:${port}`;
|
|
24032
|
-
const
|
|
24032
|
+
const get3 = deps.fetchJson ?? ((path95) => defaultFetchJson(`${base}${path95}`));
|
|
24033
24033
|
let history;
|
|
24034
24034
|
try {
|
|
24035
|
-
history = await
|
|
24035
|
+
history = await get3("/stats-history");
|
|
24036
24036
|
} catch (err) {
|
|
24037
24037
|
log.info("headroomUsage", `stats-history unavailable: ${err.message}`);
|
|
24038
24038
|
return null;
|
|
24039
24039
|
}
|
|
24040
24040
|
let proxyVersion;
|
|
24041
24041
|
try {
|
|
24042
|
-
const health = await
|
|
24042
|
+
const health = await get3("/health");
|
|
24043
24043
|
if (health && typeof health.version === "string") proxyVersion = health.version;
|
|
24044
24044
|
} catch {
|
|
24045
24045
|
}
|
|
@@ -24380,7 +24380,18 @@ function isBuildHealSupported(framework) {
|
|
|
24380
24380
|
function defaultWatchDir(dir, onEvent) {
|
|
24381
24381
|
try {
|
|
24382
24382
|
const w3 = fs52.watch(dir, { persistent: false }, (_eventType, filename) => onEvent(filename));
|
|
24383
|
-
|
|
24383
|
+
w3.on("error", () => {
|
|
24384
|
+
try {
|
|
24385
|
+
w3.close();
|
|
24386
|
+
} catch {
|
|
24387
|
+
}
|
|
24388
|
+
});
|
|
24389
|
+
return () => {
|
|
24390
|
+
try {
|
|
24391
|
+
w3.close();
|
|
24392
|
+
} catch {
|
|
24393
|
+
}
|
|
24394
|
+
};
|
|
24384
24395
|
} catch {
|
|
24385
24396
|
return null;
|
|
24386
24397
|
}
|
|
@@ -24798,11 +24809,78 @@ async function waitForPortListening(port, opts) {
|
|
|
24798
24809
|
var import_fs4 = require("fs");
|
|
24799
24810
|
var import_path7 = __toESM(require("path"));
|
|
24800
24811
|
|
|
24801
|
-
// src/services/preview/
|
|
24812
|
+
// src/services/preview/embedded-postgres.ts
|
|
24802
24813
|
var import_child_process20 = require("child_process");
|
|
24814
|
+
var net3 = __toESM(require("net"));
|
|
24815
|
+
var BOOT = `
|
|
24816
|
+
const { PGlite } = require('@electric-sql/pglite');
|
|
24817
|
+
const { PGLiteSocketServer } = require('@electric-sql/pglite-socket');
|
|
24818
|
+
(async () => {
|
|
24819
|
+
// 'memory://' \u2014 ef\xEDmero por dise\xF1o; ver el comentario del m\xF3dulo.
|
|
24820
|
+
const db = await PGlite.create('memory://');
|
|
24821
|
+
const server = new PGLiteSocketServer({ db, port: PORT, host: '127.0.0.1' });
|
|
24822
|
+
await server.start();
|
|
24823
|
+
process.on('SIGTERM', async () => { await server.stop(); process.exit(0); });
|
|
24824
|
+
})().catch((e) => { console.error(String(e && e.message)); process.exit(1); });
|
|
24825
|
+
`;
|
|
24826
|
+
function isListening(port) {
|
|
24827
|
+
return new Promise((resolve10) => {
|
|
24828
|
+
const s = net3.connect({ host: "127.0.0.1", port }, () => {
|
|
24829
|
+
s.destroy();
|
|
24830
|
+
resolve10(true);
|
|
24831
|
+
}).on("error", () => resolve10(false));
|
|
24832
|
+
s.setTimeout(1e3, () => {
|
|
24833
|
+
s.destroy();
|
|
24834
|
+
resolve10(false);
|
|
24835
|
+
});
|
|
24836
|
+
});
|
|
24837
|
+
}
|
|
24838
|
+
var DEFAULT_PORT = 5432;
|
|
24839
|
+
async function startEmbeddedPostgres(opts = {}) {
|
|
24840
|
+
const port = opts.port ?? DEFAULT_PORT;
|
|
24841
|
+
const probe = opts.probe ?? isListening;
|
|
24842
|
+
const log2 = opts.log ?? (() => void 0);
|
|
24843
|
+
if (await probe(port)) {
|
|
24844
|
+
log2(`embedded postgres skipped \u2014 port ${port} already serving`);
|
|
24845
|
+
return null;
|
|
24846
|
+
}
|
|
24847
|
+
const child = (opts.spawnFn ?? import_child_process20.spawn)(
|
|
24848
|
+
process.execPath,
|
|
24849
|
+
["-e", `const PORT=${port};${BOOT}`],
|
|
24850
|
+
{ stdio: ["ignore", "pipe", "pipe"], detached: false }
|
|
24851
|
+
);
|
|
24852
|
+
let failure = "";
|
|
24853
|
+
child.stderr?.on("data", (d3) => {
|
|
24854
|
+
failure += String(d3).slice(0, 400);
|
|
24855
|
+
});
|
|
24856
|
+
const deadline = Date.now() + (opts.readyTimeoutMs ?? 2e4);
|
|
24857
|
+
while (Date.now() < deadline) {
|
|
24858
|
+
if (child.exitCode !== null) {
|
|
24859
|
+
log2(`embedded postgres unavailable (${failure.trim() || "exited"})`);
|
|
24860
|
+
return null;
|
|
24861
|
+
}
|
|
24862
|
+
if (await probe(port)) {
|
|
24863
|
+
log2(`embedded postgres serving on ${port}`);
|
|
24864
|
+
return { port, stop: () => stopChild(child) };
|
|
24865
|
+
}
|
|
24866
|
+
await new Promise((r) => setTimeout(r, 250));
|
|
24867
|
+
}
|
|
24868
|
+
log2("embedded postgres did not become ready in time");
|
|
24869
|
+
stopChild(child);
|
|
24870
|
+
return null;
|
|
24871
|
+
}
|
|
24872
|
+
function stopChild(child) {
|
|
24873
|
+
try {
|
|
24874
|
+
child.kill("SIGTERM");
|
|
24875
|
+
} catch {
|
|
24876
|
+
}
|
|
24877
|
+
}
|
|
24878
|
+
|
|
24879
|
+
// src/services/preview/run-setup.ts
|
|
24880
|
+
var import_child_process21 = require("child_process");
|
|
24803
24881
|
function runSetupCommand(cmd, args2, cwd, env, opts) {
|
|
24804
24882
|
return new Promise((resolve10) => {
|
|
24805
|
-
const child = (0,
|
|
24883
|
+
const child = (0, import_child_process21.spawn)(cmd, args2, {
|
|
24806
24884
|
cwd,
|
|
24807
24885
|
env: { ...process.env, ...env ?? {} },
|
|
24808
24886
|
stdio: ["ignore", "pipe", "pipe"]
|
|
@@ -24886,6 +24964,35 @@ var REDIS = {
|
|
|
24886
24964
|
healthTest: ["CMD", "redis-cli", "ping"],
|
|
24887
24965
|
envLines: ["REDIS_URL=redis://localhost:6379", "REDIS_HOST=localhost", "REDIS_PORT=6379"]
|
|
24888
24966
|
};
|
|
24967
|
+
async function readPrismaProvider(cwd) {
|
|
24968
|
+
for (const rel of ["prisma/schema.prisma", "schema.prisma", "src/prisma/schema.prisma"]) {
|
|
24969
|
+
try {
|
|
24970
|
+
return prismaProvider(await import_fs4.promises.readFile(import_path7.default.join(cwd, rel), "utf8"));
|
|
24971
|
+
} catch {
|
|
24972
|
+
}
|
|
24973
|
+
}
|
|
24974
|
+
return null;
|
|
24975
|
+
}
|
|
24976
|
+
function prismaProvider(schema) {
|
|
24977
|
+
const m = /datasource\s+\w+\s*\{[^}]*?provider\s*=\s*"([^"]+)"/s.exec(schema);
|
|
24978
|
+
return m ? m[1] : null;
|
|
24979
|
+
}
|
|
24980
|
+
function serviceForPrismaProvider(provider) {
|
|
24981
|
+
switch (provider) {
|
|
24982
|
+
case "postgresql":
|
|
24983
|
+
case "postgres":
|
|
24984
|
+
return POSTGRES;
|
|
24985
|
+
case "mysql":
|
|
24986
|
+
// PlanetScale habla el protocolo de MySQL.
|
|
24987
|
+
case "planetscale":
|
|
24988
|
+
return MYSQL;
|
|
24989
|
+
case "mongodb":
|
|
24990
|
+
return MONGO;
|
|
24991
|
+
// `sqlite` es un FICHERO: no necesita contenedor y no es un hueco.
|
|
24992
|
+
default:
|
|
24993
|
+
return null;
|
|
24994
|
+
}
|
|
24995
|
+
}
|
|
24889
24996
|
function detectServicesFromDeps(pkg) {
|
|
24890
24997
|
const deps = /* @__PURE__ */ new Set([
|
|
24891
24998
|
...Object.keys(pkg.dependencies ?? {}),
|
|
@@ -24994,12 +25101,72 @@ function runDockerComposeUp(cwd, composeArgs) {
|
|
|
24994
25101
|
{ timeoutMs: 18e4 }
|
|
24995
25102
|
);
|
|
24996
25103
|
}
|
|
25104
|
+
var embeddedPg = null;
|
|
25105
|
+
function registerEmbeddedPostgres(pg) {
|
|
25106
|
+
embeddedPg?.stop();
|
|
25107
|
+
embeddedPg = pg;
|
|
25108
|
+
}
|
|
25109
|
+
var lastOutcome = null;
|
|
25110
|
+
function noteProvisionOutcome(outcome) {
|
|
25111
|
+
lastOutcome = outcome;
|
|
25112
|
+
}
|
|
25113
|
+
function getLastProvisionOutcome() {
|
|
25114
|
+
return lastOutcome;
|
|
25115
|
+
}
|
|
25116
|
+
function envVarFor(service) {
|
|
25117
|
+
const first = service.envLines[0] ?? "";
|
|
25118
|
+
return first.split("=")[0] || "DATABASE_URL";
|
|
25119
|
+
}
|
|
24997
25120
|
async function provisionProjectDependencies(cwd) {
|
|
25121
|
+
let needed = [];
|
|
25122
|
+
const outcome = (reason) => ({
|
|
25123
|
+
reason,
|
|
25124
|
+
missing: reason === "ok" ? [] : needed.map((sv) => ({ service: sv.name, envVar: envVarFor(sv) }))
|
|
25125
|
+
});
|
|
24998
25126
|
try {
|
|
24999
|
-
|
|
25127
|
+
let docker = await runSetupCommand("docker", ["info"], cwd, void 0, {
|
|
25128
|
+
timeoutMs: 15e3
|
|
25129
|
+
});
|
|
25130
|
+
if (docker.status !== "ok") {
|
|
25131
|
+
log.info("provision", "docker not responding \u2014 trying to start the daemon");
|
|
25132
|
+
for (const argv of [
|
|
25133
|
+
["-n", "systemctl", "start", "docker"],
|
|
25134
|
+
["-n", "service", "docker", "start"]
|
|
25135
|
+
]) {
|
|
25136
|
+
const started2 = await runSetupCommand("sudo", argv, cwd, void 0, {
|
|
25137
|
+
timeoutMs: 45e3
|
|
25138
|
+
});
|
|
25139
|
+
if (started2.status !== "ok") continue;
|
|
25140
|
+
docker = await runSetupCommand("docker", ["info"], cwd, void 0, {
|
|
25141
|
+
timeoutMs: 2e4
|
|
25142
|
+
});
|
|
25143
|
+
if (docker.status === "ok") {
|
|
25144
|
+
log.info("provision", `docker daemon started via ${argv[1]}`);
|
|
25145
|
+
break;
|
|
25146
|
+
}
|
|
25147
|
+
}
|
|
25148
|
+
}
|
|
25000
25149
|
if (docker.status !== "ok") {
|
|
25001
25150
|
log.info("provision", "docker not usable \u2014 skipping dependency provisioning");
|
|
25002
|
-
|
|
25151
|
+
const pkgForNeeds = await readPackageJson(cwd);
|
|
25152
|
+
needed = pkgForNeeds ? detectServicesFromDeps(pkgForNeeds) : [];
|
|
25153
|
+
const prismaNeed = serviceForPrismaProvider(await readPrismaProvider(cwd));
|
|
25154
|
+
if (prismaNeed && !needed.some((n) => n.name === prismaNeed.name)) {
|
|
25155
|
+
needed.push(prismaNeed);
|
|
25156
|
+
}
|
|
25157
|
+
const pgIndex = needed.findIndex((n) => n.name === "postgres");
|
|
25158
|
+
if (pgIndex !== -1) {
|
|
25159
|
+
const embedded = await startEmbeddedPostgres({
|
|
25160
|
+
port: 5432,
|
|
25161
|
+
log: (m) => log.info("provision", m)
|
|
25162
|
+
});
|
|
25163
|
+
if (embedded) {
|
|
25164
|
+
registerEmbeddedPostgres(embedded);
|
|
25165
|
+
await ensureEnvFile(cwd, [needed[pgIndex]]);
|
|
25166
|
+
needed.splice(pgIndex, 1);
|
|
25167
|
+
}
|
|
25168
|
+
}
|
|
25169
|
+
return outcome(needed.length === 0 ? "ok" : "no-docker");
|
|
25003
25170
|
}
|
|
25004
25171
|
const pkg = await readPackageJson(cwd);
|
|
25005
25172
|
let started = false;
|
|
@@ -25012,6 +25179,11 @@ async function provisionProjectDependencies(cwd) {
|
|
|
25012
25179
|
if (!started) log.warn("provision", `compose up \u2192 ${up.status} (non-fatal)`);
|
|
25013
25180
|
} else if (pkg) {
|
|
25014
25181
|
generated = detectServicesFromDeps(pkg);
|
|
25182
|
+
const prismaSvc = serviceForPrismaProvider(await readPrismaProvider(cwd));
|
|
25183
|
+
if (prismaSvc && !generated.some((g) => g.name === prismaSvc.name)) {
|
|
25184
|
+
generated.push(prismaSvc);
|
|
25185
|
+
}
|
|
25186
|
+
needed = generated;
|
|
25015
25187
|
if (generated.length > 0) {
|
|
25016
25188
|
const dir = import_path7.default.join(cwd, ".codeam", "provision");
|
|
25017
25189
|
await import_fs4.promises.mkdir(dir, { recursive: true });
|
|
@@ -25031,8 +25203,10 @@ async function provisionProjectDependencies(cwd) {
|
|
|
25031
25203
|
await ensureEnvFile(cwd, generated);
|
|
25032
25204
|
if (started && pkg?.scripts) await runMigrationsIfPresent(cwd, pkg.scripts);
|
|
25033
25205
|
log.info("provision", "project dependency provisioning complete");
|
|
25206
|
+
return outcome(needed.length > 0 && !started ? "compose-failed" : "ok");
|
|
25034
25207
|
} catch (err) {
|
|
25035
25208
|
log.warn("provision", "provisionProjectDependencies failed (non-fatal)", err);
|
|
25209
|
+
return outcome("unknown");
|
|
25036
25210
|
}
|
|
25037
25211
|
}
|
|
25038
25212
|
|
|
@@ -25100,6 +25274,51 @@ async function awaitTunnelRegistered(candidate, hostname3, deadlineMs) {
|
|
|
25100
25274
|
}
|
|
25101
25275
|
}
|
|
25102
25276
|
|
|
25277
|
+
// src/services/preview/adopt-port.ts
|
|
25278
|
+
var http6 = __toESM(require("http"));
|
|
25279
|
+
var DIRECTORY_LISTING_RE = /<title>\s*(?:Directory listing for|Index of)/i;
|
|
25280
|
+
var PROBE_TIMEOUT_MS = 2e3;
|
|
25281
|
+
var PROBE_BODY_LIMIT = 4 * 1024;
|
|
25282
|
+
function verdictFor(res) {
|
|
25283
|
+
if (!res) return { adopt: false, reason: "unreachable" };
|
|
25284
|
+
if (!res.contentType || !res.contentType.toLowerCase().includes("text/html")) {
|
|
25285
|
+
return { adopt: false, reason: "not-html" };
|
|
25286
|
+
}
|
|
25287
|
+
if (DIRECTORY_LISTING_RE.test(res.bodyStart)) {
|
|
25288
|
+
return { adopt: false, reason: "directory-listing" };
|
|
25289
|
+
}
|
|
25290
|
+
return { adopt: true };
|
|
25291
|
+
}
|
|
25292
|
+
var probePort = (port) => new Promise((resolve10) => {
|
|
25293
|
+
const req = http6.get(
|
|
25294
|
+
{ host: "127.0.0.1", port, path: "/", timeout: PROBE_TIMEOUT_MS },
|
|
25295
|
+
(res) => {
|
|
25296
|
+
let body = "";
|
|
25297
|
+
res.setEncoding("utf8");
|
|
25298
|
+
res.on("data", (c2) => {
|
|
25299
|
+
if (body.length < PROBE_BODY_LIMIT) body += c2;
|
|
25300
|
+
});
|
|
25301
|
+
res.on(
|
|
25302
|
+
"end",
|
|
25303
|
+
() => resolve10({ contentType: res.headers["content-type"], bodyStart: body })
|
|
25304
|
+
);
|
|
25305
|
+
res.on("error", () => resolve10(null));
|
|
25306
|
+
}
|
|
25307
|
+
);
|
|
25308
|
+
req.on("timeout", () => {
|
|
25309
|
+
req.destroy();
|
|
25310
|
+
resolve10(null);
|
|
25311
|
+
});
|
|
25312
|
+
req.on("error", () => resolve10(null));
|
|
25313
|
+
});
|
|
25314
|
+
async function canAdoptPort(port, probe = probePort) {
|
|
25315
|
+
try {
|
|
25316
|
+
return verdictFor(await probe(port));
|
|
25317
|
+
} catch {
|
|
25318
|
+
return { adopt: false, reason: "unreachable" };
|
|
25319
|
+
}
|
|
25320
|
+
}
|
|
25321
|
+
|
|
25103
25322
|
// src/services/preview/index.ts
|
|
25104
25323
|
var activePreviews = /* @__PURE__ */ new Map();
|
|
25105
25324
|
function registerPreview(sessionId, preview) {
|
|
@@ -25133,9 +25352,9 @@ async function killPreview(sessionId) {
|
|
|
25133
25352
|
await preview.inspector?.close();
|
|
25134
25353
|
} catch {
|
|
25135
25354
|
}
|
|
25136
|
-
killProcessTree(preview.devServer, "SIGTERM");
|
|
25355
|
+
if (preview.devServer) killProcessTree(preview.devServer, "SIGTERM");
|
|
25137
25356
|
const sigkillTimer = setTimeout(() => {
|
|
25138
|
-
killProcessTree(preview.devServer, "SIGKILL");
|
|
25357
|
+
if (preview.devServer) killProcessTree(preview.devServer, "SIGKILL");
|
|
25139
25358
|
if (preview.tunnel) killProcessTree(preview.tunnel, "SIGKILL");
|
|
25140
25359
|
}, 250);
|
|
25141
25360
|
sigkillTimer.unref?.();
|
|
@@ -25151,7 +25370,7 @@ function activePreviewSessionIds() {
|
|
|
25151
25370
|
}
|
|
25152
25371
|
|
|
25153
25372
|
// src/services/preview/start-orchestrator.ts
|
|
25154
|
-
var
|
|
25373
|
+
var import_child_process23 = require("child_process");
|
|
25155
25374
|
var fs59 = __toESM(require("fs"));
|
|
25156
25375
|
var path64 = __toESM(require("path"));
|
|
25157
25376
|
var import_which2 = __toESM(require("which"));
|
|
@@ -25161,7 +25380,7 @@ var import_fs6 = require("fs");
|
|
|
25161
25380
|
var path63 = __toESM(require("path"));
|
|
25162
25381
|
|
|
25163
25382
|
// src/beads/project-key.ts
|
|
25164
|
-
var
|
|
25383
|
+
var import_child_process22 = require("child_process");
|
|
25165
25384
|
var crypto2 = __toESM(require("crypto"));
|
|
25166
25385
|
var fs57 = __toESM(require("fs"));
|
|
25167
25386
|
var path62 = __toESM(require("path"));
|
|
@@ -25208,7 +25427,7 @@ function findRepoRoot(cwd) {
|
|
|
25208
25427
|
}
|
|
25209
25428
|
var _execSeam3 = {
|
|
25210
25429
|
exec: (file, args2, opts) => {
|
|
25211
|
-
const out2 = (0,
|
|
25430
|
+
const out2 = (0, import_child_process22.execFileSync)(file, args2, opts);
|
|
25212
25431
|
return typeof out2 === "string" ? out2 : out2.toString("utf8");
|
|
25213
25432
|
},
|
|
25214
25433
|
realpath: (p2) => fs57.realpathSync(p2)
|
|
@@ -25318,12 +25537,16 @@ async function resolveNamedTunnel(ctx, fetchTunnel) {
|
|
|
25318
25537
|
}
|
|
25319
25538
|
|
|
25320
25539
|
// src/services/preview/inspector-proxy.ts
|
|
25321
|
-
var
|
|
25322
|
-
var
|
|
25540
|
+
var http7 = __toESM(require("http"));
|
|
25541
|
+
var net4 = __toESM(require("net"));
|
|
25323
25542
|
var INJECTION_SCAN_BUDGET_BYTES = 64 * 1024;
|
|
25324
25543
|
var INJECTION_ANCHORS = ["</head>", "<body>", "</body>"];
|
|
25325
|
-
function
|
|
25326
|
-
|
|
25544
|
+
function isNavigation(headers) {
|
|
25545
|
+
if (headers.secFetchDest !== void 0) {
|
|
25546
|
+
return headers.secFetchDest === "document" || headers.secFetchDest === "iframe";
|
|
25547
|
+
}
|
|
25548
|
+
if (headers.secFetchMode !== void 0) return headers.secFetchMode === "navigate";
|
|
25549
|
+
return typeof headers.accept === "string" && headers.accept.includes("text/html");
|
|
25327
25550
|
}
|
|
25328
25551
|
function isHtmlResponse(contentType) {
|
|
25329
25552
|
return typeof contentType === "string" && contentType.toLowerCase().includes("text/html");
|
|
@@ -25340,11 +25563,16 @@ function injectAt(html, script) {
|
|
|
25340
25563
|
async function startInspectorProxy(opts) {
|
|
25341
25564
|
const targetHost = opts.targetHost ?? "127.0.0.1";
|
|
25342
25565
|
const upgraded = /* @__PURE__ */ new Set();
|
|
25343
|
-
const server =
|
|
25344
|
-
const
|
|
25566
|
+
const server = http7.createServer((req, res) => {
|
|
25567
|
+
const one = (v) => Array.isArray(v) ? v[0] : v;
|
|
25568
|
+
const inject = isNavigation({
|
|
25569
|
+
accept: one(req.headers.accept),
|
|
25570
|
+
secFetchDest: one(req.headers["sec-fetch-dest"]),
|
|
25571
|
+
secFetchMode: one(req.headers["sec-fetch-mode"])
|
|
25572
|
+
});
|
|
25345
25573
|
const headers = { ...req.headers };
|
|
25346
25574
|
if (inject) delete headers["accept-encoding"];
|
|
25347
|
-
const upstream =
|
|
25575
|
+
const upstream = http7.request(
|
|
25348
25576
|
{ host: targetHost, port: opts.targetPort, method: req.method, path: req.url, headers },
|
|
25349
25577
|
(originRes) => {
|
|
25350
25578
|
const outHeaders = { ...originRes.headers };
|
|
@@ -25391,7 +25619,7 @@ async function startInspectorProxy(opts) {
|
|
|
25391
25619
|
});
|
|
25392
25620
|
server.on("upgrade", (req, clientSocket, head) => {
|
|
25393
25621
|
upgraded.add(clientSocket);
|
|
25394
|
-
const upstream =
|
|
25622
|
+
const upstream = net4.connect(opts.targetPort, targetHost, () => {
|
|
25395
25623
|
const lines = [`${req.method} ${req.url} HTTP/1.1`];
|
|
25396
25624
|
for (const [k2, v] of Object.entries(req.headers)) {
|
|
25397
25625
|
for (const one of Array.isArray(v) ? v : [v]) {
|
|
@@ -25588,6 +25816,77 @@ function inspectorClientSource(opts) {
|
|
|
25588
25816
|
send('hover', { element: describe(el) });
|
|
25589
25817
|
}
|
|
25590
25818
|
|
|
25819
|
+
// Captura, y se traga el evento: mientras el modo esta activo un clic
|
|
25820
|
+
// SELECCIONA, no navega. Sin esto, pulsar un enlace se llevaria el
|
|
25821
|
+
// preview a otra pagina en mitad del gesto.
|
|
25822
|
+
/**
|
|
25823
|
+
* Las marcas FIJADAS, dibujadas DENTRO de la pagina.
|
|
25824
|
+
*
|
|
25825
|
+
* \u26A0\uFE0F Antes las pintaba el dashboard, en una capa sobre el iframe. Como esa
|
|
25826
|
+
* capa vive fuera del documento, sus coordenadas son del VIEWPORT: al
|
|
25827
|
+
* hacer scroll dentro del preview las marcas se quedaban clavadas en la
|
|
25828
|
+
* pantalla mientras el elemento se iba (reportado el 2026-08-29).
|
|
25829
|
+
*
|
|
25830
|
+
* Aqui se anclan al DOCUMENTO (position:absolute mas el scroll sumado), asi
|
|
25831
|
+
* que acompa\xF1an al contenido igual que cualquier otro nodo de la pagina \u2014 y
|
|
25832
|
+
* ademas se recolocan si el layout cambia, que una capa externa no puede
|
|
25833
|
+
* saber.
|
|
25834
|
+
*/
|
|
25835
|
+
var picked = [];
|
|
25836
|
+
var seq = 0;
|
|
25837
|
+
var marksHost = null;
|
|
25838
|
+
|
|
25839
|
+
function ensureMarksHost() {
|
|
25840
|
+
if (marksHost && marksHost.parentNode) return marksHost;
|
|
25841
|
+
marksHost = document.createElement('div');
|
|
25842
|
+
marksHost.setAttribute('data-codeam', 'marks');
|
|
25843
|
+
marksHost.style.cssText = 'position:absolute;left:0;top:0;width:0;height:0;z-index:2147483646';
|
|
25844
|
+
document.body.appendChild(marksHost);
|
|
25845
|
+
return marksHost;
|
|
25846
|
+
}
|
|
25847
|
+
|
|
25848
|
+
function redrawMarks() {
|
|
25849
|
+
if (picked.length === 0) {
|
|
25850
|
+
if (marksHost && marksHost.parentNode) marksHost.parentNode.removeChild(marksHost);
|
|
25851
|
+
marksHost = null;
|
|
25852
|
+
return;
|
|
25853
|
+
}
|
|
25854
|
+
var host = ensureMarksHost();
|
|
25855
|
+
host.innerHTML = '';
|
|
25856
|
+
for (var i = 0; i < picked.length; i++) {
|
|
25857
|
+
var r = picked[i].el.getBoundingClientRect();
|
|
25858
|
+
// Coordenadas de DOCUMENTO: es lo que hace que la marca viaje con el
|
|
25859
|
+
// contenido en vez de quedarse pegada a la pantalla.
|
|
25860
|
+
var top = r.top + (window.scrollY || window.pageYOffset || 0);
|
|
25861
|
+
var left = r.left + (window.scrollX || window.pageXOffset || 0);
|
|
25862
|
+
|
|
25863
|
+
var box = document.createElement('div');
|
|
25864
|
+
box.setAttribute('data-codeam', 'mark');
|
|
25865
|
+
box.style.cssText = [
|
|
25866
|
+
'position:absolute', 'pointer-events:none', 'box-sizing:border-box',
|
|
25867
|
+
'border:1.5px solid #a855f7', 'background:rgba(168,85,247,0.12)',
|
|
25868
|
+
'border-radius:3px',
|
|
25869
|
+
'left:' + left + 'px', 'top:' + top + 'px',
|
|
25870
|
+
'width:' + r.width + 'px', 'height:' + r.height + 'px'
|
|
25871
|
+
].join(';');
|
|
25872
|
+
|
|
25873
|
+
var badge = document.createElement('div');
|
|
25874
|
+
badge.setAttribute('data-codeam', 'mark-badge');
|
|
25875
|
+
badge.style.cssText = [
|
|
25876
|
+
'position:absolute', 'left:-10px', 'top:-10px', 'width:20px', 'height:20px',
|
|
25877
|
+
'border-radius:10px', 'background:#a855f7', 'color:#000',
|
|
25878
|
+
'font:700 11px/20px ui-monospace,SFMono-Regular,Menlo,monospace',
|
|
25879
|
+
'text-align:center', 'pointer-events:none'
|
|
25880
|
+
].join(';');
|
|
25881
|
+
badge.textContent = String(i + 1);
|
|
25882
|
+
|
|
25883
|
+
box.appendChild(badge);
|
|
25884
|
+
host.appendChild(box);
|
|
25885
|
+
}
|
|
25886
|
+
}
|
|
25887
|
+
|
|
25888
|
+
function reposition() { if (picked.length) redrawMarks(); }
|
|
25889
|
+
|
|
25591
25890
|
// Captura, y se traga el evento: mientras el modo esta activo un clic
|
|
25592
25891
|
// SELECCIONA, no navega. Sin esto, pulsar un enlace se llevaria el
|
|
25593
25892
|
// preview a otra pagina en mitad del gesto.
|
|
@@ -25597,7 +25896,30 @@ function inspectorClientSource(opts) {
|
|
|
25597
25896
|
if (el && el.getAttribute && el.getAttribute('data-codeam')) return;
|
|
25598
25897
|
e.preventDefault();
|
|
25599
25898
|
e.stopPropagation();
|
|
25600
|
-
if (el)
|
|
25899
|
+
if (!el) return;
|
|
25900
|
+
var id = 'p' + (++seq);
|
|
25901
|
+
picked.push({ id: id, el: el });
|
|
25902
|
+
redrawMarks();
|
|
25903
|
+
var described = describe(el);
|
|
25904
|
+
described.markId = id;
|
|
25905
|
+
send('pick', { element: described });
|
|
25906
|
+
}
|
|
25907
|
+
|
|
25908
|
+
/**
|
|
25909
|
+
* El dashboard manda la lista de ids que SIGUEN vivos, en su orden.
|
|
25910
|
+
*
|
|
25911
|
+
* Es la otra mitad de \xABla marca es un objeto\xBB: si el usuario borra un chip
|
|
25912
|
+
* en el composer, la marca tiene que desaparecer de la pagina \u2014 y las que
|
|
25913
|
+
* quedan renumerarse, porque lo que el usuario escribe (\xAB\u2460 se sale\xBB) mira
|
|
25914
|
+
* a estos numeros.
|
|
25915
|
+
*/
|
|
25916
|
+
function syncMarks(ids) {
|
|
25917
|
+
var byId = {};
|
|
25918
|
+
for (var i = 0; i < picked.length; i++) byId[picked[i].id] = picked[i];
|
|
25919
|
+
var next = [];
|
|
25920
|
+
for (var j = 0; j < ids.length; j++) if (byId[ids[j]]) next.push(byId[ids[j]]);
|
|
25921
|
+
picked = next;
|
|
25922
|
+
redrawMarks();
|
|
25601
25923
|
}
|
|
25602
25924
|
|
|
25603
25925
|
function enable(origin) {
|
|
@@ -25606,6 +25928,9 @@ function inspectorClientSource(opts) {
|
|
|
25606
25928
|
driver = origin;
|
|
25607
25929
|
document.addEventListener('mousemove', onMove, true);
|
|
25608
25930
|
document.addEventListener('click', onClick, true);
|
|
25931
|
+
// El scroll y el resize mueven los elementos; las marcas los siguen.
|
|
25932
|
+
window.addEventListener('scroll', reposition, true);
|
|
25933
|
+
window.addEventListener('resize', reposition);
|
|
25609
25934
|
send('ready', {});
|
|
25610
25935
|
}
|
|
25611
25936
|
|
|
@@ -25615,7 +25940,11 @@ function inspectorClientSource(opts) {
|
|
|
25615
25940
|
current = null;
|
|
25616
25941
|
document.removeEventListener('mousemove', onMove, true);
|
|
25617
25942
|
document.removeEventListener('click', onClick, true);
|
|
25943
|
+
window.removeEventListener('scroll', reposition, true);
|
|
25944
|
+
window.removeEventListener('resize', reposition);
|
|
25618
25945
|
removeOverlay();
|
|
25946
|
+
// Las marcas fijadas SI sobreviven a salir del modo: siguen siendo el
|
|
25947
|
+
// contexto del mensaje que el usuario esta escribiendo.
|
|
25619
25948
|
driver = null;
|
|
25620
25949
|
}
|
|
25621
25950
|
|
|
@@ -25625,6 +25954,7 @@ function inspectorClientSource(opts) {
|
|
|
25625
25954
|
if (!data || data.source !== CHANNEL) return;
|
|
25626
25955
|
if (data.type === 'enable') enable(e.origin);
|
|
25627
25956
|
else if (data.type === 'disable') disable();
|
|
25957
|
+
else if (data.type === 'marks' && data.ids) syncMarks(data.ids);
|
|
25628
25958
|
});
|
|
25629
25959
|
|
|
25630
25960
|
/**
|
|
@@ -25772,7 +26102,7 @@ async function runPreviewStart(args2) {
|
|
|
25772
26102
|
}
|
|
25773
26103
|
};
|
|
25774
26104
|
const existing = activePreviews.get(sessionId);
|
|
25775
|
-
if (existing && existing.devServer.exitCode
|
|
26105
|
+
if (existing && existing.devServer?.exitCode !== 0 && existing.devServer?.exitCode == null) {
|
|
25776
26106
|
log.info(
|
|
25777
26107
|
"preview",
|
|
25778
26108
|
`reusing running preview for session=${sessionId} url=${existing.url}`
|
|
@@ -25806,7 +26136,9 @@ async function runPreviewStart(args2) {
|
|
|
25806
26136
|
detection,
|
|
25807
26137
|
cwd: ctx.cwd
|
|
25808
26138
|
});
|
|
25809
|
-
|
|
26139
|
+
if (dev.devServer) {
|
|
26140
|
+
recordPreviewPort(detection.port, dev.devServer.pid, sessionId, Date.now());
|
|
26141
|
+
}
|
|
25810
26142
|
log.info("preview", `ready: ${detection.framework} at ${tun.url}`);
|
|
25811
26143
|
emit2(USER_EVENTS.PREVIEW_READY, {
|
|
25812
26144
|
url: tun.url,
|
|
@@ -25919,7 +26251,7 @@ async function startDevServer(ctx) {
|
|
|
25919
26251
|
const { sessionId, detection, cwd, emit: emit2, emitProgress } = ctx;
|
|
25920
26252
|
if (await isPortListening(detection.port)) {
|
|
25921
26253
|
const raceExisting = activePreviews.get(sessionId);
|
|
25922
|
-
if (raceExisting && raceExisting.devServer
|
|
26254
|
+
if (raceExisting && raceExisting.devServer?.exitCode == null) {
|
|
25923
26255
|
log.info(
|
|
25924
26256
|
"preview",
|
|
25925
26257
|
`port race: reusing running preview for session=${sessionId} url=${raceExisting.url}`
|
|
@@ -25935,7 +26267,7 @@ async function startDevServer(ctx) {
|
|
|
25935
26267
|
if (raceExisting) {
|
|
25936
26268
|
log.info(
|
|
25937
26269
|
"preview",
|
|
25938
|
-
`reclaiming stale preview holding port ${detection.port} for session=${sessionId} (exit=${raceExisting.devServer
|
|
26270
|
+
`reclaiming stale preview holding port ${detection.port} for session=${sessionId} (exit=${raceExisting.devServer?.exitCode})`
|
|
25939
26271
|
);
|
|
25940
26272
|
await killPreview(sessionId);
|
|
25941
26273
|
const freeDeadline = Date.now() + 4e3;
|
|
@@ -25963,9 +26295,18 @@ async function startDevServer(ctx) {
|
|
|
25963
26295
|
return null;
|
|
25964
26296
|
}
|
|
25965
26297
|
} else {
|
|
26298
|
+
const verdict = await canAdoptPort(detection.port);
|
|
26299
|
+
if (verdict.adopt) {
|
|
26300
|
+
log.info(
|
|
26301
|
+
"preview",
|
|
26302
|
+
`adopting the dev server already serving on port ${detection.port}`
|
|
26303
|
+
);
|
|
26304
|
+
emitProgress("READY_DETECTED", `adopted the server already on port ${detection.port}`);
|
|
26305
|
+
return { devServer: null, expoUrlRef: { current: null } };
|
|
26306
|
+
}
|
|
25966
26307
|
emit2(USER_EVENTS.PREVIEW_ERROR, {
|
|
25967
26308
|
stage: "spawn",
|
|
25968
|
-
message: `Port ${detection.port} is already in use by
|
|
26309
|
+
message: verdict.reason === "directory-listing" ? `Port ${detection.port} is serving a directory listing, not your app \u2014 that's usually a leftover \`python -m http.server\`. Stop it and try the preview again.` : `Port ${detection.port} is already in use by something that isn't a dev server, so the preview can't start there. Stop whatever is listening on port ${detection.port} and try again.`
|
|
25969
26310
|
});
|
|
25970
26311
|
return null;
|
|
25971
26312
|
}
|
|
@@ -25973,7 +26314,7 @@ async function startDevServer(ctx) {
|
|
|
25973
26314
|
await applyPreviewHostAllow(cwd);
|
|
25974
26315
|
const spawnable = normalizeDetectionForSpawn(detection, cwd);
|
|
25975
26316
|
emitProgress("BOOT_SEQUENCE", `${spawnable.command} ${spawnable.args.join(" ")}`);
|
|
25976
|
-
const devServer = (0,
|
|
26317
|
+
const devServer = (0, import_child_process23.spawn)(spawnable.command, spawnable.args, {
|
|
25977
26318
|
cwd,
|
|
25978
26319
|
env: { ...process.env, ...spawnable.env ?? {} },
|
|
25979
26320
|
stdio: ["ignore", "pipe", "pipe"],
|
|
@@ -26039,7 +26380,7 @@ async function establishTunnel(ctx, dev) {
|
|
|
26039
26380
|
}
|
|
26040
26381
|
const expoUrl = dev.expoUrlRef.current;
|
|
26041
26382
|
if (!expoUrl) {
|
|
26042
|
-
killProcessTree(devServer, "SIGTERM");
|
|
26383
|
+
if (devServer) killProcessTree(devServer, "SIGTERM");
|
|
26043
26384
|
emit2(USER_EVENTS.PREVIEW_ERROR, {
|
|
26044
26385
|
stage: "tunnel",
|
|
26045
26386
|
message: "Expo did not report a tunnel URL."
|
|
@@ -26056,7 +26397,7 @@ async function establishTunnel(ctx, dev) {
|
|
|
26056
26397
|
try {
|
|
26057
26398
|
bin = await resolveCloudflared();
|
|
26058
26399
|
} catch (e) {
|
|
26059
|
-
killProcessTree(devServer, "SIGTERM");
|
|
26400
|
+
if (devServer) killProcessTree(devServer, "SIGTERM");
|
|
26060
26401
|
emit2(USER_EVENTS.PREVIEW_ERROR, {
|
|
26061
26402
|
stage: "tunnel",
|
|
26062
26403
|
message: e.message
|
|
@@ -26110,7 +26451,7 @@ async function establishTunnel(ctx, dev) {
|
|
|
26110
26451
|
`cloudflared quick tunnel (retry ${attempt}/${MAX_TUNNEL_ATTEMPTS})`
|
|
26111
26452
|
);
|
|
26112
26453
|
}
|
|
26113
|
-
const candidate = (0,
|
|
26454
|
+
const candidate = (0, import_child_process23.spawn)(
|
|
26114
26455
|
bin,
|
|
26115
26456
|
["tunnel", "--url", `http://localhost:${tunnelPort}`],
|
|
26116
26457
|
{ stdio: ["ignore", "pipe", "pipe"] }
|
|
@@ -26130,7 +26471,7 @@ async function establishTunnel(ctx, dev) {
|
|
|
26130
26471
|
}
|
|
26131
26472
|
}
|
|
26132
26473
|
if (!parsedUrl) {
|
|
26133
|
-
killProcessTree(devServer, "SIGTERM");
|
|
26474
|
+
if (devServer) killProcessTree(devServer, "SIGTERM");
|
|
26134
26475
|
emit2(USER_EVENTS.PREVIEW_ERROR, {
|
|
26135
26476
|
stage: "tunnel",
|
|
26136
26477
|
message: `Tunnel did not become reachable after ${MAX_TUNNEL_ATTEMPTS} attempts (${lastTunnelErr}). Cloudflare Quick Tunnels occasionally fail to register \u2014 please retry.`
|
|
@@ -26141,7 +26482,7 @@ async function establishTunnel(ctx, dev) {
|
|
|
26141
26482
|
}
|
|
26142
26483
|
|
|
26143
26484
|
// src/beads/bd-adapter.ts
|
|
26144
|
-
var
|
|
26485
|
+
var import_child_process24 = require("child_process");
|
|
26145
26486
|
var fs60 = __toESM(require("fs"));
|
|
26146
26487
|
var os48 = __toESM(require("os"));
|
|
26147
26488
|
var path65 = __toESM(require("path"));
|
|
@@ -26195,7 +26536,7 @@ function _defaultSpawn(binaryPath, args2, opts) {
|
|
|
26195
26536
|
return new Promise((resolve10) => {
|
|
26196
26537
|
let proc;
|
|
26197
26538
|
try {
|
|
26198
|
-
proc = (0,
|
|
26539
|
+
proc = (0, import_child_process24.spawn)(binaryPath, args2, { cwd: opts.cwd, env: opts.env });
|
|
26199
26540
|
} catch (err) {
|
|
26200
26541
|
resolve10({ code: -1, stdout: "", stderr: err.message });
|
|
26201
26542
|
return;
|
|
@@ -26352,13 +26693,13 @@ function coerceIssue(row, projectKey) {
|
|
|
26352
26693
|
}
|
|
26353
26694
|
|
|
26354
26695
|
// src/beads/provisioner.ts
|
|
26355
|
-
var
|
|
26696
|
+
var import_child_process27 = require("child_process");
|
|
26356
26697
|
var fs62 = __toESM(require("fs"));
|
|
26357
26698
|
var os50 = __toESM(require("os"));
|
|
26358
26699
|
var path67 = __toESM(require("path"));
|
|
26359
26700
|
|
|
26360
26701
|
// src/beads/install-bd.ts
|
|
26361
|
-
var
|
|
26702
|
+
var import_child_process25 = require("child_process");
|
|
26362
26703
|
var INSTALL_SH_URL = "https://raw.githubusercontent.com/gastownhall/beads/main/scripts/install.sh";
|
|
26363
26704
|
var INSTALL_PS1_URL = "https://raw.githubusercontent.com/gastownhall/beads/main/install.ps1";
|
|
26364
26705
|
function resolveInstallStrategy(platform3) {
|
|
@@ -26389,7 +26730,7 @@ function _defaultInstallSpawn(strategy) {
|
|
|
26389
26730
|
return new Promise((resolve10) => {
|
|
26390
26731
|
let proc;
|
|
26391
26732
|
try {
|
|
26392
|
-
proc = (0,
|
|
26733
|
+
proc = (0, import_child_process25.spawn)(strategy.command, strategy.args, { env: process.env });
|
|
26393
26734
|
} catch (err) {
|
|
26394
26735
|
resolve10({ ok: false, code: -1, stderr: err.message });
|
|
26395
26736
|
return;
|
|
@@ -26419,7 +26760,7 @@ async function installBd(platform3 = process.platform) {
|
|
|
26419
26760
|
}
|
|
26420
26761
|
|
|
26421
26762
|
// src/beads/install-dolt.ts
|
|
26422
|
-
var
|
|
26763
|
+
var import_child_process26 = require("child_process");
|
|
26423
26764
|
var fs61 = __toESM(require("fs"));
|
|
26424
26765
|
var os49 = __toESM(require("os"));
|
|
26425
26766
|
var path66 = __toESM(require("path"));
|
|
@@ -26581,7 +26922,7 @@ function _defaultDoltInstallSpawn(strategy) {
|
|
|
26581
26922
|
};
|
|
26582
26923
|
let proc;
|
|
26583
26924
|
try {
|
|
26584
|
-
proc = (0,
|
|
26925
|
+
proc = (0, import_child_process26.spawn)(strategy.command, strategy.args, {
|
|
26585
26926
|
env: process.env,
|
|
26586
26927
|
stdio: ["ignore", "pipe", "pipe"]
|
|
26587
26928
|
});
|
|
@@ -26808,7 +27149,7 @@ function linkBdOntoPath(binaryPath) {
|
|
|
26808
27149
|
log.info("beads", `linked bd onto PATH: ${linkPath} -> ${binaryPath}`);
|
|
26809
27150
|
}
|
|
26810
27151
|
function setGitBeadsRole() {
|
|
26811
|
-
(0,
|
|
27152
|
+
(0, import_child_process27.execFileSync)("git", ["config", "--global", "beads.role", "contributor"], {
|
|
26812
27153
|
stdio: "ignore"
|
|
26813
27154
|
});
|
|
26814
27155
|
}
|
|
@@ -27663,7 +28004,7 @@ var sessionTerminated = async (ctx, cmd) => {
|
|
|
27663
28004
|
}
|
|
27664
28005
|
quiet(() => ctx.agent.kill());
|
|
27665
28006
|
try {
|
|
27666
|
-
const proc = (0,
|
|
28007
|
+
const proc = (0, import_child_process28.spawn)("bash", ["-lc", "pm2 delete codeam-pair >/dev/null 2>&1 || true"], {
|
|
27667
28008
|
detached: true,
|
|
27668
28009
|
stdio: "ignore"
|
|
27669
28010
|
});
|
|
@@ -27682,7 +28023,7 @@ var shutdownSession = async (ctx, cmd) => {
|
|
|
27682
28023
|
quiet(() => ctx.agent.kill());
|
|
27683
28024
|
if (ctx.keepAliveCtx.inCodespace && ctx.keepAliveCtx.codespaceName) {
|
|
27684
28025
|
try {
|
|
27685
|
-
const stopProc = (0,
|
|
28026
|
+
const stopProc = (0, import_child_process28.spawn)(
|
|
27686
28027
|
"bash",
|
|
27687
28028
|
["-lc", `sleep 1; gh codespace stop -c ${JSON.stringify(ctx.keepAliveCtx.codespaceName)} >/dev/null 2>&1 || true`],
|
|
27688
28029
|
{ detached: true, stdio: "ignore" }
|
|
@@ -27692,7 +28033,7 @@ var shutdownSession = async (ctx, cmd) => {
|
|
|
27692
28033
|
}
|
|
27693
28034
|
}
|
|
27694
28035
|
try {
|
|
27695
|
-
const proc = (0,
|
|
28036
|
+
const proc = (0, import_child_process28.spawn)("bash", ["-lc", "pm2 delete codeam-pair >/dev/null 2>&1 || true"], {
|
|
27696
28037
|
detached: true,
|
|
27697
28038
|
stdio: "ignore"
|
|
27698
28039
|
});
|
|
@@ -28297,7 +28638,7 @@ var defaultCliUpdateDeps = {
|
|
|
28297
28638
|
// Only a truly local `codeam start` (neither marker) re-execs in place below.
|
|
28298
28639
|
isSupervised: () => process.env["CODEAM_AUTO_APPROVE"] === "1" || process.env["CODESPACES"] === "true",
|
|
28299
28640
|
relaunch: (args2) => {
|
|
28300
|
-
const child = (0,
|
|
28641
|
+
const child = (0, import_child_process28.spawnSync)("codeam", args2, { stdio: "inherit", env: process.env });
|
|
28301
28642
|
process.exit(child.status ?? 0);
|
|
28302
28643
|
}
|
|
28303
28644
|
};
|
|
@@ -28378,7 +28719,7 @@ async function runNpmInstallLatest() {
|
|
|
28378
28719
|
const useShell = process.platform === "win32";
|
|
28379
28720
|
const command2 = useShell && invocation.command.includes(" ") ? `"${invocation.command}"` : invocation.command;
|
|
28380
28721
|
const result = await new Promise((resolve10) => {
|
|
28381
|
-
(0,
|
|
28722
|
+
(0, import_child_process28.execFile)(
|
|
28382
28723
|
command2,
|
|
28383
28724
|
invocation.args,
|
|
28384
28725
|
{ timeout: CLI_UPDATE_INSTALL_TIMEOUT_MS, shell: useShell },
|
|
@@ -28705,9 +29046,18 @@ function parseInsightText(text) {
|
|
|
28705
29046
|
securityNote: securityMatch?.[1]?.trim() || void 0
|
|
28706
29047
|
};
|
|
28707
29048
|
}
|
|
28708
|
-
var
|
|
29049
|
+
var emitPreviewEventRaw = makeSerializedEmitter(
|
|
28709
29050
|
(args2) => postPreviewEvent(args2)
|
|
28710
29051
|
);
|
|
29052
|
+
var emitPreviewEvent = (args2) => {
|
|
29053
|
+
if (args2.type !== USER_EVENTS.PREVIEW_ERROR) return emitPreviewEventRaw(args2);
|
|
29054
|
+
const missing = getLastProvisionOutcome()?.missing ?? [];
|
|
29055
|
+
if (missing.length === 0) return emitPreviewEventRaw(args2);
|
|
29056
|
+
return emitPreviewEventRaw({
|
|
29057
|
+
...args2,
|
|
29058
|
+
payload: { ...args2.payload ?? {}, missingServices: missing }
|
|
29059
|
+
});
|
|
29060
|
+
};
|
|
28711
29061
|
var requestPreviewDetectH = (ctx) => {
|
|
28712
29062
|
if (!ctx.pluginAuthToken) {
|
|
28713
29063
|
log.info("preview", "no pluginAuthToken \u2014 skipping detect");
|
|
@@ -28804,7 +29154,7 @@ function makePreviewReaffirm(args2) {
|
|
|
28804
29154
|
return makePreviewHeartbeatReaffirm({
|
|
28805
29155
|
serving: () => {
|
|
28806
29156
|
const active2 = activePreviews.get(sessionId);
|
|
28807
|
-
if (!active2 || active2.devServer.exitCode !== null) return null;
|
|
29157
|
+
if (!active2 || active2.devServer && active2.devServer.exitCode !== null) return null;
|
|
28808
29158
|
return {
|
|
28809
29159
|
url: active2.url,
|
|
28810
29160
|
framework: active2.framework,
|
|
@@ -29048,13 +29398,13 @@ async function dispatchCommand(ctx, cmd) {
|
|
|
29048
29398
|
}
|
|
29049
29399
|
|
|
29050
29400
|
// src/commands/start/keep-alive.ts
|
|
29051
|
-
var
|
|
29401
|
+
var import_child_process29 = require("child_process");
|
|
29052
29402
|
function buildKeepAlive(ctx) {
|
|
29053
29403
|
let timer = null;
|
|
29054
29404
|
async function setIdleTimeout(minutes) {
|
|
29055
29405
|
if (!ctx.inCodespace || !ctx.codespaceName) return;
|
|
29056
29406
|
await new Promise((resolve10) => {
|
|
29057
|
-
const proc = (0,
|
|
29407
|
+
const proc = (0, import_child_process29.spawn)(
|
|
29058
29408
|
"gh",
|
|
29059
29409
|
[
|
|
29060
29410
|
"api",
|
|
@@ -30227,7 +30577,7 @@ var fs67 = __toESM(require("fs"));
|
|
|
30227
30577
|
var path74 = __toESM(require("path"));
|
|
30228
30578
|
var os56 = __toESM(require("os"));
|
|
30229
30579
|
var https7 = __toESM(require("https"));
|
|
30230
|
-
var
|
|
30580
|
+
var http8 = __toESM(require("http"));
|
|
30231
30581
|
var import_zod2 = require("zod");
|
|
30232
30582
|
var historyRecordSchema = import_zod2.z.object({
|
|
30233
30583
|
type: import_zod2.z.string().optional(),
|
|
@@ -30310,7 +30660,7 @@ function post(endpoint, body, pluginAuthToken) {
|
|
|
30310
30660
|
return new Promise((resolve10) => {
|
|
30311
30661
|
const payload = JSON.stringify(body);
|
|
30312
30662
|
const u2 = new URL(`${API_BASE8}${endpoint}`);
|
|
30313
|
-
const transport = u2.protocol === "https:" ? https7 :
|
|
30663
|
+
const transport = u2.protocol === "https:" ? https7 : http8;
|
|
30314
30664
|
const req = transport.request(
|
|
30315
30665
|
{
|
|
30316
30666
|
hostname: u2.hostname,
|
|
@@ -36036,12 +36386,12 @@ function buildRelaunchProxyEnv(baseEnv) {
|
|
|
36036
36386
|
return env;
|
|
36037
36387
|
}
|
|
36038
36388
|
var relaunchProxyWithoutBudget = async () => {
|
|
36039
|
-
const { spawn:
|
|
36389
|
+
const { spawn: spawn47 } = await import("child_process");
|
|
36040
36390
|
killHeadroomProxy();
|
|
36041
36391
|
await new Promise((r) => setTimeout(r, 500));
|
|
36042
36392
|
const proxyEnv = buildRelaunchProxyEnv(process.env);
|
|
36043
36393
|
try {
|
|
36044
|
-
const proxy =
|
|
36394
|
+
const proxy = spawn47(
|
|
36045
36395
|
"headroom",
|
|
36046
36396
|
["proxy", "--port", "8787"],
|
|
36047
36397
|
{ stdio: "ignore", detached: true, env: proxyEnv }
|
|
@@ -36261,7 +36611,7 @@ async function performAgentSwitch(deps, rawAgentId, fastPath = {}) {
|
|
|
36261
36611
|
}
|
|
36262
36612
|
|
|
36263
36613
|
// src/services/streaming/transport.ts
|
|
36264
|
-
var
|
|
36614
|
+
var http9 = __toESM(require("http"));
|
|
36265
36615
|
var https8 = __toESM(require("https"));
|
|
36266
36616
|
var _transport4 = {
|
|
36267
36617
|
post: _post3,
|
|
@@ -36271,7 +36621,7 @@ function _post3(url2, headers, payload) {
|
|
|
36271
36621
|
return new Promise((resolve10, reject) => {
|
|
36272
36622
|
let settled = false;
|
|
36273
36623
|
const u2 = new URL(url2);
|
|
36274
|
-
const lib = u2.protocol === "https:" ? https8 :
|
|
36624
|
+
const lib = u2.protocol === "https:" ? https8 : http9;
|
|
36275
36625
|
const req = lib.request(
|
|
36276
36626
|
{
|
|
36277
36627
|
hostname: u2.hostname,
|
|
@@ -36313,7 +36663,7 @@ function _get(url2, headers) {
|
|
|
36313
36663
|
return new Promise((resolve10, reject) => {
|
|
36314
36664
|
let settled = false;
|
|
36315
36665
|
const u2 = new URL(url2);
|
|
36316
|
-
const lib = u2.protocol === "https:" ? https8 :
|
|
36666
|
+
const lib = u2.protocol === "https:" ? https8 : http9;
|
|
36317
36667
|
const req = lib.request(
|
|
36318
36668
|
{
|
|
36319
36669
|
hostname: u2.hostname,
|
|
@@ -36947,7 +37297,7 @@ function withholdTrailingPartialFenceMarker(text) {
|
|
|
36947
37297
|
}
|
|
36948
37298
|
|
|
36949
37299
|
// src/agents/acp/onboarding.ts
|
|
36950
|
-
var
|
|
37300
|
+
var import_child_process30 = require("child_process");
|
|
36951
37301
|
var fs69 = __toESM(require("fs"));
|
|
36952
37302
|
var os59 = __toESM(require("os"));
|
|
36953
37303
|
var path77 = __toESM(require("path"));
|
|
@@ -36968,7 +37318,7 @@ var _onboardingSeam = {
|
|
|
36968
37318
|
*/
|
|
36969
37319
|
gitRemoteUrl: (cwd) => {
|
|
36970
37320
|
try {
|
|
36971
|
-
return (0,
|
|
37321
|
+
return (0, import_child_process30.execFileSync)("git", ["-C", cwd, "remote", "get-url", "origin"], {
|
|
36972
37322
|
encoding: "utf8",
|
|
36973
37323
|
stdio: ["ignore", "pipe", "ignore"],
|
|
36974
37324
|
timeout: 2e3
|
|
@@ -37324,7 +37674,7 @@ function extractSelectPrompt(text) {
|
|
|
37324
37674
|
var import_crypto5 = require("crypto");
|
|
37325
37675
|
|
|
37326
37676
|
// src/services/turn-files/git-changeset.ts
|
|
37327
|
-
var
|
|
37677
|
+
var import_child_process31 = require("child_process");
|
|
37328
37678
|
var fs71 = __toESM(require("fs/promises"));
|
|
37329
37679
|
var path79 = __toESM(require("path"));
|
|
37330
37680
|
|
|
@@ -37510,7 +37860,7 @@ function defaultRunGit(cwd, args2) {
|
|
|
37510
37860
|
return new Promise((resolve10) => {
|
|
37511
37861
|
let proc;
|
|
37512
37862
|
try {
|
|
37513
|
-
proc = (0,
|
|
37863
|
+
proc = (0, import_child_process31.spawn)("git", args2, { cwd, env: process.env });
|
|
37514
37864
|
} catch {
|
|
37515
37865
|
resolve10(null);
|
|
37516
37866
|
return;
|
|
@@ -43537,8 +43887,9 @@ async function start(requestedAgent, presetSession) {
|
|
|
43537
43887
|
})
|
|
43538
43888
|
);
|
|
43539
43889
|
provisionSkillsForStart();
|
|
43540
|
-
const
|
|
43541
|
-
|
|
43890
|
+
const managedBox = !isLocalSession();
|
|
43891
|
+
const depsReady = managedBox ? provisionProjectDependencies(cwd).then((outcome) => noteProvisionOutcome(outcome)).catch(() => void 0) : Promise.resolve();
|
|
43892
|
+
if (managedBox) {
|
|
43542
43893
|
const GATE_TIMEOUT_MS = 24e4;
|
|
43543
43894
|
const acpAdapterForGate = requiresAcp(session.agent) ? await resolveAcpAdapterWithRetry(session.agent) : null;
|
|
43544
43895
|
const agentBinaryReady = acpAdapterForGate ? Promise.all([
|
|
@@ -44158,11 +44509,11 @@ async function logout() {
|
|
|
44158
44509
|
var import_picocolors11 = __toESM(require("picocolors"));
|
|
44159
44510
|
|
|
44160
44511
|
// src/services/providers/github-codespaces.ts
|
|
44161
|
-
var
|
|
44512
|
+
var import_child_process32 = require("child_process");
|
|
44162
44513
|
var import_util4 = require("util");
|
|
44163
44514
|
var import_picocolors9 = __toESM(require("picocolors"));
|
|
44164
44515
|
var path89 = __toESM(require("path"));
|
|
44165
|
-
var execFileP6 = (0, import_util4.promisify)(
|
|
44516
|
+
var execFileP6 = (0, import_util4.promisify)(import_child_process32.execFile);
|
|
44166
44517
|
var MAX_BUFFER = 8 * 1024 * 1024;
|
|
44167
44518
|
function resetStdinForChild() {
|
|
44168
44519
|
if (process.stdin.isTTY) {
|
|
@@ -44206,7 +44557,7 @@ var GitHubCodespacesProvider = class {
|
|
|
44206
44557
|
if (!isAuthed) {
|
|
44207
44558
|
resetStdinForChild();
|
|
44208
44559
|
await new Promise((resolve10, reject) => {
|
|
44209
|
-
const proc = (0,
|
|
44560
|
+
const proc = (0, import_child_process32.spawn)("gh", ["auth", "login", "-s", "codespace,repo,read:user"], {
|
|
44210
44561
|
stdio: "inherit"
|
|
44211
44562
|
});
|
|
44212
44563
|
proc.on("exit", (code) => {
|
|
@@ -44240,7 +44591,7 @@ var GitHubCodespacesProvider = class {
|
|
|
44240
44591
|
wt(noteLines.join("\n"), "One more permission needed");
|
|
44241
44592
|
resetStdinForChild();
|
|
44242
44593
|
const refreshCode = await new Promise((resolve10, reject) => {
|
|
44243
|
-
const proc = (0,
|
|
44594
|
+
const proc = (0, import_child_process32.spawn)(
|
|
44244
44595
|
"gh",
|
|
44245
44596
|
["auth", "refresh", "-h", "github.com", "-s", "codespace"],
|
|
44246
44597
|
{ stdio: "inherit" }
|
|
@@ -44390,7 +44741,7 @@ var GitHubCodespacesProvider = class {
|
|
|
44390
44741
|
O2.step(`Installing gh via ${installCmd.describe}\u2026`);
|
|
44391
44742
|
resetStdinForChild();
|
|
44392
44743
|
const ok = await new Promise((resolve10) => {
|
|
44393
|
-
const proc = (0,
|
|
44744
|
+
const proc = (0, import_child_process32.spawn)(installCmd.exe, installCmd.args, { stdio: "inherit" });
|
|
44394
44745
|
proc.on("exit", (code) => resolve10(code === 0));
|
|
44395
44746
|
proc.on("error", () => resolve10(false));
|
|
44396
44747
|
});
|
|
@@ -44417,7 +44768,7 @@ var GitHubCodespacesProvider = class {
|
|
|
44417
44768
|
);
|
|
44418
44769
|
resetStdinForChild();
|
|
44419
44770
|
await new Promise((resolve10, reject) => {
|
|
44420
|
-
const proc = (0,
|
|
44771
|
+
const proc = (0, import_child_process32.spawn)(
|
|
44421
44772
|
"gh",
|
|
44422
44773
|
["auth", "refresh", "-h", "github.com", "-s", "repo,read:org"],
|
|
44423
44774
|
{ stdio: "inherit" }
|
|
@@ -44595,7 +44946,7 @@ var GitHubCodespacesProvider = class {
|
|
|
44595
44946
|
async streamCommand(workspaceId, command2) {
|
|
44596
44947
|
resetStdinForChild();
|
|
44597
44948
|
return new Promise((resolve10, reject) => {
|
|
44598
|
-
const proc = (0,
|
|
44949
|
+
const proc = (0, import_child_process32.spawn)(
|
|
44599
44950
|
"gh",
|
|
44600
44951
|
["codespace", "ssh", "-c", workspaceId, "--", "-tt", command2],
|
|
44601
44952
|
{ stdio: "inherit" }
|
|
@@ -44622,11 +44973,11 @@ var GitHubCodespacesProvider = class {
|
|
|
44622
44973
|
`mkdir -p ${shellQuote(remoteDir)} && tar -xzf - -C ${shellQuote(remoteDir)}`
|
|
44623
44974
|
];
|
|
44624
44975
|
await new Promise((resolve10, reject) => {
|
|
44625
|
-
const tar = (0,
|
|
44976
|
+
const tar = (0, import_child_process32.spawn)("tar", tarArgs, {
|
|
44626
44977
|
stdio: ["ignore", "pipe", "pipe"],
|
|
44627
44978
|
env: tarEnv
|
|
44628
44979
|
});
|
|
44629
|
-
const ssh = (0,
|
|
44980
|
+
const ssh = (0, import_child_process32.spawn)("gh", sshArgs, {
|
|
44630
44981
|
stdio: [tar.stdout, "pipe", "pipe"]
|
|
44631
44982
|
});
|
|
44632
44983
|
let tarErr = "";
|
|
@@ -44660,7 +45011,7 @@ var GitHubCodespacesProvider = class {
|
|
|
44660
45011
|
}
|
|
44661
45012
|
const cmd = parts.join(" && ");
|
|
44662
45013
|
await new Promise((resolve10, reject) => {
|
|
44663
|
-
const proc = (0,
|
|
45014
|
+
const proc = (0, import_child_process32.spawn)(
|
|
44664
45015
|
"gh",
|
|
44665
45016
|
["codespace", "ssh", "-c", workspaceId, "--", cmd],
|
|
44666
45017
|
{ stdio: ["pipe", "pipe", "pipe"] }
|
|
@@ -44718,11 +45069,11 @@ function shellQuote(s) {
|
|
|
44718
45069
|
}
|
|
44719
45070
|
|
|
44720
45071
|
// src/services/providers/gitpod.ts
|
|
44721
|
-
var
|
|
45072
|
+
var import_child_process33 = require("child_process");
|
|
44722
45073
|
var import_util5 = require("util");
|
|
44723
45074
|
var path90 = __toESM(require("path"));
|
|
44724
45075
|
var import_picocolors10 = __toESM(require("picocolors"));
|
|
44725
|
-
var execFileP7 = (0, import_util5.promisify)(
|
|
45076
|
+
var execFileP7 = (0, import_util5.promisify)(import_child_process33.execFile);
|
|
44726
45077
|
var MAX_BUFFER2 = 8 * 1024 * 1024;
|
|
44727
45078
|
function resetStdinForChild2() {
|
|
44728
45079
|
if (process.stdin.isTTY) {
|
|
@@ -44762,7 +45113,7 @@ var GitpodProvider = class {
|
|
|
44762
45113
|
);
|
|
44763
45114
|
resetStdinForChild2();
|
|
44764
45115
|
await new Promise((resolve10, reject) => {
|
|
44765
|
-
const proc = (0,
|
|
45116
|
+
const proc = (0, import_child_process33.spawn)("gitpod", ["login"], { stdio: "inherit" });
|
|
44766
45117
|
proc.on("exit", (code) => {
|
|
44767
45118
|
if (code === 0) resolve10();
|
|
44768
45119
|
else reject(new Error("gitpod login failed."));
|
|
@@ -44914,7 +45265,7 @@ var GitpodProvider = class {
|
|
|
44914
45265
|
async streamCommand(workspaceId, command2) {
|
|
44915
45266
|
resetStdinForChild2();
|
|
44916
45267
|
return new Promise((resolve10, reject) => {
|
|
44917
|
-
const proc = (0,
|
|
45268
|
+
const proc = (0, import_child_process33.spawn)(
|
|
44918
45269
|
"gitpod",
|
|
44919
45270
|
["workspace", "ssh", workspaceId, "--", "-tt", command2],
|
|
44920
45271
|
{ stdio: "inherit" }
|
|
@@ -44934,11 +45285,11 @@ var GitpodProvider = class {
|
|
|
44934
45285
|
const tarEnv = { ...process.env, COPYFILE_DISABLE: "1" };
|
|
44935
45286
|
const remoteCmd = `mkdir -p ${shellQuote2(remoteDir)} && tar -xzf - -C ${shellQuote2(remoteDir)}`;
|
|
44936
45287
|
await new Promise((resolve10, reject) => {
|
|
44937
|
-
const tar = (0,
|
|
45288
|
+
const tar = (0, import_child_process33.spawn)("tar", tarArgs, {
|
|
44938
45289
|
stdio: ["ignore", "pipe", "pipe"],
|
|
44939
45290
|
env: tarEnv
|
|
44940
45291
|
});
|
|
44941
|
-
const ssh = (0,
|
|
45292
|
+
const ssh = (0, import_child_process33.spawn)(
|
|
44942
45293
|
"gitpod",
|
|
44943
45294
|
["workspace", "ssh", workspaceId, "--", remoteCmd],
|
|
44944
45295
|
{ stdio: [tar.stdout, "pipe", "pipe"] }
|
|
@@ -44970,7 +45321,7 @@ var GitpodProvider = class {
|
|
|
44970
45321
|
}
|
|
44971
45322
|
const cmd = parts.join(" && ");
|
|
44972
45323
|
await new Promise((resolve10, reject) => {
|
|
44973
|
-
const proc = (0,
|
|
45324
|
+
const proc = (0, import_child_process33.spawn)(
|
|
44974
45325
|
"gitpod",
|
|
44975
45326
|
["workspace", "ssh", workspaceId, "--", cmd],
|
|
44976
45327
|
{ stdio: ["pipe", "pipe", "pipe"] }
|
|
@@ -44994,10 +45345,10 @@ function shellQuote2(s) {
|
|
|
44994
45345
|
}
|
|
44995
45346
|
|
|
44996
45347
|
// src/services/providers/gitlab-workspaces.ts
|
|
44997
|
-
var
|
|
45348
|
+
var import_child_process34 = require("child_process");
|
|
44998
45349
|
var import_util6 = require("util");
|
|
44999
45350
|
var path91 = __toESM(require("path"));
|
|
45000
|
-
var execFileP8 = (0, import_util6.promisify)(
|
|
45351
|
+
var execFileP8 = (0, import_util6.promisify)(import_child_process34.execFile);
|
|
45001
45352
|
var MAX_BUFFER3 = 8 * 1024 * 1024;
|
|
45002
45353
|
var GITLAB_API_BASE = process.env.CODEAM_GITLAB_API_URL ?? "https://gitlab.com/api/v4";
|
|
45003
45354
|
function resetStdinForChild3() {
|
|
@@ -45039,7 +45390,7 @@ var GitLabWorkspacesProvider = class {
|
|
|
45039
45390
|
);
|
|
45040
45391
|
resetStdinForChild3();
|
|
45041
45392
|
await new Promise((resolve10, reject) => {
|
|
45042
|
-
const proc = (0,
|
|
45393
|
+
const proc = (0, import_child_process34.spawn)(
|
|
45043
45394
|
"glab",
|
|
45044
45395
|
["auth", "login", "--scopes", "api,read_user,read_repository"],
|
|
45045
45396
|
{ stdio: "inherit" }
|
|
@@ -45211,7 +45562,7 @@ Docs: https://docs.gitlab.com/ee/user/workspace/configuration.html`
|
|
|
45211
45562
|
const sshHost = process.env.CODEAM_GITLAB_SSH_HOST ?? "workspaces.gitlab.com";
|
|
45212
45563
|
resetStdinForChild3();
|
|
45213
45564
|
return new Promise((resolve10, reject) => {
|
|
45214
|
-
const proc = (0,
|
|
45565
|
+
const proc = (0, import_child_process34.spawn)(
|
|
45215
45566
|
"ssh",
|
|
45216
45567
|
["-tt", "-o", "StrictHostKeyChecking=accept-new", `${workspaceId}@${sshHost}`, command2],
|
|
45217
45568
|
{ stdio: "inherit" }
|
|
@@ -45232,8 +45583,8 @@ Docs: https://docs.gitlab.com/ee/user/workspace/configuration.html`
|
|
|
45232
45583
|
const tarEnv = { ...process.env, COPYFILE_DISABLE: "1" };
|
|
45233
45584
|
const remoteCmd = `mkdir -p ${shellQuote3(remoteDir)} && tar -xzf - -C ${shellQuote3(remoteDir)}`;
|
|
45234
45585
|
await new Promise((resolve10, reject) => {
|
|
45235
|
-
const tar = (0,
|
|
45236
|
-
const ssh = (0,
|
|
45586
|
+
const tar = (0, import_child_process34.spawn)("tar", tarArgs, { stdio: ["ignore", "pipe", "pipe"], env: tarEnv });
|
|
45587
|
+
const ssh = (0, import_child_process34.spawn)(
|
|
45237
45588
|
"ssh",
|
|
45238
45589
|
["-o", "StrictHostKeyChecking=accept-new", `${workspaceId}@${sshHost}`, remoteCmd],
|
|
45239
45590
|
{ stdio: [tar.stdout, "pipe", "pipe"] }
|
|
@@ -45263,7 +45614,7 @@ Docs: https://docs.gitlab.com/ee/user/workspace/configuration.html`
|
|
|
45263
45614
|
}
|
|
45264
45615
|
const cmd = parts.join(" && ");
|
|
45265
45616
|
await new Promise((resolve10, reject) => {
|
|
45266
|
-
const proc = (0,
|
|
45617
|
+
const proc = (0, import_child_process34.spawn)(
|
|
45267
45618
|
"ssh",
|
|
45268
45619
|
["-o", "StrictHostKeyChecking=accept-new", `${workspaceId}@${sshHost}`, cmd],
|
|
45269
45620
|
{ stdio: ["pipe", "pipe", "pipe"] }
|
|
@@ -45322,10 +45673,10 @@ function shellQuote3(s) {
|
|
|
45322
45673
|
}
|
|
45323
45674
|
|
|
45324
45675
|
// src/services/providers/railway.ts
|
|
45325
|
-
var
|
|
45676
|
+
var import_child_process35 = require("child_process");
|
|
45326
45677
|
var import_util7 = require("util");
|
|
45327
45678
|
var path92 = __toESM(require("path"));
|
|
45328
|
-
var execFileP9 = (0, import_util7.promisify)(
|
|
45679
|
+
var execFileP9 = (0, import_util7.promisify)(import_child_process35.execFile);
|
|
45329
45680
|
var MAX_BUFFER4 = 8 * 1024 * 1024;
|
|
45330
45681
|
function resetStdinForChild4() {
|
|
45331
45682
|
if (process.stdin.isTTY) {
|
|
@@ -45366,7 +45717,7 @@ var RailwayProvider = class {
|
|
|
45366
45717
|
);
|
|
45367
45718
|
resetStdinForChild4();
|
|
45368
45719
|
await new Promise((resolve10, reject) => {
|
|
45369
|
-
const proc = (0,
|
|
45720
|
+
const proc = (0, import_child_process35.spawn)("railway", ["login"], { stdio: "inherit" });
|
|
45370
45721
|
proc.on("exit", (code) => {
|
|
45371
45722
|
if (code === 0) resolve10();
|
|
45372
45723
|
else reject(new Error("railway login failed."));
|
|
@@ -45509,7 +45860,7 @@ var RailwayProvider = class {
|
|
|
45509
45860
|
}
|
|
45510
45861
|
resetStdinForChild4();
|
|
45511
45862
|
return new Promise((resolve10, reject) => {
|
|
45512
|
-
const proc = (0,
|
|
45863
|
+
const proc = (0, import_child_process35.spawn)(
|
|
45513
45864
|
"railway",
|
|
45514
45865
|
["shell", "--project", projectId, "--service", serviceId, "--command", command2],
|
|
45515
45866
|
{ stdio: "inherit" }
|
|
@@ -45533,8 +45884,8 @@ var RailwayProvider = class {
|
|
|
45533
45884
|
const tarEnv = { ...process.env, COPYFILE_DISABLE: "1" };
|
|
45534
45885
|
const remoteCmd = `mkdir -p ${shellQuote4(remoteDir)} && tar -xzf - -C ${shellQuote4(remoteDir)}`;
|
|
45535
45886
|
await new Promise((resolve10, reject) => {
|
|
45536
|
-
const tar = (0,
|
|
45537
|
-
const sh = (0,
|
|
45887
|
+
const tar = (0, import_child_process35.spawn)("tar", tarArgs, { stdio: ["ignore", "pipe", "pipe"], env: tarEnv });
|
|
45888
|
+
const sh = (0, import_child_process35.spawn)(
|
|
45538
45889
|
"railway",
|
|
45539
45890
|
["shell", "--project", projectId, "--service", serviceId, "--command", remoteCmd],
|
|
45540
45891
|
{ stdio: [tar.stdout, "pipe", "pipe"] }
|
|
@@ -45567,7 +45918,7 @@ var RailwayProvider = class {
|
|
|
45567
45918
|
}
|
|
45568
45919
|
const cmd = parts.join(" && ");
|
|
45569
45920
|
await new Promise((resolve10, reject) => {
|
|
45570
|
-
const proc = (0,
|
|
45921
|
+
const proc = (0, import_child_process35.spawn)(
|
|
45571
45922
|
"railway",
|
|
45572
45923
|
["shell", "--project", projectId, "--service", serviceId, "--command", cmd],
|
|
45573
45924
|
{ stdio: ["pipe", "pipe", "pipe"] }
|
|
@@ -46375,7 +46726,7 @@ function checkChokidar() {
|
|
|
46375
46726
|
}
|
|
46376
46727
|
async function doctor(args2 = []) {
|
|
46377
46728
|
const json = args2.includes("--json");
|
|
46378
|
-
const cliVersion = true ? "2.
|
|
46729
|
+
const cliVersion = true ? "2.71.0" : "0.0.0-dev";
|
|
46379
46730
|
const apiBase2 = resolveApiBaseUrl();
|
|
46380
46731
|
const diagnosticId = (0, import_node_crypto13.randomUUID)();
|
|
46381
46732
|
log.info("doctor", `run id=${diagnosticId} cli=${cliVersion}`);
|
|
@@ -46766,7 +47117,7 @@ async function mcpRun(args2) {
|
|
|
46766
47117
|
// src/commands/version.ts
|
|
46767
47118
|
var import_picocolors15 = __toESM(require("picocolors"));
|
|
46768
47119
|
function version2() {
|
|
46769
|
-
const v = true ? "2.
|
|
47120
|
+
const v = true ? "2.71.0" : "unknown";
|
|
46770
47121
|
console.log(`${import_picocolors15.default.bold("codeam-cli")} ${import_picocolors15.default.cyan(v)}`);
|
|
46771
47122
|
}
|
|
46772
47123
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "codeam-cli",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.71.0",
|
|
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",
|