@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/dist/renderer.js CHANGED
@@ -25,32 +25,26 @@
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 sendBlock(channelId, kind, content) {
31
- * const msg = await myApi.sendMessage(channelId, content);
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(channelId, ref, kind, content, sealed) {
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
  // ---------------------------------------------------------------------------
56
50
  // Constants
@@ -68,11 +62,18 @@ const DEFAULT_MIN_EDIT_INTERVAL_MS = 1000;
68
62
  * return type of `sendBlock` and the first argument of `editBlock`.
69
63
  */
70
64
  export class BlockRenderer {
65
+ /** When true, blocks are sent and edited in real-time. When false, each
66
+ * block is held until complete, then sent once (send-only mode). */
67
+ streaming;
71
68
  flushIntervalMs;
72
69
  minEditIntervalMs;
73
70
  verbose;
74
71
  states = new Map();
72
+ /** The chatId of the most recent prompt. Used as fallback target for
73
+ * notifications that arrive without an explicit chatId. */
74
+ lastActiveChatId = null;
75
75
  constructor(options = {}) {
76
+ this.streaming = options.streaming ?? true;
76
77
  this.flushIntervalMs = options.flushIntervalMs ?? DEFAULT_FLUSH_INTERVAL_MS;
77
78
  this.minEditIntervalMs = options.minEditIntervalMs ?? DEFAULT_MIN_EDIT_INTERVAL_MS;
78
79
  this.verbose = {
@@ -99,29 +100,17 @@ export class BlockRenderer {
99
100
  }
100
101
  /**
101
102
  * Called after the last block has been flushed and the turn is complete.
102
- * Override to perform cleanup (e.g. remove a "typing" indicator, a
103
- * processing reaction, etc.).
104
- */
105
- onAfterTurnEnd(_channelId) {
106
- return Promise.resolve();
107
- }
108
- /**
109
- * Called after a turn error, once state has been cleaned up.
110
- * Override to send an error message to the user.
103
+ * Override to perform cleanup (e.g. remove a "typing" indicator).
111
104
  */
112
- onAfterTurnError(_channelId, _error) {
105
+ onAfterTurnEnd(_chatId) {
113
106
  return Promise.resolve();
114
107
  }
115
108
  /**
116
- * Map an ACP `sessionId` to the channel ID used internally.
117
- *
118
- * Default: identity (sessionId === channelId).
119
- *
120
- * Override if your plugin namespaces channel IDs (e.g. Feishu uses
121
- * `"feishu:<sessionId>"`, WeChat uses `"weixin-openclaw-bridge:<sessionId>"`).
109
+ * Called after a turn error. Default sends an error message via sendText.
110
+ * Override for platform-specific error rendering (e.g. error card).
122
111
  */
123
- sessionIdToChannelId(sessionId) {
124
- return sessionId;
112
+ async onAfterTurnError(chatId, error) {
113
+ await this.sendText(chatId, `❌ Error: ${error}`);
125
114
  }
126
115
  // ---------------------------------------------------------------------------
127
116
  // Public API
@@ -132,74 +121,123 @@ export class BlockRenderer {
132
121
  * Routes the event to the correct block based on its variant, appending
133
122
  * deltas to the current block or starting a new one when the kind changes.
134
123
  *
135
- * Call this from the ACP `Client.sessionUpdate` handler.
124
+ * Called automatically by `runChannelPlugin` — plugins don't call this directly.
136
125
  */
137
126
  onSessionUpdate(notification) {
138
- const sessionId = notification.sessionId;
139
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
140
- const update = notification.update;
141
- const variant = update.sessionUpdate;
142
- const channelId = this.sessionIdToChannelId(sessionId);
143
- switch (variant) {
127
+ // sessionId from ACP = chatId (the host replaces the real agent session
128
+ // ID with the chat ID before forwarding to the plugin).
129
+ const chatId = notification.sessionId;
130
+ const rawUpdate = notification.update;
131
+ const variant = rawUpdate.sessionUpdate;
132
+ if (variant !== "agent_message_chunk" &&
133
+ variant !== "agent_thought_chunk" &&
134
+ variant !== "tool_call" &&
135
+ variant !== "tool_call_update") {
136
+ return;
137
+ }
138
+ const update = rawUpdate;
139
+ switch (update.sessionUpdate) {
144
140
  case "agent_message_chunk": {
145
- const delta = (update.content?.text ?? "");
141
+ const delta = update.content?.text ?? "";
146
142
  if (delta)
147
- this.appendToBlock(channelId, "text", delta);
143
+ this.appendToBlock(chatId, "text", delta);
148
144
  break;
149
145
  }
150
146
  case "agent_thought_chunk": {
151
147
  if (!this.verbose.showThinking)
152
- return; // skip — no block, no boundary
153
- const delta = (update.content?.text ?? "");
148
+ return;
149
+ const delta = update.content?.text ?? "";
154
150
  if (delta)
155
- this.appendToBlock(channelId, "thinking", delta);
151
+ this.appendToBlock(chatId, "thinking", delta);
156
152
  break;
157
153
  }
158
154
  case "tool_call": {
159
155
  if (!this.verbose.showToolUse)
160
- return; // skip
161
- const title = update.title;
162
- if (title)
163
- this.appendToBlock(channelId, "tool", `🔧 ${title}\n`);
156
+ return;
157
+ if (update.title)
158
+ this.appendToBlock(chatId, "tool", `🔧 ${update.title}\n`);
164
159
  break;
165
160
  }
166
161
  case "tool_call_update": {
167
162
  if (!this.verbose.showToolUse)
168
- return; // skip
169
- const title = (update.title ?? "tool");
170
- const status = update.status;
171
- if (status === "completed" || status === "error") {
172
- this.appendToBlock(channelId, "tool", `✅ ${title}\n`);
163
+ return;
164
+ const title = update.title ?? "tool";
165
+ if (update.status === "completed" || update.status === "error") {
166
+ this.appendToBlock(chatId, "tool", `✅ ${title}\n`);
173
167
  }
174
168
  break;
175
169
  }
176
170
  }
177
171
  }
178
172
  /**
179
- * Call this before sending a prompt to the agent.
180
- *
181
- * Clears any leftover state from a previous turn so the new turn starts
182
- * with a clean slate.
173
+ * Call before sending a prompt. Tracks the active chatId and clears
174
+ * leftover state from a previous turn.
183
175
  */
184
- onPromptSent(channelId) {
185
- const old = this.states.get(channelId);
176
+ onPromptSent(chatId) {
177
+ this.lastActiveChatId = chatId;
178
+ const old = this.states.get(chatId);
186
179
  if (old?.flushTimer)
187
180
  clearTimeout(old.flushTimer);
188
- this.states.set(channelId, {
181
+ this.states.set(chatId, {
189
182
  blocks: [],
190
183
  flushTimer: null,
191
184
  lastEditMs: 0,
192
185
  sendChain: Promise.resolve(),
193
186
  });
194
187
  }
188
+ // ---------------------------------------------------------------------------
189
+ // Host notification handlers — built-in defaults, no per-plugin duplication
190
+ // ---------------------------------------------------------------------------
191
+ /** Handle `va/system_text` from host. */
192
+ onSystemText(chatId, text) {
193
+ this.sendText(chatId, text).catch(() => { });
194
+ }
195
+ /** Handle `va/agent_ready` from host. */
196
+ onAgentReady(chatId, agent, version) {
197
+ this.sendText(chatId, `🤖 Agent: ${agent} v${version}`).catch(() => { });
198
+ }
199
+ /** Handle `va/session_ready` from host. */
200
+ onSessionReady(chatId, sessionId) {
201
+ this.sendText(chatId, `📋 Session: ${sessionId}`).catch(() => { });
202
+ }
203
+ /**
204
+ * Handle `va/command_menu` from host — display available commands.
205
+ *
206
+ * Default renders a plain-text list. Override for platform-specific
207
+ * rendering (e.g. Feishu interactive card, Slack Block Kit, Telegram
208
+ * inline keyboard).
209
+ */
210
+ onCommandMenu(chatId, systemCommands, agentCommands) {
211
+ const lines = [];
212
+ lines.push("System commands:");
213
+ for (const cmd of systemCommands) {
214
+ const usage = cmd.args ? `/${cmd.name} ${cmd.args}` : `/${cmd.name}`;
215
+ lines.push(` ${usage} — ${cmd.description}`);
216
+ }
217
+ if (agentCommands.length > 0) {
218
+ lines.push("");
219
+ lines.push("Agent commands (use /agent <command>):");
220
+ for (const cmd of agentCommands) {
221
+ const desc = cmd.description.length > 80
222
+ ? `${cmd.description.slice(0, 77)}...`
223
+ : cmd.description;
224
+ lines.push(` /${cmd.name} — ${desc}`);
225
+ }
226
+ }
227
+ else {
228
+ lines.push("");
229
+ lines.push("Agent commands will appear after sending your first message.");
230
+ }
231
+ this.sendText(chatId, lines.join("\n")).catch(() => { });
232
+ }
195
233
  /**
196
234
  * Call this after `agent.prompt()` resolves (turn complete).
197
235
  *
198
236
  * Seals and flushes the last block, then waits for all pending sends/edits
199
237
  * to complete before calling `onAfterTurnEnd`.
200
238
  */
201
- async onTurnEnd(channelId) {
202
- const state = this.states.get(channelId);
239
+ async onTurnEnd(chatId) {
240
+ const state = this.states.get(chatId);
203
241
  if (!state)
204
242
  return;
205
243
  if (state.flushTimer) {
@@ -211,33 +249,31 @@ export class BlockRenderer {
211
249
  last.sealed = true;
212
250
  this.enqueueFlush(state, last);
213
251
  }
214
- // Wait for the entire chain to drain before cleanup
215
252
  await state.sendChain;
216
- this.states.delete(channelId);
217
- await this.onAfterTurnEnd(channelId);
253
+ this.states.delete(chatId);
254
+ await this.onAfterTurnEnd(chatId);
218
255
  }
219
256
  /**
220
257
  * Call this when `agent.prompt()` throws (turn error).
221
258
  *
222
- * Discards pending state and calls `onAfterTurnError` so the subclass can
223
- * send an error message to the user.
259
+ * Discards pending state and calls `onAfterTurnError`.
224
260
  */
225
- async onTurnError(channelId, error) {
226
- const state = this.states.get(channelId);
261
+ async onTurnError(chatId, error) {
262
+ const state = this.states.get(chatId);
227
263
  if (state?.flushTimer)
228
264
  clearTimeout(state.flushTimer);
229
- this.states.delete(channelId);
230
- await this.onAfterTurnError(channelId, error);
265
+ this.states.delete(chatId);
266
+ await this.onAfterTurnError(chatId, error);
231
267
  }
232
268
  // ---------------------------------------------------------------------------
233
269
  // Internal — block management
234
270
  // ---------------------------------------------------------------------------
235
- appendToBlock(channelId, kind, delta) {
236
- let state = this.states.get(channelId);
271
+ appendToBlock(chatId, kind, delta) {
272
+ let state = this.states.get(chatId);
237
273
  if (!state) {
238
274
  // Auto-create state if onPromptSent wasn't called (e.g. host-initiated turns)
239
275
  state = { blocks: [], flushTimer: null, lastEditMs: 0, sendChain: Promise.resolve() };
240
- this.states.set(channelId, state);
276
+ this.states.set(chatId, state);
241
277
  }
242
278
  const last = state.blocks.at(-1);
243
279
  if (last && !last.sealed && last.kind === kind) {
@@ -255,22 +291,29 @@ export class BlockRenderer {
255
291
  }
256
292
  this.enqueueFlush(state, last);
257
293
  }
258
- state.blocks.push({ channelId, kind, content: delta, ref: null, creating: false, sealed: false });
294
+ state.blocks.push({ chatId, kind, content: delta, ref: null, creating: false, sealed: false });
259
295
  }
260
- this.scheduleFlush(channelId, state);
296
+ this.scheduleFlush(chatId, state);
261
297
  }
262
- scheduleFlush(channelId, state) {
298
+ scheduleFlush(chatId, state) {
263
299
  if (state.flushTimer)
264
300
  return; // already scheduled
265
301
  state.flushTimer = setTimeout(() => {
266
302
  state.flushTimer = null;
267
- this.flush(channelId, state);
303
+ this.flush(chatId, state);
268
304
  }, this.flushIntervalMs);
269
305
  }
270
- flush(channelId, state) {
306
+ flush(chatId, state) {
271
307
  const block = state.blocks.at(-1);
272
308
  if (!block || block.sealed || !block.content)
273
309
  return;
310
+ // Send-only mode (streaming=false): defer intermediate sends.
311
+ // Only sealed blocks (from onTurnEnd or block boundary transitions)
312
+ // will actually POST. This prevents the user seeing a partial chunk
313
+ // followed by the full message as two separate messages.
314
+ if (!this.streaming) {
315
+ return;
316
+ }
274
317
  const now = Date.now();
275
318
  if (now - state.lastEditMs < this.minEditIntervalMs) {
276
319
  // Throttled — reschedule for the remaining window
@@ -278,7 +321,7 @@ export class BlockRenderer {
278
321
  if (!state.flushTimer) {
279
322
  state.flushTimer = setTimeout(() => {
280
323
  state.flushTimer = null;
281
- this.flush(channelId, state);
324
+ this.flush(chatId, state);
282
325
  }, delay);
283
326
  }
284
327
  return;
@@ -298,13 +341,13 @@ export class BlockRenderer {
298
341
  if (block.ref === null && !block.creating) {
299
342
  // First send — use sentinel to prevent concurrent creates
300
343
  block.creating = true;
301
- block.ref = await this.sendBlock(block.channelId, block.kind, content);
344
+ block.ref = await this.sendBlock(block.chatId, block.kind, content);
302
345
  block.creating = false;
303
346
  state.lastEditMs = Date.now();
304
347
  }
305
- else if (block.ref !== null && !block.creating && this.editBlock) {
306
- // Subsequent update — edit in-place
307
- await this.editBlock(block.channelId, block.ref, block.kind, content, block.sealed);
348
+ else if (block.ref !== null && !block.creating && this.streaming && this.editBlock) {
349
+ // Subsequent update — edit in-place (streaming mode only)
350
+ await this.editBlock(block.chatId, block.ref, block.kind, content, block.sealed);
308
351
  state.lastEditMs = Date.now();
309
352
  }
310
353
  // else: create is in-flight (creating === true) — skip
@@ -1 +1 @@
1
- {"version":3,"file":"renderer.js","sourceRoot":"","sources":["../src/renderer.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"renderer.js","sourceRoot":"","sources":["../src/renderer.ts"],"names":[],"mappings":"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"}
package/dist/types.d.ts CHANGED
@@ -29,6 +29,13 @@ export interface PluginManifest {
29
29
  configSchema?: Record<string, unknown>;
30
30
  capabilities?: PluginCapabilities;
31
31
  }
32
+ /** A command entry from the host's command list. */
33
+ export interface CommandEntry {
34
+ name: string;
35
+ description: string;
36
+ args?: string;
37
+ aliases?: string[];
38
+ }
32
39
  /** The three kinds of content blocks a plugin renders. */
33
40
  export type BlockKind = "text" | "thinking" | "tool";
34
41
  export interface VerboseConfig {
@@ -38,6 +45,18 @@ export interface VerboseConfig {
38
45
  showToolUse: boolean;
39
46
  }
40
47
  export interface BlockRendererOptions {
48
+ /**
49
+ * Whether the IM platform supports message editing (streaming mode).
50
+ *
51
+ * - `true` (default): blocks stream in real-time — `sendBlock()` creates
52
+ * the message, `editBlock()` updates it as more content arrives.
53
+ * - `false`: each block is held until complete, then sent once via
54
+ * `sendBlock()`. `editBlock()` is never called.
55
+ *
56
+ * Set to `false` for platforms that don't support editing sent messages
57
+ * (e.g. QQ Bot, WhatsApp, WeChat, LINE).
58
+ */
59
+ streaming?: boolean;
41
60
  /**
42
61
  * Debounce interval before flushing an unsealed block (ms).
43
62
  * Controls how often in-progress blocks are sent to the platform.
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,YAAY,EACV,KAAK,EACL,MAAM,EACN,YAAY,EACZ,mBAAmB,EACnB,wBAAwB,EACxB,yBAAyB,GAC1B,MAAM,0BAA0B,CAAC;AAMlC,MAAM,WAAW,kBAAkB;IACjC,mDAAmD;IACnD,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,8DAA8D;IAC9D,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,uDAAuD;IACvD,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,8CAA8C;IAC9C,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,IAAI,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;CAC/B;AAED,uDAAuD;AACvD,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,SAAS,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACvC,YAAY,CAAC,EAAE,kBAAkB,CAAC;CACnC;AAMD,0DAA0D;AAC1D,MAAM,MAAM,SAAS,GAAG,MAAM,GAAG,UAAU,GAAG,MAAM,CAAC;AAErD,MAAM,WAAW,aAAa;IAC5B,4DAA4D;IAC5D,YAAY,EAAE,OAAO,CAAC;IACtB,2DAA2D;IAC3D,WAAW,EAAE,OAAO,CAAC;CACtB;AAED,MAAM,WAAW,oBAAoB;IACnC;;;;OAIG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB;;;;OAIG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,OAAO,CAAC,EAAE,OAAO,CAAC,aAAa,CAAC,CAAC;CAClC;AAMD;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,wDAAwD;IACxD,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAChC,8DAA8D;IAC9D,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,YAAY,EACV,KAAK,EACL,MAAM,EACN,YAAY,EACZ,mBAAmB,EACnB,wBAAwB,EACxB,yBAAyB,GAC1B,MAAM,0BAA0B,CAAC;AAMlC,MAAM,WAAW,kBAAkB;IACjC,mDAAmD;IACnD,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,8DAA8D;IAC9D,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,uDAAuD;IACvD,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,8CAA8C;IAC9C,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,IAAI,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;CAC/B;AAED,uDAAuD;AACvD,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,SAAS,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACvC,YAAY,CAAC,EAAE,kBAAkB,CAAC;CACnC;AAMD,oDAAoD;AACpD,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;CACpB;AAMD,0DAA0D;AAC1D,MAAM,MAAM,SAAS,GAAG,MAAM,GAAG,UAAU,GAAG,MAAM,CAAC;AAErD,MAAM,WAAW,aAAa;IAC5B,4DAA4D;IAC5D,YAAY,EAAE,OAAO,CAAC;IACtB,2DAA2D;IAC3D,WAAW,EAAE,OAAO,CAAC;CACtB;AAED,MAAM,WAAW,oBAAoB;IACnC;;;;;;;;;;OAUG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB;;;;OAIG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB;;;;OAIG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,OAAO,CAAC,EAAE,OAAO,CAAC,aAAa,CAAC,CAAC;CAClC;AAMD;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,wDAAwD;IACxD,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAChC,8DAA8D;IAC9D,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vibearound/plugin-channel-sdk",
3
- "version": "0.1.2",
3
+ "version": "0.4.0",
4
4
  "description": "VibeAround Plugin SDK — base classes and utilities for building channel plugins",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -14,6 +14,10 @@
14
14
  ".": {
15
15
  "import": "./dist/index.js",
16
16
  "types": "./dist/index.d.ts"
17
+ },
18
+ "./advanced": {
19
+ "import": "./dist/advanced.js",
20
+ "types": "./dist/advanced.d.ts"
17
21
  }
18
22
  },
19
23
  "scripts": {
@@ -0,0 +1,43 @@
1
+ /**
2
+ * @vibearound/plugin-channel-sdk — Advanced / low-level API
3
+ *
4
+ * For plugins that need custom ACP lifecycle control instead of
5
+ * the standard `runChannelPlugin()` flow.
6
+ *
7
+ * Normal plugins should use the main entry point instead:
8
+ * ```ts
9
+ * import { runChannelPlugin, BlockRenderer } from "@vibearound/plugin-channel-sdk";
10
+ * ```
11
+ */
12
+
13
+ // Low-level ACP connection
14
+ export { connectToHost, stripExtPrefix, redirectConsoleToStderr } from "./connection.js";
15
+ export type { PluginInfo, ConnectResult, AgentInfo } from "./connection.js";
16
+
17
+ // All types (including internal ones)
18
+ export type {
19
+ Agent,
20
+ Client,
21
+ ContentBlock,
22
+ SessionNotification,
23
+ RequestPermissionRequest,
24
+ RequestPermissionResponse,
25
+ BlockKind,
26
+ VerboseConfig,
27
+ BlockRendererOptions,
28
+ PluginCapabilities,
29
+ PluginManifest,
30
+ PluginInitMeta,
31
+ } from "./types.js";
32
+
33
+ // Re-export high-level API too (so advanced users don't need two imports)
34
+ export { runChannelPlugin } from "./plugin.js";
35
+ export { BlockRenderer } from "./renderer.js";
36
+ export { extractErrorMessage } from "./errors.js";
37
+ export type {
38
+ ChannelBot,
39
+ ChannelPluginLogger,
40
+ CreateBotContext,
41
+ RunChannelPluginSpec,
42
+ VerboseOptions,
43
+ } from "./plugin.js";
package/src/connection.ts CHANGED
@@ -111,12 +111,18 @@ export async function connectToHost(
111
111
  // ---------------------------------------------------------------------------
112
112
 
113
113
  /**
114
- * Normalize ACP ext notification method names.
114
+ * Strip the `_` prefix from ACP extension method names.
115
115
  *
116
- * The ACP SDK prepends "_" to ext method names (e.g. "_channel/system_text").
117
- * Strip the prefix to get the canonical method name used in plugin.json.
116
+ * The Rust ACP SDK adds `_` when sending ext notifications on the wire,
117
+ * but the TypeScript ACP SDK does not strip it on receipt. This function
118
+ * normalizes the received method name so handlers can match the canonical
119
+ * name (e.g. `_va/system_text` → `va/system_text`).
120
+ *
121
+ * Note: when sending ext notifications FROM TypeScript TO the Rust host,
122
+ * the method name must include the `_` prefix manually (e.g. `_va/callback`)
123
+ * because the TypeScript SDK does not add it automatically.
118
124
  */
119
- export function normalizeExtMethod(method: string): string {
125
+ export function stripExtPrefix(method: string): string {
120
126
  return method.startsWith("_") ? method.slice(1) : method;
121
127
  }
122
128
 
package/src/errors.ts ADDED
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Error normalization for channel plugins.
3
+ *
4
+ * Every plugin had an ad-hoc ladder that tried `instanceof Error`, then
5
+ * `typeof error === "object"`, then fell back to `String(error)`. That
6
+ * ladder lived in five slightly-different forms across bot.ts files and
7
+ * drifted over time. Centralize it here.
8
+ */
9
+
10
+ /**
11
+ * Extract a human-readable message from an unknown thrown value.
12
+ *
13
+ * Prefers `Error.message`, falls back to a non-circular JSON stringify for
14
+ * objects, and finally to `String(e)` for primitives.
15
+ */
16
+ export function extractErrorMessage(e: unknown): string {
17
+ if (e instanceof Error) return e.message;
18
+ if (typeof e === "string") return e;
19
+ if (e && typeof e === "object") {
20
+ const msg = (e as { message?: unknown }).message;
21
+ if (typeof msg === "string") return msg;
22
+ try {
23
+ return JSON.stringify(e);
24
+ } catch {
25
+ return String(e);
26
+ }
27
+ }
28
+ return String(e);
29
+ }