codeam-cli 2.74.13 → 2.75.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 +37 -0
- package/dist/index.js +207 -86
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,43 @@ 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.74.14] — 2026-09-11
|
|
8
|
+
|
|
9
|
+
### Fixed
|
|
10
|
+
|
|
11
|
+
- **cli:** Stop dropping short ACP text deltas that are a prefix of the reply (#748)
|
|
12
|
+
- **cli:** Resolve select_option by optionId, stop adding `from` as an index offset (#749)
|
|
13
|
+
|
|
14
|
+
## [2.74.13] — 2026-09-10
|
|
15
|
+
|
|
16
|
+
### Added
|
|
17
|
+
|
|
18
|
+
- **cli:** Open the command stream on the stream host with a one-time api-host fallback (#745)
|
|
19
|
+
|
|
20
|
+
### Build
|
|
21
|
+
|
|
22
|
+
- **deps:** Bump gradle-wrapper in /apps/jetbrains-plugin (#661)
|
|
23
|
+
- **deps:** Bump com.squareup.okhttp3:okhttp in /apps/jetbrains-plugin (#641)
|
|
24
|
+
- **deps:** Bump actions/setup-java from 5 to 6 (#662)
|
|
25
|
+
|
|
26
|
+
### CI
|
|
27
|
+
|
|
28
|
+
- **workflow:** Root the npm Dependabot config at the workspace, so its PRs can actually install (#737)
|
|
29
|
+
|
|
30
|
+
### Chore
|
|
31
|
+
|
|
32
|
+
- **deps:** Bump org.jetbrains.kotlin.jvm in /apps/jetbrains-plugin (#743)
|
|
33
|
+
- **deps:** Bump docker/setup-buildx-action from 3 to 4 (#414)
|
|
34
|
+
- **deps:** Bump actions/checkout from 4 to 7 (#366)
|
|
35
|
+
- **deps:** Bump ws from 8.21.0 to 8.21.3 (#740)
|
|
36
|
+
- **deps:** Bump posthog-node from 5.35.1 to 5.51.6 (#741)
|
|
37
|
+
- **deps-dev:** Bump knip from 6.25.0 to 6.34.0 (#742)
|
|
38
|
+
|
|
39
|
+
### Fixed
|
|
40
|
+
|
|
41
|
+
- **cli:** Local baton sessions go silent on mobile after the mirror's 10-min startup wait (#744)
|
|
42
|
+
- **vsc-plugin:** Stop advertising a Copilot agent the plugin cannot dispatch to (#746)
|
|
43
|
+
|
|
7
44
|
## [2.74.12] — 2026-09-09
|
|
8
45
|
|
|
9
46
|
### Fixed
|
package/dist/index.js
CHANGED
|
@@ -950,6 +950,38 @@ function isKnownAgentId(id) {
|
|
|
950
950
|
var HOUSE_AGENT_ID = "house-codeagent-cloud";
|
|
951
951
|
var HOUSE_AGENT_NAME = "CodeAgent Cloud";
|
|
952
952
|
var HOUSE_AGENT_SUBTITLE = "Included \u2014 no setup";
|
|
953
|
+
var MANAGED_PROVIDER_IDS = [
|
|
954
|
+
"managed-deepseek",
|
|
955
|
+
"managed-deepseek-flash",
|
|
956
|
+
"managed-qwen-coder",
|
|
957
|
+
"managed-codex",
|
|
958
|
+
"managed-claude"
|
|
959
|
+
];
|
|
960
|
+
function isManagedProviderId(value) {
|
|
961
|
+
return typeof value === "string" && MANAGED_PROVIDER_IDS.includes(value);
|
|
962
|
+
}
|
|
963
|
+
var MANAGED_PROVIDER_DISPLAY_NAMES = {
|
|
964
|
+
"managed-deepseek": "DeepSeek V4",
|
|
965
|
+
"managed-deepseek-flash": "DeepSeek V4 Flash",
|
|
966
|
+
"managed-qwen-coder": "Qwen3 Coder",
|
|
967
|
+
"managed-codex": "Codex",
|
|
968
|
+
"managed-claude": "Claude"
|
|
969
|
+
};
|
|
970
|
+
var MANAGED_AGENT_SUBTITLE = "Prepaid usage credits";
|
|
971
|
+
var MANAGED_AGENT_ENV = "CODEAM_MANAGED_AGENT_ID";
|
|
972
|
+
var LINKED_AGENT_IDS = [
|
|
973
|
+
"claude_code",
|
|
974
|
+
"codex",
|
|
975
|
+
"cursor",
|
|
976
|
+
"aider",
|
|
977
|
+
"coderabbit",
|
|
978
|
+
"gemini",
|
|
979
|
+
"kimi",
|
|
980
|
+
"openrouter",
|
|
981
|
+
"opencode",
|
|
982
|
+
HOUSE_AGENT_ID,
|
|
983
|
+
...MANAGED_PROVIDER_IDS
|
|
984
|
+
];
|
|
953
985
|
var PUBLIC_TO_INTERNAL = {
|
|
954
986
|
claude_code: "claude",
|
|
955
987
|
// CLI-side extra: self-hosted deploy payloads may carry the internal id.
|
|
@@ -976,7 +1008,13 @@ var PUBLIC_TO_INTERNAL = {
|
|
|
976
1008
|
openrouter: "claude",
|
|
977
1009
|
// The house agent runs Claude Code under the hood (pointed at the
|
|
978
1010
|
// MiniMax proxy). Its internal runtime is therefore `claude`.
|
|
979
|
-
[HOUSE_AGENT_ID]: "claude"
|
|
1011
|
+
[HOUSE_AGENT_ID]: "claude",
|
|
1012
|
+
// Every managed provider runs Claude Code against our proxy too.
|
|
1013
|
+
"managed-deepseek": "claude",
|
|
1014
|
+
"managed-deepseek-flash": "claude",
|
|
1015
|
+
"managed-qwen-coder": "claude",
|
|
1016
|
+
"managed-codex": "claude",
|
|
1017
|
+
"managed-claude": "claude"
|
|
980
1018
|
};
|
|
981
1019
|
function isPublicToInternalKey(v) {
|
|
982
1020
|
return Object.prototype.hasOwnProperty.call(PUBLIC_TO_INTERNAL, v);
|
|
@@ -10199,7 +10237,7 @@ function readAnonId() {
|
|
|
10199
10237
|
}
|
|
10200
10238
|
function superProperties() {
|
|
10201
10239
|
return {
|
|
10202
|
-
cliVersion: true ? "2.
|
|
10240
|
+
cliVersion: true ? "2.75.0" : "0.0.0-dev",
|
|
10203
10241
|
nodeVersion: process.version,
|
|
10204
10242
|
platform: process.platform,
|
|
10205
10243
|
arch: process.arch,
|
|
@@ -10441,7 +10479,7 @@ var http = __toESM(require("http"));
|
|
|
10441
10479
|
// package.json
|
|
10442
10480
|
var package_default = {
|
|
10443
10481
|
name: "codeam-cli",
|
|
10444
|
-
version: "2.
|
|
10482
|
+
version: "2.75.0",
|
|
10445
10483
|
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.",
|
|
10446
10484
|
type: "commonjs",
|
|
10447
10485
|
main: "dist/index.js",
|
|
@@ -10875,6 +10913,7 @@ async function fetchProvisionCredentialDetailed(input) {
|
|
|
10875
10913
|
method: data.method,
|
|
10876
10914
|
credential: data.credential,
|
|
10877
10915
|
...typeof data.baseUrl === "string" && data.baseUrl.length > 0 ? { baseUrl: data.baseUrl } : {},
|
|
10916
|
+
...typeof data.model === "string" && data.model.length > 0 ? { model: data.model } : {},
|
|
10878
10917
|
...typeof data.installScript === "string" && data.installScript.length > 0 ? { installScript: data.installScript } : {}
|
|
10879
10918
|
};
|
|
10880
10919
|
}
|
|
@@ -12131,7 +12170,7 @@ var CommandRelayService = class _CommandRelayService {
|
|
|
12131
12170
|
// fresh + clear the "CLI update available" banner after a self-update
|
|
12132
12171
|
// (a codespace that reinstalls @latest reconnects via heartbeat, not
|
|
12133
12172
|
// pair/reconnect). Older backends ignore the extra field.
|
|
12134
|
-
..."2.
|
|
12173
|
+
..."2.75.0" ? { ideVersion: "2.75.0" } : {}
|
|
12135
12174
|
}).then(() => log.trace("relay", `heartbeat ok online=${online}`)).catch((err) => log.trace("relay", `heartbeat failed online=${online}`, err));
|
|
12136
12175
|
}
|
|
12137
12176
|
/**
|
|
@@ -24210,7 +24249,9 @@ function readHouseProxyChildEnv() {
|
|
|
24210
24249
|
baseUrl: o.baseUrl,
|
|
24211
24250
|
token: o.token,
|
|
24212
24251
|
openRouter: o.openRouter === true,
|
|
24213
|
-
...typeof o.claudeConfigDir === "string" && o.claudeConfigDir ? { claudeConfigDir: o.claudeConfigDir } : {}
|
|
24252
|
+
...typeof o.claudeConfigDir === "string" && o.claudeConfigDir ? { claudeConfigDir: o.claudeConfigDir } : {},
|
|
24253
|
+
...typeof o.model === "string" && o.model ? { model: o.model } : {},
|
|
24254
|
+
...typeof o.managedAgentId === "string" && o.managedAgentId ? { managedAgentId: o.managedAgentId } : {}
|
|
24214
24255
|
});
|
|
24215
24256
|
} catch {
|
|
24216
24257
|
return {};
|
|
@@ -24250,16 +24291,24 @@ function buildHouseProxyChildEnv(cfg) {
|
|
|
24250
24291
|
if (cfg.openRouter === true) {
|
|
24251
24292
|
env.ANTHROPIC_API_KEY = "";
|
|
24252
24293
|
} else {
|
|
24253
|
-
|
|
24254
|
-
env.
|
|
24255
|
-
env.
|
|
24256
|
-
env.
|
|
24294
|
+
const model = typeof cfg.model === "string" && cfg.model ? cfg.model : "MiniMax-M3";
|
|
24295
|
+
env.ANTHROPIC_MODEL = model;
|
|
24296
|
+
env.ANTHROPIC_DEFAULT_SONNET_MODEL = model;
|
|
24297
|
+
env.ANTHROPIC_DEFAULT_OPUS_MODEL = model;
|
|
24298
|
+
env.ANTHROPIC_DEFAULT_HAIKU_MODEL = model;
|
|
24257
24299
|
}
|
|
24258
24300
|
if (typeof cfg.claudeConfigDir === "string" && cfg.claudeConfigDir) {
|
|
24259
24301
|
env.CLAUDE_CONFIG_DIR = cfg.claudeConfigDir;
|
|
24260
24302
|
}
|
|
24303
|
+
if (isManagedProviderId(cfg.managedAgentId)) {
|
|
24304
|
+
env[MANAGED_AGENT_ENV] = cfg.managedAgentId;
|
|
24305
|
+
}
|
|
24261
24306
|
return env;
|
|
24262
24307
|
}
|
|
24308
|
+
function houseRailWireId(env) {
|
|
24309
|
+
const managed = env[MANAGED_AGENT_ENV];
|
|
24310
|
+
return isManagedProviderId(managed) ? managed : HOUSE_AGENT_ID;
|
|
24311
|
+
}
|
|
24263
24312
|
var HOUSE_PROXY_ENV_KEYS = [
|
|
24264
24313
|
"ANTHROPIC_BASE_URL",
|
|
24265
24314
|
"ANTHROPIC_AUTH_TOKEN",
|
|
@@ -24271,7 +24320,8 @@ var HOUSE_PROXY_ENV_KEYS = [
|
|
|
24271
24320
|
"CLAUDE_CODE_AUTO_COMPACT_WINDOW",
|
|
24272
24321
|
"CLAUDE_CODE_MAX_CONTEXT_TOKENS",
|
|
24273
24322
|
"API_TIMEOUT_MS",
|
|
24274
|
-
"CLAUDE_CONFIG_DIR"
|
|
24323
|
+
"CLAUDE_CONFIG_DIR",
|
|
24324
|
+
MANAGED_AGENT_ENV
|
|
24275
24325
|
];
|
|
24276
24326
|
function clearHouseProxyEnvOverrides() {
|
|
24277
24327
|
const out2 = {};
|
|
@@ -24451,7 +24501,7 @@ async function autoUpgradeBeforeCriticalCommand() {
|
|
|
24451
24501
|
if (process.env.NODE_ENV === "test") return;
|
|
24452
24502
|
if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
|
|
24453
24503
|
if (process.env.CI) return;
|
|
24454
|
-
const current2 = true ? "2.
|
|
24504
|
+
const current2 = true ? "2.75.0" : null;
|
|
24455
24505
|
if (!current2) return;
|
|
24456
24506
|
const cache = readCache();
|
|
24457
24507
|
const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
|
|
@@ -24468,7 +24518,7 @@ function checkForUpdates() {
|
|
|
24468
24518
|
if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
|
|
24469
24519
|
if (process.env.CI) return;
|
|
24470
24520
|
if (!process.stdout.isTTY) return;
|
|
24471
|
-
const current2 = true ? "2.
|
|
24521
|
+
const current2 = true ? "2.75.0" : null;
|
|
24472
24522
|
if (!current2) return;
|
|
24473
24523
|
const cache = readCache();
|
|
24474
24524
|
const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
|
|
@@ -24491,7 +24541,7 @@ var SELF_UPDATE_INSTALL_TIMEOUT_MS = 18e4;
|
|
|
24491
24541
|
var SELF_UPDATE_LS_TIMEOUT_MS = 15e3;
|
|
24492
24542
|
var SUDO_PREFLIGHT_TIMEOUT_MS = 5e3;
|
|
24493
24543
|
function currentCliVersion() {
|
|
24494
|
-
return true ? "2.
|
|
24544
|
+
return true ? "2.75.0" : null;
|
|
24495
24545
|
}
|
|
24496
24546
|
async function installedVersion(deps) {
|
|
24497
24547
|
const ls = await deps.run(
|
|
@@ -39210,18 +39260,25 @@ var NON_SWITCHABLE = /* @__PURE__ */ new Set([
|
|
|
39210
39260
|
]);
|
|
39211
39261
|
function displayName(id) {
|
|
39212
39262
|
if (id === HOUSE_AGENT_ID) return HOUSE_AGENT_NAME;
|
|
39263
|
+
if (isManagedProviderId(id)) return MANAGED_PROVIDER_DISPLAY_NAMES[id];
|
|
39213
39264
|
return isKnownAgentId(id) ? AGENT_REGISTRY[id]?.displayName ?? id : id;
|
|
39214
39265
|
}
|
|
39215
39266
|
function credentialFailureMessage(agentId, failure) {
|
|
39216
39267
|
if (failure.message) return failure.message;
|
|
39217
39268
|
return `No linked credential for ${displayName(agentId)}. Link it in Profile \u203A Agents first.`;
|
|
39218
39269
|
}
|
|
39219
|
-
function resolveSwitchTarget(raw, currentAgent, currentIsHouse = false) {
|
|
39270
|
+
function resolveSwitchTarget(raw, currentAgent, currentIsHouse = false, currentHouseWireId = HOUSE_AGENT_ID) {
|
|
39220
39271
|
if (typeof raw !== "string" || raw.length === 0) {
|
|
39221
39272
|
return { ok: false, error: "switch_agent: missing agentId" };
|
|
39222
39273
|
}
|
|
39274
|
+
if (isManagedProviderId(raw)) {
|
|
39275
|
+
if (currentIsHouse && currentHouseWireId === raw) {
|
|
39276
|
+
return { ok: false, error: `${displayName(raw)} is already this session's agent.` };
|
|
39277
|
+
}
|
|
39278
|
+
return { ok: true, agentId: "claude", wireId: raw, house: true };
|
|
39279
|
+
}
|
|
39223
39280
|
if (raw === HOUSE_AGENT_ID) {
|
|
39224
|
-
if (currentIsHouse) {
|
|
39281
|
+
if (currentIsHouse && currentHouseWireId === HOUSE_AGENT_ID) {
|
|
39225
39282
|
return { ok: false, error: `${HOUSE_AGENT_NAME} is already this session's agent.` };
|
|
39226
39283
|
}
|
|
39227
39284
|
return { ok: true, agentId: "claude", wireId: HOUSE_AGENT_ID, house: true };
|
|
@@ -39317,7 +39374,8 @@ function makeSerializedSwitchEmitter(post2) {
|
|
|
39317
39374
|
async function performAgentSwitch(deps, rawAgentId, fastPath = {}) {
|
|
39318
39375
|
const from = deps.currentAgent();
|
|
39319
39376
|
const fromIsHouse = deps.currentIsHouse();
|
|
39320
|
-
const
|
|
39377
|
+
const fromHouseWireId = deps.currentHouseWireId?.() ?? HOUSE_AGENT_ID;
|
|
39378
|
+
const target = resolveSwitchTarget(rawAgentId, from, fromIsHouse, fromHouseWireId);
|
|
39321
39379
|
if (!target.ok) {
|
|
39322
39380
|
return {
|
|
39323
39381
|
ok: false,
|
|
@@ -39327,7 +39385,7 @@ async function performAgentSwitch(deps, rawAgentId, fastPath = {}) {
|
|
|
39327
39385
|
}
|
|
39328
39386
|
const agentId = target.agentId;
|
|
39329
39387
|
const wireId = target.wireId;
|
|
39330
|
-
const fromWireId = fromIsHouse ?
|
|
39388
|
+
const fromWireId = fromIsHouse ? fromHouseWireId : from;
|
|
39331
39389
|
const targetName = displayName(wireId);
|
|
39332
39390
|
const emitStatus = (status2) => deps.postEvent("switch_agent_status", { ...status2 });
|
|
39333
39391
|
const emitStep = (step) => deps.postEvent("switch_agent_progress", { step, agentId: wireId });
|
|
@@ -39350,7 +39408,12 @@ async function performAgentSwitch(deps, rawAgentId, fastPath = {}) {
|
|
|
39350
39408
|
return fail2(`${targetName} isn't available on this backend yet.`);
|
|
39351
39409
|
}
|
|
39352
39410
|
try {
|
|
39353
|
-
deps.provisionHouseProxy({
|
|
39411
|
+
deps.provisionHouseProxy({
|
|
39412
|
+
baseUrl: cred.baseUrl,
|
|
39413
|
+
token: cred.credential,
|
|
39414
|
+
...cred.model ? { model: cred.model } : {},
|
|
39415
|
+
...isManagedProviderId(wireId) ? { managedAgentId: wireId } : {}
|
|
39416
|
+
});
|
|
39354
39417
|
} catch (err) {
|
|
39355
39418
|
log.warn("switchAgent", `house proxy provisioning failed: ${err.message}`);
|
|
39356
39419
|
return fail2(`Couldn't configure ${targetName} on this machine.`);
|
|
@@ -39377,11 +39440,17 @@ async function performAgentSwitch(deps, rawAgentId, fastPath = {}) {
|
|
|
39377
39440
|
}
|
|
39378
39441
|
void emitStep("restart");
|
|
39379
39442
|
try {
|
|
39380
|
-
await deps.swapRuntime(agentId, {
|
|
39443
|
+
await deps.swapRuntime(agentId, {
|
|
39444
|
+
house: target.house,
|
|
39445
|
+
...isManagedProviderId(wireId) ? { wireId } : {}
|
|
39446
|
+
});
|
|
39381
39447
|
} catch (err) {
|
|
39382
39448
|
log.warn("switchAgent", `swap failed, reverting to ${fromWireId}: ${err.message}`);
|
|
39383
39449
|
try {
|
|
39384
|
-
await deps.revertRuntime(from, {
|
|
39450
|
+
await deps.revertRuntime(from, {
|
|
39451
|
+
house: fromIsHouse,
|
|
39452
|
+
...fromIsHouse && isManagedProviderId(fromHouseWireId) ? { wireId: fromHouseWireId } : {}
|
|
39453
|
+
});
|
|
39385
39454
|
} catch (revertErr) {
|
|
39386
39455
|
log.warn("switchAgent", `revert failed: ${revertErr.message}`);
|
|
39387
39456
|
return fail2(
|
|
@@ -39845,13 +39914,17 @@ function createWakeCredentialProbe(deps) {
|
|
|
39845
39914
|
function reconcileCumulative(existing, incoming) {
|
|
39846
39915
|
if (incoming.length === 0) return existing;
|
|
39847
39916
|
if (incoming.startsWith(existing)) return incoming;
|
|
39848
|
-
if (existing.startsWith(incoming)) return existing;
|
|
39849
39917
|
const shared = commonPrefixLength(existing, incoming);
|
|
39850
|
-
if (
|
|
39918
|
+
if (looksLikeSnapshot(existing, incoming, shared)) {
|
|
39919
|
+
if (shared === incoming.length) return existing;
|
|
39851
39920
|
return existing.slice(0, shared) + incoming.slice(shared);
|
|
39852
39921
|
}
|
|
39853
39922
|
return existing + incoming;
|
|
39854
39923
|
}
|
|
39924
|
+
var MIN_SNAPSHOT_PREFIX = 8;
|
|
39925
|
+
function looksLikeSnapshot(existing, incoming, shared) {
|
|
39926
|
+
return shared >= MIN_SNAPSHOT_PREFIX && shared * 2 >= existing.length && incoming.length * 2 >= existing.length;
|
|
39927
|
+
}
|
|
39855
39928
|
function commonPrefixLength(a, b) {
|
|
39856
39929
|
const max = Math.min(a.length, b.length);
|
|
39857
39930
|
let i = 0;
|
|
@@ -40262,25 +40335,19 @@ function mapSessionUpdate(notification) {
|
|
|
40262
40335
|
}
|
|
40263
40336
|
}
|
|
40264
40337
|
function mapPermissionRequest(request2) {
|
|
40265
|
-
const prompt =
|
|
40266
|
-
const
|
|
40267
|
-
|
|
40268
|
-
|
|
40269
|
-
|
|
40270
|
-
|
|
40271
|
-
if (label in optionIdByLabel) continue;
|
|
40272
|
-
optionIdByLabel[label] = opt.optionId;
|
|
40273
|
-
kindByLabel[label] = opt.kind;
|
|
40274
|
-
labels.push(label);
|
|
40275
|
-
}
|
|
40338
|
+
const prompt = describePermissionToolCall(request2.toolCall) ?? "The agent requested permission to continue.";
|
|
40339
|
+
const options = request2.options.map((opt) => ({
|
|
40340
|
+
label: opt.name?.trim() || humanizeKind(opt.kind),
|
|
40341
|
+
optionId: opt.optionId,
|
|
40342
|
+
kind: opt.kind
|
|
40343
|
+
}));
|
|
40276
40344
|
return {
|
|
40277
40345
|
event: {
|
|
40278
40346
|
questionId: (0, import_node_crypto10.randomUUID)(),
|
|
40279
40347
|
prompt,
|
|
40280
|
-
options:
|
|
40348
|
+
options: options.length > 0 ? options.map((o) => ({ label: o.label, value: o.optionId })) : void 0
|
|
40281
40349
|
},
|
|
40282
|
-
|
|
40283
|
-
kindByLabel
|
|
40350
|
+
options
|
|
40284
40351
|
};
|
|
40285
40352
|
}
|
|
40286
40353
|
function messageChunkId(messageId) {
|
|
@@ -40311,6 +40378,28 @@ function describeToolCall(call) {
|
|
|
40311
40378
|
}
|
|
40312
40379
|
return null;
|
|
40313
40380
|
}
|
|
40381
|
+
var PERMISSION_DETAIL_MAX = 400;
|
|
40382
|
+
function permissionInputDetail(rawInput) {
|
|
40383
|
+
if (!rawInput || typeof rawInput !== "object") return null;
|
|
40384
|
+
const input = rawInput;
|
|
40385
|
+
for (const key of ["command", "file_path", "path"]) {
|
|
40386
|
+
const v = input[key];
|
|
40387
|
+
if (typeof v === "string" && v.trim().length > 0) {
|
|
40388
|
+
const detail = v.trim();
|
|
40389
|
+
return detail.length > PERMISSION_DETAIL_MAX ? `${detail.slice(0, PERMISSION_DETAIL_MAX)}\u2026` : detail;
|
|
40390
|
+
}
|
|
40391
|
+
}
|
|
40392
|
+
return null;
|
|
40393
|
+
}
|
|
40394
|
+
function describePermissionToolCall(call) {
|
|
40395
|
+
const title = describeToolCall(call);
|
|
40396
|
+
const detail = permissionInputDetail(call.rawInput);
|
|
40397
|
+
if (!detail) return title;
|
|
40398
|
+
if (!title) return detail;
|
|
40399
|
+
if (title.includes(detail)) return title;
|
|
40400
|
+
return `${title}
|
|
40401
|
+
${detail}`;
|
|
40402
|
+
}
|
|
40314
40403
|
function describeToolCallUpdate(update) {
|
|
40315
40404
|
const parts = [];
|
|
40316
40405
|
if (Array.isArray(update.content)) {
|
|
@@ -40404,13 +40493,9 @@ function createOnRequestPermission(deps) {
|
|
|
40404
40493
|
}
|
|
40405
40494
|
log.warn("acpRunner", "AUTO mode \u2014 no allow option offered; falling back to interactive");
|
|
40406
40495
|
}
|
|
40407
|
-
const { event,
|
|
40496
|
+
const { event, options } = mapPermissionRequest(request2);
|
|
40408
40497
|
await deps.publisher.publishAwaitingAnswer(event);
|
|
40409
|
-
return deps.registerPermission({
|
|
40410
|
-
questionId: event.questionId,
|
|
40411
|
-
labels: event.options ?? [],
|
|
40412
|
-
optionIdByLabel
|
|
40413
|
-
});
|
|
40498
|
+
return deps.registerPermission({ questionId: event.questionId, options });
|
|
40414
40499
|
};
|
|
40415
40500
|
}
|
|
40416
40501
|
|
|
@@ -42590,9 +42675,9 @@ function rebindSessionHandles(ctx, outcome) {
|
|
|
42590
42675
|
Object.assign(ctx, outcome.handles);
|
|
42591
42676
|
return outcome;
|
|
42592
42677
|
}
|
|
42593
|
-
function namesCurrentAgent(requested, currentAgent, currentIsHouse) {
|
|
42678
|
+
function namesCurrentAgent(requested, currentAgent, currentIsHouse, currentHouseWireId = HOUSE_AGENT_ID) {
|
|
42594
42679
|
if (requested === currentAgent) return true;
|
|
42595
|
-
if (currentIsHouse) return requested ===
|
|
42680
|
+
if (currentIsHouse) return requested === currentHouseWireId;
|
|
42596
42681
|
return publicToInternal(requested) === currentAgent;
|
|
42597
42682
|
}
|
|
42598
42683
|
async function routeSquadTask(ctx, target) {
|
|
@@ -42805,7 +42890,12 @@ async function startTaskH(ctx) {
|
|
|
42805
42890
|
await relay.sendResult(cmd.id, "failed", { error: "empty prompt" });
|
|
42806
42891
|
return;
|
|
42807
42892
|
}
|
|
42808
|
-
if (requestedAgentId.length > 0 && !namesCurrentAgent(
|
|
42893
|
+
if (requestedAgentId.length > 0 && !namesCurrentAgent(
|
|
42894
|
+
requestedAgentId,
|
|
42895
|
+
opts.agent,
|
|
42896
|
+
ctx.currentIsHouse?.() ?? false,
|
|
42897
|
+
ctx.currentHouseWireId?.() ?? HOUSE_AGENT_ID
|
|
42898
|
+
)) {
|
|
42809
42899
|
const routed = await routeSquadTask(ctx, requestedAgentId);
|
|
42810
42900
|
if (!routed.ok) {
|
|
42811
42901
|
log.warn("acpRunner", `start_task routing to ${requestedAgentId} failed: ${routed.error}`);
|
|
@@ -43172,20 +43262,19 @@ async function selectOptionH(ctx) {
|
|
|
43172
43262
|
const { cmd, client: client3, relay, streaming, history, budgetRecovery } = ctx;
|
|
43173
43263
|
const payload = cmd.payload;
|
|
43174
43264
|
const index = typeof payload?.index === "number" ? payload.index : 0;
|
|
43175
|
-
const
|
|
43176
|
-
|
|
43177
|
-
|
|
43178
|
-
const result = streaming.resolveSelection(absoluteIndex);
|
|
43265
|
+
const optionId = typeof payload?.optionId === "string" && payload.optionId.length > 0 ? payload.optionId : typeof payload?.answer === "string" && payload.answer.length > 0 ? payload.answer : void 0;
|
|
43266
|
+
if (await budgetRecovery.tryRecover(cmd.id, index)) return;
|
|
43267
|
+
const result = streaming.resolveSelection(index, optionId);
|
|
43179
43268
|
switch (result.kind) {
|
|
43180
43269
|
case "resolved":
|
|
43181
|
-
log.info("acpRunner", `select_option index=${absoluteIndex} \u2192 permission resolved`);
|
|
43182
|
-
await relay.sendResult(cmd.id, "completed", {});
|
|
43183
|
-
return;
|
|
43184
|
-
case "reprompt": {
|
|
43185
43270
|
log.info(
|
|
43186
43271
|
"acpRunner",
|
|
43187
|
-
`select_option index=${
|
|
43272
|
+
`select_option index=${index} \u2192 permission resolved optionId=${result.optionId ?? "cancelled"}`
|
|
43188
43273
|
);
|
|
43274
|
+
await relay.sendResult(cmd.id, "completed", {});
|
|
43275
|
+
return;
|
|
43276
|
+
case "reprompt": {
|
|
43277
|
+
log.info("acpRunner", `select_option index=${index} \u2192 reprompt chars=${result.text.length}`);
|
|
43189
43278
|
await streaming.beginTurn();
|
|
43190
43279
|
history.appendUserPrompt(result.text);
|
|
43191
43280
|
try {
|
|
@@ -43205,7 +43294,7 @@ async function selectOptionH(ctx) {
|
|
|
43205
43294
|
case "none":
|
|
43206
43295
|
log.warn(
|
|
43207
43296
|
"acpRunner",
|
|
43208
|
-
`select_option index=${
|
|
43297
|
+
`select_option index=${index} arrived with no pending question \u2014 likely stale`
|
|
43209
43298
|
);
|
|
43210
43299
|
await relay.sendResult(cmd.id, "failed", {
|
|
43211
43300
|
error: "No pending interactive question \u2014 the prompt may have expired."
|
|
@@ -43643,9 +43732,17 @@ var StreamingState = class {
|
|
|
43643
43732
|
turnSeq = 0;
|
|
43644
43733
|
/**
|
|
43645
43734
|
* Register a permission Promise. The Promise stays pending until
|
|
43646
|
-
* `resolveSelection(
|
|
43647
|
-
*
|
|
43648
|
-
*
|
|
43735
|
+
* `resolveSelection()` is called from the relay handler, OR the
|
|
43736
|
+
* safety timer fires after PERMISSION_TIMEOUT_MS and we auto-cancel.
|
|
43737
|
+
* Caller is the SDK's `onRequestPermission`.
|
|
43738
|
+
*
|
|
43739
|
+
* The auto-cancel is NEVER silent (same HARD RULE as the auto-denies
|
|
43740
|
+
* in ./permission-gate.ts): a visible chat line says the request
|
|
43741
|
+
* expired. The adapter reports a cancel to the model as a failed tool
|
|
43742
|
+
* ("Tool use aborted"), which the model then narrates as a refusal —
|
|
43743
|
+
* replay 01a08b05 (2026-09-10): two prompts expired while the user was
|
|
43744
|
+
* in the preview, Claude told him HE had refused them twice, and he
|
|
43745
|
+
* protested "J'ai rien refusé". The line is the user's evidence.
|
|
43649
43746
|
*/
|
|
43650
43747
|
registerPermission(args2) {
|
|
43651
43748
|
return new Promise((resolve11) => {
|
|
@@ -43656,14 +43753,18 @@ var StreamingState = class {
|
|
|
43656
43753
|
`permission ${args2.questionId.slice(0, 8)} TTL expired \u2014 auto-cancel`
|
|
43657
43754
|
);
|
|
43658
43755
|
this.pending = null;
|
|
43756
|
+
void this.publisher.publishOutput({
|
|
43757
|
+
type: "text",
|
|
43758
|
+
content: permissionExpiredNotice(),
|
|
43759
|
+
done: true
|
|
43760
|
+
});
|
|
43659
43761
|
resolve11({ outcome: { outcome: "cancelled" } });
|
|
43660
43762
|
}
|
|
43661
43763
|
}, PERMISSION_TIMEOUT_MS);
|
|
43662
43764
|
this.pending = {
|
|
43663
43765
|
kind: "permission",
|
|
43664
43766
|
questionId: args2.questionId,
|
|
43665
|
-
|
|
43666
|
-
optionIdByLabel: args2.optionIdByLabel,
|
|
43767
|
+
options: args2.options,
|
|
43667
43768
|
resolve: resolve11,
|
|
43668
43769
|
timeoutTimer
|
|
43669
43770
|
};
|
|
@@ -43683,28 +43784,33 @@ var StreamingState = class {
|
|
|
43683
43784
|
* routing instruction the runner uses to drive the next ACP RPC:
|
|
43684
43785
|
*
|
|
43685
43786
|
* - 'resolved' — permission Promise resolved; SDK is unblocked
|
|
43686
|
-
* and the runner just acks the relay command.
|
|
43787
|
+
* and the runner just acks the relay command. `optionId` is
|
|
43788
|
+
* what was answered (null = cancelled).
|
|
43687
43789
|
* - 'reprompt' — free-form selection; the runner must call
|
|
43688
43790
|
* `client.prompt(text)` with the returned text to send the
|
|
43689
43791
|
* user's pick to the adapter as a new turn.
|
|
43690
43792
|
* - 'none' — nothing pending; the runner acks the command as
|
|
43691
43793
|
* failed so mobile shows a stale-question affordance.
|
|
43794
|
+
*
|
|
43795
|
+
* For a permission, `optionId` (the wire `value` the client echoes
|
|
43796
|
+
* back) wins when it names one of the registered options; otherwise
|
|
43797
|
+
* `index` is the position in the options we put on the wire.
|
|
43692
43798
|
*/
|
|
43693
|
-
resolveSelection(index) {
|
|
43799
|
+
resolveSelection(index, optionId) {
|
|
43694
43800
|
if (!this.pending) return { kind: "none" };
|
|
43695
43801
|
if (this.pending.kind === "permission") {
|
|
43696
|
-
const
|
|
43697
|
-
const
|
|
43802
|
+
const byId = optionId ? this.pending.options.find((o) => o.optionId === optionId) : void 0;
|
|
43803
|
+
const picked = byId ?? this.pending.options[index];
|
|
43698
43804
|
clearTimeout(this.pending.timeoutTimer);
|
|
43699
43805
|
const resolve11 = this.pending.resolve;
|
|
43700
43806
|
this.pending = null;
|
|
43701
|
-
if (!
|
|
43807
|
+
if (!picked) {
|
|
43702
43808
|
log.warn("acpRunner", `select_option index=${index} out of bounds \u2014 cancel`);
|
|
43703
43809
|
resolve11({ outcome: { outcome: "cancelled" } });
|
|
43704
|
-
return { kind: "resolved" };
|
|
43810
|
+
return { kind: "resolved", optionId: null };
|
|
43705
43811
|
}
|
|
43706
|
-
resolve11({ outcome: { outcome: "selected", optionId } });
|
|
43707
|
-
return { kind: "resolved" };
|
|
43812
|
+
resolve11({ outcome: { outcome: "selected", optionId: picked.optionId } });
|
|
43813
|
+
return { kind: "resolved", optionId: picked.optionId };
|
|
43708
43814
|
}
|
|
43709
43815
|
const text = this.pending.options[index];
|
|
43710
43816
|
this.pending = null;
|
|
@@ -43968,6 +44074,10 @@ var StreamingState = class {
|
|
|
43968
44074
|
}
|
|
43969
44075
|
};
|
|
43970
44076
|
var PERMISSION_TIMEOUT_MS = 5 * 60 * 1e3;
|
|
44077
|
+
function permissionExpiredNotice() {
|
|
44078
|
+
const minutes = Math.round(PERMISSION_TIMEOUT_MS / 6e4);
|
|
44079
|
+
return `\u23F1 A permission request expired after ${minutes} minutes with no answer, so CodeAgent cancelled it \u2014 this was a timeout, not a refusal by you. Ask the agent to try again and approve it from here.`;
|
|
44080
|
+
}
|
|
43971
44081
|
var AcpHistory = class {
|
|
43972
44082
|
constructor(publisher, opts) {
|
|
43973
44083
|
this.publisher = publisher;
|
|
@@ -44443,7 +44553,9 @@ async function runAcpSession(opts) {
|
|
|
44443
44553
|
emitSwitchEvent,
|
|
44444
44554
|
// Same live flag the switch deps read — a start_task naming the
|
|
44445
44555
|
// house agent on a house session is the agent already running.
|
|
44446
|
-
() => houseActive
|
|
44556
|
+
() => houseActive,
|
|
44557
|
+
// …and WHICH house-rail agent (a managed id, or the house sentinel).
|
|
44558
|
+
() => houseWireId
|
|
44447
44559
|
);
|
|
44448
44560
|
},
|
|
44449
44561
|
{ id: opts.agent, name: opts.agent, displayName: opts.agent },
|
|
@@ -44482,6 +44594,7 @@ async function runAcpSession(opts) {
|
|
|
44482
44594
|
const pendingProposal = { current: null };
|
|
44483
44595
|
let switchCredentialEnv = {};
|
|
44484
44596
|
let houseActive = isHouseProxyEnv(process.env);
|
|
44597
|
+
let houseWireId = houseRailWireId(process.env);
|
|
44485
44598
|
let houseEnv = houseActive ? pickHouseProxyEnv(process.env) : {};
|
|
44486
44599
|
let pendingHouseConfig = null;
|
|
44487
44600
|
const relaunchWith = async (nextAgent, swapOpts = { house: false }) => {
|
|
@@ -44529,6 +44642,7 @@ async function runAcpSession(opts) {
|
|
|
44529
44642
|
const wasHouse = houseActive;
|
|
44530
44643
|
houseActive = swapOpts.house;
|
|
44531
44644
|
if (swapOpts.house) {
|
|
44645
|
+
houseWireId = swapOpts.wireId ?? HOUSE_AGENT_ID;
|
|
44532
44646
|
if (pendingHouseConfig) {
|
|
44533
44647
|
persistHouseProxyConfig(pendingHouseConfig);
|
|
44534
44648
|
pendingHouseConfig = null;
|
|
@@ -44536,12 +44650,14 @@ async function runAcpSession(opts) {
|
|
|
44536
44650
|
} else if (wasHouse) {
|
|
44537
44651
|
clearHouseProxyConfig();
|
|
44538
44652
|
}
|
|
44653
|
+
const managedBanner = swapOpts.house && isManagedProviderId(houseWireId) ? houseWireId : null;
|
|
44539
44654
|
void publisher.publishOutput({
|
|
44540
44655
|
type: "agent_banner",
|
|
44541
|
-
agentId: swapOpts.house ?
|
|
44656
|
+
agentId: swapOpts.house ? houseWireId : nextAgent,
|
|
44542
44657
|
// A switch starts a FRESH conversation with the new agent — never "back".
|
|
44543
|
-
|
|
44544
|
-
|
|
44658
|
+
// A managed target is named by its model; the house agent stays white-label.
|
|
44659
|
+
title: managedBanner ? MANAGED_PROVIDER_DISPLAY_NAMES[managedBanner] : swapOpts.house ? HOUSE_AGENT_NAME : bannerTitle(false),
|
|
44660
|
+
subtitle: managedBanner ? MANAGED_AGENT_SUBTITLE : swapOpts.house ? HOUSE_AGENT_SUBTITLE : buildBannerSubtitle(nextAgent, hs.sessionId, hs.model, hs.tier),
|
|
44545
44661
|
path: swapOpts.house ? "" : bannerLocation(opts.cwd),
|
|
44546
44662
|
done: true
|
|
44547
44663
|
});
|
|
@@ -44558,6 +44674,7 @@ async function runAcpSession(opts) {
|
|
|
44558
44674
|
const switchDeps = {
|
|
44559
44675
|
currentAgent: () => opts.agent,
|
|
44560
44676
|
currentIsHouse: () => houseActive,
|
|
44677
|
+
currentHouseWireId: () => houseWireId,
|
|
44561
44678
|
postEvent: emitSwitchEvent,
|
|
44562
44679
|
fetchCredential: (agentId) => fetchProvisionCredentialDetailed({
|
|
44563
44680
|
agentId,
|
|
@@ -44569,7 +44686,7 @@ async function runAcpSession(opts) {
|
|
|
44569
44686
|
provisionCredential: (agentId, auth) => {
|
|
44570
44687
|
switchCredentialEnv = provisionAgentCredentials(agentId, auth);
|
|
44571
44688
|
},
|
|
44572
|
-
provisionHouseProxy: ({ baseUrl, token }) => {
|
|
44689
|
+
provisionHouseProxy: ({ baseUrl, token, model, managedAgentId }) => {
|
|
44573
44690
|
const claudeConfigDir = path87.join(
|
|
44574
44691
|
os62.homedir(),
|
|
44575
44692
|
".codeam",
|
|
@@ -44580,8 +44697,15 @@ async function runAcpSession(opts) {
|
|
|
44580
44697
|
fs78.mkdirSync(claudeConfigDir, { recursive: true, mode: 448 });
|
|
44581
44698
|
} catch {
|
|
44582
44699
|
}
|
|
44583
|
-
|
|
44584
|
-
|
|
44700
|
+
const cfg = {
|
|
44701
|
+
baseUrl,
|
|
44702
|
+
token,
|
|
44703
|
+
claudeConfigDir,
|
|
44704
|
+
...model ? { model } : {},
|
|
44705
|
+
...managedAgentId ? { managedAgentId } : {}
|
|
44706
|
+
};
|
|
44707
|
+
houseEnv = buildHouseProxyChildEnv(cfg);
|
|
44708
|
+
pendingHouseConfig = cfg;
|
|
44585
44709
|
switchCredentialEnv = {};
|
|
44586
44710
|
},
|
|
44587
44711
|
ensureBinary: (agentId, installScript, onRetry) => ensureAgentBinaryForSwitch(agentId, installScript, { onRetry }),
|
|
@@ -44669,7 +44793,7 @@ async function runAcpSession(opts) {
|
|
|
44669
44793
|
await new Promise(() => {
|
|
44670
44794
|
});
|
|
44671
44795
|
}
|
|
44672
|
-
async function handleCommand(cmd, client3, relay, acpSessionId, streaming, opts, history, jsonlHistory, agentCaps, turnFiles, getBeads, publisher, recentStderr, budgetRecovery, budgetReachedFlag, onActiveSessionChanged, switchAgent, pendingHandoff, squad, routeToAgent, pendingProposal, postSquadEvent, currentIsHouse) {
|
|
44796
|
+
async function handleCommand(cmd, client3, relay, acpSessionId, streaming, opts, history, jsonlHistory, agentCaps, turnFiles, getBeads, publisher, recentStderr, budgetRecovery, budgetReachedFlag, onActiveSessionChanged, switchAgent, pendingHandoff, squad, routeToAgent, pendingProposal, postSquadEvent, currentIsHouse, currentHouseWireId) {
|
|
44673
44797
|
const session = {
|
|
44674
44798
|
client: client3,
|
|
44675
44799
|
relay,
|
|
@@ -44692,7 +44816,8 @@ async function handleCommand(cmd, client3, relay, acpSessionId, streaming, opts,
|
|
|
44692
44816
|
routeToAgent,
|
|
44693
44817
|
pendingProposal,
|
|
44694
44818
|
postSquadEvent,
|
|
44695
|
-
currentIsHouse
|
|
44819
|
+
currentIsHouse,
|
|
44820
|
+
currentHouseWireId
|
|
44696
44821
|
};
|
|
44697
44822
|
await dispatchAcpCommand(assembleAcpCommandContext(session, cmd));
|
|
44698
44823
|
}
|
|
@@ -46604,13 +46729,9 @@ async function runBatonSession(opts) {
|
|
|
46604
46729
|
beginLoadReplay: () => streaming.beginLoadReplay(),
|
|
46605
46730
|
endLoadReplay: () => streaming.endLoadReplay(),
|
|
46606
46731
|
onRequestPermission: async (request2) => {
|
|
46607
|
-
const { event,
|
|
46732
|
+
const { event, options } = mapPermissionRequest(request2);
|
|
46608
46733
|
await publisher.publishAwaitingAnswer(event);
|
|
46609
|
-
return streaming.registerPermission({
|
|
46610
|
-
questionId: event.questionId,
|
|
46611
|
-
labels: event.options ?? [],
|
|
46612
|
-
optionIdByLabel
|
|
46613
|
-
});
|
|
46734
|
+
return streaming.registerPermission({ questionId: event.questionId, options });
|
|
46614
46735
|
},
|
|
46615
46736
|
onStderr: (line) => {
|
|
46616
46737
|
recentStderr.push(line);
|
|
@@ -46974,7 +47095,7 @@ async function start(requestedAgent, presetSession) {
|
|
|
46974
47095
|
// The house agent runs the `claude` runtime, so `session.agent` cannot
|
|
46975
47096
|
// tell it apart; the managed-proxy env can (`isHouseProxyEnv`). The
|
|
46976
47097
|
// backend turns the tool router on for the house agent ONLY.
|
|
46977
|
-
agent: isHouseProxyEnv(process.env) ?
|
|
47098
|
+
agent: isHouseProxyEnv(process.env) ? houseRailWireId(process.env) : session.agent
|
|
46978
47099
|
});
|
|
46979
47100
|
}
|
|
46980
47101
|
const mcpServers = mergeWithLocalMcpServers(
|
|
@@ -49825,7 +49946,7 @@ function checkChokidar() {
|
|
|
49825
49946
|
}
|
|
49826
49947
|
async function doctor(args2 = []) {
|
|
49827
49948
|
const json = args2.includes("--json");
|
|
49828
|
-
const cliVersion = true ? "2.
|
|
49949
|
+
const cliVersion = true ? "2.75.0" : "0.0.0-dev";
|
|
49829
49950
|
const apiBase2 = resolveApiBaseUrl();
|
|
49830
49951
|
const diagnosticId = (0, import_node_crypto13.randomUUID)();
|
|
49831
49952
|
log.info("doctor", `run id=${diagnosticId} cli=${cliVersion}`);
|
|
@@ -50349,7 +50470,7 @@ async function mcpWarm(argv = [], opts = {}) {
|
|
|
50349
50470
|
// src/commands/version.ts
|
|
50350
50471
|
var import_picocolors15 = __toESM(require("picocolors"));
|
|
50351
50472
|
function version2() {
|
|
50352
|
-
const v = true ? "2.
|
|
50473
|
+
const v = true ? "2.75.0" : "unknown";
|
|
50353
50474
|
console.log(`${import_picocolors15.default.bold("codeam-cli")} ${import_picocolors15.default.cyan(v)}`);
|
|
50354
50475
|
}
|
|
50355
50476
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "codeam-cli",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.75.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",
|