codeam-cli 2.61.10 → 2.61.13
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 +114 -12
- 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.61.11] — 2026-07-16
|
|
8
|
+
|
|
9
|
+
### Fixed
|
|
10
|
+
|
|
11
|
+
- **cli:** Periodic 12h re-baseline so an idle session's conversation outlives the backend TTL
|
|
12
|
+
|
|
13
|
+
## [2.61.10] — 2026-07-16
|
|
14
|
+
|
|
15
|
+
### Fixed
|
|
16
|
+
|
|
17
|
+
- **cli:** Fleet box hardening — self-updatable image, fresh-pull creates, dead-container rm
|
|
18
|
+
|
|
7
19
|
## [2.61.9] — 2026-07-16
|
|
8
20
|
|
|
9
21
|
### Fixed
|
package/dist/index.js
CHANGED
|
@@ -742,6 +742,49 @@ var INTEGRATION_REGISTRY = {
|
|
|
742
742
|
staticEnv: { AZURE_DEVOPS_AUTH_METHOD: "pat" }
|
|
743
743
|
}
|
|
744
744
|
}
|
|
745
|
+
},
|
|
746
|
+
figma: {
|
|
747
|
+
id: "figma",
|
|
748
|
+
name: "Figma",
|
|
749
|
+
icon: "figma",
|
|
750
|
+
// LIVE — the Figma OAuth app (Confidential, both prod+dev redirect URIs)
|
|
751
|
+
// is registered and FIGMA_OAUTH_CLIENT_ID/SECRET/REDIRECT_URI are in
|
|
752
|
+
// Secret Manager (prod+dev, created 2026-07-16). The backend
|
|
753
|
+
// FigmaOAuthProvider is config-gated (503 if env unset) so this is safe
|
|
754
|
+
// even mid-rollout before the secrets mount.
|
|
755
|
+
enabled: true,
|
|
756
|
+
auth: {
|
|
757
|
+
kind: "oauth_redirect",
|
|
758
|
+
// Granular READ-ONLY scopes (legacy `files:read` is deprecated for
|
|
759
|
+
// OAuth). Asset export (GET /v1/images) rides file_content:read.
|
|
760
|
+
// file_variables:read is Enterprise-only and would break linking for
|
|
761
|
+
// normal accounts — deliberately excluded. ⚠️ Changing these requires
|
|
762
|
+
// the user to RE-LINK Figma.
|
|
763
|
+
scopes: [
|
|
764
|
+
"current_user:read",
|
|
765
|
+
"file_content:read",
|
|
766
|
+
"file_metadata:read",
|
|
767
|
+
"file_dev_resources:read",
|
|
768
|
+
"library_content:read"
|
|
769
|
+
]
|
|
770
|
+
},
|
|
771
|
+
delivery: {
|
|
772
|
+
mcp: {
|
|
773
|
+
// Framelink figma-developer-mcp (Node, stdio) in BYO-token headless
|
|
774
|
+
// mode — the ONLY known Figma MCP server that accepts an OAuth
|
|
775
|
+
// Bearer token: FIGMA_OAUTH_TOKEN → `Authorization: Bearer` (env
|
|
776
|
+
// only, never argv). Figma's official servers can't be used here
|
|
777
|
+
// (remote = interactive OAuth + client allowlist; Dev Mode =
|
|
778
|
+
// desktop app). Version PINNED; bump only after re-verifying
|
|
779
|
+
// headless. Tools: get_figma_data (condensed layout extraction) +
|
|
780
|
+
// download_figma_images (asset export).
|
|
781
|
+
command: "npx",
|
|
782
|
+
args: ["-y", "figma-developer-mcp@0.13.2", "--stdio", "--no-telemetry"],
|
|
783
|
+
envMapping: {
|
|
784
|
+
FIGMA_OAUTH_TOKEN: "accessToken"
|
|
785
|
+
}
|
|
786
|
+
}
|
|
787
|
+
}
|
|
745
788
|
}
|
|
746
789
|
};
|
|
747
790
|
function getIntegration(id) {
|
|
@@ -5975,7 +6018,7 @@ function readAnonId() {
|
|
|
5975
6018
|
}
|
|
5976
6019
|
function superProperties() {
|
|
5977
6020
|
return {
|
|
5978
|
-
cliVersion: true ? "2.61.
|
|
6021
|
+
cliVersion: true ? "2.61.13" : "0.0.0-dev",
|
|
5979
6022
|
nodeVersion: process.version,
|
|
5980
6023
|
platform: process.platform,
|
|
5981
6024
|
arch: process.arch,
|
|
@@ -6156,7 +6199,7 @@ var os4 = __toESM(require("os"));
|
|
|
6156
6199
|
// package.json
|
|
6157
6200
|
var package_default = {
|
|
6158
6201
|
name: "codeam-cli",
|
|
6159
|
-
version: "2.61.
|
|
6202
|
+
version: "2.61.13",
|
|
6160
6203
|
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.",
|
|
6161
6204
|
type: "commonjs",
|
|
6162
6205
|
main: "dist/index.js",
|
|
@@ -7299,7 +7342,7 @@ var CommandRelayService = class _CommandRelayService {
|
|
|
7299
7342
|
// fresh + clear the "CLI update available" banner after a self-update
|
|
7300
7343
|
// (a codespace that reinstalls @latest reconnects via heartbeat, not
|
|
7301
7344
|
// pair/reconnect). Older backends ignore the extra field.
|
|
7302
|
-
..."2.61.
|
|
7345
|
+
..."2.61.13" ? { ideVersion: "2.61.13" } : {}
|
|
7303
7346
|
}).then(() => log.trace("relay", `heartbeat ok online=${online}`)).catch((err) => log.trace("relay", `heartbeat failed online=${online}`, err));
|
|
7304
7347
|
}
|
|
7305
7348
|
/**
|
|
@@ -17900,7 +17943,7 @@ async function autoUpgradeBeforeCriticalCommand() {
|
|
|
17900
17943
|
if (process.env.NODE_ENV === "test") return;
|
|
17901
17944
|
if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
|
|
17902
17945
|
if (process.env.CI) return;
|
|
17903
|
-
const current = true ? "2.61.
|
|
17946
|
+
const current = true ? "2.61.13" : null;
|
|
17904
17947
|
if (!current) return;
|
|
17905
17948
|
const cache = readCache();
|
|
17906
17949
|
const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
|
|
@@ -17917,7 +17960,7 @@ function checkForUpdates() {
|
|
|
17917
17960
|
if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
|
|
17918
17961
|
if (process.env.CI) return;
|
|
17919
17962
|
if (!process.stdout.isTTY) return;
|
|
17920
|
-
const current = true ? "2.61.
|
|
17963
|
+
const current = true ? "2.61.13" : null;
|
|
17921
17964
|
if (!current) return;
|
|
17922
17965
|
const cache = readCache();
|
|
17923
17966
|
const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
|
|
@@ -17937,7 +17980,7 @@ var SELF_UPDATE_INTERVAL_MS = 60 * 60 * 1e3;
|
|
|
17937
17980
|
var SELF_UPDATE_VIEW_TIMEOUT_MS = 3e4;
|
|
17938
17981
|
var SELF_UPDATE_INSTALL_TIMEOUT_MS = 18e4;
|
|
17939
17982
|
function currentCliVersion() {
|
|
17940
|
-
return true ? "2.61.
|
|
17983
|
+
return true ? "2.61.13" : null;
|
|
17941
17984
|
}
|
|
17942
17985
|
function runCmd(cmd, args2, timeoutMs) {
|
|
17943
17986
|
return new Promise((resolve8) => {
|
|
@@ -24941,6 +24984,18 @@ var HistoryService = class _HistoryService {
|
|
|
24941
24984
|
}
|
|
24942
24985
|
/** Per-session JSONL mtime at the last upload — gates {@link uploadConversationIfChanged}. */
|
|
24943
24986
|
lastTranscriptMtimeMs = /* @__PURE__ */ new Map();
|
|
24987
|
+
/** Wall-clock of the last upload per session — drives the periodic
|
|
24988
|
+
* re-baseline below. */
|
|
24989
|
+
lastUploadWallMs = /* @__PURE__ */ new Map();
|
|
24990
|
+
/** The backend stores the conversation with a bounded TTL (24 h,
|
|
24991
|
+
* `WS_SESSION_TTL`). An IDLE session's JSONL never changes, so a pure
|
|
24992
|
+
* mtime gate would never re-ship and the backend copy would expire —
|
|
24993
|
+
* every later `get_conversation` → GET then returns EMPTY forever (the
|
|
24994
|
+
* 2026-07-16 "la sesión no carga" regression, second occurrence: the
|
|
24995
|
+
* first fix pushed at session START but nothing refreshed an idle
|
|
24996
|
+
* session past the TTL). Re-baseline at half the backend TTL so the
|
|
24997
|
+
* stored copy can never lapse while the session lives. */
|
|
24998
|
+
static REBASELINE_INTERVAL_MS = 12 * 60 * 60 * 1e3;
|
|
24944
24999
|
/**
|
|
24945
25000
|
* Upload a session's transcript when its JSONL changed since the last upload.
|
|
24946
25001
|
* Scales to long/heavy conversations: the ACP `get_conversation` handler is
|
|
@@ -24966,7 +25021,12 @@ var HistoryService = class _HistoryService {
|
|
|
24966
25021
|
} catch {
|
|
24967
25022
|
return false;
|
|
24968
25023
|
}
|
|
24969
|
-
|
|
25024
|
+
const now = Date.now();
|
|
25025
|
+
const staleBaseline = now - (this.lastUploadWallMs.get(sessionId) ?? 0) > _HistoryService.REBASELINE_INTERVAL_MS;
|
|
25026
|
+
if (!staleBaseline && this.lastTranscriptMtimeMs.get(sessionId) === mtimeMs) {
|
|
25027
|
+
return false;
|
|
25028
|
+
}
|
|
25029
|
+
if (staleBaseline) this.lastUploadedUuid.delete(sessionId);
|
|
24970
25030
|
let uploaded;
|
|
24971
25031
|
if (this.lastUploadedUuid.has(sessionId)) {
|
|
24972
25032
|
uploaded = await this.uploadDelta(sessionId) > 0;
|
|
@@ -24975,6 +25035,7 @@ var HistoryService = class _HistoryService {
|
|
|
24975
25035
|
uploaded = true;
|
|
24976
25036
|
}
|
|
24977
25037
|
this.lastTranscriptMtimeMs.set(sessionId, mtimeMs);
|
|
25038
|
+
this.lastUploadWallMs.set(sessionId, now);
|
|
24978
25039
|
return uploaded;
|
|
24979
25040
|
}
|
|
24980
25041
|
/**
|
|
@@ -31789,6 +31850,23 @@ async function resumeSessionH(ctx) {
|
|
|
31789
31850
|
}
|
|
31790
31851
|
try {
|
|
31791
31852
|
await client3.loadSession(id);
|
|
31853
|
+
ctx.history.switchActiveSession(id);
|
|
31854
|
+
ctx.onActiveSessionChanged?.(id);
|
|
31855
|
+
try {
|
|
31856
|
+
await ctx.jsonlHistory.uploadConversationIfChanged(id);
|
|
31857
|
+
} catch (err) {
|
|
31858
|
+
log.warn("acpRunner", `resume_session: transcript upload failed: ${describeError(err)}`);
|
|
31859
|
+
}
|
|
31860
|
+
void (async () => {
|
|
31861
|
+
try {
|
|
31862
|
+
const listed = await client3.listSessions();
|
|
31863
|
+
if (listed && listed.length > 0) {
|
|
31864
|
+
await ctx.publisher.pushSessionList({ agentId: opts.agent, sessions: listed });
|
|
31865
|
+
}
|
|
31866
|
+
} catch (err) {
|
|
31867
|
+
log.warn("acpRunner", `resume_session: list push failed: ${describeError(err)}`);
|
|
31868
|
+
}
|
|
31869
|
+
})();
|
|
31792
31870
|
await relay.sendResult(cmd.id, "completed", { sessionId: id });
|
|
31793
31871
|
} catch (err) {
|
|
31794
31872
|
log.warn("acpRunner", `resume_session failed: ${describeError(err)}`);
|
|
@@ -32342,6 +32420,21 @@ var AcpHistory = class {
|
|
|
32342
32420
|
opts;
|
|
32343
32421
|
messages = [];
|
|
32344
32422
|
summary = null;
|
|
32423
|
+
/**
|
|
32424
|
+
* Switch the active conversation after a `resume_session` loadSession
|
|
32425
|
+
* (2026-07-16 "conversation never loads on resume" fix). The buffered
|
|
32426
|
+
* turns belong to the PREVIOUS conversation — flushing them under the
|
|
32427
|
+
* new id would corrupt it — so the buffer and summary reset; the loaded
|
|
32428
|
+
* conversation's real history lives in its JSONL, which the resume
|
|
32429
|
+
* handler uploads via HistoryService. Future turn flushes then push
|
|
32430
|
+
* under the new id.
|
|
32431
|
+
*/
|
|
32432
|
+
switchActiveSession(id) {
|
|
32433
|
+
if (id === this.opts.acpSessionId) return;
|
|
32434
|
+
this.opts.acpSessionId = id;
|
|
32435
|
+
this.messages.length = 0;
|
|
32436
|
+
this.summary = null;
|
|
32437
|
+
}
|
|
32345
32438
|
appendUserPrompt(text) {
|
|
32346
32439
|
if (this.summary === null) {
|
|
32347
32440
|
const trimmed = text.trim().replace(/\s+/g, " ");
|
|
@@ -32727,7 +32820,15 @@ async function runAcpSession(opts) {
|
|
|
32727
32820
|
budgetRecovery,
|
|
32728
32821
|
{ get: () => _budgetReachedPosted, set: (v) => {
|
|
32729
32822
|
_budgetReachedPosted = v;
|
|
32730
|
-
} }
|
|
32823
|
+
} },
|
|
32824
|
+
// resume_session re-points the runner's active conversation: the
|
|
32825
|
+
// relay callback reads `acpSessionId` per command, so every FUTURE
|
|
32826
|
+
// get_conversation / upload / one-shot serves the RESUMED id — not
|
|
32827
|
+
// the boot-time one (2026-07-16 "resume loads the old/blank
|
|
32828
|
+
// conversation" fix).
|
|
32829
|
+
(id) => {
|
|
32830
|
+
acpSessionId = id;
|
|
32831
|
+
}
|
|
32731
32832
|
);
|
|
32732
32833
|
},
|
|
32733
32834
|
{ id: opts.agent, name: opts.agent, displayName: opts.agent }
|
|
@@ -32762,7 +32863,7 @@ async function runAcpSession(opts) {
|
|
|
32762
32863
|
await new Promise(() => {
|
|
32763
32864
|
});
|
|
32764
32865
|
}
|
|
32765
|
-
async function handleCommand(cmd, client3, relay, acpSessionId, models, streaming, opts, history, jsonlHistory, agentCaps, turnFiles, getBeads, publisher, recentStderr, budgetRecovery, budgetReachedFlag) {
|
|
32866
|
+
async function handleCommand(cmd, client3, relay, acpSessionId, models, streaming, opts, history, jsonlHistory, agentCaps, turnFiles, getBeads, publisher, recentStderr, budgetRecovery, budgetReachedFlag, onActiveSessionChanged) {
|
|
32766
32867
|
const session = {
|
|
32767
32868
|
client: client3,
|
|
32768
32869
|
relay,
|
|
@@ -32778,7 +32879,8 @@ async function handleCommand(cmd, client3, relay, acpSessionId, models, streamin
|
|
|
32778
32879
|
publisher,
|
|
32779
32880
|
recentStderr,
|
|
32780
32881
|
budgetRecovery,
|
|
32781
|
-
budgetReachedFlag
|
|
32882
|
+
budgetReachedFlag,
|
|
32883
|
+
onActiveSessionChanged
|
|
32782
32884
|
};
|
|
32783
32885
|
await dispatchAcpCommand(assembleAcpCommandContext(session, cmd));
|
|
32784
32886
|
}
|
|
@@ -37437,7 +37539,7 @@ function checkChokidar() {
|
|
|
37437
37539
|
}
|
|
37438
37540
|
async function doctor(args2 = []) {
|
|
37439
37541
|
const json = args2.includes("--json");
|
|
37440
|
-
const cliVersion = true ? "2.61.
|
|
37542
|
+
const cliVersion = true ? "2.61.13" : "0.0.0-dev";
|
|
37441
37543
|
const apiBase2 = resolveApiBaseUrl();
|
|
37442
37544
|
const diagnosticId = (0, import_node_crypto12.randomUUID)();
|
|
37443
37545
|
log.info("doctor", `run id=${diagnosticId} cli=${cliVersion}`);
|
|
@@ -37948,7 +38050,7 @@ async function mcpRun(args2) {
|
|
|
37948
38050
|
// src/commands/version.ts
|
|
37949
38051
|
var import_picocolors15 = __toESM(require("picocolors"));
|
|
37950
38052
|
function version2() {
|
|
37951
|
-
const v = true ? "2.61.
|
|
38053
|
+
const v = true ? "2.61.13" : "unknown";
|
|
37952
38054
|
console.log(`${import_picocolors15.default.bold("codeam-cli")} ${import_picocolors15.default.cyan(v)}`);
|
|
37953
38055
|
}
|
|
37954
38056
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "codeam-cli",
|
|
3
|
-
"version": "2.61.
|
|
3
|
+
"version": "2.61.13",
|
|
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",
|