@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,15 @@
1
+ export declare function resolveConversationAssetCacheRoot(params: {
2
+ explicitCacheRoot?: string | null;
3
+ agentId: string;
4
+ conversationId: string;
5
+ }): string;
6
+ export declare function findCachedAssetFile(cacheRoot: string, attachmentId: string): string | null;
7
+ export declare function buildCachedAssetFilePath(cacheRoot: string, attachmentId: string, filename: string): string;
8
+ export type CachedAssetMetadata = {
9
+ filename?: string | null;
10
+ mimeType?: string | null;
11
+ };
12
+ export declare function buildCachedAssetMetadataPath(cacheRoot: string, attachmentId: string): string;
13
+ export declare function readCachedAssetMetadata(cacheRoot: string, attachmentId: string): CachedAssetMetadata | null;
14
+ export declare function writeCachedAssetMetadata(cacheRoot: string, attachmentId: string, metadata: CachedAssetMetadata): void;
15
+ export declare function sanitizeAssetFilename(filename: string): string;
@@ -0,0 +1,50 @@
1
+ import { mkdirSync, readdirSync, readFileSync, writeFileSync } from 'node:fs';
2
+ import { tmpdir } from 'node:os';
3
+ import { join, normalize, sep } from 'node:path';
4
+ const ASSET_CACHE_ROOT_DIRNAME = 'bigbang-assets';
5
+ export function resolveConversationAssetCacheRoot(params) {
6
+ const explicitCacheRoot = params.explicitCacheRoot?.trim();
7
+ const cacheRoot = explicitCacheRoot && explicitCacheRoot.length > 0
8
+ ? explicitCacheRoot
9
+ : join(tmpdir(), ASSET_CACHE_ROOT_DIRNAME, sanitizeAssetCacheSegment(params.agentId), sanitizeAssetCacheSegment(params.conversationId));
10
+ mkdirSync(cacheRoot, { recursive: true });
11
+ return cacheRoot;
12
+ }
13
+ export function findCachedAssetFile(cacheRoot, attachmentId) {
14
+ const filename = readdirSync(cacheRoot).find((entry) => entry.startsWith(`${attachmentId}--`));
15
+ return filename ? join(cacheRoot, filename) : null;
16
+ }
17
+ export function buildCachedAssetFilePath(cacheRoot, attachmentId, filename) {
18
+ return join(cacheRoot, `${attachmentId}--${sanitizeAssetFilename(filename)}`);
19
+ }
20
+ export function buildCachedAssetMetadataPath(cacheRoot, attachmentId) {
21
+ return join(cacheRoot, `${attachmentId}.metadata.json`);
22
+ }
23
+ export function readCachedAssetMetadata(cacheRoot, attachmentId) {
24
+ try {
25
+ const raw = readFileSync(buildCachedAssetMetadataPath(cacheRoot, attachmentId), 'utf8');
26
+ const parsed = JSON.parse(raw);
27
+ return parsed && typeof parsed === 'object' ? parsed : null;
28
+ }
29
+ catch {
30
+ return null;
31
+ }
32
+ }
33
+ export function writeCachedAssetMetadata(cacheRoot, attachmentId, metadata) {
34
+ writeFileSync(buildCachedAssetMetadataPath(cacheRoot, attachmentId), JSON.stringify({
35
+ ...(metadata.filename ? { filename: metadata.filename } : {}),
36
+ ...(metadata.mimeType ? { mimeType: metadata.mimeType } : {}),
37
+ }), 'utf8');
38
+ }
39
+ export function sanitizeAssetFilename(filename) {
40
+ const normalized = normalize(filename).split(sep).pop()?.trim() ?? '';
41
+ return normalized
42
+ .replace(/[^A-Za-z0-9._-]+/g, '_')
43
+ .replace(/_+/g, '_')
44
+ .replace(/^_+|_+$/g, '')
45
+ || 'asset';
46
+ }
47
+ function sanitizeAssetCacheSegment(value) {
48
+ const normalized = value.trim() || 'unknown';
49
+ return encodeURIComponent(normalized).replace(/%/g, '_');
50
+ }
@@ -0,0 +1,3 @@
1
+ import type { RelevantContextBundle, RelevantContextBundleItem } from '@bbigbang/protocol';
2
+ export type { RelevantContextBundle, RelevantContextBundleItem };
3
+ export declare function formatContextBundleToolText(bundle: RelevantContextBundle): string;
@@ -0,0 +1,82 @@
1
+ export function formatContextBundleToolText(bundle) {
2
+ const lines = ['## Relevant Context Bundle'];
3
+ lines.push(`Current: ${bundle.currentConversation.replyTarget} [${bundle.currentConversation.surfaceKind}, ${bundle.currentConversation.status}]`);
4
+ lines.push(`Recommended next action: ${bundle.recommendedNextAction}`);
5
+ lines.push(`Why: ${bundle.recommendedNextActionReason}`);
6
+ if (bundle.suggestedHistoryReads.length > 0) {
7
+ lines.push('', 'Suggested history reads:');
8
+ for (const suggestion of bundle.suggestedHistoryReads) {
9
+ const parts = [suggestion.target];
10
+ if (suggestion.around)
11
+ parts.push(`around=${suggestion.around}`);
12
+ if (suggestion.includeRoot)
13
+ parts.push('include_root=true');
14
+ parts.push(`reason=${suggestion.reason}`);
15
+ lines.push(`- ${parts.join(' ')}`);
16
+ }
17
+ }
18
+ lines.push('', `Items (${bundle.items.length}/${bundle.totalCount})`);
19
+ if (bundle.items.length === 0) {
20
+ lines.push('- No related surface, task, or handoff scored above zero.');
21
+ }
22
+ else {
23
+ for (const item of bundle.items) {
24
+ lines.push(`- ${formatBundleItem(item)}`);
25
+ }
26
+ }
27
+ if (bundle.truncated) {
28
+ const overflow = Object.entries(bundle.overflowByStatus)
29
+ .map(([status, count]) => `${status}=${count}`)
30
+ .join(', ');
31
+ lines.push('', `Overflow: ${overflow || 'additional items omitted'}`);
32
+ }
33
+ return lines.join('\n');
34
+ }
35
+ function formatBundleItem(item) {
36
+ const reasonText = item.reasons
37
+ .map((reason) => reason.detail ? `${reason.code}(${reason.detail})` : reason.code)
38
+ .join(', ');
39
+ if (item.kind === 'surface') {
40
+ const parts = [
41
+ `[surface score=${item.score}] ${item.replyTarget} [${item.status}]`,
42
+ `surface=${item.surfaceKind}`,
43
+ `reasons=${reasonText}`,
44
+ ];
45
+ if (item.boundTask)
46
+ parts.push(`task=${formatTaskIdentity(item.boundTask.agentTaskRef, item.boundTask.taskNumber)} [${item.boundTask.status}]`);
47
+ if (item.goal)
48
+ parts.push(`goal=${item.goal}`);
49
+ if (item.nextStep)
50
+ parts.push(`next=${item.nextStep}`);
51
+ return parts.join(' ');
52
+ }
53
+ if (item.kind === 'task') {
54
+ const parts = [
55
+ `[task score=${item.score}] ${formatTaskIdentity(item.agentTaskRef, item.taskNumber)} [${item.status}]`,
56
+ `title=${item.title}`,
57
+ `reasons=${reasonText}`,
58
+ ];
59
+ if (item.threadTarget)
60
+ parts.push(`thread=${item.threadTarget}`);
61
+ else if (item.sourceTarget)
62
+ parts.push(`source=${item.sourceTarget}`);
63
+ return parts.join(' ');
64
+ }
65
+ const parts = [
66
+ `[handoff score=${item.score}] ${item.handoffId} ${item.mode} [${item.status}]`,
67
+ `${item.sourceTarget ?? item.sourceConversationId} -> ${item.targetReplyTarget}`,
68
+ `reasons=${reasonText}`,
69
+ ];
70
+ if (item.relatedTaskRef)
71
+ parts.push(`task=${item.relatedTaskRef}`);
72
+ return parts.join(' ');
73
+ }
74
+ function formatTaskIdentity(agentTaskRef, taskNumber) {
75
+ if (agentTaskRef && taskNumber != null)
76
+ return `${agentTaskRef} · #t${taskNumber}`;
77
+ if (agentTaskRef)
78
+ return agentTaskRef;
79
+ if (taskNumber != null)
80
+ return `#t${taskNumber}`;
81
+ return 'task';
82
+ }
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * channel-bridge — MCP server for bigbang agents.
4
+ *
5
+ * Mirrors Slock's chat-bridge.js: exposes send_message, check_messages,
6
+ * list_server, read_history, and task board tools over MCP stdio transport.
7
+ * The tools call bigbang's internal agent API (/api/internal/agent/:id/*).
8
+ *
9
+ * Usage:
10
+ * channel-bridge --agent-id <id> --server-url <url> [--auth-token <token>]
11
+ */
12
+ export {};