@ganglion/xacpx 0.15.1 → 0.15.3
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/README.md +2 -2
- package/dist/bridge/bridge-main.js +178 -11
- package/dist/cli.js +251 -66
- package/dist/control/control-service.d.ts +5 -0
- package/dist/transport/types.d.ts +2 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# xacpx
|
|
2
2
|
|
|
3
|
+

|
|
4
|
+
|
|
3
5
|
> Remotely drive Codex, Claude Code, and other acpx sessions from WeChat, Feishu, or Yuanbao.
|
|
4
6
|
|
|
5
7
|
[](https://www.npmjs.com/package/@ganglion/xacpx)
|
|
@@ -13,8 +15,6 @@ English · **[中文](./docs/zh/README_zh.md)**
|
|
|
13
15
|
|
|
14
16
|
`xacpx` is a tool that lets you control ACP agents such as Codex / Claude Code / Gemini / OpenCode directly from WeChat, Feishu, or Yuanbao. It connects chat messages to your agent CLI sessions through `acpx`, so you can, right from your phone:
|
|
15
17
|
|
|
16
|
-
[](https://imgchr.com/i/pmZXIv6)
|
|
17
|
-
|
|
18
18
|
- Create and switch between sessions
|
|
19
19
|
- Have the agent keep working in a specific project directory
|
|
20
20
|
- View streaming replies, final results, and tool-call summaries
|
|
@@ -820,6 +820,13 @@ var init_streaming_prompt = __esm(() => {
|
|
|
820
820
|
];
|
|
821
821
|
});
|
|
822
822
|
|
|
823
|
+
// src/transport/model-not-advertised.ts
|
|
824
|
+
function isModelNotAdvertisedError(text) {
|
|
825
|
+
if (!text)
|
|
826
|
+
return false;
|
|
827
|
+
return /Cannot (?:apply --model|replay saved model)\b/i.test(text) || /did not advertise (?:that model|model support)/i.test(text);
|
|
828
|
+
}
|
|
829
|
+
|
|
823
830
|
// src/recovery/discover-parent-package-paths.ts
|
|
824
831
|
import { spawn as spawn2 } from "node:child_process";
|
|
825
832
|
import { createRequire as createRequire2 } from "node:module";
|
|
@@ -3470,6 +3477,143 @@ var init_path = __esm(() => {
|
|
|
3470
3477
|
ROOT_PATH_RE = /^(\/|[a-zA-Z]:\/?)$/;
|
|
3471
3478
|
});
|
|
3472
3479
|
|
|
3480
|
+
// src/transport/codex-subagent-filter.ts
|
|
3481
|
+
import { closeSync, openSync, readdirSync, readSync, statSync } from "node:fs";
|
|
3482
|
+
import { homedir as homedir4 } from "node:os";
|
|
3483
|
+
import { join as join3 } from "node:path";
|
|
3484
|
+
function resolveCodexHome(env = process.env) {
|
|
3485
|
+
const fromEnv = env.CODEX_HOME?.trim();
|
|
3486
|
+
return fromEnv ? fromEnv : join3(homedir4(), ".codex");
|
|
3487
|
+
}
|
|
3488
|
+
function isPlainObject(value) {
|
|
3489
|
+
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
3490
|
+
}
|
|
3491
|
+
function isSubagentSource(source) {
|
|
3492
|
+
if (!isPlainObject(source) || !Object.hasOwn(source, "subagent"))
|
|
3493
|
+
return false;
|
|
3494
|
+
const subagent = source.subagent;
|
|
3495
|
+
if (!isPlainObject(subagent))
|
|
3496
|
+
return false;
|
|
3497
|
+
return Object.values(subagent).some((variant) => isPlainObject(variant) && typeof variant.parent_thread_id === "string");
|
|
3498
|
+
}
|
|
3499
|
+
function sessionMetaLineIsSubagent(line) {
|
|
3500
|
+
if (!line)
|
|
3501
|
+
return false;
|
|
3502
|
+
let parsed;
|
|
3503
|
+
try {
|
|
3504
|
+
parsed = JSON.parse(line);
|
|
3505
|
+
} catch {
|
|
3506
|
+
return false;
|
|
3507
|
+
}
|
|
3508
|
+
const payload = parsed?.payload;
|
|
3509
|
+
return isSubagentSource(payload?.source);
|
|
3510
|
+
}
|
|
3511
|
+
function createSubagentPredicate(reader) {
|
|
3512
|
+
let index = null;
|
|
3513
|
+
const cache = new Map;
|
|
3514
|
+
return (sessionId) => {
|
|
3515
|
+
const cached = cache.get(sessionId);
|
|
3516
|
+
if (cached !== undefined)
|
|
3517
|
+
return cached;
|
|
3518
|
+
let result = false;
|
|
3519
|
+
try {
|
|
3520
|
+
if (!index) {
|
|
3521
|
+
index = new Map;
|
|
3522
|
+
for (const path4 of reader.listRolloutPaths()) {
|
|
3523
|
+
const id = path4.match(ROLLOUT_RE)?.[1];
|
|
3524
|
+
if (id)
|
|
3525
|
+
index.set(id.toLowerCase(), path4);
|
|
3526
|
+
}
|
|
3527
|
+
}
|
|
3528
|
+
const path3 = index.get(sessionId.toLowerCase());
|
|
3529
|
+
if (path3)
|
|
3530
|
+
result = sessionMetaLineIsSubagent(reader.readFirstLine(path3));
|
|
3531
|
+
} catch {
|
|
3532
|
+
result = false;
|
|
3533
|
+
}
|
|
3534
|
+
cache.set(sessionId, result);
|
|
3535
|
+
return result;
|
|
3536
|
+
};
|
|
3537
|
+
}
|
|
3538
|
+
function filterSubagentSessions(result, isSubagent) {
|
|
3539
|
+
return {
|
|
3540
|
+
...result,
|
|
3541
|
+
sessions: result.sessions.filter((session3) => {
|
|
3542
|
+
try {
|
|
3543
|
+
return !isSubagent(session3.sessionId);
|
|
3544
|
+
} catch {
|
|
3545
|
+
return true;
|
|
3546
|
+
}
|
|
3547
|
+
})
|
|
3548
|
+
};
|
|
3549
|
+
}
|
|
3550
|
+
function nodeRolloutReader(home) {
|
|
3551
|
+
const root = join3(home, "sessions");
|
|
3552
|
+
return {
|
|
3553
|
+
listRolloutPaths() {
|
|
3554
|
+
const out = [];
|
|
3555
|
+
const walk = (dir) => {
|
|
3556
|
+
let entries;
|
|
3557
|
+
try {
|
|
3558
|
+
entries = readdirSync(dir, { withFileTypes: true });
|
|
3559
|
+
} catch {
|
|
3560
|
+
return;
|
|
3561
|
+
}
|
|
3562
|
+
for (const entry of entries) {
|
|
3563
|
+
const full = join3(dir, entry.name);
|
|
3564
|
+
if (entry.isDirectory())
|
|
3565
|
+
walk(full);
|
|
3566
|
+
else if (entry.isFile() && entry.name.startsWith("rollout-") && entry.name.endsWith(".jsonl"))
|
|
3567
|
+
out.push(full);
|
|
3568
|
+
}
|
|
3569
|
+
};
|
|
3570
|
+
walk(root);
|
|
3571
|
+
return out;
|
|
3572
|
+
},
|
|
3573
|
+
readFirstLine(path3) {
|
|
3574
|
+
let fd;
|
|
3575
|
+
try {
|
|
3576
|
+
statSync(path3);
|
|
3577
|
+
fd = openSync(path3, "r");
|
|
3578
|
+
const buf = Buffer.alloc(READ_CHUNK);
|
|
3579
|
+
let acc = "";
|
|
3580
|
+
let total = 0;
|
|
3581
|
+
for (;; ) {
|
|
3582
|
+
const bytes = readSync(fd, buf, 0, READ_CHUNK, total);
|
|
3583
|
+
if (bytes <= 0)
|
|
3584
|
+
break;
|
|
3585
|
+
acc += buf.toString("utf8", 0, bytes);
|
|
3586
|
+
total += bytes;
|
|
3587
|
+
const nl = acc.indexOf(`
|
|
3588
|
+
`);
|
|
3589
|
+
if (nl !== -1)
|
|
3590
|
+
return acc.slice(0, nl);
|
|
3591
|
+
if (total >= FIRST_LINE_READ_CAP)
|
|
3592
|
+
return;
|
|
3593
|
+
}
|
|
3594
|
+
return acc.length ? acc : undefined;
|
|
3595
|
+
} catch {
|
|
3596
|
+
return;
|
|
3597
|
+
} finally {
|
|
3598
|
+
if (fd !== undefined) {
|
|
3599
|
+
try {
|
|
3600
|
+
closeSync(fd);
|
|
3601
|
+
} catch {}
|
|
3602
|
+
}
|
|
3603
|
+
}
|
|
3604
|
+
}
|
|
3605
|
+
};
|
|
3606
|
+
}
|
|
3607
|
+
function codexSubagentPredicate(env) {
|
|
3608
|
+
return createSubagentPredicate(nodeRolloutReader(resolveCodexHome(env)));
|
|
3609
|
+
}
|
|
3610
|
+
var CODEX_AGENT_NAME = "codex", FIRST_LINE_READ_CAP, READ_CHUNK, ROLLOUT_RE;
|
|
3611
|
+
var init_codex_subagent_filter = __esm(() => {
|
|
3612
|
+
FIRST_LINE_READ_CAP = 1024 * 1024;
|
|
3613
|
+
READ_CHUNK = 64 * 1024;
|
|
3614
|
+
ROLLOUT_RE = /rollout-.*-([0-9a-fA-F-]{36})\.jsonl$/;
|
|
3615
|
+
});
|
|
3616
|
+
|
|
3473
3617
|
// src/transport/agent-session-list.ts
|
|
3474
3618
|
function isUnknownFilterCwdOption(output) {
|
|
3475
3619
|
return /(?:unknown|unrecognized) option/i.test(output) && output.includes("--filter-cwd");
|
|
@@ -3487,7 +3631,11 @@ async function runAgentSessionList(options) {
|
|
|
3487
3631
|
}
|
|
3488
3632
|
throw new Error(options.formatError(result));
|
|
3489
3633
|
}
|
|
3490
|
-
|
|
3634
|
+
const parsed = parseAgentSessionListOutput(result.stdout, filterLocally ? options.filterCwd : undefined);
|
|
3635
|
+
if (parsed && options.isSubagentSession) {
|
|
3636
|
+
return filterSubagentSessions(parsed, options.isSubagentSession);
|
|
3637
|
+
}
|
|
3638
|
+
return parsed;
|
|
3491
3639
|
}
|
|
3492
3640
|
function parseAgentSessionListOutput(stdout, filterCwd) {
|
|
3493
3641
|
let parsed;
|
|
@@ -3522,16 +3670,17 @@ function filterAgentSessionListByCwd(result, cwd) {
|
|
|
3522
3670
|
}
|
|
3523
3671
|
var init_agent_session_list = __esm(() => {
|
|
3524
3672
|
init_path();
|
|
3673
|
+
init_codex_subagent_filter();
|
|
3525
3674
|
});
|
|
3526
3675
|
|
|
3527
3676
|
// src/transport/acpx-session-files.ts
|
|
3528
3677
|
import { readdir, unlink as unlink2 } from "node:fs/promises";
|
|
3529
|
-
import { homedir as
|
|
3530
|
-
import { join as
|
|
3678
|
+
import { homedir as homedir5 } from "node:os";
|
|
3679
|
+
import { join as join4 } from "node:path";
|
|
3531
3680
|
async function deleteAcpxSessionFiles(options) {
|
|
3532
|
-
const dir = options.sessionsDir ??
|
|
3681
|
+
const dir = options.sessionsDir ?? join4(homedir5(), ".acpx", "sessions");
|
|
3533
3682
|
const safeId = encodeURIComponent(options.acpxRecordId);
|
|
3534
|
-
await unlink2(
|
|
3683
|
+
await unlink2(join4(dir, `${safeId}.json`)).catch(() => {
|
|
3535
3684
|
return;
|
|
3536
3685
|
});
|
|
3537
3686
|
let entries;
|
|
@@ -3542,7 +3691,7 @@ async function deleteAcpxSessionFiles(options) {
|
|
|
3542
3691
|
}
|
|
3543
3692
|
const streamFiles = entries.filter((name) => name.startsWith(`${safeId}.stream.`));
|
|
3544
3693
|
for (const name of streamFiles) {
|
|
3545
|
-
await unlink2(
|
|
3694
|
+
await unlink2(join4(dir, name)).catch(() => {
|
|
3546
3695
|
return;
|
|
3547
3696
|
});
|
|
3548
3697
|
}
|
|
@@ -3622,8 +3771,8 @@ init_prompt_output();
|
|
|
3622
3771
|
init_prompt_media();
|
|
3623
3772
|
init_streaming_prompt();
|
|
3624
3773
|
import { copyFile, readdir as readdir2 } from "node:fs/promises";
|
|
3625
|
-
import { homedir as
|
|
3626
|
-
import { dirname as dirname2, join as
|
|
3774
|
+
import { homedir as homedir6 } from "node:os";
|
|
3775
|
+
import { dirname as dirname2, join as join5, win32 } from "node:path";
|
|
3627
3776
|
import { spawn as spawn4 } from "node:child_process";
|
|
3628
3777
|
|
|
3629
3778
|
// src/bridge/parse-missing-optional-dep.ts
|
|
@@ -3643,6 +3792,7 @@ function parseMissingOptionalDep(text) {
|
|
|
3643
3792
|
init_discover_parent_package_paths();
|
|
3644
3793
|
init_acpx_queue_owner_launcher();
|
|
3645
3794
|
init_agent_session_list();
|
|
3795
|
+
init_codex_subagent_filter();
|
|
3646
3796
|
init_acpx_session_files();
|
|
3647
3797
|
class EnsureSessionFailedError extends Error {
|
|
3648
3798
|
kind;
|
|
@@ -3708,7 +3858,8 @@ class BridgeRuntime {
|
|
|
3708
3858
|
], { format: "json" }));
|
|
3709
3859
|
return await this.run(spec.command, spec.args);
|
|
3710
3860
|
},
|
|
3711
|
-
formatError: (result) => result.stderr || result.stdout || `sessions list failed with exit code ${result.code}
|
|
3861
|
+
formatError: (result) => result.stderr || result.stdout || `sessions list failed with exit code ${result.code}`,
|
|
3862
|
+
isSubagentSession: (input.driver ?? input.agent) === CODEX_AGENT_NAME ? codexSubagentPredicate() : undefined
|
|
3712
3863
|
});
|
|
3713
3864
|
}
|
|
3714
3865
|
async resumeAgentSession(input) {
|
|
@@ -3769,6 +3920,21 @@ class BridgeRuntime {
|
|
|
3769
3920
|
throw new Error(message);
|
|
3770
3921
|
}
|
|
3771
3922
|
async ensureSession(input, onProgress) {
|
|
3923
|
+
try {
|
|
3924
|
+
return await this.attemptEnsureSession(input, onProgress);
|
|
3925
|
+
} catch (error) {
|
|
3926
|
+
const requestedModel = input.model?.trim();
|
|
3927
|
+
if (requestedModel && error instanceof EnsureSessionFailedError && isModelNotAdvertisedError(error.message)) {
|
|
3928
|
+
onProgress?.({
|
|
3929
|
+
kind: "note",
|
|
3930
|
+
text: `agent did not advertise model "${requestedModel}"; retrying with the agent's default model`
|
|
3931
|
+
});
|
|
3932
|
+
return await this.attemptEnsureSession({ ...input, model: undefined }, onProgress);
|
|
3933
|
+
}
|
|
3934
|
+
throw error;
|
|
3935
|
+
}
|
|
3936
|
+
}
|
|
3937
|
+
async attemptEnsureSession(input, onProgress) {
|
|
3772
3938
|
onProgress?.("spawn");
|
|
3773
3939
|
const timeoutMs = this.sessionInitTimeoutMs();
|
|
3774
3940
|
const now = this.options.now ?? Date.now;
|
|
@@ -4218,11 +4384,11 @@ async function tryRepairAcpxSessionIndex(deps = {}) {
|
|
|
4218
4384
|
if (platform !== "win32") {
|
|
4219
4385
|
return false;
|
|
4220
4386
|
}
|
|
4221
|
-
const home = deps.home ?? process.env.HOME ?? process.env.USERPROFILE ??
|
|
4387
|
+
const home = deps.home ?? process.env.HOME ?? process.env.USERPROFILE ?? homedir6();
|
|
4222
4388
|
if (!home) {
|
|
4223
4389
|
return false;
|
|
4224
4390
|
}
|
|
4225
|
-
const pathJoin = platform === "win32" ? win32.join :
|
|
4391
|
+
const pathJoin = platform === "win32" ? win32.join : join5;
|
|
4226
4392
|
const sessionsDir = pathJoin(home, ".acpx", "sessions");
|
|
4227
4393
|
const indexPath = pathJoin(sessionsDir, "index.json");
|
|
4228
4394
|
const readdirFn = deps.readdirFn ?? readdir2;
|
|
@@ -4372,6 +4538,7 @@ class BridgeServer {
|
|
|
4372
4538
|
return await this.runtime.listAgentSessions({
|
|
4373
4539
|
agent: requireString(params, "agent"),
|
|
4374
4540
|
agentCommand: asOptionalString(params.agentCommand),
|
|
4541
|
+
driver: asOptionalString(params.driver),
|
|
4375
4542
|
cwd: requireString(params, "cwd"),
|
|
4376
4543
|
cursor: asOptionalString(params.cursor),
|
|
4377
4544
|
filterCwd: asOptionalString(params.filterCwd)
|
package/dist/cli.js
CHANGED
|
@@ -23806,6 +23806,15 @@ var init_session_shortcut_handler = __esm(() => {
|
|
|
23806
23806
|
});
|
|
23807
23807
|
|
|
23808
23808
|
// src/commands/handlers/native-session-handler.ts
|
|
23809
|
+
async function listFirstNonEmptyPage(listAgentSessions, query) {
|
|
23810
|
+
let result = await listAgentSessions(query);
|
|
23811
|
+
let guard = 0;
|
|
23812
|
+
while (result && result.sessions.length === 0 && result.nextCursor && guard < MAX_EMPTY_PAGE_ADVANCE) {
|
|
23813
|
+
guard++;
|
|
23814
|
+
result = await listAgentSessions({ ...query, cursor: result.nextCursor });
|
|
23815
|
+
}
|
|
23816
|
+
return result;
|
|
23817
|
+
}
|
|
23809
23818
|
async function handleNativeSessionList(context, chatKey, input) {
|
|
23810
23819
|
const target = await resolveNativeTarget(context, chatKey, input);
|
|
23811
23820
|
if (isRouterResponse(target)) {
|
|
@@ -23818,13 +23827,14 @@ async function handleNativeSessionList(context, chatKey, input) {
|
|
|
23818
23827
|
const query = {
|
|
23819
23828
|
agent: target.agent,
|
|
23820
23829
|
agentCommand: target.agentCommand,
|
|
23830
|
+
...target.driver ? { driver: target.driver } : {},
|
|
23821
23831
|
cwd: target.cwd,
|
|
23822
23832
|
...input.cursor ? { cursor: input.cursor } : {},
|
|
23823
23833
|
...input.all ? {} : { filterCwd: target.cwd }
|
|
23824
23834
|
};
|
|
23825
23835
|
let result;
|
|
23826
23836
|
try {
|
|
23827
|
-
result = await listAgentSessions
|
|
23837
|
+
result = await listFirstNonEmptyPage(listAgentSessions, query);
|
|
23828
23838
|
} catch (error2) {
|
|
23829
23839
|
return { text: renderNativeListError(target, error2) };
|
|
23830
23840
|
}
|
|
@@ -23950,6 +23960,7 @@ async function resolveNativeTarget(context, chatKey, input) {
|
|
|
23950
23960
|
agent: agent3,
|
|
23951
23961
|
agentDisplayName: displayAgentName(agent3),
|
|
23952
23962
|
agentCommand: resolveRuntimeAgentCommand(agentConfig.driver, agentConfig.command, context.config?.transport.preferLocalAgents !== false),
|
|
23963
|
+
driver: agentConfig.driver,
|
|
23953
23964
|
workspace: workspaceResolution.workspace,
|
|
23954
23965
|
workspaceLabel: workspaceResolution.workspaceLabel,
|
|
23955
23966
|
cwd: workspaceResolution.cwd,
|
|
@@ -24185,7 +24196,7 @@ function displayAgentName(agent3) {
|
|
|
24185
24196
|
}
|
|
24186
24197
|
return agent3.charAt(0).toUpperCase() + agent3.slice(1);
|
|
24187
24198
|
}
|
|
24188
|
-
var NATIVE_SESSION_CACHE_TTL_MS;
|
|
24199
|
+
var NATIVE_SESSION_CACHE_TTL_MS, MAX_EMPTY_PAGE_ADVANCE = 25;
|
|
24189
24200
|
var init_native_session_handler = __esm(() => {
|
|
24190
24201
|
init_resolve_agent_command();
|
|
24191
24202
|
init_channel_scope();
|
|
@@ -25054,6 +25065,7 @@ class CommandRouter {
|
|
|
25054
25065
|
const result = await listAgentSessions({
|
|
25055
25066
|
agent: agent3,
|
|
25056
25067
|
...agentCommand ? { agentCommand } : {},
|
|
25068
|
+
...agentConfig.driver ? { driver: agentConfig.driver } : {},
|
|
25057
25069
|
cwd: workspaceConfig.cwd,
|
|
25058
25070
|
filterCwd: workspaceConfig.cwd
|
|
25059
25071
|
});
|
|
@@ -31575,6 +31587,13 @@ var init_acpx_bridge_transport = __esm(() => {
|
|
|
31575
31587
|
init_quota_gated_reply_sink();
|
|
31576
31588
|
});
|
|
31577
31589
|
|
|
31590
|
+
// src/transport/model-not-advertised.ts
|
|
31591
|
+
function isModelNotAdvertisedError(text) {
|
|
31592
|
+
if (!text)
|
|
31593
|
+
return false;
|
|
31594
|
+
return /Cannot (?:apply --model|replay saved model)\b/i.test(text) || /did not advertise (?:that model|model support)/i.test(text);
|
|
31595
|
+
}
|
|
31596
|
+
|
|
31578
31597
|
// src/transport/prompt-media.ts
|
|
31579
31598
|
import { mkdtemp, open as open4, rm as rm9, writeFile as writeFile7 } from "node:fs/promises";
|
|
31580
31599
|
import { tmpdir as defaultTmpdir } from "node:os";
|
|
@@ -32150,6 +32169,143 @@ function permissionModeToFlag(permissionMode) {
|
|
|
32150
32169
|
}
|
|
32151
32170
|
}
|
|
32152
32171
|
|
|
32172
|
+
// src/transport/codex-subagent-filter.ts
|
|
32173
|
+
import { closeSync, openSync, readdirSync, readSync, statSync as statSync2 } from "node:fs";
|
|
32174
|
+
import { homedir as homedir9 } from "node:os";
|
|
32175
|
+
import { join as join19 } from "node:path";
|
|
32176
|
+
function resolveCodexHome(env = process.env) {
|
|
32177
|
+
const fromEnv = env.CODEX_HOME?.trim();
|
|
32178
|
+
return fromEnv ? fromEnv : join19(homedir9(), ".codex");
|
|
32179
|
+
}
|
|
32180
|
+
function isPlainObject3(value) {
|
|
32181
|
+
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
32182
|
+
}
|
|
32183
|
+
function isSubagentSource(source) {
|
|
32184
|
+
if (!isPlainObject3(source) || !Object.hasOwn(source, "subagent"))
|
|
32185
|
+
return false;
|
|
32186
|
+
const subagent = source.subagent;
|
|
32187
|
+
if (!isPlainObject3(subagent))
|
|
32188
|
+
return false;
|
|
32189
|
+
return Object.values(subagent).some((variant) => isPlainObject3(variant) && typeof variant.parent_thread_id === "string");
|
|
32190
|
+
}
|
|
32191
|
+
function sessionMetaLineIsSubagent(line) {
|
|
32192
|
+
if (!line)
|
|
32193
|
+
return false;
|
|
32194
|
+
let parsed;
|
|
32195
|
+
try {
|
|
32196
|
+
parsed = JSON.parse(line);
|
|
32197
|
+
} catch {
|
|
32198
|
+
return false;
|
|
32199
|
+
}
|
|
32200
|
+
const payload = parsed?.payload;
|
|
32201
|
+
return isSubagentSource(payload?.source);
|
|
32202
|
+
}
|
|
32203
|
+
function createSubagentPredicate(reader) {
|
|
32204
|
+
let index = null;
|
|
32205
|
+
const cache = new Map;
|
|
32206
|
+
return (sessionId) => {
|
|
32207
|
+
const cached2 = cache.get(sessionId);
|
|
32208
|
+
if (cached2 !== undefined)
|
|
32209
|
+
return cached2;
|
|
32210
|
+
let result = false;
|
|
32211
|
+
try {
|
|
32212
|
+
if (!index) {
|
|
32213
|
+
index = new Map;
|
|
32214
|
+
for (const path16 of reader.listRolloutPaths()) {
|
|
32215
|
+
const id = path16.match(ROLLOUT_RE)?.[1];
|
|
32216
|
+
if (id)
|
|
32217
|
+
index.set(id.toLowerCase(), path16);
|
|
32218
|
+
}
|
|
32219
|
+
}
|
|
32220
|
+
const path15 = index.get(sessionId.toLowerCase());
|
|
32221
|
+
if (path15)
|
|
32222
|
+
result = sessionMetaLineIsSubagent(reader.readFirstLine(path15));
|
|
32223
|
+
} catch {
|
|
32224
|
+
result = false;
|
|
32225
|
+
}
|
|
32226
|
+
cache.set(sessionId, result);
|
|
32227
|
+
return result;
|
|
32228
|
+
};
|
|
32229
|
+
}
|
|
32230
|
+
function filterSubagentSessions(result, isSubagent) {
|
|
32231
|
+
return {
|
|
32232
|
+
...result,
|
|
32233
|
+
sessions: result.sessions.filter((session3) => {
|
|
32234
|
+
try {
|
|
32235
|
+
return !isSubagent(session3.sessionId);
|
|
32236
|
+
} catch {
|
|
32237
|
+
return true;
|
|
32238
|
+
}
|
|
32239
|
+
})
|
|
32240
|
+
};
|
|
32241
|
+
}
|
|
32242
|
+
function nodeRolloutReader(home) {
|
|
32243
|
+
const root = join19(home, "sessions");
|
|
32244
|
+
return {
|
|
32245
|
+
listRolloutPaths() {
|
|
32246
|
+
const out = [];
|
|
32247
|
+
const walk = (dir) => {
|
|
32248
|
+
let entries;
|
|
32249
|
+
try {
|
|
32250
|
+
entries = readdirSync(dir, { withFileTypes: true });
|
|
32251
|
+
} catch {
|
|
32252
|
+
return;
|
|
32253
|
+
}
|
|
32254
|
+
for (const entry of entries) {
|
|
32255
|
+
const full = join19(dir, entry.name);
|
|
32256
|
+
if (entry.isDirectory())
|
|
32257
|
+
walk(full);
|
|
32258
|
+
else if (entry.isFile() && entry.name.startsWith("rollout-") && entry.name.endsWith(".jsonl"))
|
|
32259
|
+
out.push(full);
|
|
32260
|
+
}
|
|
32261
|
+
};
|
|
32262
|
+
walk(root);
|
|
32263
|
+
return out;
|
|
32264
|
+
},
|
|
32265
|
+
readFirstLine(path15) {
|
|
32266
|
+
let fd;
|
|
32267
|
+
try {
|
|
32268
|
+
statSync2(path15);
|
|
32269
|
+
fd = openSync(path15, "r");
|
|
32270
|
+
const buf = Buffer.alloc(READ_CHUNK);
|
|
32271
|
+
let acc = "";
|
|
32272
|
+
let total = 0;
|
|
32273
|
+
for (;; ) {
|
|
32274
|
+
const bytes = readSync(fd, buf, 0, READ_CHUNK, total);
|
|
32275
|
+
if (bytes <= 0)
|
|
32276
|
+
break;
|
|
32277
|
+
acc += buf.toString("utf8", 0, bytes);
|
|
32278
|
+
total += bytes;
|
|
32279
|
+
const nl = acc.indexOf(`
|
|
32280
|
+
`);
|
|
32281
|
+
if (nl !== -1)
|
|
32282
|
+
return acc.slice(0, nl);
|
|
32283
|
+
if (total >= FIRST_LINE_READ_CAP)
|
|
32284
|
+
return;
|
|
32285
|
+
}
|
|
32286
|
+
return acc.length ? acc : undefined;
|
|
32287
|
+
} catch {
|
|
32288
|
+
return;
|
|
32289
|
+
} finally {
|
|
32290
|
+
if (fd !== undefined) {
|
|
32291
|
+
try {
|
|
32292
|
+
closeSync(fd);
|
|
32293
|
+
} catch {}
|
|
32294
|
+
}
|
|
32295
|
+
}
|
|
32296
|
+
}
|
|
32297
|
+
};
|
|
32298
|
+
}
|
|
32299
|
+
function codexSubagentPredicate(env) {
|
|
32300
|
+
return createSubagentPredicate(nodeRolloutReader(resolveCodexHome(env)));
|
|
32301
|
+
}
|
|
32302
|
+
var CODEX_AGENT_NAME = "codex", FIRST_LINE_READ_CAP, READ_CHUNK, ROLLOUT_RE;
|
|
32303
|
+
var init_codex_subagent_filter = __esm(() => {
|
|
32304
|
+
FIRST_LINE_READ_CAP = 1024 * 1024;
|
|
32305
|
+
READ_CHUNK = 64 * 1024;
|
|
32306
|
+
ROLLOUT_RE = /rollout-.*-([0-9a-fA-F-]{36})\.jsonl$/;
|
|
32307
|
+
});
|
|
32308
|
+
|
|
32153
32309
|
// src/transport/agent-session-list.ts
|
|
32154
32310
|
function isUnknownFilterCwdOption(output) {
|
|
32155
32311
|
return /(?:unknown|unrecognized) option/i.test(output) && output.includes("--filter-cwd");
|
|
@@ -32167,7 +32323,11 @@ async function runAgentSessionList(options) {
|
|
|
32167
32323
|
}
|
|
32168
32324
|
throw new Error(options.formatError(result));
|
|
32169
32325
|
}
|
|
32170
|
-
|
|
32326
|
+
const parsed = parseAgentSessionListOutput(result.stdout, filterLocally ? options.filterCwd : undefined);
|
|
32327
|
+
if (parsed && options.isSubagentSession) {
|
|
32328
|
+
return filterSubagentSessions(parsed, options.isSubagentSession);
|
|
32329
|
+
}
|
|
32330
|
+
return parsed;
|
|
32171
32331
|
}
|
|
32172
32332
|
function parseAgentSessionListOutput(stdout2, filterCwd) {
|
|
32173
32333
|
let parsed;
|
|
@@ -32202,16 +32362,17 @@ function filterAgentSessionListByCwd(result, cwd) {
|
|
|
32202
32362
|
}
|
|
32203
32363
|
var init_agent_session_list = __esm(() => {
|
|
32204
32364
|
init_path();
|
|
32365
|
+
init_codex_subagent_filter();
|
|
32205
32366
|
});
|
|
32206
32367
|
|
|
32207
32368
|
// src/transport/acpx-session-files.ts
|
|
32208
32369
|
import { readdir as readdir3, unlink as unlink2 } from "node:fs/promises";
|
|
32209
|
-
import { homedir as
|
|
32210
|
-
import { join as
|
|
32370
|
+
import { homedir as homedir10 } from "node:os";
|
|
32371
|
+
import { join as join20 } from "node:path";
|
|
32211
32372
|
async function deleteAcpxSessionFiles(options) {
|
|
32212
|
-
const dir = options.sessionsDir ??
|
|
32373
|
+
const dir = options.sessionsDir ?? join20(homedir10(), ".acpx", "sessions");
|
|
32213
32374
|
const safeId = encodeURIComponent(options.acpxRecordId);
|
|
32214
|
-
await unlink2(
|
|
32375
|
+
await unlink2(join20(dir, `${safeId}.json`)).catch(() => {
|
|
32215
32376
|
return;
|
|
32216
32377
|
});
|
|
32217
32378
|
let entries;
|
|
@@ -32222,7 +32383,7 @@ async function deleteAcpxSessionFiles(options) {
|
|
|
32222
32383
|
}
|
|
32223
32384
|
const streamFiles = entries.filter((name) => name.startsWith(`${safeId}.stream.`));
|
|
32224
32385
|
for (const name of streamFiles) {
|
|
32225
|
-
await unlink2(
|
|
32386
|
+
await unlink2(join20(dir, name)).catch(() => {
|
|
32226
32387
|
return;
|
|
32227
32388
|
});
|
|
32228
32389
|
}
|
|
@@ -32327,6 +32488,18 @@ class AcpxCliTransport {
|
|
|
32327
32488
|
this.streamingHooks = streamingHooks;
|
|
32328
32489
|
}
|
|
32329
32490
|
async ensureSession(session3, _onProgress) {
|
|
32491
|
+
try {
|
|
32492
|
+
await this.runEnsureSession(session3);
|
|
32493
|
+
} catch (error2) {
|
|
32494
|
+
const requestedModel = session3.model?.trim();
|
|
32495
|
+
if (requestedModel && isModelNotAdvertisedError(error2 instanceof Error ? error2.message : null)) {
|
|
32496
|
+
await this.runEnsureSession({ ...session3, model: undefined });
|
|
32497
|
+
return;
|
|
32498
|
+
}
|
|
32499
|
+
throw error2;
|
|
32500
|
+
}
|
|
32501
|
+
}
|
|
32502
|
+
async runEnsureSession(session3) {
|
|
32330
32503
|
const args = this.buildArgs(session3, [
|
|
32331
32504
|
"sessions",
|
|
32332
32505
|
"new",
|
|
@@ -32352,7 +32525,8 @@ class AcpxCliTransport {
|
|
|
32352
32525
|
timeoutMs: this.sessionInitTimeoutMs
|
|
32353
32526
|
});
|
|
32354
32527
|
},
|
|
32355
|
-
formatError: (result) => normalizeCommandError(result) ?? `command failed with exit code ${result.code}
|
|
32528
|
+
formatError: (result) => normalizeCommandError(result) ?? `command failed with exit code ${result.code}`,
|
|
32529
|
+
isSubagentSession: (query.driver ?? query.agent) === CODEX_AGENT_NAME ? codexSubagentPredicate() : undefined
|
|
32356
32530
|
});
|
|
32357
32531
|
}
|
|
32358
32532
|
async tailSessionHistory(session3, lines) {
|
|
@@ -32812,6 +32986,7 @@ var init_acpx_cli_transport = __esm(() => {
|
|
|
32812
32986
|
init_terminate_process_tree();
|
|
32813
32987
|
init_acpx_queue_owner_launcher();
|
|
32814
32988
|
init_agent_session_list();
|
|
32989
|
+
init_codex_subagent_filter();
|
|
32815
32990
|
init_acpx_session_files();
|
|
32816
32991
|
require4 = createRequire5(import.meta.url);
|
|
32817
32992
|
});
|
|
@@ -33284,8 +33459,8 @@ function createControlEventBus(logger2) {
|
|
|
33284
33459
|
|
|
33285
33460
|
// src/transport/native-session-history.ts
|
|
33286
33461
|
import { readFile as readFile14 } from "node:fs/promises";
|
|
33287
|
-
import { homedir as
|
|
33288
|
-
import { join as
|
|
33462
|
+
import { homedir as homedir11 } from "node:os";
|
|
33463
|
+
import { join as join21 } from "node:path";
|
|
33289
33464
|
function classifyToolKind(name) {
|
|
33290
33465
|
const n = name.toLowerCase();
|
|
33291
33466
|
if (/(^|[^a-z])(read|cat|view|open)([^a-z]|$)/.test(n))
|
|
@@ -33397,8 +33572,8 @@ function mapAcpxMessagesToHistory(raw) {
|
|
|
33397
33572
|
}
|
|
33398
33573
|
async function readNativeSessionHistory(opts) {
|
|
33399
33574
|
try {
|
|
33400
|
-
const dir = opts.sessionsDir ??
|
|
33401
|
-
const indexRaw = await readFile14(
|
|
33575
|
+
const dir = opts.sessionsDir ?? join21(opts.homeDir ?? homedir11(), ".acpx", "sessions");
|
|
33576
|
+
const indexRaw = await readFile14(join21(dir, "index.json"), "utf8").catch(() => null);
|
|
33402
33577
|
if (!indexRaw)
|
|
33403
33578
|
return [];
|
|
33404
33579
|
const index = JSON.parse(indexRaw);
|
|
@@ -33407,7 +33582,7 @@ async function readNativeSessionHistory(opts) {
|
|
|
33407
33582
|
for (const entry of candidates) {
|
|
33408
33583
|
if (!entry.file)
|
|
33409
33584
|
continue;
|
|
33410
|
-
const recRaw = await readFile14(
|
|
33585
|
+
const recRaw = await readFile14(join21(dir, entry.file), "utf8").catch(() => null);
|
|
33411
33586
|
if (!recRaw)
|
|
33412
33587
|
continue;
|
|
33413
33588
|
const record3 = JSON.parse(recRaw);
|
|
@@ -33425,14 +33600,14 @@ var init_native_session_history = () => {};
|
|
|
33425
33600
|
// src/control/workspace-fs.ts
|
|
33426
33601
|
import { execFile } from "node:child_process";
|
|
33427
33602
|
import { promisify } from "node:util";
|
|
33428
|
-
import { homedir as
|
|
33603
|
+
import { homedir as homedir12 } from "node:os";
|
|
33429
33604
|
import { readdir as readdir4, realpath, stat as stat3, open as open5 } from "node:fs/promises";
|
|
33430
33605
|
import { isAbsolute as isAbsolute3, relative, resolve as resolve3, sep } from "node:path";
|
|
33431
33606
|
function expandHome2(p) {
|
|
33432
33607
|
if (p === "~")
|
|
33433
|
-
return
|
|
33608
|
+
return homedir12();
|
|
33434
33609
|
if (p.startsWith("~/") || p.startsWith("~" + sep))
|
|
33435
|
-
return resolve3(
|
|
33610
|
+
return resolve3(homedir12(), p.slice(2));
|
|
33436
33611
|
return p;
|
|
33437
33612
|
}
|
|
33438
33613
|
|
|
@@ -33561,16 +33736,16 @@ class WorkspaceFs {
|
|
|
33561
33736
|
}
|
|
33562
33737
|
const files = [];
|
|
33563
33738
|
try {
|
|
33564
|
-
const { stdout: stdout2 } = await execFileAsync("git", ["-C", root, "status", "--porcelain"], { maxBuffer: GIT_MAX_BUFFER });
|
|
33565
|
-
|
|
33566
|
-
|
|
33567
|
-
|
|
33739
|
+
const { stdout: stdout2 } = await execFileAsync("git", ["-C", root, "-c", "core.quotePath=false", "status", "--porcelain", "-z"], { maxBuffer: GIT_MAX_BUFFER });
|
|
33740
|
+
const fields = stdout2.split("\x00");
|
|
33741
|
+
for (let i = 0;i < fields.length; i++) {
|
|
33742
|
+
const field = fields[i];
|
|
33743
|
+
if (!field)
|
|
33568
33744
|
continue;
|
|
33569
|
-
const status =
|
|
33570
|
-
|
|
33571
|
-
|
|
33572
|
-
|
|
33573
|
-
path15 = path15.slice(arrow + 4);
|
|
33745
|
+
const status = field.slice(0, 2);
|
|
33746
|
+
const path15 = field.slice(3);
|
|
33747
|
+
if (status[0] === "R" || status[0] === "C")
|
|
33748
|
+
i++;
|
|
33574
33749
|
files.push({ path: path15, status });
|
|
33575
33750
|
}
|
|
33576
33751
|
} catch {}
|
|
@@ -33585,6 +33760,15 @@ class WorkspaceFs {
|
|
|
33585
33760
|
diff = "";
|
|
33586
33761
|
}
|
|
33587
33762
|
}
|
|
33763
|
+
if (rel && !diff) {
|
|
33764
|
+
try {
|
|
33765
|
+
diff = (await execFileAsync("git", ["-C", root, "-c", "core.quotePath=false", "diff", "--no-index", "--", "/dev/null", rel], { maxBuffer: GIT_MAX_BUFFER })).stdout;
|
|
33766
|
+
} catch (e) {
|
|
33767
|
+
const out = e.stdout;
|
|
33768
|
+
if (typeof out === "string")
|
|
33769
|
+
diff = out;
|
|
33770
|
+
}
|
|
33771
|
+
}
|
|
33588
33772
|
const truncated = diff.length > DIFF_CAP;
|
|
33589
33773
|
return { workspace: workspace3, files, diff: truncated ? diff.slice(0, DIFF_CAP) : diff, truncated, ...await this.gitContext(root) };
|
|
33590
33774
|
}
|
|
@@ -33676,7 +33860,8 @@ class ControlService {
|
|
|
33676
33860
|
workspace: session3.workspace,
|
|
33677
33861
|
transportSession: session3.transportSession,
|
|
33678
33862
|
running: this.deps.activeTurns.isActiveAnywhere(session3.alias),
|
|
33679
|
-
archived: session3.archived === true
|
|
33863
|
+
archived: session3.archived === true,
|
|
33864
|
+
...session3.agentCommand ? { agentCommand: session3.agentCommand } : {}
|
|
33680
33865
|
}));
|
|
33681
33866
|
}
|
|
33682
33867
|
async listNativeSessions(_chatKey, agent3, workspace3) {
|
|
@@ -34036,10 +34221,10 @@ var init_control_service = __esm(() => {
|
|
|
34036
34221
|
|
|
34037
34222
|
// src/control/upload-store.ts
|
|
34038
34223
|
import { mkdtemp as mkdtemp2, readdir as readdir5, rm as rm10, stat as stat4, writeFile as writeFile8 } from "node:fs/promises";
|
|
34039
|
-
import { homedir as
|
|
34224
|
+
import { homedir as homedir13 } from "node:os";
|
|
34040
34225
|
import path16 from "node:path";
|
|
34041
34226
|
function defaultRootDir() {
|
|
34042
|
-
const home = process.env.HOME ??
|
|
34227
|
+
const home = process.env.HOME ?? homedir13();
|
|
34043
34228
|
return path16.join(coreHomeDir(home), "runtime", "uploads");
|
|
34044
34229
|
}
|
|
34045
34230
|
function sanitizeUploadFilename(raw) {
|
|
@@ -34115,7 +34300,7 @@ var init_upload_store = __esm(() => {
|
|
|
34115
34300
|
|
|
34116
34301
|
// src/config/agent-catalog.ts
|
|
34117
34302
|
import { existsSync as existsSync3 } from "node:fs";
|
|
34118
|
-
import { delimiter as delimiter2, join as
|
|
34303
|
+
import { delimiter as delimiter2, join as join22 } from "node:path";
|
|
34119
34304
|
function isBinaryOnPath(binary) {
|
|
34120
34305
|
const path17 = process.env.PATH ?? "";
|
|
34121
34306
|
const exts = process.platform === "win32" ? ["", ".exe", ".cmd", ".bat"] : [""];
|
|
@@ -34124,7 +34309,7 @@ function isBinaryOnPath(binary) {
|
|
|
34124
34309
|
continue;
|
|
34125
34310
|
for (const ext of exts) {
|
|
34126
34311
|
try {
|
|
34127
|
-
if (existsSync3(
|
|
34312
|
+
if (existsSync3(join22(dir, binary + ext)))
|
|
34128
34313
|
return true;
|
|
34129
34314
|
} catch {}
|
|
34130
34315
|
}
|
|
@@ -34215,8 +34400,8 @@ __export(exports_main, {
|
|
|
34215
34400
|
buildApp: () => buildApp
|
|
34216
34401
|
});
|
|
34217
34402
|
import { randomUUID as randomUUID3 } from "node:crypto";
|
|
34218
|
-
import { homedir as
|
|
34219
|
-
import { dirname as dirname13, join as
|
|
34403
|
+
import { homedir as homedir14 } from "node:os";
|
|
34404
|
+
import { dirname as dirname13, join as join23 } from "node:path";
|
|
34220
34405
|
import { fileURLToPath as fileURLToPath5 } from "node:url";
|
|
34221
34406
|
function startProgressHeartbeat(orchestration3, config4, logger2, channel) {
|
|
34222
34407
|
const thresholdSeconds = config4.orchestration.progressHeartbeatSeconds;
|
|
@@ -34907,8 +35092,8 @@ async function main() {
|
|
|
34907
35092
|
}
|
|
34908
35093
|
}
|
|
34909
35094
|
async function prepareChannelMedia(configPath, config4) {
|
|
34910
|
-
const runtimeDir =
|
|
34911
|
-
const mediaRootDir =
|
|
35095
|
+
const runtimeDir = join23(dirname13(configPath), "runtime");
|
|
35096
|
+
const mediaRootDir = join23(runtimeDir, "media");
|
|
34912
35097
|
const mediaStore = new RuntimeMediaStore({ rootDir: mediaRootDir });
|
|
34913
35098
|
await mediaStore.cleanupExpired().catch((error2) => {
|
|
34914
35099
|
console.error("[xacpx] media cleanup failed:", error2 instanceof Error ? error2.message : String(error2));
|
|
@@ -34917,16 +35102,16 @@ async function prepareChannelMedia(configPath, config4) {
|
|
|
34917
35102
|
return { mediaStore, channelDeps: { mediaStore, allowedMediaRoots } };
|
|
34918
35103
|
}
|
|
34919
35104
|
function resolveRuntimePaths() {
|
|
34920
|
-
const home = process.env.HOME ??
|
|
35105
|
+
const home = process.env.HOME ?? homedir14();
|
|
34921
35106
|
if (!home) {
|
|
34922
35107
|
throw new Error("Unable to resolve the current user home directory");
|
|
34923
35108
|
}
|
|
34924
|
-
const configPath = coreEnv("CONFIG") ??
|
|
34925
|
-
const runtimeDir =
|
|
35109
|
+
const configPath = coreEnv("CONFIG") ?? join23(coreHomeDir(home), "config.json");
|
|
35110
|
+
const runtimeDir = join23(dirname13(configPath), "runtime");
|
|
34926
35111
|
return {
|
|
34927
35112
|
configPath,
|
|
34928
|
-
statePath: coreEnv("STATE") ??
|
|
34929
|
-
perfLogPath:
|
|
35113
|
+
statePath: coreEnv("STATE") ?? join23(coreHomeDir(home), "state.json"),
|
|
35114
|
+
perfLogPath: join23(runtimeDir, "perf.log"),
|
|
34930
35115
|
orchestrationSocketPath: coreEnv("ORCHESTRATION_SOCKET") ?? resolveDaemonOrchestrationSocketPath(runtimeDir)
|
|
34931
35116
|
};
|
|
34932
35117
|
}
|
|
@@ -34938,13 +35123,13 @@ function resolveBridgeEntryPath() {
|
|
|
34938
35123
|
}
|
|
34939
35124
|
function resolveAppLogPath(configPath) {
|
|
34940
35125
|
const rootDir = dirname13(configPath);
|
|
34941
|
-
const runtimeDir =
|
|
34942
|
-
return
|
|
35126
|
+
const runtimeDir = join23(rootDir, "runtime");
|
|
35127
|
+
return join23(runtimeDir, "app.log");
|
|
34943
35128
|
}
|
|
34944
35129
|
function resolvePerfLogPath(configPath) {
|
|
34945
35130
|
const rootDir = dirname13(configPath);
|
|
34946
|
-
const runtimeDir =
|
|
34947
|
-
return
|
|
35131
|
+
const runtimeDir = join23(rootDir, "runtime");
|
|
35132
|
+
return join23(runtimeDir, "perf.log");
|
|
34948
35133
|
}
|
|
34949
35134
|
function resolveOrchestrationSocketPathFromConfigPath(configPath) {
|
|
34950
35135
|
const runtimeDir = resolveRuntimeDirFromConfigPath(configPath);
|
|
@@ -35186,10 +35371,10 @@ var init_config_check = __esm(async () => {
|
|
|
35186
35371
|
// src/doctor/checks/daemon-check.ts
|
|
35187
35372
|
import { readdir as readdir6, readFile as readFile15, rm as rm11 } from "node:fs/promises";
|
|
35188
35373
|
import { fileURLToPath as fileURLToPath6 } from "node:url";
|
|
35189
|
-
import { homedir as
|
|
35190
|
-
import { join as
|
|
35374
|
+
import { homedir as homedir15 } from "node:os";
|
|
35375
|
+
import { join as join24 } from "node:path";
|
|
35191
35376
|
async function checkDaemon(options = {}) {
|
|
35192
|
-
const home = options.home ?? process.env.HOME ??
|
|
35377
|
+
const home = options.home ?? process.env.HOME ?? homedir15();
|
|
35193
35378
|
const runtimeDir = options.configPath ? resolveRuntimeDirFromConfigPath(options.configPath) : undefined;
|
|
35194
35379
|
const paths = (options.resolveDaemonPaths ?? resolveDaemonPaths)({
|
|
35195
35380
|
home,
|
|
@@ -35289,7 +35474,7 @@ async function detectStaleConsumerLockFix(runtimeDir, deps) {
|
|
|
35289
35474
|
if (!fileName.endsWith(CONSUMER_LOCK_SUFFIX)) {
|
|
35290
35475
|
continue;
|
|
35291
35476
|
}
|
|
35292
|
-
const lockPath =
|
|
35477
|
+
const lockPath = join24(runtimeDir, fileName);
|
|
35293
35478
|
const lock2 = await deps.readConsumerLock(lockPath);
|
|
35294
35479
|
if (lock2 && !deps.isProcessRunning(lock2.pid)) {
|
|
35295
35480
|
stalePaths.push(lockPath);
|
|
@@ -35354,10 +35539,10 @@ var init_daemon_check = __esm(() => {
|
|
|
35354
35539
|
|
|
35355
35540
|
// src/doctor/checks/logs-check.ts
|
|
35356
35541
|
import { stat as stat5, readdir as readdir7 } from "node:fs/promises";
|
|
35357
|
-
import { basename as basename4, join as
|
|
35358
|
-
import { homedir as
|
|
35542
|
+
import { basename as basename4, join as join25 } from "node:path";
|
|
35543
|
+
import { homedir as homedir16 } from "node:os";
|
|
35359
35544
|
async function checkLogs(options = {}) {
|
|
35360
|
-
const home = options.home ?? process.env.HOME ??
|
|
35545
|
+
const home = options.home ?? process.env.HOME ?? homedir16();
|
|
35361
35546
|
const runtimeDir = options.configPath ? resolveRuntimeDirFromConfigPath(options.configPath) : undefined;
|
|
35362
35547
|
const paths = (options.resolveDaemonPaths ?? resolveDaemonPaths)({
|
|
35363
35548
|
home,
|
|
@@ -35389,7 +35574,7 @@ async function checkLogs(options = {}) {
|
|
|
35389
35574
|
const matched = entries.filter((entry) => isTrackedLogName(entry, tracked));
|
|
35390
35575
|
const files = [];
|
|
35391
35576
|
for (const name of matched) {
|
|
35392
|
-
const path17 =
|
|
35577
|
+
const path17 = join25(paths.runtimeDir, name);
|
|
35393
35578
|
try {
|
|
35394
35579
|
const fileStat = await probe.stat(path17);
|
|
35395
35580
|
if (fileStat.isDirectory()) {
|
|
@@ -35539,9 +35724,9 @@ var init_orchestration_health = __esm(() => {
|
|
|
35539
35724
|
});
|
|
35540
35725
|
|
|
35541
35726
|
// src/doctor/checks/orchestration-socket-check.ts
|
|
35542
|
-
import { homedir as
|
|
35727
|
+
import { homedir as homedir17 } from "node:os";
|
|
35543
35728
|
async function checkOrchestrationSocket(options = {}) {
|
|
35544
|
-
const home = options.home ?? process.env.HOME ??
|
|
35729
|
+
const home = options.home ?? process.env.HOME ?? homedir17();
|
|
35545
35730
|
const runtimeDir = options.configPath ? resolveRuntimeDirFromConfigPath(options.configPath) : undefined;
|
|
35546
35731
|
const paths = (options.resolveDaemonPaths ?? resolveDaemonPaths)({
|
|
35547
35732
|
home,
|
|
@@ -35716,9 +35901,9 @@ var init_plugin_check = __esm(async () => {
|
|
|
35716
35901
|
import { constants } from "node:fs";
|
|
35717
35902
|
import { access as access4, stat as stat6 } from "node:fs/promises";
|
|
35718
35903
|
import { dirname as dirname14 } from "node:path";
|
|
35719
|
-
import { homedir as
|
|
35904
|
+
import { homedir as homedir18 } from "node:os";
|
|
35720
35905
|
async function checkRuntime(options = {}) {
|
|
35721
|
-
const home = options.home ?? process.env.HOME ??
|
|
35906
|
+
const home = options.home ?? process.env.HOME ?? homedir18();
|
|
35722
35907
|
const runtimeDir = options.configPath ? resolveRuntimeDirFromConfigPath(options.configPath) : undefined;
|
|
35723
35908
|
const paths = (options.resolveDaemonPaths ?? resolveDaemonPaths)({
|
|
35724
35909
|
home,
|
|
@@ -36351,10 +36536,10 @@ var init_render_doctor = __esm(() => {
|
|
|
36351
36536
|
});
|
|
36352
36537
|
|
|
36353
36538
|
// src/doctor/doctor.ts
|
|
36354
|
-
import { homedir as
|
|
36355
|
-
import { join as
|
|
36539
|
+
import { homedir as homedir19 } from "node:os";
|
|
36540
|
+
import { join as join26 } from "node:path";
|
|
36356
36541
|
async function runDoctor(options = {}, deps = {}) {
|
|
36357
|
-
const home = deps.home ?? process.env.HOME ??
|
|
36542
|
+
const home = deps.home ?? process.env.HOME ?? homedir19();
|
|
36358
36543
|
const runtimePaths = resolveDoctorRuntimePaths(home, deps.resolveRuntimePaths);
|
|
36359
36544
|
const sharedLoadConfig = createSharedLoadConfig(runtimePaths, deps.loadConfig ?? loadConfig);
|
|
36360
36545
|
const runners = [
|
|
@@ -36507,8 +36692,8 @@ function resolveDoctorRuntimePaths(home, resolver) {
|
|
|
36507
36692
|
return resolveRuntimePaths();
|
|
36508
36693
|
}
|
|
36509
36694
|
return {
|
|
36510
|
-
configPath:
|
|
36511
|
-
statePath:
|
|
36695
|
+
configPath: join26(coreHomeDir(home), "config.json"),
|
|
36696
|
+
statePath: join26(coreHomeDir(home), "state.json")
|
|
36512
36697
|
};
|
|
36513
36698
|
}
|
|
36514
36699
|
function depsUseExplicitRuntimeOverrides() {
|
|
@@ -36691,8 +36876,8 @@ var init_doctor2 = __esm(async () => {
|
|
|
36691
36876
|
// src/cli.ts
|
|
36692
36877
|
init_core_home();
|
|
36693
36878
|
import { randomUUID as randomUUID4 } from "node:crypto";
|
|
36694
|
-
import { homedir as
|
|
36695
|
-
import { dirname as dirname15, join as
|
|
36879
|
+
import { homedir as homedir20 } from "node:os";
|
|
36880
|
+
import { dirname as dirname15, join as join27, sep as sep2 } from "node:path";
|
|
36696
36881
|
import { fileURLToPath as fileURLToPath7 } from "node:url";
|
|
36697
36882
|
|
|
36698
36883
|
// src/runtime/migrate-core-home.ts
|
|
@@ -52946,7 +53131,7 @@ async function createCliScheduledTaskService() {
|
|
|
52946
53131
|
return new ScheduledTaskService(state, stateStore);
|
|
52947
53132
|
}
|
|
52948
53133
|
function resolveConfigPathForCurrentEnv() {
|
|
52949
|
-
return coreEnv("CONFIG") ??
|
|
53134
|
+
return coreEnv("CONFIG") ?? join27(coreHomeDir(requireHome2()), "config.json");
|
|
52950
53135
|
}
|
|
52951
53136
|
function resolveDaemonPathsForCurrentConfig() {
|
|
52952
53137
|
const configPath = resolveConfigPathForCurrentEnv();
|
|
@@ -53297,7 +53482,7 @@ function decodeFirstRunOnboarding(raw) {
|
|
|
53297
53482
|
return null;
|
|
53298
53483
|
}
|
|
53299
53484
|
function requireHome2() {
|
|
53300
|
-
const home = process.env.HOME ??
|
|
53485
|
+
const home = process.env.HOME ?? homedir20();
|
|
53301
53486
|
if (!home) {
|
|
53302
53487
|
throw new Error("Unable to resolve the current user home directory");
|
|
53303
53488
|
}
|
|
@@ -53321,7 +53506,7 @@ function safeDaemonLogPaths() {
|
|
|
53321
53506
|
const configPath = resolveConfigPathForCurrentEnv();
|
|
53322
53507
|
const paths = resolveDaemonPathsForCurrentConfig();
|
|
53323
53508
|
return {
|
|
53324
|
-
appLog:
|
|
53509
|
+
appLog: join27(dirname15(configPath), "runtime", "app.log"),
|
|
53325
53510
|
stderrLog: paths.stderrLog
|
|
53326
53511
|
};
|
|
53327
53512
|
} catch {
|
|
@@ -18,6 +18,11 @@ export interface ControlSessionInfo {
|
|
|
18
18
|
transportSession: string;
|
|
19
19
|
running: boolean;
|
|
20
20
|
archived: boolean;
|
|
21
|
+
/** The agent adapter command this session runs (acpx-recorded, or the agent's resolved
|
|
22
|
+
* default). Surfaced so the web can avoid seeding a new session's model picker from a
|
|
23
|
+
* session on a different adapter version (whose advertised model ids may be in an
|
|
24
|
+
* incompatible format). Omitted when unknown. */
|
|
25
|
+
agentCommand?: string;
|
|
21
26
|
}
|
|
22
27
|
export interface ControlAgentInfo {
|
|
23
28
|
name: string;
|
|
@@ -102,6 +102,8 @@ export interface AgentSession {
|
|
|
102
102
|
export interface AgentSessionListQuery {
|
|
103
103
|
agent: string;
|
|
104
104
|
agentCommand?: string;
|
|
105
|
+
/** Resolved acpx driver for `agent` (e.g. a custom `my-codex` agent has driver `codex`). Used to gate driver-specific list filtering. */
|
|
106
|
+
driver?: string;
|
|
105
107
|
cwd: string;
|
|
106
108
|
cursor?: string;
|
|
107
109
|
filterCwd?: string;
|