@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 +326 -0
- package/dist/agent-bridge.d.ts +42 -0
- package/dist/agent-bridge.js +709 -0
- package/dist/agent-bridge.js.map +1 -0
- package/dist/bridge.d.ts +12 -0
- package/dist/bridge.js +58 -0
- package/dist/bridge.js.map +1 -0
- package/dist/cli/init.d.ts +9 -0
- package/dist/cli/init.js +656 -0
- package/dist/cli/init.js.map +1 -0
- package/dist/cli/profile-maker.d.ts +1 -0
- package/dist/cli/profile-maker.js +136 -0
- package/dist/cli/profile-maker.js.map +1 -0
- package/dist/cli-agent-client.d.ts +21 -0
- package/dist/cli-agent-client.js +150 -0
- package/dist/cli-agent-client.js.map +1 -0
- package/dist/cli-profiles.d.ts +10 -0
- package/dist/cli-profiles.js +97 -0
- package/dist/cli-profiles.js.map +1 -0
- package/dist/config.d.ts +639 -0
- package/dist/config.js +95 -0
- package/dist/config.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +256 -0
- package/dist/index.js.map +1 -0
- package/dist/pairing.d.ts +39 -0
- package/dist/pairing.js +110 -0
- package/dist/pairing.js.map +1 -0
- package/dist/prompt-builder.d.ts +15 -0
- package/dist/prompt-builder.js +388 -0
- package/dist/prompt-builder.js.map +1 -0
- package/dist/storage.d.ts +7 -0
- package/dist/storage.js +65 -0
- package/dist/storage.js.map +1 -0
- package/dist/stream-parser.d.ts +26 -0
- package/dist/stream-parser.js +155 -0
- package/dist/stream-parser.js.map +1 -0
- package/package.json +32 -0
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
|
+
}
|