@bbigbang/channel-bridge 0.1.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.
@@ -0,0 +1,349 @@
1
+ function formatTaskIdentity(agentTaskRef, taskNumber) {
2
+ if (agentTaskRef && taskNumber != null)
3
+ return `${agentTaskRef} · #t${taskNumber}`;
4
+ if (agentTaskRef)
5
+ return agentTaskRef;
6
+ if (taskNumber != null)
7
+ return `#t${taskNumber}`;
8
+ return 'task';
9
+ }
10
+ export function formatToolResult(format, text, data) {
11
+ if (format === 'json') {
12
+ return JSON.stringify(data, null, 2);
13
+ }
14
+ if (format === 'both') {
15
+ return `${text}\n\n## Structured\n\`\`\`json\n${JSON.stringify(data, null, 2)}\n\`\`\``;
16
+ }
17
+ return text;
18
+ }
19
+ export function formatSendMessageDiagnostics(data) {
20
+ const diagnostics = data.diagnostics && typeof data.diagnostics === 'object'
21
+ ? data.diagnostics
22
+ : null;
23
+ const panel = diagnostics?.panel && typeof diagnostics.panel === 'object'
24
+ ? diagnostics.panel
25
+ : null;
26
+ const unattachedPanelIds = Array.isArray(panel?.unattachedProducedPanelIds)
27
+ ? panel.unattachedProducedPanelIds
28
+ .map((id) => typeof id === 'string' ? id.trim() : '')
29
+ .filter((id) => id.length > 0)
30
+ : [];
31
+ if (unattachedPanelIds.length === 0)
32
+ return '';
33
+ const recommendation = typeof panel?.recommendation === 'string' && panel.recommendation.trim()
34
+ ? `\nRecommendation: ${panel.recommendation.trim()}`
35
+ : '';
36
+ return `\n\nPanel diagnostic: this run produced additional panels that were not attached to this message: ${unattachedPanelIds.join(', ')}.${recommendation}`;
37
+ }
38
+ export function formatConversationListText(conversations) {
39
+ if (conversations.length === 0)
40
+ return 'No conversations found.';
41
+ const lines = conversations.map((conversation) => {
42
+ const context = getConversationContext(conversation);
43
+ const parts = [
44
+ `${conversation.replyTarget} [${conversation.status}]`,
45
+ `surface=${conversation.surfaceKind}`,
46
+ `unread=${conversation.unreadCount}`,
47
+ `queued=${conversation.queuedPromptCount}`,
48
+ ];
49
+ if (context?.myRole)
50
+ parts.push(`role=${context.myRole}`);
51
+ if (context?.goal)
52
+ parts.push(`goal=${context.goal}`);
53
+ if (context?.nextStep)
54
+ parts.push(`next=${context.nextStep}`);
55
+ if (context?.blockers?.length)
56
+ parts.push(`blockers=${context.blockers.join('; ')}`);
57
+ if (context?.lastMessage) {
58
+ parts.push(`last=@${context.lastMessage.senderName}: ${context.lastMessage.preview}`);
59
+ }
60
+ return `- ${parts.join(' ')}`;
61
+ }).join('\n');
62
+ return `## My Conversations (${conversations.length})\n\n${lines}`;
63
+ }
64
+ export function formatConversationSummaryToolText(conversation) {
65
+ if (conversation.reportText?.trim())
66
+ return conversation.reportText.trim();
67
+ const context = getConversationContext(conversation);
68
+ const lines = [
69
+ `Target: ${conversation.replyTarget}`,
70
+ `Status: ${conversation.status}`,
71
+ `Surface: ${conversation.surfaceKind}`,
72
+ `Unread: ${conversation.unreadCount}`,
73
+ `Queued prompts: ${conversation.queuedPromptCount}`,
74
+ ];
75
+ if (context?.goal)
76
+ lines.push(`Goal: ${context.goal}`);
77
+ if (context?.recentState)
78
+ lines.push(`Recent state: ${context.recentState}`);
79
+ if (context?.blockers?.length)
80
+ lines.push(`Blockers: ${context.blockers.join('; ')}`);
81
+ if (context?.nextStep)
82
+ lines.push(`Next: ${context.nextStep}`);
83
+ if (context?.myRole)
84
+ lines.push(`My role: ${context.myRole}`);
85
+ if (context?.ownerName)
86
+ lines.push(`Owner: @${context.ownerName}`);
87
+ if (context?.boundTask) {
88
+ lines.push(`Bound task: ${formatTaskIdentity(context.boundTask.agentTaskRef, context.boundTask.taskNumber)} [${context.boundTask.status}]`);
89
+ }
90
+ if (context?.participants?.length) {
91
+ lines.push(`Participants: ${context.participants.map((name) => `@${name}`).join(', ')}`);
92
+ }
93
+ if (context?.activeHandoff) {
94
+ lines.push(`Active handoff: ${context.activeHandoff.handoffId} ${context.activeHandoff.mode} [${context.activeHandoff.status}] -> ${context.activeHandoff.targetReplyTarget}`);
95
+ }
96
+ if (context?.lastMessage) {
97
+ lines.push(`Last message: @${context.lastMessage.senderName} — ${context.lastMessage.preview}`);
98
+ }
99
+ return lines.join('\n');
100
+ }
101
+ export function formatRuntimePresenceToolText(presence) {
102
+ if (presence.reportText?.trim())
103
+ return presence.reportText.trim();
104
+ const driverNames = (presence.runtime?.runtimeDrivers ?? []).map((driver) => driver.agentType).join(', ') || 'none';
105
+ const lines = [
106
+ '[Runtime presence]',
107
+ `node: ${presence.node?.nodeId ?? 'none'}${presence.node?.machineName ? ` (${presence.node.machineName})` : ''} [${presence.node?.status ?? 'unknown'}]`,
108
+ `runtime: workspace_root=${presence.runtime?.workspaceRoot ?? 'unknown'} | terminals=${presence.runtime?.terminalBackendAvailable == null ? 'unknown' : (presence.runtime.terminalBackendAvailable ? 'yes' : 'no')} | drivers=${driverNames}`,
109
+ `hosts: total=${presence.summary?.totalHosts ?? 0}, active=${presence.summary?.activeHosts ?? 0}, idle=${presence.summary?.idleHosts ?? 0}, failed=${presence.summary?.failedHosts ?? 0}, approval=${presence.summary?.hostsWithPendingApproval ?? 0}, resumable=${presence.summary?.resumableHosts ?? 0}`,
110
+ ];
111
+ if (presence.currentHost) {
112
+ lines.push(`current_host: ${(presence.currentHost.replyTarget ?? presence.currentHost.hostKey)} [${presence.currentHost.state}] | pending_dispatch=${presence.currentHost.pendingDispatchCount} | approval=${presence.currentHost.hasPendingApproval ? 'yes' : 'no'}`);
113
+ }
114
+ return lines.join('\n');
115
+ }
116
+ export function buildCompactRuntimePresenceData(presence) {
117
+ return {
118
+ generatedAt: presence.generatedAt ?? null,
119
+ node: presence.node ?? null,
120
+ runtime: presence.runtime
121
+ ? {
122
+ workspaceRoot: presence.runtime.workspaceRoot ?? null,
123
+ terminalBackendAvailable: presence.runtime.terminalBackendAvailable ?? null,
124
+ runtimeDrivers: (presence.runtime.runtimeDrivers ?? []).map((driver) => driver.agentType),
125
+ capabilities: presence.runtime.capabilities
126
+ ? Object.entries(presence.runtime.capabilities)
127
+ .filter(([, enabled]) => Boolean(enabled))
128
+ .map(([name]) => name)
129
+ : [],
130
+ }
131
+ : null,
132
+ summary: presence.summary ?? null,
133
+ currentHost: presence.currentHost
134
+ ? {
135
+ target: presence.currentHost.replyTarget ?? null,
136
+ state: presence.currentHost.state,
137
+ pendingDispatchCount: presence.currentHost.pendingDispatchCount,
138
+ hasPendingApproval: presence.currentHost.hasPendingApproval,
139
+ resumable: presence.currentHost.resumable,
140
+ }
141
+ : null,
142
+ otherHosts: (presence.otherHosts ?? []).map((host) => ({
143
+ target: host.replyTarget ?? null,
144
+ state: host.state,
145
+ pendingDispatchCount: host.pendingDispatchCount,
146
+ hasPendingApproval: host.hasPendingApproval,
147
+ })),
148
+ };
149
+ }
150
+ export function formatSelfStateToolText(state) {
151
+ if (state.reportText?.trim())
152
+ return state.reportText.trim();
153
+ const currentConversationId = state.currentConversation?.conversationId ?? null;
154
+ const otherSurfaces = (state.conversations ?? []).filter((item) => item.conversationId !== currentConversationId);
155
+ const lines = ['[Agent self state]'];
156
+ if (state.currentContext?.myRole)
157
+ lines.push(`role_here: ${state.currentContext.myRole}`);
158
+ if (state.currentContext?.boundTask) {
159
+ lines.push(`bound_task: ${formatTaskIdentity(state.currentContext.boundTask.agentTaskRef, state.currentContext.boundTask.taskNumber)} [${state.currentContext.boundTask.status}]`);
160
+ }
161
+ lines.push('other_surfaces:');
162
+ if (otherSurfaces.length === 0) {
163
+ lines.push('- none');
164
+ }
165
+ else {
166
+ for (const conversation of otherSurfaces.slice(0, 6)) {
167
+ const summary = getConversationContext(conversation);
168
+ const extras = [];
169
+ if (conversation.unreadCount > 0)
170
+ extras.push(`unread=${conversation.unreadCount}`);
171
+ if (summary?.myRole)
172
+ extras.push(`role=${summary.myRole}`);
173
+ if (summary?.boundTask) {
174
+ extras.push(`task=${formatTaskIdentity(summary.boundTask.agentTaskRef, summary.boundTask.taskNumber)} [${summary.boundTask.status}]`);
175
+ }
176
+ if (summary?.activeHandoff) {
177
+ extras.push(`handoff=${summary.activeHandoff.handoffId} ${summary.activeHandoff.mode} [${summary.activeHandoff.status}]`);
178
+ }
179
+ const teaser = buildSelfStateTeaser(summary);
180
+ if (teaser)
181
+ extras.push(`teaser=${teaser}`);
182
+ lines.push(`- ${conversation.replyTarget} [${conversation.surfaceKind}, ${conversation.status}]${extras.length ? ` | ${extras.join(' | ')}` : ''}`);
183
+ }
184
+ const hiddenSurfaces = otherSurfaces.slice(6);
185
+ if (hiddenSurfaces.length > 0) {
186
+ lines.push(`- hidden=${hiddenSurfaces.length}${formatHiddenSurfaceBreakdown(hiddenSurfaces)}`);
187
+ }
188
+ }
189
+ return lines.join('\n');
190
+ }
191
+ export function buildCompactSelfStateData(state) {
192
+ const currentConversationId = state.currentConversation?.conversationId ?? null;
193
+ const currentBoundTaskId = state.currentContext?.boundTask?.taskId ?? null;
194
+ const allOtherSurfaces = (state.conversations ?? [])
195
+ .filter((conversation) => conversation.conversationId !== currentConversationId);
196
+ const otherSurfaces = allOtherSurfaces
197
+ .slice(0, 4)
198
+ .map((conversation) => {
199
+ const summary = getConversationContext(conversation);
200
+ const activeHandoff = summary?.activeHandoff ?? null;
201
+ return {
202
+ target: conversation.replyTarget,
203
+ status: conversation.status,
204
+ surfaceKind: conversation.surfaceKind,
205
+ ...(conversation.unreadCount > 0 ? { unreadCount: conversation.unreadCount } : {}),
206
+ role: summary?.myRole ?? null,
207
+ task: toCompactBoundTask(summary?.boundTask ?? null),
208
+ activeHandoff: activeHandoff
209
+ ? {
210
+ handoffId: activeHandoff.handoffId,
211
+ mode: activeHandoff.mode,
212
+ status: activeHandoff.status,
213
+ target: activeHandoff.targetReplyTarget,
214
+ }
215
+ : null,
216
+ teaser: buildSelfStateTeaser(summary),
217
+ };
218
+ });
219
+ const hiddenSurfaces = allOtherSurfaces.slice(4);
220
+ const visibleTasks = (state.recentTasks ?? [])
221
+ .filter((task) => task.taskId !== currentBoundTaskId)
222
+ .slice(0, 3);
223
+ const hiddenTasksCount = Math.max(0, (state.summary?.involvedTasks ?? 0) - (currentBoundTaskId ? 1 : 0) - visibleTasks.length);
224
+ return {
225
+ generatedAt: state.generatedAt ?? null,
226
+ agent: state.agent
227
+ ? {
228
+ name: state.agent.name ?? null,
229
+ agentType: state.agent.agentType ?? null,
230
+ joinedChannels: (state.agent.joinedChannels ?? []).map((channel) => channel.target),
231
+ }
232
+ : null,
233
+ runtimePresence: state.runtimePresence
234
+ ? buildCompactRuntimePresenceData(state.runtimePresence)
235
+ : null,
236
+ summary: state.summary
237
+ ? {
238
+ conversations: state.summary.totalConversations ?? 0,
239
+ active: state.summary.activeConversations ?? 0,
240
+ queued: state.summary.queuedConversations ?? 0,
241
+ recovering: state.summary.recoveringConversations ?? 0,
242
+ approval: state.summary.awaitingApprovalConversations ?? 0,
243
+ failed: state.summary.failedConversations ?? 0,
244
+ surfacesWithNewActivity: state.summary.surfacesWithUnread ?? 0,
245
+ pending: state.summary.pendingPrompts ?? 0,
246
+ tasks: {
247
+ claimed: state.summary.claimedTasks ?? 0,
248
+ involved: state.summary.involvedTasks ?? 0,
249
+ review: state.summary.inReviewTasks ?? 0,
250
+ },
251
+ }
252
+ : null,
253
+ current: state.currentConversation
254
+ ? {
255
+ target: state.currentConversation.replyTarget,
256
+ status: state.currentConversation.status,
257
+ surfaceKind: state.currentConversation.surfaceKind,
258
+ role: state.currentContext?.myRole ?? null,
259
+ task: toCompactBoundTask(state.currentContext?.boundTask ?? null),
260
+ blockers: (state.currentContext?.blockers ?? [])
261
+ .map((blocker) => summarizeInline(blocker, 96))
262
+ .filter((blocker) => Boolean(blocker)),
263
+ activeHandoff: state.currentContext?.activeHandoff
264
+ ? {
265
+ handoffId: state.currentContext.activeHandoff.handoffId,
266
+ mode: state.currentContext.activeHandoff.mode,
267
+ status: state.currentContext.activeHandoff.status,
268
+ target: state.currentContext.activeHandoff.targetReplyTarget,
269
+ }
270
+ : null,
271
+ }
272
+ : null,
273
+ otherSurfaces,
274
+ ...(hiddenSurfaces.length > 0
275
+ ? {
276
+ hiddenSurfaces: {
277
+ count: hiddenSurfaces.length,
278
+ byStatus: summarizeHiddenSurfaceStatuses(hiddenSurfaces),
279
+ },
280
+ }
281
+ : {}),
282
+ tasks: visibleTasks
283
+ .map((task) => ({
284
+ task: formatTaskIdentity(task.agentTaskRef, task.taskNumber),
285
+ status: task.status,
286
+ title: summarizeInline(task.title),
287
+ target: task.threadTarget ?? task.sourceTarget ?? null,
288
+ })),
289
+ ...(hiddenTasksCount > 0 ? { hiddenTasksCount } : {}),
290
+ handoffs: (state.recentHandoffs ?? [])
291
+ .filter((handoff) => handoff.status !== 'completed')
292
+ .slice(0, 3)
293
+ .map((handoff) => ({
294
+ handoffId: handoff.handoffId,
295
+ mode: handoff.mode,
296
+ status: handoff.status,
297
+ source: handoff.sourceTarget ?? null,
298
+ target: handoff.targetReplyTarget,
299
+ })),
300
+ };
301
+ }
302
+ function summarizeInline(value, maxLength = 96) {
303
+ const trimmed = value?.trim() ?? '';
304
+ if (!trimmed)
305
+ return null;
306
+ if (trimmed.length <= maxLength)
307
+ return trimmed;
308
+ return `${trimmed.slice(0, Math.max(0, maxLength - 3)).trimEnd()}...`;
309
+ }
310
+ function getConversationContext(conversation) {
311
+ return conversation?.context ?? null;
312
+ }
313
+ function buildSelfStateTeaser(summary, maxLength = 64) {
314
+ const candidates = [
315
+ summary?.boundTask?.title,
316
+ summary?.goal,
317
+ summary?.lastMessage?.preview,
318
+ ];
319
+ for (const candidate of candidates) {
320
+ const teaser = summarizeInline(candidate, maxLength);
321
+ if (teaser)
322
+ return teaser;
323
+ }
324
+ return null;
325
+ }
326
+ function formatHiddenSurfaceBreakdown(conversations) {
327
+ const parts = Object.entries(summarizeHiddenSurfaceStatuses(conversations))
328
+ .map(([status, count]) => `${status}=${count}`);
329
+ return parts.length > 0 ? `(${parts.join(',')})` : '';
330
+ }
331
+ function summarizeHiddenSurfaceStatuses(conversations) {
332
+ const order = ['active', 'queued', 'recovering', 'awaiting_approval', 'failed', 'idle'];
333
+ const counts = new Map();
334
+ for (const conversation of conversations) {
335
+ counts.set(conversation.status, (counts.get(conversation.status) ?? 0) + 1);
336
+ }
337
+ const result = {};
338
+ for (const status of order) {
339
+ const count = counts.get(status) ?? 0;
340
+ if (count > 0)
341
+ result[status] = count;
342
+ }
343
+ return result;
344
+ }
345
+ function toCompactBoundTask(boundTask) {
346
+ if (!boundTask)
347
+ return null;
348
+ return `${formatTaskIdentity(boundTask.agentTaskRef, boundTask.taskNumber)} [${boundTask.status}]`;
349
+ }
@@ -0,0 +1,3 @@
1
+ import type { TaskUpdateDelivery } from '@bbigbang/protocol';
2
+ export declare function formatTaskUpdateDeliveryText(delivery: TaskUpdateDelivery): string;
3
+ export declare function formatTaskUpdateDeliveriesSection(deliveries: TaskUpdateDelivery[]): string;
@@ -0,0 +1,17 @@
1
+ export function formatTaskUpdateDeliveryText(delivery) {
2
+ const noteTargets = delivery.recommendedNoteTargets.length > 0
3
+ ? delivery.recommendedNoteTargets.join(', ')
4
+ : 'none';
5
+ return [
6
+ delivery.summaryText,
7
+ `Recommended note targets: ${noteTargets}`,
8
+ delivery.noteGuidance,
9
+ delivery.memoryReminder,
10
+ ].join('\n');
11
+ }
12
+ export function formatTaskUpdateDeliveriesSection(deliveries) {
13
+ if (deliveries.length === 0)
14
+ return '';
15
+ const blocks = deliveries.map((delivery) => formatTaskUpdateDeliveryText(delivery)).join('\n\n');
16
+ return `\n\nTask update guidance:\n${blocks}`;
17
+ }
@@ -0,0 +1,9 @@
1
+ declare const DEFAULT_INLINE_TEXT_PREVIEW_MAX_BYTES: number;
2
+ export declare function buildInlineTextPreview(params: {
3
+ attachmentId: string;
4
+ mimeType: string;
5
+ sizeLabel: string;
6
+ fileBuffer: Buffer;
7
+ maxBytes?: number;
8
+ }): string;
9
+ export { DEFAULT_INLINE_TEXT_PREVIEW_MAX_BYTES };
@@ -0,0 +1,38 @@
1
+ const DEFAULT_INLINE_TEXT_PREVIEW_MAX_BYTES = 64 * 1024;
2
+ function trimIncompleteUtf8Suffix(buffer) {
3
+ if (buffer.length === 0)
4
+ return buffer;
5
+ let continuationBytes = 0;
6
+ while (continuationBytes < Math.min(3, buffer.length)
7
+ && (buffer[buffer.length - 1 - continuationBytes] & 0b1100_0000) === 0b1000_0000) {
8
+ continuationBytes += 1;
9
+ }
10
+ const leadIndex = buffer.length - 1 - continuationBytes;
11
+ if (leadIndex < 0) {
12
+ return buffer.subarray(0, buffer.length - continuationBytes);
13
+ }
14
+ const leadByte = buffer[leadIndex];
15
+ const expectedLength = ((leadByte & 0b1000_0000) === 0 ? 1
16
+ : (leadByte & 0b1110_0000) === 0b1100_0000 ? 2
17
+ : (leadByte & 0b1111_0000) === 0b1110_0000 ? 3
18
+ : (leadByte & 0b1111_1000) === 0b1111_0000 ? 4
19
+ : 1);
20
+ const actualLength = buffer.length - leadIndex;
21
+ if (actualLength < expectedLength) {
22
+ return buffer.subarray(0, leadIndex);
23
+ }
24
+ return buffer;
25
+ }
26
+ export function buildInlineTextPreview(params) {
27
+ const maxBytes = params.maxBytes ?? DEFAULT_INLINE_TEXT_PREVIEW_MAX_BYTES;
28
+ const truncated = params.fileBuffer.length > maxBytes;
29
+ const previewBuffer = truncated
30
+ ? params.fileBuffer.subarray(0, maxBytes)
31
+ : params.fileBuffer;
32
+ const previewText = trimIncompleteUtf8Suffix(previewBuffer).toString('utf8');
33
+ const suffix = truncated
34
+ ? `\n\n[truncated preview: showing first ${(maxBytes / 1024).toFixed(0)} KB of ${params.sizeLabel}; inspect locally for the full file.]`
35
+ : '';
36
+ return `Attachment ${params.attachmentId} (${params.mimeType}, ${params.sizeLabel}):\n\n${previewText}${suffix}`;
37
+ }
38
+ export { DEFAULT_INLINE_TEXT_PREVIEW_MAX_BYTES };
@@ -0,0 +1,7 @@
1
+ import type { AgentWorkspaceFileResult, AgentWorkspaceListResult, AgentWorkspaceInspectResult } from '@bbigbang/protocol';
2
+ export declare function formatWorkspaceInspectToolText(result: AgentWorkspaceInspectResult & {
3
+ reportText?: string | null;
4
+ }): string;
5
+ export declare function buildCompactWorkspaceInspectData(result: AgentWorkspaceInspectResult): Record<string, unknown>;
6
+ export declare function formatWorkspaceTreeToolText(result: AgentWorkspaceListResult): string;
7
+ export declare function formatWorkspaceFileToolText(result: AgentWorkspaceFileResult): string;
@@ -0,0 +1,41 @@
1
+ export function formatWorkspaceInspectToolText(result) {
2
+ if (result.reportText?.trim())
3
+ return result.reportText.trim();
4
+ const inspect = result.inspect;
5
+ return [
6
+ '[Workspace inspect]',
7
+ `node: ${result.nodeId ?? 'none'}`,
8
+ `workspace_root: ${result.workspaceRoot ?? 'none'}`,
9
+ `git: ${inspect?.isGit ? 'yes' : 'no'} | kind=${inspect?.workspaceKind ?? 'unknown'} | branch=${inspect?.branchName ?? 'none'}`,
10
+ inspect?.repoRoot ? `repo_root: ${inspect.repoRoot}` : null,
11
+ inspect?.remoteUrl ? `remote: ${inspect.remoteUrl}` : null,
12
+ ].filter(Boolean).join('\n');
13
+ }
14
+ export function buildCompactWorkspaceInspectData(result) {
15
+ return {
16
+ nodeId: result.nodeId ?? null,
17
+ workspaceRoot: result.workspaceRoot ?? null,
18
+ inspect: result.inspect ?? null,
19
+ };
20
+ }
21
+ export function formatWorkspaceTreeToolText(result) {
22
+ const prefix = result.path ? result.path : '.';
23
+ if (!result.entries.length)
24
+ return `[Workspace tree]\npath: ${prefix}\n(entries: empty)`;
25
+ const lines = result.entries.map((entry) => `- ${entry.path} [${entry.kind}]`);
26
+ return `[Workspace tree]\npath: ${prefix}\n${lines.join('\n')}`;
27
+ }
28
+ export function formatWorkspaceFileToolText(result) {
29
+ const fence = result.mimeType === 'text/markdown' ? 'markdown' : 'text';
30
+ return [
31
+ '[Workspace file]',
32
+ `path: ${result.path}`,
33
+ `mime: ${result.mimeType}`,
34
+ `size: ${result.size}`,
35
+ result.modifiedAt != null ? `modified_at: ${new Date(result.modifiedAt).toISOString()}` : null,
36
+ '',
37
+ `\`\`\`${fence}`,
38
+ result.content,
39
+ '\`\`\`',
40
+ ].filter((line) => line !== null).join('\n');
41
+ }
package/package.json ADDED
@@ -0,0 +1,36 @@
1
+ {
2
+ "name": "@bbigbang/channel-bridge",
3
+ "version": "0.1.0",
4
+ "type": "module",
5
+ "bin": {
6
+ "channel-bridge": "dist/index.js"
7
+ },
8
+ "main": "dist/index.js",
9
+ "files": [
10
+ "dist",
11
+ "!dist/**/__tests__/**",
12
+ "!dist/**/*.test.*",
13
+ "!dist/**/*.map",
14
+ "package.json"
15
+ ],
16
+ "exports": {
17
+ ".": "./dist/index.js"
18
+ },
19
+ "dependencies": {
20
+ "@modelcontextprotocol/sdk": "^1.26.0",
21
+ "zod": "^4.3.6",
22
+ "@bbigbang/protocol": "0.1.0"
23
+ },
24
+ "devDependencies": {
25
+ "@types/node": "^25.3.3",
26
+ "typescript": "^5.9.3",
27
+ "vitest": "^3.2.1"
28
+ },
29
+ "scripts": {
30
+ "build": "tsc -p tsconfig.json",
31
+ "typecheck": "tsc --noEmit -p tsconfig.json",
32
+ "lint": "echo 'No lint configured'",
33
+ "dev": "tsc -p tsconfig.json --watch",
34
+ "test": "vitest run"
35
+ }
36
+ }