@qwen-code/channel-base 0.14.0-preview.1 → 0.14.0-preview.2

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 ADDED
@@ -0,0 +1,295 @@
1
+ # @qwen-code/channel-base
2
+
3
+ Base infrastructure for building Qwen Code channel adapters. Provides the abstract base class, access control, session routing, and the ACP bridge that communicates with the agent.
4
+
5
+ If you're building a channel plugin, this is your only dependency.
6
+
7
+ ## Install
8
+
9
+ ```bash
10
+ npm install @qwen-code/channel-base
11
+ ```
12
+
13
+ ## Quick start
14
+
15
+ Subclass `ChannelBase` and implement three methods:
16
+
17
+ ```typescript
18
+ import { ChannelBase } from '@qwen-code/channel-base';
19
+ import type {
20
+ ChannelConfig,
21
+ Envelope,
22
+ AcpBridge,
23
+ } from '@qwen-code/channel-base';
24
+
25
+ class MyChannel extends ChannelBase {
26
+ async connect(): Promise<void> {
27
+ // Connect to platform API, register message handlers.
28
+ // When a message arrives, build an Envelope and call:
29
+ // this.handleInbound(envelope)
30
+ }
31
+
32
+ async sendMessage(chatId: string, text: string): Promise<void> {
33
+ // Deliver the agent's response to the platform.
34
+ }
35
+
36
+ disconnect(): void {
37
+ // Clean up connections on shutdown.
38
+ }
39
+ }
40
+ ```
41
+
42
+ Export a `ChannelPlugin` object so the extension loader can discover it:
43
+
44
+ ```typescript
45
+ import type { ChannelPlugin } from '@qwen-code/channel-base';
46
+
47
+ export const plugin: ChannelPlugin = {
48
+ channelType: 'my-platform',
49
+ displayName: 'My Platform',
50
+ requiredConfigFields: ['apiKey'],
51
+ createChannel: (name, config, bridge, options) =>
52
+ new MyChannel(name, config, bridge, options),
53
+ };
54
+ ```
55
+
56
+ For a complete working example, see [`@qwen-code/channel-plugin-example`](../plugin-example/).
57
+
58
+ ## Architecture
59
+
60
+ ```
61
+ Inbound: Platform message
62
+ → Envelope (with attachments)
63
+ → GroupGate (group policy + mention gating)
64
+ → SenderGate (allowlist / pairing / open)
65
+ → Slash commands (/clear, /help, /status)
66
+ → SessionRouter (resolve or create ACP session)
67
+ → Resolve attachments (images → bridge, files → prompt text)
68
+ → AcpBridge.prompt() → agent
69
+
70
+ Outbound: Agent response
71
+ → BlockStreamer (if enabled: split into blocks at paragraph boundaries)
72
+ → sendMessage() → platform
73
+ ```
74
+
75
+ Everything between `handleInbound()` and `sendMessage()` is handled by the base class — your adapter only deals with platform I/O.
76
+
77
+ ## Exports
78
+
79
+ ### Classes
80
+
81
+ | Class | Purpose |
82
+ | --------------- | ---------------------------------------------------------------- |
83
+ | `ChannelBase` | Abstract base class — extend this to build a channel adapter |
84
+ | `AcpBridge` | Spawns and communicates with the `qwen-code --acp` agent process |
85
+ | `BlockStreamer` | Progressive multi-message delivery for block streaming |
86
+ | `SessionRouter` | Maps senders to ACP sessions with configurable scoping |
87
+ | `SenderGate` | DM access control (allowlist / pairing / open) |
88
+ | `GroupGate` | Group chat policy and @mention gating |
89
+ | `PairingStore` | Pairing code generation, approval, and allowlist persistence |
90
+
91
+ ### Types
92
+
93
+ | Type | Description |
94
+ | --------------- | ---------------------------------------------- |
95
+ | `Attachment` | Structured file/image/audio/video attachment |
96
+ | `ChannelConfig` | Channel configuration from `settings.json` |
97
+ | `ChannelPlugin` | Plugin factory interface (what you export) |
98
+ | `Envelope` | Normalized inbound message format |
99
+ | `SenderPolicy` | `'allowlist' \| 'pairing' \| 'open'` |
100
+ | `GroupPolicy` | `'disabled' \| 'allowlist' \| 'open'` |
101
+ | `SessionScope` | `'user' \| 'thread' \| 'single'` |
102
+ | `GroupConfig` | Per-group settings (e.g. `requireMention`) |
103
+ | `SessionTarget` | Maps a session back to its channel/sender/chat |
104
+
105
+ ## API reference
106
+
107
+ ### ChannelBase
108
+
109
+ ```typescript
110
+ constructor(name: string, config: ChannelConfig, bridge: AcpBridge, options?: ChannelBaseOptions)
111
+ ```
112
+
113
+ **Abstract methods** (you must implement):
114
+
115
+ | Method | Signature |
116
+ | --------------- | ---------------------------------------------------------------------------- |
117
+ | `connect()` | `() => Promise<void>` — Connect to the platform and start receiving messages |
118
+ | `sendMessage()` | `(chatId: string, text: string) => Promise<void>` — Deliver agent response |
119
+ | `disconnect()` | `() => void` — Clean up on shutdown |
120
+
121
+ **Provided methods:**
122
+
123
+ | Method | Description |
124
+ | ------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------- |
125
+ | `handleInbound(envelope)` | Route an inbound message through the full pipeline (gate checks, commands, session, prompt). Call this from your message handler. |
126
+ | `setBridge(bridge)` | Replace the ACP bridge after crash recovery |
127
+ | `registerCommand(name, handler)` | Register a custom slash command (e.g. `/mycommand`) |
128
+ | `onToolCall(chatId, event)` | Hook called on agent tool invocations — override to show indicators |
129
+ | `onResponseChunk(chatId, chunk, sessionId)` | Hook called per streaming text chunk — override for progressive display (default: no-op) |
130
+ | `onResponseComplete(chatId, fullText, sessionId)` | Hook called when full response is ready — override to customize delivery (default: `sendMessage()`) |
131
+
132
+ **Block streaming:** When `blockStreaming: "on"` is set in the channel config, the base class automatically splits the agent's streaming response into multiple messages at paragraph boundaries. See [Block Streaming](#block-streaming) below.
133
+
134
+ **Built-in slash commands:** `/clear` (`/reset`, `/new`), `/help`, `/status`
135
+
136
+ ### AcpBridge
137
+
138
+ Manages the `qwen-code --acp` child process and ACP sessions.
139
+
140
+ ```typescript
141
+ constructor(options: { cliEntryPath: string; cwd: string; model?: string })
142
+ ```
143
+
144
+ | Method | Description |
145
+ | ----------------------------------- | ----------------------------------------------------------------------------------------------------------------- |
146
+ | `start()` | Spawn the agent process |
147
+ | `stop()` | Kill the agent process |
148
+ | `newSession(cwd)` | Create a new ACP session, returns `sessionId` |
149
+ | `loadSession(sessionId, cwd)` | Restore an existing session |
150
+ | `prompt(sessionId, text, options?)` | Send a message to the agent, returns the full response text. Supports optional `imageBase64` and `imageMimeType`. |
151
+ | `isConnected` | Whether the agent process is alive |
152
+
153
+ **Events** (EventEmitter):
154
+
155
+ | Event | Payload | Description |
156
+ | -------------- | ------------------------ | ------------------------ |
157
+ | `textChunk` | `(sessionId, chunk)` | Streaming response chunk |
158
+ | `toolCall` | `(event: ToolCallEvent)` | Agent invoked a tool |
159
+ | `disconnected` | `(code, signal)` | Agent process exited |
160
+
161
+ ### SessionRouter
162
+
163
+ Maps senders to ACP sessions based on the configured scope.
164
+
165
+ ```typescript
166
+ constructor(bridge: AcpBridge, defaultCwd: string, scope?: SessionScope, persistPath?: string)
167
+ ```
168
+
169
+ **Routing keys by scope:**
170
+
171
+ | Scope | Key format | Effect |
172
+ | ---------------- | ------------------------- | ----------------------------------------- |
173
+ | `user` (default) | `channel:senderId:chatId` | Each user gets their own session per chat |
174
+ | `thread` | `channel:threadId` | One session per thread |
175
+ | `single` | `channel:__single__` | One shared session for the entire channel |
176
+
177
+ | Method | Description |
178
+ | --------------------------------------------------------- | ----------------------------------------------------------- |
179
+ | `resolve(channelName, senderId, chatId, threadId?, cwd?)` | Get or create a session for the given sender |
180
+ | `removeSession(channelName, senderId, chatId?)` | Remove session(s) — used by `/clear` |
181
+ | `restoreSessions()` | Reload sessions from disk after bridge restart |
182
+ | `clearAll()` | Clear all sessions and delete persist file (clean shutdown) |
183
+
184
+ ### SenderGate
185
+
186
+ ```typescript
187
+ constructor(policy: SenderPolicy, allowedUsers?: string[], pairingStore?: PairingStore)
188
+ ```
189
+
190
+ | Method | Description |
191
+ | ------------------------------ | ------------------------------------------------------------ |
192
+ | `check(senderId, senderName?)` | Returns `{ allowed: boolean, pairingCode?: string \| null }` |
193
+
194
+ **Policy behavior:**
195
+
196
+ | Policy | Behavior |
197
+ | ----------- | --------------------------------------------------------------------------------------------------------- |
198
+ | `open` | Everyone allowed |
199
+ | `allowlist` | Only `allowedUsers` allowed |
200
+ | `pairing` | Check allowlist, then approved pairings, then generate a pairing code (8-char, 1hr expiry, max 3 pending) |
201
+
202
+ ### GroupGate
203
+
204
+ ```typescript
205
+ constructor(policy?: GroupPolicy, groups?: Record<string, GroupConfig>)
206
+ ```
207
+
208
+ | Method | Description |
209
+ | ----------------- | ---------------------------------------------------------------------------------------------- |
210
+ | `check(envelope)` | Returns `{ allowed: boolean, reason?: 'disabled' \| 'not_allowlisted' \| 'mention_required' }` |
211
+
212
+ **Policy behavior:**
213
+
214
+ | Policy | Behavior |
215
+ | ----------- | ---------------------------------------- |
216
+ | `disabled` | All group messages rejected |
217
+ | `allowlist` | Only groups listed in config are allowed |
218
+ | `open` | All groups allowed |
219
+
220
+ When `requireMention` is `true` (default), group messages are only processed if the bot is @mentioned or the message is a reply to the bot.
221
+
222
+ ### PairingStore
223
+
224
+ ```typescript
225
+ constructor(channelName: string)
226
+ ```
227
+
228
+ Persists pairing state to `~/.qwen/channels/{channelName}-pairing.json` and `{channelName}-allowlist.json`.
229
+
230
+ | Method | Description |
231
+ | ------------------------------------- | --------------------------------------------------------------------------------------------------------- |
232
+ | `createRequest(senderId, senderName)` | Generate an 8-char pairing code (or return existing). Returns `null` if 3 pending requests already exist. |
233
+ | `approve(code)` | Approve a pairing request, adds sender to allowlist. Returns the request or `null`. |
234
+ | `isApproved(senderId)` | Check if sender is in the approved allowlist |
235
+ | `listPending()` | Get active (non-expired) pending requests |
236
+
237
+ ## Envelope
238
+
239
+ The normalized message format your adapter must construct:
240
+
241
+ ```typescript
242
+ interface Envelope {
243
+ channelName: string; // your channel instance name
244
+ senderId: string; // stable, unique sender ID
245
+ senderName: string; // display name
246
+ chatId: string; // distinguishes DMs from groups
247
+ text: string; // message text (@mentions stripped)
248
+ messageId?: string; // platform message ID
249
+ threadId?: string; // for thread-scoped sessions
250
+ isGroup: boolean; // true for group chats
251
+ isMentioned: boolean; // true if bot was @mentioned
252
+ isReplyToBot: boolean; // true if replying to bot's message
253
+ referencedText?: string; // quoted message text
254
+ imageBase64?: string; // base64-encoded image (legacy — prefer attachments)
255
+ imageMimeType?: string; // e.g. 'image/jpeg' (legacy — prefer attachments)
256
+ attachments?: Attachment[]; // structured file/image/audio/video attachments
257
+ }
258
+
259
+ interface Attachment {
260
+ type: 'image' | 'file' | 'audio' | 'video';
261
+ data?: string; // base64-encoded data (images, small files)
262
+ filePath?: string; // absolute path to local file (large files)
263
+ mimeType: string; // e.g. 'application/pdf', 'image/jpeg'
264
+ fileName?: string; // original file name from the platform
265
+ }
266
+ ```
267
+
268
+ `handleInbound()` automatically resolves attachments: images with `data` are sent to the model as vision input, files with `filePath` get their path appended to the prompt text so the agent can read them with its tools.
269
+
270
+ ## Block Streaming
271
+
272
+ When `blockStreaming: "on"` is set in a channel's config, the agent's response is delivered as multiple separate messages instead of one large wall of text. The `BlockStreamer` accumulates streaming chunks and emits completed blocks based on paragraph boundaries and size heuristics.
273
+
274
+ **Config fields** (on `ChannelConfig`):
275
+
276
+ | Field | Type | Default | Description |
277
+ | ------------------------ | ------------------------ | --------------- | --------------------------------------------------------------------------- |
278
+ | `blockStreaming` | `'on' \| 'off'` | `'off'` | Enable/disable block streaming |
279
+ | `blockStreamingChunk` | `{ minChars, maxChars }` | `{ 400, 1000 }` | `minChars`: don't emit until this size. `maxChars`: force-emit at this size |
280
+ | `blockStreamingCoalesce` | `{ idleMs }` | `{ 1500 }` | Emit buffered text after this many ms of silence from the agent |
281
+
282
+ **How it works:**
283
+
284
+ 1. Text accumulates as the agent streams its response
285
+ 2. When the buffer reaches `minChars` and hits a paragraph break (`\n\n`), that block is sent as a separate message
286
+ 3. If the buffer reaches `maxChars` without a paragraph break, it force-splits at the best break point (newline > space)
287
+ 4. If the agent goes quiet for `idleMs`, the buffer is flushed (as long as it's past `minChars`)
288
+ 5. When the agent finishes, any remaining text is sent immediately regardless of `minChars`
289
+
290
+ Block streaming and `onResponseChunk` work independently — plugins can override `onResponseChunk` for their own purposes while block streaming handles delivery.
291
+
292
+ ## Further reading
293
+
294
+ - [Channel Plugin Developer Guide](../../docs/developers/channel-plugins.md)
295
+ - [`@qwen-code/channel-plugin-example`](../plugin-example/) — working reference implementation
@@ -30,6 +30,7 @@ export declare class AcpBridge extends EventEmitter {
30
30
  imageBase64?: string;
31
31
  imageMimeType?: string;
32
32
  }): Promise<string>;
