@vibearound/plugin-channel-sdk 0.1.2 → 0.4.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 +62 -108
- package/dist/advanced.d.ts +19 -0
- package/dist/advanced.d.ts.map +1 -0
- package/dist/advanced.js +18 -0
- package/dist/advanced.js.map +1 -0
- package/dist/connection.d.ts +10 -4
- package/dist/connection.d.ts.map +1 -1
- package/dist/connection.js +10 -4
- package/dist/connection.js.map +1 -1
- package/dist/errors.d.ts +16 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +33 -0
- package/dist/errors.js.map +1 -0
- package/dist/index.d.ts +27 -41
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +30 -41
- package/dist/index.js.map +1 -1
- package/dist/plugin.d.ts +80 -0
- package/dist/plugin.d.ts.map +1 -0
- package/dist/plugin.js +131 -0
- package/dist/plugin.js.map +1 -0
- package/dist/renderer.d.ts +52 -46
- package/dist/renderer.d.ts.map +1 -1
- package/dist/renderer.js +131 -88
- package/dist/renderer.js.map +1 -1
- package/dist/types.d.ts +19 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +5 -1
- package/src/advanced.ts +43 -0
- package/src/connection.ts +10 -4
- package/src/errors.ts +29 -0
- package/src/index.ts +48 -52
- package/src/plugin.ts +247 -0
- package/src/renderer.ts +199 -94
- package/src/types.ts +24 -0
package/dist/plugin.d.ts
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* runChannelPlugin — the SDK entry point for every channel plugin.
|
|
3
|
+
*
|
|
4
|
+
* Handles the full ACP lifecycle: connect to host, validate config, create
|
|
5
|
+
* bot + renderer, start the bot, then await disconnect and stop. The plugin
|
|
6
|
+
* only implements platform-specific transport (sendText, sendBlock, editBlock).
|
|
7
|
+
*
|
|
8
|
+
* ## Usage
|
|
9
|
+
*
|
|
10
|
+
* ```ts
|
|
11
|
+
* import { runChannelPlugin } from "@vibearound/plugin-channel-sdk";
|
|
12
|
+
*
|
|
13
|
+
* runChannelPlugin({
|
|
14
|
+
* name: "vibearound-slack",
|
|
15
|
+
* version: "0.1.0",
|
|
16
|
+
* requiredConfig: ["bot_token", "app_token"],
|
|
17
|
+
* createBot: ({ config, agent, log, cacheDir }) =>
|
|
18
|
+
* new SlackBot({ ... }, agent, log, cacheDir),
|
|
19
|
+
* createRenderer: (bot, log, verbose) =>
|
|
20
|
+
* new SlackRenderer(bot, log, verbose),
|
|
21
|
+
* });
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
import type { Agent } from "@agentclientprotocol/sdk";
|
|
25
|
+
import { BlockRenderer } from "./renderer.js";
|
|
26
|
+
export type ChannelPluginLogger = (level: string, msg: string) => void;
|
|
27
|
+
/**
|
|
28
|
+
* The platform bot — handles IM connectivity and message transport.
|
|
29
|
+
*
|
|
30
|
+
* Plugins implement this interface on their bot class. The SDK calls these
|
|
31
|
+
* methods during the plugin lifecycle.
|
|
32
|
+
*/
|
|
33
|
+
export interface ChannelBot<TRenderer extends BlockRenderer<any> = BlockRenderer<any>> {
|
|
34
|
+
/** Wire the renderer to receive streaming events. */
|
|
35
|
+
setStreamHandler(handler: TRenderer): void;
|
|
36
|
+
/** Connect to the IM platform and start receiving messages. */
|
|
37
|
+
start(): Promise<void> | void;
|
|
38
|
+
/** Disconnect and clean up. */
|
|
39
|
+
stop(): Promise<void> | void;
|
|
40
|
+
}
|
|
41
|
+
export interface CreateBotContext {
|
|
42
|
+
config: Record<string, unknown>;
|
|
43
|
+
agent: Agent;
|
|
44
|
+
log: ChannelPluginLogger;
|
|
45
|
+
cacheDir: string;
|
|
46
|
+
}
|
|
47
|
+
export interface VerboseOptions {
|
|
48
|
+
showThinking: boolean;
|
|
49
|
+
showToolUse: boolean;
|
|
50
|
+
}
|
|
51
|
+
export interface RunChannelPluginSpec<TBot extends ChannelBot<TRenderer>, TRenderer extends BlockRenderer<any>> {
|
|
52
|
+
/** Plugin name reported during ACP initialize (e.g. "vibearound-slack"). */
|
|
53
|
+
name: string;
|
|
54
|
+
/** Plugin version reported during ACP initialize. */
|
|
55
|
+
version: string;
|
|
56
|
+
/**
|
|
57
|
+
* Config keys that MUST be present. Plugin fails fast if any are missing.
|
|
58
|
+
*/
|
|
59
|
+
requiredConfig?: string[];
|
|
60
|
+
/** Factory: build the platform bot. */
|
|
61
|
+
createBot: (ctx: CreateBotContext) => TBot | Promise<TBot>;
|
|
62
|
+
/**
|
|
63
|
+
* Factory: build the renderer (extends BlockRenderer).
|
|
64
|
+
* Only implements platform-specific sendText/sendBlock/editBlock.
|
|
65
|
+
*/
|
|
66
|
+
createRenderer: (bot: TBot, log: ChannelPluginLogger, verbose: VerboseOptions) => TRenderer;
|
|
67
|
+
/**
|
|
68
|
+
* Optional hook invoked after bot constructed but before start().
|
|
69
|
+
*/
|
|
70
|
+
afterCreate?: (bot: TBot, log: ChannelPluginLogger) => Promise<void> | void;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Run a channel plugin.
|
|
74
|
+
*
|
|
75
|
+
* Handles the full ACP lifecycle: connect to host, validate config,
|
|
76
|
+
* construct bot + renderer, start the bot, then wait for the host
|
|
77
|
+
* to disconnect before stopping and exiting.
|
|
78
|
+
*/
|
|
79
|
+
export declare function runChannelPlugin<TBot extends ChannelBot<TRenderer>, TRenderer extends BlockRenderer<any>>(spec: RunChannelPluginSpec<TBot, TRenderer>): Promise<void>;
|
|
80
|
+
//# sourceMappingURL=plugin.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAIH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,0BAA0B,CAAC;AAItD,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAW9C,MAAM,MAAM,mBAAmB,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;AAEvE;;;;;GAKG;AAEH,MAAM,WAAW,UAAU,CAAC,SAAS,SAAS,aAAa,CAAC,GAAG,CAAC,GAAG,aAAa,CAAC,GAAG,CAAC;IACnF,qDAAqD;IACrD,gBAAgB,CAAC,OAAO,EAAE,SAAS,GAAG,IAAI,CAAC;IAC3C,+DAA+D;IAC/D,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IAC9B,+BAA+B;IAC/B,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;CAC9B;AAED,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAChC,KAAK,EAAE,KAAK,CAAC;IACb,GAAG,EAAE,mBAAmB,CAAC;IACzB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,cAAc;IAC7B,YAAY,EAAE,OAAO,CAAC;IACtB,WAAW,EAAE,OAAO,CAAC;CACtB;AAED,MAAM,WAAW,oBAAoB,CACnC,IAAI,SAAS,UAAU,CAAC,SAAS,CAAC,EAClC,SAAS,SAAS,aAAa,CAAC,GAAG,CAAC;IAEpC,4EAA4E;IAC5E,IAAI,EAAE,MAAM,CAAC;IAEb,qDAAqD;IACrD,OAAO,EAAE,MAAM,CAAC;IAEhB;;OAEG;IACH,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAE1B,uCAAuC;IACvC,SAAS,EAAE,CAAC,GAAG,EAAE,gBAAgB,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAE3D;;;OAGG;IACH,cAAc,EAAE,CACd,GAAG,EAAE,IAAI,EACT,GAAG,EAAE,mBAAmB,EACxB,OAAO,EAAE,cAAc,KACpB,SAAS,CAAC;IAEf;;OAEG;IACH,WAAW,CAAC,EAAE,CAAC,GAAG,EAAE,IAAI,EAAE,GAAG,EAAE,mBAAmB,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;CAC7E;AAMD;;;;;;GAMG;AACH,wBAAsB,gBAAgB,CACpC,IAAI,SAAS,UAAU,CAAC,SAAS,CAAC,EAClC,SAAS,SAAS,aAAa,CAAC,GAAG,CAAC,EACpC,IAAI,EAAE,oBAAoB,CAAC,IAAI,EAAE,SAAS,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAY5D"}
|
package/dist/plugin.js
ADDED
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* runChannelPlugin — the SDK entry point for every channel plugin.
|
|
3
|
+
*
|
|
4
|
+
* Handles the full ACP lifecycle: connect to host, validate config, create
|
|
5
|
+
* bot + renderer, start the bot, then await disconnect and stop. The plugin
|
|
6
|
+
* only implements platform-specific transport (sendText, sendBlock, editBlock).
|
|
7
|
+
*
|
|
8
|
+
* ## Usage
|
|
9
|
+
*
|
|
10
|
+
* ```ts
|
|
11
|
+
* import { runChannelPlugin } from "@vibearound/plugin-channel-sdk";
|
|
12
|
+
*
|
|
13
|
+
* runChannelPlugin({
|
|
14
|
+
* name: "vibearound-slack",
|
|
15
|
+
* version: "0.1.0",
|
|
16
|
+
* requiredConfig: ["bot_token", "app_token"],
|
|
17
|
+
* createBot: ({ config, agent, log, cacheDir }) =>
|
|
18
|
+
* new SlackBot({ ... }, agent, log, cacheDir),
|
|
19
|
+
* createRenderer: (bot, log, verbose) =>
|
|
20
|
+
* new SlackRenderer(bot, log, verbose),
|
|
21
|
+
* });
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
import os from "node:os";
|
|
25
|
+
import path from "node:path";
|
|
26
|
+
import { connectToHost, stripExtPrefix } from "./connection.js";
|
|
27
|
+
import { extractErrorMessage } from "./errors.js";
|
|
28
|
+
// ---------------------------------------------------------------------------
|
|
29
|
+
// Implementation
|
|
30
|
+
// ---------------------------------------------------------------------------
|
|
31
|
+
/**
|
|
32
|
+
* Run a channel plugin.
|
|
33
|
+
*
|
|
34
|
+
* Handles the full ACP lifecycle: connect to host, validate config,
|
|
35
|
+
* construct bot + renderer, start the bot, then wait for the host
|
|
36
|
+
* to disconnect before stopping and exiting.
|
|
37
|
+
*/
|
|
38
|
+
export async function runChannelPlugin(spec) {
|
|
39
|
+
const prefix = `[${spec.name.replace(/^vibearound-/, "")}-plugin]`;
|
|
40
|
+
const log = (level, msg) => {
|
|
41
|
+
process.stderr.write(`${prefix}[${level}] ${msg}\n`);
|
|
42
|
+
};
|
|
43
|
+
try {
|
|
44
|
+
await runInner(spec, log);
|
|
45
|
+
}
|
|
46
|
+
catch (err) {
|
|
47
|
+
log("error", `fatal: ${extractErrorMessage(err)}`);
|
|
48
|
+
process.exit(1);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
async function runInner(spec, log) {
|
|
52
|
+
log("info", "initializing ACP connection...");
|
|
53
|
+
let renderer = null;
|
|
54
|
+
const { agent, meta, agentInfo, conn } = await connectToHost({ name: spec.name, version: spec.version }, () => ({
|
|
55
|
+
async sessionUpdate(params) {
|
|
56
|
+
renderer?.onSessionUpdate(params);
|
|
57
|
+
},
|
|
58
|
+
async requestPermission(params) {
|
|
59
|
+
const first = params.options?.[0];
|
|
60
|
+
if (first) {
|
|
61
|
+
return { outcome: { outcome: "selected", optionId: first.optionId } };
|
|
62
|
+
}
|
|
63
|
+
throw new Error("No permission options provided");
|
|
64
|
+
},
|
|
65
|
+
async extNotification(method, params) {
|
|
66
|
+
const chatId = typeof params.chatId === "string" ? params.chatId : undefined;
|
|
67
|
+
switch (stripExtPrefix(method)) {
|
|
68
|
+
case "va/system_text": {
|
|
69
|
+
const text = typeof params.text === "string" ? params.text : "";
|
|
70
|
+
if (chatId && renderer) {
|
|
71
|
+
renderer.onSystemText(chatId, text);
|
|
72
|
+
}
|
|
73
|
+
break;
|
|
74
|
+
}
|
|
75
|
+
case "va/agent_ready": {
|
|
76
|
+
const agentName = typeof params.agent === "string" ? params.agent : "unknown";
|
|
77
|
+
const version = typeof params.version === "string" ? params.version : "";
|
|
78
|
+
log("info", `agent_ready: ${agentName} v${version}`);
|
|
79
|
+
if (chatId && renderer) {
|
|
80
|
+
renderer.onAgentReady(chatId, agentName, version);
|
|
81
|
+
}
|
|
82
|
+
break;
|
|
83
|
+
}
|
|
84
|
+
case "va/session_ready": {
|
|
85
|
+
const sessionId = typeof params.sessionId === "string" ? params.sessionId : "";
|
|
86
|
+
log("info", `session_ready: ${sessionId}`);
|
|
87
|
+
if (chatId && renderer) {
|
|
88
|
+
renderer.onSessionReady(chatId, sessionId);
|
|
89
|
+
}
|
|
90
|
+
break;
|
|
91
|
+
}
|
|
92
|
+
case "va/command_menu": {
|
|
93
|
+
const systemCommands = Array.isArray(params.systemCommands) ? params.systemCommands : [];
|
|
94
|
+
const agentCommands = Array.isArray(params.agentCommands) ? params.agentCommands : [];
|
|
95
|
+
if (chatId && renderer) {
|
|
96
|
+
renderer.onCommandMenu(chatId, systemCommands, agentCommands);
|
|
97
|
+
}
|
|
98
|
+
break;
|
|
99
|
+
}
|
|
100
|
+
default:
|
|
101
|
+
log("warn", `unhandled ext_notification: ${method}`);
|
|
102
|
+
}
|
|
103
|
+
},
|
|
104
|
+
}));
|
|
105
|
+
const config = meta.config;
|
|
106
|
+
for (const key of spec.requiredConfig ?? []) {
|
|
107
|
+
if (config[key] === undefined || config[key] === null || config[key] === "") {
|
|
108
|
+
throw new Error(`${key} is required in config`);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
const cacheDir = meta.cacheDir ?? path.join(os.homedir(), ".vibearound", ".cache");
|
|
112
|
+
log("info", `initialized, host=${agentInfo.name ?? "unknown"} cacheDir=${cacheDir}`);
|
|
113
|
+
const bot = await spec.createBot({ config, agent, log, cacheDir });
|
|
114
|
+
if (spec.afterCreate) {
|
|
115
|
+
await spec.afterCreate(bot, log);
|
|
116
|
+
}
|
|
117
|
+
const verboseRaw = config.verbose;
|
|
118
|
+
const verbose = {
|
|
119
|
+
showThinking: verboseRaw?.show_thinking ?? false,
|
|
120
|
+
showToolUse: verboseRaw?.show_tool_use ?? false,
|
|
121
|
+
};
|
|
122
|
+
renderer = spec.createRenderer(bot, log, verbose);
|
|
123
|
+
bot.setStreamHandler(renderer);
|
|
124
|
+
await bot.start();
|
|
125
|
+
log("info", "plugin started");
|
|
126
|
+
await conn.closed;
|
|
127
|
+
log("info", "connection closed, shutting down");
|
|
128
|
+
await bot.stop();
|
|
129
|
+
process.exit(0);
|
|
130
|
+
}
|
|
131
|
+
//# sourceMappingURL=plugin.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin.js","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"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"}
|
package/dist/renderer.d.ts
CHANGED
|
@@ -25,35 +25,29 @@
|
|
|
25
25
|
*
|
|
26
26
|
* ## Usage
|
|
27
27
|
*
|
|
28
|
+
* Subclass and implement `sendText` + `sendBlock` (+ optionally `editBlock`):
|
|
29
|
+
*
|
|
28
30
|
* ```ts
|
|
29
31
|
* class MyRenderer extends BlockRenderer<string> {
|
|
30
|
-
* protected async
|
|
31
|
-
*
|
|
32
|
+
* protected async sendText(chatId, text) {
|
|
33
|
+
* await myApi.sendMessage(chatId, text);
|
|
34
|
+
* }
|
|
35
|
+
* protected async sendBlock(chatId, kind, content) {
|
|
36
|
+
* const msg = await myApi.sendMessage(chatId, content);
|
|
32
37
|
* return msg.id;
|
|
33
38
|
* }
|
|
34
|
-
* protected async editBlock(
|
|
39
|
+
* protected async editBlock(chatId, ref, kind, content, sealed) {
|
|
35
40
|
* await myApi.editMessage(ref, content);
|
|
36
41
|
* }
|
|
37
42
|
* }
|
|
38
|
-
*
|
|
39
|
-
* // In main.ts:
|
|
40
|
-
* const renderer = new MyRenderer({ verbose: { showThinking: false } });
|
|
41
|
-
*
|
|
42
|
-
* // When user sends a message:
|
|
43
|
-
* renderer.onPromptSent(channelId);
|
|
44
|
-
* try {
|
|
45
|
-
* await agent.prompt({ sessionId, content });
|
|
46
|
-
* await renderer.onTurnEnd(channelId);
|
|
47
|
-
* } catch (e) {
|
|
48
|
-
* await renderer.onTurnError(channelId, String(e));
|
|
49
|
-
* }
|
|
50
|
-
*
|
|
51
|
-
* // In the ACP client's sessionUpdate handler:
|
|
52
|
-
* renderer.onSessionUpdate(notification);
|
|
53
43
|
* ```
|
|
44
|
+
*
|
|
45
|
+
* The SDK's `runChannelPlugin` wires all ACP events to this renderer
|
|
46
|
+
* automatically — plugins don't call onSessionUpdate/onPromptSent/etc
|
|
47
|
+
* directly.
|
|
54
48
|
*/
|
|
55
49
|
import type { SessionNotification } from "@agentclientprotocol/sdk";
|
|
56
|
-
import type { BlockKind, BlockRendererOptions, VerboseConfig } from "./types.js";
|
|
50
|
+
import type { BlockKind, BlockRendererOptions, CommandEntry, VerboseConfig } from "./types.js";
|
|
57
51
|
/**
|
|
58
52
|
* Abstract base class for block-based rendering of ACP session streams.
|
|
59
53
|
*
|
|
@@ -62,18 +56,29 @@ import type { BlockKind, BlockRendererOptions, VerboseConfig } from "./types.js"
|
|
|
62
56
|
* return type of `sendBlock` and the first argument of `editBlock`.
|
|
63
57
|
*/
|
|
64
58
|
export declare abstract class BlockRenderer<TRef = string> {
|
|
59
|
+
/** When true, blocks are sent and edited in real-time. When false, each
|
|
60
|
+
* block is held until complete, then sent once (send-only mode). */
|
|
61
|
+
protected readonly streaming: boolean;
|
|
65
62
|
protected readonly flushIntervalMs: number;
|
|
66
63
|
protected readonly minEditIntervalMs: number;
|
|
67
64
|
protected readonly verbose: VerboseConfig;
|
|
68
65
|
private states;
|
|
66
|
+
/** The chatId of the most recent prompt. Used as fallback target for
|
|
67
|
+
* notifications that arrive without an explicit chatId. */
|
|
68
|
+
private lastActiveChatId;
|
|
69
69
|
constructor(options?: BlockRendererOptions);
|
|
70
70
|
/**
|
|
71
|
-
* Send a
|
|
71
|
+
* Send a plain text message to the IM. Used for system text, agent ready
|
|
72
|
+
* notifications, session ready, and error messages.
|
|
73
|
+
*/
|
|
74
|
+
protected abstract sendText(chatId: string, text: string): Promise<void>;
|
|
75
|
+
/**
|
|
76
|
+
* Send a new streaming block message to the platform.
|
|
72
77
|
*
|
|
73
78
|
* Return the platform message reference that will be passed to future
|
|
74
79
|
* `editBlock` calls. Return `null` if editing is not supported.
|
|
75
80
|
*/
|
|
76
|
-
protected abstract sendBlock(
|
|
81
|
+
protected abstract sendBlock(chatId: string, kind: BlockKind, content: string): Promise<TRef | null>;
|
|
77
82
|
/**
|
|
78
83
|
* Edit an existing block message in-place.
|
|
79
84
|
*
|
|
@@ -83,7 +88,7 @@ export declare abstract class BlockRenderer<TRef = string> {
|
|
|
83
88
|
* @param sealed - `true` when this is the final edit (block done streaming).
|
|
84
89
|
* Use to switch from a "streaming" card format to a finalized one.
|
|
85
90
|
*/
|
|
86
|
-
protected editBlock?(
|
|
91
|
+
protected editBlock?(chatId: string, ref: TRef, kind: BlockKind, content: string, sealed: boolean): Promise<void>;
|
|
87
92
|
/**
|
|
88
93
|
* Format block content before sending or editing.
|
|
89
94
|
*
|
|
@@ -97,54 +102,55 @@ export declare abstract class BlockRenderer<TRef = string> {
|
|
|
97
102
|
protected formatContent(kind: BlockKind, content: string, _sealed: boolean): string;
|
|
98
103
|
/**
|
|
99
104
|
* Called after the last block has been flushed and the turn is complete.
|
|
100
|
-
* Override to perform cleanup (e.g. remove a "typing" indicator
|
|
101
|
-
* processing reaction, etc.).
|
|
105
|
+
* Override to perform cleanup (e.g. remove a "typing" indicator).
|
|
102
106
|
*/
|
|
103
|
-
protected onAfterTurnEnd(
|
|
107
|
+
protected onAfterTurnEnd(_chatId: string): Promise<void>;
|
|
104
108
|
/**
|
|
105
|
-
* Called after a turn error
|
|
106
|
-
* Override
|
|
109
|
+
* Called after a turn error. Default sends an error message via sendText.
|
|
110
|
+
* Override for platform-specific error rendering (e.g. error card).
|
|
107
111
|
*/
|
|
108
|
-
protected onAfterTurnError(
|
|
109
|
-
/**
|
|
110
|
-
* Map an ACP `sessionId` to the channel ID used internally.
|
|
111
|
-
*
|
|
112
|
-
* Default: identity (sessionId === channelId).
|
|
113
|
-
*
|
|
114
|
-
* Override if your plugin namespaces channel IDs (e.g. Feishu uses
|
|
115
|
-
* `"feishu:<sessionId>"`, WeChat uses `"weixin-openclaw-bridge:<sessionId>"`).
|
|
116
|
-
*/
|
|
117
|
-
protected sessionIdToChannelId(sessionId: string): string;
|
|
112
|
+
protected onAfterTurnError(chatId: string, error: string): Promise<void>;
|
|
118
113
|
/**
|
|
119
114
|
* Process an ACP `sessionUpdate` notification from the host.
|
|
120
115
|
*
|
|
121
116
|
* Routes the event to the correct block based on its variant, appending
|
|
122
117
|
* deltas to the current block or starting a new one when the kind changes.
|
|
123
118
|
*
|
|
124
|
-
*
|
|
119
|
+
* Called automatically by `runChannelPlugin` — plugins don't call this directly.
|
|
125
120
|
*/
|
|
126
121
|
onSessionUpdate(notification: SessionNotification): void;
|
|
127
122
|
/**
|
|
128
|
-
* Call
|
|
123
|
+
* Call before sending a prompt. Tracks the active chatId and clears
|
|
124
|
+
* leftover state from a previous turn.
|
|
125
|
+
*/
|
|
126
|
+
onPromptSent(chatId: string): void;
|
|
127
|
+
/** Handle `va/system_text` from host. */
|
|
128
|
+
onSystemText(chatId: string, text: string): void;
|
|
129
|
+
/** Handle `va/agent_ready` from host. */
|
|
130
|
+
onAgentReady(chatId: string, agent: string, version: string): void;
|
|
131
|
+
/** Handle `va/session_ready` from host. */
|
|
132
|
+
onSessionReady(chatId: string, sessionId: string): void;
|
|
133
|
+
/**
|
|
134
|
+
* Handle `va/command_menu` from host — display available commands.
|
|
129
135
|
*
|
|
130
|
-
*
|
|
131
|
-
*
|
|
136
|
+
* Default renders a plain-text list. Override for platform-specific
|
|
137
|
+
* rendering (e.g. Feishu interactive card, Slack Block Kit, Telegram
|
|
138
|
+
* inline keyboard).
|
|
132
139
|
*/
|
|
133
|
-
|
|
140
|
+
onCommandMenu(chatId: string, systemCommands: CommandEntry[], agentCommands: CommandEntry[]): void;
|
|
134
141
|
/**
|
|
135
142
|
* Call this after `agent.prompt()` resolves (turn complete).
|
|
136
143
|
*
|
|
137
144
|
* Seals and flushes the last block, then waits for all pending sends/edits
|
|
138
145
|
* to complete before calling `onAfterTurnEnd`.
|
|
139
146
|
*/
|
|
140
|
-
onTurnEnd(
|
|
147
|
+
onTurnEnd(chatId: string): Promise<void>;
|
|
141
148
|
/**
|
|
142
149
|
* Call this when `agent.prompt()` throws (turn error).
|
|
143
150
|
*
|
|
144
|
-
* Discards pending state and calls `onAfterTurnError
|
|
145
|
-
* send an error message to the user.
|
|
151
|
+
* Discards pending state and calls `onAfterTurnError`.
|
|
146
152
|
*/
|
|
147
|
-
onTurnError(
|
|
153
|
+
onTurnError(chatId: string, error: string): Promise<void>;
|
|
148
154
|
private appendToBlock;
|
|
149
155
|
private scheduleFlush;
|
|
150
156
|
private flush;
|
package/dist/renderer.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"renderer.d.ts","sourceRoot":"","sources":["../src/renderer.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"renderer.d.ts","sourceRoot":"","sources":["../src/renderer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+CG;AAEH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AACpE,OAAO,KAAK,EAAE,SAAS,EAAE,oBAAoB,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AA6E/F;;;;;;GAMG;AACH,8BAAsB,aAAa,CAAC,IAAI,GAAG,MAAM;IAC/C;yEACqE;IACrE,SAAS,CAAC,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IACtC,SAAS,CAAC,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IAC3C,SAAS,CAAC,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAC;IAC7C,SAAS,CAAC,QAAQ,CAAC,OAAO,EAAE,aAAa,CAAC;IAE1C,OAAO,CAAC,MAAM,CAAyC;IAEvD;gEAC4D;IAC5D,OAAO,CAAC,gBAAgB,CAAuB;gBAEnC,OAAO,GAAE,oBAAyB;IAc9C;;;OAGG;IACH,SAAS,CAAC,QAAQ,CAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAExE;;;;;OAKG;IACH,SAAS,CAAC,QAAQ,CAAC,SAAS,CAC1B,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,SAAS,EACf,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;IAMvB;;;;;;;;OAQG;IACH,SAAS,CAAC,SAAS,CAAC,CAClB,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,IAAI,EACT,IAAI,EAAE,SAAS,EACf,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,OAAO,GACd,OAAO,CAAC,IAAI,CAAC;IAEhB;;;;;;;;;OASG;IACH,SAAS,CAAC,aAAa,CAAC,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,MAAM;IAQnF;;;OAGG;IACH,SAAS,CAAC,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIxD;;;OAGG;cACa,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAQ9E;;;;;;;OAOG;IACH,eAAe,CAAC,YAAY,EAAE,mBAAmB,GAAG,IAAI;IA4CxD;;;OAGG;IACH,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAgBlC,yCAAyC;IACzC,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI;IAIhD,yCAAyC;IACzC,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI;IAIlE,2CAA2C;IAC3C,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI;IAIvD;;;;;;OAMG;IACH,aAAa,CACX,MAAM,EAAE,MAAM,EACd,cAAc,EAAE,YAAY,EAAE,EAC9B,aAAa,EAAE,YAAY,EAAE,GAC5B,IAAI;IA0BP;;;;;OAKG;IACG,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAoB9C;;;;OAIG;IACG,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAW/D,OAAO,CAAC,aAAa;IA8BrB,OAAO,CAAC,aAAa;IASrB,OAAO,CAAC,KAAK;IA4Bb,OAAO,CAAC,YAAY;YAMN,UAAU;CAqBzB"}
|