codeam-cli 2.26.11 → 2.26.12

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 CHANGED
@@ -4,6 +4,12 @@ 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.26.11] — 2026-06-03
8
+
9
+ ### Added
10
+
11
+ - **cli:** Emit preview_progress SSE events at each bring-up milestone (#244)
12
+
7
13
  ## [2.26.10] — 2026-06-03
8
14
 
9
15
  ### Fixed
package/dist/index.js CHANGED
@@ -472,7 +472,7 @@ var import_qrcode_terminal = __toESM(require("qrcode-terminal"));
472
472
  // package.json
473
473
  var package_default = {
474
474
  name: "codeam-cli",
475
- version: "2.26.11",
475
+ version: "2.26.12",
476
476
  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.",
477
477
  type: "commonjs",
478
478
  main: "dist/index.js",
@@ -5829,7 +5829,7 @@ function readAnonId() {
5829
5829
  }
5830
5830
  function superProperties() {
5831
5831
  return {
5832
- cliVersion: true ? "2.26.11" : "0.0.0-dev",
5832
+ cliVersion: true ? "2.26.12" : "0.0.0-dev",
5833
5833
  nodeVersion: process.version,
5834
5834
  platform: process.platform,
5835
5835
  arch: process.arch,
@@ -16057,25 +16057,29 @@ async function linkDryRunPreflight(ctx) {
16057
16057
  }
16058
16058
 
16059
16059
  // src/services/preview/cloudflared.ts
16060
+ var import_promises = require("dns/promises");
16060
16061
  var import_fs = require("fs");
16061
- var import_promises = __toESM(require("fs/promises"));
16062
+ var import_promises2 = __toESM(require("fs/promises"));
16062
16063
  var import_os7 = __toESM(require("os"));
16063
16064
  var import_path4 = __toESM(require("path"));
16064
- var import_promises2 = require("stream/promises");
16065
+ var import_promises3 = require("stream/promises");
16065
16066
  var import_which = __toESM(require("which"));
16066
16067
  var CACHED_BINARY = import_path4.default.join(import_os7.default.homedir(), ".codeam", "bin", "cloudflared");
16067
- async function waitForCloudflaredReady(url, timeoutMs = 3e4) {
16068
+ async function waitForCloudflaredReady(url, timeoutMs = 6e4) {
16069
+ const hostname3 = new URL(url).hostname;
16070
+ const resolver = new import_promises.Resolver();
16071
+ resolver.setServers(["1.1.1.1", "1.0.0.1"]);
16068
16072
  const start2 = Date.now();
16069
16073
  while (Date.now() - start2 < timeoutMs) {
16070
16074
  try {
16071
- const res = await fetch(url, { method: "HEAD" });
16072
- if (res.status < 500) return;
16075
+ const addrs = await resolver.resolve4(hostname3);
16076
+ if (addrs.length > 0) return;
16073
16077
  } catch {
16074
16078
  }
16075
16079
  await new Promise((r) => setTimeout(r, 500));
16076
16080
  }
16077
16081
  throw new Error(
16078
- `Tunnel URL ${url} not reachable after ${timeoutMs}ms (DNS may still be propagating).`
16082
+ `DNS for ${hostname3} did not resolve within ${timeoutMs}ms (Cloudflare Quick Tunnel registration may have failed).`
16079
16083
  );
16080
16084
  }
16081
16085
  async function resolveCloudflared(opts = {}) {
@@ -16084,7 +16088,7 @@ async function resolveCloudflared(opts = {}) {
16084
16088
  } catch {
16085
16089
  }
16086
16090
  try {
16087
- await import_promises.default.access(CACHED_BINARY);
16091
+ await import_promises2.default.access(CACHED_BINARY);
16088
16092
  return CACHED_BINARY;
16089
16093
  } catch {
16090
16094
  }
@@ -16098,14 +16102,14 @@ async function resolveCloudflared(opts = {}) {
16098
16102
  }
16099
16103
  async function downloadCloudflared(target) {
16100
16104
  const url = downloadUrlForPlatform();
16101
- await import_promises.default.mkdir(import_path4.default.dirname(target), { recursive: true });
16105
+ await import_promises2.default.mkdir(import_path4.default.dirname(target), { recursive: true });
16102
16106
  const response = await fetch(url);
16103
16107
  if (!response.ok || !response.body) {
16104
16108
  throw new Error(
16105
16109
  `Failed to download cloudflared from ${url}: HTTP ${response.status}. Install manually from https://github.com/cloudflare/cloudflared/releases.`
16106
16110
  );
16107
16111
  }
16108
- await (0, import_promises2.pipeline)(
16112
+ await (0, import_promises3.pipeline)(
16109
16113
  response.body,
16110
16114
  (0, import_fs.createWriteStream)(target, { mode: 493 })
16111
16115
  );
@@ -16158,7 +16162,7 @@ async function waitForCodespacePortReady(url, timeoutMs = 15e3) {
16158
16162
  }
16159
16163
 
16160
16164
  // src/services/preview/config-file.ts
16161
- var import_promises3 = __toESM(require("fs/promises"));
16165
+ var import_promises4 = __toESM(require("fs/promises"));
16162
16166
  var import_path5 = __toESM(require("path"));
16163
16167
  var CONFIG_DIR = ".codeam";
16164
16168
  var CONFIG_FILE = "preview.json";
@@ -16175,7 +16179,7 @@ var REQUIRED_FIELDS = [
16175
16179
  async function readPreviewConfig(cwd) {
16176
16180
  let raw;
16177
16181
  try {
16178
- raw = await import_promises3.default.readFile(configPath(cwd), "utf-8");
16182
+ raw = await import_promises4.default.readFile(configPath(cwd), "utf-8");
16179
16183
  } catch {
16180
16184
  return null;
16181
16185
  }
@@ -16194,8 +16198,8 @@ async function readPreviewConfig(cwd) {
16194
16198
  }
16195
16199
  async function writePreviewConfig(cwd, detection) {
16196
16200
  const filePath = configPath(cwd);
16197
- await import_promises3.default.mkdir(import_path5.default.dirname(filePath), { recursive: true });
16198
- await import_promises3.default.writeFile(filePath, JSON.stringify(detection, null, 2) + "\n", "utf-8");
16201
+ await import_promises4.default.mkdir(import_path5.default.dirname(filePath), { recursive: true });
16202
+ await import_promises4.default.writeFile(filePath, JSON.stringify(detection, null, 2) + "\n", "utf-8");
16199
16203
  }
16200
16204
 
16201
16205
  // src/services/preview/parser.ts
@@ -17102,7 +17106,30 @@ var previewStartH = (ctx, _cmd, parsed) => {
17102
17106
  });
17103
17107
  return;
17104
17108
  }
17105
- void waitForCloudflaredReady(parsedUrl, 3e4).then(() => log.info("preview", `cloudflared probe: ${parsedUrl} reachable from CLI host`)).catch((e) => log.info("preview", `cloudflared probe: ${String(e.message)} (non-fatal)`));
17109
+ try {
17110
+ await waitForCloudflaredReady(parsedUrl, 6e4);
17111
+ log.info("preview", `cloudflared probe: ${parsedUrl} reachable from CLI host`);
17112
+ } catch (e) {
17113
+ try {
17114
+ tunnel.kill("SIGTERM");
17115
+ } catch {
17116
+ }
17117
+ try {
17118
+ devServer.kill("SIGTERM");
17119
+ } catch {
17120
+ }
17121
+ void postPreviewEvent({
17122
+ sessionId: ctx.sessionId,
17123
+ pluginId: ctx.pluginId,
17124
+ pluginAuthToken,
17125
+ type: "preview_error",
17126
+ payload: {
17127
+ stage: "tunnel",
17128
+ message: `Tunnel ${parsedUrl} did not become reachable within 60s (${e.message}). Cloudflare Quick Tunnels occasionally fail to register \u2014 retry usually succeeds.`
17129
+ }
17130
+ });
17131
+ return;
17132
+ }
17106
17133
  url = parsedUrl;
17107
17134
  }
17108
17135
  emitProgress("TUNNEL_READY", url);
@@ -20160,7 +20187,7 @@ function checkChokidar() {
20160
20187
  }
20161
20188
  async function doctor(args2 = []) {
20162
20189
  const json = args2.includes("--json");
20163
- const cliVersion = true ? "2.26.11" : "0.0.0-dev";
20190
+ const cliVersion = true ? "2.26.12" : "0.0.0-dev";
20164
20191
  const apiBase = resolveApiBaseUrl();
20165
20192
  const diagnosticId = (0, import_node_crypto6.randomUUID)();
20166
20193
  log.info("doctor", `run id=${diagnosticId} cli=${cliVersion}`);
@@ -20359,7 +20386,7 @@ async function completion(args2) {
20359
20386
  // src/commands/version.ts
20360
20387
  var import_picocolors13 = __toESM(require("picocolors"));
20361
20388
  function version2() {
20362
- const v = true ? "2.26.11" : "unknown";
20389
+ const v = true ? "2.26.12" : "unknown";
20363
20390
  console.log(`${import_picocolors13.default.bold("codeam-cli")} ${import_picocolors13.default.cyan(v)}`);
20364
20391
  }
20365
20392
 
@@ -20587,7 +20614,7 @@ function checkForUpdates() {
20587
20614
  if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
20588
20615
  if (process.env.CI) return;
20589
20616
  if (!process.stdout.isTTY) return;
20590
- const current = true ? "2.26.11" : null;
20617
+ const current = true ? "2.26.12" : null;
20591
20618
  if (!current) return;
20592
20619
  const cache = readCache();
20593
20620
  const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "codeam-cli",
3
- "version": "2.26.11",
3
+ "version": "2.26.12",
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",