codeam-cli 2.75.45 → 2.75.46
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 +6 -0
- package/dist/index.js +717 -696
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -3763,9 +3763,9 @@ var _default = makeConfig();
|
|
|
3763
3763
|
var { getConfig, ensurePluginId, addSession, removeSession, setActiveSession, getActiveSession, getActiveSessionForAgent, setDisable1mContext, setSessionAgent, setSquadAuto, getSquadAuto, clearAll, saveCliConfig, loadCliConfig } = _default;
|
|
3764
3764
|
|
|
3765
3765
|
// src/commands/pair-auto.ts
|
|
3766
|
-
var
|
|
3767
|
-
var
|
|
3768
|
-
var
|
|
3766
|
+
var fs54 = __toESM(require("fs"));
|
|
3767
|
+
var os42 = __toESM(require("os"));
|
|
3768
|
+
var path62 = __toESM(require("path"));
|
|
3769
3769
|
var import_crypto3 = require("crypto");
|
|
3770
3770
|
|
|
3771
3771
|
// src/services/telemetry.service.ts
|
|
@@ -10577,7 +10577,7 @@ function readAnonId() {
|
|
|
10577
10577
|
}
|
|
10578
10578
|
function superProperties() {
|
|
10579
10579
|
return {
|
|
10580
|
-
cliVersion: true ? "2.75.
|
|
10580
|
+
cliVersion: true ? "2.75.46" : "0.0.0-dev",
|
|
10581
10581
|
nodeVersion: process.version,
|
|
10582
10582
|
platform: process.platform,
|
|
10583
10583
|
arch: process.arch,
|
|
@@ -10822,7 +10822,7 @@ var http = __toESM(require("http"));
|
|
|
10822
10822
|
// package.json
|
|
10823
10823
|
var package_default = {
|
|
10824
10824
|
name: "codeam-cli",
|
|
10825
|
-
version: "2.75.
|
|
10825
|
+
version: "2.75.46",
|
|
10826
10826
|
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.",
|
|
10827
10827
|
type: "commonjs",
|
|
10828
10828
|
main: "dist/index.js",
|
|
@@ -12156,7 +12156,7 @@ var CommandRelayService = class _CommandRelayService {
|
|
|
12156
12156
|
// fresh + clear the "CLI update available" banner after a self-update
|
|
12157
12157
|
// (a codespace that reinstalls @latest reconnects via heartbeat, not
|
|
12158
12158
|
// pair/reconnect). Older backends ignore the extra field.
|
|
12159
|
-
..."2.75.
|
|
12159
|
+
..."2.75.46" ? { ideVersion: "2.75.46" } : {}
|
|
12160
12160
|
};
|
|
12161
12161
|
try {
|
|
12162
12162
|
const res = await _postJson(`${API_BASE2}/api/plugin/heartbeat`, body);
|
|
@@ -13632,9 +13632,9 @@ function closeAllTerminals() {
|
|
|
13632
13632
|
}
|
|
13633
13633
|
|
|
13634
13634
|
// src/commands/start/handlers.ts
|
|
13635
|
-
var
|
|
13636
|
-
var
|
|
13637
|
-
var
|
|
13635
|
+
var fs53 = __toESM(require("fs"));
|
|
13636
|
+
var os41 = __toESM(require("os"));
|
|
13637
|
+
var path61 = __toESM(require("path"));
|
|
13638
13638
|
var import_crypto2 = require("crypto");
|
|
13639
13639
|
var import_child_process25 = require("child_process");
|
|
13640
13640
|
|
|
@@ -17638,6 +17638,8 @@ async function spawnAndCapture(cmd, args2, opts = {}) {
|
|
|
17638
17638
|
clearTimeout(timer);
|
|
17639
17639
|
activeChildren.delete(child);
|
|
17640
17640
|
if (code !== 0) {
|
|
17641
|
+
const failedOut = stdout.trim();
|
|
17642
|
+
if (failedOut) opts.onFailedOutput?.(failedOut);
|
|
17641
17643
|
settle(null);
|
|
17642
17644
|
return;
|
|
17643
17645
|
}
|
|
@@ -18143,6 +18145,7 @@ var ClaudeRuntimeStrategy = class {
|
|
|
18143
18145
|
if (!launch) return null;
|
|
18144
18146
|
return spawnAndCapture(launch.cmd, launch.args, {
|
|
18145
18147
|
onStderr: opts?.onStderr,
|
|
18148
|
+
onFailedOutput: opts?.onFailedOutput,
|
|
18146
18149
|
cwd: opts?.cwd,
|
|
18147
18150
|
timeoutMs: opts?.timeoutMs
|
|
18148
18151
|
});
|
|
@@ -19230,6 +19233,7 @@ var CodexRuntimeStrategy = class {
|
|
|
19230
19233
|
const launch = this.os.buildLaunch(binary, ["exec", prompt]);
|
|
19231
19234
|
return spawnAndCapture(launch.cmd, launch.args, {
|
|
19232
19235
|
onStderr: opts?.onStderr,
|
|
19236
|
+
onFailedOutput: opts?.onFailedOutput,
|
|
19233
19237
|
cwd: opts?.cwd,
|
|
19234
19238
|
timeoutMs: opts?.timeoutMs
|
|
19235
19239
|
});
|
|
@@ -20335,6 +20339,7 @@ var CursorRuntimeStrategy = class {
|
|
|
20335
20339
|
const launch = this.os.buildLaunch(binary, ["--print", "--force", "--trust", prompt]);
|
|
20336
20340
|
return spawnAndCapture(launch.cmd, launch.args, {
|
|
20337
20341
|
onStderr: opts?.onStderr,
|
|
20342
|
+
onFailedOutput: opts?.onFailedOutput,
|
|
20338
20343
|
cwd: opts?.cwd,
|
|
20339
20344
|
timeoutMs: opts?.timeoutMs
|
|
20340
20345
|
});
|
|
@@ -21138,6 +21143,7 @@ var GeminiRuntimeStrategy = class {
|
|
|
21138
21143
|
const launch = this.os.buildLaunch(binary, ["--skip-trust", "-p", prompt]);
|
|
21139
21144
|
return spawnAndCapture(launch.cmd, launch.args, {
|
|
21140
21145
|
onStderr: opts?.onStderr,
|
|
21146
|
+
onFailedOutput: opts?.onFailedOutput,
|
|
21141
21147
|
cwd: opts?.cwd,
|
|
21142
21148
|
timeoutMs: opts?.timeoutMs
|
|
21143
21149
|
});
|
|
@@ -21416,6 +21422,7 @@ var KimiRuntimeStrategy = class {
|
|
|
21416
21422
|
const launch = this.os.buildLaunch(binary, ["-p", prompt, "--output-format", "text"]);
|
|
21417
21423
|
return spawnAndCapture(launch.cmd, launch.args, {
|
|
21418
21424
|
onStderr: opts?.onStderr,
|
|
21425
|
+
onFailedOutput: opts?.onFailedOutput,
|
|
21419
21426
|
cwd: opts?.cwd,
|
|
21420
21427
|
timeoutMs: opts?.timeoutMs
|
|
21421
21428
|
});
|
|
@@ -21536,6 +21543,7 @@ var OpencodeRuntimeStrategy = class {
|
|
|
21536
21543
|
const launch = this.os.buildLaunch(binary, ["run", prompt]);
|
|
21537
21544
|
return spawnAndCapture(launch.cmd, launch.args, {
|
|
21538
21545
|
onStderr: opts?.onStderr,
|
|
21546
|
+
onFailedOutput: opts?.onFailedOutput,
|
|
21539
21547
|
cwd: opts?.cwd,
|
|
21540
21548
|
timeoutMs: opts?.timeoutMs
|
|
21541
21549
|
});
|
|
@@ -22676,17 +22684,548 @@ function setGuardrailPolicy(raw, homeDir2 = os28.homedir()) {
|
|
|
22676
22684
|
return next;
|
|
22677
22685
|
}
|
|
22678
22686
|
|
|
22679
|
-
// src/
|
|
22680
|
-
var
|
|
22681
|
-
|
|
22687
|
+
// src/agents/acp/oneMContextRecovery.ts
|
|
22688
|
+
var ONE_M_CONTEXT_CREDITS_RE = /usage credits required for 1m context/i;
|
|
22689
|
+
function looksLike1mContextCreditsError(text) {
|
|
22690
|
+
return ONE_M_CONTEXT_CREDITS_RE.test(text);
|
|
22691
|
+
}
|
|
22692
|
+
function shouldOfferOneMRecovery(opts) {
|
|
22693
|
+
return looksLike1mContextCreditsError(opts.detail) || looksLike1mContextCreditsError(opts.recentStderr) || looksLike1mContextCreditsError(opts.finalText);
|
|
22694
|
+
}
|
|
22695
|
+
|
|
22696
|
+
// src/commands/host/house-proxy-config.ts
|
|
22697
|
+
var fs34 = __toESM(require("fs"));
|
|
22698
|
+
var os30 = __toESM(require("os"));
|
|
22682
22699
|
var path40 = __toESM(require("path"));
|
|
22700
|
+
|
|
22701
|
+
// src/lib/restrict-to-owner.ts
|
|
22702
|
+
var import_node_fs7 = __toESM(require("fs"));
|
|
22703
|
+
var import_node_os4 = __toESM(require("os"));
|
|
22704
|
+
var import_node_child_process18 = require("child_process");
|
|
22705
|
+
var BROAD_WINDOWS_SIDS = [
|
|
22706
|
+
"*S-1-1-0",
|
|
22707
|
+
"*S-1-5-11",
|
|
22708
|
+
"*S-1-5-32-545",
|
|
22709
|
+
"*S-1-5-32-544",
|
|
22710
|
+
"*S-1-5-18"
|
|
22711
|
+
];
|
|
22712
|
+
function restrictToOwner(filePath) {
|
|
22713
|
+
try {
|
|
22714
|
+
if (process.platform === "win32") {
|
|
22715
|
+
const username = import_node_os4.default.userInfo().username;
|
|
22716
|
+
(0, import_node_child_process18.execFileSync)(
|
|
22717
|
+
"icacls",
|
|
22718
|
+
[
|
|
22719
|
+
filePath,
|
|
22720
|
+
"/inheritance:r",
|
|
22721
|
+
"/grant:r",
|
|
22722
|
+
`${username}:F`,
|
|
22723
|
+
...BROAD_WINDOWS_SIDS.flatMap((sid) => ["/remove", sid])
|
|
22724
|
+
],
|
|
22725
|
+
{ stdio: "ignore" }
|
|
22726
|
+
);
|
|
22727
|
+
} else {
|
|
22728
|
+
import_node_fs7.default.chmodSync(filePath, 384);
|
|
22729
|
+
}
|
|
22730
|
+
} catch {
|
|
22731
|
+
}
|
|
22732
|
+
}
|
|
22733
|
+
|
|
22734
|
+
// src/commands/host/house-proxy-config.ts
|
|
22735
|
+
function houseProxyConfigPath() {
|
|
22736
|
+
return path40.join(os30.homedir(), ".codeam", "house-proxy.json");
|
|
22737
|
+
}
|
|
22738
|
+
var DEPLOY_ID_RE = /^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/;
|
|
22739
|
+
function deployHouseProxyConfigPath(deployId) {
|
|
22740
|
+
if (!DEPLOY_ID_RE.test(deployId) || deployId.includes("..")) return null;
|
|
22741
|
+
return path40.join(os30.homedir(), ".codeam", "house-proxy", `${deployId}.json`);
|
|
22742
|
+
}
|
|
22743
|
+
function writeJson0600(file, value) {
|
|
22744
|
+
fs34.mkdirSync(path40.dirname(file), { recursive: true, mode: 448 });
|
|
22745
|
+
const tmp = `${file}.tmp-${process.pid}`;
|
|
22746
|
+
fs34.writeFileSync(tmp, JSON.stringify(value, null, 2), { encoding: "utf8", mode: 384 });
|
|
22747
|
+
fs34.renameSync(tmp, file);
|
|
22748
|
+
restrictToOwner(file);
|
|
22749
|
+
}
|
|
22750
|
+
function persistHouseProxyConfig(config, deployId) {
|
|
22751
|
+
try {
|
|
22752
|
+
const perDeploy = deployId ? deployHouseProxyConfigPath(deployId) : null;
|
|
22753
|
+
if (perDeploy) writeJson0600(perDeploy, config);
|
|
22754
|
+
writeJson0600(houseProxyConfigPath(), config);
|
|
22755
|
+
} catch (err) {
|
|
22756
|
+
log.warn(
|
|
22757
|
+
"host-agent",
|
|
22758
|
+
`failed to persist house-proxy config (best-effort): ${err instanceof Error ? err.message : String(err)}`
|
|
22759
|
+
);
|
|
22760
|
+
}
|
|
22761
|
+
}
|
|
22762
|
+
function clearHouseProxyConfig(deployId) {
|
|
22763
|
+
try {
|
|
22764
|
+
fs34.rmSync(houseProxyConfigPath(), { force: true });
|
|
22765
|
+
const perDeploy = deployId ? deployHouseProxyConfigPath(deployId) : null;
|
|
22766
|
+
if (perDeploy) writeJson0600(perDeploy, { none: true });
|
|
22767
|
+
} catch {
|
|
22768
|
+
}
|
|
22769
|
+
}
|
|
22770
|
+
function readHouseProxyChildEnv(deployId) {
|
|
22771
|
+
try {
|
|
22772
|
+
const perDeploy = deployId ? deployHouseProxyConfigPath(deployId) : null;
|
|
22773
|
+
const file = perDeploy && fs34.existsSync(perDeploy) ? perDeploy : houseProxyConfigPath();
|
|
22774
|
+
const raw = fs34.readFileSync(file, "utf8");
|
|
22775
|
+
const parsed = JSON.parse(raw);
|
|
22776
|
+
if (typeof parsed !== "object" || parsed === null) return {};
|
|
22777
|
+
const o = parsed;
|
|
22778
|
+
if (o.none === true) return {};
|
|
22779
|
+
if (typeof o.baseUrl !== "string" || !o.baseUrl) return {};
|
|
22780
|
+
if (typeof o.token !== "string" || !o.token) return {};
|
|
22781
|
+
return buildHouseProxyChildEnv({
|
|
22782
|
+
baseUrl: o.baseUrl,
|
|
22783
|
+
token: o.token,
|
|
22784
|
+
openRouter: o.openRouter === true,
|
|
22785
|
+
...typeof o.claudeConfigDir === "string" && o.claudeConfigDir ? { claudeConfigDir: o.claudeConfigDir } : {},
|
|
22786
|
+
...typeof o.model === "string" && o.model ? { model: o.model } : {},
|
|
22787
|
+
...typeof o.managedAgentId === "string" && o.managedAgentId ? { managedAgentId: o.managedAgentId } : {}
|
|
22788
|
+
});
|
|
22789
|
+
} catch {
|
|
22790
|
+
return {};
|
|
22791
|
+
}
|
|
22792
|
+
}
|
|
22793
|
+
var HOUSE_MODEL_CONTEXT_TOKENS = "512000";
|
|
22794
|
+
function buildHouseProxyChildEnv(cfg) {
|
|
22795
|
+
const env = {
|
|
22796
|
+
ANTHROPIC_BASE_URL: cfg.baseUrl,
|
|
22797
|
+
ANTHROPIC_AUTH_TOKEN: cfg.token,
|
|
22798
|
+
// ⚠️ MAX_CONTEXT_TOKENS, not (only) AUTO_COMPACT_WINDOW — and this is
|
|
22799
|
+
// HOUSE-AGENT ONLY: it lives in this builder precisely so a user's own
|
|
22800
|
+
// Claude Code (a real Anthropic model claude knows) is never touched.
|
|
22801
|
+
//
|
|
22802
|
+
// claude does not know `MiniMax-M3`, so it falls back to its
|
|
22803
|
+
// unknown-model default (200k). `CLAUDE_CODE_AUTO_COMPACT_WINDOW` is then
|
|
22804
|
+
// applied as `Math.min(assumedWindow, env)` — it can only SHRINK the
|
|
22805
|
+
// window, never grow it — so the 512000 we used to set here was inert:
|
|
22806
|
+
// claude kept believing 200k. Meanwhile a session with a dozen linked
|
|
22807
|
+
// integrations carries ~175k tokens of MCP tool schemas on EVERY turn
|
|
22808
|
+
// (measured: 475 tools ≈ 698 KB on a real box), so the context started
|
|
22809
|
+
// ~88% full and a 28-character prompt triggered a compaction, then the
|
|
22810
|
+
// next small tool result triggered another: "Autocompact is thrashing:
|
|
22811
|
+
// the context refilled to the limit within 3 turns", 13 compactions in
|
|
22812
|
+
// one session (rafaelph90.br@gmail.com, 2026-09-03).
|
|
22813
|
+
//
|
|
22814
|
+
// claude's own unknown-model notice names the fix: "set
|
|
22815
|
+
// CLAUDE_CODE_MAX_CONTEXT_TOKENS to its real window" — that variable is
|
|
22816
|
+
// what `wL()` returns for an unrecognised model. MiniMax-M3 is a 1M-context
|
|
22817
|
+
// model with a guaranteed minimum of 512K, so 512000 here is the
|
|
22818
|
+
// conservative truth, not a wish. AUTO_COMPACT_WINDOW stays as the
|
|
22819
|
+
// compaction threshold beneath it.
|
|
22820
|
+
CLAUDE_CODE_MAX_CONTEXT_TOKENS: HOUSE_MODEL_CONTEXT_TOKENS,
|
|
22821
|
+
CLAUDE_CODE_AUTO_COMPACT_WINDOW: HOUSE_MODEL_CONTEXT_TOKENS,
|
|
22822
|
+
API_TIMEOUT_MS: "3000000"
|
|
22823
|
+
};
|
|
22824
|
+
if (cfg.openRouter === true) {
|
|
22825
|
+
env.ANTHROPIC_API_KEY = "";
|
|
22826
|
+
} else {
|
|
22827
|
+
const model = typeof cfg.model === "string" && cfg.model ? cfg.model : "MiniMax-M3";
|
|
22828
|
+
env.ANTHROPIC_MODEL = model;
|
|
22829
|
+
env.ANTHROPIC_DEFAULT_SONNET_MODEL = model;
|
|
22830
|
+
env.ANTHROPIC_DEFAULT_OPUS_MODEL = model;
|
|
22831
|
+
env.ANTHROPIC_DEFAULT_HAIKU_MODEL = model;
|
|
22832
|
+
}
|
|
22833
|
+
if (typeof cfg.claudeConfigDir === "string" && cfg.claudeConfigDir) {
|
|
22834
|
+
env.CLAUDE_CONFIG_DIR = cfg.claudeConfigDir;
|
|
22835
|
+
}
|
|
22836
|
+
if (isManagedProviderId(cfg.managedAgentId)) {
|
|
22837
|
+
env[MANAGED_AGENT_ENV] = cfg.managedAgentId;
|
|
22838
|
+
}
|
|
22839
|
+
return env;
|
|
22840
|
+
}
|
|
22841
|
+
function houseRailWireId(env) {
|
|
22842
|
+
const managed = env[MANAGED_AGENT_ENV];
|
|
22843
|
+
return isManagedProviderId(managed) ? managed : HOUSE_AGENT_ID;
|
|
22844
|
+
}
|
|
22845
|
+
var HOUSE_PROXY_ENV_KEYS = [
|
|
22846
|
+
"ANTHROPIC_BASE_URL",
|
|
22847
|
+
"ANTHROPIC_AUTH_TOKEN",
|
|
22848
|
+
"ANTHROPIC_API_KEY",
|
|
22849
|
+
"ANTHROPIC_MODEL",
|
|
22850
|
+
"ANTHROPIC_DEFAULT_SONNET_MODEL",
|
|
22851
|
+
"ANTHROPIC_DEFAULT_OPUS_MODEL",
|
|
22852
|
+
"ANTHROPIC_DEFAULT_HAIKU_MODEL",
|
|
22853
|
+
"CLAUDE_CODE_AUTO_COMPACT_WINDOW",
|
|
22854
|
+
"CLAUDE_CODE_MAX_CONTEXT_TOKENS",
|
|
22855
|
+
"API_TIMEOUT_MS",
|
|
22856
|
+
"CLAUDE_CONFIG_DIR",
|
|
22857
|
+
MANAGED_AGENT_ENV
|
|
22858
|
+
];
|
|
22859
|
+
function clearHouseProxyEnvOverrides() {
|
|
22860
|
+
const out2 = {};
|
|
22861
|
+
for (const key of HOUSE_PROXY_ENV_KEYS) out2[key] = void 0;
|
|
22862
|
+
return out2;
|
|
22863
|
+
}
|
|
22864
|
+
function isHouseProxyEnv(env) {
|
|
22865
|
+
return typeof env.ANTHROPIC_AUTH_TOKEN === "string" && env.ANTHROPIC_AUTH_TOKEN.length > 0 && (env.ANTHROPIC_BASE_URL ?? "").includes("/api/v1/agent-proxy");
|
|
22866
|
+
}
|
|
22867
|
+
function currentRailWireId(env = process.env) {
|
|
22868
|
+
return isHouseProxyEnv(env) ? houseRailWireId(env) : null;
|
|
22869
|
+
}
|
|
22870
|
+
function pickHouseProxyEnv(env) {
|
|
22871
|
+
const out2 = {};
|
|
22872
|
+
for (const key of HOUSE_PROXY_ENV_KEYS) {
|
|
22873
|
+
const v = env[key];
|
|
22874
|
+
if (typeof v === "string") out2[key] = v;
|
|
22875
|
+
}
|
|
22876
|
+
return out2;
|
|
22877
|
+
}
|
|
22878
|
+
|
|
22879
|
+
// src/lib/provider-routing.ts
|
|
22880
|
+
var fs35 = __toESM(require("fs"));
|
|
22881
|
+
var os31 = __toESM(require("os"));
|
|
22882
|
+
var path41 = __toESM(require("path"));
|
|
22883
|
+
var PROVIDER_BASE_URL_ENV_KEYS = [
|
|
22884
|
+
"ANTHROPIC_BASE_URL",
|
|
22885
|
+
"OPENAI_BASE_URL",
|
|
22886
|
+
"OPENAI_API_BASE",
|
|
22887
|
+
"GEMINI_API_BASE",
|
|
22888
|
+
"GOOGLE_GEMINI_BASE_URL"
|
|
22889
|
+
];
|
|
22890
|
+
var ROUTING_DEFAULT = "default";
|
|
22891
|
+
function redactUrlToOrigin(raw) {
|
|
22892
|
+
if (typeof raw !== "string") return null;
|
|
22893
|
+
const trimmed = raw.trim();
|
|
22894
|
+
if (!trimmed) return null;
|
|
22895
|
+
try {
|
|
22896
|
+
const u2 = new URL(trimmed);
|
|
22897
|
+
if (!u2.host) return "invalid-url";
|
|
22898
|
+
return `${u2.protocol}//${u2.host}`;
|
|
22899
|
+
} catch {
|
|
22900
|
+
return "invalid-url";
|
|
22901
|
+
}
|
|
22902
|
+
}
|
|
22903
|
+
function readOpencodeProviderOrigins(opts = {}) {
|
|
22904
|
+
const home = opts.homeDir ?? os31.homedir();
|
|
22905
|
+
const readFile7 = opts.readFile ?? ((f) => fs35.readFileSync(f, "utf8"));
|
|
22906
|
+
const candidates = [];
|
|
22907
|
+
if (opts.cwd) {
|
|
22908
|
+
candidates.push(path41.join(opts.cwd, "opencode.json"), path41.join(opts.cwd, "opencode.jsonc"));
|
|
22909
|
+
}
|
|
22910
|
+
candidates.push(
|
|
22911
|
+
path41.join(home, ".config", "opencode", "opencode.json"),
|
|
22912
|
+
path41.join(home, ".config", "opencode", "opencode.jsonc")
|
|
22913
|
+
);
|
|
22914
|
+
const out2 = [];
|
|
22915
|
+
const seen2 = /* @__PURE__ */ new Set();
|
|
22916
|
+
for (const file of candidates) {
|
|
22917
|
+
let text;
|
|
22918
|
+
try {
|
|
22919
|
+
text = readFile7(file);
|
|
22920
|
+
} catch {
|
|
22921
|
+
continue;
|
|
22922
|
+
}
|
|
22923
|
+
let parsed;
|
|
22924
|
+
try {
|
|
22925
|
+
parsed = JSON.parse(text.replace(/^\s*\/\/.*$/gm, ""));
|
|
22926
|
+
} catch {
|
|
22927
|
+
continue;
|
|
22928
|
+
}
|
|
22929
|
+
const providers = parsed?.provider;
|
|
22930
|
+
if (!providers || typeof providers !== "object") continue;
|
|
22931
|
+
for (const [id, cfg] of Object.entries(providers)) {
|
|
22932
|
+
if (seen2.has(id)) continue;
|
|
22933
|
+
const options = cfg?.options;
|
|
22934
|
+
const base = options?.baseURL ?? options?.baseUrl ?? options?.base_url;
|
|
22935
|
+
const origin = redactUrlToOrigin(base);
|
|
22936
|
+
if (!origin) continue;
|
|
22937
|
+
seen2.add(id);
|
|
22938
|
+
out2.push({ provider: id, origin });
|
|
22939
|
+
}
|
|
22940
|
+
}
|
|
22941
|
+
return out2;
|
|
22942
|
+
}
|
|
22943
|
+
function describeProviderRouting(env, opts = {}) {
|
|
22944
|
+
const routed = {};
|
|
22945
|
+
for (const key of PROVIDER_BASE_URL_ENV_KEYS) {
|
|
22946
|
+
routed[key] = redactUrlToOrigin(env[key]) ?? ROUTING_DEFAULT;
|
|
22947
|
+
}
|
|
22948
|
+
let opencode = [];
|
|
22949
|
+
try {
|
|
22950
|
+
opencode = readOpencodeProviderOrigins(opts);
|
|
22951
|
+
} catch {
|
|
22952
|
+
}
|
|
22953
|
+
const houseKeys = HOUSE_PROXY_ENV_KEYS.filter(
|
|
22954
|
+
(k2) => typeof env[k2] === "string" && env[k2].length > 0
|
|
22955
|
+
);
|
|
22956
|
+
const codeamKeys = Object.keys(env).filter((k2) => k2.startsWith("CODEAM_") && typeof env[k2] === "string" && env[k2].length > 0).sort();
|
|
22957
|
+
return { env: routed, opencode, houseProxy: isHouseProxyEnv(env), houseKeys, codeamKeys };
|
|
22958
|
+
}
|
|
22959
|
+
function formatProviderRouting(r, label) {
|
|
22960
|
+
const parts = [
|
|
22961
|
+
label ? `agent=${label}` : null,
|
|
22962
|
+
`anthropic=${r.env.ANTHROPIC_BASE_URL}`,
|
|
22963
|
+
`openai=${r.env.OPENAI_BASE_URL !== ROUTING_DEFAULT ? r.env.OPENAI_BASE_URL : r.env.OPENAI_API_BASE}`,
|
|
22964
|
+
`gemini=${r.env.GEMINI_API_BASE !== ROUTING_DEFAULT ? r.env.GEMINI_API_BASE : r.env.GOOGLE_GEMINI_BASE_URL}`,
|
|
22965
|
+
`opencode=[${r.opencode.map((p2) => `${p2.provider}=${p2.origin}`).join(",")}]`,
|
|
22966
|
+
`houseProxy=${r.houseProxy ? "yes" : "no"}`,
|
|
22967
|
+
`houseKeys=[${r.houseKeys.join(",")}]`,
|
|
22968
|
+
`codeamKeys=[${r.codeamKeys.join(",")}]`
|
|
22969
|
+
];
|
|
22970
|
+
return parts.filter((p2) => p2 !== null).join(" ");
|
|
22971
|
+
}
|
|
22972
|
+
var PROVIDER_BILLING_RE = /(?:api error|http|status)[:\s]+402\b|\b402\b[^\n]{0,40}(?:payment required|insufficient|credits?|balance)|insufficient (?:credits?|balance|funds)|payment required/i;
|
|
22973
|
+
function matchesProviderBilling(text) {
|
|
22974
|
+
return PROVIDER_BILLING_RE.test(text);
|
|
22975
|
+
}
|
|
22976
|
+
function scrubSecrets(text) {
|
|
22977
|
+
return text.replace(/\b(?:sk|pk|rk|key|token)[-_][A-Za-z0-9_-]{12,}/gi, "[redacted]").replace(/bearer\s+[A-Za-z0-9._-]{12,}/gi, "Bearer [redacted]").replace(/\b[A-Za-z0-9_-]{40,}\b/g, "[redacted]");
|
|
22978
|
+
}
|
|
22979
|
+
function classifyProviderBilling(text, env) {
|
|
22980
|
+
if (!matchesProviderBilling(text)) return null;
|
|
22981
|
+
const line = text.split("\n").find((l) => PROVIDER_BILLING_RE.test(l)) ?? text;
|
|
22982
|
+
return {
|
|
22983
|
+
marker: isHouseProxyEnv(env) ? "provider_billing_house" : "provider_billing_external",
|
|
22984
|
+
anthropicHost: redactUrlToOrigin(env.ANTHROPIC_BASE_URL) ?? ROUTING_DEFAULT,
|
|
22985
|
+
snippet: scrubSecrets(line.trim()).slice(0, 160)
|
|
22986
|
+
};
|
|
22987
|
+
}
|
|
22988
|
+
|
|
22989
|
+
// src/agents/acp/agent-hooks.ts
|
|
22990
|
+
function replyIsCursorUpgradeRequired(finalText) {
|
|
22991
|
+
const t2 = finalText.trim().toLowerCase();
|
|
22992
|
+
if (t2.length === 0 || t2.length > 200) return false;
|
|
22993
|
+
return t2.includes("upgrade your plan to continue") || t2.includes("upgrade your plan") && t2.includes("continue");
|
|
22994
|
+
}
|
|
22995
|
+
function isGeminiIneligibleTier(haystack2) {
|
|
22996
|
+
return /IneligibleTierError|UNSUPPORTED_CLIENT|no longer supported for Gemini Code Assist|not eligible for Gemini Code Assist/i.test(
|
|
22997
|
+
haystack2
|
|
22998
|
+
);
|
|
22999
|
+
}
|
|
23000
|
+
var ACP_AGENT_HOOKS = {
|
|
23001
|
+
claude: {
|
|
23002
|
+
statusPage: { vendor: "Anthropic", url: "https://status.anthropic.com" },
|
|
23003
|
+
// Freeze the SDK-bundled Claude Code binary at the version this CLI (and its
|
|
23004
|
+
// pinned ACP adapter) was tested against. Without this the binary silently
|
|
23005
|
+
// self-updates to @latest and can drift PAST the adapter — a newer Claude
|
|
23006
|
+
// Code (v2.1.211) started streaming its TUI chrome (What's-new banner, status
|
|
23007
|
+
// line, box-drawing) into the ACP text channel, which paints as a broken chat
|
|
23008
|
+
// on mobile. A version regression must now reach users only through a gated
|
|
23009
|
+
// codeam-cli release, never silently via auto-update.
|
|
23010
|
+
startupExtraEnv: () => ({
|
|
23011
|
+
DISABLE_AUTOUPDATER: "1",
|
|
23012
|
+
CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC: "1"
|
|
23013
|
+
})
|
|
23014
|
+
},
|
|
23015
|
+
codex: {
|
|
23016
|
+
statusPage: { vendor: "OpenAI", url: "https://status.openai.com" },
|
|
23017
|
+
startupExtraEnv: ({ autoApprovePermissions }) => autoApprovePermissions ? { INITIAL_AGENT_MODE: "agent-full-access" } : {}
|
|
23018
|
+
},
|
|
23019
|
+
gemini: {
|
|
23020
|
+
statusPage: { vendor: "Google", url: "https://status.cloud.google.com" },
|
|
23021
|
+
classifyStartupFailure: (haystack2) => isGeminiIneligibleTier(haystack2) ? "ineligible_tier" : null
|
|
23022
|
+
},
|
|
23023
|
+
copilot: {
|
|
23024
|
+
statusPage: { vendor: "GitHub", url: "https://www.githubstatus.com" }
|
|
23025
|
+
},
|
|
23026
|
+
cursor: {
|
|
23027
|
+
statusPage: { vendor: "Cursor", url: "https://status.cursor.com" },
|
|
23028
|
+
classifyCompletedReply: (finalText) => replyIsCursorUpgradeRequired(finalText) ? "upgrade_required" : null
|
|
23029
|
+
}
|
|
23030
|
+
};
|
|
23031
|
+
function agentHooks(agent) {
|
|
23032
|
+
return ACP_AGENT_HOOKS[agent];
|
|
23033
|
+
}
|
|
23034
|
+
|
|
23035
|
+
// src/agents/acp/failure-messages.ts
|
|
23036
|
+
function describeError(err) {
|
|
23037
|
+
if (err instanceof Error) return err.message;
|
|
23038
|
+
return String(err);
|
|
23039
|
+
}
|
|
23040
|
+
var AUTH_FAILURE_RE = /invalid authentication credentials|failed to authenticate|authentication[_ ](?:error|required)|please run \/login|\bunauthorized\b|\binvalid x-api-key\b|oauth (?:token|session) (?:expired|revoked)|(?:session|token|credentials?|oauth)[^\n]{0,40}could not be refreshed|(?:api error|http|status)[:\s]+401|\b401\b[^\n]{0,40}(?:unauthor|authenticat|credential|api[_ ]?key|login)/i;
|
|
23041
|
+
var HOUSE_AGENT_LIMIT_RE = /HOUSE_AGENT_CEILING|CodeAgent Cloud[^\n]{0,60}(?:usage )?ceiling|CodeAgent Cloud is temporarily (?:unavailable|disabled)/i;
|
|
23042
|
+
function looksLikeHouseAgentLimit(text) {
|
|
23043
|
+
return HOUSE_AGENT_LIMIT_RE.test(text);
|
|
23044
|
+
}
|
|
23045
|
+
var LOCAL_PROXY_RE = /(?:127\.0\.0\.1|localhost|\[::1\]):\d+/i;
|
|
23046
|
+
var CONNECTION_ERROR_RE = /ECONNREFUSED|ECONNRESET|ETIMEDOUT|EHOSTUNREACH|socket hang up|fetch failed|network error|connection (?:refused|reset|closed)/i;
|
|
23047
|
+
function looksLikeLocalProxyUnavailable(text) {
|
|
23048
|
+
return LOCAL_PROXY_RE.test(text) && CONNECTION_ERROR_RE.test(text);
|
|
23049
|
+
}
|
|
23050
|
+
function looksLikeAuthFailure(text) {
|
|
23051
|
+
if (looksLikeHouseAgentLimit(text)) return false;
|
|
23052
|
+
if (looksLikeLocalProxyUnavailable(text)) return false;
|
|
23053
|
+
return AUTH_FAILURE_RE.test(text);
|
|
23054
|
+
}
|
|
23055
|
+
function replyIsAuthFailure(finalText) {
|
|
23056
|
+
const t2 = finalText.trim();
|
|
23057
|
+
return t2.length > 0 && t2.length <= 200 && looksLikeAuthFailure(t2);
|
|
23058
|
+
}
|
|
23059
|
+
function replyIsHouseAgentLimit(finalText) {
|
|
23060
|
+
const t2 = finalText.trim();
|
|
23061
|
+
return t2.length > 0 && t2.length <= 400 && looksLikeHouseAgentLimit(t2);
|
|
23062
|
+
}
|
|
23063
|
+
var BYO_PROVIDER_BILLING_RE = /(?:api error|http|status)[:\s]+402\b[^\n]{0,80}(?:insufficient (?:credits?|balance)|requires more credits)|\b402\b[^\n]{0,40}(?:insufficient (?:credits?|balance)|requires more credits)|insufficient (?:credits?|balance)[^\n]{0,40}\b402\b/i;
|
|
23064
|
+
var PROVIDER_CREDITS_PHRASE_RE = /\brequires more credits\b|\binsufficient credits\.?\s+add more\b|\bcredit balance is too low\b|\binsufficient_quota\b|\bexceeded your current quota\b/i;
|
|
23065
|
+
function looksLikeByoProviderBilling(text, env = currentAgentEnv()) {
|
|
23066
|
+
return !isHouseProxyEnv(env) && (BYO_PROVIDER_BILLING_RE.test(text) || PROVIDER_CREDITS_PHRASE_RE.test(text));
|
|
23067
|
+
}
|
|
23068
|
+
function replyIsByoProviderBilling(finalText, env = currentAgentEnv()) {
|
|
23069
|
+
const t2 = finalText.trim();
|
|
23070
|
+
return t2.length > 0 && t2.length <= 600 && looksLikeByoProviderBilling(t2, env);
|
|
23071
|
+
}
|
|
23072
|
+
var PROVIDER_HOST_NAMES = [
|
|
23073
|
+
[/(^|\.)openrouter\.ai$/i, "OpenRouter"],
|
|
23074
|
+
[/(^|\.)deepinfra\.com$/i, "DeepInfra"],
|
|
23075
|
+
[/(^|\.)anthropic\.com$/i, "Anthropic"],
|
|
23076
|
+
[/(^|\.)openai\.com$/i, "OpenAI"],
|
|
23077
|
+
[/(^|\.)googleapis\.com$/i, "Google"],
|
|
23078
|
+
[/(^|\.)minimax(?:i)?\.(?:io|com|chat)$/i, "MiniMax"],
|
|
23079
|
+
[/(^|\.)moonshot\.(?:ai|cn)$/i, "Moonshot"],
|
|
23080
|
+
[/(^|\.)x\.ai$/i, "xAI"],
|
|
23081
|
+
[/(^|\.)mistral\.ai$/i, "Mistral"],
|
|
23082
|
+
[/(^|\.)groq\.com$/i, "Groq"],
|
|
23083
|
+
[/(^|\.)together\.(?:ai|xyz)$/i, "Together"]
|
|
23084
|
+
];
|
|
23085
|
+
var AGENT_DEFAULT_PROVIDER = {
|
|
23086
|
+
claude: "Anthropic",
|
|
23087
|
+
codex: "OpenAI",
|
|
23088
|
+
gemini: "Google"
|
|
23089
|
+
};
|
|
23090
|
+
function byoProviderName(opts) {
|
|
23091
|
+
const env = opts.env ?? currentAgentEnv();
|
|
23092
|
+
for (const key of PROVIDER_BASE_URL_ENV_KEYS) {
|
|
23093
|
+
const origin = redactUrlToOrigin(env[key]);
|
|
23094
|
+
if (!origin || origin === "invalid-url") continue;
|
|
23095
|
+
const host2 = new URL(origin).hostname;
|
|
23096
|
+
for (const [re2, name] of PROVIDER_HOST_NAMES) if (re2.test(host2)) return name;
|
|
23097
|
+
return host2;
|
|
23098
|
+
}
|
|
23099
|
+
return opts.agent && AGENT_DEFAULT_PROVIDER[opts.agent] || "provider";
|
|
23100
|
+
}
|
|
23101
|
+
function byoProviderBillingMessage(provider) {
|
|
23102
|
+
return `\u{1F4B3} **Your ${provider} account has no credits left.** Top up at your provider, or switch this session to another agent.`;
|
|
23103
|
+
}
|
|
23104
|
+
function completedReplyFailureBubble(opts) {
|
|
23105
|
+
const env = opts.env ?? currentAgentEnv();
|
|
23106
|
+
if (replyIsHouseAgentLimit(opts.finalText)) return houseAgentLimitMessage(opts.finalText);
|
|
23107
|
+
if (replyIsByoProviderBilling(opts.finalText, env)) {
|
|
23108
|
+
return byoProviderBillingMessage(byoProviderName({ env, agent: opts.agent }));
|
|
23109
|
+
}
|
|
23110
|
+
if (replyIsAuthFailure(opts.finalText)) return AUTH_FAILURE_MESSAGE;
|
|
23111
|
+
return null;
|
|
23112
|
+
}
|
|
23113
|
+
function houseAgentLimitMessage(text) {
|
|
23114
|
+
if (/temporarily (?:unavailable|disabled)/i.test(text)) {
|
|
23115
|
+
return "\u23F3 **Our agent service is temporarily unavailable \u2014 this one\u2019s on us, not your account.**\n\nThere\u2019s nothing to buy and nothing owed, and it isn\u2019t a problem with your login, so re-authenticating won\u2019t help. Send your message again in a bit, or connect your own agent (Claude Code, Codex, Cursor, Gemini) in **Profile \u203A Agents** to keep going now.";
|
|
23116
|
+
}
|
|
23117
|
+
const canUpgrade = /upgrade to pro/i.test(text);
|
|
23118
|
+
return "\u{1F4CA} **You\u2019ve reached today\u2019s agent usage limit.**\n\nThe free agent has a daily usage ceiling that resets at midnight UTC. This is a usage limit, not a problem with your login \u2014 re-authenticating won\u2019t change it. " + (canUpgrade ? "To keep going now, upgrade to **Pro** for a higher ceiling, or connect your own agent (Claude, Codex, \u2026) in **Profile \u203A Agents** to run without this limit." : "To keep going now, connect your own agent (Claude, Codex, \u2026) in **Profile \u203A Agents** to run without this limit, or wait for the reset.");
|
|
23119
|
+
}
|
|
23120
|
+
var AUTH_FAILURE_MESSAGE = (
|
|
23121
|
+
// ⚠️ Do NOT name a status code here. This bubble fires for several
|
|
23122
|
+
// different failures, and the old hard-coded "(API 401)" told users the API
|
|
23123
|
+
// had answered 401 when it never had — it also sent a live investigation
|
|
23124
|
+
// hunting for 401s in proxy logs that were serving 200s throughout
|
|
23125
|
+
// (2026-08-24). Say what happened, not a number we did not see.
|
|
23126
|
+
"\u{1F512} **Authentication failed \u2014 your agent credentials are invalid or expired.**\n\nTap [Re-authenticate this agent](codeam://reauth) to renew your credentials in Profile \u203A Agents, then send your message again."
|
|
23127
|
+
);
|
|
23128
|
+
var CURSOR_UPGRADE_MESSAGE = "\u26A1 **Cursor needs a paid plan to run the agent.**\n\nThe headless Cursor Agent requires Cursor **Pro** \u2014 your Free plan\u2019s included usage does NOT cover Agent runs, even with quota left. This is your Cursor account (not CodeAgent). Upgrade, then send your message again:\n\n[Upgrade to Cursor Pro \u2192](https://cursor.com/dashboard)";
|
|
23129
|
+
var ONE_M_CREDITS_MESSAGE = "\u{1F504} **Reconnect your Claude subscription to continue.**\n\nClaude requested 1M-context but your account doesn\u2019t have the usage credits for it on this credential. Reconnecting refreshes your subscription so the agent can keep going \u2014 disabling 1M context won\u2019t fix a credits gate.\n\nTap [Reconnect this agent](codeam://reauth) to reconnect your Claude subscription in Profile \u203A Agents, then send your message again.";
|
|
23130
|
+
var TURN_FAILURE_MESSAGE = "\u26A0\uFE0F **The agent hit an error and couldn\u2019t finish this turn.** Please send your message again.";
|
|
23131
|
+
function emptyReplyMessage(agent) {
|
|
23132
|
+
const label = isKnownAgentId(agent) ? AGENT_REGISTRY[agent].displayName : agent;
|
|
23133
|
+
const binary = isKnownAgentId(agent) ? AGENT_REGISTRY[agent].binaryName : agent;
|
|
23134
|
+
return `\u26A0\uFE0F **${label} returned an empty reply.** Its provider may be having issues \u2014 check the agent's login/subscription on this machine (e.g. run \`${binary} -p "test"\` there).`;
|
|
23135
|
+
}
|
|
23136
|
+
var PROVIDER_OUTAGE_RE = /overloaded_error|\boverloaded\b|service[ _]unavailable|temporarily[ _]unavailable|(?:api error|http|status)[:\s]+(?:529|503|502|504)\b|\b(?:529|503|502|504)\b[^\n]{0,40}(?:overload|unavailable|gateway|upstream|server error)|bad gateway|gateway time-?out|upstream (?:error|connect|timeout)/i;
|
|
23137
|
+
function looksLikeProviderOutage(text) {
|
|
23138
|
+
return PROVIDER_OUTAGE_RE.test(text);
|
|
23139
|
+
}
|
|
23140
|
+
function agentStatusPage(agent, railWireId) {
|
|
23141
|
+
if (railWireId) return null;
|
|
23142
|
+
const a = (agent ?? "").toLowerCase();
|
|
23143
|
+
const id = a.includes("claude") || a.includes("anthropic") ? "claude" : a.includes("codex") || a.includes("openai") ? "codex" : a.includes("gemini") || a.includes("google") ? "gemini" : a.includes("copilot") ? "copilot" : a.includes("cursor") ? "cursor" : null;
|
|
23144
|
+
return id ? agentHooks(id)?.statusPage ?? null : null;
|
|
23145
|
+
}
|
|
23146
|
+
function providerOutageMessage(agent, railWireId) {
|
|
23147
|
+
if (railWireId) {
|
|
23148
|
+
const who2 = isManagedProviderId(railWireId) ? `${MANAGED_PROVIDER_DISPLAY_NAMES[railWireId]} ` : "";
|
|
23149
|
+
return `\u{1F310} **CodeAgent's agent service is having a disruption \u2014 this isn't your session.**
|
|
23150
|
+
|
|
23151
|
+
Your ${who2}agent couldn't finish this turn because our provider returned an overload error. It usually clears up on its own \u2014 just send your message again in a bit.`;
|
|
23152
|
+
}
|
|
23153
|
+
const info = agentStatusPage(agent);
|
|
23154
|
+
const who = info ? info.vendor : "The agent provider";
|
|
23155
|
+
return `\u{1F310} **${who} is having a service disruption \u2014 this isn\u2019t your session.**
|
|
23156
|
+
|
|
23157
|
+
The agent provider returned an overload/outage error, so this turn couldn\u2019t finish. It usually clears up on its own \u2014 just send your message again in a bit.` + (info ? `
|
|
23158
|
+
|
|
23159
|
+
Follow the status here: [${info.url}](${info.url})` : "");
|
|
23160
|
+
}
|
|
23161
|
+
function startupFailureMessage(agent, detail, recentStderr, railWireId) {
|
|
23162
|
+
const haystack2 = `${detail}
|
|
23163
|
+
${recentStderr}`;
|
|
23164
|
+
if (agentHooks(agent)?.classifyStartupFailure?.(haystack2) === "ineligible_tier") {
|
|
23165
|
+
return [
|
|
23166
|
+
"\u26A0\uFE0F **Gemini couldn't start \u2014 your Google account isn't eligible.**",
|
|
23167
|
+
"",
|
|
23168
|
+
"Google discontinued free **\u201CLogin with Google\u201D** access to the Gemini CLI on 2026-06-18. The free / individual tier (and Google AI Pro/Ultra) can no longer authenticate here.",
|
|
23169
|
+
"",
|
|
23170
|
+
"To use Gemini from CodeAgent, re-link it in **Profile \u203A Agents** with either:",
|
|
23171
|
+
"\u2022 a **Gemini API key** (AI Studio \u2014 free quota available), or",
|
|
23172
|
+
"\u2022 a paid **Gemini Code Assist (Standard/Enterprise)** subscription."
|
|
23173
|
+
].join("\n");
|
|
23174
|
+
}
|
|
23175
|
+
if (looksLikeAuthFailure(haystack2)) return AUTH_FAILURE_MESSAGE;
|
|
23176
|
+
if (looksLikeProviderOutage(haystack2)) return providerOutageMessage(agent, railWireId);
|
|
23177
|
+
const tail = recentStderr.split("\n").filter(Boolean).slice(-3).join("\n");
|
|
23178
|
+
return [`\u26A0\uFE0F The ${agent} agent failed to start.`, "", tail ? `Details:
|
|
23179
|
+
${tail}` : detail].join(
|
|
23180
|
+
"\n"
|
|
23181
|
+
);
|
|
23182
|
+
}
|
|
23183
|
+
function startupCredentialInvalidReason(agent, detail, recentStderr) {
|
|
23184
|
+
const haystack2 = `${detail}
|
|
23185
|
+
${recentStderr}`;
|
|
23186
|
+
return agentHooks(agent)?.classifyStartupFailure?.(haystack2) === "ineligible_tier" ? "ineligible_tier" : null;
|
|
23187
|
+
}
|
|
23188
|
+
function failureBubble(opts) {
|
|
23189
|
+
const env = opts.env ?? currentAgentEnv();
|
|
23190
|
+
if (looksLikeHouseAgentLimit(opts.detail) || looksLikeHouseAgentLimit(opts.recentStderr)) {
|
|
23191
|
+
return houseAgentLimitMessage(`${opts.detail}
|
|
23192
|
+
${opts.recentStderr}`);
|
|
23193
|
+
}
|
|
23194
|
+
if (looksLikeByoProviderBilling(opts.detail, env) || looksLikeByoProviderBilling(opts.recentStderr, env)) {
|
|
23195
|
+
return byoProviderBillingMessage(byoProviderName({ env, agent: opts.agent }));
|
|
23196
|
+
}
|
|
23197
|
+
if (looksLikeAuthFailure(opts.detail) || looksLikeAuthFailure(opts.recentStderr)) {
|
|
23198
|
+
return AUTH_FAILURE_MESSAGE;
|
|
23199
|
+
}
|
|
23200
|
+
if (looksLike1mContextCreditsError(opts.detail) || looksLike1mContextCreditsError(opts.recentStderr)) {
|
|
23201
|
+
return ONE_M_CREDITS_MESSAGE;
|
|
23202
|
+
}
|
|
23203
|
+
if (looksLikeProviderOutage(opts.detail) || looksLikeProviderOutage(opts.recentStderr)) {
|
|
23204
|
+
return providerOutageMessage(opts.agent, opts.railWireId);
|
|
23205
|
+
}
|
|
23206
|
+
if (!opts.hadText) return TURN_FAILURE_MESSAGE;
|
|
23207
|
+
return null;
|
|
23208
|
+
}
|
|
23209
|
+
var WINDOWS_CONTROL_C_EXIT = 3221225786;
|
|
23210
|
+
function adapterExitMessage(opts) {
|
|
23211
|
+
if (opts.code === WINDOWS_CONTROL_C_EXIT) return null;
|
|
23212
|
+
if (opts.signal === "SIGINT") return null;
|
|
23213
|
+
if (opts.authFail) return AUTH_FAILURE_MESSAGE;
|
|
23214
|
+
if (opts.outageFail) return providerOutageMessage(opts.agent, opts.railWireId);
|
|
23215
|
+
return `Agent adapter exited unexpectedly (code=${opts.code ?? "null"} signal=${opts.signal ?? "null"}).`;
|
|
23216
|
+
}
|
|
23217
|
+
|
|
23218
|
+
// src/services/preview/port-registry.ts
|
|
23219
|
+
var fs36 = __toESM(require("fs"));
|
|
23220
|
+
var os32 = __toESM(require("os"));
|
|
23221
|
+
var path42 = __toESM(require("path"));
|
|
22683
23222
|
var import_child_process14 = require("child_process");
|
|
22684
23223
|
function registryPath() {
|
|
22685
|
-
return
|
|
23224
|
+
return path42.join(os32.homedir(), ".codeam", "preview-ports.json");
|
|
22686
23225
|
}
|
|
22687
23226
|
function readRegistry() {
|
|
22688
23227
|
try {
|
|
22689
|
-
const raw =
|
|
23228
|
+
const raw = fs36.readFileSync(registryPath(), "utf8");
|
|
22690
23229
|
const parsed = JSON.parse(raw);
|
|
22691
23230
|
if (parsed && typeof parsed === "object") return parsed;
|
|
22692
23231
|
} catch {
|
|
@@ -22696,10 +23235,10 @@ function readRegistry() {
|
|
|
22696
23235
|
function writeRegistry(reg) {
|
|
22697
23236
|
try {
|
|
22698
23237
|
const file = registryPath();
|
|
22699
|
-
|
|
23238
|
+
fs36.mkdirSync(path42.dirname(file), { recursive: true });
|
|
22700
23239
|
const tmp = `${file}.tmp`;
|
|
22701
|
-
|
|
22702
|
-
|
|
23240
|
+
fs36.writeFileSync(tmp, JSON.stringify(reg), "utf8");
|
|
23241
|
+
fs36.renameSync(tmp, file);
|
|
22703
23242
|
} catch (err) {
|
|
22704
23243
|
log.warn("preview", `port-registry write failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
22705
23244
|
}
|
|
@@ -22765,7 +23304,7 @@ function reclaimOwnOrphanPort(port) {
|
|
|
22765
23304
|
|
|
22766
23305
|
// src/services/preview/host-allow.ts
|
|
22767
23306
|
var import_fs2 = require("fs");
|
|
22768
|
-
var
|
|
23307
|
+
var path43 = __toESM(require("path"));
|
|
22769
23308
|
var NEXT_ALLOWED_ORIGINS = [
|
|
22770
23309
|
"*.trycloudflare.com",
|
|
22771
23310
|
"*.preview.codeagent-mobile.com",
|
|
@@ -22785,7 +23324,7 @@ var MARKER_DIR = ".codeam";
|
|
|
22785
23324
|
var MARKER_FILE = "preview-host-allow.json";
|
|
22786
23325
|
var ORIG_INFIX = ".codeam-orig";
|
|
22787
23326
|
function markerPath(cwd) {
|
|
22788
|
-
return
|
|
23327
|
+
return path43.join(cwd, MARKER_DIR, MARKER_FILE);
|
|
22789
23328
|
}
|
|
22790
23329
|
async function fileExists(p2) {
|
|
22791
23330
|
try {
|
|
@@ -22798,13 +23337,13 @@ async function fileExists(p2) {
|
|
|
22798
23337
|
async function findConfigFile(cwd, framework) {
|
|
22799
23338
|
const base = CONFIG_BASENAMES[framework];
|
|
22800
23339
|
for (const ext of CONFIG_EXTS) {
|
|
22801
|
-
if (await fileExists(
|
|
23340
|
+
if (await fileExists(path43.join(cwd, `${base}${ext}`))) return `${base}${ext}`;
|
|
22802
23341
|
}
|
|
22803
23342
|
return null;
|
|
22804
23343
|
}
|
|
22805
23344
|
async function dependsOn(cwd, pkgName) {
|
|
22806
23345
|
try {
|
|
22807
|
-
const raw = await import_fs2.promises.readFile(
|
|
23346
|
+
const raw = await import_fs2.promises.readFile(path43.join(cwd, "package.json"), "utf8");
|
|
22808
23347
|
const pkg = JSON.parse(raw);
|
|
22809
23348
|
return !!(pkg.dependencies?.[pkgName] ?? pkg.devDependencies?.[pkgName]);
|
|
22810
23349
|
} catch {
|
|
@@ -22812,11 +23351,11 @@ async function dependsOn(cwd, pkgName) {
|
|
|
22812
23351
|
}
|
|
22813
23352
|
}
|
|
22814
23353
|
async function isEsmConfig(cwd, configFile) {
|
|
22815
|
-
const ext =
|
|
23354
|
+
const ext = path43.extname(configFile);
|
|
22816
23355
|
if (ext === ".mjs" || ext === ".mts" || ext === ".ts") return true;
|
|
22817
23356
|
if (ext === ".cjs") return false;
|
|
22818
23357
|
try {
|
|
22819
|
-
const raw = await import_fs2.promises.readFile(
|
|
23358
|
+
const raw = await import_fs2.promises.readFile(path43.join(cwd, "package.json"), "utf8");
|
|
22820
23359
|
return JSON.parse(raw).type === "module";
|
|
22821
23360
|
} catch {
|
|
22822
23361
|
return false;
|
|
@@ -22907,7 +23446,7 @@ async function isOurShim(abs) {
|
|
|
22907
23446
|
}
|
|
22908
23447
|
}
|
|
22909
23448
|
async function writeMarker(cwd, marker) {
|
|
22910
|
-
await import_fs2.promises.mkdir(
|
|
23449
|
+
await import_fs2.promises.mkdir(path43.join(cwd, MARKER_DIR), { recursive: true });
|
|
22911
23450
|
await import_fs2.promises.writeFile(markerPath(cwd), JSON.stringify(marker, null, 2), "utf8");
|
|
22912
23451
|
}
|
|
22913
23452
|
async function readMarker(cwd) {
|
|
@@ -22922,9 +23461,9 @@ async function restorePreviewHostAllow(cwd) {
|
|
|
22922
23461
|
const marker = await readMarker(cwd);
|
|
22923
23462
|
if (!marker) return;
|
|
22924
23463
|
try {
|
|
22925
|
-
const configAbs =
|
|
23464
|
+
const configAbs = path43.join(cwd, marker.configFile);
|
|
22926
23465
|
if (marker.backupFile) {
|
|
22927
|
-
const backupAbs =
|
|
23466
|
+
const backupAbs = path43.join(cwd, marker.backupFile);
|
|
22928
23467
|
if (await fileExists(backupAbs)) {
|
|
22929
23468
|
await import_fs2.promises.rm(configAbs, { force: true });
|
|
22930
23469
|
await import_fs2.promises.rename(backupAbs, configAbs);
|
|
@@ -22957,26 +23496,26 @@ async function applyPreviewHostAllow(cwd) {
|
|
|
22957
23496
|
}
|
|
22958
23497
|
if (!framework) return;
|
|
22959
23498
|
if (existing) {
|
|
22960
|
-
const ext =
|
|
23499
|
+
const ext = path43.extname(existing);
|
|
22961
23500
|
const origBasename = `${CONFIG_BASENAMES[framework]}${ORIG_INFIX}${ext}`;
|
|
22962
|
-
if (await isOurShim(
|
|
22963
|
-
const origAbs =
|
|
23501
|
+
if (await isOurShim(path43.join(cwd, existing))) {
|
|
23502
|
+
const origAbs = path43.join(cwd, origBasename);
|
|
22964
23503
|
if (!await fileExists(origAbs) || await isOurShim(origAbs)) {
|
|
22965
23504
|
log.warn("preview", `host-allow: ${existing} is a leftover shim with no original \u2014 skipped`);
|
|
22966
23505
|
return;
|
|
22967
23506
|
}
|
|
22968
|
-
await import_fs2.promises.rm(
|
|
22969
|
-
await import_fs2.promises.rename(origAbs,
|
|
23507
|
+
await import_fs2.promises.rm(path43.join(cwd, existing), { force: true });
|
|
23508
|
+
await import_fs2.promises.rename(origAbs, path43.join(cwd, existing));
|
|
22970
23509
|
log.info("preview", `host-allow: restored ${existing} from a leftover ${origBasename}`);
|
|
22971
23510
|
}
|
|
22972
23511
|
const esm = await isEsmConfig(cwd, existing);
|
|
22973
|
-
await import_fs2.promises.rename(
|
|
22974
|
-
await import_fs2.promises.writeFile(
|
|
23512
|
+
await import_fs2.promises.rename(path43.join(cwd, existing), path43.join(cwd, origBasename));
|
|
23513
|
+
await import_fs2.promises.writeFile(path43.join(cwd, existing), shimFor(framework, origBasename, esm), "utf8");
|
|
22975
23514
|
await writeMarker(cwd, { framework, configFile: existing, backupFile: origBasename });
|
|
22976
23515
|
log.info("preview", `host-allow: wrapped ${existing} (${framework}) for tunnel access`);
|
|
22977
23516
|
} else {
|
|
22978
23517
|
const configFile = `${CONFIG_BASENAMES[framework]}.mjs`;
|
|
22979
|
-
await import_fs2.promises.writeFile(
|
|
23518
|
+
await import_fs2.promises.writeFile(path43.join(cwd, configFile), shimFor(framework, null, true), "utf8");
|
|
22980
23519
|
await writeMarker(cwd, { framework, configFile, backupFile: null });
|
|
22981
23520
|
log.info("preview", `host-allow: created ${configFile} (${framework}) for tunnel access`);
|
|
22982
23521
|
}
|
|
@@ -22986,8 +23525,8 @@ async function applyPreviewHostAllow(cwd) {
|
|
|
22986
23525
|
}
|
|
22987
23526
|
|
|
22988
23527
|
// src/services/preview/build-heal.ts
|
|
22989
|
-
var
|
|
22990
|
-
var
|
|
23528
|
+
var fs38 = __toESM(require("fs"));
|
|
23529
|
+
var path44 = __toESM(require("path"));
|
|
22991
23530
|
var BUILD_MARKER_NAME = "BUILD_ID";
|
|
22992
23531
|
var DEFAULT_DEBOUNCE_MS = 1500;
|
|
22993
23532
|
var DEFAULT_MAX_RESTARTS = 3;
|
|
@@ -22996,7 +23535,7 @@ function isBuildHealSupported(framework) {
|
|
|
22996
23535
|
}
|
|
22997
23536
|
function defaultWatchDir(dir, onEvent) {
|
|
22998
23537
|
try {
|
|
22999
|
-
const w3 =
|
|
23538
|
+
const w3 = fs38.watch(dir, { persistent: false }, (_eventType, filename) => onEvent(filename));
|
|
23000
23539
|
w3.on("error", () => {
|
|
23001
23540
|
try {
|
|
23002
23541
|
w3.close();
|
|
@@ -23019,7 +23558,7 @@ function resetBuildHealState(sessionId) {
|
|
|
23019
23558
|
}
|
|
23020
23559
|
function readMarker2(markerPath2) {
|
|
23021
23560
|
try {
|
|
23022
|
-
return
|
|
23561
|
+
return fs38.readFileSync(markerPath2, "utf8").trim();
|
|
23023
23562
|
} catch {
|
|
23024
23563
|
return null;
|
|
23025
23564
|
}
|
|
@@ -23028,8 +23567,8 @@ function watchForBuildClobber(deps) {
|
|
|
23028
23567
|
const watchDir = deps.watchDir ?? defaultWatchDir;
|
|
23029
23568
|
const debounceMs = deps.debounceMs ?? DEFAULT_DEBOUNCE_MS;
|
|
23030
23569
|
const maxRestarts = deps.maxRestarts ?? DEFAULT_MAX_RESTARTS;
|
|
23031
|
-
const nextDir =
|
|
23032
|
-
const markerPath2 =
|
|
23570
|
+
const nextDir = path44.join(deps.cwd, ".next");
|
|
23571
|
+
const markerPath2 = path44.join(nextDir, BUILD_MARKER_NAME);
|
|
23033
23572
|
let stopped = false;
|
|
23034
23573
|
let debounceTimer = null;
|
|
23035
23574
|
let dirUnwatch = null;
|
|
@@ -23087,12 +23626,12 @@ function watchForBuildClobber(deps) {
|
|
|
23087
23626
|
if (filename === null || filename === BUILD_MARKER_NAME) onMarkerTouched();
|
|
23088
23627
|
});
|
|
23089
23628
|
};
|
|
23090
|
-
if (
|
|
23629
|
+
if (fs38.existsSync(nextDir)) {
|
|
23091
23630
|
attachDirWatch();
|
|
23092
23631
|
} else {
|
|
23093
23632
|
cwdUnwatch = watchDir(deps.cwd, (filename) => {
|
|
23094
23633
|
if (stopped || dirUnwatch) return;
|
|
23095
|
-
if ((filename === ".next" || filename === null) &&
|
|
23634
|
+
if ((filename === ".next" || filename === null) && fs38.existsSync(nextDir)) {
|
|
23096
23635
|
cwdUnwatch?.();
|
|
23097
23636
|
cwdUnwatch = null;
|
|
23098
23637
|
attachDirWatch();
|
|
@@ -23319,7 +23858,7 @@ function quoteIfNeeded(value) {
|
|
|
23319
23858
|
|
|
23320
23859
|
// src/services/preview/expo.ts
|
|
23321
23860
|
var http6 = __toESM(require("http"));
|
|
23322
|
-
var
|
|
23861
|
+
var path47 = __toESM(require("path"));
|
|
23323
23862
|
var EXPO_PACKAGER_PROXY_URL_ENV = "EXPO_PACKAGER_PROXY_URL";
|
|
23324
23863
|
function stripExpoTunnelFlag(args2) {
|
|
23325
23864
|
return args2.filter((a) => a !== "--tunnel" && !a.startsWith("--tunnel="));
|
|
@@ -23328,7 +23867,7 @@ function ensureExpoPortArg(command2, args2, port) {
|
|
|
23328
23867
|
const hasPort = args2.some((a) => a === "--port" || a.startsWith("--port="));
|
|
23329
23868
|
if (hasPort) return [...args2];
|
|
23330
23869
|
const out2 = [...args2];
|
|
23331
|
-
if (
|
|
23870
|
+
if (path47.basename(command2) === "npm" && !out2.includes("--")) out2.push("--");
|
|
23332
23871
|
out2.push("--port", String(port));
|
|
23333
23872
|
return out2;
|
|
23334
23873
|
}
|
|
@@ -23457,6 +23996,9 @@ function describeOneShotAgentError(stderr) {
|
|
|
23457
23996
|
if (!detail) return null;
|
|
23458
23997
|
return `Preview detection couldn't run \u2014 the agent answered ${m[1]}: ${detail}`;
|
|
23459
23998
|
}
|
|
23999
|
+
function previewProviderCreditsMessage(provider) {
|
|
24000
|
+
return `Preview detection couldn't run \u2014 your ${provider} account has no credits left. Top up at your provider, or switch this session to another agent.`;
|
|
24001
|
+
}
|
|
23460
24002
|
var RAW_EXCERPT_LIMIT = 1e3;
|
|
23461
24003
|
function describeDetectionFailure(raw) {
|
|
23462
24004
|
const text = raw?.trim() ?? "";
|
|
@@ -23949,8 +24491,8 @@ function isJsInstallCommand(cmd, args2) {
|
|
|
23949
24491
|
}
|
|
23950
24492
|
|
|
23951
24493
|
// src/services/preview/script-candidates.ts
|
|
23952
|
-
var
|
|
23953
|
-
var
|
|
24494
|
+
var fs43 = __toESM(require("fs"));
|
|
24495
|
+
var path50 = __toESM(require("path"));
|
|
23954
24496
|
var EXCLUDE_RE = /(^|:)(deploy|publish|release|build|test|e2e|lint|format|typecheck|type-check|clean|prebuild|postinstall|preinstall|prepare|install|migrate|seed|db|prisma|codegen|storybook-build)(:|$)/i;
|
|
23955
24497
|
var EXCLUDE_BODY_RE = /\b(run:android|run:ios|gradlew|fastlane|xcodebuild|eas build|eas submit)\b/i;
|
|
23956
24498
|
var MAX_APPS = 40;
|
|
@@ -23968,7 +24510,7 @@ function frameworkFor(pkg, body) {
|
|
|
23968
24510
|
}
|
|
23969
24511
|
function readPkg(file) {
|
|
23970
24512
|
try {
|
|
23971
|
-
return JSON.parse(
|
|
24513
|
+
return JSON.parse(fs43.readFileSync(file, "utf8"));
|
|
23972
24514
|
} catch {
|
|
23973
24515
|
return null;
|
|
23974
24516
|
}
|
|
@@ -23978,7 +24520,7 @@ function expandGlob(root, pattern) {
|
|
|
23978
24520
|
if (!clean.endsWith("/*")) return [clean];
|
|
23979
24521
|
const base = clean.slice(0, -2);
|
|
23980
24522
|
try {
|
|
23981
|
-
return
|
|
24523
|
+
return fs43.readdirSync(path50.join(root, base), { withFileTypes: true }).filter((d3) => d3.isDirectory() && !d3.name.startsWith(".") && d3.name !== "node_modules").map((d3) => path50.join(base, d3.name));
|
|
23982
24524
|
} catch {
|
|
23983
24525
|
return [];
|
|
23984
24526
|
}
|
|
@@ -23987,7 +24529,7 @@ function workspaceDirs(root, rootPkg) {
|
|
|
23987
24529
|
const ws = rootPkg?.workspaces;
|
|
23988
24530
|
const patterns = Array.isArray(ws) ? ws : ws?.packages ?? [];
|
|
23989
24531
|
try {
|
|
23990
|
-
const pnpm =
|
|
24532
|
+
const pnpm = fs43.readFileSync(path50.join(root, "pnpm-workspace.yaml"), "utf8");
|
|
23991
24533
|
for (const m of pnpm.matchAll(/^\s*-\s*['"]?([^'"\n]+)['"]?\s*$/gm)) patterns.push(m[1]);
|
|
23992
24534
|
} catch {
|
|
23993
24535
|
}
|
|
@@ -23998,14 +24540,14 @@ function workspaceDirs(root, rootPkg) {
|
|
|
23998
24540
|
}
|
|
23999
24541
|
function listScriptCandidates(root) {
|
|
24000
24542
|
const out2 = [];
|
|
24001
|
-
const rootPkg = readPkg(
|
|
24543
|
+
const rootPkg = readPkg(path50.join(root, "package.json"));
|
|
24002
24544
|
const add = (pkg, appDir) => {
|
|
24003
24545
|
for (const [script, body] of Object.entries(pkg.scripts ?? {})) {
|
|
24004
24546
|
if (out2.length >= MAX_CANDIDATES) return;
|
|
24005
24547
|
if (EXCLUDE_RE.test(script) || EXCLUDE_BODY_RE.test(body)) continue;
|
|
24006
24548
|
const fw = frameworkFor(pkg, body);
|
|
24007
24549
|
out2.push({
|
|
24008
|
-
app: pkg.name ?? (appDir === "." ?
|
|
24550
|
+
app: pkg.name ?? (appDir === "." ? path50.basename(root) : appDir),
|
|
24009
24551
|
appDir,
|
|
24010
24552
|
script,
|
|
24011
24553
|
body,
|
|
@@ -24019,8 +24561,8 @@ function listScriptCandidates(root) {
|
|
|
24019
24561
|
};
|
|
24020
24562
|
if (rootPkg) add(rootPkg, ".");
|
|
24021
24563
|
for (const dir of workspaceDirs(root, rootPkg)) {
|
|
24022
|
-
const pkg = readPkg(
|
|
24023
|
-
if (pkg) add(pkg, dir.split(
|
|
24564
|
+
const pkg = readPkg(path50.join(root, dir, "package.json"));
|
|
24565
|
+
if (pkg) add(pkg, dir.split(path50.sep).join("/"));
|
|
24024
24566
|
}
|
|
24025
24567
|
return out2;
|
|
24026
24568
|
}
|
|
@@ -24202,19 +24744,19 @@ function activePreviewSessionIds() {
|
|
|
24202
24744
|
|
|
24203
24745
|
// src/services/preview/start-orchestrator.ts
|
|
24204
24746
|
var import_child_process20 = require("child_process");
|
|
24205
|
-
var
|
|
24206
|
-
var
|
|
24747
|
+
var fs46 = __toESM(require("fs"));
|
|
24748
|
+
var path53 = __toESM(require("path"));
|
|
24207
24749
|
var import_which3 = __toESM(require("which"));
|
|
24208
24750
|
|
|
24209
24751
|
// src/services/project-env/index.ts
|
|
24210
24752
|
var import_fs6 = require("fs");
|
|
24211
|
-
var
|
|
24753
|
+
var path52 = __toESM(require("path"));
|
|
24212
24754
|
|
|
24213
24755
|
// src/beads/project-key.ts
|
|
24214
24756
|
var import_child_process19 = require("child_process");
|
|
24215
24757
|
var crypto2 = __toESM(require("crypto"));
|
|
24216
|
-
var
|
|
24217
|
-
var
|
|
24758
|
+
var fs44 = __toESM(require("fs"));
|
|
24759
|
+
var path51 = __toESM(require("path"));
|
|
24218
24760
|
function normalizeOrigin(raw) {
|
|
24219
24761
|
const trimmed = raw.trim();
|
|
24220
24762
|
if (!trimmed) return null;
|
|
@@ -24240,17 +24782,17 @@ function normalizeOrigin(raw) {
|
|
|
24240
24782
|
return `${host2}/${pathPart}`;
|
|
24241
24783
|
}
|
|
24242
24784
|
function findRepoRoot(cwd) {
|
|
24243
|
-
let dir =
|
|
24785
|
+
let dir = path51.resolve(cwd);
|
|
24244
24786
|
const seen2 = /* @__PURE__ */ new Set();
|
|
24245
24787
|
for (let i = 0; i < 256; i++) {
|
|
24246
24788
|
if (seen2.has(dir)) return null;
|
|
24247
24789
|
seen2.add(dir);
|
|
24248
24790
|
try {
|
|
24249
|
-
const stat3 =
|
|
24791
|
+
const stat3 = fs44.statSync(path51.join(dir, ".git"), { throwIfNoEntry: false });
|
|
24250
24792
|
if (stat3 && (stat3.isDirectory() || stat3.isFile())) return dir;
|
|
24251
24793
|
} catch {
|
|
24252
24794
|
}
|
|
24253
|
-
const parent =
|
|
24795
|
+
const parent = path51.dirname(dir);
|
|
24254
24796
|
if (parent === dir) return null;
|
|
24255
24797
|
dir = parent;
|
|
24256
24798
|
}
|
|
@@ -24261,7 +24803,7 @@ var _execSeam3 = {
|
|
|
24261
24803
|
const out2 = (0, import_child_process19.execFileSync)(file, args2, opts);
|
|
24262
24804
|
return typeof out2 === "string" ? out2 : out2.toString("utf8");
|
|
24263
24805
|
},
|
|
24264
|
-
realpath: (p2) =>
|
|
24806
|
+
realpath: (p2) => fs44.realpathSync(p2)
|
|
24265
24807
|
};
|
|
24266
24808
|
function readOrigin(cwd) {
|
|
24267
24809
|
try {
|
|
@@ -24290,7 +24832,7 @@ function deriveProjectIdentity(cwd = process.cwd()) {
|
|
|
24290
24832
|
} catch {
|
|
24291
24833
|
}
|
|
24292
24834
|
const hash = crypto2.createHash("sha256").update(real).digest("hex");
|
|
24293
|
-
return { projectKey: `path:${hash}`, projectLabel:
|
|
24835
|
+
return { projectKey: `path:${hash}`, projectLabel: path51.basename(real) || "project" };
|
|
24294
24836
|
}
|
|
24295
24837
|
|
|
24296
24838
|
// src/services/project-env/index.ts
|
|
@@ -24303,7 +24845,7 @@ async function readIfExists(p2) {
|
|
|
24303
24845
|
}
|
|
24304
24846
|
async function syncProjectEnvUp(cwd, ctx) {
|
|
24305
24847
|
if (!ctx.pluginAuthToken) return;
|
|
24306
|
-
const content = await readIfExists(
|
|
24848
|
+
const content = await readIfExists(path52.join(cwd, ".env"));
|
|
24307
24849
|
if (content == null) return;
|
|
24308
24850
|
try {
|
|
24309
24851
|
const { projectKey, projectLabel } = deriveProjectIdentity(cwd);
|
|
@@ -24325,7 +24867,7 @@ async function syncProjectEnvUp(cwd, ctx) {
|
|
|
24325
24867
|
}
|
|
24326
24868
|
async function restoreProjectEnvIfMissing(cwd, ctx) {
|
|
24327
24869
|
if (!ctx.pluginAuthToken) return false;
|
|
24328
|
-
const envPath =
|
|
24870
|
+
const envPath = path52.join(cwd, ".env");
|
|
24329
24871
|
if (await readIfExists(envPath) != null) return false;
|
|
24330
24872
|
try {
|
|
24331
24873
|
const { projectKey, projectLabel } = deriveProjectIdentity(cwd);
|
|
@@ -24336,7 +24878,7 @@ async function restoreProjectEnvIfMissing(cwd, ctx) {
|
|
|
24336
24878
|
projectKey
|
|
24337
24879
|
});
|
|
24338
24880
|
if (!stored) return false;
|
|
24339
|
-
const tmp =
|
|
24881
|
+
const tmp = path52.join(cwd, ".env.codeam-restore.tmp");
|
|
24340
24882
|
await import_fs6.promises.writeFile(tmp, stored.content, { encoding: "utf8", mode: 384 });
|
|
24341
24883
|
await import_fs6.promises.rename(tmp, envPath);
|
|
24342
24884
|
log.info("project-env", `restored .env (${stored.keyCount} vars) for ${projectLabel}`);
|
|
@@ -25119,8 +25661,8 @@ function normalizeDetectionForSpawn(detection, cwd) {
|
|
|
25119
25661
|
if (args2.length === 0) return detection;
|
|
25120
25662
|
const binName = args2[0];
|
|
25121
25663
|
if (binName.startsWith("-")) return detection;
|
|
25122
|
-
const binPath =
|
|
25123
|
-
if (!
|
|
25664
|
+
const binPath = path53.join(cwd, "node_modules", ".bin", binName);
|
|
25665
|
+
if (!fs46.existsSync(binPath)) return detection;
|
|
25124
25666
|
return {
|
|
25125
25667
|
...detection,
|
|
25126
25668
|
command: binPath,
|
|
@@ -25531,9 +26073,9 @@ async function bringUpPublicUrl(ctx, tunnelPort) {
|
|
|
25531
26073
|
|
|
25532
26074
|
// src/beads/bd-adapter.ts
|
|
25533
26075
|
var import_child_process21 = require("child_process");
|
|
25534
|
-
var
|
|
25535
|
-
var
|
|
25536
|
-
var
|
|
26076
|
+
var fs47 = __toESM(require("fs"));
|
|
26077
|
+
var os34 = __toESM(require("os"));
|
|
26078
|
+
var path54 = __toESM(require("path"));
|
|
25537
26079
|
var BD_PACKAGE = "@beads/bd";
|
|
25538
26080
|
function resolveBundledBdBinary() {
|
|
25539
26081
|
return _resolveSeam.resolveBundled();
|
|
@@ -25545,11 +26087,11 @@ function _defaultResolveBundled() {
|
|
|
25545
26087
|
} catch {
|
|
25546
26088
|
return null;
|
|
25547
26089
|
}
|
|
25548
|
-
const binDir =
|
|
26090
|
+
const binDir = path54.join(path54.dirname(pkgJsonPath), "bin");
|
|
25549
26091
|
const binaryName = process.platform === "win32" ? "bd.exe" : "bd";
|
|
25550
|
-
const binaryPath =
|
|
26092
|
+
const binaryPath = path54.join(binDir, binaryName);
|
|
25551
26093
|
try {
|
|
25552
|
-
|
|
26094
|
+
fs47.accessSync(binaryPath, fs47.constants.F_OK);
|
|
25553
26095
|
return binaryPath;
|
|
25554
26096
|
} catch {
|
|
25555
26097
|
return null;
|
|
@@ -25559,13 +26101,13 @@ function resolveBdOnPath() {
|
|
|
25559
26101
|
return _resolveSeam.resolveOnPath();
|
|
25560
26102
|
}
|
|
25561
26103
|
function _defaultResolveOnPath() {
|
|
25562
|
-
const dirs = (process.env.PATH ?? "").split(
|
|
26104
|
+
const dirs = (process.env.PATH ?? "").split(path54.delimiter).filter(Boolean);
|
|
25563
26105
|
const candidates = process.platform === "win32" ? ["bd.exe", "bd.cmd", "bd"] : ["bd"];
|
|
25564
26106
|
for (const dir of dirs) {
|
|
25565
26107
|
for (const candidate of candidates) {
|
|
25566
|
-
const full =
|
|
26108
|
+
const full = path54.join(dir, candidate);
|
|
25567
26109
|
try {
|
|
25568
|
-
|
|
26110
|
+
fs47.accessSync(full, fs47.constants.F_OK);
|
|
25569
26111
|
return full;
|
|
25570
26112
|
} catch {
|
|
25571
26113
|
}
|
|
@@ -25650,7 +26192,7 @@ var BdAdapter = class {
|
|
|
25650
26192
|
const env = { ...process.env };
|
|
25651
26193
|
if (!env.HOME) {
|
|
25652
26194
|
try {
|
|
25653
|
-
const home =
|
|
26195
|
+
const home = os34.homedir();
|
|
25654
26196
|
if (home) env.HOME = home;
|
|
25655
26197
|
} catch {
|
|
25656
26198
|
}
|
|
@@ -25742,9 +26284,9 @@ function coerceIssue(row, projectKey) {
|
|
|
25742
26284
|
|
|
25743
26285
|
// src/beads/provisioner.ts
|
|
25744
26286
|
var import_child_process24 = require("child_process");
|
|
25745
|
-
var
|
|
25746
|
-
var
|
|
25747
|
-
var
|
|
26287
|
+
var fs49 = __toESM(require("fs"));
|
|
26288
|
+
var os36 = __toESM(require("os"));
|
|
26289
|
+
var path56 = __toESM(require("path"));
|
|
25748
26290
|
|
|
25749
26291
|
// src/beads/install-bd.ts
|
|
25750
26292
|
var import_child_process22 = require("child_process");
|
|
@@ -25809,9 +26351,9 @@ async function installBd(platform3 = process.platform) {
|
|
|
25809
26351
|
|
|
25810
26352
|
// src/beads/install-dolt.ts
|
|
25811
26353
|
var import_child_process23 = require("child_process");
|
|
25812
|
-
var
|
|
25813
|
-
var
|
|
25814
|
-
var
|
|
26354
|
+
var fs48 = __toESM(require("fs"));
|
|
26355
|
+
var os35 = __toESM(require("os"));
|
|
26356
|
+
var path55 = __toESM(require("path"));
|
|
25815
26357
|
var DOLT_INSTALL_SH_URL = "https://github.com/dolthub/dolt/releases/latest/download/install.sh";
|
|
25816
26358
|
var DOLT_MSI_URL = "https://github.com/dolthub/dolt/releases/latest/download/dolt-windows-amd64.msi";
|
|
25817
26359
|
function resolveDoltInstallStrategy(platform3) {
|
|
@@ -25900,14 +26442,14 @@ async function installDoltToDir(targetDir, platform3 = process.platform, arch2 =
|
|
|
25900
26442
|
return result;
|
|
25901
26443
|
}
|
|
25902
26444
|
var _doltPathSeam = {
|
|
25903
|
-
homedir: () =>
|
|
26445
|
+
homedir: () => os35.homedir(),
|
|
25904
26446
|
getPath: () => process.env.PATH ?? "",
|
|
25905
26447
|
setPath: (p2) => {
|
|
25906
26448
|
process.env.PATH = p2;
|
|
25907
26449
|
},
|
|
25908
26450
|
exists: (p2) => {
|
|
25909
26451
|
try {
|
|
25910
|
-
|
|
26452
|
+
fs48.accessSync(p2, fs48.constants.F_OK);
|
|
25911
26453
|
return true;
|
|
25912
26454
|
} catch {
|
|
25913
26455
|
return false;
|
|
@@ -25918,7 +26460,7 @@ function doltBinaryNames(platform3) {
|
|
|
25918
26460
|
return platform3 === "win32" ? ["dolt.exe", "dolt.cmd", "dolt"] : ["dolt"];
|
|
25919
26461
|
}
|
|
25920
26462
|
function knownDoltDirs(platform3) {
|
|
25921
|
-
const P3 = platform3 === "win32" ?
|
|
26463
|
+
const P3 = platform3 === "win32" ? path55.win32 : path55.posix;
|
|
25922
26464
|
const home = _doltPathSeam.homedir();
|
|
25923
26465
|
if (platform3 === "win32") {
|
|
25924
26466
|
return [
|
|
@@ -25934,7 +26476,7 @@ function knownDoltDirs(platform3) {
|
|
|
25934
26476
|
].filter(Boolean);
|
|
25935
26477
|
}
|
|
25936
26478
|
function ensureDoltResolvable(platform3 = process.platform) {
|
|
25937
|
-
const P3 = platform3 === "win32" ?
|
|
26479
|
+
const P3 = platform3 === "win32" ? path55.win32 : path55.posix;
|
|
25938
26480
|
const delim = platform3 === "win32" ? ";" : ":";
|
|
25939
26481
|
const names = doltBinaryNames(platform3);
|
|
25940
26482
|
const pathDirs = _doltPathSeam.getPath().split(delim).filter(Boolean);
|
|
@@ -26128,17 +26670,17 @@ function remoteHasDoltData(cwd) {
|
|
|
26128
26670
|
}
|
|
26129
26671
|
var _linkSeam = {
|
|
26130
26672
|
platform: () => process.platform,
|
|
26131
|
-
homedir: () =>
|
|
26673
|
+
homedir: () => os36.homedir(),
|
|
26132
26674
|
isWritableDir: (dir) => {
|
|
26133
26675
|
try {
|
|
26134
|
-
|
|
26676
|
+
fs49.accessSync(dir, fs49.constants.W_OK);
|
|
26135
26677
|
return true;
|
|
26136
26678
|
} catch {
|
|
26137
26679
|
return false;
|
|
26138
26680
|
}
|
|
26139
26681
|
},
|
|
26140
26682
|
ensureDir: (dir) => {
|
|
26141
|
-
|
|
26683
|
+
fs49.mkdirSync(dir, { recursive: true });
|
|
26142
26684
|
},
|
|
26143
26685
|
/**
|
|
26144
26686
|
* A directory to symlink `bd` into so the AGENT's shell + Claude Code's
|
|
@@ -26159,9 +26701,9 @@ var _linkSeam = {
|
|
|
26159
26701
|
* which `linkBdOntoPath` creates if missing.
|
|
26160
26702
|
*/
|
|
26161
26703
|
cliBinDir: () => {
|
|
26162
|
-
const pathDirs = (process.env.PATH ?? "").split(
|
|
26704
|
+
const pathDirs = (process.env.PATH ?? "").split(path56.delimiter).filter(Boolean);
|
|
26163
26705
|
const home = _linkSeam.homedir();
|
|
26164
|
-
const localBin = home ?
|
|
26706
|
+
const localBin = home ? path56.join(home, ".local", "bin") : null;
|
|
26165
26707
|
if (localBin) {
|
|
26166
26708
|
try {
|
|
26167
26709
|
_linkSeam.ensureDir(localBin);
|
|
@@ -26171,16 +26713,16 @@ var _linkSeam = {
|
|
|
26171
26713
|
const candidates = [];
|
|
26172
26714
|
if (localBin) candidates.push(localBin);
|
|
26173
26715
|
try {
|
|
26174
|
-
candidates.push(
|
|
26716
|
+
candidates.push(path56.dirname(process.execPath));
|
|
26175
26717
|
} catch {
|
|
26176
26718
|
}
|
|
26177
26719
|
candidates.push("/usr/local/bin");
|
|
26178
26720
|
const entry = process.argv[1];
|
|
26179
26721
|
if (entry) {
|
|
26180
26722
|
try {
|
|
26181
|
-
candidates.push(
|
|
26723
|
+
candidates.push(path56.dirname(fs49.realpathSync(entry)));
|
|
26182
26724
|
} catch {
|
|
26183
|
-
candidates.push(
|
|
26725
|
+
candidates.push(path56.dirname(entry));
|
|
26184
26726
|
}
|
|
26185
26727
|
}
|
|
26186
26728
|
const onPathWritable = candidates.find(
|
|
@@ -26192,20 +26734,20 @@ var _linkSeam = {
|
|
|
26192
26734
|
/** Current symlink target at `linkPath`, or null when absent / not a link. */
|
|
26193
26735
|
readlink: (linkPath) => {
|
|
26194
26736
|
try {
|
|
26195
|
-
return
|
|
26737
|
+
return fs49.readlinkSync(linkPath);
|
|
26196
26738
|
} catch {
|
|
26197
26739
|
return null;
|
|
26198
26740
|
}
|
|
26199
26741
|
},
|
|
26200
|
-
unlink: (linkPath) =>
|
|
26201
|
-
symlink: (target, linkPath) =>
|
|
26742
|
+
unlink: (linkPath) => fs49.unlinkSync(linkPath),
|
|
26743
|
+
symlink: (target, linkPath) => fs49.symlinkSync(target, linkPath)
|
|
26202
26744
|
};
|
|
26203
26745
|
function linkBdOntoPath(binaryPath) {
|
|
26204
26746
|
if (_linkSeam.platform() === "win32") return;
|
|
26205
26747
|
const binDir = _linkSeam.cliBinDir();
|
|
26206
26748
|
if (!binDir) return;
|
|
26207
26749
|
_linkSeam.ensureDir(binDir);
|
|
26208
|
-
const linkPath =
|
|
26750
|
+
const linkPath = path56.join(binDir, "bd");
|
|
26209
26751
|
if (linkPath === binaryPath) return;
|
|
26210
26752
|
const current2 = _linkSeam.readlink(linkPath);
|
|
26211
26753
|
if (current2 === binaryPath) return;
|
|
@@ -26419,16 +26961,16 @@ function dedupeRecipes(agents) {
|
|
|
26419
26961
|
}
|
|
26420
26962
|
function ensureLocalGitExclude(cwd, patterns) {
|
|
26421
26963
|
try {
|
|
26422
|
-
const gitDir =
|
|
26423
|
-
if (!
|
|
26424
|
-
const file =
|
|
26425
|
-
|
|
26426
|
-
const current2 =
|
|
26964
|
+
const gitDir = path56.join(cwd, ".git");
|
|
26965
|
+
if (!fs49.statSync(gitDir).isDirectory()) return;
|
|
26966
|
+
const file = path56.join(gitDir, "info", "exclude");
|
|
26967
|
+
fs49.mkdirSync(path56.dirname(file), { recursive: true });
|
|
26968
|
+
const current2 = fs49.existsSync(file) ? fs49.readFileSync(file, "utf8") : "";
|
|
26427
26969
|
const have = new Set(current2.split(/\r?\n/).map((l) => l.trim()));
|
|
26428
26970
|
const missing = patterns.filter((p2) => !have.has(p2));
|
|
26429
26971
|
if (missing.length === 0) return;
|
|
26430
26972
|
const prefix = current2.length > 0 && !current2.endsWith("\n") ? "\n" : "";
|
|
26431
|
-
|
|
26973
|
+
fs49.appendFileSync(file, `${prefix}# CodeAgent: beads state stays local
|
|
26432
26974
|
${missing.join("\n")}
|
|
26433
26975
|
`);
|
|
26434
26976
|
} catch {
|
|
@@ -26437,7 +26979,7 @@ ${missing.join("\n")}
|
|
|
26437
26979
|
|
|
26438
26980
|
// src/beads/watcher.ts
|
|
26439
26981
|
var crypto4 = __toESM(require("crypto"));
|
|
26440
|
-
var
|
|
26982
|
+
var path57 = __toESM(require("path"));
|
|
26441
26983
|
var API_BASE5 = resolveApiBaseUrl();
|
|
26442
26984
|
var DEBOUNCE_MS2 = 400;
|
|
26443
26985
|
var ZERO_SUMMARY = {
|
|
@@ -26461,7 +27003,7 @@ var BeadsWatcher = class {
|
|
|
26461
27003
|
constructor(opts) {
|
|
26462
27004
|
this.opts = opts;
|
|
26463
27005
|
this.bd = opts.adapter ?? new BdAdapter({ cwd: opts.cwd, beadsDir: opts.beadsDir });
|
|
26464
|
-
this.feedPath = opts.feedPath ??
|
|
27006
|
+
this.feedPath = opts.feedPath ?? path57.join(opts.cwd ?? process.cwd(), ".beads", "last-touched");
|
|
26465
27007
|
this.apiBase = opts.apiBaseUrl ?? API_BASE5;
|
|
26466
27008
|
}
|
|
26467
27009
|
opts;
|
|
@@ -26715,41 +27257,6 @@ async function handleBeadsActionCommand(action, started) {
|
|
|
26715
27257
|
var import_node_fs8 = __toESM(require("fs"));
|
|
26716
27258
|
var import_node_os5 = __toESM(require("os"));
|
|
26717
27259
|
var import_node_path6 = __toESM(require("path"));
|
|
26718
|
-
|
|
26719
|
-
// src/lib/restrict-to-owner.ts
|
|
26720
|
-
var import_node_fs7 = __toESM(require("fs"));
|
|
26721
|
-
var import_node_os4 = __toESM(require("os"));
|
|
26722
|
-
var import_node_child_process18 = require("child_process");
|
|
26723
|
-
var BROAD_WINDOWS_SIDS = [
|
|
26724
|
-
"*S-1-1-0",
|
|
26725
|
-
"*S-1-5-11",
|
|
26726
|
-
"*S-1-5-32-545",
|
|
26727
|
-
"*S-1-5-32-544",
|
|
26728
|
-
"*S-1-5-18"
|
|
26729
|
-
];
|
|
26730
|
-
function restrictToOwner(filePath) {
|
|
26731
|
-
try {
|
|
26732
|
-
if (process.platform === "win32") {
|
|
26733
|
-
const username = import_node_os4.default.userInfo().username;
|
|
26734
|
-
(0, import_node_child_process18.execFileSync)(
|
|
26735
|
-
"icacls",
|
|
26736
|
-
[
|
|
26737
|
-
filePath,
|
|
26738
|
-
"/inheritance:r",
|
|
26739
|
-
"/grant:r",
|
|
26740
|
-
`${username}:F`,
|
|
26741
|
-
...BROAD_WINDOWS_SIDS.flatMap((sid) => ["/remove", sid])
|
|
26742
|
-
],
|
|
26743
|
-
{ stdio: "ignore" }
|
|
26744
|
-
);
|
|
26745
|
-
} else {
|
|
26746
|
-
import_node_fs7.default.chmodSync(filePath, 384);
|
|
26747
|
-
}
|
|
26748
|
-
} catch {
|
|
26749
|
-
}
|
|
26750
|
-
}
|
|
26751
|
-
|
|
26752
|
-
// src/beads/config-store.ts
|
|
26753
27260
|
function beadsConfigPath() {
|
|
26754
27261
|
return import_node_path6.default.join(import_node_os5.default.homedir(), ".codeam", "beads-config.json");
|
|
26755
27262
|
}
|
|
@@ -27036,8 +27543,8 @@ function cleanupAttachmentTempFiles() {
|
|
|
27036
27543
|
function saveFilesTemp(files) {
|
|
27037
27544
|
return files.filter(({ base64 }) => base64 && base64.length > 0).map(({ filename, base64 }) => {
|
|
27038
27545
|
const safeName = filename.replace(/[^a-zA-Z0-9._-]/g, "_").slice(0, 80);
|
|
27039
|
-
const tmpPath =
|
|
27040
|
-
|
|
27546
|
+
const tmpPath = path61.join(os41.tmpdir(), `codeam-${(0, import_crypto2.randomUUID)()}-${safeName}`);
|
|
27547
|
+
fs53.writeFileSync(tmpPath, Buffer.from(base64, "base64"));
|
|
27041
27548
|
pendingAttachmentFiles.add(tmpPath);
|
|
27042
27549
|
return tmpPath;
|
|
27043
27550
|
});
|
|
@@ -27272,10 +27779,10 @@ var listFiles = async (ctx, cmd, parsed) => {
|
|
|
27272
27779
|
await ctx.relay.sendResult(cmd.id, "completed", result);
|
|
27273
27780
|
};
|
|
27274
27781
|
var envReadH = async (ctx, cmd) => {
|
|
27275
|
-
const envPath =
|
|
27782
|
+
const envPath = path61.join(process.cwd(), ".env");
|
|
27276
27783
|
await restoreProjectEnvIfMissing(process.cwd(), ctx);
|
|
27277
27784
|
try {
|
|
27278
|
-
const raw = await
|
|
27785
|
+
const raw = await fs53.promises.readFile(envPath, "utf8");
|
|
27279
27786
|
await ctx.relay.sendResult(cmd.id, "completed", {
|
|
27280
27787
|
exists: true,
|
|
27281
27788
|
vars: parseDotenv(raw)
|
|
@@ -27304,7 +27811,7 @@ var envParseH = async (ctx, cmd, parsed) => {
|
|
|
27304
27811
|
const existing = /* @__PURE__ */ new Map();
|
|
27305
27812
|
if (!replace) {
|
|
27306
27813
|
try {
|
|
27307
|
-
const raw = await
|
|
27814
|
+
const raw = await fs53.promises.readFile(path61.join(process.cwd(), ".env"), "utf8");
|
|
27308
27815
|
for (const v of parseDotenv(raw)) existing.set(v.key, v.value);
|
|
27309
27816
|
} catch {
|
|
27310
27817
|
}
|
|
@@ -27344,15 +27851,15 @@ var envWriteH = async (ctx, cmd, parsed) => {
|
|
|
27344
27851
|
}
|
|
27345
27852
|
seen2.add(v.key);
|
|
27346
27853
|
}
|
|
27347
|
-
const envPath =
|
|
27348
|
-
const tmpPath =
|
|
27854
|
+
const envPath = path61.join(process.cwd(), ".env");
|
|
27855
|
+
const tmpPath = path61.join(process.cwd(), ".env.codeam.tmp");
|
|
27349
27856
|
try {
|
|
27350
|
-
await
|
|
27351
|
-
await
|
|
27857
|
+
await fs53.promises.writeFile(tmpPath, serializeDotenv(vars), "utf8");
|
|
27858
|
+
await fs53.promises.rename(tmpPath, envPath);
|
|
27352
27859
|
await ctx.relay.sendResult(cmd.id, "completed", { ok: true, count: vars.length });
|
|
27353
27860
|
void syncProjectEnvUp(process.cwd(), ctx);
|
|
27354
27861
|
} catch (err) {
|
|
27355
|
-
await
|
|
27862
|
+
await fs53.promises.rm(tmpPath, { force: true }).catch(() => void 0);
|
|
27356
27863
|
await ctx.relay.sendResult(cmd.id, "failed", { error: err.message });
|
|
27357
27864
|
}
|
|
27358
27865
|
};
|
|
@@ -27684,9 +28191,9 @@ var CLI_UPDATE_MAX_ATTEMPTS = 3;
|
|
|
27684
28191
|
function buildNpmInstallInvocation(opts) {
|
|
27685
28192
|
const entryScript = opts?.entryScript ?? process.argv[1] ?? "";
|
|
27686
28193
|
const execPath = opts?.execPath ?? process.execPath;
|
|
27687
|
-
const exists2 = opts?.existsSync ??
|
|
28194
|
+
const exists2 = opts?.existsSync ?? fs53.existsSync;
|
|
27688
28195
|
const platform3 = opts?.platform ?? process.platform;
|
|
27689
|
-
const p2 = platform3 === "win32" ?
|
|
28196
|
+
const p2 = platform3 === "win32" ? path61.win32 : path61.posix;
|
|
27690
28197
|
const normalized = entryScript.split(/[\\/]/).join("/");
|
|
27691
28198
|
const marker = "/lib/node_modules/codeam-cli/";
|
|
27692
28199
|
const markerIdx = normalized.indexOf(marker);
|
|
@@ -27708,7 +28215,7 @@ function isPermissionError(stderr) {
|
|
|
27708
28215
|
function resolveGlobalNodeModulesDir(opts) {
|
|
27709
28216
|
const entryScript = opts?.entryScript ?? process.argv[1] ?? "";
|
|
27710
28217
|
const platform3 = opts?.platform ?? process.platform;
|
|
27711
|
-
const p2 = platform3 === "win32" ?
|
|
28218
|
+
const p2 = platform3 === "win32" ? path61.win32 : path61.posix;
|
|
27712
28219
|
const marker = "/lib/node_modules/codeam-cli/";
|
|
27713
28220
|
const markerIdx = entryScript.split(/[\\/]/).join("/").indexOf(marker);
|
|
27714
28221
|
if (markerIdx <= 0) return null;
|
|
@@ -27718,9 +28225,9 @@ function resolveGlobalNodeModulesDir(opts) {
|
|
|
27718
28225
|
var STALE_STAGING_AGE_MS = CLI_UPDATE_INSTALL_TIMEOUT_MS;
|
|
27719
28226
|
function sweepStaleCliStagingDirs(nodeModulesDir, now = Date.now(), deps) {
|
|
27720
28227
|
if (!nodeModulesDir) return 0;
|
|
27721
|
-
const readdirSync16 = deps?.readdirSync ??
|
|
27722
|
-
const statSync16 = deps?.statSync ??
|
|
27723
|
-
const rmSync10 = deps?.rmSync ??
|
|
28228
|
+
const readdirSync16 = deps?.readdirSync ?? fs53.readdirSync;
|
|
28229
|
+
const statSync16 = deps?.statSync ?? fs53.statSync;
|
|
28230
|
+
const rmSync10 = deps?.rmSync ?? fs53.rmSync;
|
|
27724
28231
|
let removed = 0;
|
|
27725
28232
|
let entries;
|
|
27726
28233
|
try {
|
|
@@ -27730,7 +28237,7 @@ function sweepStaleCliStagingDirs(nodeModulesDir, now = Date.now(), deps) {
|
|
|
27730
28237
|
}
|
|
27731
28238
|
for (const name of entries) {
|
|
27732
28239
|
if (!/^\.codeam-cli-/.test(name)) continue;
|
|
27733
|
-
const full =
|
|
28240
|
+
const full = path61.join(nodeModulesDir, name);
|
|
27734
28241
|
try {
|
|
27735
28242
|
const st3 = statSync16(full);
|
|
27736
28243
|
if (now - st3.mtimeMs < STALE_STAGING_AGE_MS) continue;
|
|
@@ -28102,11 +28609,13 @@ async function runDetectOneShot(generate, timeoutMs = PREVIEW_DETECT_TIMEOUT_MS)
|
|
|
28102
28609
|
const onStderr = (chunk) => {
|
|
28103
28610
|
stderr = (stderr + chunk).slice(-4e3);
|
|
28104
28611
|
};
|
|
28612
|
+
const onFailedOutput = (stdout) => onStderr(`
|
|
28613
|
+
${stdout}`);
|
|
28105
28614
|
const deadline = new Promise((resolve12) => {
|
|
28106
28615
|
timer = setTimeout(() => resolve12({ raw: null, timedOut: true, stderr }), timeoutMs);
|
|
28107
28616
|
timer.unref?.();
|
|
28108
28617
|
});
|
|
28109
|
-
const oneShot = generate(PREVIEW_DETECT_PROMPT, { timeoutMs, onStderr }).then(
|
|
28618
|
+
const oneShot = generate(PREVIEW_DETECT_PROMPT, { timeoutMs, onStderr, onFailedOutput }).then(
|
|
28110
28619
|
(raw) => ({ raw, timedOut: false, stderr }),
|
|
28111
28620
|
(err) => {
|
|
28112
28621
|
log.info("preview", `detect: generateOneShot threw: ${String(err)}`);
|
|
@@ -28170,6 +28679,15 @@ async function resolvePreviewDetection(args2) {
|
|
|
28170
28679
|
--- salida cruda del agente (acotada) ---
|
|
28171
28680
|
${failure?.rawExcerpt ?? ""}`
|
|
28172
28681
|
);
|
|
28682
|
+
if (looksLikeByoProviderBilling(`${raw ?? ""}
|
|
28683
|
+
${stderr}`)) {
|
|
28684
|
+
log.info("preview", "detect: provider out of credits \u2014 emitting preview_error");
|
|
28685
|
+
emit2(USER_EVENTS.PREVIEW_ERROR, {
|
|
28686
|
+
stage: "detection",
|
|
28687
|
+
message: previewProviderCreditsMessage(byoProviderName({ agent: runtime.id }))
|
|
28688
|
+
});
|
|
28689
|
+
return null;
|
|
28690
|
+
}
|
|
28173
28691
|
emit2(USER_EVENTS.PREVIEW_ERROR, {
|
|
28174
28692
|
stage: "detection",
|
|
28175
28693
|
// El mensaje sale del diagnostico: decir "JSON invalido" cuando el
|
|
@@ -28765,7 +29283,7 @@ function resolveTokenValue(args2) {
|
|
|
28765
29283
|
if (fileFlag) {
|
|
28766
29284
|
const path98 = fileFlag.slice("--token-file=".length);
|
|
28767
29285
|
try {
|
|
28768
|
-
const content =
|
|
29286
|
+
const content = fs54.readFileSync(path98, "utf8").trim();
|
|
28769
29287
|
if (content.length === 0) fail(`--token-file ${path98} is empty`);
|
|
28770
29288
|
rmIfExistsQuiet(path98);
|
|
28771
29289
|
return content;
|
|
@@ -28859,12 +29377,12 @@ async function claim(token, pluginId, pluginSecretHash) {
|
|
|
28859
29377
|
}
|
|
28860
29378
|
}
|
|
28861
29379
|
function pairAutoLockPath() {
|
|
28862
|
-
return
|
|
29380
|
+
return path62.join(os42.homedir(), ".codeam", "pair-auto.lock");
|
|
28863
29381
|
}
|
|
28864
29382
|
var procRoot = "/proc";
|
|
28865
29383
|
function readProcFile(rel) {
|
|
28866
29384
|
try {
|
|
28867
|
-
return
|
|
29385
|
+
return fs54.readFileSync(path62.join(procRoot, rel), "utf8");
|
|
28868
29386
|
} catch {
|
|
28869
29387
|
return void 0;
|
|
28870
29388
|
}
|
|
@@ -28885,7 +29403,7 @@ function currentBootId() {
|
|
|
28885
29403
|
function readLockRecord(lockPath) {
|
|
28886
29404
|
let raw;
|
|
28887
29405
|
try {
|
|
28888
|
-
raw =
|
|
29406
|
+
raw = fs54.readFileSync(lockPath, "utf8");
|
|
28889
29407
|
} catch {
|
|
28890
29408
|
return void 0;
|
|
28891
29409
|
}
|
|
@@ -28934,7 +29452,7 @@ function isLiveLockHolder(rec) {
|
|
|
28934
29452
|
}
|
|
28935
29453
|
function releaseOwnLock(lockPath) {
|
|
28936
29454
|
try {
|
|
28937
|
-
if (readLockRecord(lockPath)?.pid === process.pid)
|
|
29455
|
+
if (readLockRecord(lockPath)?.pid === process.pid) fs54.unlinkSync(lockPath);
|
|
28938
29456
|
} catch {
|
|
28939
29457
|
}
|
|
28940
29458
|
}
|
|
@@ -28958,7 +29476,7 @@ function snapshotProcessTree(root) {
|
|
|
28958
29476
|
const children = /* @__PURE__ */ new Map();
|
|
28959
29477
|
let entries = [];
|
|
28960
29478
|
try {
|
|
28961
|
-
entries =
|
|
29479
|
+
entries = fs54.readdirSync(procRoot).filter((e) => /^\d+$/.test(e));
|
|
28962
29480
|
} catch {
|
|
28963
29481
|
}
|
|
28964
29482
|
for (const e of entries) {
|
|
@@ -28993,18 +29511,18 @@ function signalProcessTree(refs, signal) {
|
|
|
28993
29511
|
}
|
|
28994
29512
|
function daemonLockPath(sessionId) {
|
|
28995
29513
|
const safe = sessionId.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
28996
|
-
return
|
|
29514
|
+
return path62.join(os42.homedir(), ".codeam", `daemon-${safe}.lock`);
|
|
28997
29515
|
}
|
|
28998
29516
|
function acquireDaemonLock(sessionId) {
|
|
28999
29517
|
const lockPath = daemonLockPath(sessionId);
|
|
29000
29518
|
try {
|
|
29001
|
-
|
|
29519
|
+
fs54.mkdirSync(path62.dirname(lockPath), { recursive: true });
|
|
29002
29520
|
try {
|
|
29003
|
-
|
|
29521
|
+
fs54.writeFileSync(lockPath, ownLockBody(), { flag: "wx" });
|
|
29004
29522
|
} catch (e) {
|
|
29005
29523
|
if (e.code !== "EEXIST") throw e;
|
|
29006
29524
|
if (isLiveLockHolder(readLockRecord(lockPath))) return false;
|
|
29007
|
-
|
|
29525
|
+
fs54.writeFileSync(lockPath, ownLockBody());
|
|
29008
29526
|
}
|
|
29009
29527
|
const release3 = () => releaseOwnLock(lockPath);
|
|
29010
29528
|
process.once("exit", release3);
|
|
@@ -29024,13 +29542,13 @@ function acquireDaemonLock(sessionId) {
|
|
|
29024
29542
|
function acquireSingletonLock() {
|
|
29025
29543
|
const lockPath = pairAutoLockPath();
|
|
29026
29544
|
try {
|
|
29027
|
-
|
|
29545
|
+
fs54.mkdirSync(path62.dirname(lockPath), { recursive: true });
|
|
29028
29546
|
try {
|
|
29029
|
-
|
|
29547
|
+
fs54.writeFileSync(lockPath, ownLockBody(), { flag: "wx" });
|
|
29030
29548
|
} catch (e) {
|
|
29031
29549
|
if (e.code !== "EEXIST") throw e;
|
|
29032
29550
|
if (isLiveLockHolder(readLockRecord(lockPath))) return false;
|
|
29033
|
-
|
|
29551
|
+
fs54.writeFileSync(lockPath, ownLockBody());
|
|
29034
29552
|
}
|
|
29035
29553
|
process.once("exit", () => releaseOwnLock(lockPath));
|
|
29036
29554
|
return true;
|
|
@@ -29447,7 +29965,7 @@ var AgentService = class _AgentService {
|
|
|
29447
29965
|
};
|
|
29448
29966
|
|
|
29449
29967
|
// src/agents/acp/adapters.ts
|
|
29450
|
-
var
|
|
29968
|
+
var path63 = __toESM(require("path"));
|
|
29451
29969
|
|
|
29452
29970
|
// src/agents/kimi/installer.ts
|
|
29453
29971
|
var import_node_child_process19 = require("child_process");
|
|
@@ -29567,13 +30085,13 @@ function resolveBin(pkgName, binName) {
|
|
|
29567
30085
|
try {
|
|
29568
30086
|
const manifestPath = require_.resolve(`${pkgName}/package.json`);
|
|
29569
30087
|
const manifest = require_(`${pkgName}/package.json`);
|
|
29570
|
-
const pkgDir =
|
|
30088
|
+
const pkgDir = path63.dirname(manifestPath);
|
|
29571
30089
|
const bin = manifest.bin;
|
|
29572
30090
|
if (!bin) return null;
|
|
29573
|
-
if (typeof bin === "string") return
|
|
30091
|
+
if (typeof bin === "string") return path63.resolve(pkgDir, bin);
|
|
29574
30092
|
const target = binName ?? Object.keys(bin)[0];
|
|
29575
30093
|
if (!target || !bin[target]) return null;
|
|
29576
|
-
return
|
|
30094
|
+
return path63.resolve(pkgDir, bin[target]);
|
|
29577
30095
|
} catch {
|
|
29578
30096
|
return null;
|
|
29579
30097
|
}
|
|
@@ -29753,25 +30271,25 @@ async function resolveAcpAdapterWithRetry(agent, opts = {}) {
|
|
|
29753
30271
|
}
|
|
29754
30272
|
|
|
29755
30273
|
// src/commands/host/workspace.ts
|
|
29756
|
-
var
|
|
29757
|
-
var
|
|
29758
|
-
var
|
|
30274
|
+
var fs55 = __toESM(require("fs"));
|
|
30275
|
+
var os43 = __toESM(require("os"));
|
|
30276
|
+
var path64 = __toESM(require("path"));
|
|
29759
30277
|
var import_node_child_process21 = require("child_process");
|
|
29760
30278
|
var import_node_util5 = require("util");
|
|
29761
30279
|
var execFileP5 = (0, import_node_util5.promisify)(import_node_child_process21.execFile);
|
|
29762
30280
|
function isAbsolutePathTarget(target) {
|
|
29763
|
-
return
|
|
30281
|
+
return path64.isAbsolute(target);
|
|
29764
30282
|
}
|
|
29765
30283
|
function selfHostedWorkspaceRoot() {
|
|
29766
|
-
return
|
|
30284
|
+
return path64.join(os43.homedir(), ".codeam", "self-hosted");
|
|
29767
30285
|
}
|
|
29768
30286
|
function deployIdFromWorkspace(cwd) {
|
|
29769
30287
|
if (!cwd) return null;
|
|
29770
30288
|
const root = selfHostedWorkspaceRoot();
|
|
29771
|
-
const resolved =
|
|
29772
|
-
const rel =
|
|
29773
|
-
if (!rel || rel.startsWith("..") ||
|
|
29774
|
-
const parts = rel.split(
|
|
30289
|
+
const resolved = path64.resolve(cwd);
|
|
30290
|
+
const rel = path64.relative(root, resolved);
|
|
30291
|
+
if (!rel || rel.startsWith("..") || path64.isAbsolute(rel)) return null;
|
|
30292
|
+
const parts = rel.split(path64.sep).filter(Boolean);
|
|
29775
30293
|
if (parts.length !== 1) return null;
|
|
29776
30294
|
return parts[0];
|
|
29777
30295
|
}
|
|
@@ -29843,15 +30361,15 @@ async function configureGitCredentials(dest, repoRef, cloneToken, provider = "gi
|
|
|
29843
30361
|
const isGitlab = provider === "gitlab";
|
|
29844
30362
|
if (isGitlab ? !gitlabProjectPath(repoRef.trim()) : !githubOwnerRepo(repoRef.trim())) return;
|
|
29845
30363
|
if (!cloneToken) return;
|
|
29846
|
-
const credFile =
|
|
30364
|
+
const credFile = path64.join(dest, ".git", "codeam-credentials");
|
|
29847
30365
|
const credLine = isGitlab ? `https://oauth2:${cloneToken}@gitlab.com
|
|
29848
30366
|
` : `https://x-access-token:${cloneToken}@github.com
|
|
29849
30367
|
`;
|
|
29850
|
-
|
|
30368
|
+
fs55.writeFileSync(credFile, credLine, { mode: 384 });
|
|
29851
30369
|
restrictToOwner(credFile);
|
|
29852
30370
|
const env = nonInteractiveGitEnv();
|
|
29853
30371
|
const git2 = (args2) => execFileP5("git", ["-C", dest, ...args2], { timeout: 3e4, env });
|
|
29854
|
-
const credFilePosix = credFile.split(
|
|
30372
|
+
const credFilePosix = credFile.split(path64.sep).join("/");
|
|
29855
30373
|
await git2(["config", "--local", "--replace-all", "credential.helper", ""]).catch(() => {
|
|
29856
30374
|
});
|
|
29857
30375
|
await git2([
|
|
@@ -29884,17 +30402,17 @@ function maskToken(text, cloneToken) {
|
|
|
29884
30402
|
}
|
|
29885
30403
|
async function prepareWorkspace(repoOrPath, deployId, cloneToken, provider = "github", branch) {
|
|
29886
30404
|
if (isAbsolutePathTarget(repoOrPath)) {
|
|
29887
|
-
if (!
|
|
30405
|
+
if (!fs55.existsSync(repoOrPath)) {
|
|
29888
30406
|
throw new Error(`deploy target path does not exist: ${repoOrPath}`);
|
|
29889
30407
|
}
|
|
29890
30408
|
return repoOrPath;
|
|
29891
30409
|
}
|
|
29892
|
-
const dest =
|
|
29893
|
-
if (
|
|
30410
|
+
const dest = path64.join(selfHostedWorkspaceRoot(), deployId);
|
|
30411
|
+
if (fs55.existsSync(path64.join(dest, ".git"))) {
|
|
29894
30412
|
if (cloneToken) await configureGitCredentials(dest, repoOrPath, cloneToken, provider);
|
|
29895
30413
|
return dest;
|
|
29896
30414
|
}
|
|
29897
|
-
|
|
30415
|
+
fs55.mkdirSync(selfHostedWorkspaceRoot(), { recursive: true, mode: 448 });
|
|
29898
30416
|
const cloneUrl = repoCloneUrl(repoOrPath, cloneToken, provider);
|
|
29899
30417
|
const cloneArgs = branch ? ["clone", "--depth", "1", "--branch", branch, cloneUrl, dest] : ["clone", "--depth", "1", cloneUrl, dest];
|
|
29900
30418
|
try {
|
|
@@ -29917,266 +30435,6 @@ var fs72 = __toESM(require("fs"));
|
|
|
29917
30435
|
var os56 = __toESM(require("os"));
|
|
29918
30436
|
var path83 = __toESM(require("path"));
|
|
29919
30437
|
|
|
29920
|
-
// src/lib/provider-routing.ts
|
|
29921
|
-
var fs55 = __toESM(require("fs"));
|
|
29922
|
-
var os43 = __toESM(require("os"));
|
|
29923
|
-
var path64 = __toESM(require("path"));
|
|
29924
|
-
|
|
29925
|
-
// src/commands/host/house-proxy-config.ts
|
|
29926
|
-
var fs54 = __toESM(require("fs"));
|
|
29927
|
-
var os42 = __toESM(require("os"));
|
|
29928
|
-
var path63 = __toESM(require("path"));
|
|
29929
|
-
function houseProxyConfigPath() {
|
|
29930
|
-
return path63.join(os42.homedir(), ".codeam", "house-proxy.json");
|
|
29931
|
-
}
|
|
29932
|
-
var DEPLOY_ID_RE = /^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/;
|
|
29933
|
-
function deployHouseProxyConfigPath(deployId) {
|
|
29934
|
-
if (!DEPLOY_ID_RE.test(deployId) || deployId.includes("..")) return null;
|
|
29935
|
-
return path63.join(os42.homedir(), ".codeam", "house-proxy", `${deployId}.json`);
|
|
29936
|
-
}
|
|
29937
|
-
function writeJson0600(file, value) {
|
|
29938
|
-
fs54.mkdirSync(path63.dirname(file), { recursive: true, mode: 448 });
|
|
29939
|
-
const tmp = `${file}.tmp-${process.pid}`;
|
|
29940
|
-
fs54.writeFileSync(tmp, JSON.stringify(value, null, 2), { encoding: "utf8", mode: 384 });
|
|
29941
|
-
fs54.renameSync(tmp, file);
|
|
29942
|
-
restrictToOwner(file);
|
|
29943
|
-
}
|
|
29944
|
-
function persistHouseProxyConfig(config, deployId) {
|
|
29945
|
-
try {
|
|
29946
|
-
const perDeploy = deployId ? deployHouseProxyConfigPath(deployId) : null;
|
|
29947
|
-
if (perDeploy) writeJson0600(perDeploy, config);
|
|
29948
|
-
writeJson0600(houseProxyConfigPath(), config);
|
|
29949
|
-
} catch (err) {
|
|
29950
|
-
log.warn(
|
|
29951
|
-
"host-agent",
|
|
29952
|
-
`failed to persist house-proxy config (best-effort): ${err instanceof Error ? err.message : String(err)}`
|
|
29953
|
-
);
|
|
29954
|
-
}
|
|
29955
|
-
}
|
|
29956
|
-
function clearHouseProxyConfig(deployId) {
|
|
29957
|
-
try {
|
|
29958
|
-
fs54.rmSync(houseProxyConfigPath(), { force: true });
|
|
29959
|
-
const perDeploy = deployId ? deployHouseProxyConfigPath(deployId) : null;
|
|
29960
|
-
if (perDeploy) writeJson0600(perDeploy, { none: true });
|
|
29961
|
-
} catch {
|
|
29962
|
-
}
|
|
29963
|
-
}
|
|
29964
|
-
function readHouseProxyChildEnv(deployId) {
|
|
29965
|
-
try {
|
|
29966
|
-
const perDeploy = deployId ? deployHouseProxyConfigPath(deployId) : null;
|
|
29967
|
-
const file = perDeploy && fs54.existsSync(perDeploy) ? perDeploy : houseProxyConfigPath();
|
|
29968
|
-
const raw = fs54.readFileSync(file, "utf8");
|
|
29969
|
-
const parsed = JSON.parse(raw);
|
|
29970
|
-
if (typeof parsed !== "object" || parsed === null) return {};
|
|
29971
|
-
const o = parsed;
|
|
29972
|
-
if (o.none === true) return {};
|
|
29973
|
-
if (typeof o.baseUrl !== "string" || !o.baseUrl) return {};
|
|
29974
|
-
if (typeof o.token !== "string" || !o.token) return {};
|
|
29975
|
-
return buildHouseProxyChildEnv({
|
|
29976
|
-
baseUrl: o.baseUrl,
|
|
29977
|
-
token: o.token,
|
|
29978
|
-
openRouter: o.openRouter === true,
|
|
29979
|
-
...typeof o.claudeConfigDir === "string" && o.claudeConfigDir ? { claudeConfigDir: o.claudeConfigDir } : {},
|
|
29980
|
-
...typeof o.model === "string" && o.model ? { model: o.model } : {},
|
|
29981
|
-
...typeof o.managedAgentId === "string" && o.managedAgentId ? { managedAgentId: o.managedAgentId } : {}
|
|
29982
|
-
});
|
|
29983
|
-
} catch {
|
|
29984
|
-
return {};
|
|
29985
|
-
}
|
|
29986
|
-
}
|
|
29987
|
-
var HOUSE_MODEL_CONTEXT_TOKENS = "512000";
|
|
29988
|
-
function buildHouseProxyChildEnv(cfg) {
|
|
29989
|
-
const env = {
|
|
29990
|
-
ANTHROPIC_BASE_URL: cfg.baseUrl,
|
|
29991
|
-
ANTHROPIC_AUTH_TOKEN: cfg.token,
|
|
29992
|
-
// ⚠️ MAX_CONTEXT_TOKENS, not (only) AUTO_COMPACT_WINDOW — and this is
|
|
29993
|
-
// HOUSE-AGENT ONLY: it lives in this builder precisely so a user's own
|
|
29994
|
-
// Claude Code (a real Anthropic model claude knows) is never touched.
|
|
29995
|
-
//
|
|
29996
|
-
// claude does not know `MiniMax-M3`, so it falls back to its
|
|
29997
|
-
// unknown-model default (200k). `CLAUDE_CODE_AUTO_COMPACT_WINDOW` is then
|
|
29998
|
-
// applied as `Math.min(assumedWindow, env)` — it can only SHRINK the
|
|
29999
|
-
// window, never grow it — so the 512000 we used to set here was inert:
|
|
30000
|
-
// claude kept believing 200k. Meanwhile a session with a dozen linked
|
|
30001
|
-
// integrations carries ~175k tokens of MCP tool schemas on EVERY turn
|
|
30002
|
-
// (measured: 475 tools ≈ 698 KB on a real box), so the context started
|
|
30003
|
-
// ~88% full and a 28-character prompt triggered a compaction, then the
|
|
30004
|
-
// next small tool result triggered another: "Autocompact is thrashing:
|
|
30005
|
-
// the context refilled to the limit within 3 turns", 13 compactions in
|
|
30006
|
-
// one session (rafaelph90.br@gmail.com, 2026-09-03).
|
|
30007
|
-
//
|
|
30008
|
-
// claude's own unknown-model notice names the fix: "set
|
|
30009
|
-
// CLAUDE_CODE_MAX_CONTEXT_TOKENS to its real window" — that variable is
|
|
30010
|
-
// what `wL()` returns for an unrecognised model. MiniMax-M3 is a 1M-context
|
|
30011
|
-
// model with a guaranteed minimum of 512K, so 512000 here is the
|
|
30012
|
-
// conservative truth, not a wish. AUTO_COMPACT_WINDOW stays as the
|
|
30013
|
-
// compaction threshold beneath it.
|
|
30014
|
-
CLAUDE_CODE_MAX_CONTEXT_TOKENS: HOUSE_MODEL_CONTEXT_TOKENS,
|
|
30015
|
-
CLAUDE_CODE_AUTO_COMPACT_WINDOW: HOUSE_MODEL_CONTEXT_TOKENS,
|
|
30016
|
-
API_TIMEOUT_MS: "3000000"
|
|
30017
|
-
};
|
|
30018
|
-
if (cfg.openRouter === true) {
|
|
30019
|
-
env.ANTHROPIC_API_KEY = "";
|
|
30020
|
-
} else {
|
|
30021
|
-
const model = typeof cfg.model === "string" && cfg.model ? cfg.model : "MiniMax-M3";
|
|
30022
|
-
env.ANTHROPIC_MODEL = model;
|
|
30023
|
-
env.ANTHROPIC_DEFAULT_SONNET_MODEL = model;
|
|
30024
|
-
env.ANTHROPIC_DEFAULT_OPUS_MODEL = model;
|
|
30025
|
-
env.ANTHROPIC_DEFAULT_HAIKU_MODEL = model;
|
|
30026
|
-
}
|
|
30027
|
-
if (typeof cfg.claudeConfigDir === "string" && cfg.claudeConfigDir) {
|
|
30028
|
-
env.CLAUDE_CONFIG_DIR = cfg.claudeConfigDir;
|
|
30029
|
-
}
|
|
30030
|
-
if (isManagedProviderId(cfg.managedAgentId)) {
|
|
30031
|
-
env[MANAGED_AGENT_ENV] = cfg.managedAgentId;
|
|
30032
|
-
}
|
|
30033
|
-
return env;
|
|
30034
|
-
}
|
|
30035
|
-
function houseRailWireId(env) {
|
|
30036
|
-
const managed = env[MANAGED_AGENT_ENV];
|
|
30037
|
-
return isManagedProviderId(managed) ? managed : HOUSE_AGENT_ID;
|
|
30038
|
-
}
|
|
30039
|
-
var HOUSE_PROXY_ENV_KEYS = [
|
|
30040
|
-
"ANTHROPIC_BASE_URL",
|
|
30041
|
-
"ANTHROPIC_AUTH_TOKEN",
|
|
30042
|
-
"ANTHROPIC_API_KEY",
|
|
30043
|
-
"ANTHROPIC_MODEL",
|
|
30044
|
-
"ANTHROPIC_DEFAULT_SONNET_MODEL",
|
|
30045
|
-
"ANTHROPIC_DEFAULT_OPUS_MODEL",
|
|
30046
|
-
"ANTHROPIC_DEFAULT_HAIKU_MODEL",
|
|
30047
|
-
"CLAUDE_CODE_AUTO_COMPACT_WINDOW",
|
|
30048
|
-
"CLAUDE_CODE_MAX_CONTEXT_TOKENS",
|
|
30049
|
-
"API_TIMEOUT_MS",
|
|
30050
|
-
"CLAUDE_CONFIG_DIR",
|
|
30051
|
-
MANAGED_AGENT_ENV
|
|
30052
|
-
];
|
|
30053
|
-
function clearHouseProxyEnvOverrides() {
|
|
30054
|
-
const out2 = {};
|
|
30055
|
-
for (const key of HOUSE_PROXY_ENV_KEYS) out2[key] = void 0;
|
|
30056
|
-
return out2;
|
|
30057
|
-
}
|
|
30058
|
-
function isHouseProxyEnv(env) {
|
|
30059
|
-
return typeof env.ANTHROPIC_AUTH_TOKEN === "string" && env.ANTHROPIC_AUTH_TOKEN.length > 0 && (env.ANTHROPIC_BASE_URL ?? "").includes("/api/v1/agent-proxy");
|
|
30060
|
-
}
|
|
30061
|
-
function currentRailWireId(env = process.env) {
|
|
30062
|
-
return isHouseProxyEnv(env) ? houseRailWireId(env) : null;
|
|
30063
|
-
}
|
|
30064
|
-
function pickHouseProxyEnv(env) {
|
|
30065
|
-
const out2 = {};
|
|
30066
|
-
for (const key of HOUSE_PROXY_ENV_KEYS) {
|
|
30067
|
-
const v = env[key];
|
|
30068
|
-
if (typeof v === "string") out2[key] = v;
|
|
30069
|
-
}
|
|
30070
|
-
return out2;
|
|
30071
|
-
}
|
|
30072
|
-
|
|
30073
|
-
// src/lib/provider-routing.ts
|
|
30074
|
-
var PROVIDER_BASE_URL_ENV_KEYS = [
|
|
30075
|
-
"ANTHROPIC_BASE_URL",
|
|
30076
|
-
"OPENAI_BASE_URL",
|
|
30077
|
-
"OPENAI_API_BASE",
|
|
30078
|
-
"GEMINI_API_BASE",
|
|
30079
|
-
"GOOGLE_GEMINI_BASE_URL"
|
|
30080
|
-
];
|
|
30081
|
-
var ROUTING_DEFAULT = "default";
|
|
30082
|
-
function redactUrlToOrigin(raw) {
|
|
30083
|
-
if (typeof raw !== "string") return null;
|
|
30084
|
-
const trimmed = raw.trim();
|
|
30085
|
-
if (!trimmed) return null;
|
|
30086
|
-
try {
|
|
30087
|
-
const u2 = new URL(trimmed);
|
|
30088
|
-
if (!u2.host) return "invalid-url";
|
|
30089
|
-
return `${u2.protocol}//${u2.host}`;
|
|
30090
|
-
} catch {
|
|
30091
|
-
return "invalid-url";
|
|
30092
|
-
}
|
|
30093
|
-
}
|
|
30094
|
-
function readOpencodeProviderOrigins(opts = {}) {
|
|
30095
|
-
const home = opts.homeDir ?? os43.homedir();
|
|
30096
|
-
const readFile7 = opts.readFile ?? ((f) => fs55.readFileSync(f, "utf8"));
|
|
30097
|
-
const candidates = [];
|
|
30098
|
-
if (opts.cwd) {
|
|
30099
|
-
candidates.push(path64.join(opts.cwd, "opencode.json"), path64.join(opts.cwd, "opencode.jsonc"));
|
|
30100
|
-
}
|
|
30101
|
-
candidates.push(
|
|
30102
|
-
path64.join(home, ".config", "opencode", "opencode.json"),
|
|
30103
|
-
path64.join(home, ".config", "opencode", "opencode.jsonc")
|
|
30104
|
-
);
|
|
30105
|
-
const out2 = [];
|
|
30106
|
-
const seen2 = /* @__PURE__ */ new Set();
|
|
30107
|
-
for (const file of candidates) {
|
|
30108
|
-
let text;
|
|
30109
|
-
try {
|
|
30110
|
-
text = readFile7(file);
|
|
30111
|
-
} catch {
|
|
30112
|
-
continue;
|
|
30113
|
-
}
|
|
30114
|
-
let parsed;
|
|
30115
|
-
try {
|
|
30116
|
-
parsed = JSON.parse(text.replace(/^\s*\/\/.*$/gm, ""));
|
|
30117
|
-
} catch {
|
|
30118
|
-
continue;
|
|
30119
|
-
}
|
|
30120
|
-
const providers = parsed?.provider;
|
|
30121
|
-
if (!providers || typeof providers !== "object") continue;
|
|
30122
|
-
for (const [id, cfg] of Object.entries(providers)) {
|
|
30123
|
-
if (seen2.has(id)) continue;
|
|
30124
|
-
const options = cfg?.options;
|
|
30125
|
-
const base = options?.baseURL ?? options?.baseUrl ?? options?.base_url;
|
|
30126
|
-
const origin = redactUrlToOrigin(base);
|
|
30127
|
-
if (!origin) continue;
|
|
30128
|
-
seen2.add(id);
|
|
30129
|
-
out2.push({ provider: id, origin });
|
|
30130
|
-
}
|
|
30131
|
-
}
|
|
30132
|
-
return out2;
|
|
30133
|
-
}
|
|
30134
|
-
function describeProviderRouting(env, opts = {}) {
|
|
30135
|
-
const routed = {};
|
|
30136
|
-
for (const key of PROVIDER_BASE_URL_ENV_KEYS) {
|
|
30137
|
-
routed[key] = redactUrlToOrigin(env[key]) ?? ROUTING_DEFAULT;
|
|
30138
|
-
}
|
|
30139
|
-
let opencode = [];
|
|
30140
|
-
try {
|
|
30141
|
-
opencode = readOpencodeProviderOrigins(opts);
|
|
30142
|
-
} catch {
|
|
30143
|
-
}
|
|
30144
|
-
const houseKeys = HOUSE_PROXY_ENV_KEYS.filter(
|
|
30145
|
-
(k2) => typeof env[k2] === "string" && env[k2].length > 0
|
|
30146
|
-
);
|
|
30147
|
-
const codeamKeys = Object.keys(env).filter((k2) => k2.startsWith("CODEAM_") && typeof env[k2] === "string" && env[k2].length > 0).sort();
|
|
30148
|
-
return { env: routed, opencode, houseProxy: isHouseProxyEnv(env), houseKeys, codeamKeys };
|
|
30149
|
-
}
|
|
30150
|
-
function formatProviderRouting(r, label) {
|
|
30151
|
-
const parts = [
|
|
30152
|
-
label ? `agent=${label}` : null,
|
|
30153
|
-
`anthropic=${r.env.ANTHROPIC_BASE_URL}`,
|
|
30154
|
-
`openai=${r.env.OPENAI_BASE_URL !== ROUTING_DEFAULT ? r.env.OPENAI_BASE_URL : r.env.OPENAI_API_BASE}`,
|
|
30155
|
-
`gemini=${r.env.GEMINI_API_BASE !== ROUTING_DEFAULT ? r.env.GEMINI_API_BASE : r.env.GOOGLE_GEMINI_BASE_URL}`,
|
|
30156
|
-
`opencode=[${r.opencode.map((p2) => `${p2.provider}=${p2.origin}`).join(",")}]`,
|
|
30157
|
-
`houseProxy=${r.houseProxy ? "yes" : "no"}`,
|
|
30158
|
-
`houseKeys=[${r.houseKeys.join(",")}]`,
|
|
30159
|
-
`codeamKeys=[${r.codeamKeys.join(",")}]`
|
|
30160
|
-
];
|
|
30161
|
-
return parts.filter((p2) => p2 !== null).join(" ");
|
|
30162
|
-
}
|
|
30163
|
-
var PROVIDER_BILLING_RE = /(?:api error|http|status)[:\s]+402\b|\b402\b[^\n]{0,40}(?:payment required|insufficient|credits?|balance)|insufficient (?:credits?|balance|funds)|payment required/i;
|
|
30164
|
-
function matchesProviderBilling(text) {
|
|
30165
|
-
return PROVIDER_BILLING_RE.test(text);
|
|
30166
|
-
}
|
|
30167
|
-
function scrubSecrets(text) {
|
|
30168
|
-
return text.replace(/\b(?:sk|pk|rk|key|token)[-_][A-Za-z0-9_-]{12,}/gi, "[redacted]").replace(/bearer\s+[A-Za-z0-9._-]{12,}/gi, "Bearer [redacted]").replace(/\b[A-Za-z0-9_-]{40,}\b/g, "[redacted]");
|
|
30169
|
-
}
|
|
30170
|
-
function classifyProviderBilling(text, env) {
|
|
30171
|
-
if (!matchesProviderBilling(text)) return null;
|
|
30172
|
-
const line = text.split("\n").find((l) => PROVIDER_BILLING_RE.test(l)) ?? text;
|
|
30173
|
-
return {
|
|
30174
|
-
marker: isHouseProxyEnv(env) ? "provider_billing_house" : "provider_billing_external",
|
|
30175
|
-
anthropicHost: redactUrlToOrigin(env.ANTHROPIC_BASE_URL) ?? ROUTING_DEFAULT,
|
|
30176
|
-
snippet: scrubSecrets(line.trim()).slice(0, 160)
|
|
30177
|
-
};
|
|
30178
|
-
}
|
|
30179
|
-
|
|
30180
30438
|
// src/agents/acp/provider-billing-signal.ts
|
|
30181
30439
|
var seen = /* @__PURE__ */ new Set();
|
|
30182
30440
|
function noteProviderBillingSignal(opts) {
|
|
@@ -38540,243 +38798,6 @@ function withTimeout(p2, ms) {
|
|
|
38540
38798
|
});
|
|
38541
38799
|
}
|
|
38542
38800
|
|
|
38543
|
-
// src/agents/acp/oneMContextRecovery.ts
|
|
38544
|
-
var ONE_M_CONTEXT_CREDITS_RE = /usage credits required for 1m context/i;
|
|
38545
|
-
function looksLike1mContextCreditsError(text) {
|
|
38546
|
-
return ONE_M_CONTEXT_CREDITS_RE.test(text);
|
|
38547
|
-
}
|
|
38548
|
-
function shouldOfferOneMRecovery(opts) {
|
|
38549
|
-
return looksLike1mContextCreditsError(opts.detail) || looksLike1mContextCreditsError(opts.recentStderr) || looksLike1mContextCreditsError(opts.finalText);
|
|
38550
|
-
}
|
|
38551
|
-
|
|
38552
|
-
// src/agents/acp/agent-hooks.ts
|
|
38553
|
-
function replyIsCursorUpgradeRequired(finalText) {
|
|
38554
|
-
const t2 = finalText.trim().toLowerCase();
|
|
38555
|
-
if (t2.length === 0 || t2.length > 200) return false;
|
|
38556
|
-
return t2.includes("upgrade your plan to continue") || t2.includes("upgrade your plan") && t2.includes("continue");
|
|
38557
|
-
}
|
|
38558
|
-
function isGeminiIneligibleTier(haystack2) {
|
|
38559
|
-
return /IneligibleTierError|UNSUPPORTED_CLIENT|no longer supported for Gemini Code Assist|not eligible for Gemini Code Assist/i.test(
|
|
38560
|
-
haystack2
|
|
38561
|
-
);
|
|
38562
|
-
}
|
|
38563
|
-
var ACP_AGENT_HOOKS = {
|
|
38564
|
-
claude: {
|
|
38565
|
-
statusPage: { vendor: "Anthropic", url: "https://status.anthropic.com" },
|
|
38566
|
-
// Freeze the SDK-bundled Claude Code binary at the version this CLI (and its
|
|
38567
|
-
// pinned ACP adapter) was tested against. Without this the binary silently
|
|
38568
|
-
// self-updates to @latest and can drift PAST the adapter — a newer Claude
|
|
38569
|
-
// Code (v2.1.211) started streaming its TUI chrome (What's-new banner, status
|
|
38570
|
-
// line, box-drawing) into the ACP text channel, which paints as a broken chat
|
|
38571
|
-
// on mobile. A version regression must now reach users only through a gated
|
|
38572
|
-
// codeam-cli release, never silently via auto-update.
|
|
38573
|
-
startupExtraEnv: () => ({
|
|
38574
|
-
DISABLE_AUTOUPDATER: "1",
|
|
38575
|
-
CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC: "1"
|
|
38576
|
-
})
|
|
38577
|
-
},
|
|
38578
|
-
codex: {
|
|
38579
|
-
statusPage: { vendor: "OpenAI", url: "https://status.openai.com" },
|
|
38580
|
-
startupExtraEnv: ({ autoApprovePermissions }) => autoApprovePermissions ? { INITIAL_AGENT_MODE: "agent-full-access" } : {}
|
|
38581
|
-
},
|
|
38582
|
-
gemini: {
|
|
38583
|
-
statusPage: { vendor: "Google", url: "https://status.cloud.google.com" },
|
|
38584
|
-
classifyStartupFailure: (haystack2) => isGeminiIneligibleTier(haystack2) ? "ineligible_tier" : null
|
|
38585
|
-
},
|
|
38586
|
-
copilot: {
|
|
38587
|
-
statusPage: { vendor: "GitHub", url: "https://www.githubstatus.com" }
|
|
38588
|
-
},
|
|
38589
|
-
cursor: {
|
|
38590
|
-
statusPage: { vendor: "Cursor", url: "https://status.cursor.com" },
|
|
38591
|
-
classifyCompletedReply: (finalText) => replyIsCursorUpgradeRequired(finalText) ? "upgrade_required" : null
|
|
38592
|
-
}
|
|
38593
|
-
};
|
|
38594
|
-
function agentHooks(agent) {
|
|
38595
|
-
return ACP_AGENT_HOOKS[agent];
|
|
38596
|
-
}
|
|
38597
|
-
|
|
38598
|
-
// src/agents/acp/failure-messages.ts
|
|
38599
|
-
function describeError(err) {
|
|
38600
|
-
if (err instanceof Error) return err.message;
|
|
38601
|
-
return String(err);
|
|
38602
|
-
}
|
|
38603
|
-
var AUTH_FAILURE_RE = /invalid authentication credentials|failed to authenticate|authentication[_ ](?:error|required)|please run \/login|\bunauthorized\b|\binvalid x-api-key\b|oauth (?:token|session) (?:expired|revoked)|(?:session|token|credentials?|oauth)[^\n]{0,40}could not be refreshed|(?:api error|http|status)[:\s]+401|\b401\b[^\n]{0,40}(?:unauthor|authenticat|credential|api[_ ]?key|login)/i;
|
|
38604
|
-
var HOUSE_AGENT_LIMIT_RE = /HOUSE_AGENT_CEILING|CodeAgent Cloud[^\n]{0,60}(?:usage )?ceiling|CodeAgent Cloud is temporarily (?:unavailable|disabled)/i;
|
|
38605
|
-
function looksLikeHouseAgentLimit(text) {
|
|
38606
|
-
return HOUSE_AGENT_LIMIT_RE.test(text);
|
|
38607
|
-
}
|
|
38608
|
-
var LOCAL_PROXY_RE = /(?:127\.0\.0\.1|localhost|\[::1\]):\d+/i;
|
|
38609
|
-
var CONNECTION_ERROR_RE = /ECONNREFUSED|ECONNRESET|ETIMEDOUT|EHOSTUNREACH|socket hang up|fetch failed|network error|connection (?:refused|reset|closed)/i;
|
|
38610
|
-
function looksLikeLocalProxyUnavailable(text) {
|
|
38611
|
-
return LOCAL_PROXY_RE.test(text) && CONNECTION_ERROR_RE.test(text);
|
|
38612
|
-
}
|
|
38613
|
-
function looksLikeAuthFailure(text) {
|
|
38614
|
-
if (looksLikeHouseAgentLimit(text)) return false;
|
|
38615
|
-
if (looksLikeLocalProxyUnavailable(text)) return false;
|
|
38616
|
-
return AUTH_FAILURE_RE.test(text);
|
|
38617
|
-
}
|
|
38618
|
-
function replyIsAuthFailure(finalText) {
|
|
38619
|
-
const t2 = finalText.trim();
|
|
38620
|
-
return t2.length > 0 && t2.length <= 200 && looksLikeAuthFailure(t2);
|
|
38621
|
-
}
|
|
38622
|
-
function replyIsHouseAgentLimit(finalText) {
|
|
38623
|
-
const t2 = finalText.trim();
|
|
38624
|
-
return t2.length > 0 && t2.length <= 400 && looksLikeHouseAgentLimit(t2);
|
|
38625
|
-
}
|
|
38626
|
-
var BYO_PROVIDER_BILLING_RE = /(?:api error|http|status)[:\s]+402\b[^\n]{0,80}(?:insufficient (?:credits?|balance)|requires more credits)|\b402\b[^\n]{0,40}(?:insufficient (?:credits?|balance)|requires more credits)|insufficient (?:credits?|balance)[^\n]{0,40}\b402\b/i;
|
|
38627
|
-
function looksLikeByoProviderBilling(text, env = process.env) {
|
|
38628
|
-
return !isHouseProxyEnv(env) && BYO_PROVIDER_BILLING_RE.test(text);
|
|
38629
|
-
}
|
|
38630
|
-
function replyIsByoProviderBilling(finalText, env = process.env) {
|
|
38631
|
-
const t2 = finalText.trim();
|
|
38632
|
-
return t2.length > 0 && t2.length <= 600 && looksLikeByoProviderBilling(t2, env);
|
|
38633
|
-
}
|
|
38634
|
-
var PROVIDER_HOST_NAMES = [
|
|
38635
|
-
[/(^|\.)openrouter\.ai$/i, "OpenRouter"],
|
|
38636
|
-
[/(^|\.)deepinfra\.com$/i, "DeepInfra"],
|
|
38637
|
-
[/(^|\.)anthropic\.com$/i, "Anthropic"],
|
|
38638
|
-
[/(^|\.)openai\.com$/i, "OpenAI"],
|
|
38639
|
-
[/(^|\.)googleapis\.com$/i, "Google"],
|
|
38640
|
-
[/(^|\.)minimax(?:i)?\.(?:io|com|chat)$/i, "MiniMax"],
|
|
38641
|
-
[/(^|\.)moonshot\.(?:ai|cn)$/i, "Moonshot"],
|
|
38642
|
-
[/(^|\.)x\.ai$/i, "xAI"],
|
|
38643
|
-
[/(^|\.)mistral\.ai$/i, "Mistral"],
|
|
38644
|
-
[/(^|\.)groq\.com$/i, "Groq"],
|
|
38645
|
-
[/(^|\.)together\.(?:ai|xyz)$/i, "Together"]
|
|
38646
|
-
];
|
|
38647
|
-
var AGENT_DEFAULT_PROVIDER = {
|
|
38648
|
-
claude: "Anthropic",
|
|
38649
|
-
codex: "OpenAI",
|
|
38650
|
-
gemini: "Google"
|
|
38651
|
-
};
|
|
38652
|
-
function byoProviderName(opts) {
|
|
38653
|
-
const env = opts.env ?? process.env;
|
|
38654
|
-
for (const key of PROVIDER_BASE_URL_ENV_KEYS) {
|
|
38655
|
-
const origin = redactUrlToOrigin(env[key]);
|
|
38656
|
-
if (!origin || origin === "invalid-url") continue;
|
|
38657
|
-
const host2 = new URL(origin).hostname;
|
|
38658
|
-
for (const [re2, name] of PROVIDER_HOST_NAMES) if (re2.test(host2)) return name;
|
|
38659
|
-
return host2;
|
|
38660
|
-
}
|
|
38661
|
-
return opts.agent && AGENT_DEFAULT_PROVIDER[opts.agent] || "provider";
|
|
38662
|
-
}
|
|
38663
|
-
function byoProviderBillingMessage(provider) {
|
|
38664
|
-
return `\u{1F4B3} **Your ${provider} account has no credits left.** Top up at your provider, or switch this session to another agent.`;
|
|
38665
|
-
}
|
|
38666
|
-
function completedReplyFailureBubble(opts) {
|
|
38667
|
-
const env = opts.env ?? process.env;
|
|
38668
|
-
if (replyIsHouseAgentLimit(opts.finalText)) return houseAgentLimitMessage(opts.finalText);
|
|
38669
|
-
if (replyIsByoProviderBilling(opts.finalText, env)) {
|
|
38670
|
-
return byoProviderBillingMessage(byoProviderName({ env, agent: opts.agent }));
|
|
38671
|
-
}
|
|
38672
|
-
if (replyIsAuthFailure(opts.finalText)) return AUTH_FAILURE_MESSAGE;
|
|
38673
|
-
return null;
|
|
38674
|
-
}
|
|
38675
|
-
function houseAgentLimitMessage(text) {
|
|
38676
|
-
if (/temporarily (?:unavailable|disabled)/i.test(text)) {
|
|
38677
|
-
return "\u23F3 **Our agent service is temporarily unavailable \u2014 this one\u2019s on us, not your account.**\n\nThere\u2019s nothing to buy and nothing owed, and it isn\u2019t a problem with your login, so re-authenticating won\u2019t help. Send your message again in a bit, or connect your own agent (Claude Code, Codex, Cursor, Gemini) in **Profile \u203A Agents** to keep going now.";
|
|
38678
|
-
}
|
|
38679
|
-
const canUpgrade = /upgrade to pro/i.test(text);
|
|
38680
|
-
return "\u{1F4CA} **You\u2019ve reached today\u2019s agent usage limit.**\n\nThe free agent has a daily usage ceiling that resets at midnight UTC. This is a usage limit, not a problem with your login \u2014 re-authenticating won\u2019t change it. " + (canUpgrade ? "To keep going now, upgrade to **Pro** for a higher ceiling, or connect your own agent (Claude, Codex, \u2026) in **Profile \u203A Agents** to run without this limit." : "To keep going now, connect your own agent (Claude, Codex, \u2026) in **Profile \u203A Agents** to run without this limit, or wait for the reset.");
|
|
38681
|
-
}
|
|
38682
|
-
var AUTH_FAILURE_MESSAGE = (
|
|
38683
|
-
// ⚠️ Do NOT name a status code here. This bubble fires for several
|
|
38684
|
-
// different failures, and the old hard-coded "(API 401)" told users the API
|
|
38685
|
-
// had answered 401 when it never had — it also sent a live investigation
|
|
38686
|
-
// hunting for 401s in proxy logs that were serving 200s throughout
|
|
38687
|
-
// (2026-08-24). Say what happened, not a number we did not see.
|
|
38688
|
-
"\u{1F512} **Authentication failed \u2014 your agent credentials are invalid or expired.**\n\nTap [Re-authenticate this agent](codeam://reauth) to renew your credentials in Profile \u203A Agents, then send your message again."
|
|
38689
|
-
);
|
|
38690
|
-
var CURSOR_UPGRADE_MESSAGE = "\u26A1 **Cursor needs a paid plan to run the agent.**\n\nThe headless Cursor Agent requires Cursor **Pro** \u2014 your Free plan\u2019s included usage does NOT cover Agent runs, even with quota left. This is your Cursor account (not CodeAgent). Upgrade, then send your message again:\n\n[Upgrade to Cursor Pro \u2192](https://cursor.com/dashboard)";
|
|
38691
|
-
var ONE_M_CREDITS_MESSAGE = "\u{1F504} **Reconnect your Claude subscription to continue.**\n\nClaude requested 1M-context but your account doesn\u2019t have the usage credits for it on this credential. Reconnecting refreshes your subscription so the agent can keep going \u2014 disabling 1M context won\u2019t fix a credits gate.\n\nTap [Reconnect this agent](codeam://reauth) to reconnect your Claude subscription in Profile \u203A Agents, then send your message again.";
|
|
38692
|
-
var TURN_FAILURE_MESSAGE = "\u26A0\uFE0F **The agent hit an error and couldn\u2019t finish this turn.** Please send your message again.";
|
|
38693
|
-
function emptyReplyMessage(agent) {
|
|
38694
|
-
const label = isKnownAgentId(agent) ? AGENT_REGISTRY[agent].displayName : agent;
|
|
38695
|
-
const binary = isKnownAgentId(agent) ? AGENT_REGISTRY[agent].binaryName : agent;
|
|
38696
|
-
return `\u26A0\uFE0F **${label} returned an empty reply.** Its provider may be having issues \u2014 check the agent's login/subscription on this machine (e.g. run \`${binary} -p "test"\` there).`;
|
|
38697
|
-
}
|
|
38698
|
-
var PROVIDER_OUTAGE_RE = /overloaded_error|\boverloaded\b|service[ _]unavailable|temporarily[ _]unavailable|(?:api error|http|status)[:\s]+(?:529|503|502|504)\b|\b(?:529|503|502|504)\b[^\n]{0,40}(?:overload|unavailable|gateway|upstream|server error)|bad gateway|gateway time-?out|upstream (?:error|connect|timeout)/i;
|
|
38699
|
-
function looksLikeProviderOutage(text) {
|
|
38700
|
-
return PROVIDER_OUTAGE_RE.test(text);
|
|
38701
|
-
}
|
|
38702
|
-
function agentStatusPage(agent, railWireId) {
|
|
38703
|
-
if (railWireId) return null;
|
|
38704
|
-
const a = (agent ?? "").toLowerCase();
|
|
38705
|
-
const id = a.includes("claude") || a.includes("anthropic") ? "claude" : a.includes("codex") || a.includes("openai") ? "codex" : a.includes("gemini") || a.includes("google") ? "gemini" : a.includes("copilot") ? "copilot" : a.includes("cursor") ? "cursor" : null;
|
|
38706
|
-
return id ? agentHooks(id)?.statusPage ?? null : null;
|
|
38707
|
-
}
|
|
38708
|
-
function providerOutageMessage(agent, railWireId) {
|
|
38709
|
-
if (railWireId) {
|
|
38710
|
-
const who2 = isManagedProviderId(railWireId) ? `${MANAGED_PROVIDER_DISPLAY_NAMES[railWireId]} ` : "";
|
|
38711
|
-
return `\u{1F310} **CodeAgent's agent service is having a disruption \u2014 this isn't your session.**
|
|
38712
|
-
|
|
38713
|
-
Your ${who2}agent couldn't finish this turn because our provider returned an overload error. It usually clears up on its own \u2014 just send your message again in a bit.`;
|
|
38714
|
-
}
|
|
38715
|
-
const info = agentStatusPage(agent);
|
|
38716
|
-
const who = info ? info.vendor : "The agent provider";
|
|
38717
|
-
return `\u{1F310} **${who} is having a service disruption \u2014 this isn\u2019t your session.**
|
|
38718
|
-
|
|
38719
|
-
The agent provider returned an overload/outage error, so this turn couldn\u2019t finish. It usually clears up on its own \u2014 just send your message again in a bit.` + (info ? `
|
|
38720
|
-
|
|
38721
|
-
Follow the status here: [${info.url}](${info.url})` : "");
|
|
38722
|
-
}
|
|
38723
|
-
function startupFailureMessage(agent, detail, recentStderr, railWireId) {
|
|
38724
|
-
const haystack2 = `${detail}
|
|
38725
|
-
${recentStderr}`;
|
|
38726
|
-
if (agentHooks(agent)?.classifyStartupFailure?.(haystack2) === "ineligible_tier") {
|
|
38727
|
-
return [
|
|
38728
|
-
"\u26A0\uFE0F **Gemini couldn't start \u2014 your Google account isn't eligible.**",
|
|
38729
|
-
"",
|
|
38730
|
-
"Google discontinued free **\u201CLogin with Google\u201D** access to the Gemini CLI on 2026-06-18. The free / individual tier (and Google AI Pro/Ultra) can no longer authenticate here.",
|
|
38731
|
-
"",
|
|
38732
|
-
"To use Gemini from CodeAgent, re-link it in **Profile \u203A Agents** with either:",
|
|
38733
|
-
"\u2022 a **Gemini API key** (AI Studio \u2014 free quota available), or",
|
|
38734
|
-
"\u2022 a paid **Gemini Code Assist (Standard/Enterprise)** subscription."
|
|
38735
|
-
].join("\n");
|
|
38736
|
-
}
|
|
38737
|
-
if (looksLikeAuthFailure(haystack2)) return AUTH_FAILURE_MESSAGE;
|
|
38738
|
-
if (looksLikeProviderOutage(haystack2)) return providerOutageMessage(agent, railWireId);
|
|
38739
|
-
const tail = recentStderr.split("\n").filter(Boolean).slice(-3).join("\n");
|
|
38740
|
-
return [`\u26A0\uFE0F The ${agent} agent failed to start.`, "", tail ? `Details:
|
|
38741
|
-
${tail}` : detail].join(
|
|
38742
|
-
"\n"
|
|
38743
|
-
);
|
|
38744
|
-
}
|
|
38745
|
-
function startupCredentialInvalidReason(agent, detail, recentStderr) {
|
|
38746
|
-
const haystack2 = `${detail}
|
|
38747
|
-
${recentStderr}`;
|
|
38748
|
-
return agentHooks(agent)?.classifyStartupFailure?.(haystack2) === "ineligible_tier" ? "ineligible_tier" : null;
|
|
38749
|
-
}
|
|
38750
|
-
function failureBubble(opts) {
|
|
38751
|
-
const env = opts.env ?? process.env;
|
|
38752
|
-
if (looksLikeHouseAgentLimit(opts.detail) || looksLikeHouseAgentLimit(opts.recentStderr)) {
|
|
38753
|
-
return houseAgentLimitMessage(`${opts.detail}
|
|
38754
|
-
${opts.recentStderr}`);
|
|
38755
|
-
}
|
|
38756
|
-
if (looksLikeByoProviderBilling(opts.detail, env) || looksLikeByoProviderBilling(opts.recentStderr, env)) {
|
|
38757
|
-
return byoProviderBillingMessage(byoProviderName({ env, agent: opts.agent }));
|
|
38758
|
-
}
|
|
38759
|
-
if (looksLikeAuthFailure(opts.detail) || looksLikeAuthFailure(opts.recentStderr)) {
|
|
38760
|
-
return AUTH_FAILURE_MESSAGE;
|
|
38761
|
-
}
|
|
38762
|
-
if (looksLike1mContextCreditsError(opts.detail) || looksLike1mContextCreditsError(opts.recentStderr)) {
|
|
38763
|
-
return ONE_M_CREDITS_MESSAGE;
|
|
38764
|
-
}
|
|
38765
|
-
if (looksLikeProviderOutage(opts.detail) || looksLikeProviderOutage(opts.recentStderr)) {
|
|
38766
|
-
return providerOutageMessage(opts.agent, opts.railWireId);
|
|
38767
|
-
}
|
|
38768
|
-
if (!opts.hadText) return TURN_FAILURE_MESSAGE;
|
|
38769
|
-
return null;
|
|
38770
|
-
}
|
|
38771
|
-
var WINDOWS_CONTROL_C_EXIT = 3221225786;
|
|
38772
|
-
function adapterExitMessage(opts) {
|
|
38773
|
-
if (opts.code === WINDOWS_CONTROL_C_EXIT) return null;
|
|
38774
|
-
if (opts.signal === "SIGINT") return null;
|
|
38775
|
-
if (opts.authFail) return AUTH_FAILURE_MESSAGE;
|
|
38776
|
-
if (opts.outageFail) return providerOutageMessage(opts.agent, opts.railWireId);
|
|
38777
|
-
return `Agent adapter exited unexpectedly (code=${opts.code ?? "null"} signal=${opts.signal ?? "null"}).`;
|
|
38778
|
-
}
|
|
38779
|
-
|
|
38780
38801
|
// src/agents/acp/backend-reports.ts
|
|
38781
38802
|
async function reportCredentialInvalid(opts, fetchImpl = fetch) {
|
|
38782
38803
|
const url2 = `${resolveApiBaseUrl()}/api/plugin/agents/${encodeURIComponent(opts.agent)}/credential-invalid`;
|
|
@@ -48963,7 +48984,7 @@ async function autoUpgradeBeforeCriticalCommand() {
|
|
|
48963
48984
|
if (process.env.NODE_ENV === "test") return;
|
|
48964
48985
|
if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
|
|
48965
48986
|
if (process.env.CI) return;
|
|
48966
|
-
const current2 = true ? "2.75.
|
|
48987
|
+
const current2 = true ? "2.75.46" : null;
|
|
48967
48988
|
if (!current2) return;
|
|
48968
48989
|
const cache = readCache();
|
|
48969
48990
|
const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
|
|
@@ -48980,7 +49001,7 @@ function checkForUpdates() {
|
|
|
48980
49001
|
if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
|
|
48981
49002
|
if (process.env.CI) return;
|
|
48982
49003
|
if (!process.stdout.isTTY) return;
|
|
48983
|
-
const current2 = true ? "2.75.
|
|
49004
|
+
const current2 = true ? "2.75.46" : null;
|
|
48984
49005
|
if (!current2) return;
|
|
48985
49006
|
const cache = readCache();
|
|
48986
49007
|
const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
|
|
@@ -49003,7 +49024,7 @@ var SELF_UPDATE_INSTALL_TIMEOUT_MS = 18e4;
|
|
|
49003
49024
|
var SELF_UPDATE_LS_TIMEOUT_MS = 15e3;
|
|
49004
49025
|
var SUDO_PREFLIGHT_TIMEOUT_MS = 5e3;
|
|
49005
49026
|
function currentCliVersion() {
|
|
49006
|
-
return true ? "2.75.
|
|
49027
|
+
return true ? "2.75.46" : null;
|
|
49007
49028
|
}
|
|
49008
49029
|
async function installedVersion(deps) {
|
|
49009
49030
|
const ls = await deps.run(
|
|
@@ -51058,7 +51079,7 @@ function checkChokidar() {
|
|
|
51058
51079
|
}
|
|
51059
51080
|
async function doctor(args2 = []) {
|
|
51060
51081
|
const json = args2.includes("--json");
|
|
51061
|
-
const cliVersion = true ? "2.75.
|
|
51082
|
+
const cliVersion = true ? "2.75.46" : "0.0.0-dev";
|
|
51062
51083
|
const apiBase2 = resolveApiBaseUrl();
|
|
51063
51084
|
const diagnosticId = (0, import_node_crypto13.randomUUID)();
|
|
51064
51085
|
log.info("doctor", `run id=${diagnosticId} cli=${cliVersion}`);
|
|
@@ -51582,7 +51603,7 @@ async function mcpWarm(argv = [], opts = {}) {
|
|
|
51582
51603
|
// src/commands/version.ts
|
|
51583
51604
|
var import_picocolors15 = __toESM(require("picocolors"));
|
|
51584
51605
|
function version2() {
|
|
51585
|
-
const v = true ? "2.75.
|
|
51606
|
+
const v = true ? "2.75.46" : "unknown";
|
|
51586
51607
|
console.log(`${import_picocolors15.default.bold("codeam-cli")} ${import_picocolors15.default.cyan(v)}`);
|
|
51587
51608
|
}
|
|
51588
51609
|
|