@zengxingyuan/aamp-cli-bridge 0.1.7-dev.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/README.md ADDED
@@ -0,0 +1,326 @@
1
+ # aamp-cli-bridge
2
+
3
+ Profile-driven bridge for direct CLI agents that do not speak ACP.
4
+
5
+ `aamp-cli-bridge` turns command-line agents into AAMP mailbox participants. It receives `task.dispatch` mail, renders the task into a CLI prompt, runs the configured command, streams incremental output when the CLI provides it, and sends the final `task.result` or `task.help_needed` back to the same AAMP thread.
6
+
7
+ Use it for agents whose public surface is a command such as `claude`, `codex`, `coco`, `gemini`, `codem`, or a private in-house CLI.
8
+
9
+ ## Install
10
+
11
+ ```bash
12
+ npm install aamp-cli-bridge
13
+ ```
14
+
15
+ From this repo:
16
+
17
+ ```bash
18
+ cd packages/cli-bridge
19
+ npm install
20
+ npm run build
21
+ ```
22
+
23
+ ## Recommended Flow
24
+
25
+ The normal flow is:
26
+
27
+ ```bash
28
+ npx aamp-cli-bridge profile-maker
29
+ npx aamp-cli-bridge init
30
+ ```
31
+
32
+ `profile-maker` creates or updates a user profile for a custom CLI agent. Built-in profiles do not need this step.
33
+
34
+ `init` is repeatable. It scans built-in profiles, user-created profiles, profiles already present in the config file, and already configured agents. The prompt is a multi-select list: use arrow keys to move, Space to select, and Enter to confirm. Agents that were configured previously stay selected by default, so you can rerun `init` to add a new agent without losing existing ones.
35
+
36
+ After writing config and printing any requested QR code, `init` starts the
37
+ bridge immediately so scanned `pair.request` mail is live without a separate
38
+ command. Use `npx aamp-cli-bridge init --no-start` when you only want to write
39
+ config.
40
+
41
+ For every selected agent, `init` asks you to choose one authorization setup
42
+ method: pair with a five-minute QR code / `aamp://connect?...` URL, manually
43
+ enter `senderPolicies`, reuse existing `senderPolicies` when available, or configure sender authorization later. The
44
+ later option rejects `task.dispatch` until pairing or policy setup is complete. If you
45
+ choose QR pairing, scan it with AAMP App or paste it into User UI /
46
+ `aamp-cli pair` to authorize that sender without manually editing
47
+ `senderPolicies`. Every `pair.request` is answered with `pair.respond` so the
48
+ requester can tell whether pairing succeeded or why it failed.
49
+
50
+ After an agent has been initialized, generate a fresh pairing QR code without
51
+ re-running setup:
52
+
53
+ ```bash
54
+ npx aamp-cli-bridge pair --agent codex
55
+ ```
56
+
57
+ `pair` also starts that agent by default after printing the QR code. Use
58
+ `--no-start` if you only need the URL.
59
+
60
+ `start` is still available for existing configs; it loads the config, provisions or reuses each agent mailbox, listens for `task.dispatch`, and forwards work into the matching CLI command.
61
+
62
+ ## Storage
63
+
64
+ Default paths:
65
+
66
+ - Config: `~/.aamp/cli-bridge/config.json`
67
+ - Agent credentials: `~/.aamp/cli-bridge/credentials/<agent>.json`
68
+ - Agent pairing codes: `~/.aamp/cli-bridge/pairing/<agent>.json`
69
+ - Paired sender policies: `~/.aamp/cli-bridge/sender-policies/<agent>.json`
70
+ - User profiles: `~/.aamp/cli-bridge/profiles/<profile>.json`
71
+
72
+ `init` writes the main config and credentials. `profile-maker` writes user profile JSON files. You can also pass a config path to commands that support it:
73
+
74
+ ```bash
75
+ npx aamp-cli-bridge start --config ./production.cli-bridge.json
76
+ npx aamp-cli-bridge list --config ./production.cli-bridge.json
77
+ ```
78
+
79
+ ## Profile Model
80
+
81
+ A CLI profile describes how to invoke an agent and how to interpret its output.
82
+
83
+ Profiles can come from four places:
84
+
85
+ - Built-in profiles shipped by the bridge: `claude`, `codex`, `coco`, `gemini`, and `codem`
86
+ - User profiles in `~/.aamp/cli-bridge/profiles/*.json`
87
+ - Shared top-level `profiles` in the bridge config
88
+ - Inline `cliProfile` objects on a specific agent config
89
+
90
+ When an agent uses a string profile reference, resolution order is:
91
+
92
+ 1. `profiles.<name>` in the loaded config
93
+ 2. `~/.aamp/cli-bridge/profiles/<name>.json`
94
+ 3. built-in profile `<name>`
95
+
96
+ When an agent uses an inline `cliProfile` object, that object is used directly for that agent.
97
+
98
+ ## Profile Format
99
+
100
+ ```json
101
+ {
102
+ "name": "codem",
103
+ "description": "Codem SSE mode.",
104
+ "command": "codem",
105
+ "args": ["-p", "{{prompt}}", "--sse", "--yolo"],
106
+ "stdin": null,
107
+ "env": {
108
+ "MY_AGENT_MODE": "aamp"
109
+ },
110
+ "cwd": "/path/to/workspace",
111
+ "shell": false,
112
+ "timeoutMs": 1800000,
113
+ "successExitCodes": [0],
114
+ "stream": {
115
+ "format": "sse",
116
+ "enabled": true
117
+ },
118
+ "output": {
119
+ "includeStderr": false,
120
+ "stripAnsi": true,
121
+ "trim": true
122
+ }
123
+ }
124
+ ```
125
+
126
+ Fields:
127
+
128
+ - `name`: optional profile name; file names and config keys also name profiles
129
+ - `description`: optional human-readable description shown by profile listing and init
130
+ - `command`: executable to run
131
+ - `args`: argument list; each string supports template variables
132
+ - `stdin`: optional stdin template; use this when the CLI reads the prompt from stdin
133
+ - `env`: extra environment variables for the child process
134
+ - `cwd`: working directory for the child process
135
+ - `shell`: run through a shell when true
136
+ - `timeoutMs`: process timeout; defaults to the bridge runtime default when omitted
137
+ - `successExitCodes`: accepted exit codes; defaults to `[0]`
138
+ - `stream`: optional parser declaration for streaming CLIs
139
+ - `output`: plain-output cleanup rules
140
+
141
+ Supported template variables:
142
+
143
+ - `{{prompt}}`: rendered AAMP task prompt
144
+ - `{{agentName}}`: current bridge agent name
145
+ - `{{sessionKey}}`: stable AAMP session key for the thread, when available
146
+ - `{{env.NAME}}`: environment variable `NAME`
147
+
148
+ ## Examples
149
+
150
+ Prompt in arguments:
151
+
152
+ ```json
153
+ {
154
+ "name": "my-agent",
155
+ "command": "my-agent",
156
+ "args": ["run", "--prompt", "{{prompt}}"],
157
+ "timeoutMs": 1800000,
158
+ "output": {
159
+ "stripAnsi": true,
160
+ "trim": true
161
+ }
162
+ }
163
+ ```
164
+
165
+ Prompt over stdin:
166
+
167
+ ```json
168
+ {
169
+ "name": "stdin-agent",
170
+ "command": "stdin-agent",
171
+ "args": ["run"],
172
+ "stdin": "{{prompt}}"
173
+ }
174
+ ```
175
+
176
+ SSE stream:
177
+
178
+ ```json
179
+ {
180
+ "name": "codem",
181
+ "command": "codem",
182
+ "args": ["-p", "{{prompt}}", "--sse", "--yolo"],
183
+ "stream": {
184
+ "format": "sse"
185
+ },
186
+ "timeoutMs": 1800000
187
+ }
188
+ ```
189
+
190
+ NDJSON stream:
191
+
192
+ ```json
193
+ {
194
+ "name": "custom-ndjson-agent",
195
+ "command": "custom-agent",
196
+ "args": ["run", "--json"],
197
+ "stdin": "{{prompt}}",
198
+ "stream": {
199
+ "format": "ndjson"
200
+ }
201
+ }
202
+ ```
203
+
204
+ ## Stream Parsing
205
+
206
+ `stream.format` supports:
207
+
208
+ - `sse`: Server-Sent Events with `event:` and `data:` lines
209
+ - `ndjson`: one JSON object per line
210
+
211
+ The parser accepts common event shapes used by CLI agents:
212
+
213
+ - `text`, `delta`, `text.delta`: forwarded to AAMP as `text.delta`
214
+ - `tool_start`, `tool_result`, `tool`: forwarded as stream progress or status events
215
+ - `usage`: forwarded as a progress event
216
+ - `result`: used as final text when present
217
+ - `done`: closes the stream state for the current task
218
+
219
+ Text deltas are streamed to AAMP and concatenated into the final `task.result`. This lets a mailbox UI show live output while still preserving a complete final answer in the thread.
220
+
221
+ ## Bridge Config
222
+
223
+ Minimal config using a built-in profile:
224
+
225
+ ```json
226
+ {
227
+ "aampHost": "https://meshmail.ai",
228
+ "rejectUnauthorized": false,
229
+ "agents": [
230
+ {
231
+ "name": "codex",
232
+ "cliProfile": "codex",
233
+ "slug": "codex-cli-bridge",
234
+ "credentialsFile": "~/.aamp/cli-bridge/credentials/codex.json",
235
+ "pairingFile": "~/.aamp/cli-bridge/pairing/codex.json",
236
+ "senderPoliciesFile": "~/.aamp/cli-bridge/sender-policies/codex.json"
237
+ }
238
+ ]
239
+ }
240
+ ```
241
+
242
+ Inline custom profile:
243
+
244
+ ```json
245
+ {
246
+ "aampHost": "https://meshmail.ai",
247
+ "rejectUnauthorized": false,
248
+ "agents": [
249
+ {
250
+ "name": "my-agent",
251
+ "cliProfile": {
252
+ "command": "my-agent",
253
+ "args": ["run", "{{prompt}}"],
254
+ "timeoutMs": 1800000
255
+ },
256
+ "slug": "my-agent-cli-bridge"
257
+ }
258
+ ]
259
+ }
260
+ ```
261
+
262
+ Shared top-level profile:
263
+
264
+ ```json
265
+ {
266
+ "aampHost": "https://meshmail.ai",
267
+ "profiles": {
268
+ "my-agent": {
269
+ "command": "my-agent",
270
+ "stdin": "{{prompt}}"
271
+ }
272
+ },
273
+ "agents": [
274
+ {
275
+ "name": "my-agent",
276
+ "cliProfile": "my-agent"
277
+ }
278
+ ]
279
+ }
280
+ ```
281
+
282
+ `senderPolicies` is optional, but omitted policies do not authorize anyone by default. Use QR pairing or configure at least one policy before sending `task.dispatch`; matching policies can also enforce exact-match `X-AAMP-Dispatch-Context` values:
283
+
284
+ ```json
285
+ {
286
+ "senderPolicies": [
287
+ {
288
+ "sender": "meegle-bot@meshmail.ai",
289
+ "dispatchContextRules": {
290
+ "project_key": ["project-a"],
291
+ "user_key": ["alice"]
292
+ }
293
+ }
294
+ ]
295
+ }
296
+ ```
297
+
298
+ ## Runtime Contract
299
+
300
+ For each accepted `task.dispatch`, the bridge:
301
+
302
+ 1. builds a task prompt from AAMP headers, body, and attachments
303
+ 2. renders the configured profile templates
304
+ 3. starts the CLI process
305
+ 4. streams parsed events to AAMP when `stream` is enabled
306
+ 5. sends `task.result` with the final concatenated output
307
+
308
+ The CLI agent can use these plain-output conventions:
309
+
310
+ - Start final output with `HELP:` to send `task.help_needed`
311
+ - End output with `FILE:/absolute/path/to/file` lines to attach generated files to `task.result`
312
+
313
+ ## Commands
314
+
315
+ ```bash
316
+ npx aamp-cli-bridge init [--no-start]
317
+ npx aamp-cli-bridge start [--config X]
318
+ npx aamp-cli-bridge pair --agent NAME [--config X] [--no-start]
319
+ npx aamp-cli-bridge list [--config X]
320
+ npx aamp-cli-bridge status
321
+ npx aamp-cli-bridge profile-list
322
+ npx aamp-cli-bridge profile-maker
323
+ npx aamp-cli-bridge directory-list --agent NAME [--include-self]
324
+ npx aamp-cli-bridge directory-search --agent NAME --query TEXT
325
+ npx aamp-cli-bridge directory-update --agent NAME --summary TEXT
326
+ ```
@@ -0,0 +1,42 @@
1
+ import type { AgentConfig, BridgeConfig } from './config.js';
2
+ export interface AgentIdentity {
3
+ email: string;
4
+ mailboxToken: string;
5
+ smtpPassword: string;
6
+ }
7
+ export interface AgentBridgeStartOptions {
8
+ quiet?: boolean;
9
+ }
10
+ export declare class AgentBridge {
11
+ private readonly agentConfig;
12
+ private readonly aampHost;
13
+ private readonly rejectUnauthorized;
14
+ private client;
15
+ private identity;
16
+ private cli;
17
+ private activeTaskCount;
18
+ private pollingFallback;
19
+ private cancelledTaskIds;
20
+ private profileLabel;
21
+ private streamEnabled;
22
+ private senderPolicies;
23
+ private isHistoricalReconcile;
24
+ constructor(agentConfig: AgentConfig, aampHost: string, rejectUnauthorized: boolean, customProfiles?: BridgeConfig['profiles']);
25
+ get name(): string;
26
+ get email(): string;
27
+ get isConnected(): boolean;
28
+ get isUsingPollingFallback(): boolean;
29
+ get isBusy(): boolean;
30
+ private getConfiguredCardText;
31
+ private syncDirectoryProfile;
32
+ start(options?: AgentBridgeStartOptions): Promise<void>;
33
+ stop(): void;
34
+ private handleTask;
35
+ private normalizeEmail;
36
+ private sendPairResponse;
37
+ private handlePairRequest;
38
+ private resolveIdentity;
39
+ private registerIdentity;
40
+ private checkIdentityAuthorization;
41
+ private waitForIdentityAuthorization;
42
+ }