@hasna/bridge 0.1.2 → 0.2.1

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/types.d.ts CHANGED
@@ -27,6 +27,13 @@ export interface WebhookChannelConfig extends BaseChannelConfig {
27
27
  export interface IMessageChannelConfig extends BaseChannelConfig {
28
28
  kind: "imessage";
29
29
  account?: string;
30
+ serviceName?: string;
31
+ defaultHandle?: string;
32
+ allowedHandles?: string[];
33
+ allowAllHandles?: boolean;
34
+ receiveMode?: "disabled" | "chat-db";
35
+ chatDbPath?: string;
36
+ pollLimit?: number;
30
37
  }
31
38
  export type ChannelConfig = TelegramChannelConfig | ConsoleChannelConfig | WebhookChannelConfig | IMessageChannelConfig;
32
39
  export interface ProfileConfig {
@@ -75,13 +82,69 @@ export interface BridgeMessage {
75
82
  channelId: string;
76
83
  text: string;
77
84
  chatId?: string;
85
+ threadId?: string;
86
+ responseTargetId?: string;
78
87
  from?: string;
79
88
  receivedAt: string;
80
89
  raw?: unknown;
81
90
  }
91
+ export type BridgeSessionStatus = "active" | "paused" | "closed";
92
+ export type AgentSessionMode = "durable" | "compatibility";
93
+ export interface AgentSessionRef {
94
+ kind: AgentKind;
95
+ mode: AgentSessionMode;
96
+ refId?: string;
97
+ createdAt?: string;
98
+ updatedAt?: string;
99
+ detail?: string;
100
+ }
101
+ export interface BridgeSession {
102
+ id: string;
103
+ agentId: string;
104
+ profileId?: string;
105
+ cwd?: string;
106
+ title?: string;
107
+ status: BridgeSessionStatus;
108
+ createdAt: string;
109
+ updatedAt: string;
110
+ lastMessageAt?: string;
111
+ agentSession?: AgentSessionRef;
112
+ }
113
+ export interface BridgeBinding {
114
+ id: string;
115
+ channelId: string;
116
+ conversationId: string;
117
+ activeSessionId: string;
118
+ defaultSessionId?: string;
119
+ createdAt: string;
120
+ updatedAt: string;
121
+ authorization?: {
122
+ chatId?: string;
123
+ from?: string;
124
+ };
125
+ }
126
+ export type LedgerStatus = "processing" | "agent_completed" | "delivered" | "skipped" | "unauthorized" | "failed";
127
+ export interface MessageLedgerEntry {
128
+ id: string;
129
+ channelId: string;
130
+ messageId: string;
131
+ conversationId?: string;
132
+ sessionId?: string;
133
+ status: LedgerStatus;
134
+ attempts: number;
135
+ firstSeenAt: string;
136
+ updatedAt: string;
137
+ terminalAt?: string;
138
+ error?: string;
139
+ responseText?: string;
140
+ deliveredResponse?: boolean;
141
+ agentExitCode?: number | null;
142
+ agentTimedOut?: boolean;
143
+ }
82
144
  export interface AgentRunInput {
83
145
  message: BridgeMessage;
84
146
  route: RouteConfig;
147
+ session?: BridgeSession;
85
148
  }
86
149
  export interface AgentRunResult {
87
150
  agentId: string;
@@ -97,6 +160,16 @@ export interface RoutedMessageResult {
97
160
  agent: AgentRunResult;
98
161
  deliveredResponse?: boolean;
99
162
  }
163
+ export interface SessionMessageResult {
164
+ kind: "session";
165
+ session?: BridgeSession;
166
+ binding?: BridgeBinding;
167
+ conversationId?: string;
168
+ agent?: AgentRunResult;
169
+ deliveredResponse?: boolean;
170
+ status: "delivered" | "no_session" | "paused" | "closed" | "unauthorized" | "no_output" | "failed";
171
+ message?: string;
172
+ }
100
173
  export interface DoctorCheck {
101
174
  name: string;
102
175
  ok: boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
@@ -1,35 +1,50 @@
1
1
  # Bridge Architecture
2
2
 
3
- `bridge` separates channel connectors from agent adapters.
3
+ `bridge` separates channel connectors from agent adapters. In `0.2.x`, the
4
+ primary product model is session-backed routing: external conversations bind to
5
+ durable bridge sessions, and bridge sessions bind to agent sessions.
4
6
 
5
7
  Channels own external transport details such as Telegram bot tokens, chat IDs,
6
- webhooks, or future iMessage transport. Agents own local execution details such
7
- as Codewith auth profiles, Claude profile homes, AIcopilot state roots, command
8
- arguments, cwd, and environment. Routes connect one channel to one agent.
8
+ webhooks, or iMessage transport. Agents own local execution details such as
9
+ Codewith auth profiles, Claude profile homes, AIcopilot state roots, cwd, and
10
+ environment. Bindings connect a channel conversation to a durable bridge
11
+ session. Routes remain a compatibility surface for explicit stateless tests.
9
12
 
10
- The package deliberately keeps Telegram-specific behavior out of Codewith,
11
- Claude, and AIcopilot integrations. Agent adapters receive plain text prompts
12
- and return stdout/stderr plus process metadata. Channel connectors decide how
13
- to receive and deliver messages.
13
+ The package deliberately keeps Telegram-specific or iMessage-specific behavior
14
+ out of Codewith, Claude, and AIcopilot integrations. Agent adapters receive
15
+ normalized session messages and return final responses or stream events. Channel
16
+ connectors decide how to receive, authorize, normalize, and deliver messages.
14
17
 
15
18
  ## Data Model
16
19
 
17
20
  - `channels`: external message transports.
18
21
  - `profiles`: reusable identity/state settings for an agent family.
19
22
  - `agents`: runnable targets, usually pointing at one profile.
20
- - `routes`: mapping rules from channel messages to agents.
23
+ - `sessions`: bridge-owned conversations with one agent target and optional
24
+ external agent session reference.
25
+ - `bindings`: mapping from normalized external conversation IDs to active
26
+ bridge sessions.
27
+ - `messageLedger`: idempotency and retry records for inbound channel messages.
28
+ - `cursors`: per-channel offsets committed after terminal processing.
29
+ - `routes`: compatibility mapping rules from channel messages to agents.
30
+
31
+ Runtime state uses `schemaVersion: 2` and is backward-compatible with the
32
+ `0.1.x` state shape that only stored `telegramOffsets`.
21
33
 
22
34
  ## Profile Model
23
35
 
24
- Codewith profiles use `authProfile` and render as `codewith --auth-profile
25
- <name> --cd <cwd> exec <prompt>`.
36
+ Codewith profiles use `authProfile`. The durable adapter should use Codewith's
37
+ background-agent surface where a noninteractive create/send/resume flow is
38
+ available. `codewith --auth-profile <name> --cd <cwd> exec <prompt>` is
39
+ compatibility mode because it is a one-shot process and does not preserve
40
+ agent-side conversation context.
26
41
 
27
42
  Claude profiles can use `home` or custom env vars so multiple accounts do not
28
43
  share local state.
29
44
 
30
- AIcopilot profiles currently use cwd/env/command isolation. The target repo
31
- work dispatched on spark02 is expected to add or document first-class profile
32
- support.
45
+ AIcopilot profiles currently use cwd/env/command isolation. The adapter must add
46
+ or consume first-class create/send/events session support before AIcopilot can
47
+ be presented as a durable bridge session target.
33
48
 
34
49
  ## Telegram
35
50
 
@@ -48,7 +63,22 @@ MCP config inspection redacts profile and agent environment values so local
48
63
  secrets are not exposed through `bridge_config`.
49
64
 
50
65
  Long-poll offsets are persisted in a private state file so process restarts do
51
- not replay already-seen updates and re-run agents.
66
+ not replay already-seen terminal updates and re-run agents. In session mode,
67
+ offsets must be committed only after the inbound message reaches a terminal
68
+ ledger state: delivered, intentionally skipped, or unauthorized. Failed
69
+ messages remain retryable and do not advance the Telegram offset.
70
+
71
+ If the agent succeeds and outbound delivery fails, the ledger stores the final
72
+ response in `agent_completed`; retry attempts deliver the stored response rather
73
+ than invoking the agent again.
74
+
75
+ When a Telegram chat has an active binding, plain text routes to that session.
76
+ When no binding exists, the bridge can reply with setup instructions and does
77
+ not invoke an agent. Route matching is still available as compatibility fallback
78
+ for explicit configured routes.
79
+
80
+ Telegram forum topics are part of the normalized conversation ID:
81
+ `telegram:<channelId>:<chatId>:<messageThreadId>`.
52
82
 
53
83
  `BRIDGE_TELEGRAM_API_BASE` can override the Telegram API origin for local tests.
54
84
  The override accepts only `http` or `https` URLs without credentials. It is not
@@ -80,3 +110,27 @@ errors.
80
110
  `bridge serve` handles per-channel poll errors without exiting in long-running
81
111
  mode. `serve --once` still fails fast so health checks and tests can catch
82
112
  misconfiguration.
113
+
114
+ ## iMessage
115
+
116
+ iMessage support is local macOS-only. The adapter must send through Messages
117
+ automation and receive through local Messages state or a documented helper mode.
118
+ It must fail closed when Automation or Full Disk Access permissions are missing.
119
+ Diagnostics should report the missing permission without reading or logging
120
+ private message contents unnecessarily.
121
+
122
+ The implemented adapter sends with `osascript` and can optionally receive by
123
+ polling `~/Library/Messages/chat.db` when `receiveMode` is `chat-db`. The send
124
+ script honors `account` when configured. The receive path filters out messages
125
+ from the local user, enforces `allowedHandles` unless `allowAllHandles` is
126
+ explicitly set, scans ahead past disallowed rows to avoid cursor starvation, and
127
+ keeps local Messages chat GUIDs so group chats do not collapse to a single
128
+ sender handle. Daemon cursors store the last processed Messages row ID per
129
+ channel.
130
+
131
+ ## MCP
132
+
133
+ MCP must expose session-first tools for listing, creating, attaching, sending
134
+ to, and inspecting bridge sessions. Route-based MCP tools are compatibility-only
135
+ after `0.2.x`; MCP clients should use `bridge_session_route_message` when they
136
+ want normal inbound message behavior through bindings.
@@ -0,0 +1,204 @@
1
+ # Session-Backed Multi-Channel Bridge Plan
2
+
3
+ This is the working plan for the `0.2.x` bridge release. The repo folder is
4
+ `open-bridge`, the package is `@hasna/bridge`, and the CLI remains `bridge`.
5
+
6
+ ## Goal
7
+
8
+ `bridge` should connect external conversations to durable agent sessions. A
9
+ Telegram chat, iMessage thread, Slack channel, or future channel should map to a
10
+ bridge conversation and then to a Codewith, Claude Code, or AIcopilot session.
11
+ Normal messages go to the active bound session. Prefixes are only acceptable as
12
+ an optional compatibility route, not as the main product model.
13
+
14
+ ## Target Model
15
+
16
+ ```text
17
+ channel event
18
+ -> normalized bridge conversation
19
+ -> durable bridge binding
20
+ -> agent session adapter
21
+ -> streamed or final channel response
22
+ ```
23
+
24
+ - Channels normalize inbound events and deliver outbound text.
25
+ - Bindings map external conversation IDs to bridge sessions.
26
+ - Agent adapters own account/profile state and send messages to a durable agent
27
+ session.
28
+ - Session commands manage control flow; ordinary text is user intent.
29
+
30
+ ## Versioned State
31
+
32
+ `0.2.x` must add versioned state separate from static config:
33
+
34
+ - `schemaVersion`: state schema version with forward-only migration.
35
+ - `sessions`: bridge-owned session records keyed by stable session ID.
36
+ - `bindings`: external conversation bindings keyed by normalized channel
37
+ conversation ID.
38
+ - `messageLedger`: per-channel inbound processing records for idempotency,
39
+ retries, and delivery status.
40
+ - `cursors`: per-channel cursor/offset state, committed only after the inbound
41
+ message has reached a terminal routing state.
42
+
43
+ Session records must include agent ID, profile ID, cwd, status
44
+ (`active`, `paused`, `closed`), external agent session reference, timestamps,
45
+ last activity, timeout policy, and compatibility-mode marker when an adapter
46
+ falls back to one-shot execution.
47
+
48
+ Binding records must include channel ID, normalized conversation ID, active
49
+ session ID, optional default session ID, created/updated timestamps, and an
50
+ authorization snapshot such as Telegram chat ID or iMessage handle.
51
+
52
+ ## Idempotency And Retry
53
+
54
+ - Inbound message processing writes a ledger row before invoking an agent.
55
+ - Channel cursors advance only after a message is delivered, intentionally
56
+ skipped, or rejected as unauthorized. Failed messages remain retryable until a
57
+ retry-exhaustion policy is added.
58
+ - Agent failure leaves a retryable `failed` ledger state.
59
+ - Outbound send failure after an agent succeeds leaves an `agent_completed`
60
+ ledger state with the generated response, so retries do not re-run the agent.
61
+ - Replayed updates must not run the agent twice after a successful delivery.
62
+ - Daemon restart must recover in-progress ledger rows without losing prompts.
63
+
64
+ ## Commands
65
+
66
+ Planned CLI surface:
67
+
68
+ ```sh
69
+ bridge sessions list
70
+ bridge sessions show <id>
71
+ bridge sessions create --agent codewith --cwd /repo
72
+ bridge sessions attach <id> --channel telegram-main --conversation 1225577096
73
+ bridge sessions use <id> --channel telegram-main --conversation 1225577096
74
+ bridge sessions detach --channel telegram-main --conversation 1225577096
75
+ bridge sessions close <id>
76
+ bridge sessions pause <id>
77
+ bridge sessions resume <id>
78
+ ```
79
+
80
+ Telegram and future command-capable channels should expose the same session
81
+ controls as slash commands:
82
+
83
+ ```text
84
+ /sessions
85
+ /new
86
+ /use <id>
87
+ /attach <id>
88
+ /detach
89
+ /pause
90
+ /resume
91
+ /close
92
+ /help
93
+ ```
94
+
95
+ ## Channels
96
+
97
+ Telegram:
98
+
99
+ - Plain messages route to the active session for that chat.
100
+ - If no active session exists, the bot responds with a short setup prompt and
101
+ does not invoke an agent.
102
+ - Slash commands manage sessions and never require a `cw` prefix.
103
+ - Group chats must support `/command@BotName`, topic/thread IDs when Telegram
104
+ provides them, and unauthorized command rejection.
105
+ - Unknown slash commands are treated as control errors, not agent prompts.
106
+ - A literal agent prompt that starts with `/` must require an explicit escape
107
+ command or compatibility route, so control messages and prompts do not collide.
108
+ - Existing route-based behavior can remain for explicit compatibility tests.
109
+
110
+ iMessage:
111
+
112
+ - The first adapter is local macOS-only.
113
+ - Sending uses Messages automation through `osascript` and reports TCC
114
+ Automation failures clearly.
115
+ - Receiving uses local Messages state with a per-chat cursor or a documented
116
+ helper mode. It must fail closed when Full Disk Access or Messages data access
117
+ is unavailable.
118
+ - Conversation IDs are normalized from service, chat GUID, handle, and optional
119
+ account so multiple local accounts do not collide.
120
+ - Permission diagnostics explain needed macOS Automation and Full Disk Access
121
+ grants without storing private message contents in config.
122
+ - Tests must be skip-safe on non-macOS and on macOS machines without the needed
123
+ permissions.
124
+ - The current implementation supports send through `osascript` and optional
125
+ receive through `chat.db` polling when `receiveMode` is `chat-db`.
126
+
127
+ ## Channel Adapter Contract
128
+
129
+ Each channel adapter must provide:
130
+
131
+ - `poll` or `receive` with a cursor and bounded batch size.
132
+ - `send` with normalized conversation ID and delivery result.
133
+ - `diagnose` for auth, permissions, and environment checks.
134
+ - Per-channel backoff hints for daemon runtime.
135
+ - Redaction rules for sensitive channel metadata and message contents.
136
+
137
+ ## Agents
138
+
139
+ Codewith:
140
+
141
+ - Use a stable local session API or mailbox-backed background session.
142
+ - Use auth profiles explicitly, for example `account001`.
143
+ - Avoid typing into the interactive TUI as the primary integration method.
144
+
145
+ Claude Code:
146
+
147
+ - Use the official resumable/session surface where available.
148
+ - Keep account homes/profiles isolated.
149
+ - Mark any process-wrapper fallback clearly as compatibility mode and do not
150
+ advertise it as a durable session.
151
+
152
+ AIcopilot:
153
+
154
+ - Use the same session contract as Codewith where possible.
155
+ - Add create/send/events semantics if the repo does not expose them yet.
156
+
157
+ ## Agent Adapter Contract
158
+
159
+ Each agent adapter must provide:
160
+
161
+ - `createSession(profile, cwd, options) -> agentSessionRef`.
162
+ - `sendMessage(sessionRef, text, options) -> final response or stream events`.
163
+ - `resumeSession(sessionRef)` after daemon restart.
164
+ - `cancel(sessionRef)` where the underlying agent supports cancellation.
165
+ - `close(sessionRef)` for local cleanup.
166
+ - Explicit timeout, output limit, stderr, and compatibility-mode behavior.
167
+
168
+ ## Tracked Tasks
169
+
170
+ The local `todos` plan is `cba73b38-97c5-4a02-bf58-1a03069cc0c4`:
171
+
172
+ - `4e73f3bf-3fbb-4aae-8d01-045501db925d`: define durable bridge session model.
173
+ - `630b62e3-6d57-4121-b3de-90052ad21f66`: add session CLI and persistent bindings.
174
+ - `e5820e95-3c91-4523-a583-84bb4b1e7a56`: implement session-aware agent adapters.
175
+ - `56906077-0fdb-4767-bdd0-a1990508eade`: make Telegram work without prefixes.
176
+ - `a93e4741-529e-4718-a6c9-f8ed213756db`: add macOS iMessage channel adapter.
177
+ - `54698f24-7a62-4f02-9dba-4095194adc59`: release, reinstall, and verify bridge 0.2.
178
+ - `e268d9a7-ac40-4df9-9cfb-8e820795d87a`: adversarially verify the release.
179
+
180
+ ## Done Criteria
181
+
182
+ - `bun run build`, `bun run typecheck`, and `bun test` pass.
183
+ - Session bindings survive daemon restarts.
184
+ - Telegram live test works with plain messages against the configured bot.
185
+ - iMessage diagnostics and send/receive smoke behavior work on macOS or fail
186
+ closed with a clear permission result.
187
+ - The package is committed, pushed, published, reinstalled locally, and smoke
188
+ tested from the public npm package.
189
+ - An adversarial review checks routing security, secret handling, daemon
190
+ lifecycle, replay/idempotency, channel spoofing, and package installability.
191
+
192
+ ## MCP Migration
193
+
194
+ `bridge-mcp` must expose session-first tools:
195
+
196
+ - `bridge_session_list`
197
+ - `bridge_session_create`
198
+ - `bridge_session_attach`
199
+ - `bridge_session_send`
200
+ - `bridge_session_status`
201
+ - `bridge_session_route_message`
202
+
203
+ `bridge_route_message` can remain during `0.2.x` as compatibility-only and must
204
+ be documented that way in MCP metadata.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hasna/bridge",
3
- "version": "0.1.2",
3
+ "version": "0.2.1",
4
4
  "description": "Agent messaging bridge for Telegram and other channels",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",