codeam-cli 2.11.0 → 2.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +37 -0
- package/dist/index.js +315 -101
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,43 @@ All notable changes to `codeam-cli` are documented here.
|
|
|
4
4
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
6
6
|
|
|
7
|
+
## [2.11.0] — 2026-05-13
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
- **shared:** Add agent type primitives
|
|
12
|
+
- **shared:** Add AGENT_REGISTRY with Claude enabled
|
|
13
|
+
- **shared:** Export agents module + bump minor
|
|
14
|
+
- **cli:** Define RuntimeStrategy + DeployStrategy interfaces
|
|
15
|
+
- **cli:** Implement ClaudeRuntimeStrategy
|
|
16
|
+
- **cli:** Implement ClaudeDeployStrategy + extract credential bridge
|
|
17
|
+
- **cli:** Add agent to SavedSession + preferredAgent to CliConfig
|
|
18
|
+
- **cli:** Add parseAgentFlag + promptForAgent helpers
|
|
19
|
+
- **cli:** Pair accepts --agent flag + prompts + remembers preferredAgent
|
|
20
|
+
- **cli:** Pair-auto consumes agent from API response
|
|
21
|
+
- **cli:** Change_model + summarize handlers route through RuntimeStrategy
|
|
22
|
+
|
|
23
|
+
### Changed
|
|
24
|
+
|
|
25
|
+
- **vsc-plugin:** Port JetBrains agent-strategy pattern
|
|
26
|
+
- **cli:** Extract Claude history parsing to agents/claude/history.ts
|
|
27
|
+
- **cli:** Extract Claude /usage parsing to agents/claude/quota.ts
|
|
28
|
+
- **cli:** Rename ClaudeService → AgentService, add registry factory
|
|
29
|
+
- **cli:** History + quota services delegate to RuntimeStrategy
|
|
30
|
+
- **cli:** Start.ts uses session.agent for runtime factory
|
|
31
|
+
- **cli:** Deploy uses DeployStrategy + switches to pair-auto
|
|
32
|
+
- **cli:** Pass args to pair command
|
|
33
|
+
|
|
34
|
+
### Documentation
|
|
35
|
+
|
|
36
|
+
- Align CLAUDE.md + bump in-source versions to v2.10.8
|
|
37
|
+
- **cli:** Drop misleading codeam-login note in deploy.ts
|
|
38
|
+
|
|
39
|
+
### Fixed
|
|
40
|
+
|
|
41
|
+
- **cli:** Reload config after addSession to avoid clobbering activeSessionId
|
|
42
|
+
- **cli:** Revert deploy PM2 wrapper to pair --agent=<id> (Phase 1 lacks user-JWT)
|
|
43
|
+
|
|
7
44
|
## [2.10.8] — 2026-05-12
|
|
8
45
|
|
|
9
46
|
### Fixed
|
package/dist/index.js
CHANGED
|
@@ -519,9 +519,9 @@ var require_windowsPtyAgent = __commonJS({
|
|
|
519
519
|
"use strict";
|
|
520
520
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
521
521
|
exports2.argsToCommandLine = exports2.WindowsPtyAgent = void 0;
|
|
522
|
-
var
|
|
523
|
-
var
|
|
524
|
-
var
|
|
522
|
+
var fs17 = require("fs");
|
|
523
|
+
var os16 = require("os");
|
|
524
|
+
var path23 = require("path");
|
|
525
525
|
var child_process_1 = require("child_process");
|
|
526
526
|
var net_1 = require("net");
|
|
527
527
|
var windowsConoutConnection_1 = require_windowsConoutConnection();
|
|
@@ -557,7 +557,7 @@ var require_windowsPtyAgent = __commonJS({
|
|
|
557
557
|
}
|
|
558
558
|
}
|
|
559
559
|
this._ptyNative = this._useConpty ? conptyNative : winptyNative;
|
|
560
|
-
cwd =
|
|
560
|
+
cwd = path23.resolve(cwd);
|
|
561
561
|
var commandLine = argsToCommandLine(file, args2);
|
|
562
562
|
var term;
|
|
563
563
|
if (this._useConpty) {
|
|
@@ -578,7 +578,7 @@ var require_windowsPtyAgent = __commonJS({
|
|
|
578
578
|
this._outSocket.on("connect", function() {
|
|
579
579
|
_this._outSocket.emit("ready_datapipe");
|
|
580
580
|
});
|
|
581
|
-
var inSocketFD =
|
|
581
|
+
var inSocketFD = fs17.openSync(term.conin, "w");
|
|
582
582
|
this._inSocket = new net_1.Socket({
|
|
583
583
|
fd: inSocketFD,
|
|
584
584
|
readable: false,
|
|
@@ -679,7 +679,7 @@ var require_windowsPtyAgent = __commonJS({
|
|
|
679
679
|
WindowsPtyAgent2.prototype._getConsoleProcessList = function() {
|
|
680
680
|
var _this = this;
|
|
681
681
|
return new Promise(function(resolve2) {
|
|
682
|
-
var agent = child_process_1.fork(
|
|
682
|
+
var agent = child_process_1.fork(path23.join(__dirname, "conpty_console_list_agent"), [_this._innerPid.toString()]);
|
|
683
683
|
agent.on("message", function(message) {
|
|
684
684
|
clearTimeout(timeout);
|
|
685
685
|
resolve2(message.consoleProcessList);
|
|
@@ -702,7 +702,7 @@ var require_windowsPtyAgent = __commonJS({
|
|
|
702
702
|
configurable: true
|
|
703
703
|
});
|
|
704
704
|
WindowsPtyAgent2.prototype._getWindowsBuildNumber = function() {
|
|
705
|
-
var osVersion = /(\d+)\.(\d+)\.(\d+)/g.exec(
|
|
705
|
+
var osVersion = /(\d+)\.(\d+)\.(\d+)/g.exec(os16.release());
|
|
706
706
|
var buildNumber = 0;
|
|
707
707
|
if (osVersion && osVersion.length === 4) {
|
|
708
708
|
buildNumber = parseInt(osVersion[3]);
|
|
@@ -1012,15 +1012,15 @@ var require_unixTerminal = __commonJS({
|
|
|
1012
1012
|
})();
|
|
1013
1013
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
1014
1014
|
exports2.UnixTerminal = void 0;
|
|
1015
|
-
var
|
|
1016
|
-
var
|
|
1015
|
+
var fs17 = require("fs");
|
|
1016
|
+
var path23 = require("path");
|
|
1017
1017
|
var tty = require("tty");
|
|
1018
1018
|
var terminal_1 = require_terminal();
|
|
1019
1019
|
var utils_1 = require_utils();
|
|
1020
1020
|
var native = utils_1.loadNativeModule("pty");
|
|
1021
1021
|
var pty = native.module;
|
|
1022
1022
|
var helperPath = native.dir + "/spawn-helper";
|
|
1023
|
-
helperPath =
|
|
1023
|
+
helperPath = path23.resolve(__dirname, helperPath);
|
|
1024
1024
|
helperPath = helperPath.replace("app.asar", "app.asar.unpacked");
|
|
1025
1025
|
helperPath = helperPath.replace("node_modules.asar", "node_modules.asar.unpacked");
|
|
1026
1026
|
var DEFAULT_FILE = "sh";
|
|
@@ -1275,7 +1275,7 @@ var require_unixTerminal = __commonJS({
|
|
|
1275
1275
|
return;
|
|
1276
1276
|
}
|
|
1277
1277
|
var task = this._writeQueue[0];
|
|
1278
|
-
|
|
1278
|
+
fs17.write(this._fd, task.buffer, task.offset, function(err, written) {
|
|
1279
1279
|
if (err) {
|
|
1280
1280
|
if ("code" in err && err.code === "EAGAIN") {
|
|
1281
1281
|
_this._writeImmediate = setImmediate(function() {
|
|
@@ -1313,10 +1313,10 @@ var require_lib = __commonJS({
|
|
|
1313
1313
|
} else {
|
|
1314
1314
|
terminalCtor = require_unixTerminal().UnixTerminal;
|
|
1315
1315
|
}
|
|
1316
|
-
function
|
|
1316
|
+
function spawn11(file, args2, opt) {
|
|
1317
1317
|
return new terminalCtor(file, args2, opt);
|
|
1318
1318
|
}
|
|
1319
|
-
exports2.spawn =
|
|
1319
|
+
exports2.spawn = spawn11;
|
|
1320
1320
|
function fork(file, args2, opt) {
|
|
1321
1321
|
return new terminalCtor(file, args2, opt);
|
|
1322
1322
|
}
|
|
@@ -1738,18 +1738,37 @@ function filterChrome(lines) {
|
|
|
1738
1738
|
|
|
1739
1739
|
// ../../packages/shared/src/models/pricing.ts
|
|
1740
1740
|
var MODEL_PRICING = {
|
|
1741
|
+
// ── Anthropic / Claude ────────────────────────────────────
|
|
1741
1742
|
"claude-sonnet-4": { input: 3, output: 15, cacheRead: 0.3, cacheWrite: 3.75 },
|
|
1742
1743
|
"claude-opus-4": { input: 15, output: 75, cacheRead: 1.5, cacheWrite: 18.75 },
|
|
1743
1744
|
"claude-3-5-sonnet": { input: 3, output: 15, cacheRead: 0.3, cacheWrite: 3.75 },
|
|
1744
1745
|
"claude-3-5-haiku": { input: 0.8, output: 4, cacheRead: 0.08, cacheWrite: 1 },
|
|
1745
|
-
"claude-3-haiku": { input: 0.25, output: 1.25, cacheRead: 0.03, cacheWrite: 0.3 }
|
|
1746
|
+
"claude-3-haiku": { input: 0.25, output: 1.25, cacheRead: 0.03, cacheWrite: 0.3 },
|
|
1747
|
+
// ── Codex / OpenAI ────────────────────────────────────────
|
|
1748
|
+
// Phase 2 placeholder pricing: 0 across the board until OpenAI publishes
|
|
1749
|
+
// confirmed rates for the GPT-5.x catalog. Sync from
|
|
1750
|
+
// developers.openai.com/pricing when available.
|
|
1751
|
+
"gpt-5.5": { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
|
|
1752
|
+
"gpt-5.4": { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
|
|
1753
|
+
"gpt-5.4-mini": { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
|
|
1754
|
+
"gpt-5.3-codex": { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
|
|
1755
|
+
"gpt-5.2": { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
|
|
1756
|
+
"codex-auto-review": { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 }
|
|
1746
1757
|
};
|
|
1747
1758
|
var MODEL_CONTEXT_WINDOW = {
|
|
1759
|
+
// ── Anthropic / Claude ────────────────────────────────────
|
|
1748
1760
|
"claude-opus-4": 1e6,
|
|
1749
1761
|
"claude-sonnet-4": 1e6,
|
|
1750
1762
|
"claude-3-5-sonnet": 2e5,
|
|
1751
1763
|
"claude-3-5-haiku": 2e5,
|
|
1752
|
-
"claude-3-haiku": 2e5
|
|
1764
|
+
"claude-3-haiku": 2e5,
|
|
1765
|
+
// ── Codex / OpenAI ────────────────────────────────────────
|
|
1766
|
+
"gpt-5.5": 272e3,
|
|
1767
|
+
"gpt-5.4": 272e3,
|
|
1768
|
+
"gpt-5.4-mini": 272e3,
|
|
1769
|
+
"gpt-5.3-codex": 272e3,
|
|
1770
|
+
"gpt-5.2": 272e3,
|
|
1771
|
+
"codex-auto-review": 272e3
|
|
1753
1772
|
};
|
|
1754
1773
|
var DEFAULT_CONTEXT_WINDOW = 2e5;
|
|
1755
1774
|
function getPricing(model) {
|
|
@@ -1780,7 +1799,7 @@ var AGENT_REGISTRY = {
|
|
|
1780
1799
|
id: "codex",
|
|
1781
1800
|
displayName: "Codex CLI",
|
|
1782
1801
|
binaryName: "codex",
|
|
1783
|
-
enabled:
|
|
1802
|
+
enabled: true,
|
|
1784
1803
|
supportedAuthKinds: ["oauth_token", "api_key"],
|
|
1785
1804
|
preferredAuthKind: "oauth_token"
|
|
1786
1805
|
},
|
|
@@ -1900,7 +1919,7 @@ var import_qrcode_terminal = __toESM(require("qrcode-terminal"));
|
|
|
1900
1919
|
// package.json
|
|
1901
1920
|
var package_default = {
|
|
1902
1921
|
name: "codeam-cli",
|
|
1903
|
-
version: "2.
|
|
1922
|
+
version: "2.12.0",
|
|
1904
1923
|
description: "Remote control Claude Code (and other AI coding agents) from your mobile phone. Pair your device, send prompts, stream responses in real-time, and approve commands \u2014 from anywhere.",
|
|
1905
1924
|
type: "commonjs",
|
|
1906
1925
|
main: "dist/index.js",
|
|
@@ -5648,13 +5667,208 @@ var ClaudeDeployStrategy = class {
|
|
|
5648
5667
|
}
|
|
5649
5668
|
};
|
|
5650
5669
|
|
|
5670
|
+
// src/agents/codex/runtime.ts
|
|
5671
|
+
var import_node_child_process = require("child_process");
|
|
5672
|
+
|
|
5673
|
+
// src/agents/codex/history.ts
|
|
5674
|
+
var import_node_fs2 = __toESM(require("fs"));
|
|
5675
|
+
var import_node_path2 = __toESM(require("path"));
|
|
5676
|
+
var import_node_os = __toESM(require("os"));
|
|
5677
|
+
function resolveHistoryDir2(_cwd, homeOverride) {
|
|
5678
|
+
const home = homeOverride ?? import_node_os.default.homedir();
|
|
5679
|
+
const codexDir = import_node_path2.default.join(home, ".codex");
|
|
5680
|
+
if (!import_node_fs2.default.existsSync(import_node_path2.default.join(codexDir, "history.jsonl"))) return null;
|
|
5681
|
+
return codexDir;
|
|
5682
|
+
}
|
|
5683
|
+
function isCodexRecord(v) {
|
|
5684
|
+
if (!v || typeof v !== "object") return false;
|
|
5685
|
+
const r = v;
|
|
5686
|
+
return typeof r.session_id === "string" && typeof r.ts === "number" && typeof r.text === "string";
|
|
5687
|
+
}
|
|
5688
|
+
function parseHistoryFile2(filePath) {
|
|
5689
|
+
const raw = import_node_fs2.default.readFileSync(filePath, "utf8");
|
|
5690
|
+
const out = [];
|
|
5691
|
+
let idx = 0;
|
|
5692
|
+
for (const line of raw.split("\n").filter(Boolean)) {
|
|
5693
|
+
let rec;
|
|
5694
|
+
try {
|
|
5695
|
+
rec = JSON.parse(line);
|
|
5696
|
+
} catch {
|
|
5697
|
+
continue;
|
|
5698
|
+
}
|
|
5699
|
+
if (!isCodexRecord(rec)) continue;
|
|
5700
|
+
out.push({
|
|
5701
|
+
id: `${rec.session_id}:${idx}`,
|
|
5702
|
+
role: "user",
|
|
5703
|
+
text: rec.text,
|
|
5704
|
+
timestamp: new Date(rec.ts * 1e3).toISOString()
|
|
5705
|
+
});
|
|
5706
|
+
idx++;
|
|
5707
|
+
}
|
|
5708
|
+
return out;
|
|
5709
|
+
}
|
|
5710
|
+
function getCurrentUsage2(_historyDir) {
|
|
5711
|
+
return null;
|
|
5712
|
+
}
|
|
5713
|
+
|
|
5714
|
+
// src/agents/codex/runtime.ts
|
|
5715
|
+
var CODEX_CONTEXT_WINDOW = 272e3;
|
|
5716
|
+
var CODEX_MODELS = [
|
|
5717
|
+
{ id: "gpt-5.5", label: "GPT-5.5", contextWindow: CODEX_CONTEXT_WINDOW },
|
|
5718
|
+
{ id: "gpt-5.4", label: "GPT-5.4", contextWindow: CODEX_CONTEXT_WINDOW },
|
|
5719
|
+
{ id: "gpt-5.4-mini", label: "GPT-5.4 Mini", contextWindow: CODEX_CONTEXT_WINDOW },
|
|
5720
|
+
{ id: "gpt-5.3-codex", label: "GPT-5.3 Codex", contextWindow: CODEX_CONTEXT_WINDOW },
|
|
5721
|
+
{ id: "gpt-5.2", label: "GPT-5.2", contextWindow: CODEX_CONTEXT_WINDOW },
|
|
5722
|
+
{ id: "codex-auto-review", label: "Codex Auto Review", contextWindow: CODEX_CONTEXT_WINDOW }
|
|
5723
|
+
];
|
|
5724
|
+
var CodexRuntimeStrategy = class {
|
|
5725
|
+
id = "codex";
|
|
5726
|
+
meta = getAgent("codex");
|
|
5727
|
+
async prepareLaunch() {
|
|
5728
|
+
const binary = findInPath("codex");
|
|
5729
|
+
if (!binary) {
|
|
5730
|
+
await installCodexViaNpm();
|
|
5731
|
+
const afterInstall = findInPath("codex");
|
|
5732
|
+
if (!afterInstall) {
|
|
5733
|
+
throw new Error(
|
|
5734
|
+
"Could not find 'codex' on PATH after running 'npm install -g @openai/codex'. Install it manually and retry."
|
|
5735
|
+
);
|
|
5736
|
+
}
|
|
5737
|
+
return { cmd: afterInstall, args: [] };
|
|
5738
|
+
}
|
|
5739
|
+
return { cmd: binary, args: [] };
|
|
5740
|
+
}
|
|
5741
|
+
/** `codex resume <SESSION_ID>` — subcommand, not flag. */
|
|
5742
|
+
resumeLaunchArgs(sessionId) {
|
|
5743
|
+
return ["resume", sessionId];
|
|
5744
|
+
}
|
|
5745
|
+
resolveHistoryDir(cwd) {
|
|
5746
|
+
return resolveHistoryDir2(cwd);
|
|
5747
|
+
}
|
|
5748
|
+
parseHistoryFile(filePath) {
|
|
5749
|
+
return parseHistoryFile2(filePath);
|
|
5750
|
+
}
|
|
5751
|
+
getCurrentUsage(historyDir) {
|
|
5752
|
+
return getCurrentUsage2(historyDir);
|
|
5753
|
+
}
|
|
5754
|
+
/**
|
|
5755
|
+
* Codex's quota lives behind the `account/get_account_rate_limits` RPC,
|
|
5756
|
+
* not a TUI slash command. Phase 2 ships with this stubbed to null so the
|
|
5757
|
+
* mobile shows "—" for weekly usage on Codex sessions. A follow-up will
|
|
5758
|
+
* invoke the RPC directly.
|
|
5759
|
+
*/
|
|
5760
|
+
async fetchWeeklyUsage() {
|
|
5761
|
+
return null;
|
|
5762
|
+
}
|
|
5763
|
+
async listModels() {
|
|
5764
|
+
return CODEX_MODELS;
|
|
5765
|
+
}
|
|
5766
|
+
changeModelInstruction(modelId) {
|
|
5767
|
+
return { type: "pty", ptyInput: `/model ${modelId}\r` };
|
|
5768
|
+
}
|
|
5769
|
+
/**
|
|
5770
|
+
* Codex has no auto-compact (`auto_compact_token_limit: null` for every
|
|
5771
|
+
* model). Both modes fall through to the manual `/compact` slash command.
|
|
5772
|
+
*/
|
|
5773
|
+
summarizeInstruction(_mode) {
|
|
5774
|
+
return { ptyInput: "/compact\r" };
|
|
5775
|
+
}
|
|
5776
|
+
};
|
|
5777
|
+
async function installCodexViaNpm() {
|
|
5778
|
+
return new Promise((resolve2, reject) => {
|
|
5779
|
+
const npm = process.platform === "win32" ? "npm.cmd" : "npm";
|
|
5780
|
+
const proc = (0, import_node_child_process.spawn)(npm, ["install", "-g", "@openai/codex"], {
|
|
5781
|
+
stdio: "inherit"
|
|
5782
|
+
});
|
|
5783
|
+
proc.on("close", (code) => {
|
|
5784
|
+
if (code === 0) resolve2();
|
|
5785
|
+
else reject(new Error(`npm install -g @openai/codex exited ${code}`));
|
|
5786
|
+
});
|
|
5787
|
+
proc.on("error", reject);
|
|
5788
|
+
});
|
|
5789
|
+
}
|
|
5790
|
+
|
|
5791
|
+
// src/agents/codex/credentials.ts
|
|
5792
|
+
var import_node_fs3 = __toESM(require("fs"));
|
|
5793
|
+
var import_node_path3 = __toESM(require("path"));
|
|
5794
|
+
var import_node_os2 = __toESM(require("os"));
|
|
5795
|
+
async function detectLocalCodexCredentials() {
|
|
5796
|
+
const home = process.env.HOME ?? import_node_os2.default.homedir();
|
|
5797
|
+
const authJson = import_node_path3.default.join(home, ".codex", "auth.json");
|
|
5798
|
+
if (import_node_fs3.default.existsSync(authJson)) {
|
|
5799
|
+
return { source: "flat-file", description: "~/.codex/auth.json" };
|
|
5800
|
+
}
|
|
5801
|
+
if (process.env.OPENAI_API_KEY) {
|
|
5802
|
+
return { source: "env-var", description: "OPENAI_API_KEY env var" };
|
|
5803
|
+
}
|
|
5804
|
+
return { source: "none", description: "" };
|
|
5805
|
+
}
|
|
5806
|
+
async function bridgeLocalCodexCredentials(provider, workspaceId) {
|
|
5807
|
+
const home = process.env.HOME ?? import_node_os2.default.homedir();
|
|
5808
|
+
const authJson = import_node_path3.default.join(home, ".codex", "auth.json");
|
|
5809
|
+
if (import_node_fs3.default.existsSync(authJson)) {
|
|
5810
|
+
const contents = import_node_fs3.default.readFileSync(authJson);
|
|
5811
|
+
await provider.exec(workspaceId, "mkdir -p ~/.codex && chmod 700 ~/.codex");
|
|
5812
|
+
await provider.uploadFile(workspaceId, "/home/codespace/.codex/auth.json", contents, { mode: 384 });
|
|
5813
|
+
return { source: "flat-file", description: "~/.codex/auth.json" };
|
|
5814
|
+
}
|
|
5815
|
+
const key = process.env.OPENAI_API_KEY;
|
|
5816
|
+
if (key) {
|
|
5817
|
+
const escaped = key.replace(/'/g, "'\\''");
|
|
5818
|
+
const line = `export OPENAI_API_KEY='${escaped}'`;
|
|
5819
|
+
await provider.exec(workspaceId, `grep -qxF "${line}" ~/.bashrc || echo "${line}" >> ~/.bashrc`);
|
|
5820
|
+
return { source: "env-var", description: "OPENAI_API_KEY env var" };
|
|
5821
|
+
}
|
|
5822
|
+
return { source: "none", description: "" };
|
|
5823
|
+
}
|
|
5824
|
+
async function runRemoteCodexLogin(provider, workspaceId) {
|
|
5825
|
+
await provider.streamCommand(workspaceId, 'bash -lc "codex login"');
|
|
5826
|
+
}
|
|
5827
|
+
async function verifyCodexAuth(provider, workspaceId) {
|
|
5828
|
+
const r = await provider.exec(workspaceId, 'bash -lc "codex --version"');
|
|
5829
|
+
return r.code === 0;
|
|
5830
|
+
}
|
|
5831
|
+
|
|
5832
|
+
// src/agents/codex/deploy.ts
|
|
5833
|
+
var CodexDeployStrategy = class {
|
|
5834
|
+
id = "codex";
|
|
5835
|
+
async detectLocalCredentials() {
|
|
5836
|
+
return detectLocalCodexCredentials();
|
|
5837
|
+
}
|
|
5838
|
+
async bridgeLocalCredentials(provider, workspaceId) {
|
|
5839
|
+
return bridgeLocalCodexCredentials(provider, workspaceId);
|
|
5840
|
+
}
|
|
5841
|
+
async runRemoteLogin(provider, workspaceId) {
|
|
5842
|
+
return runRemoteCodexLogin(provider, workspaceId);
|
|
5843
|
+
}
|
|
5844
|
+
/**
|
|
5845
|
+
* Steps 5–7 of the existing local-deploy flow, adapted for Codex:
|
|
5846
|
+
* 1. Install codex via npm
|
|
5847
|
+
* 2. (skipped — bridge already happened before this method runs, or the
|
|
5848
|
+
* fallback runs via runRemoteLogin)
|
|
5849
|
+
* 3. Verify auth; fallback to remote login if verify fails AND no
|
|
5850
|
+
* credentials were bridged.
|
|
5851
|
+
*/
|
|
5852
|
+
async setupOnWorkspace(provider, workspaceId, opts) {
|
|
5853
|
+
const installResult = await provider.exec(workspaceId, "npm install -g @openai/codex");
|
|
5854
|
+
if (installResult.code !== 0) {
|
|
5855
|
+
throw new Error(`codex install failed: ${installResult.stderr.slice(0, 500)}`);
|
|
5856
|
+
}
|
|
5857
|
+
const verified = await verifyCodexAuth(provider, workspaceId);
|
|
5858
|
+
if (!verified && opts.bridged === "none") {
|
|
5859
|
+
await runRemoteCodexLogin(provider, workspaceId);
|
|
5860
|
+
}
|
|
5861
|
+
}
|
|
5862
|
+
};
|
|
5863
|
+
|
|
5651
5864
|
// src/agents/registry.ts
|
|
5652
5865
|
var runtimeBuilders = {
|
|
5653
|
-
claude: () => new ClaudeRuntimeStrategy()
|
|
5654
|
-
|
|
5866
|
+
claude: () => new ClaudeRuntimeStrategy(),
|
|
5867
|
+
codex: () => new CodexRuntimeStrategy()
|
|
5655
5868
|
};
|
|
5656
5869
|
var deployBuilders = {
|
|
5657
|
-
claude: () => new ClaudeDeployStrategy()
|
|
5870
|
+
claude: () => new ClaudeDeployStrategy(),
|
|
5871
|
+
codex: () => new CodexDeployStrategy()
|
|
5658
5872
|
};
|
|
5659
5873
|
function createRuntimeStrategy(agent) {
|
|
5660
5874
|
if (!AGENT_REGISTRY[agent]?.enabled) {
|
|
@@ -6149,9 +6363,9 @@ var OutputService = class _OutputService {
|
|
|
6149
6363
|
};
|
|
6150
6364
|
|
|
6151
6365
|
// src/services/history.service.ts
|
|
6152
|
-
var
|
|
6153
|
-
var
|
|
6154
|
-
var
|
|
6366
|
+
var fs11 = __toESM(require("fs"));
|
|
6367
|
+
var path14 = __toESM(require("path"));
|
|
6368
|
+
var os12 = __toESM(require("os"));
|
|
6155
6369
|
var https4 = __toESM(require("https"));
|
|
6156
6370
|
var http4 = __toESM(require("http"));
|
|
6157
6371
|
var import_zod = require("zod");
|
|
@@ -6178,7 +6392,7 @@ function parseJsonl(filePath) {
|
|
|
6178
6392
|
const messages = [];
|
|
6179
6393
|
let raw;
|
|
6180
6394
|
try {
|
|
6181
|
-
raw =
|
|
6395
|
+
raw = fs11.readFileSync(filePath, "utf8");
|
|
6182
6396
|
} catch (err) {
|
|
6183
6397
|
if (err.code !== "ENOENT") {
|
|
6184
6398
|
log.warn("history:parseJsonl", `read failed for ${filePath}`, err);
|
|
@@ -6312,7 +6526,7 @@ var HistoryService = class _HistoryService {
|
|
|
6312
6526
|
return this._quotaPercent === null || Date.now() - this._quotaFetchedAt > ttlMs;
|
|
6313
6527
|
}
|
|
6314
6528
|
get projectDir() {
|
|
6315
|
-
return this.runtime.resolveHistoryDir(this.cwd) ??
|
|
6529
|
+
return this.runtime.resolveHistoryDir(this.cwd) ?? path14.join(os12.homedir(), ".claude", "projects", encodeCwd(this.cwd));
|
|
6316
6530
|
}
|
|
6317
6531
|
/** Set the current Claude conversation ID (extracted from /cost command or session start) */
|
|
6318
6532
|
setCurrentConversationId(id) {
|
|
@@ -6324,7 +6538,7 @@ var HistoryService = class _HistoryService {
|
|
|
6324
6538
|
/** Return the current message count in the active conversation. */
|
|
6325
6539
|
getCurrentMessageCount() {
|
|
6326
6540
|
if (!this.currentConversationId) return 0;
|
|
6327
|
-
const filePath =
|
|
6541
|
+
const filePath = path14.join(this.projectDir, `${this.currentConversationId}.jsonl`);
|
|
6328
6542
|
return parseJsonl(filePath).length;
|
|
6329
6543
|
}
|
|
6330
6544
|
/**
|
|
@@ -6335,7 +6549,7 @@ var HistoryService = class _HistoryService {
|
|
|
6335
6549
|
const deadline = Date.now() + timeoutMs;
|
|
6336
6550
|
while (Date.now() < deadline) {
|
|
6337
6551
|
if (!this.currentConversationId) return null;
|
|
6338
|
-
const filePath =
|
|
6552
|
+
const filePath = path14.join(this.projectDir, `${this.currentConversationId}.jsonl`);
|
|
6339
6553
|
const messages = parseJsonl(filePath);
|
|
6340
6554
|
if (messages.length > previousCount) {
|
|
6341
6555
|
for (let i = messages.length - 1; i >= previousCount; i--) {
|
|
@@ -6361,16 +6575,16 @@ var HistoryService = class _HistoryService {
|
|
|
6361
6575
|
const dir = this.projectDir;
|
|
6362
6576
|
const cutoff = this.bootTimeMs - _HistoryService.BIRTHTIME_GRACE_MS;
|
|
6363
6577
|
try {
|
|
6364
|
-
const files =
|
|
6578
|
+
const files = fs11.readdirSync(dir, { withFileTypes: true }).filter((e) => e.isFile() && e.name.endsWith(".jsonl")).map((e) => {
|
|
6365
6579
|
try {
|
|
6366
|
-
const stat3 =
|
|
6580
|
+
const stat3 = fs11.statSync(path14.join(dir, e.name));
|
|
6367
6581
|
return { name: e.name, mtime: stat3.mtimeMs, birthtime: stat3.birthtimeMs };
|
|
6368
6582
|
} catch {
|
|
6369
6583
|
return { name: e.name, mtime: 0, birthtime: 0 };
|
|
6370
6584
|
}
|
|
6371
6585
|
}).filter((f) => f.birthtime >= cutoff).sort((a, b) => b.mtime - a.mtime);
|
|
6372
6586
|
if (files.length > 0) {
|
|
6373
|
-
this.currentConversationId =
|
|
6587
|
+
this.currentConversationId = path14.basename(files[0].name, ".jsonl");
|
|
6374
6588
|
}
|
|
6375
6589
|
} catch {
|
|
6376
6590
|
}
|
|
@@ -6404,13 +6618,13 @@ var HistoryService = class _HistoryService {
|
|
|
6404
6618
|
const cutoff = this.bootTimeMs - _HistoryService.BIRTHTIME_GRACE_MS;
|
|
6405
6619
|
let entries;
|
|
6406
6620
|
try {
|
|
6407
|
-
entries =
|
|
6621
|
+
entries = fs11.readdirSync(dir, { withFileTypes: true });
|
|
6408
6622
|
} catch {
|
|
6409
6623
|
return null;
|
|
6410
6624
|
}
|
|
6411
6625
|
const files = entries.filter((e) => e.isFile() && e.name.endsWith(".jsonl")).map((e) => {
|
|
6412
6626
|
try {
|
|
6413
|
-
const stat3 =
|
|
6627
|
+
const stat3 = fs11.statSync(path14.join(dir, e.name));
|
|
6414
6628
|
return { name: e.name, mtime: stat3.mtimeMs, birthtime: stat3.birthtimeMs };
|
|
6415
6629
|
} catch {
|
|
6416
6630
|
return { name: e.name, mtime: 0, birthtime: 0 };
|
|
@@ -6419,12 +6633,12 @@ var HistoryService = class _HistoryService {
|
|
|
6419
6633
|
if (files.length === 0) return null;
|
|
6420
6634
|
const targetFile = this.currentConversationId ? `${this.currentConversationId}.jsonl` : files[0].name;
|
|
6421
6635
|
if (!files.some((f) => f.name === targetFile)) return null;
|
|
6422
|
-
return this.extractUsageFromFile(
|
|
6636
|
+
return this.extractUsageFromFile(path14.join(dir, targetFile));
|
|
6423
6637
|
}
|
|
6424
6638
|
extractUsageFromFile(filePath) {
|
|
6425
6639
|
let raw;
|
|
6426
6640
|
try {
|
|
6427
|
-
raw =
|
|
6641
|
+
raw = fs11.readFileSync(filePath, "utf8");
|
|
6428
6642
|
} catch {
|
|
6429
6643
|
return null;
|
|
6430
6644
|
}
|
|
@@ -6469,9 +6683,9 @@ var HistoryService = class _HistoryService {
|
|
|
6469
6683
|
let totalCost = 0;
|
|
6470
6684
|
let files;
|
|
6471
6685
|
try {
|
|
6472
|
-
files =
|
|
6686
|
+
files = fs11.readdirSync(projectDir).filter((f) => f.endsWith(".jsonl")).filter((f) => {
|
|
6473
6687
|
try {
|
|
6474
|
-
return
|
|
6688
|
+
return fs11.statSync(path14.join(projectDir, f)).mtimeMs >= monthStartMs;
|
|
6475
6689
|
} catch {
|
|
6476
6690
|
return false;
|
|
6477
6691
|
}
|
|
@@ -6482,7 +6696,7 @@ var HistoryService = class _HistoryService {
|
|
|
6482
6696
|
for (const file of files) {
|
|
6483
6697
|
let raw;
|
|
6484
6698
|
try {
|
|
6485
|
-
raw =
|
|
6699
|
+
raw = fs11.readFileSync(path14.join(projectDir, file), "utf8");
|
|
6486
6700
|
} catch {
|
|
6487
6701
|
continue;
|
|
6488
6702
|
}
|
|
@@ -6517,23 +6731,23 @@ var HistoryService = class _HistoryService {
|
|
|
6517
6731
|
const dir = this.projectDir;
|
|
6518
6732
|
let entries;
|
|
6519
6733
|
try {
|
|
6520
|
-
entries =
|
|
6734
|
+
entries = fs11.readdirSync(dir, { withFileTypes: true });
|
|
6521
6735
|
} catch {
|
|
6522
6736
|
return;
|
|
6523
6737
|
}
|
|
6524
6738
|
const sessions2 = [];
|
|
6525
6739
|
for (const entry of entries) {
|
|
6526
6740
|
if (!entry.isFile() || !entry.name.endsWith(".jsonl")) continue;
|
|
6527
|
-
const id =
|
|
6528
|
-
const filePath =
|
|
6741
|
+
const id = path14.basename(entry.name, ".jsonl");
|
|
6742
|
+
const filePath = path14.join(dir, entry.name);
|
|
6529
6743
|
let mtime = Date.now();
|
|
6530
6744
|
try {
|
|
6531
|
-
mtime =
|
|
6745
|
+
mtime = fs11.statSync(filePath).mtimeMs;
|
|
6532
6746
|
} catch {
|
|
6533
6747
|
}
|
|
6534
6748
|
let summary = "";
|
|
6535
6749
|
try {
|
|
6536
|
-
const raw =
|
|
6750
|
+
const raw = fs11.readFileSync(filePath, "utf8");
|
|
6537
6751
|
for (const line of raw.split("\n")) {
|
|
6538
6752
|
if (!line.trim()) continue;
|
|
6539
6753
|
try {
|
|
@@ -6566,7 +6780,7 @@ var HistoryService = class _HistoryService {
|
|
|
6566
6780
|
* showing an empty conversation.
|
|
6567
6781
|
*/
|
|
6568
6782
|
async loadConversation(sessionId) {
|
|
6569
|
-
const filePath =
|
|
6783
|
+
const filePath = path14.join(this.projectDir, `${sessionId}.jsonl`);
|
|
6570
6784
|
const messages = parseJsonl(filePath);
|
|
6571
6785
|
if (messages.length === 0) return;
|
|
6572
6786
|
const totalBatches = Math.ceil(messages.length / CONVERSATION_BATCH_SIZE);
|
|
@@ -6609,7 +6823,7 @@ var HistoryService = class _HistoryService {
|
|
|
6609
6823
|
if (!this.currentConversationId) return 0;
|
|
6610
6824
|
}
|
|
6611
6825
|
const sessionId = this.currentConversationId;
|
|
6612
|
-
const filePath =
|
|
6826
|
+
const filePath = path14.join(this.projectDir, `${sessionId}.jsonl`);
|
|
6613
6827
|
const messages = parseJsonl(filePath);
|
|
6614
6828
|
if (messages.length === 0) return 0;
|
|
6615
6829
|
const marker = this.lastUploadedUuid.get(sessionId);
|
|
@@ -6695,9 +6909,9 @@ function buildKeepAlive(ctx) {
|
|
|
6695
6909
|
}
|
|
6696
6910
|
|
|
6697
6911
|
// src/commands/start/handlers.ts
|
|
6698
|
-
var
|
|
6699
|
-
var
|
|
6700
|
-
var
|
|
6912
|
+
var fs14 = __toESM(require("fs"));
|
|
6913
|
+
var os13 = __toESM(require("os"));
|
|
6914
|
+
var path17 = __toESM(require("path"));
|
|
6701
6915
|
var import_crypto = require("crypto");
|
|
6702
6916
|
var import_child_process8 = require("child_process");
|
|
6703
6917
|
|
|
@@ -6736,8 +6950,8 @@ function parsePayload(schema, raw) {
|
|
|
6736
6950
|
}
|
|
6737
6951
|
|
|
6738
6952
|
// src/services/file-ops.service.ts
|
|
6739
|
-
var
|
|
6740
|
-
var
|
|
6953
|
+
var fs12 = __toESM(require("fs/promises"));
|
|
6954
|
+
var path15 = __toESM(require("path"));
|
|
6741
6955
|
var MAX_FILE_BYTES = 5 * 1024 * 1024;
|
|
6742
6956
|
var MAX_WALK_DEPTH = 6;
|
|
6743
6957
|
var MAX_VISITED_DIRS = 5e3;
|
|
@@ -6772,12 +6986,12 @@ var SUBDIR_IGNORE = /* @__PURE__ */ new Set([
|
|
|
6772
6986
|
"__pycache__"
|
|
6773
6987
|
]);
|
|
6774
6988
|
function isUnder(parent, candidate) {
|
|
6775
|
-
const rel =
|
|
6776
|
-
return rel === "" || !rel.startsWith("..") && !
|
|
6989
|
+
const rel = path15.relative(parent, candidate);
|
|
6990
|
+
return rel === "" || !rel.startsWith("..") && !path15.isAbsolute(rel);
|
|
6777
6991
|
}
|
|
6778
6992
|
async function isExistingFile(absPath) {
|
|
6779
6993
|
try {
|
|
6780
|
-
const stat3 = await
|
|
6994
|
+
const stat3 = await fs12.stat(absPath);
|
|
6781
6995
|
return stat3.isFile();
|
|
6782
6996
|
} catch {
|
|
6783
6997
|
return false;
|
|
@@ -6790,13 +7004,13 @@ async function walkForSuffix(dir, needleVariants, depth, ctx) {
|
|
|
6790
7004
|
ctx.visited++;
|
|
6791
7005
|
let entries = [];
|
|
6792
7006
|
try {
|
|
6793
|
-
entries = await
|
|
7007
|
+
entries = await fs12.readdir(dir, { withFileTypes: true });
|
|
6794
7008
|
} catch {
|
|
6795
7009
|
return;
|
|
6796
7010
|
}
|
|
6797
7011
|
for (const e of entries) {
|
|
6798
7012
|
if (!e.isFile()) continue;
|
|
6799
|
-
const full =
|
|
7013
|
+
const full = path15.join(dir, e.name);
|
|
6800
7014
|
if (needleVariants.some((needle) => full.endsWith(needle))) {
|
|
6801
7015
|
ctx.matches.push(full);
|
|
6802
7016
|
if (ctx.matches.length >= ctx.cap) return;
|
|
@@ -6806,21 +7020,21 @@ async function walkForSuffix(dir, needleVariants, depth, ctx) {
|
|
|
6806
7020
|
if (!e.isDirectory()) continue;
|
|
6807
7021
|
if (SUBDIR_IGNORE.has(e.name)) continue;
|
|
6808
7022
|
if (e.name.startsWith(".") && SUBDIR_IGNORE.has(e.name)) continue;
|
|
6809
|
-
await walkForSuffix(
|
|
7023
|
+
await walkForSuffix(path15.join(dir, e.name), needleVariants, depth + 1, ctx);
|
|
6810
7024
|
if (ctx.matches.length >= ctx.cap) return;
|
|
6811
7025
|
}
|
|
6812
7026
|
}
|
|
6813
7027
|
async function findFile(rawPath) {
|
|
6814
7028
|
const cwd = process.cwd();
|
|
6815
|
-
if (
|
|
6816
|
-
const abs =
|
|
7029
|
+
if (path15.isAbsolute(rawPath)) {
|
|
7030
|
+
const abs = path15.normalize(rawPath);
|
|
6817
7031
|
if (isUnder(cwd, abs) && await isExistingFile(abs)) return abs;
|
|
6818
7032
|
}
|
|
6819
|
-
const direct =
|
|
7033
|
+
const direct = path15.resolve(cwd, rawPath);
|
|
6820
7034
|
if (isUnder(cwd, direct) && await isExistingFile(direct)) return direct;
|
|
6821
|
-
const normalized =
|
|
7035
|
+
const normalized = path15.normalize(rawPath).replace(/^[./\\]+/, "");
|
|
6822
7036
|
const needles = [
|
|
6823
|
-
`${
|
|
7037
|
+
`${path15.sep}${normalized}`,
|
|
6824
7038
|
`/${normalized}`
|
|
6825
7039
|
].filter((v, i, a) => a.indexOf(v) === i);
|
|
6826
7040
|
const ctx = { visited: 0, matches: [], cap: 16 };
|
|
@@ -6834,7 +7048,7 @@ async function findWriteTarget(rawPath) {
|
|
|
6834
7048
|
const found = await findFile(rawPath);
|
|
6835
7049
|
if (found) return found;
|
|
6836
7050
|
const cwd = process.cwd();
|
|
6837
|
-
const fallback =
|
|
7051
|
+
const fallback = path15.isAbsolute(rawPath) ? path15.normalize(rawPath) : path15.resolve(cwd, rawPath);
|
|
6838
7052
|
if (!isUnder(cwd, fallback)) return null;
|
|
6839
7053
|
return fallback;
|
|
6840
7054
|
}
|
|
@@ -6851,11 +7065,11 @@ async function readProjectFile(rawPath) {
|
|
|
6851
7065
|
if (!abs) {
|
|
6852
7066
|
return { error: `File not found in the project tree: ${rawPath}` };
|
|
6853
7067
|
}
|
|
6854
|
-
const stat3 = await
|
|
7068
|
+
const stat3 = await fs12.stat(abs);
|
|
6855
7069
|
if (stat3.size > MAX_FILE_BYTES) {
|
|
6856
7070
|
return { error: `File too large (${(stat3.size / 1024 / 1024).toFixed(1)} MB > ${MAX_FILE_BYTES / 1024 / 1024} MB).` };
|
|
6857
7071
|
}
|
|
6858
|
-
const buf = await
|
|
7072
|
+
const buf = await fs12.readFile(abs);
|
|
6859
7073
|
if (looksBinary(buf)) {
|
|
6860
7074
|
return { error: "Binary file \u2014 refusing to open in a code editor." };
|
|
6861
7075
|
}
|
|
@@ -6874,8 +7088,8 @@ async function writeProjectFile(rawPath, content) {
|
|
|
6874
7088
|
if (Buffer.byteLength(content, "utf-8") > MAX_FILE_BYTES) {
|
|
6875
7089
|
return { error: "Content too large." };
|
|
6876
7090
|
}
|
|
6877
|
-
await
|
|
6878
|
-
await
|
|
7091
|
+
await fs12.mkdir(path15.dirname(abs), { recursive: true });
|
|
7092
|
+
await fs12.writeFile(abs, content, "utf-8");
|
|
6879
7093
|
return { ok: true };
|
|
6880
7094
|
} catch (e) {
|
|
6881
7095
|
const msg = e instanceof Error ? e.message : "Write failed";
|
|
@@ -6886,8 +7100,8 @@ async function writeProjectFile(rawPath, content) {
|
|
|
6886
7100
|
// src/services/project-ops.service.ts
|
|
6887
7101
|
var import_child_process7 = require("child_process");
|
|
6888
7102
|
var import_util2 = require("util");
|
|
6889
|
-
var
|
|
6890
|
-
var
|
|
7103
|
+
var fs13 = __toESM(require("fs/promises"));
|
|
7104
|
+
var path16 = __toESM(require("path"));
|
|
6891
7105
|
var execFileP2 = (0, import_util2.promisify)(import_child_process7.execFile);
|
|
6892
7106
|
var PROJECT_IGNORE = /* @__PURE__ */ new Set([
|
|
6893
7107
|
"node_modules",
|
|
@@ -6935,7 +7149,7 @@ async function listProjectFiles(opts = {}) {
|
|
|
6935
7149
|
}
|
|
6936
7150
|
let entries = [];
|
|
6937
7151
|
try {
|
|
6938
|
-
entries = await
|
|
7152
|
+
entries = await fs13.readdir(dir, { withFileTypes: true });
|
|
6939
7153
|
} catch {
|
|
6940
7154
|
return;
|
|
6941
7155
|
}
|
|
@@ -6945,18 +7159,18 @@ async function listProjectFiles(opts = {}) {
|
|
|
6945
7159
|
return;
|
|
6946
7160
|
}
|
|
6947
7161
|
if (PROJECT_IGNORE.has(e.name)) continue;
|
|
6948
|
-
const full =
|
|
7162
|
+
const full = path16.join(dir, e.name);
|
|
6949
7163
|
if (e.isDirectory()) {
|
|
6950
7164
|
if (depth >= 12) continue;
|
|
6951
7165
|
await walk(full, depth + 1);
|
|
6952
7166
|
} else if (e.isFile()) {
|
|
6953
|
-
const rel =
|
|
7167
|
+
const rel = path16.relative(root, full);
|
|
6954
7168
|
if (q2 && !rel.toLowerCase().includes(q2) && !e.name.toLowerCase().includes(q2)) {
|
|
6955
7169
|
continue;
|
|
6956
7170
|
}
|
|
6957
7171
|
let size = 0;
|
|
6958
7172
|
try {
|
|
6959
|
-
const st3 = await
|
|
7173
|
+
const st3 = await fs13.stat(full);
|
|
6960
7174
|
size = st3.size;
|
|
6961
7175
|
} catch {
|
|
6962
7176
|
}
|
|
@@ -7058,8 +7272,8 @@ async function gitStatus(cwd) {
|
|
|
7058
7272
|
let hasMergeInProgress = false;
|
|
7059
7273
|
try {
|
|
7060
7274
|
const gitDir = (await git(["rev-parse", "--git-dir"], root)).stdout.trim();
|
|
7061
|
-
const mergeHead =
|
|
7062
|
-
await
|
|
7275
|
+
const mergeHead = path16.isAbsolute(gitDir) ? path16.join(gitDir, "MERGE_HEAD") : path16.join(root, gitDir, "MERGE_HEAD");
|
|
7276
|
+
await fs13.access(mergeHead);
|
|
7063
7277
|
hasMergeInProgress = true;
|
|
7064
7278
|
} catch {
|
|
7065
7279
|
}
|
|
@@ -7136,8 +7350,8 @@ async function gitResolve(file, side, cwd) {
|
|
|
7136
7350
|
function saveFilesTemp(files) {
|
|
7137
7351
|
return files.filter(({ base64 }) => base64 && base64.length > 0).map(({ filename, base64 }) => {
|
|
7138
7352
|
const safeName = filename.replace(/[^a-zA-Z0-9._-]/g, "_").slice(0, 80);
|
|
7139
|
-
const tmpPath =
|
|
7140
|
-
|
|
7353
|
+
const tmpPath = path17.join(os13.tmpdir(), `codeam-${(0, import_crypto.randomUUID)()}-${safeName}`);
|
|
7354
|
+
fs14.writeFileSync(tmpPath, Buffer.from(base64, "base64"));
|
|
7141
7355
|
return tmpPath;
|
|
7142
7356
|
});
|
|
7143
7357
|
}
|
|
@@ -7156,7 +7370,7 @@ var startTask = (ctx, _cmd, parsed) => {
|
|
|
7156
7370
|
setTimeout(() => {
|
|
7157
7371
|
for (const p2 of paths) {
|
|
7158
7372
|
try {
|
|
7159
|
-
|
|
7373
|
+
fs14.unlinkSync(p2);
|
|
7160
7374
|
} catch {
|
|
7161
7375
|
}
|
|
7162
7376
|
}
|
|
@@ -7615,8 +7829,8 @@ async function pair(args2 = []) {
|
|
|
7615
7829
|
}
|
|
7616
7830
|
|
|
7617
7831
|
// src/commands/pair-auto.ts
|
|
7618
|
-
var
|
|
7619
|
-
var
|
|
7832
|
+
var fs15 = __toESM(require("fs"));
|
|
7833
|
+
var os14 = __toESM(require("os"));
|
|
7620
7834
|
var import_crypto3 = require("crypto");
|
|
7621
7835
|
var API_BASE5 = process.env.CODEAM_API_URL ?? "https://codeagent-mobile-api.vercel.app";
|
|
7622
7836
|
function fail(msg) {
|
|
@@ -7633,12 +7847,12 @@ function readTokenFromArgs(args2) {
|
|
|
7633
7847
|
}
|
|
7634
7848
|
const fileFlag = args2.find((a) => a.startsWith("--token-file="));
|
|
7635
7849
|
if (fileFlag) {
|
|
7636
|
-
const
|
|
7850
|
+
const path23 = fileFlag.slice("--token-file=".length);
|
|
7637
7851
|
try {
|
|
7638
|
-
const content =
|
|
7639
|
-
if (content.length === 0) fail(`--token-file ${
|
|
7852
|
+
const content = fs15.readFileSync(path23, "utf8").trim();
|
|
7853
|
+
if (content.length === 0) fail(`--token-file ${path23} is empty`);
|
|
7640
7854
|
try {
|
|
7641
|
-
|
|
7855
|
+
fs15.unlinkSync(path23);
|
|
7642
7856
|
} catch {
|
|
7643
7857
|
}
|
|
7644
7858
|
return content;
|
|
@@ -7656,7 +7870,7 @@ async function claim(token, pluginId) {
|
|
|
7656
7870
|
pluginId,
|
|
7657
7871
|
ideName: "codeam-cli (codespace)",
|
|
7658
7872
|
ideVersion: process.env.npm_package_version ?? "unknown",
|
|
7659
|
-
hostname:
|
|
7873
|
+
hostname: os14.hostname(),
|
|
7660
7874
|
codespaceName: process.env.CODESPACE_NAME ?? ""
|
|
7661
7875
|
};
|
|
7662
7876
|
const res = await fetch(url, {
|
|
@@ -7808,7 +8022,7 @@ var import_picocolors9 = __toESM(require("picocolors"));
|
|
|
7808
8022
|
var import_child_process9 = require("child_process");
|
|
7809
8023
|
var import_util3 = require("util");
|
|
7810
8024
|
var import_picocolors7 = __toESM(require("picocolors"));
|
|
7811
|
-
var
|
|
8025
|
+
var path18 = __toESM(require("path"));
|
|
7812
8026
|
var execFileP3 = (0, import_util3.promisify)(import_child_process9.execFile);
|
|
7813
8027
|
var MAX_BUFFER = 8 * 1024 * 1024;
|
|
7814
8028
|
function resetStdinForChild() {
|
|
@@ -8297,7 +8511,7 @@ var GitHubCodespacesProvider = class {
|
|
|
8297
8511
|
});
|
|
8298
8512
|
}
|
|
8299
8513
|
async uploadFile(workspaceId, remotePath, contents, options = {}) {
|
|
8300
|
-
const remoteDir =
|
|
8514
|
+
const remoteDir = path18.posix.dirname(remotePath);
|
|
8301
8515
|
const parts = [
|
|
8302
8516
|
`mkdir -p ${shellQuote(remoteDir)}`,
|
|
8303
8517
|
`cat > ${shellQuote(remotePath)}`
|
|
@@ -8367,7 +8581,7 @@ function shellQuote(s) {
|
|
|
8367
8581
|
// src/services/providers/gitpod.ts
|
|
8368
8582
|
var import_child_process10 = require("child_process");
|
|
8369
8583
|
var import_util4 = require("util");
|
|
8370
|
-
var
|
|
8584
|
+
var path19 = __toESM(require("path"));
|
|
8371
8585
|
var import_picocolors8 = __toESM(require("picocolors"));
|
|
8372
8586
|
var execFileP4 = (0, import_util4.promisify)(import_child_process10.execFile);
|
|
8373
8587
|
var MAX_BUFFER2 = 8 * 1024 * 1024;
|
|
@@ -8607,7 +8821,7 @@ var GitpodProvider = class {
|
|
|
8607
8821
|
});
|
|
8608
8822
|
}
|
|
8609
8823
|
async uploadFile(workspaceId, remotePath, contents, options = {}) {
|
|
8610
|
-
const remoteDir =
|
|
8824
|
+
const remoteDir = path19.posix.dirname(remotePath);
|
|
8611
8825
|
const parts = [
|
|
8612
8826
|
`mkdir -p ${shellQuote2(remoteDir)}`,
|
|
8613
8827
|
`cat > ${shellQuote2(remotePath)}`
|
|
@@ -8643,7 +8857,7 @@ function shellQuote2(s) {
|
|
|
8643
8857
|
// src/services/providers/gitlab-workspaces.ts
|
|
8644
8858
|
var import_child_process11 = require("child_process");
|
|
8645
8859
|
var import_util5 = require("util");
|
|
8646
|
-
var
|
|
8860
|
+
var path20 = __toESM(require("path"));
|
|
8647
8861
|
var execFileP5 = (0, import_util5.promisify)(import_child_process11.execFile);
|
|
8648
8862
|
var MAX_BUFFER3 = 8 * 1024 * 1024;
|
|
8649
8863
|
var GITLAB_API_BASE = process.env.CODEAM_GITLAB_API_URL ?? "https://gitlab.com/api/v4";
|
|
@@ -8903,7 +9117,7 @@ Docs: https://docs.gitlab.com/ee/user/workspace/configuration.html`
|
|
|
8903
9117
|
}
|
|
8904
9118
|
async uploadFile(workspaceId, remotePath, contents, options = {}) {
|
|
8905
9119
|
const sshHost = process.env.CODEAM_GITLAB_SSH_HOST ?? "workspaces.gitlab.com";
|
|
8906
|
-
const remoteDir =
|
|
9120
|
+
const remoteDir = path20.posix.dirname(remotePath);
|
|
8907
9121
|
const parts = [`mkdir -p ${shellQuote3(remoteDir)}`, `cat > ${shellQuote3(remotePath)}`];
|
|
8908
9122
|
if (options.mode != null) {
|
|
8909
9123
|
parts.push(`chmod ${options.mode.toString(8)} ${shellQuote3(remotePath)}`);
|
|
@@ -8971,7 +9185,7 @@ function shellQuote3(s) {
|
|
|
8971
9185
|
// src/services/providers/railway.ts
|
|
8972
9186
|
var import_child_process12 = require("child_process");
|
|
8973
9187
|
var import_util6 = require("util");
|
|
8974
|
-
var
|
|
9188
|
+
var path21 = __toESM(require("path"));
|
|
8975
9189
|
var execFileP6 = (0, import_util6.promisify)(import_child_process12.execFile);
|
|
8976
9190
|
var MAX_BUFFER4 = 8 * 1024 * 1024;
|
|
8977
9191
|
function resetStdinForChild4() {
|
|
@@ -9207,7 +9421,7 @@ var RailwayProvider = class {
|
|
|
9207
9421
|
if (!projectId || !serviceId) {
|
|
9208
9422
|
throw new Error("Invalid Railway workspace id (expected projectId/serviceId).");
|
|
9209
9423
|
}
|
|
9210
|
-
const remoteDir =
|
|
9424
|
+
const remoteDir = path21.posix.dirname(remotePath);
|
|
9211
9425
|
const parts = [`mkdir -p ${shellQuote4(remoteDir)}`, `cat > ${shellQuote4(remotePath)}`];
|
|
9212
9426
|
if (options.mode != null) {
|
|
9213
9427
|
parts.push(`chmod ${options.mode.toString(8)} ${shellQuote4(remotePath)}`);
|
|
@@ -9749,7 +9963,7 @@ async function stopWorkspaceFromLocal(target) {
|
|
|
9749
9963
|
// src/commands/version.ts
|
|
9750
9964
|
var import_picocolors11 = __toESM(require("picocolors"));
|
|
9751
9965
|
function version() {
|
|
9752
|
-
const v = true ? "2.
|
|
9966
|
+
const v = true ? "2.12.0" : "unknown";
|
|
9753
9967
|
console.log(`${import_picocolors11.default.bold("codeam-cli")} ${import_picocolors11.default.cyan(v)}`);
|
|
9754
9968
|
}
|
|
9755
9969
|
|
|
@@ -9786,9 +10000,9 @@ function help() {
|
|
|
9786
10000
|
}
|
|
9787
10001
|
|
|
9788
10002
|
// src/lib/updateNotifier.ts
|
|
9789
|
-
var
|
|
9790
|
-
var
|
|
9791
|
-
var
|
|
10003
|
+
var fs16 = __toESM(require("fs"));
|
|
10004
|
+
var os15 = __toESM(require("os"));
|
|
10005
|
+
var path22 = __toESM(require("path"));
|
|
9792
10006
|
var https5 = __toESM(require("https"));
|
|
9793
10007
|
var import_picocolors13 = __toESM(require("picocolors"));
|
|
9794
10008
|
var PKG_NAME = "codeam-cli";
|
|
@@ -9796,12 +10010,12 @@ var REGISTRY_URL = `https://registry.npmjs.org/${PKG_NAME}/latest`;
|
|
|
9796
10010
|
var TTL_MS = 24 * 60 * 60 * 1e3;
|
|
9797
10011
|
var REQUEST_TIMEOUT_MS = 1500;
|
|
9798
10012
|
function cachePath() {
|
|
9799
|
-
const dir =
|
|
9800
|
-
return
|
|
10013
|
+
const dir = path22.join(os15.homedir(), ".codeam");
|
|
10014
|
+
return path22.join(dir, "update-check.json");
|
|
9801
10015
|
}
|
|
9802
10016
|
function readCache() {
|
|
9803
10017
|
try {
|
|
9804
|
-
const raw =
|
|
10018
|
+
const raw = fs16.readFileSync(cachePath(), "utf8");
|
|
9805
10019
|
const parsed = JSON.parse(raw);
|
|
9806
10020
|
if (typeof parsed.fetchedAt !== "number" || typeof parsed.latest !== "string") return null;
|
|
9807
10021
|
return parsed;
|
|
@@ -9812,8 +10026,8 @@ function readCache() {
|
|
|
9812
10026
|
function writeCache(cache) {
|
|
9813
10027
|
try {
|
|
9814
10028
|
const file = cachePath();
|
|
9815
|
-
|
|
9816
|
-
|
|
10029
|
+
fs16.mkdirSync(path22.dirname(file), { recursive: true });
|
|
10030
|
+
fs16.writeFileSync(file, JSON.stringify(cache));
|
|
9817
10031
|
} catch {
|
|
9818
10032
|
}
|
|
9819
10033
|
}
|
|
@@ -9884,7 +10098,7 @@ function checkForUpdates() {
|
|
|
9884
10098
|
if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
|
|
9885
10099
|
if (process.env.CI) return;
|
|
9886
10100
|
if (!process.stdout.isTTY) return;
|
|
9887
|
-
const current = true ? "2.
|
|
10101
|
+
const current = true ? "2.12.0" : null;
|
|
9888
10102
|
if (!current) return;
|
|
9889
10103
|
const cache = readCache();
|
|
9890
10104
|
const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "codeam-cli",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.12.0",
|
|
4
4
|
"description": "Remote control Claude Code (and other AI coding agents) from your mobile phone. Pair your device, send prompts, stream responses in real-time, and approve commands — from anywhere.",
|
|
5
5
|
"type": "commonjs",
|
|
6
6
|
"main": "dist/index.js",
|