@ganglion/xacpx 0.10.1 → 0.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/README.md +20 -0
- package/dist/bridge/bridge-main.js +148 -9
- package/dist/channels/types.d.ts +16 -0
- package/dist/cli.js +1759 -371
- package/dist/commands/handlers/agent-handler.d.ts +1 -1
- package/dist/commands/handlers/session-handler.d.ts +13 -4
- package/dist/commands/parse-command.d.ts +7 -0
- package/dist/commands/router-types.d.ts +10 -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 +65 -0
- package/dist/control/control-service.d.ts +147 -0
- package/dist/control/workspace-fs.d.ts +64 -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 +37 -1
- package/dist/weixin/agent/interface.d.ts +8 -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,14 @@ function encodeBridgePromptThoughtEvent(event) {
|
|
|
64
64
|
return `${JSON.stringify(event)}
|
|
65
65
|
`;
|
|
66
66
|
}
|
|
67
|
+
function encodeBridgePromptPlanEvent(event) {
|
|
68
|
+
return `${JSON.stringify(event)}
|
|
69
|
+
`;
|
|
70
|
+
}
|
|
71
|
+
function encodeBridgePromptUsageEvent(event) {
|
|
72
|
+
return `${JSON.stringify(event)}
|
|
73
|
+
`;
|
|
74
|
+
}
|
|
67
75
|
function encodeBridgeSessionProgressEvent(event) {
|
|
68
76
|
return `${JSON.stringify(event)}
|
|
69
77
|
`;
|
|
@@ -419,6 +427,9 @@ function createStreamingPromptState(formatToolCalls = false, options) {
|
|
|
419
427
|
let toolEventMode;
|
|
420
428
|
let onToolEvent;
|
|
421
429
|
let onThought;
|
|
430
|
+
let onPlan;
|
|
431
|
+
let onUsage;
|
|
432
|
+
let rawStream = false;
|
|
422
433
|
if (options === undefined) {
|
|
423
434
|
toolEventMode = "text";
|
|
424
435
|
onToolEvent = undefined;
|
|
@@ -428,6 +439,9 @@ function createStreamingPromptState(formatToolCalls = false, options) {
|
|
|
428
439
|
} else {
|
|
429
440
|
onToolEvent = options.onToolEvent;
|
|
430
441
|
onThought = options.onThought;
|
|
442
|
+
onPlan = options.onPlan;
|
|
443
|
+
onUsage = options.onUsage;
|
|
444
|
+
rawStream = options.rawStream ?? false;
|
|
431
445
|
toolEventMode = resolveToolEventMode({
|
|
432
446
|
toolEventMode: options.mode,
|
|
433
447
|
onToolEvent
|
|
@@ -441,13 +455,16 @@ function createStreamingPromptState(formatToolCalls = false, options) {
|
|
|
441
455
|
formatToolCalls,
|
|
442
456
|
emittedToolCallIds: new Set,
|
|
443
457
|
toolEventMode,
|
|
458
|
+
rawStream,
|
|
444
459
|
onToolEvent,
|
|
445
460
|
onThought,
|
|
461
|
+
onPlan,
|
|
462
|
+
onUsage,
|
|
446
463
|
finalize() {
|
|
447
464
|
if (this.pendingLine.trim().length > 0) {
|
|
448
465
|
parseStreamingChunks(this, this.pendingLine);
|
|
449
466
|
}
|
|
450
|
-
const remaining = this.buffer.trim();
|
|
467
|
+
const remaining = this.rawStream ? this.buffer : this.buffer.trim();
|
|
451
468
|
this.buffer = "";
|
|
452
469
|
this.pendingLine = "";
|
|
453
470
|
return remaining;
|
|
@@ -479,9 +496,9 @@ function parseStreamingChunks(state, line) {
|
|
|
479
496
|
const update = event.params?.update;
|
|
480
497
|
if (!update)
|
|
481
498
|
return;
|
|
482
|
-
if (
|
|
499
|
+
if (update.sessionUpdate === "tool_call" || update.sessionUpdate === "tool_call_update") {
|
|
483
500
|
const wantsStructured = state.toolEventMode === "structured" || state.toolEventMode === "both";
|
|
484
|
-
const wantsText = state.toolEventMode === "text" || state.toolEventMode === "both";
|
|
501
|
+
const wantsText = (state.toolEventMode === "text" || state.toolEventMode === "both") && state.formatToolCalls;
|
|
485
502
|
if (wantsStructured && state.onToolEvent) {
|
|
486
503
|
const toolEvent = buildToolUseEvent(update);
|
|
487
504
|
if (toolEvent)
|
|
@@ -501,6 +518,19 @@ function parseStreamingChunks(state, line) {
|
|
|
501
518
|
}
|
|
502
519
|
return;
|
|
503
520
|
}
|
|
521
|
+
if (update.sessionUpdate === "plan") {
|
|
522
|
+
const entries = Array.isArray(update.entries) ? update.entries.filter((x) => !!x && typeof x === "object" && typeof x.content === "string" && typeof x.status === "string") : [];
|
|
523
|
+
if (entries.length > 0)
|
|
524
|
+
state.onPlan?.(entries);
|
|
525
|
+
return;
|
|
526
|
+
}
|
|
527
|
+
if (update.sessionUpdate === "usage_update") {
|
|
528
|
+
const used = typeof update.used === "number" && Number.isFinite(update.used) ? update.used : undefined;
|
|
529
|
+
const size = typeof update.size === "number" && Number.isFinite(update.size) ? update.size : undefined;
|
|
530
|
+
if (used !== undefined && size !== undefined && size > 0)
|
|
531
|
+
state.onUsage?.({ used, size });
|
|
532
|
+
return;
|
|
533
|
+
}
|
|
504
534
|
const isThoughtChunk = update.sessionUpdate === "agent_thought_chunk" && update.content?.type === "text" && typeof update.content.text === "string";
|
|
505
535
|
if (isThoughtChunk) {
|
|
506
536
|
const chunk2 = update.content.text;
|
|
@@ -517,6 +547,8 @@ function parseStreamingChunks(state, line) {
|
|
|
517
547
|
if (chunk.length === 0)
|
|
518
548
|
return;
|
|
519
549
|
state.buffer += chunk;
|
|
550
|
+
if (state.rawStream)
|
|
551
|
+
return;
|
|
520
552
|
let boundary;
|
|
521
553
|
while ((boundary = state.buffer.indexOf(`
|
|
522
554
|
|
|
@@ -882,6 +914,14 @@ var init_session = __esm(() => {
|
|
|
882
914
|
modeModeLabel: (modeId) => `- mode: ${modeId}`,
|
|
883
915
|
modeNotSet: "not set",
|
|
884
916
|
modeSet: (modeId) => `Current session mode set to: ${modeId}`,
|
|
917
|
+
modelHeader: "Current model:",
|
|
918
|
+
modelSessionLabel: (alias) => `- Session: ${alias}`,
|
|
919
|
+
modelModelLabel: (modelId) => `- model: ${modelId}`,
|
|
920
|
+
modelNotSet: "not set (using agent default)",
|
|
921
|
+
modelAvailableLabel: (models) => `- available: ${models}`,
|
|
922
|
+
modelSet: (modelId) => `Current session model switched to: ${modelId}`,
|
|
923
|
+
modelSetFailed: (modelId, detail) => `Failed to switch model: ${modelId}
|
|
924
|
+
${detail}`,
|
|
885
925
|
replyModeHeader: "Current reply mode:",
|
|
886
926
|
replyModeSessionLabel: (alias) => `- Session: ${alias}`,
|
|
887
927
|
replyModeGlobalDefault: (value) => `- Global default: ${value}`,
|
|
@@ -958,6 +998,11 @@ var init_session = __esm(() => {
|
|
|
958
998
|
modeHelpCmdShowDesc: "Show the saved mode of the current session",
|
|
959
999
|
modeHelpCmdSet: "/mode <id>",
|
|
960
1000
|
modeHelpCmdSetDesc: "Set the current session mode",
|
|
1001
|
+
modelHelpSummary: "View or switch the LLM model for the current session.",
|
|
1002
|
+
modelHelpCmdShow: "/model",
|
|
1003
|
+
modelHelpCmdShowDesc: "Show the current session model and the available ones",
|
|
1004
|
+
modelHelpCmdSet: "/model <id>",
|
|
1005
|
+
modelHelpCmdSetDesc: "Switch the current session model (e.g. gpt-5.2[high])",
|
|
961
1006
|
replyModeHelpSummary: "View or set the reply output mode for the current logical session.",
|
|
962
1007
|
replyModeHelpCmdShow: "/replymode",
|
|
963
1008
|
replyModeHelpCmdShowDesc: "Show global default, current override, and effective value",
|
|
@@ -1961,6 +2006,14 @@ var init_session2 = __esm(() => {
|
|
|
1961
2006
|
modeModeLabel: (modeId) => `- mode:${modeId}`,
|
|
1962
2007
|
modeNotSet: "未设置",
|
|
1963
2008
|
modeSet: (modeId) => `已设置当前会话 mode:${modeId}`,
|
|
2009
|
+
modelHeader: "当前 model:",
|
|
2010
|
+
modelSessionLabel: (alias) => `- 会话:${alias}`,
|
|
2011
|
+
modelModelLabel: (modelId) => `- model:${modelId}`,
|
|
2012
|
+
modelNotSet: "未设置(使用 agent 默认)",
|
|
2013
|
+
modelAvailableLabel: (models) => `- 可选:${models}`,
|
|
2014
|
+
modelSet: (modelId) => `已切换当前会话 model:${modelId}`,
|
|
2015
|
+
modelSetFailed: (modelId, detail) => `切换 model 失败:${modelId}
|
|
2016
|
+
${detail}`,
|
|
1964
2017
|
replyModeHeader: "当前 reply mode:",
|
|
1965
2018
|
replyModeSessionLabel: (alias) => `- 会话:${alias}`,
|
|
1966
2019
|
replyModeGlobalDefault: (value) => `- 全局默认:${value}`,
|
|
@@ -2037,6 +2090,11 @@ var init_session2 = __esm(() => {
|
|
|
2037
2090
|
modeHelpCmdShowDesc: "查看当前会话已保存的 mode",
|
|
2038
2091
|
modeHelpCmdSet: "/mode <id>",
|
|
2039
2092
|
modeHelpCmdSetDesc: "设置当前会话 mode",
|
|
2093
|
+
modelHelpSummary: "查看或切换当前会话的 LLM model。",
|
|
2094
|
+
modelHelpCmdShow: "/model",
|
|
2095
|
+
modelHelpCmdShowDesc: "查看当前会话 model 及可选项",
|
|
2096
|
+
modelHelpCmdSet: "/model <id>",
|
|
2097
|
+
modelHelpCmdSetDesc: "切换当前会话 model(如 gpt-5.2[high])",
|
|
2040
2098
|
replyModeHelpSummary: "查看或设置当前逻辑会话的回复输出模式。",
|
|
2041
2099
|
replyModeHelpCmdShow: "/replymode",
|
|
2042
2100
|
replyModeHelpCmdShowDesc: "查看全局默认、当前覆盖和实际生效值",
|
|
@@ -3123,6 +3181,7 @@ class AcpxQueueOwnerLauncher {
|
|
|
3123
3181
|
nonInteractivePermissions: input.nonInteractivePermissions,
|
|
3124
3182
|
ttlMs: this.ttlMs,
|
|
3125
3183
|
maxQueueDepth: this.maxQueueDepth,
|
|
3184
|
+
...input.sessionOptions ? { sessionOptions: input.sessionOptions } : {},
|
|
3126
3185
|
mcpServers: [buildXacpxMcpServerSpec({
|
|
3127
3186
|
xacpxCommand: this.xacpxCommand,
|
|
3128
3187
|
coordinatorSession: input.coordinatorSession,
|
|
@@ -3473,6 +3532,10 @@ class CommandTimeoutError extends Error {
|
|
|
3473
3532
|
this.name = "CommandTimeoutError";
|
|
3474
3533
|
}
|
|
3475
3534
|
}
|
|
3535
|
+
function modelArgs(model) {
|
|
3536
|
+
const trimmed = model?.trim();
|
|
3537
|
+
return trimmed ? ["--model", trimmed] : [];
|
|
3538
|
+
}
|
|
3476
3539
|
|
|
3477
3540
|
class BridgeRuntime {
|
|
3478
3541
|
command;
|
|
@@ -3682,11 +3745,13 @@ class BridgeRuntime {
|
|
|
3682
3745
|
...structuredPrompt ? ["--file", structuredPrompt.filePath] : [input.text]
|
|
3683
3746
|
]));
|
|
3684
3747
|
const formatToolCalls = (input.replyMode ?? "verbose") === "verbose";
|
|
3748
|
+
const rawStream = input.replyMode === "stream";
|
|
3685
3749
|
const toolEventMode = input.toolEventMode ?? (input.toolEvents === true ? "structured" : "text");
|
|
3686
3750
|
try {
|
|
3687
3751
|
const result = onEvent ? await this.runPromptCommand(spawnSpec.command, spawnSpec.args, onEvent, {
|
|
3688
3752
|
formatToolCalls,
|
|
3689
|
-
toolEventMode
|
|
3753
|
+
toolEventMode,
|
|
3754
|
+
rawStream
|
|
3690
3755
|
}) : await this.run(spawnSpec.command, spawnSpec.args);
|
|
3691
3756
|
return { text: getPromptText(result) };
|
|
3692
3757
|
} finally {
|
|
@@ -3755,6 +3820,40 @@ class BridgeRuntime {
|
|
|
3755
3820
|
}
|
|
3756
3821
|
return {};
|
|
3757
3822
|
}
|
|
3823
|
+
async setModel(input) {
|
|
3824
|
+
const spawnSpec = resolveSpawnCommand(this.command, this.buildSessionArgs({ ...input, model: input.modelId }, [
|
|
3825
|
+
"set",
|
|
3826
|
+
"-s",
|
|
3827
|
+
input.name,
|
|
3828
|
+
"model",
|
|
3829
|
+
input.modelId
|
|
3830
|
+
]));
|
|
3831
|
+
const result = await this.run(spawnSpec.command, spawnSpec.args);
|
|
3832
|
+
if (result.code !== 0) {
|
|
3833
|
+
throw new Error(result.stderr || result.stdout || "set-model failed");
|
|
3834
|
+
}
|
|
3835
|
+
return {};
|
|
3836
|
+
}
|
|
3837
|
+
async getSessionModel(input) {
|
|
3838
|
+
const spawnSpec = resolveSpawnCommand(this.command, this.buildSessionArgs(input, [
|
|
3839
|
+
"status",
|
|
3840
|
+
"-s",
|
|
3841
|
+
input.name
|
|
3842
|
+
], { format: "json" }));
|
|
3843
|
+
const result = await this.run(spawnSpec.command, spawnSpec.args);
|
|
3844
|
+
if (result.code !== 0) {
|
|
3845
|
+
throw new Error(result.stderr || result.stdout || "status failed");
|
|
3846
|
+
}
|
|
3847
|
+
try {
|
|
3848
|
+
const json = JSON.parse(result.stdout);
|
|
3849
|
+
return {
|
|
3850
|
+
current: typeof json.model === "string" ? json.model : undefined,
|
|
3851
|
+
available: Array.isArray(json.availableModels) ? json.availableModels.filter((m) => typeof m === "string") : []
|
|
3852
|
+
};
|
|
3853
|
+
} catch {
|
|
3854
|
+
return { available: [] };
|
|
3855
|
+
}
|
|
3856
|
+
}
|
|
3758
3857
|
async cancel(input) {
|
|
3759
3858
|
const spawnSpec = resolveSpawnCommand(this.command, this.buildSessionArgs(input, [
|
|
3760
3859
|
"cancel",
|
|
@@ -3794,7 +3893,8 @@ class BridgeRuntime {
|
|
|
3794
3893
|
options.format ?? "quiet",
|
|
3795
3894
|
"--cwd",
|
|
3796
3895
|
input.cwd,
|
|
3797
|
-
...this.buildPermissionArgs()
|
|
3896
|
+
...this.buildPermissionArgs(),
|
|
3897
|
+
...modelArgs(input.model)
|
|
3798
3898
|
];
|
|
3799
3899
|
if (options.verbose) {
|
|
3800
3900
|
prefix.push("--verbose");
|
|
@@ -3812,6 +3912,7 @@ class BridgeRuntime {
|
|
|
3812
3912
|
"--cwd",
|
|
3813
3913
|
input.cwd,
|
|
3814
3914
|
...this.buildPermissionArgs(),
|
|
3915
|
+
...modelArgs(input.model),
|
|
3815
3916
|
...this.buildQueueOwnerTtlArgs()
|
|
3816
3917
|
];
|
|
3817
3918
|
if (input.agentCommand) {
|
|
@@ -3888,8 +3989,9 @@ async function runStreamingPrompt(command, args, onEvent, options = {}) {
|
|
|
3888
3989
|
const spawnPrompt = options.spawnPrompt ?? ((spawnCommand, spawnArgs) => spawn4(spawnCommand, spawnArgs, { stdio: ["ignore", "pipe", "pipe"] }));
|
|
3889
3990
|
const setIntervalFn = options.setIntervalFn ?? ((fn, delay) => setInterval(fn, delay));
|
|
3890
3991
|
const clearIntervalFn = options.clearIntervalFn ?? ((timer) => clearInterval(timer));
|
|
3891
|
-
const
|
|
3892
|
-
const
|
|
3992
|
+
const rawStream = options.rawStream ?? false;
|
|
3993
|
+
const maxSegmentWaitMs = options.maxSegmentWaitMs ?? (rawStream ? 200 : 30000);
|
|
3994
|
+
const flushCheckIntervalMs = options.flushCheckIntervalMs ?? (rawStream ? 80 : 5000);
|
|
3893
3995
|
const now = options.now ?? (() => Date.now());
|
|
3894
3996
|
return await new Promise((resolve, reject) => {
|
|
3895
3997
|
const child = spawnPrompt(command, args);
|
|
@@ -3898,12 +4000,15 @@ async function runStreamingPrompt(command, args, onEvent, options = {}) {
|
|
|
3898
4000
|
const toolEventMode = options.toolEventMode ?? "text";
|
|
3899
4001
|
const state = createStreamingPromptState(options.formatToolCalls ?? false, {
|
|
3900
4002
|
mode: toolEventMode,
|
|
4003
|
+
rawStream,
|
|
3901
4004
|
...onEvent && (toolEventMode === "structured" || toolEventMode === "both") ? { onToolEvent: (toolEvent) => onEvent({ type: "prompt.tool_event", event: toolEvent }) } : {},
|
|
3902
|
-
...onEvent ? { onThought: (chunk) => onEvent({ type: "prompt.thought", text: chunk }) } : {}
|
|
4005
|
+
...onEvent ? { onThought: (chunk) => onEvent({ type: "prompt.thought", text: chunk }) } : {},
|
|
4006
|
+
...onEvent ? { onPlan: (entries) => onEvent({ type: "prompt.plan", entries }) } : {},
|
|
4007
|
+
...onEvent ? { onUsage: (usage) => onEvent({ type: "prompt.usage", used: usage.used, size: usage.size }) } : {}
|
|
3903
4008
|
});
|
|
3904
4009
|
let lastReplyAt = now();
|
|
3905
4010
|
const flushBuffer = () => {
|
|
3906
|
-
const remaining = state.buffer.trim();
|
|
4011
|
+
const remaining = rawStream ? state.buffer : state.buffer.trim();
|
|
3907
4012
|
if (remaining.length > 0) {
|
|
3908
4013
|
state.buffer = "";
|
|
3909
4014
|
onEvent?.({ type: "prompt.segment", text: remaining });
|
|
@@ -4020,6 +4125,8 @@ var BRIDGE_METHODS = new Set([
|
|
|
4020
4125
|
"resumeAgentSession",
|
|
4021
4126
|
"prompt",
|
|
4022
4127
|
"setMode",
|
|
4128
|
+
"setModel",
|
|
4129
|
+
"getSessionModel",
|
|
4023
4130
|
"cancel",
|
|
4024
4131
|
"removeSession",
|
|
4025
4132
|
"getAgentSessionId"
|
|
@@ -4031,6 +4138,8 @@ var SESSION_SCOPED_METHODS = new Set([
|
|
|
4031
4138
|
"resumeAgentSession",
|
|
4032
4139
|
"prompt",
|
|
4033
4140
|
"setMode",
|
|
4141
|
+
"setModel",
|
|
4142
|
+
"getSessionModel",
|
|
4034
4143
|
"cancel",
|
|
4035
4144
|
"removeSession",
|
|
4036
4145
|
"getAgentSessionId"
|
|
@@ -4127,6 +4236,7 @@ class BridgeServer {
|
|
|
4127
4236
|
agentCommand: asOptionalString(params.agentCommand),
|
|
4128
4237
|
cwd: requireString(params, "cwd"),
|
|
4129
4238
|
name: requireString(params, "name"),
|
|
4239
|
+
model: asOptionalString(params.model),
|
|
4130
4240
|
mcpCoordinatorSession: asOptionalString(params.mcpCoordinatorSession),
|
|
4131
4241
|
mcpSourceHandle: asOptionalString(params.mcpSourceHandle)
|
|
4132
4242
|
}, (progress) => {
|
|
@@ -4152,6 +4262,7 @@ class BridgeServer {
|
|
|
4152
4262
|
agentCommand: asOptionalString(params.agentCommand),
|
|
4153
4263
|
cwd: requireString(params, "cwd"),
|
|
4154
4264
|
name: requireString(params, "name"),
|
|
4265
|
+
model: asOptionalString(params.model),
|
|
4155
4266
|
mcpCoordinatorSession: asOptionalString(params.mcpCoordinatorSession),
|
|
4156
4267
|
mcpSourceHandle: asOptionalString(params.mcpSourceHandle),
|
|
4157
4268
|
text: requirePromptText(params, media),
|
|
@@ -4178,6 +4289,19 @@ class BridgeServer {
|
|
|
4178
4289
|
event: "prompt.thought",
|
|
4179
4290
|
text: event.text
|
|
4180
4291
|
}));
|
|
4292
|
+
} else if (event.type === "prompt.plan") {
|
|
4293
|
+
writeLine?.(encodeBridgePromptPlanEvent({
|
|
4294
|
+
id: requestId,
|
|
4295
|
+
event: "prompt.plan",
|
|
4296
|
+
entries: event.entries
|
|
4297
|
+
}));
|
|
4298
|
+
} else if (event.type === "prompt.usage") {
|
|
4299
|
+
writeLine?.(encodeBridgePromptUsageEvent({
|
|
4300
|
+
id: requestId,
|
|
4301
|
+
event: "prompt.usage",
|
|
4302
|
+
used: event.used,
|
|
4303
|
+
size: event.size
|
|
4304
|
+
}));
|
|
4181
4305
|
}
|
|
4182
4306
|
});
|
|
4183
4307
|
case "resumeAgentSession":
|
|
@@ -4196,6 +4320,21 @@ class BridgeServer {
|
|
|
4196
4320
|
name: requireString(params, "name"),
|
|
4197
4321
|
modeId: requireString(params, "modeId")
|
|
4198
4322
|
});
|
|
4323
|
+
case "setModel":
|
|
4324
|
+
return await this.runtime.setModel({
|
|
4325
|
+
agent: requireString(params, "agent"),
|
|
4326
|
+
agentCommand: asOptionalString(params.agentCommand),
|
|
4327
|
+
cwd: requireString(params, "cwd"),
|
|
4328
|
+
name: requireString(params, "name"),
|
|
4329
|
+
modelId: requireString(params, "modelId")
|
|
4330
|
+
});
|
|
4331
|
+
case "getSessionModel":
|
|
4332
|
+
return await this.runtime.getSessionModel({
|
|
4333
|
+
agent: requireString(params, "agent"),
|
|
4334
|
+
agentCommand: asOptionalString(params.agentCommand),
|
|
4335
|
+
cwd: requireString(params, "cwd"),
|
|
4336
|
+
name: requireString(params, "name")
|
|
4337
|
+
});
|
|
4199
4338
|
case "cancel":
|
|
4200
4339
|
return await this.runtime.cancel({
|
|
4201
4340
|
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
|
+
}
|