33
+ cancelSession(sessionId: string): Promise<void>;
33
34
  stop(): void;
34
35
  get isConnected(): boolean;
35
36
  private handleSessionUpdate;
package/dist/AcpBridge.js CHANGED
@@ -108,6 +108,10 @@ export class AcpBridge extends EventEmitter {
108
108
  }
109
109
  return chunks.join('');
110
110
  }
111
+ async cancelSession(sessionId) {
112
+ const conn = this.ensureConnection();
113
+ await conn.cancel({ sessionId });
114
+ }
111
115
  stop() {
112
116
  if (this.child) {
113
117
  this.child.kill();
@@ -1 +1 @@
1
- {"version":3,"file":"AcpBridge.js","sourceRoot":"","sources":["../src/AcpBridge.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"AcpBridge.js","sourceRoot":"","sources":["../src/AcpBridge.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,54 @@
1
+ /**
2
+ * BlockStreamer — progressive multi-message delivery for channels.
3
+ *
4
+ * Accumulates text chunks from the agent's streaming response and emits
5
+ * completed "blocks" (paragraphs / sections) as separate channel messages
6
+ * while the agent is still working. This gives users a natural conversation
7
+ * flow instead of waiting 30–120 seconds for a single wall of text.
8
+ *
9
+ * Emission triggers:
10
+ * 1. Buffer ≥ maxChars → force-split at best break point
11
+ * 2. Buffer ≥ minChars AND a paragraph boundary (\n\n) exists → emit up to boundary
12
+ * 3. Idle timer fires (no chunk for idleMs) AND buffer ≥ minChars → emit buffer
13
+ * 4. flush() called (response complete) → emit everything remaining
14
+ *
15
+ * All sends are serialized — the next block waits for the previous send to complete.
16
+ */
17
+ export interface BlockStreamerOptions {
18
+ /** Minimum characters before emitting a block. Default: 400. */
19
+ minChars: number;
20
+ /** Force-emit when buffer exceeds this size. Default: 1000. */
21
+ maxChars: number;
22
+ /** Emit buffered text after this many ms of inactivity. Default: 1500. */
23
+ idleMs: number;
24
+ /** Callback to deliver a completed block. Called with trimmed text. */
25
+ send: (text: string) => Promise<void>;
26
+ }
27
+ export declare class BlockStreamer {
28
+ private buffer;
29
+ private idleTimer;
30
+ private sending;
31
+ private opts;
32
+ /** Number of blocks emitted so far. */
33
+ blockCount: number;
34
+ constructor(opts: BlockStreamerOptions);
35
+ /** Feed a new text chunk from the agent stream. */
36
+ push(chunk: string): void;
37
+ /** Flush all remaining buffered text. Awaits all pending sends. */
38
+ flush(): Promise<void>;
39
+ private checkEmit;
40
+ private onIdle;
41
+ private emitBlock;
42
+ /**
43
+ * Find the last paragraph boundary (\n\n) in the buffer.
44
+ * Returns the position after the boundary, or -1 if no suitable boundary
45
+ * exists at or after minChars.
46
+ */
47
+ private findBlockBoundary;
48
+ /**
49
+ * Find the best break point at or before maxPos.
50
+ * Prefers paragraph break > newline > space > maxPos.
51
+ */
52
+ private findBreakPoint;
53
+ private clearIdleTimer;
54
+ }
@@ -0,0 +1,115 @@
1
+ /**
2
+ * BlockStreamer — progressive multi-message delivery for channels.
3
+ *
4
+ * Accumulates text chunks from the agent's streaming response and emits
5
+ * completed "blocks" (paragraphs / sections) as separate channel messages
6
+ * while the agent is still working. This gives users a natural conversation
7
+ * flow instead of waiting 30–120 seconds for a single wall of text.
8
+ *
9
+ * Emission triggers:
10
+ * 1. Buffer ≥ maxChars → force-split at best break point
11
+ * 2. Buffer ≥ minChars AND a paragraph boundary (\n\n) exists → emit up to boundary
12
+ * 3. Idle timer fires (no chunk for idleMs) AND buffer ≥ minChars → emit buffer
13
+ * 4. flush() called (response complete) → emit everything remaining
14
+ *
15
+ * All sends are serialized — the next block waits for the previous send to complete.
16
+ */
17
+ export class BlockStreamer {
18
+ buffer = '';
19
+ idleTimer = null;
20
+ sending = Promise.resolve();
21
+ opts;
22
+ /** Number of blocks emitted so far. */
23
+ blockCount = 0;
24
+ constructor(opts) {
25
+ this.opts = opts;
26
+ }
27
+ /** Feed a new text chunk from the agent stream. */
28
+ push(chunk) {
29
+ this.buffer += chunk;
30
+ this.clearIdleTimer();
31
+ this.checkEmit();
32
+ if (this.buffer.length > 0 && this.opts.idleMs > 0) {
33
+ this.idleTimer = setTimeout(() => this.onIdle(), this.opts.idleMs);
34
+ }
35
+ }
36
+ /** Flush all remaining buffered text. Awaits all pending sends. */
37
+ async flush() {
38
+ this.clearIdleTimer();
39
+ if (this.buffer.length > 0) {
40
+ this.emitBlock(this.buffer);
41
+ this.buffer = '';
42
+ }
43
+ await this.sending;
44
+ }
45
+ // ---------------------------------------------------------------------------
46
+ // Internal
47
+ // ---------------------------------------------------------------------------
48
+ checkEmit() {
49
+ // 1. Force-split if buffer exceeds maxChars
50
+ while (this.buffer.length >= this.opts.maxChars) {
51
+ const bp = this.findBreakPoint(this.buffer, this.opts.maxChars);
52
+ this.emitBlock(this.buffer.slice(0, bp));
53
+ this.buffer = this.buffer.slice(bp);
54
+ }
55
+ // 2. Emit at paragraph boundary if we have enough text
56
+ if (this.buffer.length >= this.opts.minChars) {
57
+ const bp = this.findBlockBoundary(this.buffer);
58
+ if (bp > 0) {
59
+ this.emitBlock(this.buffer.slice(0, bp));
60
+ this.buffer = this.buffer.slice(bp);
61
+ }
62
+ }
63
+ }
64
+ onIdle() {
65
+ this.idleTimer = null;
66
+ if (this.buffer.length >= this.opts.minChars) {
67
+ this.emitBlock(this.buffer);
68
+ this.buffer = '';
69
+ }
70
+ }
71
+ emitBlock(text) {
72
+ const trimmed = text.trim();
73
+ if (!trimmed)
74
+ return;
75
+ this.blockCount++;
76
+ this.sending = this.sending
77
+ .then(() => this.opts.send(trimmed))
78
+ .catch(() => { });
79
+ }
80
+ /**
81
+ * Find the last paragraph boundary (\n\n) in the buffer.
82
+ * Returns the position after the boundary, or -1 if no suitable boundary
83
+ * exists at or after minChars.
84
+ */
85
+ findBlockBoundary(text) {
86
+ const last = text.lastIndexOf('\n\n');
87
+ if (last < 0 || last < this.opts.minChars)
88
+ return -1;
89
+ return last + 2;
90
+ }
91
+ /**
92
+ * Find the best break point at or before maxPos.
93
+ * Prefers paragraph break > newline > space > maxPos.
94
+ */
95
+ findBreakPoint(text, maxPos) {
96
+ const sub = text.slice(0, maxPos);
97
+ const para = sub.lastIndexOf('\n\n');
98
+ if (para > 0)
99
+ return para + 2;
100
+ const nl = sub.lastIndexOf('\n');
101
+ if (nl > 0)
102
+ return nl + 1;
103
+ const sp = sub.lastIndexOf(' ');
104
+ if (sp > 0)
105
+ return sp + 1;
106
+ return maxPos;
107
+ }
108
+ clearIdleTimer() {
109
+ if (this.idleTimer !== null) {
110
+ clearTimeout(this.idleTimer);
111
+ this.idleTimer = null;
112
+ }
113
+ }
114
+ }
115
+ //# sourceMappingURL=BlockStreamer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BlockStreamer.js","sourceRoot":"","sources":["../src/BlockStreamer.ts"],"names":[],"mappings":"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"}
@@ -17,8 +17,12 @@ export declare abstract class ChannelBase {
17
17
  protected name: string;
18
18
  private instructedSessions;
19
19
  private commands;
20
- /** Per-session promise chain to serialize prompt + send. */
20
+ /** Per-session promise chain to serialize prompt + send (followup mode). */
21
21
  private sessionQueues;
22
+ /** Per-session active prompt tracking for dispatch modes. */
23
+ private activePrompts;
24
+ /** Per-session message buffer for collect mode. */
25
+ private collectBuffers;
22
26
  constructor(name: string, config: ChannelConfig, bridge: AcpBridge, options?: ChannelBaseOptions);
23
27
  abstract connect(): Promise<void>;
24
28
  abstract sendMessage(chatId: string, text: string): Promise<void>;
@@ -26,6 +30,29 @@ export declare abstract class ChannelBase {
26
30
  /** Replace the bridge instance (used after crash recovery restart). */
27
31
  setBridge(bridge: AcpBridge): void;
28
32
  onToolCall(_chatId: string, _event: ToolCallEvent): void;
33
+ /**
34
+ * Called when a prompt actually begins processing (inside the session queue).
35
+ * Override to show a platform-specific working indicator (e.g., typing, reaction).
36
+ * Not called for buffered messages (collect mode) or gated/blocked messages.
37
+ */
38
+ protected onPromptStart(_chatId: string, _sessionId: string, _messageId?: string): void;
39
+ /**
40
+ * Called when a prompt finishes (response sent or cancelled).
41
+ * Override to hide the working indicator.
42
+ */
43
+ protected onPromptEnd(_chatId: string, _sessionId: string, _messageId?: string): void;
44
+ /**
45
+ * Called for each text chunk as the agent streams its response.
46
+ * Override to implement progressive display (e.g., updating an AI card in-place).
47
+ * Default: no-op (chunks are collected internally and delivered via onResponseComplete).
48
+ */
49
+ protected onResponseChunk(_chatId: string, _chunk: string, _sessionId: string): void;
50
+ /**
51
+ * Called when the agent's full response is ready.
52
+ * Override to customize delivery (e.g., finalize an AI card).
53
+ * Default: calls sendMessage() with the full response text.
54
+ */
55
+ protected onResponseComplete(chatId: string, fullText: string, _sessionId: string): Promise<void>;
29
56
  /**
30
57
  * Register a slash command handler. Subclasses can call this to add
31
58
  * platform-specific commands (e.g., /start for Telegram).
@@ -1,3 +1,4 @@
1
+ import { BlockStreamer } from './BlockStreamer.js';
1
2
  import { GroupGate } from './GroupGate.js';
2
3
  import { SenderGate } from './SenderGate.js';
3
4
  import { PairingStore } from './PairingStore.js';
@@ -11,8 +12,12 @@ export class ChannelBase {
11
12
  name;
12
13
  instructedSessions = new Set();
13
14
  commands = new Map();
14
- /** Per-session promise chain to serialize prompt + send. */
15
+ /** Per-session promise chain to serialize prompt + send (followup mode). */
15
16
  sessionQueues = new Map();
17
+ /** Per-session active prompt tracking for dispatch modes. */
18
+ activePrompts = new Map();
19
+ /** Per-session message buffer for collect mode. */
20
+ collectBuffers = new Map();
16
21
  constructor(name, config, bridge, options) {
17
22
  this.name = name;
18
23
  this.config = config;
@@ -40,6 +45,31 @@ export class ChannelBase {
40
45
  this.bridge = bridge;
41
46
  }
42
47
  onToolCall(_chatId, _event) { }
48
+ /**
49
+ * Called when a prompt actually begins processing (inside the session queue).
50
+ * Override to show a platform-specific working indicator (e.g., typing, reaction).
51
+ * Not called for buffered messages (collect mode) or gated/blocked messages.
52
+ */
53
+ onPromptStart(_chatId, _sessionId, _messageId) { }
54
+ /**
55
+ * Called when a prompt finishes (response sent or cancelled).
56
+ * Override to hide the working indicator.
57
+ */
58
+ onPromptEnd(_chatId, _sessionId, _messageId) { }
59
+ /**
60
+ * Called for each text chunk as the agent streams its response.
61
+ * Override to implement progressive display (e.g., updating an AI card in-place).
62
+ * Default: no-op (chunks are collected internally and delivered via onResponseComplete).
63
+ */
64
+ onResponseChunk(_chatId, _chunk, _sessionId) { }
65
+ /**
66
+ * Called when the agent's full response is ready.
67
+ * Override to customize delivery (e.g., finalize an AI card).
68
+ * Default: calls sendMessage() with the full response text.
69
+ */
70
+ async onResponseComplete(chatId, fullText, _sessionId) {
71
+ await this.sendMessage(chatId, fullText);
72
+ }
43
73
  /**
44
74
  * Register a slash command handler. Subclasses can call this to add
45
75
  * platform-specific commands (e.g., /start for Telegram).
@@ -151,21 +181,138 @@ export class ChannelBase {
151
181
  if (envelope.referencedText) {
152
182
  promptText = `[Replying to: "${envelope.referencedText}"]\n\n${promptText}`;
153
183
  }
184
+ // Resolve attachments: extract image for bridge, append file paths to text
185
+ let imageBase64 = envelope.imageBase64;
186
+ let imageMimeType = envelope.imageMimeType;
187
+ if (envelope.attachments?.length) {
188
+ const filePaths = [];
189
+ for (const att of envelope.attachments) {
190
+ if (att.type === 'image' && att.data && !imageBase64) {
191
+ imageBase64 = att.data;
192
+ imageMimeType = att.mimeType;
193
+ }
194
+ else if (att.filePath) {
195
+ const label = att.type === 'file' ? 'file' : att.type;
196
+ const name = att.fileName ? ` "${att.fileName}"` : '';
197
+ filePaths.push(`User sent a ${label}${name}. It has been saved to: ${att.filePath}`);
198
+ }
199
+ }
200
+ if (filePaths.length > 0) {
201
+ promptText = promptText + '\n\n' + filePaths.join('\n');
202
+ }
203
+ }
154
204
  // Prepend channel instructions on first message of a session
155
205
  if (this.config.instructions && !this.instructedSessions.has(sessionId)) {
156
206
  promptText = `${this.config.instructions}\n\n${promptText}`;
157
207
  this.instructedSessions.add(sessionId);
158
208
  }
159
- // Serialize prompt + send per session to prevent textChunk listener
160
- // pollution when concurrent messages hit the same session.
209
+ // Resolve dispatch mode: per-group override → channel config → default
210
+ const groupCfg = envelope.isGroup
211
+ ? this.config.groups[envelope.chatId] || this.config.groups['*']
212
+ : undefined;
213
+ const mode = groupCfg?.dispatchMode || this.config.dispatchMode || 'steer';
214
+ const active = this.activePrompts.get(sessionId);
215
+ if (active) {
216
+ // A prompt is already running for this session
217
+ switch (mode) {
218
+ case 'collect': {
219
+ // Buffer the message; it will be coalesced when the active prompt finishes
220
+ let buffer = this.collectBuffers.get(sessionId);
221
+ if (!buffer) {
222
+ buffer = [];
223
+ this.collectBuffers.set(sessionId, buffer);
224
+ }
225
+ buffer.push({ text: promptText, envelope });
226
+ return;
227
+ }
228
+ case 'steer': {
229
+ // Cancel the running prompt, then fall through to send a new one
230
+ active.cancelled = true;
231
+ await this.bridge.cancelSession(sessionId).catch(() => { });
232
+ // Wait for the active prompt to finish winding down
233
+ await active.done;
234
+ // Prepend a cancellation note so the agent understands context
235
+ promptText = `[The user sent a new message while you were working. Their previous request has been cancelled.]\n\n${promptText}`;
236
+ break;
237
+ }
238
+ case 'followup': {
239
+ // Chain onto the session queue (existing sequential behavior)
240
+ break;
241
+ }
242
+ default: {
243
+ // Exhaustive check — should never happen
244
+ const _exhaustive = mode;
245
+ throw new Error(`Unknown dispatch mode: ${_exhaustive}`);
246
+ }
247
+ }
248
+ }
249
+ // Run the prompt (with followup-mode serialization for safety)
161
250
  const prev = this.sessionQueues.get(sessionId) ?? Promise.resolve();
251
+ const useBlockStreaming = this.config.blockStreaming === 'on';
162
252
  const current = prev.then(async () => {
163
- const response = await this.bridge.prompt(sessionId, promptText, {
164
- imageBase64: envelope.imageBase64,
165
- imageMimeType: envelope.imageMimeType,
253
+ // Register this prompt as active
254
+ let doneResolve = () => { };
255
+ const done = new Promise((r) => {
256
+ doneResolve = r;
166
257
  });
167
- if (response) {
168
- await this.sendMessage(envelope.chatId, response);
258
+ const promptState = { cancelled: false, done, resolve: doneResolve };
259
+ this.activePrompts.set(sessionId, promptState);
260
+ this.onPromptStart(envelope.chatId, sessionId, envelope.messageId);
261
+ const streamer = useBlockStreaming
262
+ ? new BlockStreamer({
263
+ minChars: this.config.blockStreamingChunk?.minChars ?? 400,
264
+ maxChars: this.config.blockStreamingChunk?.maxChars ?? 1000,
265
+ idleMs: this.config.blockStreamingCoalesce?.idleMs ?? 1500,
266
+ send: (text) => this.sendMessage(envelope.chatId, text),
267
+ })
268
+ : null;
269
+ const onChunk = (sid, chunk) => {
270
+ if (sid === sessionId) {
271
+ this.onResponseChunk(envelope.chatId, chunk, sessionId);
272
+ streamer?.push(chunk);
273
+ }
274
+ };
275
+ this.bridge.on('textChunk', onChunk);
276
+ try {
277
+ const response = await this.bridge.prompt(sessionId, promptText, {
278
+ imageBase64,
279
+ imageMimeType,
280
+ });
281
+ // If cancelled (steer mode), skip sending the response
282
+ if (!promptState.cancelled && response) {
283
+ if (streamer) {
284
+ await streamer.flush();
285
+ }
286
+ else {
287
+ await this.onResponseComplete(envelope.chatId, response, sessionId);
288
+ }
289
+ }
290
+ }
291
+ finally {
292
+ this.bridge.off('textChunk', onChunk);
293
+ this.onPromptEnd(envelope.chatId, sessionId, envelope.messageId);
294
+ this.activePrompts.delete(sessionId);
295
+ // Signal any steer waiter that we're done
296
+ promptState.resolve();
297
+ // Drain collect buffer if any messages accumulated
298
+ const buffer = this.collectBuffers.get(sessionId);
299
+ if (buffer && buffer.length > 0) {
300
+ this.collectBuffers.delete(sessionId);
301
+ const coalesced = buffer.map((b) => b.text).join('\n\n');
302
+ const lastEnvelope = buffer[buffer.length - 1].envelope;
303
+ // Re-enter handleInbound with the coalesced message
304
+ const syntheticEnvelope = {
305
+ ...lastEnvelope,
306
+ text: coalesced,
307
+ // Clear attachments/references — already resolved in original text
308
+ referencedText: undefined,
309
+ attachments: undefined,
310
+ imageBase64: undefined,
311
+ imageMimeType: undefined,
312
+ };
313
+ // Queue the coalesced prompt (don't await to avoid deadlock on the queue)
314
+ this.handleInbound(syntheticEnvelope).catch(() => { });
315
+ }
169
316
  }
170
317
  });
171
318
  this.sessionQueues.set(sessionId, current.catch(() => { }));
@@ -1 +1 @@
1
- {"version":3,"file":"ChannelBase.js","sourceRoot":"","sources":["../src/ChannelBase.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ChannelBase.js","sourceRoot":"","sources":["../src/ChannelBase.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -1,5 +1,7 @@
1
1
  export { AcpBridge } from './AcpBridge.js';
2
2
  export type { AcpBridgeOptions, AvailableCommand, ToolCallEvent, } from './AcpBridge.js';
3
+ export { BlockStreamer } from './BlockStreamer.js';
4
+ export type { BlockStreamerOptions } from './BlockStreamer.js';
3
5
  export { ChannelBase } from './ChannelBase.js';
4
6
  export type { ChannelBaseOptions } from './ChannelBase.js';
5
7
  export { PairingStore } from './PairingStore.js';
@@ -9,4 +11,4 @@ export type { GroupCheckResult } from './GroupGate.js';
9
11
  export { SenderGate } from './SenderGate.js';
10
12
  export type { SenderCheckResult } from './SenderGate.js';
11
13
  export { SessionRouter } from './SessionRouter.js';
12
- export type { ChannelConfig, ChannelPlugin, ChannelType, Envelope, GroupConfig, GroupPolicy, SenderPolicy, SessionScope, SessionTarget, } from './types.js';
14
+ export type { Attachment, BlockStreamingChunkConfig, BlockStreamingCoalesceConfig, ChannelConfig, ChannelPlugin, ChannelType, DispatchMode, Envelope, GroupConfig, GroupPolicy, SenderPolicy, SessionScope, SessionTarget, } from './types.js';
package/dist/index.js CHANGED
@@ -1,4 +1,5 @@
1
1
  export { AcpBridge } from './AcpBridge.js';
2
+ export { BlockStreamer } from './BlockStreamer.js';
2
3
  export { ChannelBase } from './ChannelBase.js';
3
4
  export { PairingStore } from './PairingStore.js';
4
5
  export { GroupGate } from './GroupGate.js';
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAM3C,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAE/C,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEjD,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAE3C,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAE7C,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAM3C,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAEnD,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAE/C,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEjD,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAE3C,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAE7C,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC"}
package/dist/types.d.ts CHANGED
@@ -4,8 +4,20 @@ export type SenderPolicy = 'allowlist' | 'pairing' | 'open';
4
4
  export type SessionScope = 'user' | 'thread' | 'single';
5
5
  export type ChannelType = string;
6
6
  export type GroupPolicy = 'disabled' | 'allowlist' | 'open';
7
+ export type DispatchMode = 'collect' | 'steer' | 'followup';
7
8
  export interface GroupConfig {
8
9
  requireMention?: boolean;
10
+ dispatchMode?: DispatchMode;
11
+ }
12
+ export interface BlockStreamingChunkConfig {
13
+ /** Minimum characters before emitting a block. Default: 400. */
14
+ minChars?: number;
15
+ /** Force-emit when buffer exceeds this size. Default: 1000. */
16
+ maxChars?: number;
17
+ }
18
+ export interface BlockStreamingCoalesceConfig {
19
+ /** Emit buffered text after this many ms of inactivity. Default: 1500. */
20
+ idleMs?: number;
9
21
  }
10
22
  export interface ChannelConfig {
11
23
  type: ChannelType;
@@ -21,6 +33,26 @@ export interface ChannelConfig {
21
33
  model?: string;
22
34
  groupPolicy: GroupPolicy;
23
35
  groups: Record<string, GroupConfig>;
36
+ /** Dispatch mode for concurrent messages. Default: 'collect'. */
37
+ dispatchMode?: DispatchMode;
38
+ /** Enable block streaming — emit completed blocks as separate messages. */
39
+ blockStreaming?: 'on' | 'off';
40
+ /** Chunk size bounds for block streaming. */
41
+ blockStreamingChunk?: BlockStreamingChunkConfig;
42
+ /** Idle coalescing for block streaming. */
43
+ blockStreamingCoalesce?: BlockStreamingCoalesceConfig;
44
+ }
45
+ export interface Attachment {
46
+ /** Content category. */
47
+ type: 'image' | 'file' | 'audio' | 'video';
48
+ /** Base64-encoded data (for images or small files). */
49
+ data?: string;
50
+ /** Absolute path to a local file (for large files saved to disk). */
51
+ filePath?: string;
52
+ /** MIME type (e.g. "image/jpeg", "application/pdf"). */
53
+ mimeType: string;
54
+ /** Original file name from the platform. */
55
+ fileName?: string;
24
56
  }
25
57
  export interface Envelope {
26
58
  channelName: string;
@@ -40,6 +72,8 @@ export interface Envelope {
40
72
  imageBase64?: string;
41
73
  /** MIME type for the image (e.g. "image/jpeg", "image/png"). */
42
74
  imageMimeType?: string;
75
+ /** Structured attachments (images, files, audio, video). */
76
+ attachments?: Attachment[];
43
77
  }
44
78
  export interface SessionTarget {
45
79
  channelName: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@qwen-code/channel-base",
3
- "version": "0.14.0-preview.1",
3
+ "version": "0.14.0-preview.2",
4
4
  "description": "Base channel infrastructure for Qwen Code",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",