@ganglion/xacpx 0.10.1 → 0.11.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/README.md +20 -0
- package/dist/bridge/bridge-main.js +126 -9
- package/dist/channels/types.d.ts +16 -0
- package/dist/cli.js +1688 -371
- package/dist/commands/handlers/agent-handler.d.ts +1 -1
- package/dist/commands/handlers/session-handler.d.ts +7 -4
- package/dist/commands/parse-command.d.ts +7 -0
- package/dist/commands/router-types.d.ts +7 -2
- package/dist/config/agent-catalog.d.ts +14 -0
- package/dist/config/local-agent-bin.d.ts +17 -0
- package/dist/config/resolve-agent-command.d.ts +11 -0
- package/dist/config/types.d.ts +10 -0
- package/dist/control/control-event-bus.d.ts +59 -0
- package/dist/control/control-service.d.ts +147 -0
- package/dist/control/workspace-fs.d.ts +52 -0
- package/dist/i18n/types.d.ts +12 -0
- package/dist/plugin-api.d.ts +3 -0
- package/dist/plugin-api.js +53 -0
- package/dist/scheduled/scheduled-service.d.ts +3 -0
- package/dist/sessions/active-turn-registry.d.ts +2 -0
- package/dist/sessions/session-service.d.ts +4 -0
- package/dist/state/types.d.ts +2 -0
- package/dist/transport/native-session-history.d.ts +34 -0
- package/dist/transport/types.d.ts +27 -1
- package/dist/weixin/agent/interface.d.ts +3 -1
- package/package.json +17 -2
package/README.md
CHANGED
|
@@ -331,6 +331,7 @@ These templates only write `driver`; the actual launch command is resolved by ac
|
|
|
331
331
|
| `/use <alias>` | Switch the current session |
|
|
332
332
|
| `/status` | Show the current session status |
|
|
333
333
|
| `/mode` / `/mode <id>` | View or set the underlying `acpx` mode |
|
|
334
|
+
| `/model` / `/model <id>` | View or switch the session's LLM model (also `/session new --model`, `/agent add --model`) |
|
|
334
335
|
| `/replymode` | Show the current reply mode |
|
|
335
336
|
| `/replymode stream` | Streaming replies |
|
|
336
337
|
| `/replymode verbose` | Streaming + tool-call summaries |
|
|
@@ -514,6 +515,25 @@ take a look at today's API timeout issue
|
|
|
514
515
|
|
|
515
516
|
For more filtering, aliases, and troubleshooting, see [docs/native-sessions.md](./docs/native-sessions.md).
|
|
516
517
|
|
|
518
|
+
## Self-hosted relay hub (optional)
|
|
519
|
+
|
|
520
|
+
If you run several xacpx instances and want to drive them all from one browser dashboard, you can self-host the **relay hub**. Each instance dials out to the hub over WebSocket and registers; you log in to a multi-tenant web dashboard and manage every instance's sessions — chat, scheduled tasks, and orchestration — from one place. Streaming agent replies render as markdown, and the layout works on mobile.
|
|
521
|
+
|
|
522
|
+
> Status: the relay packages are built and audited but **not yet published to npm**, so today you deploy from a source checkout. See the full guide for the exact steps.
|
|
523
|
+
|
|
524
|
+
```bash
|
|
525
|
+
# Build the hub server + dashboard from a repo checkout
|
|
526
|
+
git clone https://github.com/gadzan/xacpx && cd xacpx && bun install
|
|
527
|
+
bun run build:relay && bun run build:relay-web
|
|
528
|
+
|
|
529
|
+
# Create the first admin, then start (point --web-root at the built dashboard)
|
|
530
|
+
node packages/relay/dist/cli.js init-admin --username admin --db /var/lib/xacpx-relay/relay.db
|
|
531
|
+
node packages/relay/dist/cli.js start --db /var/lib/xacpx-relay/relay.db \
|
|
532
|
+
--web-root packages/relay-web/dist --host 0.0.0.0
|
|
533
|
+
```
|
|
534
|
+
|
|
535
|
+
Full walkthrough — pairing instances, TLS/reverse-proxy, systemd, backups, troubleshooting: **[Self-Hosting the Relay Hub](https://gadzan.github.io/xacpx/guide/relay-self-hosting)** (or [docs/relay-deployment.md](./docs/relay-deployment.md) for the terse runbook).
|
|
536
|
+
|
|
517
537
|
## Config and runtime files
|
|
518
538
|
|
|
519
539
|
Default file locations:
|
|
@@ -64,6 +64,10 @@ function encodeBridgePromptThoughtEvent(event) {
|
|
|
64
64
|
return `${JSON.stringify(event)}
|
|
65
65
|
`;
|
|
66
66
|
}
|
|
67
|
+
function encodeBridgePromptPlanEvent(event) {
|
|
68
|
+
return `${JSON.stringify(event)}
|
|
69
|
+
`;
|
|
70
|
+
}
|
|
67
71
|
function encodeBridgeSessionProgressEvent(event) {
|
|
68
72
|
return `${JSON.stringify(event)}
|
|
69
73
|
`;
|
|
@@ -419,6 +423,8 @@ function createStreamingPromptState(formatToolCalls = false, options) {
|
|
|
419
423
|
let toolEventMode;
|
|
420
424
|
let onToolEvent;
|
|
421
425
|
let onThought;
|
|
426
|
+
let onPlan;
|
|
427
|
+
let rawStream = false;
|
|
422
428
|
if (options === undefined) {
|
|
423
429
|
toolEventMode = "text";
|
|
424
430
|
onToolEvent = undefined;
|
|
@@ -428,6 +434,8 @@ function createStreamingPromptState(formatToolCalls = false, options) {
|
|
|
428
434
|
} else {
|
|
429
435
|
onToolEvent = options.onToolEvent;
|
|
430
436
|
onThought = options.onThought;
|
|
437
|
+
onPlan = options.onPlan;
|
|
438
|
+
rawStream = options.rawStream ?? false;
|
|
431
439
|
toolEventMode = resolveToolEventMode({
|
|
432
440
|
toolEventMode: options.mode,
|
|
433
441
|
onToolEvent
|
|
@@ -441,13 +449,15 @@ function createStreamingPromptState(formatToolCalls = false, options) {
|
|
|
441
449
|
formatToolCalls,
|
|
442
450
|
emittedToolCallIds: new Set,
|
|
443
451
|
toolEventMode,
|
|
452
|
+
rawStream,
|
|
444
453
|
onToolEvent,
|
|
445
454
|
onThought,
|
|
455
|
+
onPlan,
|
|
446
456
|
finalize() {
|
|
447
457
|
if (this.pendingLine.trim().length > 0) {
|
|
448
458
|
parseStreamingChunks(this, this.pendingLine);
|
|
449
459
|
}
|
|
450
|
-
const remaining = this.buffer.trim();
|
|
460
|
+
const remaining = this.rawStream ? this.buffer : this.buffer.trim();
|
|
451
461
|
this.buffer = "";
|
|
452
462
|
this.pendingLine = "";
|
|
453
463
|
return remaining;
|
|
@@ -479,9 +489,9 @@ function parseStreamingChunks(state, line) {
|
|
|
479
489
|
const update = event.params?.update;
|
|
480
490
|
if (!update)
|
|
481
491
|
return;
|
|
482
|
-
if (
|
|
492
|
+
if (update.sessionUpdate === "tool_call" || update.sessionUpdate === "tool_call_update") {
|
|
483
493
|
const wantsStructured = state.toolEventMode === "structured" || state.toolEventMode === "both";
|
|
484
|
-
const wantsText = state.toolEventMode === "text" || state.toolEventMode === "both";
|
|
494
|
+
const wantsText = (state.toolEventMode === "text" || state.toolEventMode === "both") && state.formatToolCalls;
|
|
485
495
|
if (wantsStructured && state.onToolEvent) {
|
|
486
496
|
const toolEvent = buildToolUseEvent(update);
|
|
487
497
|
if (toolEvent)
|
|
@@ -501,6 +511,12 @@ function parseStreamingChunks(state, line) {
|
|
|
501
511
|
}
|
|
502
512
|
return;
|
|
503
513
|
}
|
|
514
|
+
if (update.sessionUpdate === "plan") {
|
|
515
|
+
const entries = Array.isArray(update.entries) ? update.entries.filter((x) => !!x && typeof x === "object" && typeof x.content === "string" && typeof x.status === "string") : [];
|
|
516
|
+
if (entries.length > 0)
|
|
517
|
+
state.onPlan?.(entries);
|
|
518
|
+
return;
|
|
519
|
+
}
|
|
504
520
|
const isThoughtChunk = update.sessionUpdate === "agent_thought_chunk" && update.content?.type === "text" && typeof update.content.text === "string";
|
|
505
521
|
if (isThoughtChunk) {
|
|
506
522
|
const chunk2 = update.content.text;
|
|
@@ -517,6 +533,8 @@ function parseStreamingChunks(state, line) {
|
|
|
517
533
|
if (chunk.length === 0)
|
|
518
534
|
return;
|
|
519
535
|
state.buffer += chunk;
|
|
536
|
+
if (state.rawStream)
|
|
537
|
+
return;
|
|
520
538
|
let boundary;
|
|
521
539
|
while ((boundary = state.buffer.indexOf(`
|
|
522
540
|
|
|
@@ -882,6 +900,14 @@ var init_session = __esm(() => {
|
|
|
882
900
|
modeModeLabel: (modeId) => `- mode: ${modeId}`,
|
|
883
901
|
modeNotSet: "not set",
|
|
884
902
|
modeSet: (modeId) => `Current session mode set to: ${modeId}`,
|
|
903
|
+
modelHeader: "Current model:",
|
|
904
|
+
modelSessionLabel: (alias) => `- Session: ${alias}`,
|
|
905
|
+
modelModelLabel: (modelId) => `- model: ${modelId}`,
|
|
906
|
+
modelNotSet: "not set (using agent default)",
|
|
907
|
+
modelAvailableLabel: (models) => `- available: ${models}`,
|
|
908
|
+
modelSet: (modelId) => `Current session model switched to: ${modelId}`,
|
|
909
|
+
modelSetFailed: (modelId, detail) => `Failed to switch model: ${modelId}
|
|
910
|
+
${detail}`,
|
|
885
911
|
replyModeHeader: "Current reply mode:",
|
|
886
912
|
replyModeSessionLabel: (alias) => `- Session: ${alias}`,
|
|
887
913
|
replyModeGlobalDefault: (value) => `- Global default: ${value}`,
|
|
@@ -958,6 +984,11 @@ var init_session = __esm(() => {
|
|
|
958
984
|
modeHelpCmdShowDesc: "Show the saved mode of the current session",
|
|
959
985
|
modeHelpCmdSet: "/mode <id>",
|
|
960
986
|
modeHelpCmdSetDesc: "Set the current session mode",
|
|
987
|
+
modelHelpSummary: "View or switch the LLM model for the current session.",
|
|
988
|
+
modelHelpCmdShow: "/model",
|
|
989
|
+
modelHelpCmdShowDesc: "Show the current session model and the available ones",
|
|
990
|
+
modelHelpCmdSet: "/model <id>",
|
|
991
|
+
modelHelpCmdSetDesc: "Switch the current session model (e.g. gpt-5.2[high])",
|
|
961
992
|
replyModeHelpSummary: "View or set the reply output mode for the current logical session.",
|
|
962
993
|
replyModeHelpCmdShow: "/replymode",
|
|
963
994
|
replyModeHelpCmdShowDesc: "Show global default, current override, and effective value",
|
|
@@ -1961,6 +1992,14 @@ var init_session2 = __esm(() => {
|
|
|
1961
1992
|
modeModeLabel: (modeId) => `- mode:${modeId}`,
|
|
1962
1993
|
modeNotSet: "未设置",
|
|
1963
1994
|
modeSet: (modeId) => `已设置当前会话 mode:${modeId}`,
|
|
1995
|
+
modelHeader: "当前 model:",
|
|
1996
|
+
modelSessionLabel: (alias) => `- 会话:${alias}`,
|
|
1997
|
+
modelModelLabel: (modelId) => `- model:${modelId}`,
|
|
1998
|
+
modelNotSet: "未设置(使用 agent 默认)",
|
|
1999
|
+
modelAvailableLabel: (models) => `- 可选:${models}`,
|
|
2000
|
+
modelSet: (modelId) => `已切换当前会话 model:${modelId}`,
|
|
2001
|
+
modelSetFailed: (modelId, detail) => `切换 model 失败:${modelId}
|
|
2002
|
+
${detail}`,
|
|
1964
2003
|
replyModeHeader: "当前 reply mode:",
|
|
1965
2004
|
replyModeSessionLabel: (alias) => `- 会话:${alias}`,
|
|
1966
2005
|
replyModeGlobalDefault: (value) => `- 全局默认:${value}`,
|
|
@@ -2037,6 +2076,11 @@ var init_session2 = __esm(() => {
|
|
|
2037
2076
|
modeHelpCmdShowDesc: "查看当前会话已保存的 mode",
|
|
2038
2077
|
modeHelpCmdSet: "/mode <id>",
|
|
2039
2078
|
modeHelpCmdSetDesc: "设置当前会话 mode",
|
|
2079
|
+
modelHelpSummary: "查看或切换当前会话的 LLM model。",
|
|
2080
|
+
modelHelpCmdShow: "/model",
|
|
2081
|
+
modelHelpCmdShowDesc: "查看当前会话 model 及可选项",
|
|
2082
|
+
modelHelpCmdSet: "/model <id>",
|
|
2083
|
+
modelHelpCmdSetDesc: "切换当前会话 model(如 gpt-5.2[high])",
|
|
2040
2084
|
replyModeHelpSummary: "查看或设置当前逻辑会话的回复输出模式。",
|
|
2041
2085
|
replyModeHelpCmdShow: "/replymode",
|
|
2042
2086
|
replyModeHelpCmdShowDesc: "查看全局默认、当前覆盖和实际生效值",
|
|
@@ -3123,6 +3167,7 @@ class AcpxQueueOwnerLauncher {
|
|
|
3123
3167
|
nonInteractivePermissions: input.nonInteractivePermissions,
|
|
3124
3168
|
ttlMs: this.ttlMs,
|
|
3125
3169
|
maxQueueDepth: this.maxQueueDepth,
|
|
3170
|
+
...input.sessionOptions ? { sessionOptions: input.sessionOptions } : {},
|
|
3126
3171
|
mcpServers: [buildXacpxMcpServerSpec({
|
|
3127
3172
|
xacpxCommand: this.xacpxCommand,
|
|
3128
3173
|
coordinatorSession: input.coordinatorSession,
|
|
@@ -3473,6 +3518,10 @@ class CommandTimeoutError extends Error {
|
|
|
3473
3518
|
this.name = "CommandTimeoutError";
|
|
3474
3519
|
}
|
|
3475
3520
|
}
|
|
3521
|
+
function modelArgs(model) {
|
|
3522
|
+
const trimmed = model?.trim();
|
|
3523
|
+
return trimmed ? ["--model", trimmed] : [];
|
|
3524
|
+
}
|
|
3476
3525
|
|
|
3477
3526
|
class BridgeRuntime {
|
|
3478
3527
|
command;
|
|
@@ -3682,11 +3731,13 @@ class BridgeRuntime {
|
|
|
3682
3731
|
...structuredPrompt ? ["--file", structuredPrompt.filePath] : [input.text]
|
|
3683
3732
|
]));
|
|
3684
3733
|
const formatToolCalls = (input.replyMode ?? "verbose") === "verbose";
|
|
3734
|
+
const rawStream = input.replyMode === "stream";
|
|
3685
3735
|
const toolEventMode = input.toolEventMode ?? (input.toolEvents === true ? "structured" : "text");
|
|
3686
3736
|
try {
|
|
3687
3737
|
const result = onEvent ? await this.runPromptCommand(spawnSpec.command, spawnSpec.args, onEvent, {
|
|
3688
3738
|
formatToolCalls,
|
|
3689
|
-
toolEventMode
|
|
3739
|
+
toolEventMode,
|
|
3740
|
+
rawStream
|
|
3690
3741
|
}) : await this.run(spawnSpec.command, spawnSpec.args);
|
|
3691
3742
|
return { text: getPromptText(result) };
|
|
3692
3743
|
} finally {
|
|
@@ -3755,6 +3806,40 @@ class BridgeRuntime {
|
|
|
3755
3806
|
}
|
|
3756
3807
|
return {};
|
|
3757
3808
|
}
|
|
3809
|
+
async setModel(input) {
|
|
3810
|
+
const spawnSpec = resolveSpawnCommand(this.command, this.buildSessionArgs({ ...input, model: input.modelId }, [
|
|
3811
|
+
"set",
|
|
3812
|
+
"-s",
|
|
3813
|
+
input.name,
|
|
3814
|
+
"model",
|
|
3815
|
+
input.modelId
|
|
3816
|
+
]));
|
|
3817
|
+
const result = await this.run(spawnSpec.command, spawnSpec.args);
|
|
3818
|
+
if (result.code !== 0) {
|
|
3819
|
+
throw new Error(result.stderr || result.stdout || "set-model failed");
|
|
3820
|
+
}
|
|
3821
|
+
return {};
|
|
3822
|
+
}
|
|
3823
|
+
async getSessionModel(input) {
|
|
3824
|
+
const spawnSpec = resolveSpawnCommand(this.command, this.buildSessionArgs(input, [
|
|
3825
|
+
"status",
|
|
3826
|
+
"-s",
|
|
3827
|
+
input.name
|
|
3828
|
+
], { format: "json" }));
|
|
3829
|
+
const result = await this.run(spawnSpec.command, spawnSpec.args);
|
|
3830
|
+
if (result.code !== 0) {
|
|
3831
|
+
throw new Error(result.stderr || result.stdout || "status failed");
|
|
3832
|
+
}
|
|
3833
|
+
try {
|
|
3834
|
+
const json = JSON.parse(result.stdout);
|
|
3835
|
+
return {
|
|
3836
|
+
current: typeof json.model === "string" ? json.model : undefined,
|
|
3837
|
+
available: Array.isArray(json.availableModels) ? json.availableModels.filter((m) => typeof m === "string") : []
|
|
3838
|
+
};
|
|
3839
|
+
} catch {
|
|
3840
|
+
return { available: [] };
|
|
3841
|
+
}
|
|
3842
|
+
}
|
|
3758
3843
|
async cancel(input) {
|
|
3759
3844
|
const spawnSpec = resolveSpawnCommand(this.command, this.buildSessionArgs(input, [
|
|
3760
3845
|
"cancel",
|
|
@@ -3794,7 +3879,8 @@ class BridgeRuntime {
|
|
|
3794
3879
|
options.format ?? "quiet",
|
|
3795
3880
|
"--cwd",
|
|
3796
3881
|
input.cwd,
|
|
3797
|
-
...this.buildPermissionArgs()
|
|
3882
|
+
...this.buildPermissionArgs(),
|
|
3883
|
+
...modelArgs(input.model)
|
|
3798
3884
|
];
|
|
3799
3885
|
if (options.verbose) {
|
|
3800
3886
|
prefix.push("--verbose");
|
|
@@ -3812,6 +3898,7 @@ class BridgeRuntime {
|
|
|
3812
3898
|
"--cwd",
|
|
3813
3899
|
input.cwd,
|
|
3814
3900
|
...this.buildPermissionArgs(),
|
|
3901
|
+
...modelArgs(input.model),
|
|
3815
3902
|
...this.buildQueueOwnerTtlArgs()
|
|
3816
3903
|
];
|
|
3817
3904
|
if (input.agentCommand) {
|
|
@@ -3888,8 +3975,9 @@ async function runStreamingPrompt(command, args, onEvent, options = {}) {
|
|
|
3888
3975
|
const spawnPrompt = options.spawnPrompt ?? ((spawnCommand, spawnArgs) => spawn4(spawnCommand, spawnArgs, { stdio: ["ignore", "pipe", "pipe"] }));
|
|
3889
3976
|
const setIntervalFn = options.setIntervalFn ?? ((fn, delay) => setInterval(fn, delay));
|
|
3890
3977
|
const clearIntervalFn = options.clearIntervalFn ?? ((timer) => clearInterval(timer));
|
|
3891
|
-
const
|
|
3892
|
-
const
|
|
3978
|
+
const rawStream = options.rawStream ?? false;
|
|
3979
|
+
const maxSegmentWaitMs = options.maxSegmentWaitMs ?? (rawStream ? 200 : 30000);
|
|
3980
|
+
const flushCheckIntervalMs = options.flushCheckIntervalMs ?? (rawStream ? 80 : 5000);
|
|
3893
3981
|
const now = options.now ?? (() => Date.now());
|
|
3894
3982
|
return await new Promise((resolve, reject) => {
|
|
3895
3983
|
const child = spawnPrompt(command, args);
|
|
@@ -3898,12 +3986,14 @@ async function runStreamingPrompt(command, args, onEvent, options = {}) {
|
|
|
3898
3986
|
const toolEventMode = options.toolEventMode ?? "text";
|
|
3899
3987
|
const state = createStreamingPromptState(options.formatToolCalls ?? false, {
|
|
3900
3988
|
mode: toolEventMode,
|
|
3989
|
+
rawStream,
|
|
3901
3990
|
...onEvent && (toolEventMode === "structured" || toolEventMode === "both") ? { onToolEvent: (toolEvent) => onEvent({ type: "prompt.tool_event", event: toolEvent }) } : {},
|
|
3902
|
-
...onEvent ? { onThought: (chunk) => onEvent({ type: "prompt.thought", text: chunk }) } : {}
|
|
3991
|
+
...onEvent ? { onThought: (chunk) => onEvent({ type: "prompt.thought", text: chunk }) } : {},
|
|
3992
|
+
...onEvent ? { onPlan: (entries) => onEvent({ type: "prompt.plan", entries }) } : {}
|
|
3903
3993
|
});
|
|
3904
3994
|
let lastReplyAt = now();
|
|
3905
3995
|
const flushBuffer = () => {
|
|
3906
|
-
const remaining = state.buffer.trim();
|
|
3996
|
+
const remaining = rawStream ? state.buffer : state.buffer.trim();
|
|
3907
3997
|
if (remaining.length > 0) {
|
|
3908
3998
|
state.buffer = "";
|
|
3909
3999
|
onEvent?.({ type: "prompt.segment", text: remaining });
|
|
@@ -4020,6 +4110,8 @@ var BRIDGE_METHODS = new Set([
|
|
|
4020
4110
|
"resumeAgentSession",
|
|
4021
4111
|
"prompt",
|
|
4022
4112
|
"setMode",
|
|
4113
|
+
"setModel",
|
|
4114
|
+
"getSessionModel",
|
|
4023
4115
|
"cancel",
|
|
4024
4116
|
"removeSession",
|
|
4025
4117
|
"getAgentSessionId"
|
|
@@ -4031,6 +4123,8 @@ var SESSION_SCOPED_METHODS = new Set([
|
|
|
4031
4123
|
"resumeAgentSession",
|
|
4032
4124
|
"prompt",
|
|
4033
4125
|
"setMode",
|
|
4126
|
+
"setModel",
|
|
4127
|
+
"getSessionModel",
|
|
4034
4128
|
"cancel",
|
|
4035
4129
|
"removeSession",
|
|
4036
4130
|
"getAgentSessionId"
|
|
@@ -4127,6 +4221,7 @@ class BridgeServer {
|
|
|
4127
4221
|
agentCommand: asOptionalString(params.agentCommand),
|
|
4128
4222
|
cwd: requireString(params, "cwd"),
|
|
4129
4223
|
name: requireString(params, "name"),
|
|
4224
|
+
model: asOptionalString(params.model),
|
|
4130
4225
|
mcpCoordinatorSession: asOptionalString(params.mcpCoordinatorSession),
|
|
4131
4226
|
mcpSourceHandle: asOptionalString(params.mcpSourceHandle)
|
|
4132
4227
|
}, (progress) => {
|
|
@@ -4152,6 +4247,7 @@ class BridgeServer {
|
|
|
4152
4247
|
agentCommand: asOptionalString(params.agentCommand),
|
|
4153
4248
|
cwd: requireString(params, "cwd"),
|
|
4154
4249
|
name: requireString(params, "name"),
|
|
4250
|
+
model: asOptionalString(params.model),
|
|
4155
4251
|
mcpCoordinatorSession: asOptionalString(params.mcpCoordinatorSession),
|
|
4156
4252
|
mcpSourceHandle: asOptionalString(params.mcpSourceHandle),
|
|
4157
4253
|
text: requirePromptText(params, media),
|
|
@@ -4178,6 +4274,12 @@ class BridgeServer {
|
|
|
4178
4274
|
event: "prompt.thought",
|
|
4179
4275
|
text: event.text
|
|
4180
4276
|
}));
|
|
4277
|
+
} else if (event.type === "prompt.plan") {
|
|
4278
|
+
writeLine?.(encodeBridgePromptPlanEvent({
|
|
4279
|
+
id: requestId,
|
|
4280
|
+
event: "prompt.plan",
|
|
4281
|
+
entries: event.entries
|
|
4282
|
+
}));
|
|
4181
4283
|
}
|
|
4182
4284
|
});
|
|
4183
4285
|
case "resumeAgentSession":
|
|
@@ -4196,6 +4298,21 @@ class BridgeServer {
|
|
|
4196
4298
|
name: requireString(params, "name"),
|
|
4197
4299
|
modeId: requireString(params, "modeId")
|
|
4198
4300
|
});
|
|
4301
|
+
case "setModel":
|
|
4302
|
+
return await this.runtime.setModel({
|
|
4303
|
+
agent: requireString(params, "agent"),
|
|
4304
|
+
agentCommand: asOptionalString(params.agentCommand),
|
|
4305
|
+
cwd: requireString(params, "cwd"),
|
|
4306
|
+
name: requireString(params, "name"),
|
|
4307
|
+
modelId: requireString(params, "modelId")
|
|
4308
|
+
});
|
|
4309
|
+
case "getSessionModel":
|
|
4310
|
+
return await this.runtime.getSessionModel({
|
|
4311
|
+
agent: requireString(params, "agent"),
|
|
4312
|
+
agentCommand: asOptionalString(params.agentCommand),
|
|
4313
|
+
cwd: requireString(params, "cwd"),
|
|
4314
|
+
name: requireString(params, "name")
|
|
4315
|
+
});
|
|
4199
4316
|
case "cancel":
|
|
4200
4317
|
return await this.runtime.cancel({
|
|
4201
4318
|
agent: requireString(params, "agent"),
|
package/dist/channels/types.d.ts
CHANGED
|
@@ -7,6 +7,7 @@ import type { PerfTracer } from "../perf/perf-tracer.js";
|
|
|
7
7
|
import type { SessionService } from "../sessions/session-service.js";
|
|
8
8
|
import type { ActiveTurnRegistry } from "../sessions/active-turn-registry.js";
|
|
9
9
|
import type { Locale } from "../i18n/index.js";
|
|
10
|
+
import type { ControlService } from "../control/control-service.js";
|
|
10
11
|
export type { ChatAgent };
|
|
11
12
|
export interface OutboundQuota {
|
|
12
13
|
onInbound(chatKey: string): void;
|
|
@@ -44,6 +45,7 @@ export interface ScheduledChannelMessageInput {
|
|
|
44
45
|
sessionDescriptor?: ScheduledSessionDescriptor;
|
|
45
46
|
accountId?: string;
|
|
46
47
|
replyContextToken?: string;
|
|
48
|
+
executeAt?: string;
|
|
47
49
|
noticeText: string;
|
|
48
50
|
promptText: string;
|
|
49
51
|
abortSignal?: AbortSignal;
|
|
@@ -71,6 +73,12 @@ export interface ChannelStartInput {
|
|
|
71
73
|
* the active locale via `getLocale()` from `xacpx/plugin-api`.
|
|
72
74
|
*/
|
|
73
75
|
locale?: Locale;
|
|
76
|
+
/**
|
|
77
|
+
* Structured control facade (sessions / prompt / scheduler / orchestration)
|
|
78
|
+
* for structured consumers such as the relay connector. Optional: text-only
|
|
79
|
+
* channels ignore it.
|
|
80
|
+
*/
|
|
81
|
+
control?: ControlService;
|
|
74
82
|
}
|
|
75
83
|
export interface OrchestrationDeliveryCallbacks {
|
|
76
84
|
markTaskNoticeDelivered: (taskId: string, accountId: string) => Promise<void>;
|
|
@@ -140,3 +148,11 @@ export interface ToolUseEvent {
|
|
|
140
148
|
/** Set when status transitions out of "running". */
|
|
141
149
|
durationMs?: number;
|
|
142
150
|
}
|
|
151
|
+
export type PlanEntryStatus = "pending" | "in_progress" | "completed";
|
|
152
|
+
/** One entry of the agent's ACP `plan` (its live todo list). The agent re-sends the
|
|
153
|
+
* WHOLE list on each update, so consumers REPLACE rather than append. */
|
|
154
|
+
export interface PlanEntry {
|
|
155
|
+
content: string;
|
|
156
|
+
status: PlanEntryStatus;
|
|
157
|
+
priority?: "high" | "medium" | "low";
|
|
158
|
+
}
|