codeam-cli 2.68.0 → 2.70.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 +492 -115
- 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.69.0] — 2026-08-29
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
- **cli:** El inspector habla tambien dentro del WebView de la app movil (#666)
|
|
12
|
+
|
|
13
|
+
## [2.68.0] — 2026-08-29
|
|
14
|
+
|
|
15
|
+
### Added
|
|
16
|
+
|
|
17
|
+
- **cli:** Inspector de preview — proxy inyector, script y E2E en navegador (#665)
|
|
18
|
+
|
|
7
19
|
## [2.67.6] — 2026-08-27
|
|
8
20
|
|
|
9
21
|
### Fixed
|
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.70.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.70.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.70.0" ? { ideVersion: "2.70.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.70.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.70.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.70.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,65 @@ 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
|
+
function envVarFor(service) {
|
|
25110
|
+
const first = service.envLines[0] ?? "";
|
|
25111
|
+
return first.split("=")[0] || "DATABASE_URL";
|
|
25112
|
+
}
|
|
24997
25113
|
async function provisionProjectDependencies(cwd) {
|
|
25114
|
+
let needed = [];
|
|
25115
|
+
const outcome = (reason) => ({
|
|
25116
|
+
reason,
|
|
25117
|
+
missing: reason === "ok" ? [] : needed.map((sv) => ({ service: sv.name, envVar: envVarFor(sv) }))
|
|
25118
|
+
});
|
|
24998
25119
|
try {
|
|
24999
|
-
|
|
25120
|
+
let docker = await runSetupCommand("docker", ["info"], cwd, void 0, {
|
|
25121
|
+
timeoutMs: 15e3
|
|
25122
|
+
});
|
|
25123
|
+
if (docker.status !== "ok") {
|
|
25124
|
+
log.info("provision", "docker not responding \u2014 trying to start the daemon");
|
|
25125
|
+
for (const argv of [
|
|
25126
|
+
["-n", "systemctl", "start", "docker"],
|
|
25127
|
+
["-n", "service", "docker", "start"]
|
|
25128
|
+
]) {
|
|
25129
|
+
const started2 = await runSetupCommand("sudo", argv, cwd, void 0, {
|
|
25130
|
+
timeoutMs: 45e3
|
|
25131
|
+
});
|
|
25132
|
+
if (started2.status !== "ok") continue;
|
|
25133
|
+
docker = await runSetupCommand("docker", ["info"], cwd, void 0, {
|
|
25134
|
+
timeoutMs: 2e4
|
|
25135
|
+
});
|
|
25136
|
+
if (docker.status === "ok") {
|
|
25137
|
+
log.info("provision", `docker daemon started via ${argv[1]}`);
|
|
25138
|
+
break;
|
|
25139
|
+
}
|
|
25140
|
+
}
|
|
25141
|
+
}
|
|
25000
25142
|
if (docker.status !== "ok") {
|
|
25001
25143
|
log.info("provision", "docker not usable \u2014 skipping dependency provisioning");
|
|
25002
|
-
|
|
25144
|
+
const pkgForNeeds = await readPackageJson(cwd);
|
|
25145
|
+
needed = pkgForNeeds ? detectServicesFromDeps(pkgForNeeds) : [];
|
|
25146
|
+
const prismaNeed = serviceForPrismaProvider(await readPrismaProvider(cwd));
|
|
25147
|
+
if (prismaNeed && !needed.some((n) => n.name === prismaNeed.name)) {
|
|
25148
|
+
needed.push(prismaNeed);
|
|
25149
|
+
}
|
|
25150
|
+
const pgIndex = needed.findIndex((n) => n.name === "postgres");
|
|
25151
|
+
if (pgIndex !== -1) {
|
|
25152
|
+
const embedded = await startEmbeddedPostgres({
|
|
25153
|
+
port: 5432,
|
|
25154
|
+
log: (m) => log.info("provision", m)
|
|
25155
|
+
});
|
|
25156
|
+
if (embedded) {
|
|
25157
|
+
registerEmbeddedPostgres(embedded);
|
|
25158
|
+
await ensureEnvFile(cwd, [needed[pgIndex]]);
|
|
25159
|
+
needed.splice(pgIndex, 1);
|
|
25160
|
+
}
|
|
25161
|
+
}
|
|
25162
|
+
return outcome(needed.length === 0 ? "ok" : "no-docker");
|
|
25003
25163
|
}
|
|
25004
25164
|
const pkg = await readPackageJson(cwd);
|
|
25005
25165
|
let started = false;
|
|
@@ -25012,6 +25172,11 @@ async function provisionProjectDependencies(cwd) {
|
|
|
25012
25172
|
if (!started) log.warn("provision", `compose up \u2192 ${up.status} (non-fatal)`);
|
|
25013
25173
|
} else if (pkg) {
|
|
25014
25174
|
generated = detectServicesFromDeps(pkg);
|
|
25175
|
+
const prismaSvc = serviceForPrismaProvider(await readPrismaProvider(cwd));
|
|
25176
|
+
if (prismaSvc && !generated.some((g) => g.name === prismaSvc.name)) {
|
|
25177
|
+
generated.push(prismaSvc);
|
|
25178
|
+
}
|
|
25179
|
+
needed = generated;
|
|
25015
25180
|
if (generated.length > 0) {
|
|
25016
25181
|
const dir = import_path7.default.join(cwd, ".codeam", "provision");
|
|
25017
25182
|
await import_fs4.promises.mkdir(dir, { recursive: true });
|
|
@@ -25031,8 +25196,10 @@ async function provisionProjectDependencies(cwd) {
|
|
|
25031
25196
|
await ensureEnvFile(cwd, generated);
|
|
25032
25197
|
if (started && pkg?.scripts) await runMigrationsIfPresent(cwd, pkg.scripts);
|
|
25033
25198
|
log.info("provision", "project dependency provisioning complete");
|
|
25199
|
+
return outcome(needed.length > 0 && !started ? "compose-failed" : "ok");
|
|
25034
25200
|
} catch (err) {
|
|
25035
25201
|
log.warn("provision", "provisionProjectDependencies failed (non-fatal)", err);
|
|
25202
|
+
return outcome("unknown");
|
|
25036
25203
|
}
|
|
25037
25204
|
}
|
|
25038
25205
|
|
|
@@ -25100,6 +25267,51 @@ async function awaitTunnelRegistered(candidate, hostname3, deadlineMs) {
|
|
|
25100
25267
|
}
|
|
25101
25268
|
}
|
|
25102
25269
|
|
|
25270
|
+
// src/services/preview/adopt-port.ts
|
|
25271
|
+
var http6 = __toESM(require("http"));
|
|
25272
|
+
var DIRECTORY_LISTING_RE = /<title>\s*(?:Directory listing for|Index of)/i;
|
|
25273
|
+
var PROBE_TIMEOUT_MS = 2e3;
|
|
25274
|
+
var PROBE_BODY_LIMIT = 4 * 1024;
|
|
25275
|
+
function verdictFor(res) {
|
|
25276
|
+
if (!res) return { adopt: false, reason: "unreachable" };
|
|
25277
|
+
if (!res.contentType || !res.contentType.toLowerCase().includes("text/html")) {
|
|
25278
|
+
return { adopt: false, reason: "not-html" };
|
|
25279
|
+
}
|
|
25280
|
+
if (DIRECTORY_LISTING_RE.test(res.bodyStart)) {
|
|
25281
|
+
return { adopt: false, reason: "directory-listing" };
|
|
25282
|
+
}
|
|
25283
|
+
return { adopt: true };
|
|
25284
|
+
}
|
|
25285
|
+
var probePort = (port) => new Promise((resolve10) => {
|
|
25286
|
+
const req = http6.get(
|
|
25287
|
+
{ host: "127.0.0.1", port, path: "/", timeout: PROBE_TIMEOUT_MS },
|
|
25288
|
+
(res) => {
|
|
25289
|
+
let body = "";
|
|
25290
|
+
res.setEncoding("utf8");
|
|
25291
|
+
res.on("data", (c2) => {
|
|
25292
|
+
if (body.length < PROBE_BODY_LIMIT) body += c2;
|
|
25293
|
+
});
|
|
25294
|
+
res.on(
|
|
25295
|
+
"end",
|
|
25296
|
+
() => resolve10({ contentType: res.headers["content-type"], bodyStart: body })
|
|
25297
|
+
);
|
|
25298
|
+
res.on("error", () => resolve10(null));
|
|
25299
|
+
}
|
|
25300
|
+
);
|
|
25301
|
+
req.on("timeout", () => {
|
|
25302
|
+
req.destroy();
|
|
25303
|
+
resolve10(null);
|
|
25304
|
+
});
|
|
25305
|
+
req.on("error", () => resolve10(null));
|
|
25306
|
+
});
|
|
25307
|
+
async function canAdoptPort(port, probe = probePort) {
|
|
25308
|
+
try {
|
|
25309
|
+
return verdictFor(await probe(port));
|
|
25310
|
+
} catch {
|
|
25311
|
+
return { adopt: false, reason: "unreachable" };
|
|
25312
|
+
}
|
|
25313
|
+
}
|
|
25314
|
+
|
|
25103
25315
|
// src/services/preview/index.ts
|
|
25104
25316
|
var activePreviews = /* @__PURE__ */ new Map();
|
|
25105
25317
|
function registerPreview(sessionId, preview) {
|
|
@@ -25133,9 +25345,9 @@ async function killPreview(sessionId) {
|
|
|
25133
25345
|
await preview.inspector?.close();
|
|
25134
25346
|
} catch {
|
|
25135
25347
|
}
|
|
25136
|
-
killProcessTree(preview.devServer, "SIGTERM");
|
|
25348
|
+
if (preview.devServer) killProcessTree(preview.devServer, "SIGTERM");
|
|
25137
25349
|
const sigkillTimer = setTimeout(() => {
|
|
25138
|
-
killProcessTree(preview.devServer, "SIGKILL");
|
|
25350
|
+
if (preview.devServer) killProcessTree(preview.devServer, "SIGKILL");
|
|
25139
25351
|
if (preview.tunnel) killProcessTree(preview.tunnel, "SIGKILL");
|
|
25140
25352
|
}, 250);
|
|
25141
25353
|
sigkillTimer.unref?.();
|
|
@@ -25151,7 +25363,7 @@ function activePreviewSessionIds() {
|
|
|
25151
25363
|
}
|
|
25152
25364
|
|
|
25153
25365
|
// src/services/preview/start-orchestrator.ts
|
|
25154
|
-
var
|
|
25366
|
+
var import_child_process23 = require("child_process");
|
|
25155
25367
|
var fs59 = __toESM(require("fs"));
|
|
25156
25368
|
var path64 = __toESM(require("path"));
|
|
25157
25369
|
var import_which2 = __toESM(require("which"));
|
|
@@ -25161,7 +25373,7 @@ var import_fs6 = require("fs");
|
|
|
25161
25373
|
var path63 = __toESM(require("path"));
|
|
25162
25374
|
|
|
25163
25375
|
// src/beads/project-key.ts
|
|
25164
|
-
var
|
|
25376
|
+
var import_child_process22 = require("child_process");
|
|
25165
25377
|
var crypto2 = __toESM(require("crypto"));
|
|
25166
25378
|
var fs57 = __toESM(require("fs"));
|
|
25167
25379
|
var path62 = __toESM(require("path"));
|
|
@@ -25208,7 +25420,7 @@ function findRepoRoot(cwd) {
|
|
|
25208
25420
|
}
|
|
25209
25421
|
var _execSeam3 = {
|
|
25210
25422
|
exec: (file, args2, opts) => {
|
|
25211
|
-
const out2 = (0,
|
|
25423
|
+
const out2 = (0, import_child_process22.execFileSync)(file, args2, opts);
|
|
25212
25424
|
return typeof out2 === "string" ? out2 : out2.toString("utf8");
|
|
25213
25425
|
},
|
|
25214
25426
|
realpath: (p2) => fs57.realpathSync(p2)
|
|
@@ -25318,12 +25530,16 @@ async function resolveNamedTunnel(ctx, fetchTunnel) {
|
|
|
25318
25530
|
}
|
|
25319
25531
|
|
|
25320
25532
|
// src/services/preview/inspector-proxy.ts
|
|
25321
|
-
var
|
|
25322
|
-
var
|
|
25533
|
+
var http7 = __toESM(require("http"));
|
|
25534
|
+
var net4 = __toESM(require("net"));
|
|
25323
25535
|
var INJECTION_SCAN_BUDGET_BYTES = 64 * 1024;
|
|
25324
25536
|
var INJECTION_ANCHORS = ["</head>", "<body>", "</body>"];
|
|
25325
|
-
function
|
|
25326
|
-
|
|
25537
|
+
function isNavigation(headers) {
|
|
25538
|
+
if (headers.secFetchDest !== void 0) {
|
|
25539
|
+
return headers.secFetchDest === "document" || headers.secFetchDest === "iframe";
|
|
25540
|
+
}
|
|
25541
|
+
if (headers.secFetchMode !== void 0) return headers.secFetchMode === "navigate";
|
|
25542
|
+
return typeof headers.accept === "string" && headers.accept.includes("text/html");
|
|
25327
25543
|
}
|
|
25328
25544
|
function isHtmlResponse(contentType) {
|
|
25329
25545
|
return typeof contentType === "string" && contentType.toLowerCase().includes("text/html");
|
|
@@ -25340,11 +25556,16 @@ function injectAt(html, script) {
|
|
|
25340
25556
|
async function startInspectorProxy(opts) {
|
|
25341
25557
|
const targetHost = opts.targetHost ?? "127.0.0.1";
|
|
25342
25558
|
const upgraded = /* @__PURE__ */ new Set();
|
|
25343
|
-
const server =
|
|
25344
|
-
const
|
|
25559
|
+
const server = http7.createServer((req, res) => {
|
|
25560
|
+
const one = (v) => Array.isArray(v) ? v[0] : v;
|
|
25561
|
+
const inject = isNavigation({
|
|
25562
|
+
accept: one(req.headers.accept),
|
|
25563
|
+
secFetchDest: one(req.headers["sec-fetch-dest"]),
|
|
25564
|
+
secFetchMode: one(req.headers["sec-fetch-mode"])
|
|
25565
|
+
});
|
|
25345
25566
|
const headers = { ...req.headers };
|
|
25346
25567
|
if (inject) delete headers["accept-encoding"];
|
|
25347
|
-
const upstream =
|
|
25568
|
+
const upstream = http7.request(
|
|
25348
25569
|
{ host: targetHost, port: opts.targetPort, method: req.method, path: req.url, headers },
|
|
25349
25570
|
(originRes) => {
|
|
25350
25571
|
const outHeaders = { ...originRes.headers };
|
|
@@ -25391,7 +25612,7 @@ async function startInspectorProxy(opts) {
|
|
|
25391
25612
|
});
|
|
25392
25613
|
server.on("upgrade", (req, clientSocket, head) => {
|
|
25393
25614
|
upgraded.add(clientSocket);
|
|
25394
|
-
const upstream =
|
|
25615
|
+
const upstream = net4.connect(opts.targetPort, targetHost, () => {
|
|
25395
25616
|
const lines = [`${req.method} ${req.url} HTTP/1.1`];
|
|
25396
25617
|
for (const [k2, v] of Object.entries(req.headers)) {
|
|
25397
25618
|
for (const one of Array.isArray(v) ? v : [v]) {
|
|
@@ -25453,10 +25674,33 @@ function inspectorClientSource(opts) {
|
|
|
25453
25674
|
return ALLOWED.indexOf(origin) !== -1;
|
|
25454
25675
|
}
|
|
25455
25676
|
|
|
25677
|
+
// \xBFEstamos dentro del WebView de la app movil?
|
|
25678
|
+
//
|
|
25679
|
+
// \u26A0\uFE0F En un WebView el documento es de NIVEL SUPERIOR, asi que
|
|
25680
|
+
// \`window.parent === window\` y la via del iframe no existe: el script
|
|
25681
|
+
// hablaba solo, y en movil el inspector no devolvia nada. React Native
|
|
25682
|
+
// expone su propio canal, que es el unico que sale de ahi.
|
|
25683
|
+
function rnBridge() {
|
|
25684
|
+
return typeof window.ReactNativeWebView !== 'undefined' &&
|
|
25685
|
+
window.ReactNativeWebView &&
|
|
25686
|
+
typeof window.ReactNativeWebView.postMessage === 'function'
|
|
25687
|
+
? window.ReactNativeWebView
|
|
25688
|
+
: null;
|
|
25689
|
+
}
|
|
25690
|
+
|
|
25456
25691
|
function send(type, payload) {
|
|
25457
|
-
if (!driver
|
|
25692
|
+
if (!driver) return;
|
|
25458
25693
|
var msg = { source: CHANNEL, type: type };
|
|
25459
25694
|
for (var k in payload) if (Object.prototype.hasOwnProperty.call(payload, k)) msg[k] = payload[k];
|
|
25695
|
+
|
|
25696
|
+
var rn = rnBridge();
|
|
25697
|
+
if (rn) {
|
|
25698
|
+
// El canal de RN transporta CADENAS, no objetos: pasarle el objeto
|
|
25699
|
+
// llega al otro lado como "[object Object]".
|
|
25700
|
+
rn.postMessage(JSON.stringify(msg));
|
|
25701
|
+
return;
|
|
25702
|
+
}
|
|
25703
|
+
if (window.parent === window) return;
|
|
25460
25704
|
window.parent.postMessage(msg, driver);
|
|
25461
25705
|
}
|
|
25462
25706
|
|
|
@@ -25565,6 +25809,77 @@ function inspectorClientSource(opts) {
|
|
|
25565
25809
|
send('hover', { element: describe(el) });
|
|
25566
25810
|
}
|
|
25567
25811
|
|
|
25812
|
+
// Captura, y se traga el evento: mientras el modo esta activo un clic
|
|
25813
|
+
// SELECCIONA, no navega. Sin esto, pulsar un enlace se llevaria el
|
|
25814
|
+
// preview a otra pagina en mitad del gesto.
|
|
25815
|
+
/**
|
|
25816
|
+
* Las marcas FIJADAS, dibujadas DENTRO de la pagina.
|
|
25817
|
+
*
|
|
25818
|
+
* \u26A0\uFE0F Antes las pintaba el dashboard, en una capa sobre el iframe. Como esa
|
|
25819
|
+
* capa vive fuera del documento, sus coordenadas son del VIEWPORT: al
|
|
25820
|
+
* hacer scroll dentro del preview las marcas se quedaban clavadas en la
|
|
25821
|
+
* pantalla mientras el elemento se iba (reportado el 2026-08-29).
|
|
25822
|
+
*
|
|
25823
|
+
* Aqui se anclan al DOCUMENTO (position:absolute mas el scroll sumado), asi
|
|
25824
|
+
* que acompa\xF1an al contenido igual que cualquier otro nodo de la pagina \u2014 y
|
|
25825
|
+
* ademas se recolocan si el layout cambia, que una capa externa no puede
|
|
25826
|
+
* saber.
|
|
25827
|
+
*/
|
|
25828
|
+
var picked = [];
|
|
25829
|
+
var seq = 0;
|
|
25830
|
+
var marksHost = null;
|
|
25831
|
+
|
|
25832
|
+
function ensureMarksHost() {
|
|
25833
|
+
if (marksHost && marksHost.parentNode) return marksHost;
|
|
25834
|
+
marksHost = document.createElement('div');
|
|
25835
|
+
marksHost.setAttribute('data-codeam', 'marks');
|
|
25836
|
+
marksHost.style.cssText = 'position:absolute;left:0;top:0;width:0;height:0;z-index:2147483646';
|
|
25837
|
+
document.body.appendChild(marksHost);
|
|
25838
|
+
return marksHost;
|
|
25839
|
+
}
|
|
25840
|
+
|
|
25841
|
+
function redrawMarks() {
|
|
25842
|
+
if (picked.length === 0) {
|
|
25843
|
+
if (marksHost && marksHost.parentNode) marksHost.parentNode.removeChild(marksHost);
|
|
25844
|
+
marksHost = null;
|
|
25845
|
+
return;
|
|
25846
|
+
}
|
|
25847
|
+
var host = ensureMarksHost();
|
|
25848
|
+
host.innerHTML = '';
|
|
25849
|
+
for (var i = 0; i < picked.length; i++) {
|
|
25850
|
+
var r = picked[i].el.getBoundingClientRect();
|
|
25851
|
+
// Coordenadas de DOCUMENTO: es lo que hace que la marca viaje con el
|
|
25852
|
+
// contenido en vez de quedarse pegada a la pantalla.
|
|
25853
|
+
var top = r.top + (window.scrollY || window.pageYOffset || 0);
|
|
25854
|
+
var left = r.left + (window.scrollX || window.pageXOffset || 0);
|
|
25855
|
+
|
|
25856
|
+
var box = document.createElement('div');
|
|
25857
|
+
box.setAttribute('data-codeam', 'mark');
|
|
25858
|
+
box.style.cssText = [
|
|
25859
|
+
'position:absolute', 'pointer-events:none', 'box-sizing:border-box',
|
|
25860
|
+
'border:1.5px solid #a855f7', 'background:rgba(168,85,247,0.12)',
|
|
25861
|
+
'border-radius:3px',
|
|
25862
|
+
'left:' + left + 'px', 'top:' + top + 'px',
|
|
25863
|
+
'width:' + r.width + 'px', 'height:' + r.height + 'px'
|
|
25864
|
+
].join(';');
|
|
25865
|
+
|
|
25866
|
+
var badge = document.createElement('div');
|
|
25867
|
+
badge.setAttribute('data-codeam', 'mark-badge');
|
|
25868
|
+
badge.style.cssText = [
|
|
25869
|
+
'position:absolute', 'left:-10px', 'top:-10px', 'width:20px', 'height:20px',
|
|
25870
|
+
'border-radius:10px', 'background:#a855f7', 'color:#000',
|
|
25871
|
+
'font:700 11px/20px ui-monospace,SFMono-Regular,Menlo,monospace',
|
|
25872
|
+
'text-align:center', 'pointer-events:none'
|
|
25873
|
+
].join(';');
|
|
25874
|
+
badge.textContent = String(i + 1);
|
|
25875
|
+
|
|
25876
|
+
box.appendChild(badge);
|
|
25877
|
+
host.appendChild(box);
|
|
25878
|
+
}
|
|
25879
|
+
}
|
|
25880
|
+
|
|
25881
|
+
function reposition() { if (picked.length) redrawMarks(); }
|
|
25882
|
+
|
|
25568
25883
|
// Captura, y se traga el evento: mientras el modo esta activo un clic
|
|
25569
25884
|
// SELECCIONA, no navega. Sin esto, pulsar un enlace se llevaria el
|
|
25570
25885
|
// preview a otra pagina en mitad del gesto.
|
|
@@ -25574,7 +25889,30 @@ function inspectorClientSource(opts) {
|
|
|
25574
25889
|
if (el && el.getAttribute && el.getAttribute('data-codeam')) return;
|
|
25575
25890
|
e.preventDefault();
|
|
25576
25891
|
e.stopPropagation();
|
|
25577
|
-
if (el)
|
|
25892
|
+
if (!el) return;
|
|
25893
|
+
var id = 'p' + (++seq);
|
|
25894
|
+
picked.push({ id: id, el: el });
|
|
25895
|
+
redrawMarks();
|
|
25896
|
+
var described = describe(el);
|
|
25897
|
+
described.markId = id;
|
|
25898
|
+
send('pick', { element: described });
|
|
25899
|
+
}
|
|
25900
|
+
|
|
25901
|
+
/**
|
|
25902
|
+
* El dashboard manda la lista de ids que SIGUEN vivos, en su orden.
|
|
25903
|
+
*
|
|
25904
|
+
* Es la otra mitad de \xABla marca es un objeto\xBB: si el usuario borra un chip
|
|
25905
|
+
* en el composer, la marca tiene que desaparecer de la pagina \u2014 y las que
|
|
25906
|
+
* quedan renumerarse, porque lo que el usuario escribe (\xAB\u2460 se sale\xBB) mira
|
|
25907
|
+
* a estos numeros.
|
|
25908
|
+
*/
|
|
25909
|
+
function syncMarks(ids) {
|
|
25910
|
+
var byId = {};
|
|
25911
|
+
for (var i = 0; i < picked.length; i++) byId[picked[i].id] = picked[i];
|
|
25912
|
+
var next = [];
|
|
25913
|
+
for (var j = 0; j < ids.length; j++) if (byId[ids[j]]) next.push(byId[ids[j]]);
|
|
25914
|
+
picked = next;
|
|
25915
|
+
redrawMarks();
|
|
25578
25916
|
}
|
|
25579
25917
|
|
|
25580
25918
|
function enable(origin) {
|
|
@@ -25583,6 +25921,9 @@ function inspectorClientSource(opts) {
|
|
|
25583
25921
|
driver = origin;
|
|
25584
25922
|
document.addEventListener('mousemove', onMove, true);
|
|
25585
25923
|
document.addEventListener('click', onClick, true);
|
|
25924
|
+
// El scroll y el resize mueven los elementos; las marcas los siguen.
|
|
25925
|
+
window.addEventListener('scroll', reposition, true);
|
|
25926
|
+
window.addEventListener('resize', reposition);
|
|
25586
25927
|
send('ready', {});
|
|
25587
25928
|
}
|
|
25588
25929
|
|
|
@@ -25592,7 +25933,11 @@ function inspectorClientSource(opts) {
|
|
|
25592
25933
|
current = null;
|
|
25593
25934
|
document.removeEventListener('mousemove', onMove, true);
|
|
25594
25935
|
document.removeEventListener('click', onClick, true);
|
|
25936
|
+
window.removeEventListener('scroll', reposition, true);
|
|
25937
|
+
window.removeEventListener('resize', reposition);
|
|
25595
25938
|
removeOverlay();
|
|
25939
|
+
// Las marcas fijadas SI sobreviven a salir del modo: siguen siendo el
|
|
25940
|
+
// contexto del mensaje que el usuario esta escribiendo.
|
|
25596
25941
|
driver = null;
|
|
25597
25942
|
}
|
|
25598
25943
|
|
|
@@ -25602,7 +25947,27 @@ function inspectorClientSource(opts) {
|
|
|
25602
25947
|
if (!data || data.source !== CHANNEL) return;
|
|
25603
25948
|
if (data.type === 'enable') enable(e.origin);
|
|
25604
25949
|
else if (data.type === 'disable') disable();
|
|
25605
|
-
|
|
25950
|
+
else if (data.type === 'marks' && data.ids) syncMarks(data.ids);
|
|
25951
|
+
});
|
|
25952
|
+
|
|
25953
|
+
/**
|
|
25954
|
+
* La puerta para React Native, que no puede usar \`postMessage\`.
|
|
25955
|
+
*
|
|
25956
|
+
* \u26A0\uFE0F Aqui NO hay lista blanca de origenes, y no es un descuido: quien
|
|
25957
|
+
* llama esto es la app anfitriona sobre SU PROPIO WebView, via
|
|
25958
|
+
* \`injectJavaScript\` \u2014 no hay un tercero al que filtrar. La lista blanca
|
|
25959
|
+
* protege el caso del iframe, donde cualquier pagina puede embeber el
|
|
25960
|
+
* preview y mandar mensajes; ese caso sigue exactamente igual de cerrado.
|
|
25961
|
+
*
|
|
25962
|
+
* Solo se expone donde ese puente existe, para no dejar en una pagina
|
|
25963
|
+
* normal una funcion global que encienda el inspector sin permiso.
|
|
25964
|
+
*/
|
|
25965
|
+
if (rnBridge()) {
|
|
25966
|
+
window.__codeamInspector = {
|
|
25967
|
+
enable: function () { enable('react-native'); },
|
|
25968
|
+
disable: disable,
|
|
25969
|
+
};
|
|
25970
|
+
}
|
|
25606
25971
|
} catch (e) {
|
|
25607
25972
|
// Pase lo que pase, la app del usuario sigue funcionando.
|
|
25608
25973
|
}
|
|
@@ -25730,7 +26095,7 @@ async function runPreviewStart(args2) {
|
|
|
25730
26095
|
}
|
|
25731
26096
|
};
|
|
25732
26097
|
const existing = activePreviews.get(sessionId);
|
|
25733
|
-
if (existing && existing.devServer.exitCode
|
|
26098
|
+
if (existing && existing.devServer?.exitCode !== 0 && existing.devServer?.exitCode == null) {
|
|
25734
26099
|
log.info(
|
|
25735
26100
|
"preview",
|
|
25736
26101
|
`reusing running preview for session=${sessionId} url=${existing.url}`
|
|
@@ -25764,7 +26129,9 @@ async function runPreviewStart(args2) {
|
|
|
25764
26129
|
detection,
|
|
25765
26130
|
cwd: ctx.cwd
|
|
25766
26131
|
});
|
|
25767
|
-
|
|
26132
|
+
if (dev.devServer) {
|
|
26133
|
+
recordPreviewPort(detection.port, dev.devServer.pid, sessionId, Date.now());
|
|
26134
|
+
}
|
|
25768
26135
|
log.info("preview", `ready: ${detection.framework} at ${tun.url}`);
|
|
25769
26136
|
emit2(USER_EVENTS.PREVIEW_READY, {
|
|
25770
26137
|
url: tun.url,
|
|
@@ -25877,7 +26244,7 @@ async function startDevServer(ctx) {
|
|
|
25877
26244
|
const { sessionId, detection, cwd, emit: emit2, emitProgress } = ctx;
|
|
25878
26245
|
if (await isPortListening(detection.port)) {
|
|
25879
26246
|
const raceExisting = activePreviews.get(sessionId);
|
|
25880
|
-
if (raceExisting && raceExisting.devServer
|
|
26247
|
+
if (raceExisting && raceExisting.devServer?.exitCode == null) {
|
|
25881
26248
|
log.info(
|
|
25882
26249
|
"preview",
|
|
25883
26250
|
`port race: reusing running preview for session=${sessionId} url=${raceExisting.url}`
|
|
@@ -25893,7 +26260,7 @@ async function startDevServer(ctx) {
|
|
|
25893
26260
|
if (raceExisting) {
|
|
25894
26261
|
log.info(
|
|
25895
26262
|
"preview",
|
|
25896
|
-
`reclaiming stale preview holding port ${detection.port} for session=${sessionId} (exit=${raceExisting.devServer
|
|
26263
|
+
`reclaiming stale preview holding port ${detection.port} for session=${sessionId} (exit=${raceExisting.devServer?.exitCode})`
|
|
25897
26264
|
);
|
|
25898
26265
|
await killPreview(sessionId);
|
|
25899
26266
|
const freeDeadline = Date.now() + 4e3;
|
|
@@ -25921,9 +26288,18 @@ async function startDevServer(ctx) {
|
|
|
25921
26288
|
return null;
|
|
25922
26289
|
}
|
|
25923
26290
|
} else {
|
|
26291
|
+
const verdict = await canAdoptPort(detection.port);
|
|
26292
|
+
if (verdict.adopt) {
|
|
26293
|
+
log.info(
|
|
26294
|
+
"preview",
|
|
26295
|
+
`adopting the dev server already serving on port ${detection.port}`
|
|
26296
|
+
);
|
|
26297
|
+
emitProgress("READY_DETECTED", `adopted the server already on port ${detection.port}`);
|
|
26298
|
+
return { devServer: null, expoUrlRef: { current: null } };
|
|
26299
|
+
}
|
|
25924
26300
|
emit2(USER_EVENTS.PREVIEW_ERROR, {
|
|
25925
26301
|
stage: "spawn",
|
|
25926
|
-
message: `Port ${detection.port} is already in use by
|
|
26302
|
+
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.`
|
|
25927
26303
|
});
|
|
25928
26304
|
return null;
|
|
25929
26305
|
}
|
|
@@ -25931,7 +26307,7 @@ async function startDevServer(ctx) {
|
|
|
25931
26307
|
await applyPreviewHostAllow(cwd);
|
|
25932
26308
|
const spawnable = normalizeDetectionForSpawn(detection, cwd);
|
|
25933
26309
|
emitProgress("BOOT_SEQUENCE", `${spawnable.command} ${spawnable.args.join(" ")}`);
|
|
25934
|
-
const devServer = (0,
|
|
26310
|
+
const devServer = (0, import_child_process23.spawn)(spawnable.command, spawnable.args, {
|
|
25935
26311
|
cwd,
|
|
25936
26312
|
env: { ...process.env, ...spawnable.env ?? {} },
|
|
25937
26313
|
stdio: ["ignore", "pipe", "pipe"],
|
|
@@ -25997,7 +26373,7 @@ async function establishTunnel(ctx, dev) {
|
|
|
25997
26373
|
}
|
|
25998
26374
|
const expoUrl = dev.expoUrlRef.current;
|
|
25999
26375
|
if (!expoUrl) {
|
|
26000
|
-
killProcessTree(devServer, "SIGTERM");
|
|
26376
|
+
if (devServer) killProcessTree(devServer, "SIGTERM");
|
|
26001
26377
|
emit2(USER_EVENTS.PREVIEW_ERROR, {
|
|
26002
26378
|
stage: "tunnel",
|
|
26003
26379
|
message: "Expo did not report a tunnel URL."
|
|
@@ -26014,7 +26390,7 @@ async function establishTunnel(ctx, dev) {
|
|
|
26014
26390
|
try {
|
|
26015
26391
|
bin = await resolveCloudflared();
|
|
26016
26392
|
} catch (e) {
|
|
26017
|
-
killProcessTree(devServer, "SIGTERM");
|
|
26393
|
+
if (devServer) killProcessTree(devServer, "SIGTERM");
|
|
26018
26394
|
emit2(USER_EVENTS.PREVIEW_ERROR, {
|
|
26019
26395
|
stage: "tunnel",
|
|
26020
26396
|
message: e.message
|
|
@@ -26068,7 +26444,7 @@ async function establishTunnel(ctx, dev) {
|
|
|
26068
26444
|
`cloudflared quick tunnel (retry ${attempt}/${MAX_TUNNEL_ATTEMPTS})`
|
|
26069
26445
|
);
|
|
26070
26446
|
}
|
|
26071
|
-
const candidate = (0,
|
|
26447
|
+
const candidate = (0, import_child_process23.spawn)(
|
|
26072
26448
|
bin,
|
|
26073
26449
|
["tunnel", "--url", `http://localhost:${tunnelPort}`],
|
|
26074
26450
|
{ stdio: ["ignore", "pipe", "pipe"] }
|
|
@@ -26088,7 +26464,7 @@ async function establishTunnel(ctx, dev) {
|
|
|
26088
26464
|
}
|
|
26089
26465
|
}
|
|
26090
26466
|
if (!parsedUrl) {
|
|
26091
|
-
killProcessTree(devServer, "SIGTERM");
|
|
26467
|
+
if (devServer) killProcessTree(devServer, "SIGTERM");
|
|
26092
26468
|
emit2(USER_EVENTS.PREVIEW_ERROR, {
|
|
26093
26469
|
stage: "tunnel",
|
|
26094
26470
|
message: `Tunnel did not become reachable after ${MAX_TUNNEL_ATTEMPTS} attempts (${lastTunnelErr}). Cloudflare Quick Tunnels occasionally fail to register \u2014 please retry.`
|
|
@@ -26099,7 +26475,7 @@ async function establishTunnel(ctx, dev) {
|
|
|
26099
26475
|
}
|
|
26100
26476
|
|
|
26101
26477
|
// src/beads/bd-adapter.ts
|
|
26102
|
-
var
|
|
26478
|
+
var import_child_process24 = require("child_process");
|
|
26103
26479
|
var fs60 = __toESM(require("fs"));
|
|
26104
26480
|
var os48 = __toESM(require("os"));
|
|
26105
26481
|
var path65 = __toESM(require("path"));
|
|
@@ -26153,7 +26529,7 @@ function _defaultSpawn(binaryPath, args2, opts) {
|
|
|
26153
26529
|
return new Promise((resolve10) => {
|
|
26154
26530
|
let proc;
|
|
26155
26531
|
try {
|
|
26156
|
-
proc = (0,
|
|
26532
|
+
proc = (0, import_child_process24.spawn)(binaryPath, args2, { cwd: opts.cwd, env: opts.env });
|
|
26157
26533
|
} catch (err) {
|
|
26158
26534
|
resolve10({ code: -1, stdout: "", stderr: err.message });
|
|
26159
26535
|
return;
|
|
@@ -26310,13 +26686,13 @@ function coerceIssue(row, projectKey) {
|
|
|
26310
26686
|
}
|
|
26311
26687
|
|
|
26312
26688
|
// src/beads/provisioner.ts
|
|
26313
|
-
var
|
|
26689
|
+
var import_child_process27 = require("child_process");
|
|
26314
26690
|
var fs62 = __toESM(require("fs"));
|
|
26315
26691
|
var os50 = __toESM(require("os"));
|
|
26316
26692
|
var path67 = __toESM(require("path"));
|
|
26317
26693
|
|
|
26318
26694
|
// src/beads/install-bd.ts
|
|
26319
|
-
var
|
|
26695
|
+
var import_child_process25 = require("child_process");
|
|
26320
26696
|
var INSTALL_SH_URL = "https://raw.githubusercontent.com/gastownhall/beads/main/scripts/install.sh";
|
|
26321
26697
|
var INSTALL_PS1_URL = "https://raw.githubusercontent.com/gastownhall/beads/main/install.ps1";
|
|
26322
26698
|
function resolveInstallStrategy(platform3) {
|
|
@@ -26347,7 +26723,7 @@ function _defaultInstallSpawn(strategy) {
|
|
|
26347
26723
|
return new Promise((resolve10) => {
|
|
26348
26724
|
let proc;
|
|
26349
26725
|
try {
|
|
26350
|
-
proc = (0,
|
|
26726
|
+
proc = (0, import_child_process25.spawn)(strategy.command, strategy.args, { env: process.env });
|
|
26351
26727
|
} catch (err) {
|
|
26352
26728
|
resolve10({ ok: false, code: -1, stderr: err.message });
|
|
26353
26729
|
return;
|
|
@@ -26377,7 +26753,7 @@ async function installBd(platform3 = process.platform) {
|
|
|
26377
26753
|
}
|
|
26378
26754
|
|
|
26379
26755
|
// src/beads/install-dolt.ts
|
|
26380
|
-
var
|
|
26756
|
+
var import_child_process26 = require("child_process");
|
|
26381
26757
|
var fs61 = __toESM(require("fs"));
|
|
26382
26758
|
var os49 = __toESM(require("os"));
|
|
26383
26759
|
var path66 = __toESM(require("path"));
|
|
@@ -26539,7 +26915,7 @@ function _defaultDoltInstallSpawn(strategy) {
|
|
|
26539
26915
|
};
|
|
26540
26916
|
let proc;
|
|
26541
26917
|
try {
|
|
26542
|
-
proc = (0,
|
|
26918
|
+
proc = (0, import_child_process26.spawn)(strategy.command, strategy.args, {
|
|
26543
26919
|
env: process.env,
|
|
26544
26920
|
stdio: ["ignore", "pipe", "pipe"]
|
|
26545
26921
|
});
|
|
@@ -26766,7 +27142,7 @@ function linkBdOntoPath(binaryPath) {
|
|
|
26766
27142
|
log.info("beads", `linked bd onto PATH: ${linkPath} -> ${binaryPath}`);
|
|
26767
27143
|
}
|
|
26768
27144
|
function setGitBeadsRole() {
|
|
26769
|
-
(0,
|
|
27145
|
+
(0, import_child_process27.execFileSync)("git", ["config", "--global", "beads.role", "contributor"], {
|
|
26770
27146
|
stdio: "ignore"
|
|
26771
27147
|
});
|
|
26772
27148
|
}
|
|
@@ -27621,7 +27997,7 @@ var sessionTerminated = async (ctx, cmd) => {
|
|
|
27621
27997
|
}
|
|
27622
27998
|
quiet(() => ctx.agent.kill());
|
|
27623
27999
|
try {
|
|
27624
|
-
const proc = (0,
|
|
28000
|
+
const proc = (0, import_child_process28.spawn)("bash", ["-lc", "pm2 delete codeam-pair >/dev/null 2>&1 || true"], {
|
|
27625
28001
|
detached: true,
|
|
27626
28002
|
stdio: "ignore"
|
|
27627
28003
|
});
|
|
@@ -27640,7 +28016,7 @@ var shutdownSession = async (ctx, cmd) => {
|
|
|
27640
28016
|
quiet(() => ctx.agent.kill());
|
|
27641
28017
|
if (ctx.keepAliveCtx.inCodespace && ctx.keepAliveCtx.codespaceName) {
|
|
27642
28018
|
try {
|
|
27643
|
-
const stopProc = (0,
|
|
28019
|
+
const stopProc = (0, import_child_process28.spawn)(
|
|
27644
28020
|
"bash",
|
|
27645
28021
|
["-lc", `sleep 1; gh codespace stop -c ${JSON.stringify(ctx.keepAliveCtx.codespaceName)} >/dev/null 2>&1 || true`],
|
|
27646
28022
|
{ detached: true, stdio: "ignore" }
|
|
@@ -27650,7 +28026,7 @@ var shutdownSession = async (ctx, cmd) => {
|
|
|
27650
28026
|
}
|
|
27651
28027
|
}
|
|
27652
28028
|
try {
|
|
27653
|
-
const proc = (0,
|
|
28029
|
+
const proc = (0, import_child_process28.spawn)("bash", ["-lc", "pm2 delete codeam-pair >/dev/null 2>&1 || true"], {
|
|
27654
28030
|
detached: true,
|
|
27655
28031
|
stdio: "ignore"
|
|
27656
28032
|
});
|
|
@@ -28255,7 +28631,7 @@ var defaultCliUpdateDeps = {
|
|
|
28255
28631
|
// Only a truly local `codeam start` (neither marker) re-execs in place below.
|
|
28256
28632
|
isSupervised: () => process.env["CODEAM_AUTO_APPROVE"] === "1" || process.env["CODESPACES"] === "true",
|
|
28257
28633
|
relaunch: (args2) => {
|
|
28258
|
-
const child = (0,
|
|
28634
|
+
const child = (0, import_child_process28.spawnSync)("codeam", args2, { stdio: "inherit", env: process.env });
|
|
28259
28635
|
process.exit(child.status ?? 0);
|
|
28260
28636
|
}
|
|
28261
28637
|
};
|
|
@@ -28336,7 +28712,7 @@ async function runNpmInstallLatest() {
|
|
|
28336
28712
|
const useShell = process.platform === "win32";
|
|
28337
28713
|
const command2 = useShell && invocation.command.includes(" ") ? `"${invocation.command}"` : invocation.command;
|
|
28338
28714
|
const result = await new Promise((resolve10) => {
|
|
28339
|
-
(0,
|
|
28715
|
+
(0, import_child_process28.execFile)(
|
|
28340
28716
|
command2,
|
|
28341
28717
|
invocation.args,
|
|
28342
28718
|
{ timeout: CLI_UPDATE_INSTALL_TIMEOUT_MS, shell: useShell },
|
|
@@ -28762,7 +29138,7 @@ function makePreviewReaffirm(args2) {
|
|
|
28762
29138
|
return makePreviewHeartbeatReaffirm({
|
|
28763
29139
|
serving: () => {
|
|
28764
29140
|
const active2 = activePreviews.get(sessionId);
|
|
28765
|
-
if (!active2 || active2.devServer.exitCode !== null) return null;
|
|
29141
|
+
if (!active2 || active2.devServer && active2.devServer.exitCode !== null) return null;
|
|
28766
29142
|
return {
|
|
28767
29143
|
url: active2.url,
|
|
28768
29144
|
framework: active2.framework,
|
|
@@ -29006,13 +29382,13 @@ async function dispatchCommand(ctx, cmd) {
|
|
|
29006
29382
|
}
|
|
29007
29383
|
|
|
29008
29384
|
// src/commands/start/keep-alive.ts
|
|
29009
|
-
var
|
|
29385
|
+
var import_child_process29 = require("child_process");
|
|
29010
29386
|
function buildKeepAlive(ctx) {
|
|
29011
29387
|
let timer = null;
|
|
29012
29388
|
async function setIdleTimeout(minutes) {
|
|
29013
29389
|
if (!ctx.inCodespace || !ctx.codespaceName) return;
|
|
29014
29390
|
await new Promise((resolve10) => {
|
|
29015
|
-
const proc = (0,
|
|
29391
|
+
const proc = (0, import_child_process29.spawn)(
|
|
29016
29392
|
"gh",
|
|
29017
29393
|
[
|
|
29018
29394
|
"api",
|
|
@@ -30185,7 +30561,7 @@ var fs67 = __toESM(require("fs"));
|
|
|
30185
30561
|
var path74 = __toESM(require("path"));
|
|
30186
30562
|
var os56 = __toESM(require("os"));
|
|
30187
30563
|
var https7 = __toESM(require("https"));
|
|
30188
|
-
var
|
|
30564
|
+
var http8 = __toESM(require("http"));
|
|
30189
30565
|
var import_zod2 = require("zod");
|
|
30190
30566
|
var historyRecordSchema = import_zod2.z.object({
|
|
30191
30567
|
type: import_zod2.z.string().optional(),
|
|
@@ -30268,7 +30644,7 @@ function post(endpoint, body, pluginAuthToken) {
|
|
|
30268
30644
|
return new Promise((resolve10) => {
|
|
30269
30645
|
const payload = JSON.stringify(body);
|
|
30270
30646
|
const u2 = new URL(`${API_BASE8}${endpoint}`);
|
|
30271
|
-
const transport = u2.protocol === "https:" ? https7 :
|
|
30647
|
+
const transport = u2.protocol === "https:" ? https7 : http8;
|
|
30272
30648
|
const req = transport.request(
|
|
30273
30649
|
{
|
|
30274
30650
|
hostname: u2.hostname,
|
|
@@ -35994,12 +36370,12 @@ function buildRelaunchProxyEnv(baseEnv) {
|
|
|
35994
36370
|
return env;
|
|
35995
36371
|
}
|
|
35996
36372
|
var relaunchProxyWithoutBudget = async () => {
|
|
35997
|
-
const { spawn:
|
|
36373
|
+
const { spawn: spawn47 } = await import("child_process");
|
|
35998
36374
|
killHeadroomProxy();
|
|
35999
36375
|
await new Promise((r) => setTimeout(r, 500));
|
|
36000
36376
|
const proxyEnv = buildRelaunchProxyEnv(process.env);
|
|
36001
36377
|
try {
|
|
36002
|
-
const proxy =
|
|
36378
|
+
const proxy = spawn47(
|
|
36003
36379
|
"headroom",
|
|
36004
36380
|
["proxy", "--port", "8787"],
|
|
36005
36381
|
{ stdio: "ignore", detached: true, env: proxyEnv }
|
|
@@ -36219,7 +36595,7 @@ async function performAgentSwitch(deps, rawAgentId, fastPath = {}) {
|
|
|
36219
36595
|
}
|
|
36220
36596
|
|
|
36221
36597
|
// src/services/streaming/transport.ts
|
|
36222
|
-
var
|
|
36598
|
+
var http9 = __toESM(require("http"));
|
|
36223
36599
|
var https8 = __toESM(require("https"));
|
|
36224
36600
|
var _transport4 = {
|
|
36225
36601
|
post: _post3,
|
|
@@ -36229,7 +36605,7 @@ function _post3(url2, headers, payload) {
|
|
|
36229
36605
|
return new Promise((resolve10, reject) => {
|
|
36230
36606
|
let settled = false;
|
|
36231
36607
|
const u2 = new URL(url2);
|
|
36232
|
-
const lib = u2.protocol === "https:" ? https8 :
|
|
36608
|
+
const lib = u2.protocol === "https:" ? https8 : http9;
|
|
36233
36609
|
const req = lib.request(
|
|
36234
36610
|
{
|
|
36235
36611
|
hostname: u2.hostname,
|
|
@@ -36271,7 +36647,7 @@ function _get(url2, headers) {
|
|
|
36271
36647
|
return new Promise((resolve10, reject) => {
|
|
36272
36648
|
let settled = false;
|
|
36273
36649
|
const u2 = new URL(url2);
|
|
36274
|
-
const lib = u2.protocol === "https:" ? https8 :
|
|
36650
|
+
const lib = u2.protocol === "https:" ? https8 : http9;
|
|
36275
36651
|
const req = lib.request(
|
|
36276
36652
|
{
|
|
36277
36653
|
hostname: u2.hostname,
|
|
@@ -36905,7 +37281,7 @@ function withholdTrailingPartialFenceMarker(text) {
|
|
|
36905
37281
|
}
|
|
36906
37282
|
|
|
36907
37283
|
// src/agents/acp/onboarding.ts
|
|
36908
|
-
var
|
|
37284
|
+
var import_child_process30 = require("child_process");
|
|
36909
37285
|
var fs69 = __toESM(require("fs"));
|
|
36910
37286
|
var os59 = __toESM(require("os"));
|
|
36911
37287
|
var path77 = __toESM(require("path"));
|
|
@@ -36926,7 +37302,7 @@ var _onboardingSeam = {
|
|
|
36926
37302
|
*/
|
|
36927
37303
|
gitRemoteUrl: (cwd) => {
|
|
36928
37304
|
try {
|
|
36929
|
-
return (0,
|
|
37305
|
+
return (0, import_child_process30.execFileSync)("git", ["-C", cwd, "remote", "get-url", "origin"], {
|
|
36930
37306
|
encoding: "utf8",
|
|
36931
37307
|
stdio: ["ignore", "pipe", "ignore"],
|
|
36932
37308
|
timeout: 2e3
|
|
@@ -37282,7 +37658,7 @@ function extractSelectPrompt(text) {
|
|
|
37282
37658
|
var import_crypto5 = require("crypto");
|
|
37283
37659
|
|
|
37284
37660
|
// src/services/turn-files/git-changeset.ts
|
|
37285
|
-
var
|
|
37661
|
+
var import_child_process31 = require("child_process");
|
|
37286
37662
|
var fs71 = __toESM(require("fs/promises"));
|
|
37287
37663
|
var path79 = __toESM(require("path"));
|
|
37288
37664
|
|
|
@@ -37468,7 +37844,7 @@ function defaultRunGit(cwd, args2) {
|
|
|
37468
37844
|
return new Promise((resolve10) => {
|
|
37469
37845
|
let proc;
|
|
37470
37846
|
try {
|
|
37471
|
-
proc = (0,
|
|
37847
|
+
proc = (0, import_child_process31.spawn)("git", args2, { cwd, env: process.env });
|
|
37472
37848
|
} catch {
|
|
37473
37849
|
resolve10(null);
|
|
37474
37850
|
return;
|
|
@@ -43495,8 +43871,9 @@ async function start(requestedAgent, presetSession) {
|
|
|
43495
43871
|
})
|
|
43496
43872
|
);
|
|
43497
43873
|
provisionSkillsForStart();
|
|
43498
|
-
const
|
|
43499
|
-
|
|
43874
|
+
const managedBox = !isLocalSession();
|
|
43875
|
+
const depsReady = managedBox ? provisionProjectDependencies(cwd).catch(() => void 0) : Promise.resolve();
|
|
43876
|
+
if (managedBox) {
|
|
43500
43877
|
const GATE_TIMEOUT_MS = 24e4;
|
|
43501
43878
|
const acpAdapterForGate = requiresAcp(session.agent) ? await resolveAcpAdapterWithRetry(session.agent) : null;
|
|
43502
43879
|
const agentBinaryReady = acpAdapterForGate ? Promise.all([
|
|
@@ -44116,11 +44493,11 @@ async function logout() {
|
|
|
44116
44493
|
var import_picocolors11 = __toESM(require("picocolors"));
|
|
44117
44494
|
|
|
44118
44495
|
// src/services/providers/github-codespaces.ts
|
|
44119
|
-
var
|
|
44496
|
+
var import_child_process32 = require("child_process");
|
|
44120
44497
|
var import_util4 = require("util");
|
|
44121
44498
|
var import_picocolors9 = __toESM(require("picocolors"));
|
|
44122
44499
|
var path89 = __toESM(require("path"));
|
|
44123
|
-
var execFileP6 = (0, import_util4.promisify)(
|
|
44500
|
+
var execFileP6 = (0, import_util4.promisify)(import_child_process32.execFile);
|
|
44124
44501
|
var MAX_BUFFER = 8 * 1024 * 1024;
|
|
44125
44502
|
function resetStdinForChild() {
|
|
44126
44503
|
if (process.stdin.isTTY) {
|
|
@@ -44164,7 +44541,7 @@ var GitHubCodespacesProvider = class {
|
|
|
44164
44541
|
if (!isAuthed) {
|
|
44165
44542
|
resetStdinForChild();
|
|
44166
44543
|
await new Promise((resolve10, reject) => {
|
|
44167
|
-
const proc = (0,
|
|
44544
|
+
const proc = (0, import_child_process32.spawn)("gh", ["auth", "login", "-s", "codespace,repo,read:user"], {
|
|
44168
44545
|
stdio: "inherit"
|
|
44169
44546
|
});
|
|
44170
44547
|
proc.on("exit", (code) => {
|
|
@@ -44198,7 +44575,7 @@ var GitHubCodespacesProvider = class {
|
|
|
44198
44575
|
wt(noteLines.join("\n"), "One more permission needed");
|
|
44199
44576
|
resetStdinForChild();
|
|
44200
44577
|
const refreshCode = await new Promise((resolve10, reject) => {
|
|
44201
|
-
const proc = (0,
|
|
44578
|
+
const proc = (0, import_child_process32.spawn)(
|
|
44202
44579
|
"gh",
|
|
44203
44580
|
["auth", "refresh", "-h", "github.com", "-s", "codespace"],
|
|
44204
44581
|
{ stdio: "inherit" }
|
|
@@ -44348,7 +44725,7 @@ var GitHubCodespacesProvider = class {
|
|
|
44348
44725
|
O2.step(`Installing gh via ${installCmd.describe}\u2026`);
|
|
44349
44726
|
resetStdinForChild();
|
|
44350
44727
|
const ok = await new Promise((resolve10) => {
|
|
44351
|
-
const proc = (0,
|
|
44728
|
+
const proc = (0, import_child_process32.spawn)(installCmd.exe, installCmd.args, { stdio: "inherit" });
|
|
44352
44729
|
proc.on("exit", (code) => resolve10(code === 0));
|
|
44353
44730
|
proc.on("error", () => resolve10(false));
|
|
44354
44731
|
});
|
|
@@ -44375,7 +44752,7 @@ var GitHubCodespacesProvider = class {
|
|
|
44375
44752
|
);
|
|
44376
44753
|
resetStdinForChild();
|
|
44377
44754
|
await new Promise((resolve10, reject) => {
|
|
44378
|
-
const proc = (0,
|
|
44755
|
+
const proc = (0, import_child_process32.spawn)(
|
|
44379
44756
|
"gh",
|
|
44380
44757
|
["auth", "refresh", "-h", "github.com", "-s", "repo,read:org"],
|
|
44381
44758
|
{ stdio: "inherit" }
|
|
@@ -44553,7 +44930,7 @@ var GitHubCodespacesProvider = class {
|
|
|
44553
44930
|
async streamCommand(workspaceId, command2) {
|
|
44554
44931
|
resetStdinForChild();
|
|
44555
44932
|
return new Promise((resolve10, reject) => {
|
|
44556
|
-
const proc = (0,
|
|
44933
|
+
const proc = (0, import_child_process32.spawn)(
|
|
44557
44934
|
"gh",
|
|
44558
44935
|
["codespace", "ssh", "-c", workspaceId, "--", "-tt", command2],
|
|
44559
44936
|
{ stdio: "inherit" }
|
|
@@ -44580,11 +44957,11 @@ var GitHubCodespacesProvider = class {
|
|
|
44580
44957
|
`mkdir -p ${shellQuote(remoteDir)} && tar -xzf - -C ${shellQuote(remoteDir)}`
|
|
44581
44958
|
];
|
|
44582
44959
|
await new Promise((resolve10, reject) => {
|
|
44583
|
-
const tar = (0,
|
|
44960
|
+
const tar = (0, import_child_process32.spawn)("tar", tarArgs, {
|
|
44584
44961
|
stdio: ["ignore", "pipe", "pipe"],
|
|
44585
44962
|
env: tarEnv
|
|
44586
44963
|
});
|
|
44587
|
-
const ssh = (0,
|
|
44964
|
+
const ssh = (0, import_child_process32.spawn)("gh", sshArgs, {
|
|
44588
44965
|
stdio: [tar.stdout, "pipe", "pipe"]
|
|
44589
44966
|
});
|
|
44590
44967
|
let tarErr = "";
|
|
@@ -44618,7 +44995,7 @@ var GitHubCodespacesProvider = class {
|
|
|
44618
44995
|
}
|
|
44619
44996
|
const cmd = parts.join(" && ");
|
|
44620
44997
|
await new Promise((resolve10, reject) => {
|
|
44621
|
-
const proc = (0,
|
|
44998
|
+
const proc = (0, import_child_process32.spawn)(
|
|
44622
44999
|
"gh",
|
|
44623
45000
|
["codespace", "ssh", "-c", workspaceId, "--", cmd],
|
|
44624
45001
|
{ stdio: ["pipe", "pipe", "pipe"] }
|
|
@@ -44676,11 +45053,11 @@ function shellQuote(s) {
|
|
|
44676
45053
|
}
|
|
44677
45054
|
|
|
44678
45055
|
// src/services/providers/gitpod.ts
|
|
44679
|
-
var
|
|
45056
|
+
var import_child_process33 = require("child_process");
|
|
44680
45057
|
var import_util5 = require("util");
|
|
44681
45058
|
var path90 = __toESM(require("path"));
|
|
44682
45059
|
var import_picocolors10 = __toESM(require("picocolors"));
|
|
44683
|
-
var execFileP7 = (0, import_util5.promisify)(
|
|
45060
|
+
var execFileP7 = (0, import_util5.promisify)(import_child_process33.execFile);
|
|
44684
45061
|
var MAX_BUFFER2 = 8 * 1024 * 1024;
|
|
44685
45062
|
function resetStdinForChild2() {
|
|
44686
45063
|
if (process.stdin.isTTY) {
|
|
@@ -44720,7 +45097,7 @@ var GitpodProvider = class {
|
|
|
44720
45097
|
);
|
|
44721
45098
|
resetStdinForChild2();
|
|
44722
45099
|
await new Promise((resolve10, reject) => {
|
|
44723
|
-
const proc = (0,
|
|
45100
|
+
const proc = (0, import_child_process33.spawn)("gitpod", ["login"], { stdio: "inherit" });
|
|
44724
45101
|
proc.on("exit", (code) => {
|
|
44725
45102
|
if (code === 0) resolve10();
|
|
44726
45103
|
else reject(new Error("gitpod login failed."));
|
|
@@ -44872,7 +45249,7 @@ var GitpodProvider = class {
|
|
|
44872
45249
|
async streamCommand(workspaceId, command2) {
|
|
44873
45250
|
resetStdinForChild2();
|
|
44874
45251
|
return new Promise((resolve10, reject) => {
|
|
44875
|
-
const proc = (0,
|
|
45252
|
+
const proc = (0, import_child_process33.spawn)(
|
|
44876
45253
|
"gitpod",
|
|
44877
45254
|
["workspace", "ssh", workspaceId, "--", "-tt", command2],
|
|
44878
45255
|
{ stdio: "inherit" }
|
|
@@ -44892,11 +45269,11 @@ var GitpodProvider = class {
|
|
|
44892
45269
|
const tarEnv = { ...process.env, COPYFILE_DISABLE: "1" };
|
|
44893
45270
|
const remoteCmd = `mkdir -p ${shellQuote2(remoteDir)} && tar -xzf - -C ${shellQuote2(remoteDir)}`;
|
|
44894
45271
|
await new Promise((resolve10, reject) => {
|
|
44895
|
-
const tar = (0,
|
|
45272
|
+
const tar = (0, import_child_process33.spawn)("tar", tarArgs, {
|
|
44896
45273
|
stdio: ["ignore", "pipe", "pipe"],
|
|
44897
45274
|
env: tarEnv
|
|
44898
45275
|
});
|
|
44899
|
-
const ssh = (0,
|
|
45276
|
+
const ssh = (0, import_child_process33.spawn)(
|
|
44900
45277
|
"gitpod",
|
|
44901
45278
|
["workspace", "ssh", workspaceId, "--", remoteCmd],
|
|
44902
45279
|
{ stdio: [tar.stdout, "pipe", "pipe"] }
|
|
@@ -44928,7 +45305,7 @@ var GitpodProvider = class {
|
|
|
44928
45305
|
}
|
|
44929
45306
|
const cmd = parts.join(" && ");
|
|
44930
45307
|
await new Promise((resolve10, reject) => {
|
|
44931
|
-
const proc = (0,
|
|
45308
|
+
const proc = (0, import_child_process33.spawn)(
|
|
44932
45309
|
"gitpod",
|
|
44933
45310
|
["workspace", "ssh", workspaceId, "--", cmd],
|
|
44934
45311
|
{ stdio: ["pipe", "pipe", "pipe"] }
|
|
@@ -44952,10 +45329,10 @@ function shellQuote2(s) {
|
|
|
44952
45329
|
}
|
|
44953
45330
|
|
|
44954
45331
|
// src/services/providers/gitlab-workspaces.ts
|
|
44955
|
-
var
|
|
45332
|
+
var import_child_process34 = require("child_process");
|
|
44956
45333
|
var import_util6 = require("util");
|
|
44957
45334
|
var path91 = __toESM(require("path"));
|
|
44958
|
-
var execFileP8 = (0, import_util6.promisify)(
|
|
45335
|
+
var execFileP8 = (0, import_util6.promisify)(import_child_process34.execFile);
|
|
44959
45336
|
var MAX_BUFFER3 = 8 * 1024 * 1024;
|
|
44960
45337
|
var GITLAB_API_BASE = process.env.CODEAM_GITLAB_API_URL ?? "https://gitlab.com/api/v4";
|
|
44961
45338
|
function resetStdinForChild3() {
|
|
@@ -44997,7 +45374,7 @@ var GitLabWorkspacesProvider = class {
|
|
|
44997
45374
|
);
|
|
44998
45375
|
resetStdinForChild3();
|
|
44999
45376
|
await new Promise((resolve10, reject) => {
|
|
45000
|
-
const proc = (0,
|
|
45377
|
+
const proc = (0, import_child_process34.spawn)(
|
|
45001
45378
|
"glab",
|
|
45002
45379
|
["auth", "login", "--scopes", "api,read_user,read_repository"],
|
|
45003
45380
|
{ stdio: "inherit" }
|
|
@@ -45169,7 +45546,7 @@ Docs: https://docs.gitlab.com/ee/user/workspace/configuration.html`
|
|
|
45169
45546
|
const sshHost = process.env.CODEAM_GITLAB_SSH_HOST ?? "workspaces.gitlab.com";
|
|
45170
45547
|
resetStdinForChild3();
|
|
45171
45548
|
return new Promise((resolve10, reject) => {
|
|
45172
|
-
const proc = (0,
|
|
45549
|
+
const proc = (0, import_child_process34.spawn)(
|
|
45173
45550
|
"ssh",
|
|
45174
45551
|
["-tt", "-o", "StrictHostKeyChecking=accept-new", `${workspaceId}@${sshHost}`, command2],
|
|
45175
45552
|
{ stdio: "inherit" }
|
|
@@ -45190,8 +45567,8 @@ Docs: https://docs.gitlab.com/ee/user/workspace/configuration.html`
|
|
|
45190
45567
|
const tarEnv = { ...process.env, COPYFILE_DISABLE: "1" };
|
|
45191
45568
|
const remoteCmd = `mkdir -p ${shellQuote3(remoteDir)} && tar -xzf - -C ${shellQuote3(remoteDir)}`;
|
|
45192
45569
|
await new Promise((resolve10, reject) => {
|
|
45193
|
-
const tar = (0,
|
|
45194
|
-
const ssh = (0,
|
|
45570
|
+
const tar = (0, import_child_process34.spawn)("tar", tarArgs, { stdio: ["ignore", "pipe", "pipe"], env: tarEnv });
|
|
45571
|
+
const ssh = (0, import_child_process34.spawn)(
|
|
45195
45572
|
"ssh",
|
|
45196
45573
|
["-o", "StrictHostKeyChecking=accept-new", `${workspaceId}@${sshHost}`, remoteCmd],
|
|
45197
45574
|
{ stdio: [tar.stdout, "pipe", "pipe"] }
|
|
@@ -45221,7 +45598,7 @@ Docs: https://docs.gitlab.com/ee/user/workspace/configuration.html`
|
|
|
45221
45598
|
}
|
|
45222
45599
|
const cmd = parts.join(" && ");
|
|
45223
45600
|
await new Promise((resolve10, reject) => {
|
|
45224
|
-
const proc = (0,
|
|
45601
|
+
const proc = (0, import_child_process34.spawn)(
|
|
45225
45602
|
"ssh",
|
|
45226
45603
|
["-o", "StrictHostKeyChecking=accept-new", `${workspaceId}@${sshHost}`, cmd],
|
|
45227
45604
|
{ stdio: ["pipe", "pipe", "pipe"] }
|
|
@@ -45280,10 +45657,10 @@ function shellQuote3(s) {
|
|
|
45280
45657
|
}
|
|
45281
45658
|
|
|
45282
45659
|
// src/services/providers/railway.ts
|
|
45283
|
-
var
|
|
45660
|
+
var import_child_process35 = require("child_process");
|
|
45284
45661
|
var import_util7 = require("util");
|
|
45285
45662
|
var path92 = __toESM(require("path"));
|
|
45286
|
-
var execFileP9 = (0, import_util7.promisify)(
|
|
45663
|
+
var execFileP9 = (0, import_util7.promisify)(import_child_process35.execFile);
|
|
45287
45664
|
var MAX_BUFFER4 = 8 * 1024 * 1024;
|
|
45288
45665
|
function resetStdinForChild4() {
|
|
45289
45666
|
if (process.stdin.isTTY) {
|
|
@@ -45324,7 +45701,7 @@ var RailwayProvider = class {
|
|
|
45324
45701
|
);
|
|
45325
45702
|
resetStdinForChild4();
|
|
45326
45703
|
await new Promise((resolve10, reject) => {
|
|
45327
|
-
const proc = (0,
|
|
45704
|
+
const proc = (0, import_child_process35.spawn)("railway", ["login"], { stdio: "inherit" });
|
|
45328
45705
|
proc.on("exit", (code) => {
|
|
45329
45706
|
if (code === 0) resolve10();
|
|
45330
45707
|
else reject(new Error("railway login failed."));
|
|
@@ -45467,7 +45844,7 @@ var RailwayProvider = class {
|
|
|
45467
45844
|
}
|
|
45468
45845
|
resetStdinForChild4();
|
|
45469
45846
|
return new Promise((resolve10, reject) => {
|
|
45470
|
-
const proc = (0,
|
|
45847
|
+
const proc = (0, import_child_process35.spawn)(
|
|
45471
45848
|
"railway",
|
|
45472
45849
|
["shell", "--project", projectId, "--service", serviceId, "--command", command2],
|
|
45473
45850
|
{ stdio: "inherit" }
|
|
@@ -45491,8 +45868,8 @@ var RailwayProvider = class {
|
|
|
45491
45868
|
const tarEnv = { ...process.env, COPYFILE_DISABLE: "1" };
|
|
45492
45869
|
const remoteCmd = `mkdir -p ${shellQuote4(remoteDir)} && tar -xzf - -C ${shellQuote4(remoteDir)}`;
|
|
45493
45870
|
await new Promise((resolve10, reject) => {
|
|
45494
|
-
const tar = (0,
|
|
45495
|
-
const sh = (0,
|
|
45871
|
+
const tar = (0, import_child_process35.spawn)("tar", tarArgs, { stdio: ["ignore", "pipe", "pipe"], env: tarEnv });
|
|
45872
|
+
const sh = (0, import_child_process35.spawn)(
|
|
45496
45873
|
"railway",
|
|
45497
45874
|
["shell", "--project", projectId, "--service", serviceId, "--command", remoteCmd],
|
|
45498
45875
|
{ stdio: [tar.stdout, "pipe", "pipe"] }
|
|
@@ -45525,7 +45902,7 @@ var RailwayProvider = class {
|
|
|
45525
45902
|
}
|
|
45526
45903
|
const cmd = parts.join(" && ");
|
|
45527
45904
|
await new Promise((resolve10, reject) => {
|
|
45528
|
-
const proc = (0,
|
|
45905
|
+
const proc = (0, import_child_process35.spawn)(
|
|
45529
45906
|
"railway",
|
|
45530
45907
|
["shell", "--project", projectId, "--service", serviceId, "--command", cmd],
|
|
45531
45908
|
{ stdio: ["pipe", "pipe", "pipe"] }
|
|
@@ -46333,7 +46710,7 @@ function checkChokidar() {
|
|
|
46333
46710
|
}
|
|
46334
46711
|
async function doctor(args2 = []) {
|
|
46335
46712
|
const json = args2.includes("--json");
|
|
46336
|
-
const cliVersion = true ? "2.
|
|
46713
|
+
const cliVersion = true ? "2.70.0" : "0.0.0-dev";
|
|
46337
46714
|
const apiBase2 = resolveApiBaseUrl();
|
|
46338
46715
|
const diagnosticId = (0, import_node_crypto13.randomUUID)();
|
|
46339
46716
|
log.info("doctor", `run id=${diagnosticId} cli=${cliVersion}`);
|
|
@@ -46724,7 +47101,7 @@ async function mcpRun(args2) {
|
|
|
46724
47101
|
// src/commands/version.ts
|
|
46725
47102
|
var import_picocolors15 = __toESM(require("picocolors"));
|
|
46726
47103
|
function version2() {
|
|
46727
|
-
const v = true ? "2.
|
|
47104
|
+
const v = true ? "2.70.0" : "unknown";
|
|
46728
47105
|
console.log(`${import_picocolors15.default.bold("codeam-cli")} ${import_picocolors15.default.cyan(v)}`);
|
|
46729
47106
|
}
|
|
46730
47107
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "codeam-cli",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.70.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",
|