codeam-cli 2.26.14 → 2.26.15

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,19 @@ 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.14] — 2026-06-04
8
+
9
+ ### Chore
10
+
11
+ - **deps:** Bump actions/setup-node from 4 to 6 (#246)
12
+ - **deps:** Bump actions/checkout from 4 to 6 (#247)
13
+ - **deps:** Bump org.jetbrains.kotlin.jvm in /apps/jetbrains-plugin (#248)
14
+ - **cli:** Bump which 2.0.2 → 5.0.0 (#251)
15
+
16
+ ### Fixed
17
+
18
+ - **cli:** Drop redundant install from agent setup_commands + warn agent (#256)
19
+
7
20
  ## [2.26.13] — 2026-06-04
8
21
 
9
22
  ### Added
package/dist/index.js CHANGED
@@ -486,7 +486,7 @@ var import_qrcode_terminal = __toESM(require("qrcode-terminal"));
486
486
  // package.json
487
487
  var package_default = {
488
488
  name: "codeam-cli",
489
- version: "2.26.14",
489
+ version: "2.26.15",
490
490
  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.",
491
491
  type: "commonjs",
492
492
  main: "dist/index.js",
@@ -5843,7 +5843,7 @@ function readAnonId() {
5843
5843
  }
5844
5844
  function superProperties() {
5845
5845
  return {
5846
- cliVersion: true ? "2.26.14" : "0.0.0-dev",
5846
+ cliVersion: true ? "2.26.15" : "0.0.0-dev",
5847
5847
  nodeVersion: process.version,
5848
5848
  platform: process.platform,
5849
5849
  arch: process.arch,
@@ -10888,6 +10888,40 @@ async function extractLocalCodexToken() {
10888
10888
  function codexCredentialsPaths() {
10889
10889
  return [codexCredentialsPath()];
10890
10890
  }
10891
+ function validateLocalCodexToken(credential) {
10892
+ let parsed;
10893
+ try {
10894
+ parsed = JSON.parse(credential);
10895
+ } catch {
10896
+ return { status: "unknown" };
10897
+ }
10898
+ const directExp = typeof parsed.expires_at === "number" ? parsed.expires_at : typeof parsed.tokens?.expires_at === "number" ? parsed.tokens.expires_at : void 0;
10899
+ const jwtExp = decodeJwtExp(parsed.tokens?.id_token);
10900
+ const exp = directExp ?? jwtExp;
10901
+ if (exp === void 0) return { status: "unknown" };
10902
+ const expiresAt = exp < 1e12 ? exp * 1e3 : exp;
10903
+ if (Date.now() >= expiresAt) {
10904
+ return {
10905
+ status: "expired",
10906
+ reason: "Codex OAuth access token expired",
10907
+ expiresAt
10908
+ };
10909
+ }
10910
+ return { status: "valid", expiresAt };
10911
+ }
10912
+ function decodeJwtExp(jwt) {
10913
+ if (!jwt) return void 0;
10914
+ const parts = jwt.split(".");
10915
+ if (parts.length !== 3) return void 0;
10916
+ try {
10917
+ const base64 = parts[1].replace(/-/g, "+").replace(/_/g, "/");
10918
+ const padded = base64 + "===".slice((base64.length + 3) % 4);
10919
+ const payload = JSON.parse(Buffer.from(padded, "base64").toString("utf8"));
10920
+ return typeof payload.exp === "number" ? payload.exp : void 0;
10921
+ } catch {
10922
+ return void 0;
10923
+ }
10924
+ }
10891
10925
 
10892
10926
  // src/agents/codex/link.ts
10893
10927
  function codexCredentialLocator() {
@@ -10896,7 +10930,11 @@ function codexCredentialLocator() {
10896
10930
  vendor: "OpenAI",
10897
10931
  hint: "~/.codex/auth.json",
10898
10932
  watchPaths: codexCredentialsPaths,
10899
- extract: extractLocalCodexToken
10933
+ extract: extractLocalCodexToken,
10934
+ validate: (token) => {
10935
+ const result = validateLocalCodexToken(token.credential);
10936
+ return { status: result.status, reason: result.reason };
10937
+ }
10900
10938
  };
10901
10939
  }
10902
10940
  function codexLoginLauncher() {
@@ -15907,6 +15945,7 @@ async function link(args2 = []) {
15907
15945
  installSpin.stop(`${ctx.displayName} is installed`);
15908
15946
  const existing = await ctx.locator.extract();
15909
15947
  if (existing) {
15948
+ if (refuseIfStale(ctx, existing)) return;
15910
15949
  showInfo(`Found existing ${ctx.displayName} credentials at ${import_picocolors2.default.bold(existing.source)}.`);
15911
15950
  await uploadAndSucceed(ctx, paired, pluginId, existing);
15912
15951
  return;
@@ -15923,8 +15962,26 @@ async function link(args2 = []) {
15923
15962
  console.log("");
15924
15963
  const captured = await captureFreshCredentials(ctx);
15925
15964
  console.log("");
15965
+ if (refuseIfStale(ctx, captured)) return;
15926
15966
  await uploadAndSucceed(ctx, paired, pluginId, captured);
15927
15967
  }
15968
+ function refuseIfStale(ctx, token) {
15969
+ const verdict = ctx.locator.validate?.(token);
15970
+ if (!verdict || verdict.status !== "expired") return false;
15971
+ const reason = verdict.reason ?? "Token expired";
15972
+ showError(
15973
+ `Your local ${ctx.displayName} credentials at ${import_picocolors2.default.bold(ctx.locator.hint)} are already expired:
15974
+ ${reason}
15975
+
15976
+ Uploading them would land a dead snapshot in the vault \u2014 every codespace bootstrapped from it would immediately return 401.
15977
+
15978
+ Run on your machine, then re-link:
15979
+ ${import_picocolors2.default.cyan(`${ctx.binary} logout`)}
15980
+ ${import_picocolors2.default.cyan(`${ctx.binary} login`)}
15981
+ ${import_picocolors2.default.cyan(`codeam link ${ctx.locator.publicId}`)}`
15982
+ );
15983
+ process.exit(1);
15984
+ }
15928
15985
  async function captureFreshCredentials(ctx) {
15929
15986
  const isWin = ctx.runtime.os.id === "win32";
15930
15987
  const watcher = import_chokidar.default.watch(ctx.locator.watchPaths(), {
@@ -20257,7 +20314,7 @@ function checkChokidar() {
20257
20314
  }
20258
20315
  async function doctor(args2 = []) {
20259
20316
  const json = args2.includes("--json");
20260
- const cliVersion = true ? "2.26.14" : "0.0.0-dev";
20317
+ const cliVersion = true ? "2.26.15" : "0.0.0-dev";
20261
20318
  const apiBase = resolveApiBaseUrl();
20262
20319
  const diagnosticId = (0, import_node_crypto6.randomUUID)();
20263
20320
  log.info("doctor", `run id=${diagnosticId} cli=${cliVersion}`);
@@ -20456,7 +20513,7 @@ async function completion(args2) {
20456
20513
  // src/commands/version.ts
20457
20514
  var import_picocolors13 = __toESM(require("picocolors"));
20458
20515
  function version2() {
20459
- const v = true ? "2.26.14" : "unknown";
20516
+ const v = true ? "2.26.15" : "unknown";
20460
20517
  console.log(`${import_picocolors13.default.bold("codeam-cli")} ${import_picocolors13.default.cyan(v)}`);
20461
20518
  }
20462
20519
 
@@ -20684,7 +20741,7 @@ function checkForUpdates() {
20684
20741
  if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
20685
20742
  if (process.env.CI) return;
20686
20743
  if (!process.stdout.isTTY) return;
20687
- const current = true ? "2.26.14" : null;
20744
+ const current = true ? "2.26.15" : null;
20688
20745
  if (!current) return;
20689
20746
  const cache = readCache();
20690
20747
  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.14",
3
+ "version": "2.26.15",
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",