codeam-cli 2.60.63 → 2.60.65
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 +16 -0
- package/dist/index.js +60 -22
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,22 @@ 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.60.64] — 2026-07-15
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
- **shared:** Add Slack search:read scope (agent can search the user's messages)
|
|
12
|
+
|
|
13
|
+
### Documentation
|
|
14
|
+
|
|
15
|
+
- **shared:** Clarify Slack uses a USER token (agent acts as the user)
|
|
16
|
+
|
|
17
|
+
## [2.60.63] — 2026-07-15
|
|
18
|
+
|
|
19
|
+
### Added
|
|
20
|
+
|
|
21
|
+
- **shared:** Add Slack as a live Agent Toolkit integration
|
|
22
|
+
|
|
7
23
|
## [2.60.62] — 2026-07-15
|
|
8
24
|
|
|
9
25
|
### Added
|
package/dist/index.js
CHANGED
|
@@ -614,19 +614,20 @@ var INTEGRATION_REGISTRY = {
|
|
|
614
614
|
id: "slack",
|
|
615
615
|
name: "Slack",
|
|
616
616
|
icon: "slack",
|
|
617
|
-
// LIVE — the Slack app (OAuth v2,
|
|
617
|
+
// LIVE — the Slack app (OAuth v2, USER token — the agent acts AS THE USER)
|
|
618
|
+
// is registered and
|
|
618
619
|
// SLACK_OAUTH_CLIENT_ID/SECRET/REDIRECT_URI are in Secret Manager
|
|
619
620
|
// (prod+dev). The backend SlackOAuthProvider is config-gated (503 if env
|
|
620
621
|
// unset) so this is safe even mid-rollout before the secrets mount.
|
|
621
622
|
enabled: true,
|
|
622
623
|
auth: {
|
|
623
624
|
kind: "oauth_redirect",
|
|
624
|
-
// Slack
|
|
625
|
-
// groups, DMs: list/read history, post messages, react
|
|
626
|
-
//
|
|
627
|
-
//
|
|
628
|
-
//
|
|
629
|
-
//
|
|
625
|
+
// Slack USER Token Scopes (OAuth v2). Read + write across channels,
|
|
626
|
+
// groups, DMs: list/read history, post messages, react — all AS THE USER.
|
|
627
|
+
// The backend provider requests these under `user_scope` (comma-separated)
|
|
628
|
+
// and stores the authed_user `xoxp-…` token, so the agent sees everything
|
|
629
|
+
// the user sees (no bot needs to be invited to channels). ⚠️ Changing
|
|
630
|
+
// these requires the user to RE-AUTHORIZE the Slack app.
|
|
630
631
|
scopes: [
|
|
631
632
|
"channels:read",
|
|
632
633
|
"channels:history",
|
|
@@ -639,15 +640,18 @@ var INTEGRATION_REGISTRY = {
|
|
|
639
640
|
"im:read",
|
|
640
641
|
"im:history",
|
|
641
642
|
"mpim:read",
|
|
642
|
-
"mpim:history"
|
|
643
|
+
"mpim:history",
|
|
644
|
+
// Message search across the user's channels/DMs (a user-only scope).
|
|
645
|
+
"search:read"
|
|
643
646
|
]
|
|
644
647
|
},
|
|
645
648
|
delivery: {
|
|
646
649
|
mcp: {
|
|
647
650
|
// Slack's official reference MCP server (Node). BYO-token headless: the
|
|
648
|
-
// OAuth v2
|
|
649
|
-
//
|
|
650
|
-
//
|
|
651
|
+
// OAuth v2 USER token (xoxp-…) is fed via SLACK_BOT_TOKEN (the server's
|
|
652
|
+
// env var name — it sends whatever token as `Authorization: Bearer`, and
|
|
653
|
+
// Slack's Web API accepts a user token there) and the team id via
|
|
654
|
+
// SLACK_TEAM_ID (env only, never argv). Version PINNED; bump only after
|
|
651
655
|
// re-verifying headless. Tools: list_channels, post_message,
|
|
652
656
|
// reply_to_thread, add_reaction, get_channel_history,
|
|
653
657
|
// get_thread_replies, get_users, get_user_profile (read + write).
|
|
@@ -5887,7 +5891,7 @@ function readAnonId() {
|
|
|
5887
5891
|
}
|
|
5888
5892
|
function superProperties() {
|
|
5889
5893
|
return {
|
|
5890
|
-
cliVersion: true ? "2.60.
|
|
5894
|
+
cliVersion: true ? "2.60.65" : "0.0.0-dev",
|
|
5891
5895
|
nodeVersion: process.version,
|
|
5892
5896
|
platform: process.platform,
|
|
5893
5897
|
arch: process.arch,
|
|
@@ -6068,7 +6072,7 @@ var os4 = __toESM(require("os"));
|
|
|
6068
6072
|
// package.json
|
|
6069
6073
|
var package_default = {
|
|
6070
6074
|
name: "codeam-cli",
|
|
6071
|
-
version: "2.60.
|
|
6075
|
+
version: "2.60.65",
|
|
6072
6076
|
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.",
|
|
6073
6077
|
type: "commonjs",
|
|
6074
6078
|
main: "dist/index.js",
|
|
@@ -6836,7 +6840,7 @@ function httpStatusOf(err) {
|
|
|
6836
6840
|
var API_BASE2 = resolveApiBaseUrl();
|
|
6837
6841
|
var SSE_LIVENESS_TIMEOUT_MS = 45e3;
|
|
6838
6842
|
var SSE_WATCHDOG_INTERVAL_MS = 1e4;
|
|
6839
|
-
var CommandRelayService = class {
|
|
6843
|
+
var CommandRelayService = class _CommandRelayService {
|
|
6840
6844
|
constructor(pluginId, onCommand, agentMeta, agentsOverride) {
|
|
6841
6845
|
this.pluginId = pluginId;
|
|
6842
6846
|
this.onCommand = onCommand;
|
|
@@ -6858,6 +6862,16 @@ var CommandRelayService = class {
|
|
|
6858
6862
|
agentsRegistered = false;
|
|
6859
6863
|
/** SSE connection (null when on the polling fallback or stopped). */
|
|
6860
6864
|
sseRequest = null;
|
|
6865
|
+
// At-least-once delivery: the backend now delivers commands NON-DESTRUCTIVELY
|
|
6866
|
+
// (peek) when we advertise `X-Codeam-Cmd-Ack: 1`, and drains the queue only
|
|
6867
|
+
// when we ack the ids. So a command can never be lost to a ghost/racing SSE
|
|
6868
|
+
// subscriber during codespace boot (the 2026-07-15 first-prompt loss). The
|
|
6869
|
+
// trade-off is possible REDELIVERY (reconnect, publish re-fire, ghost race),
|
|
6870
|
+
// so we dedupe by id here — a bounded FIFO set of ids we've already
|
|
6871
|
+
// dispatched. Cap keeps memory flat over a long session; the oldest ids are
|
|
6872
|
+
// evicted (a command that old is long gone from the server queue anyway).
|
|
6873
|
+
processedIds = /* @__PURE__ */ new Set();
|
|
6874
|
+
static PROCESSED_ID_CAP = 1e3;
|
|
6861
6875
|
/** Polling backoff state (only used on the fallback). */
|
|
6862
6876
|
pollTimer = null;
|
|
6863
6877
|
pollFailures = 0;
|
|
@@ -7127,14 +7141,15 @@ var CommandRelayService = class {
|
|
|
7127
7141
|
// as X-Plugin-Poll-Secret. Empty {} for legacy sessions / older
|
|
7128
7142
|
// backends (which ignore it).
|
|
7129
7143
|
pollSecretHeader() {
|
|
7144
|
+
const headers = { "X-Codeam-Cmd-Ack": "1" };
|
|
7130
7145
|
try {
|
|
7131
7146
|
const secret = loadCliConfig().sessions.find(
|
|
7132
7147
|
(s) => s.pluginId === this.pluginId
|
|
7133
7148
|
)?.pollSecret;
|
|
7134
|
-
|
|
7149
|
+
if (secret) headers["X-Plugin-Poll-Secret"] = secret;
|
|
7135
7150
|
} catch {
|
|
7136
|
-
return {};
|
|
7137
7151
|
}
|
|
7152
|
+
return headers;
|
|
7138
7153
|
}
|
|
7139
7154
|
async pollOnce() {
|
|
7140
7155
|
try {
|
|
@@ -7157,7 +7172,13 @@ var CommandRelayService = class {
|
|
|
7157
7172
|
}
|
|
7158
7173
|
}
|
|
7159
7174
|
async dispatchCommands(commands) {
|
|
7175
|
+
this.ackCommands(commands.map((c2) => c2.id));
|
|
7160
7176
|
for (const cmd of commands) {
|
|
7177
|
+
if (cmd.id && this.processedIds.has(cmd.id)) {
|
|
7178
|
+
log.trace("relay", `dedupe skip already-dispatched id=${cmd.id}`);
|
|
7179
|
+
continue;
|
|
7180
|
+
}
|
|
7181
|
+
if (cmd.id) this.rememberProcessed(cmd.id);
|
|
7161
7182
|
try {
|
|
7162
7183
|
log.trace("relay", `dispatch type=${cmd.type} id=${cmd.id}`);
|
|
7163
7184
|
await this.onCommand(cmd);
|
|
@@ -7166,6 +7187,23 @@ var CommandRelayService = class {
|
|
|
7166
7187
|
}
|
|
7167
7188
|
}
|
|
7168
7189
|
}
|
|
7190
|
+
/** Record a dispatched id, evicting the oldest when over the cap (FIFO). */
|
|
7191
|
+
rememberProcessed(id) {
|
|
7192
|
+
this.processedIds.add(id);
|
|
7193
|
+
if (this.processedIds.size > _CommandRelayService.PROCESSED_ID_CAP) {
|
|
7194
|
+
const oldest = this.processedIds.values().next().value;
|
|
7195
|
+
if (oldest !== void 0) this.processedIds.delete(oldest);
|
|
7196
|
+
}
|
|
7197
|
+
}
|
|
7198
|
+
/** Confirm receipt of command ids so the backend removes them from the queue
|
|
7199
|
+
* (the at-least-once delivery guarantee). Best-effort — never throws. */
|
|
7200
|
+
ackCommands(ids) {
|
|
7201
|
+
const commandIds = ids.filter((id) => typeof id === "string" && id.length > 0);
|
|
7202
|
+
if (commandIds.length === 0) return;
|
|
7203
|
+
void _postJson(`${API_BASE2}/api/commands/ack`, { pluginId: this.pluginId, commandIds }, {
|
|
7204
|
+
...this.pollSecretHeader()
|
|
7205
|
+
}).catch((err) => log.trace("relay", "ack post failed (will redeliver+dedupe)", err));
|
|
7206
|
+
}
|
|
7169
7207
|
// ─── Heartbeat + agents ──────────────────────────────────────────
|
|
7170
7208
|
async sendHeartbeat(online) {
|
|
7171
7209
|
await _postJson(`${API_BASE2}/api/plugin/heartbeat`, {
|
|
@@ -7177,7 +7215,7 @@ var CommandRelayService = class {
|
|
|
7177
7215
|
// fresh + clear the "CLI update available" banner after a self-update
|
|
7178
7216
|
// (a codespace that reinstalls @latest reconnects via heartbeat, not
|
|
7179
7217
|
// pair/reconnect). Older backends ignore the extra field.
|
|
7180
|
-
..."2.60.
|
|
7218
|
+
..."2.60.65" ? { ideVersion: "2.60.65" } : {}
|
|
7181
7219
|
}).then(() => log.trace("relay", `heartbeat ok online=${online}`)).catch((err) => log.trace("relay", `heartbeat failed online=${online}`, err));
|
|
7182
7220
|
}
|
|
7183
7221
|
/**
|
|
@@ -17754,7 +17792,7 @@ async function autoUpgradeBeforeCriticalCommand() {
|
|
|
17754
17792
|
if (process.env.NODE_ENV === "test") return;
|
|
17755
17793
|
if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
|
|
17756
17794
|
if (process.env.CI) return;
|
|
17757
|
-
const current = true ? "2.60.
|
|
17795
|
+
const current = true ? "2.60.65" : null;
|
|
17758
17796
|
if (!current) return;
|
|
17759
17797
|
const cache = readCache();
|
|
17760
17798
|
const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
|
|
@@ -17771,7 +17809,7 @@ function checkForUpdates() {
|
|
|
17771
17809
|
if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
|
|
17772
17810
|
if (process.env.CI) return;
|
|
17773
17811
|
if (!process.stdout.isTTY) return;
|
|
17774
|
-
const current = true ? "2.60.
|
|
17812
|
+
const current = true ? "2.60.65" : null;
|
|
17775
17813
|
if (!current) return;
|
|
17776
17814
|
const cache = readCache();
|
|
17777
17815
|
const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
|
|
@@ -17791,7 +17829,7 @@ var SELF_UPDATE_INTERVAL_MS = 60 * 60 * 1e3;
|
|
|
17791
17829
|
var SELF_UPDATE_VIEW_TIMEOUT_MS = 3e4;
|
|
17792
17830
|
var SELF_UPDATE_INSTALL_TIMEOUT_MS = 18e4;
|
|
17793
17831
|
function currentCliVersion() {
|
|
17794
|
-
return true ? "2.60.
|
|
17832
|
+
return true ? "2.60.65" : null;
|
|
17795
17833
|
}
|
|
17796
17834
|
function runCmd(cmd, args2, timeoutMs) {
|
|
17797
17835
|
return new Promise((resolve7) => {
|
|
@@ -35220,7 +35258,7 @@ function checkChokidar() {
|
|
|
35220
35258
|
}
|
|
35221
35259
|
async function doctor(args2 = []) {
|
|
35222
35260
|
const json = args2.includes("--json");
|
|
35223
|
-
const cliVersion = true ? "2.60.
|
|
35261
|
+
const cliVersion = true ? "2.60.65" : "0.0.0-dev";
|
|
35224
35262
|
const apiBase2 = resolveApiBaseUrl();
|
|
35225
35263
|
const diagnosticId = (0, import_node_crypto12.randomUUID)();
|
|
35226
35264
|
log.info("doctor", `run id=${diagnosticId} cli=${cliVersion}`);
|
|
@@ -35697,7 +35735,7 @@ async function mcpRun(args2) {
|
|
|
35697
35735
|
// src/commands/version.ts
|
|
35698
35736
|
var import_picocolors15 = __toESM(require("picocolors"));
|
|
35699
35737
|
function version2() {
|
|
35700
|
-
const v = true ? "2.60.
|
|
35738
|
+
const v = true ? "2.60.65" : "unknown";
|
|
35701
35739
|
console.log(`${import_picocolors15.default.bold("codeam-cli")} ${import_picocolors15.default.cyan(v)}`);
|
|
35702
35740
|
}
|
|
35703
35741
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "codeam-cli",
|
|
3
|
-
"version": "2.60.
|
|
3
|
+
"version": "2.60.65",
|
|
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",
|