@ganglion/xacpx 0.17.0-beta.4 → 0.17.0-beta.6
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 +1 -1
- package/dist/bridge/bridge-main.js +211 -107
- package/dist/cli.js +5911 -4891
- package/dist/config/types.d.ts +8 -0
- package/dist/control/control-service.d.ts +20 -18
- package/dist/control/session-turn-runner.d.ts +35 -0
- package/dist/control/turn-queue.d.ts +57 -0
- package/dist/control/turn-support.d.ts +28 -0
- package/dist/orchestration/orchestration-service.d.ts +14 -101
- package/dist/orchestration/orchestration-types.d.ts +2 -0
- package/dist/orchestration/service/coordinator-registry-service.d.ts +25 -0
- package/dist/orchestration/service/group-service.d.ts +25 -0
- package/dist/orchestration/service/human-delegation-service.d.ts +16 -0
- package/dist/orchestration/service/human-question-service.d.ts +57 -0
- package/dist/orchestration/service/notice-delivery-service.d.ts +25 -0
- package/dist/orchestration/service/orchestration-state-kernel.d.ts +58 -0
- package/dist/orchestration/service/question-flow-core.d.ts +52 -0
- package/dist/orchestration/service/rpc-delegation-service.d.ts +18 -0
- package/dist/orchestration/service/task-approval-service.d.ts +17 -0
- package/dist/orchestration/service/task-cancellation-service.d.ts +26 -0
- package/dist/orchestration/service/task-lifecycle-service.d.ts +21 -0
- package/dist/orchestration/service/worker-session-manager.d.ts +65 -0
- package/dist/orchestration/task-watch-timeouts.d.ts +2 -0
- package/dist/plugin-api.js +49 -14
- package/dist/transport/command-timeouts.d.ts +47 -0
- package/dist/weixin/util/weixin-log.d.ts +14 -0
- package/package.json +2 -2
- package/dist/weixin/util/logger.d.ts +0 -14
package/README.md
CHANGED
|
@@ -182,7 +182,7 @@ xacpx-relay add token # prints the access token once
|
|
|
182
182
|
xacpx-relay start # defaults: --host 0.0.0.0 --http-port 8787
|
|
183
183
|
|
|
184
184
|
# On each instance host:
|
|
185
|
-
xacpx plugin add @ganglion/xacpx-channel-relay # requires xacpx >= 0.
|
|
185
|
+
xacpx plugin add @ganglion/xacpx-channel-relay # requires xacpx >= 0.17.0-beta.6
|
|
186
186
|
xacpx channel add relay --url wss://relay.example.com --token <access-token> --name my-box
|
|
187
187
|
xacpx restart
|
|
188
188
|
```
|
|
@@ -3426,18 +3426,6 @@ var init_acpx_queue_owner_launcher = __esm(() => {
|
|
|
3426
3426
|
init_i18n();
|
|
3427
3427
|
});
|
|
3428
3428
|
|
|
3429
|
-
// src/transport/permission-mode-flag.ts
|
|
3430
|
-
function permissionModeToFlag(permissionMode) {
|
|
3431
|
-
switch (permissionMode) {
|
|
3432
|
-
case "approve-reads":
|
|
3433
|
-
return "--approve-reads";
|
|
3434
|
-
case "deny-all":
|
|
3435
|
-
return "--deny-all";
|
|
3436
|
-
case "approve-all":
|
|
3437
|
-
return "--approve-all";
|
|
3438
|
-
}
|
|
3439
|
-
}
|
|
3440
|
-
|
|
3441
3429
|
// src/util/path.ts
|
|
3442
3430
|
import path2 from "node:path";
|
|
3443
3431
|
import { homedir as homedir3 } from "node:os";
|
|
@@ -3698,6 +3686,133 @@ async function deleteAcpxSessionFiles(options) {
|
|
|
3698
3686
|
}
|
|
3699
3687
|
var init_acpx_session_files = () => {};
|
|
3700
3688
|
|
|
3689
|
+
// src/transport/command-timeouts.ts
|
|
3690
|
+
function formatTimeout(timeoutMs) {
|
|
3691
|
+
return timeoutMs >= 1000 ? `${timeoutMs / 1000}s` : `${timeoutMs}ms`;
|
|
3692
|
+
}
|
|
3693
|
+
function captureOutputTail(value) {
|
|
3694
|
+
const normalized = value?.trim();
|
|
3695
|
+
if (!normalized)
|
|
3696
|
+
return;
|
|
3697
|
+
return normalized.slice(-COMMAND_OUTPUT_TAIL_CHARS);
|
|
3698
|
+
}
|
|
3699
|
+
function isCommandTimeoutError(error) {
|
|
3700
|
+
return error instanceof CommandTimeoutError;
|
|
3701
|
+
}
|
|
3702
|
+
var DEFAULT_MANAGEMENT_COMMAND_TIMEOUT_MS = 30000, DEFAULT_SESSION_INIT_TIMEOUT_MS = 120000, BRIDGE_REQUEST_TIMEOUT_GRACE_MS = 15000, COMMAND_OUTPUT_TAIL_CHARS = 2000, CommandTimeoutError;
|
|
3703
|
+
var init_command_timeouts = __esm(() => {
|
|
3704
|
+
CommandTimeoutError = class CommandTimeoutError extends Error {
|
|
3705
|
+
timeoutMs;
|
|
3706
|
+
command;
|
|
3707
|
+
stage;
|
|
3708
|
+
stdoutTail;
|
|
3709
|
+
stderrTail;
|
|
3710
|
+
constructor(timeoutMs, command, detail = {}) {
|
|
3711
|
+
const stdoutTail = captureOutputTail(detail.stdout);
|
|
3712
|
+
const stderrTail = captureOutputTail(detail.stderr);
|
|
3713
|
+
const output = [
|
|
3714
|
+
stdoutTail ? `stdout tail: ${stdoutTail}` : "",
|
|
3715
|
+
stderrTail ? `stderr tail: ${stderrTail}` : ""
|
|
3716
|
+
].filter(Boolean).join("; ");
|
|
3717
|
+
super(`acpx command timed out${detail.stage ? ` during ${detail.stage}` : ""} after ${formatTimeout(timeoutMs)}: ${command}` + (output ? `; ${output}` : ""));
|
|
3718
|
+
this.timeoutMs = timeoutMs;
|
|
3719
|
+
this.command = command;
|
|
3720
|
+
this.name = "CommandTimeoutError";
|
|
3721
|
+
this.stage = detail.stage;
|
|
3722
|
+
this.stdoutTail = stdoutTail;
|
|
3723
|
+
this.stderrTail = stderrTail;
|
|
3724
|
+
}
|
|
3725
|
+
};
|
|
3726
|
+
});
|
|
3727
|
+
|
|
3728
|
+
// src/transport/permission-mode-flag.ts
|
|
3729
|
+
function permissionModeToFlag(permissionMode) {
|
|
3730
|
+
switch (permissionMode) {
|
|
3731
|
+
case "approve-reads":
|
|
3732
|
+
return "--approve-reads";
|
|
3733
|
+
case "deny-all":
|
|
3734
|
+
return "--deny-all";
|
|
3735
|
+
case "approve-all":
|
|
3736
|
+
return "--approve-all";
|
|
3737
|
+
}
|
|
3738
|
+
}
|
|
3739
|
+
|
|
3740
|
+
// src/transport/acpx-command-builder.ts
|
|
3741
|
+
function buildPermissionArgs(input) {
|
|
3742
|
+
const args = [permissionModeToFlag(input.permissionMode), "--non-interactive-permissions", input.nonInteractivePermissions];
|
|
3743
|
+
if (typeof input.permissionPolicy === "string" && input.permissionPolicy.trim().length > 0) {
|
|
3744
|
+
args.push("--permission-policy", input.permissionPolicy);
|
|
3745
|
+
}
|
|
3746
|
+
return args;
|
|
3747
|
+
}
|
|
3748
|
+
function buildQueueOwnerTtlArgs(queueOwnerTtlSeconds) {
|
|
3749
|
+
if (typeof queueOwnerTtlSeconds !== "number" || !Number.isFinite(queueOwnerTtlSeconds))
|
|
3750
|
+
return [];
|
|
3751
|
+
return ["--ttl", String(queueOwnerTtlSeconds)];
|
|
3752
|
+
}
|
|
3753
|
+
function buildModelArgs(model) {
|
|
3754
|
+
const trimmed = model?.trim();
|
|
3755
|
+
return trimmed ? ["--model", trimmed] : [];
|
|
3756
|
+
}
|
|
3757
|
+
function appendAgentAndTail(prefix, input, tail) {
|
|
3758
|
+
if (input.agentCommand)
|
|
3759
|
+
return [...prefix, "--agent", input.agentCommand, ...tail];
|
|
3760
|
+
return [...prefix, input.agent, ...tail];
|
|
3761
|
+
}
|
|
3762
|
+
function buildSessionArgs(input, tail, options = {}) {
|
|
3763
|
+
const prefix = [
|
|
3764
|
+
"--format",
|
|
3765
|
+
options.format ?? "quiet",
|
|
3766
|
+
"--cwd",
|
|
3767
|
+
input.cwd,
|
|
3768
|
+
...buildPermissionArgs(input.permission),
|
|
3769
|
+
...buildModelArgs(input.model)
|
|
3770
|
+
];
|
|
3771
|
+
if (options.verbose)
|
|
3772
|
+
prefix.push("--verbose");
|
|
3773
|
+
return appendAgentAndTail(prefix, input, tail);
|
|
3774
|
+
}
|
|
3775
|
+
function buildPromptArgs(input, tail) {
|
|
3776
|
+
const prefix = [
|
|
3777
|
+
"--format",
|
|
3778
|
+
"json",
|
|
3779
|
+
"--json-strict",
|
|
3780
|
+
"--cwd",
|
|
3781
|
+
input.cwd,
|
|
3782
|
+
...buildPermissionArgs(input.permission),
|
|
3783
|
+
...buildModelArgs(input.model),
|
|
3784
|
+
...buildQueueOwnerTtlArgs(input.queueOwnerTtlSeconds)
|
|
3785
|
+
];
|
|
3786
|
+
return appendAgentAndTail(prefix, input, tail);
|
|
3787
|
+
}
|
|
3788
|
+
function buildAgentQueryArgs(input, format, tail) {
|
|
3789
|
+
const prefix = ["--format", format, "--cwd", input.cwd, ...buildPermissionArgs(input.permission)];
|
|
3790
|
+
return appendAgentAndTail(prefix, input, tail);
|
|
3791
|
+
}
|
|
3792
|
+
function isMissingAcpxSessionError(stderr, stdout) {
|
|
3793
|
+
const combined = `${stderr}
|
|
3794
|
+
${stdout}`.toLowerCase();
|
|
3795
|
+
return combined.includes("no named session") || combined.includes("no cwd session") || combined.includes("session not found") || combined.includes("unknown session") || combined.includes("no acpx session found");
|
|
3796
|
+
}
|
|
3797
|
+
function parseAcpxSessionRecordId(stdout) {
|
|
3798
|
+
try {
|
|
3799
|
+
const parsed = JSON.parse(stdout);
|
|
3800
|
+
const acpxRecordId = typeof parsed.acpxRecordId === "string" ? parsed.acpxRecordId : typeof parsed.id === "string" ? parsed.id : undefined;
|
|
3801
|
+
const agentSessionId = typeof parsed.agentSessionId === "string" ? parsed.agentSessionId : undefined;
|
|
3802
|
+
if (acpxRecordId && /^[\w.:-]+$/.test(acpxRecordId) && acpxRecordId.length >= 8) {
|
|
3803
|
+
return { acpxRecordId, agentSessionId };
|
|
3804
|
+
}
|
|
3805
|
+
} catch {
|
|
3806
|
+
const firstLine = stdout.trim().split(/\r?\n/, 1)[0];
|
|
3807
|
+
if (firstLine && /^[\w.:-]+$/.test(firstLine) && firstLine.length >= 8) {
|
|
3808
|
+
return { acpxRecordId: firstLine };
|
|
3809
|
+
}
|
|
3810
|
+
}
|
|
3811
|
+
return;
|
|
3812
|
+
}
|
|
3813
|
+
var DEFAULT_PERMISSION_MODE = "approve-all", DEFAULT_NON_INTERACTIVE = "deny";
|
|
3814
|
+
var init_acpx_command_builder = () => {};
|
|
3815
|
+
|
|
3701
3816
|
// src/bridge/bridge-main.ts
|
|
3702
3817
|
import { createInterface } from "node:readline";
|
|
3703
3818
|
|
|
@@ -3794,6 +3909,9 @@ init_acpx_queue_owner_launcher();
|
|
|
3794
3909
|
init_agent_session_list();
|
|
3795
3910
|
init_codex_subagent_filter();
|
|
3796
3911
|
init_acpx_session_files();
|
|
3912
|
+
init_command_timeouts();
|
|
3913
|
+
init_command_timeouts();
|
|
3914
|
+
init_acpx_command_builder();
|
|
3797
3915
|
class EnsureSessionFailedError extends Error {
|
|
3798
3916
|
kind;
|
|
3799
3917
|
data;
|
|
@@ -3804,20 +3922,6 @@ class EnsureSessionFailedError extends Error {
|
|
|
3804
3922
|
this.data = data;
|
|
3805
3923
|
}
|
|
3806
3924
|
}
|
|
3807
|
-
var DEFAULT_SESSION_INIT_TIMEOUT_MS = 120000;
|
|
3808
|
-
|
|
3809
|
-
class CommandTimeoutError extends Error {
|
|
3810
|
-
timeoutMs;
|
|
3811
|
-
constructor(timeoutMs, command) {
|
|
3812
|
-
super(`acpx command timed out after ${timeoutMs / 1000}s: ${command}`);
|
|
3813
|
-
this.timeoutMs = timeoutMs;
|
|
3814
|
-
this.name = "CommandTimeoutError";
|
|
3815
|
-
}
|
|
3816
|
-
}
|
|
3817
|
-
function modelArgs(model) {
|
|
3818
|
-
const trimmed = model?.trim();
|
|
3819
|
-
return trimmed ? ["--model", trimmed] : [];
|
|
3820
|
-
}
|
|
3821
3925
|
|
|
3822
3926
|
class BridgeRuntime {
|
|
3823
3927
|
command;
|
|
@@ -3856,7 +3960,7 @@ class BridgeRuntime {
|
|
|
3856
3960
|
...includeFilterCwd && input.filterCwd ? ["--filter-cwd", input.filterCwd] : [],
|
|
3857
3961
|
...input.cursor ? ["--cursor", input.cursor] : []
|
|
3858
3962
|
], { format: "json" }));
|
|
3859
|
-
return await this.run(spec.command, spec.args);
|
|
3963
|
+
return await this.run(spec.command, spec.args, { timeoutMs: this.sessionInitTimeoutMs() });
|
|
3860
3964
|
},
|
|
3861
3965
|
formatError: (result) => result.stderr || result.stdout || `sessions list failed with exit code ${result.code}`,
|
|
3862
3966
|
isSubagentSession: (input.driver ?? input.agent) === CODEX_AGENT_NAME ? codexSubagentPredicate() : undefined
|
|
@@ -3890,27 +3994,39 @@ class BridgeRuntime {
|
|
|
3890
3994
|
const value = this.options.sessionInitTimeoutMs;
|
|
3891
3995
|
return typeof value === "number" && Number.isFinite(value) && value > 0 ? value : DEFAULT_SESSION_INIT_TIMEOUT_MS;
|
|
3892
3996
|
}
|
|
3997
|
+
managementCommandTimeoutMs() {
|
|
3998
|
+
const value = this.options.managementCommandTimeoutMs;
|
|
3999
|
+
return typeof value === "number" && Number.isFinite(value) && value > 0 ? value : DEFAULT_MANAGEMENT_COMMAND_TIMEOUT_MS;
|
|
4000
|
+
}
|
|
3893
4001
|
async hasSession(input) {
|
|
3894
4002
|
const spawnSpec = resolveSpawnCommand(this.command, this.buildSessionArgs(input, [
|
|
3895
4003
|
"sessions",
|
|
3896
4004
|
"show",
|
|
3897
4005
|
input.name
|
|
3898
4006
|
]));
|
|
3899
|
-
const result = await this.run(spawnSpec.command, spawnSpec.args
|
|
4007
|
+
const result = await this.run(spawnSpec.command, spawnSpec.args, {
|
|
4008
|
+
timeoutMs: this.managementCommandTimeoutMs(),
|
|
4009
|
+
stage: "has-session"
|
|
4010
|
+
});
|
|
3900
4011
|
return { exists: result.code === 0 };
|
|
3901
4012
|
}
|
|
3902
4013
|
async tailSessionHistory(input) {
|
|
3903
4014
|
const candidates = [
|
|
4015
|
+
["sessions", "history", input.name, "--limit", String(input.lines)],
|
|
3904
4016
|
["sessions", "history", "quiet", "-s", input.name, String(input.lines)],
|
|
3905
4017
|
["sessions", "history", "quiet", input.name, String(input.lines)],
|
|
3906
4018
|
["sessions", "history", "-s", input.name, "--tail", String(input.lines)],
|
|
3907
4019
|
["sessions", "history", input.name, "--tail", String(input.lines)],
|
|
3908
4020
|
["sessions", "history", "--name", input.name, "--tail", String(input.lines)]
|
|
3909
4021
|
];
|
|
4022
|
+
const deadline = Date.now() + this.managementCommandTimeoutMs();
|
|
3910
4023
|
let lastResult;
|
|
3911
4024
|
for (const tailArgs of candidates) {
|
|
3912
4025
|
const spawnSpec = resolveSpawnCommand(this.command, this.buildSessionArgs(input, tailArgs));
|
|
3913
|
-
const result = await this.run(spawnSpec.command, spawnSpec.args
|
|
4026
|
+
const result = await this.run(spawnSpec.command, spawnSpec.args, {
|
|
4027
|
+
timeoutMs: Math.max(deadline - Date.now(), 1),
|
|
4028
|
+
stage: "session-history"
|
|
4029
|
+
});
|
|
3914
4030
|
if (result.code === 0) {
|
|
3915
4031
|
return { text: result.stdout.trimEnd() };
|
|
3916
4032
|
}
|
|
@@ -4077,28 +4193,16 @@ class BridgeRuntime {
|
|
|
4077
4193
|
"show",
|
|
4078
4194
|
input.name
|
|
4079
4195
|
]));
|
|
4080
|
-
const result = await this.run(spawnSpec.command, spawnSpec.args
|
|
4196
|
+
const result = await this.run(spawnSpec.command, spawnSpec.args, {
|
|
4197
|
+
timeoutMs: this.managementCommandTimeoutMs(),
|
|
4198
|
+
stage: "read-session-record"
|
|
4199
|
+
});
|
|
4081
4200
|
if (result.code !== 0) {
|
|
4082
4201
|
throw new Error(result.stderr || result.stdout || "sessions show failed");
|
|
4083
4202
|
}
|
|
4084
|
-
|
|
4085
|
-
|
|
4086
|
-
|
|
4087
|
-
if (typeof parsed.acpxRecordId === "string") {
|
|
4088
|
-
acpxRecordId = parsed.acpxRecordId;
|
|
4089
|
-
} else if (typeof parsed.id === "string") {
|
|
4090
|
-
acpxRecordId = parsed.id;
|
|
4091
|
-
}
|
|
4092
|
-
const agentSessionId = typeof parsed.agentSessionId === "string" ? parsed.agentSessionId : undefined;
|
|
4093
|
-
if (acpxRecordId && /^[\w.:-]+$/.test(acpxRecordId) && acpxRecordId.length >= 8) {
|
|
4094
|
-
return { acpxRecordId, agentSessionId };
|
|
4095
|
-
}
|
|
4096
|
-
} catch {
|
|
4097
|
-
const firstLine = result.stdout.trim().split(/\r?\n/, 1)[0];
|
|
4098
|
-
if (firstLine && /^[\w.:-]+$/.test(firstLine) && firstLine.length >= 8) {
|
|
4099
|
-
return { acpxRecordId: firstLine };
|
|
4100
|
-
}
|
|
4101
|
-
}
|
|
4203
|
+
const record = parseAcpxSessionRecordId(result.stdout);
|
|
4204
|
+
if (record)
|
|
4205
|
+
return record;
|
|
4102
4206
|
throw new Error("failed to resolve acpx session record id");
|
|
4103
4207
|
}
|
|
4104
4208
|
async getAgentSessionId(input) {
|
|
@@ -4112,7 +4216,10 @@ class BridgeRuntime {
|
|
|
4112
4216
|
input.name,
|
|
4113
4217
|
input.modeId
|
|
4114
4218
|
]));
|
|
4115
|
-
const result = await this.run(spawnSpec.command, spawnSpec.args
|
|
4219
|
+
const result = await this.run(spawnSpec.command, spawnSpec.args, {
|
|
4220
|
+
timeoutMs: this.managementCommandTimeoutMs(),
|
|
4221
|
+
stage: "set-mode"
|
|
4222
|
+
});
|
|
4116
4223
|
if (result.code !== 0) {
|
|
4117
4224
|
throw new Error(result.stderr || result.stdout || "set-mode failed");
|
|
4118
4225
|
}
|
|
@@ -4126,7 +4233,10 @@ class BridgeRuntime {
|
|
|
4126
4233
|
"model",
|
|
4127
4234
|
input.modelId
|
|
4128
4235
|
]));
|
|
4129
|
-
const result = await this.run(spawnSpec.command, spawnSpec.args
|
|
4236
|
+
const result = await this.run(spawnSpec.command, spawnSpec.args, {
|
|
4237
|
+
timeoutMs: this.managementCommandTimeoutMs(),
|
|
4238
|
+
stage: "set-model"
|
|
4239
|
+
});
|
|
4130
4240
|
if (result.code !== 0) {
|
|
4131
4241
|
throw new Error(result.stderr || result.stdout || "set-model failed");
|
|
4132
4242
|
}
|
|
@@ -4138,7 +4248,10 @@ class BridgeRuntime {
|
|
|
4138
4248
|
"-s",
|
|
4139
4249
|
input.name
|
|
4140
4250
|
], { format: "json" }));
|
|
4141
|
-
const result = await this.run(spawnSpec.command, spawnSpec.args
|
|
4251
|
+
const result = await this.run(spawnSpec.command, spawnSpec.args, {
|
|
4252
|
+
timeoutMs: this.managementCommandTimeoutMs(),
|
|
4253
|
+
stage: "get-session-model"
|
|
4254
|
+
});
|
|
4142
4255
|
if (result.code !== 0) {
|
|
4143
4256
|
throw new Error(result.stderr || result.stdout || "status failed");
|
|
4144
4257
|
}
|
|
@@ -4158,7 +4271,10 @@ class BridgeRuntime {
|
|
|
4158
4271
|
"-s",
|
|
4159
4272
|
input.name
|
|
4160
4273
|
]));
|
|
4161
|
-
const result = await this.run(spawnSpec.command, spawnSpec.args
|
|
4274
|
+
const result = await this.run(spawnSpec.command, spawnSpec.args, {
|
|
4275
|
+
timeoutMs: this.managementCommandTimeoutMs(),
|
|
4276
|
+
stage: "cancel"
|
|
4277
|
+
});
|
|
4162
4278
|
if (result.code !== 0) {
|
|
4163
4279
|
throw new Error(result.stderr || result.stdout || "cancel failed");
|
|
4164
4280
|
}
|
|
@@ -4173,11 +4289,14 @@ class BridgeRuntime {
|
|
|
4173
4289
|
"close",
|
|
4174
4290
|
input.name
|
|
4175
4291
|
]));
|
|
4176
|
-
const result = await this.run(spawnSpec.command, spawnSpec.args
|
|
4292
|
+
const result = await this.run(spawnSpec.command, spawnSpec.args, {
|
|
4293
|
+
timeoutMs: this.managementCommandTimeoutMs(),
|
|
4294
|
+
stage: "remove-session"
|
|
4295
|
+
});
|
|
4177
4296
|
if (result.code === 0) {
|
|
4178
4297
|
return {};
|
|
4179
4298
|
}
|
|
4180
|
-
if (
|
|
4299
|
+
if (isMissingAcpxSessionError(result.stderr, result.stdout)) {
|
|
4181
4300
|
return {};
|
|
4182
4301
|
}
|
|
4183
4302
|
throw new Error(result.stderr || result.stdout || "sessions close failed");
|
|
@@ -4207,54 +4326,30 @@ class BridgeRuntime {
|
|
|
4207
4326
|
return {};
|
|
4208
4327
|
}
|
|
4209
4328
|
buildSessionArgs(input, tail, options = {}) {
|
|
4210
|
-
|
|
4211
|
-
|
|
4212
|
-
|
|
4213
|
-
|
|
4214
|
-
input.
|
|
4215
|
-
|
|
4216
|
-
|
|
4217
|
-
];
|
|
4218
|
-
if (options.verbose) {
|
|
4219
|
-
prefix.push("--verbose");
|
|
4220
|
-
}
|
|
4221
|
-
if (input.agentCommand) {
|
|
4222
|
-
return [...prefix, "--agent", input.agentCommand, ...tail];
|
|
4223
|
-
}
|
|
4224
|
-
return [...prefix, input.agent, ...tail];
|
|
4329
|
+
return buildSessionArgs({
|
|
4330
|
+
agent: input.agent,
|
|
4331
|
+
agentCommand: input.agentCommand,
|
|
4332
|
+
cwd: input.cwd,
|
|
4333
|
+
model: input.model,
|
|
4334
|
+
permission: this.permissionInput()
|
|
4335
|
+
}, tail, options);
|
|
4225
4336
|
}
|
|
4226
4337
|
buildPromptArgs(input, tail) {
|
|
4227
|
-
|
|
4228
|
-
|
|
4229
|
-
|
|
4230
|
-
|
|
4231
|
-
|
|
4232
|
-
|
|
4233
|
-
|
|
4234
|
-
|
|
4235
|
-
|
|
4236
|
-
|
|
4237
|
-
|
|
4238
|
-
|
|
4239
|
-
|
|
4240
|
-
|
|
4241
|
-
|
|
4242
|
-
buildQueueOwnerTtlArgs() {
|
|
4243
|
-
const ttl = this.options.queueOwnerTtlSeconds;
|
|
4244
|
-
if (typeof ttl !== "number" || !Number.isFinite(ttl)) {
|
|
4245
|
-
return [];
|
|
4246
|
-
}
|
|
4247
|
-
return ["--ttl", String(ttl)];
|
|
4248
|
-
}
|
|
4249
|
-
buildPermissionArgs() {
|
|
4250
|
-
const permissionMode = this.options.permissionMode ?? "approve-all";
|
|
4251
|
-
const nonInteractivePermissions = this.options.nonInteractivePermissions ?? "deny";
|
|
4252
|
-
const modeFlag = permissionModeToFlag(permissionMode);
|
|
4253
|
-
const args = [modeFlag, "--non-interactive-permissions", nonInteractivePermissions];
|
|
4254
|
-
if (typeof this.options.permissionPolicy === "string" && this.options.permissionPolicy.trim().length > 0) {
|
|
4255
|
-
args.push("--permission-policy", this.options.permissionPolicy);
|
|
4256
|
-
}
|
|
4257
|
-
return args;
|
|
4338
|
+
return buildPromptArgs({
|
|
4339
|
+
agent: input.agent,
|
|
4340
|
+
agentCommand: input.agentCommand,
|
|
4341
|
+
cwd: input.cwd,
|
|
4342
|
+
model: input.model,
|
|
4343
|
+
permission: this.permissionInput(),
|
|
4344
|
+
queueOwnerTtlSeconds: this.options.queueOwnerTtlSeconds
|
|
4345
|
+
}, tail);
|
|
4346
|
+
}
|
|
4347
|
+
permissionInput() {
|
|
4348
|
+
return {
|
|
4349
|
+
permissionMode: this.options.permissionMode ?? DEFAULT_PERMISSION_MODE,
|
|
4350
|
+
nonInteractivePermissions: this.options.nonInteractivePermissions ?? DEFAULT_NON_INTERACTIVE,
|
|
4351
|
+
permissionPolicy: this.options.permissionPolicy
|
|
4352
|
+
};
|
|
4258
4353
|
}
|
|
4259
4354
|
}
|
|
4260
4355
|
function spawnCapture(command, args, options) {
|
|
@@ -4269,7 +4364,11 @@ function spawnCapture(command, args, options) {
|
|
|
4269
4364
|
const timeoutId = typeof options?.timeoutMs === "number" && Number.isFinite(options.timeoutMs) && options.timeoutMs > 0 ? setTimeout(() => {
|
|
4270
4365
|
const kill = options.killProcessTreeFn ?? ((pid) => terminateProcessTree(pid, { detachedProcessGroup: false }));
|
|
4271
4366
|
kill(child.pid ?? 0);
|
|
4272
|
-
reject(new CommandTimeoutError(options.timeoutMs, [command, ...args].join(" ")
|
|
4367
|
+
reject(new CommandTimeoutError(options.timeoutMs, [command, ...args].join(" "), {
|
|
4368
|
+
stage: options.stage,
|
|
4369
|
+
stdout,
|
|
4370
|
+
stderr
|
|
4371
|
+
}));
|
|
4273
4372
|
}, options.timeoutMs) : undefined;
|
|
4274
4373
|
child.stdout.on("data", (chunk) => {
|
|
4275
4374
|
stdout += String(chunk);
|
|
@@ -4425,11 +4524,6 @@ function isUnknownVerboseOption(stderr, stdout) {
|
|
|
4425
4524
|
${stdout}`;
|
|
4426
4525
|
return /(unknown|unrecognized)\b[^\n]*--verbose/i.test(combined);
|
|
4427
4526
|
}
|
|
4428
|
-
function isMissingBridgeSessionError(stderr, stdout) {
|
|
4429
|
-
const combined = `${stderr}
|
|
4430
|
-
${stdout}`.toLowerCase();
|
|
4431
|
-
return combined.includes("no named session") || combined.includes("no cwd session") || combined.includes("session not found") || combined.includes("unknown session") || combined.includes("no acpx session found");
|
|
4432
|
-
}
|
|
4433
4527
|
|
|
4434
4528
|
// src/bridge/bridge-server.ts
|
|
4435
4529
|
class BridgeInvalidRequestError extends Error {
|
|
@@ -4491,6 +4585,15 @@ class BridgeServer {
|
|
|
4491
4585
|
const message = error instanceof Error ? error.message : String(error);
|
|
4492
4586
|
const ensureSessionFields = error instanceof EnsureSessionFailedError ? { kind: error.kind, ...error.data ? { data: error.data } : {} } : {};
|
|
4493
4587
|
const promptDetails = error instanceof PromptCommandError ? { details: { exitCode: error.exitCode, stdout: error.stdout, stderr: error.stderr } } : {};
|
|
4588
|
+
const timeoutDetails = error instanceof CommandTimeoutError ? {
|
|
4589
|
+
timeout: {
|
|
4590
|
+
timeoutMs: error.timeoutMs,
|
|
4591
|
+
command: error.command,
|
|
4592
|
+
...error.stage ? { stage: error.stage } : {},
|
|
4593
|
+
...error.stdoutTail ? { stdoutTail: error.stdoutTail } : {},
|
|
4594
|
+
...error.stderrTail ? { stderrTail: error.stderrTail } : {}
|
|
4595
|
+
}
|
|
4596
|
+
} : {};
|
|
4494
4597
|
return `${JSON.stringify({
|
|
4495
4598
|
id: requestId,
|
|
4496
4599
|
ok: false,
|
|
@@ -4498,7 +4601,8 @@ class BridgeServer {
|
|
|
4498
4601
|
code: error instanceof BridgeInvalidRequestError ? "BRIDGE_INVALID_REQUEST" : "BRIDGE_INTERNAL_ERROR",
|
|
4499
4602
|
message,
|
|
4500
4603
|
...ensureSessionFields,
|
|
4501
|
-
...promptDetails
|
|
4604
|
+
...promptDetails,
|
|
4605
|
+
...timeoutDetails
|
|
4502
4606
|
}
|
|
4503
4607
|
})}
|
|
4504
4608
|
`;
|