@agentworkforce/cli 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.
- package/README.md +382 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +249 -0
- package/dist/cli.js.map +1 -0
- package/dist/env-refs.d.ts +56 -0
- package/dist/env-refs.d.ts.map +1 -0
- package/dist/env-refs.js +105 -0
- package/dist/env-refs.js.map +1 -0
- package/dist/env-refs.test.d.ts +2 -0
- package/dist/env-refs.test.d.ts.map +1 -0
- package/dist/env-refs.test.js +84 -0
- package/dist/env-refs.test.js.map +1 -0
- package/dist/local-personas.d.ts +42 -0
- package/dist/local-personas.d.ts.map +1 -0
- package/dist/local-personas.js +305 -0
- package/dist/local-personas.js.map +1 -0
- package/dist/local-personas.test.d.ts +2 -0
- package/dist/local-personas.test.d.ts.map +1 -0
- package/dist/local-personas.test.js +242 -0
- package/dist/local-personas.test.js.map +1 -0
- package/package.json +32 -0
package/README.md
ADDED
|
@@ -0,0 +1,382 @@
|
|
|
1
|
+
# agent-workforce CLI
|
|
2
|
+
|
|
3
|
+
A thin command-line front end for the workload-router. Spawns the harness CLI
|
|
4
|
+
(`claude`, `codex`, `opencode`) configured by a selected **persona** — either a
|
|
5
|
+
built-in one from `/personas/`, or a user-local one that extends a built-in.
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
agent-workforce agent <persona>[@<tier>] [task...]
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
- No `task` → drops you into an interactive session with the harness.
|
|
12
|
+
- `task...` given → runs one-shot (via `usePersona().sendMessage()`) and streams
|
|
13
|
+
output to stdout/stderr.
|
|
14
|
+
|
|
15
|
+
## Install
|
|
16
|
+
|
|
17
|
+
The CLI ships as a `bin` in `@agentworkforce/cli` (which depends on
|
|
18
|
+
`@agentworkforce/workload-router` via the pnpm workspace). From the repo
|
|
19
|
+
checkout:
|
|
20
|
+
|
|
21
|
+
```sh
|
|
22
|
+
corepack pnpm -r build
|
|
23
|
+
corepack pnpm --filter @agentworkforce/cli link --global
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
That puts `agent-workforce` on your PATH.
|
|
27
|
+
|
|
28
|
+
## Selectors
|
|
29
|
+
|
|
30
|
+
```
|
|
31
|
+
agent-workforce agent <persona>[@<tier>] [task...]
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
- `<persona>` — matches, in order:
|
|
35
|
+
1. A **pwd-local** id (files in `<cwd>/.agent-workforce/*.json`)
|
|
36
|
+
2. A **home-local** id (files in `~/.agent-workforce/*.json`)
|
|
37
|
+
3. A **library** persona — by intent first (e.g. `review`), then by id
|
|
38
|
+
(e.g. `code-reviewer`)
|
|
39
|
+
- `<tier>` — `best` | `best-value` | `minimum`. Defaults to `best-value`.
|
|
40
|
+
|
|
41
|
+
Unknown persona prints the full catalog with each entry's origin.
|
|
42
|
+
|
|
43
|
+
### Examples
|
|
44
|
+
|
|
45
|
+
```sh
|
|
46
|
+
# One-shot against the built-in code reviewer
|
|
47
|
+
agent-workforce agent review@best-value "look at the diff on this branch"
|
|
48
|
+
|
|
49
|
+
# Interactive PostHog session (library persona, needs POSTHOG_API_KEY)
|
|
50
|
+
agent-workforce agent posthog@best
|
|
51
|
+
|
|
52
|
+
# Interactive against a local override
|
|
53
|
+
agent-workforce agent my-posthog@best
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## Personas
|
|
57
|
+
|
|
58
|
+
A persona is a JSON object describing *what harness runs, which model, with
|
|
59
|
+
what system prompt, what skills to install, what env vars to inject, and which
|
|
60
|
+
MCP servers to attach*. Full library shape:
|
|
61
|
+
|
|
62
|
+
```jsonc
|
|
63
|
+
{
|
|
64
|
+
"id": "posthog",
|
|
65
|
+
"intent": "posthog",
|
|
66
|
+
"description": "…",
|
|
67
|
+
"skills": [],
|
|
68
|
+
"env": { "POSTHOG_API_KEY": "$POSTHOG_API_KEY" },
|
|
69
|
+
"mcpServers": {
|
|
70
|
+
"posthog": {
|
|
71
|
+
"type": "http",
|
|
72
|
+
"url": "https://mcp.posthog.com/mcp",
|
|
73
|
+
"headers": { "Authorization": "Bearer ${POSTHOG_API_KEY}" }
|
|
74
|
+
}
|
|
75
|
+
},
|
|
76
|
+
"tiers": {
|
|
77
|
+
"best": { "harness": "claude", "model": "claude-opus-4-6", "systemPrompt": "…", "harnessSettings": { "reasoning": "high", "timeoutSeconds": 900 } },
|
|
78
|
+
"best-value": { "harness": "claude", "model": "claude-sonnet-4-6", "systemPrompt": "…", "harnessSettings": { "reasoning": "medium", "timeoutSeconds": 600 } },
|
|
79
|
+
"minimum": { "harness": "claude", "model": "claude-haiku-4-5-20251001", "systemPrompt": "…", "harnessSettings": { "reasoning": "low", "timeoutSeconds": 300 } }
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
See `/personas/*.json` for all built-ins.
|
|
85
|
+
|
|
86
|
+
## Local personas & the cascade
|
|
87
|
+
|
|
88
|
+
Local persona files layer on top of the library. Resolution precedence (highest
|
|
89
|
+
wins):
|
|
90
|
+
|
|
91
|
+
1. `<cwd>/.agent-workforce/*.json` — **pwd**
|
|
92
|
+
2. `~/.agent-workforce/*.json` — **home** (override path via
|
|
93
|
+
`AGENT_WORKFORCE_CONFIG_DIR`)
|
|
94
|
+
3. Built-in personas in `/personas/` — **library**
|
|
95
|
+
|
|
96
|
+
Local files are **partial overlays**: only the fields you set replace the
|
|
97
|
+
inherited value. Everything else cascades through from below.
|
|
98
|
+
|
|
99
|
+
### Minimal override: add your API key
|
|
100
|
+
|
|
101
|
+
`~/.agent-workforce/my-posthog.json`:
|
|
102
|
+
|
|
103
|
+
```json
|
|
104
|
+
{
|
|
105
|
+
"id": "my-posthog",
|
|
106
|
+
"extends": "posthog",
|
|
107
|
+
"env": { "POSTHOG_API_KEY": "$POSTHOG_API_KEY" }
|
|
108
|
+
}
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
That inherits every field from the library `posthog` persona, then layers your
|
|
112
|
+
`env` on top. `agent-workforce agent my-posthog@best` now works as long as
|
|
113
|
+
`POSTHOG_API_KEY` is exported in your shell.
|
|
114
|
+
|
|
115
|
+
### Same-id override (implicit extends)
|
|
116
|
+
|
|
117
|
+
If your file's `id` matches a persona in a lower layer and you omit `extends`,
|
|
118
|
+
the loader implicitly inherits from that same-id base:
|
|
119
|
+
|
|
120
|
+
`<cwd>/.agent-workforce/posthog.json`:
|
|
121
|
+
|
|
122
|
+
```json
|
|
123
|
+
{
|
|
124
|
+
"id": "posthog",
|
|
125
|
+
"env": { "POSTHOG_API_KEY": "$POSTHOG_API_KEY" }
|
|
126
|
+
}
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
Resolving `posthog` now hits this pwd override first; it inherits the rest
|
|
130
|
+
(MCP, tiers, description, etc.) from the library `posthog`.
|
|
131
|
+
|
|
132
|
+
### Cascade chain
|
|
133
|
+
|
|
134
|
+
A pwd file can extend a home file, which extends the library:
|
|
135
|
+
|
|
136
|
+
```
|
|
137
|
+
~/.agent-workforce/ph-base.json:
|
|
138
|
+
{ "id": "ph-base", "extends": "posthog", "env": { "POSTHOG_ORG": "acme" } }
|
|
139
|
+
|
|
140
|
+
<cwd>/.agent-workforce/ph-prod.json:
|
|
141
|
+
{ "id": "ph-prod", "extends": "ph-base", "env": { "POSTHOG_API_KEY": "$PROD_KEY" } }
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
Resolving `ph-prod`:
|
|
145
|
+
|
|
146
|
+
- Start with library `posthog` (MCP, tiers, prompt, …)
|
|
147
|
+
- Layer home `ph-base` on top (adds `POSTHOG_ORG=acme`)
|
|
148
|
+
- Layer pwd `ph-prod` on top (adds `POSTHOG_API_KEY`)
|
|
149
|
+
|
|
150
|
+
`extends` is resolved **strictly against lower layers** — pwd extends home or
|
|
151
|
+
library, home extends library, library has no `extends`.
|
|
152
|
+
|
|
153
|
+
### Override shape (all fields except `id` optional)
|
|
154
|
+
|
|
155
|
+
```jsonc
|
|
156
|
+
{
|
|
157
|
+
"id": "my-agent", // required
|
|
158
|
+
"extends": "posthog", // optional; implicit same-id if omitted
|
|
159
|
+
"description": "…", // replaces base description
|
|
160
|
+
"skills": [ … ], // replaces entire skills array
|
|
161
|
+
"env": { … }, // union, local wins per key
|
|
162
|
+
"mcpServers": { … }, // union by server name, local wins per key
|
|
163
|
+
"permissions": { // allow/deny union (dedup), mode replaces
|
|
164
|
+
"allow": ["…"], "deny": ["…"], "mode": "default"
|
|
165
|
+
},
|
|
166
|
+
"systemPrompt": "…", // replaces systemPrompt on every inherited tier
|
|
167
|
+
"tiers": { // per-tier partial override
|
|
168
|
+
"best": { "model": "claude-sonnet-4-6" }
|
|
169
|
+
// other tiers inherited untouched
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
**Per-tier partial merge.** If you set `tiers.best.model`, only `model`
|
|
175
|
+
changes — `systemPrompt`, `harness`, and `harnessSettings` still come from the
|
|
176
|
+
base. Use top-level `systemPrompt` if you want to replace the prompt
|
|
177
|
+
uniformly across all tiers.
|
|
178
|
+
|
|
179
|
+
## Env references & secrets
|
|
180
|
+
|
|
181
|
+
Any `env` value or `mcpServers.*.{headers,env,args,url,command}` value can be
|
|
182
|
+
either a literal string or an env reference. Two forms:
|
|
183
|
+
|
|
184
|
+
| Form | Meaning | Example |
|
|
185
|
+
| ---- | ------- | ------- |
|
|
186
|
+
| `"$VAR"` | Whole-string reference — the entire value is the env var. | `"POSTHOG_API_KEY": "$POSTHOG_API_KEY"` |
|
|
187
|
+
| `"prefix ${VAR}"` | Braced interpolation — each `${VAR}` is replaced in place, anywhere in the string. | `"Authorization": "Bearer ${POSTHOG_API_KEY}"` |
|
|
188
|
+
|
|
189
|
+
- Both forms resolve against the shell `process.env` at **spawn time** (not
|
|
190
|
+
load time).
|
|
191
|
+
- **Unbraced `$VAR` mid-string stays literal** — `"prefix-$FOO"` is NOT
|
|
192
|
+
interpolated. Use `${FOO}` if you want interpolation there. This prevents a
|
|
193
|
+
stray `$` in a JSON string from accidentally getting eaten.
|
|
194
|
+
- An unset or empty referenced var is a **warning, not a fatal error**. The
|
|
195
|
+
CLI drops the referring entry and proceeds. So a persona that references
|
|
196
|
+
`$POSTHOG_API_KEY` in both `env` and an `Authorization` header will, if the
|
|
197
|
+
var isn't set, launch without either — and the agent can still authenticate
|
|
198
|
+
interactively (e.g. via Claude Code's MCP OAuth flow). Example warning:
|
|
199
|
+
|
|
200
|
+
```
|
|
201
|
+
warning: env.POSTHOG_API_KEY dropped (env var POSTHOG_API_KEY is not set).
|
|
202
|
+
warning: mcpServers.posthog.headers.Authorization dropped (env var POSTHOG_API_KEY is not set).
|
|
203
|
+
(referenced env vars were not set — proceeding without those values;
|
|
204
|
+
if the agent relies on them it may need to authenticate
|
|
205
|
+
interactively, e.g. via OAuth.)
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
- An MCP server whose **structural** field (`url`, `command`, or any `arg`)
|
|
209
|
+
references a missing var is dropped entirely, since the server couldn't be
|
|
210
|
+
launched without that value. The warning names the server and the refs that
|
|
211
|
+
were unset.
|
|
212
|
+
|
|
213
|
+
Secrets therefore stay in your shell/keychain, not in files on disk — local
|
|
214
|
+
persona JSON remains commit-safe as long as you only use references.
|
|
215
|
+
|
|
216
|
+
## Permissions
|
|
217
|
+
|
|
218
|
+
A persona can declare which tool calls the harness should auto-approve, block,
|
|
219
|
+
or gate via a permission mode. Skip the approval prompts for trusted tools
|
|
220
|
+
(e.g. a persona's own MCP server); keep them on for anything you want to
|
|
221
|
+
eyeball.
|
|
222
|
+
|
|
223
|
+
```jsonc
|
|
224
|
+
{
|
|
225
|
+
"permissions": {
|
|
226
|
+
"allow": ["mcp__posthog", "Bash(git *)"], // auto-approve
|
|
227
|
+
"deny": ["Bash(rm -rf *)"], // always block
|
|
228
|
+
"mode": "default" // default | acceptEdits | bypassPermissions | plan
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
- **Tool patterns** are passed through verbatim; use the harness's native
|
|
234
|
+
grammar. For Claude Code: `Bash(<pattern>)`, `Edit(<glob>)`,
|
|
235
|
+
`mcp__<server>` (all tools from that server), `mcp__<server>__<tool>`
|
|
236
|
+
(specific tool).
|
|
237
|
+
- **Harness support today:** only `claude` is wired (flags: `--allowedTools`,
|
|
238
|
+
`--disallowedTools`, `--permission-mode`). codex and opencode emit a
|
|
239
|
+
warning and fall back to their defaults when `permissions` is set.
|
|
240
|
+
- **Cascade merge:** `allow` and `deny` are unions across layers (deduped on
|
|
241
|
+
merge); `mode` is replaced by the topmost layer that sets it. So the
|
|
242
|
+
library can declare the minimum-viable allow list, home can layer on
|
|
243
|
+
project-wide denies, and pwd can add per-project patterns — they all
|
|
244
|
+
compose.
|
|
245
|
+
|
|
246
|
+
### Example: PostHog with auto-approve
|
|
247
|
+
|
|
248
|
+
The built-in `posthog` persona declares `permissions.allow = ["mcp__posthog"]`
|
|
249
|
+
so that once you've authenticated (either by passing `POSTHOG_API_KEY` up
|
|
250
|
+
front or via Claude's OAuth flow), subsequent analytics tool calls don't
|
|
251
|
+
prompt. To narrow the auto-approval to read-only tools, override in a local
|
|
252
|
+
persona:
|
|
253
|
+
|
|
254
|
+
```json
|
|
255
|
+
{
|
|
256
|
+
"id": "my-posthog",
|
|
257
|
+
"extends": "posthog",
|
|
258
|
+
"permissions": {
|
|
259
|
+
"allow": [
|
|
260
|
+
"mcp__posthog__projects-get",
|
|
261
|
+
"mcp__posthog__insights-list",
|
|
262
|
+
"mcp__posthog__events-query"
|
|
263
|
+
]
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
Because `allow` is a union, the base's `"mcp__posthog"` would still be in the
|
|
269
|
+
merged list. If you want to *shrink* the allow list in a local override,
|
|
270
|
+
include a comment explaining why — there's currently no "replace" knob, only
|
|
271
|
+
union. (File an issue if you need one.)
|
|
272
|
+
|
|
273
|
+
## MCP servers
|
|
274
|
+
|
|
275
|
+
The `mcpServers` block mirrors Claude Code's `--mcp-config` JSON shape
|
|
276
|
+
verbatim. Three transport types:
|
|
277
|
+
|
|
278
|
+
```jsonc
|
|
279
|
+
// Remote HTTP / streamable-http
|
|
280
|
+
{ "type": "http", "url": "https://…", "headers": { "Authorization": "Bearer ${TOKEN}" } }
|
|
281
|
+
|
|
282
|
+
// Remote SSE (deprecated by most servers but still supported)
|
|
283
|
+
{ "type": "sse", "url": "https://…", "headers": { … } }
|
|
284
|
+
|
|
285
|
+
// Stdio — long-running local MCP server
|
|
286
|
+
{ "type": "stdio", "command": "npx", "args": ["-y", "…"], "env": { "API_KEY": "$API_KEY" } }
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
### Harness support
|
|
290
|
+
|
|
291
|
+
| Harness | Interactive MCP | One-shot MCP |
|
|
292
|
+
| -------- | --------------- | ------------ |
|
|
293
|
+
| claude | yes (via `--mcp-config` + `--strict-mcp-config`) | not yet — SDK workflow path doesn't thread MCP |
|
|
294
|
+
| codex | not yet — warns and proceeds without MCP | not yet |
|
|
295
|
+
| opencode | not yet — warns and proceeds without MCP | not yet |
|
|
296
|
+
|
|
297
|
+
For a persona that needs MCP today, pick `claude` as the harness on every tier
|
|
298
|
+
and use interactive mode.
|
|
299
|
+
|
|
300
|
+
### MCP isolation
|
|
301
|
+
|
|
302
|
+
For the `claude` harness the CLI always spawns with `--strict-mcp-config`,
|
|
303
|
+
paired with an explicit `--mcp-config` payload (the persona's `mcpServers`, or
|
|
304
|
+
`{"mcpServers":{}}` if none). That means **only the servers declared on the
|
|
305
|
+
persona are loaded** — your user-level `~/.claude.json` MCPs and any
|
|
306
|
+
project-level MCP sources are ignored inside the session. This keeps each
|
|
307
|
+
persona session self-contained and prevents cross-contamination with the
|
|
308
|
+
agents you normally run. If you need one of your personal MCPs inside a
|
|
309
|
+
persona session, add it to the persona's `mcpServers` block.
|
|
310
|
+
|
|
311
|
+
## Interactive vs one-shot
|
|
312
|
+
|
|
313
|
+
### Interactive
|
|
314
|
+
|
|
315
|
+
```sh
|
|
316
|
+
agent-workforce agent <persona>[@<tier>]
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
1. Resolves the persona, walks the cascade, resolves `$VAR` refs.
|
|
320
|
+
2. Runs skill install (`prpm install …`) if the persona declares any skills.
|
|
321
|
+
3. Execs the harness binary with stdio inherited:
|
|
322
|
+
- `claude`: `claude --model <model> --append-system-prompt <prompt>
|
|
323
|
+
--mcp-config '<json>' --strict-mcp-config`. Both flags are always passed
|
|
324
|
+
so the session only sees the persona's declared MCP servers — see
|
|
325
|
+
**MCP isolation** above.
|
|
326
|
+
- `codex`: `codex -m <model>` with the system prompt as the initial
|
|
327
|
+
positional `[PROMPT]`. (codex has no `--system-prompt` flag today.)
|
|
328
|
+
- `opencode`: `opencode --model <model>` with the system prompt as the
|
|
329
|
+
initial argument.
|
|
330
|
+
4. Runs the skill cleanup command on exit, regardless of exit status.
|
|
331
|
+
5. Propagates the harness's exit code.
|
|
332
|
+
|
|
333
|
+
Signals (SIGINT, SIGTERM) are forwarded to the child.
|
|
334
|
+
|
|
335
|
+
### One-shot
|
|
336
|
+
|
|
337
|
+
```sh
|
|
338
|
+
agent-workforce agent <persona>[@<tier>] "<task…>"
|
|
339
|
+
```
|
|
340
|
+
|
|
341
|
+
Non-interactive. Delegates to `usePersona(intent, { tier }).sendMessage(task)`
|
|
342
|
+
from the workload-router SDK, which spawns an ad-hoc single-step workflow:
|
|
343
|
+
install skills → run agent → cleanup. Stdout/stderr stream live; exit code
|
|
344
|
+
matches the agent's.
|
|
345
|
+
|
|
346
|
+
Env from the persona is passed through via `ExecuteOptions.env`. `mcpServers`
|
|
347
|
+
is currently **ignored with a warning** in one-shot mode — the SDK workflow
|
|
348
|
+
path doesn't thread MCP config yet.
|
|
349
|
+
|
|
350
|
+
## Selecting a harness per tier
|
|
351
|
+
|
|
352
|
+
A persona's three tiers can use different harnesses. The built-in
|
|
353
|
+
`npm-provenance-publisher` has `best` on codex and `best-value` on opencode,
|
|
354
|
+
for example.
|
|
355
|
+
|
|
356
|
+
If a persona uses MCP, keep every tier on `claude` — only the claude harness
|
|
357
|
+
wires MCP at spawn time today.
|
|
358
|
+
|
|
359
|
+
## Troubleshooting
|
|
360
|
+
|
|
361
|
+
- **`Unknown persona "X".`** — The CLI prints the full catalog. If your local
|
|
362
|
+
file should be listed, check for a warning on the preceding line — parse
|
|
363
|
+
errors and bad `extends` references are reported but non-fatal.
|
|
364
|
+
|
|
365
|
+
- **`warning: <field> dropped (env var X is not set)`** — Informational. The
|
|
366
|
+
CLI skipped that value and is launching without it. Export the variable if
|
|
367
|
+
you want the agent to have it up-front; otherwise the harness may handle
|
|
368
|
+
auth interactively (e.g. Claude Code's MCP OAuth flow).
|
|
369
|
+
|
|
370
|
+
- **`Failed to spawn "claude": binary not found on PATH.`** — Install the
|
|
371
|
+
harness CLI (`claude`, `codex`, or `opencode`) and ensure it's on your PATH.
|
|
372
|
+
|
|
373
|
+
- **`warning: persona declares mcpServers but the codex harness is not yet
|
|
374
|
+
wired …`** — Either switch the tier's `harness` to `claude`, or drop the MCP
|
|
375
|
+
requirement.
|
|
376
|
+
|
|
377
|
+
- **`extends cycle detected through …`** — A local persona extends itself
|
|
378
|
+
transitively. Break the chain or point one link at the library directly.
|
|
379
|
+
|
|
380
|
+
- **Local file silently missing from the list** — Scroll up for a
|
|
381
|
+
`warning: [layer] file.json: …` line. Common causes: invalid JSON, `id`
|
|
382
|
+
missing, or `extends` pointing at something that isn't in a lower layer.
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { spawn, spawnSync } from 'node:child_process';
|
|
3
|
+
import { constants } from 'node:os';
|
|
4
|
+
import { PERSONA_TIERS, personaCatalog, useSelection } from '@agentworkforce/workload-router';
|
|
5
|
+
import { buildInteractiveSpec, formatDropWarnings, resolveMcpServersLenient, resolveStringMapLenient } from '@agentworkforce/harness-kit';
|
|
6
|
+
import { loadLocalPersonas } from './local-personas.js';
|
|
7
|
+
const USAGE = `Usage: agent-workforce agent <persona>[@<tier>] [task...]
|
|
8
|
+
|
|
9
|
+
<persona> repo persona id, repo intent, or local persona id
|
|
10
|
+
<tier> ${PERSONA_TIERS.join(' | ')} (default: best-value)
|
|
11
|
+
[task] if provided, runs one-shot non-interactively;
|
|
12
|
+
otherwise drops into an interactive harness session
|
|
13
|
+
|
|
14
|
+
Local personas cascade: <cwd>/.agent-workforce/*.json → ~/.agent-workforce/*.json → repo library.
|
|
15
|
+
Each layer only needs to specify fields it overrides; everything else inherits
|
|
16
|
+
from the next lower layer. "extends" explicitly names a base; omit it and the
|
|
17
|
+
loader implicitly inherits from the same-id persona below. (Override the home
|
|
18
|
+
layer path via AGENT_WORKFORCE_CONFIG_DIR.)
|
|
19
|
+
|
|
20
|
+
Examples:
|
|
21
|
+
agent-workforce agent npm-provenance-publisher@best
|
|
22
|
+
agent-workforce agent my-posthog@best
|
|
23
|
+
agent-workforce agent review@best-value "look at the diff on this branch"
|
|
24
|
+
`;
|
|
25
|
+
function die(msg, withUsage = true) {
|
|
26
|
+
process.stderr.write(`${msg}\n`);
|
|
27
|
+
if (withUsage)
|
|
28
|
+
process.stderr.write(`\n${USAGE}`);
|
|
29
|
+
process.exit(1);
|
|
30
|
+
}
|
|
31
|
+
const local = loadLocalPersonas();
|
|
32
|
+
for (const warning of local.warnings) {
|
|
33
|
+
process.stderr.write(`warning: ${warning}\n`);
|
|
34
|
+
}
|
|
35
|
+
function resolveSpec(key) {
|
|
36
|
+
const localSpec = local.byId.get(key);
|
|
37
|
+
if (localSpec)
|
|
38
|
+
return localSpec;
|
|
39
|
+
const catalogAsIntent = personaCatalog[key];
|
|
40
|
+
if (catalogAsIntent)
|
|
41
|
+
return catalogAsIntent;
|
|
42
|
+
const byId = Object.values(personaCatalog).find((p) => p.id === key);
|
|
43
|
+
if (byId)
|
|
44
|
+
return byId;
|
|
45
|
+
const repoListing = Object.values(personaCatalog)
|
|
46
|
+
.slice()
|
|
47
|
+
.sort((a, b) => a.id.localeCompare(b.id))
|
|
48
|
+
.map((p) => ` ${p.id} (intent: ${p.intent})`);
|
|
49
|
+
const localListing = [...local.byId.values()]
|
|
50
|
+
.sort((a, b) => a.id.localeCompare(b.id))
|
|
51
|
+
.map((p) => ` ${p.id} (${local.sources.get(p.id) ?? 'local'})`);
|
|
52
|
+
const listing = [...repoListing, ...localListing].join('\n');
|
|
53
|
+
return { error: `Unknown persona "${key}". Known personas:\n${listing}` };
|
|
54
|
+
}
|
|
55
|
+
function parseSelector(sel) {
|
|
56
|
+
const at = sel.indexOf('@');
|
|
57
|
+
const key = at === -1 ? sel : sel.slice(0, at);
|
|
58
|
+
const tierRaw = at === -1 ? undefined : sel.slice(at + 1);
|
|
59
|
+
if (!key)
|
|
60
|
+
die('Missing persona name before "@"');
|
|
61
|
+
const tier = (tierRaw ?? 'best-value');
|
|
62
|
+
if (tierRaw !== undefined && !PERSONA_TIERS.includes(tier)) {
|
|
63
|
+
die(`Invalid tier "${tierRaw}". Must be one of: ${PERSONA_TIERS.join(', ')}`);
|
|
64
|
+
}
|
|
65
|
+
const result = resolveSpec(key);
|
|
66
|
+
if ('error' in result)
|
|
67
|
+
die(result.error, false);
|
|
68
|
+
const kind = local.byId.has(key) ? 'local' : 'repo';
|
|
69
|
+
return { kind, spec: result, tier };
|
|
70
|
+
}
|
|
71
|
+
function buildSelection(spec, tier, kind) {
|
|
72
|
+
return {
|
|
73
|
+
personaId: spec.id,
|
|
74
|
+
tier,
|
|
75
|
+
runtime: spec.tiers[tier],
|
|
76
|
+
skills: spec.skills,
|
|
77
|
+
rationale: kind === 'local' ? `local-override: ${spec.id}` : `cli-tier-override: ${tier}`,
|
|
78
|
+
...(spec.env ? { env: spec.env } : {}),
|
|
79
|
+
...(spec.mcpServers ? { mcpServers: spec.mcpServers } : {}),
|
|
80
|
+
...(spec.permissions ? { permissions: spec.permissions } : {})
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
function emitDropWarnings(lines) {
|
|
84
|
+
if (lines.length === 0)
|
|
85
|
+
return;
|
|
86
|
+
for (const line of lines)
|
|
87
|
+
process.stderr.write(`warning: ${line}\n`);
|
|
88
|
+
process.stderr.write(` (referenced env vars were not set — proceeding without those values; if the agent relies on them it may need to authenticate interactively, e.g. via OAuth.)\n`);
|
|
89
|
+
}
|
|
90
|
+
async function runOneShot(selection, task) {
|
|
91
|
+
const { runtime } = selection;
|
|
92
|
+
process.stderr.write(`→ ${selection.personaId} [${selection.tier}] via ${runtime.harness} (${runtime.model})\n`);
|
|
93
|
+
const envResolution = resolveStringMapLenient(selection.env, process.env, 'env');
|
|
94
|
+
emitDropWarnings(formatDropWarnings(envResolution.dropped, [], []));
|
|
95
|
+
if (selection.mcpServers && Object.keys(selection.mcpServers).length > 0) {
|
|
96
|
+
process.stderr.write(`warning: mcpServers are not yet wired through the one-shot (sendMessage) path; the agent will run without MCP. Use interactive mode for MCP access.\n`);
|
|
97
|
+
}
|
|
98
|
+
const ctx = useSelection(selection);
|
|
99
|
+
const execution = ctx.sendMessage(task, {
|
|
100
|
+
env: envResolution.value,
|
|
101
|
+
onProgress: ({ stream, text }) => {
|
|
102
|
+
(stream === 'stderr' ? process.stderr : process.stdout).write(text);
|
|
103
|
+
}
|
|
104
|
+
});
|
|
105
|
+
try {
|
|
106
|
+
const result = await execution;
|
|
107
|
+
process.exit(result.exitCode ?? 0);
|
|
108
|
+
}
|
|
109
|
+
catch (err) {
|
|
110
|
+
const typed = err;
|
|
111
|
+
const status = typed.result?.status ?? 'failed';
|
|
112
|
+
process.stderr.write(`\n[${status}] ${typed.message}\n`);
|
|
113
|
+
process.exit(typed.result?.exitCode ?? 1);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
function signalExitCode(signal) {
|
|
117
|
+
if (!signal)
|
|
118
|
+
return 0;
|
|
119
|
+
const num = constants.signals[signal];
|
|
120
|
+
return 128 + (num ?? 1);
|
|
121
|
+
}
|
|
122
|
+
function runInstall(command, label) {
|
|
123
|
+
const [bin, ...args] = command;
|
|
124
|
+
if (!bin)
|
|
125
|
+
return;
|
|
126
|
+
process.stderr.write(`• ${label}\n`);
|
|
127
|
+
const res = spawnSync(bin, args, { stdio: 'inherit', shell: false });
|
|
128
|
+
if (res.status !== 0) {
|
|
129
|
+
const code = res.status ?? 1;
|
|
130
|
+
process.stderr.write(`${label} failed (exit ${code}). Aborting.\n`);
|
|
131
|
+
process.exit(code);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
function runCleanup(command, commandString) {
|
|
135
|
+
if (commandString === ':')
|
|
136
|
+
return;
|
|
137
|
+
const [bin, ...args] = command;
|
|
138
|
+
if (!bin)
|
|
139
|
+
return;
|
|
140
|
+
spawnSync(bin, args, { stdio: 'inherit', shell: false });
|
|
141
|
+
}
|
|
142
|
+
function runInteractive(selection) {
|
|
143
|
+
const ctx = useSelection(selection);
|
|
144
|
+
const { runtime, personaId, tier } = selection;
|
|
145
|
+
const { install } = ctx;
|
|
146
|
+
process.stderr.write(`→ ${personaId} [${tier}] via ${runtime.harness} (${runtime.model})\n`);
|
|
147
|
+
const envResolution = resolveStringMapLenient(selection.env, process.env, 'env');
|
|
148
|
+
const mcpResolution = resolveMcpServersLenient(selection.mcpServers, process.env);
|
|
149
|
+
emitDropWarnings(formatDropWarnings(envResolution.dropped, mcpResolution.dropped, mcpResolution.droppedServers));
|
|
150
|
+
const resolvedEnv = envResolution.value;
|
|
151
|
+
const resolvedMcp = mcpResolution.servers;
|
|
152
|
+
if (install.plan.installs.length > 0) {
|
|
153
|
+
const skillIds = install.plan.installs.map((i) => i.skillId).join(', ');
|
|
154
|
+
runInstall(install.command, `Installing skills: ${skillIds}`);
|
|
155
|
+
}
|
|
156
|
+
const spec = buildInteractiveSpec({
|
|
157
|
+
harness: runtime.harness,
|
|
158
|
+
model: runtime.model,
|
|
159
|
+
systemPrompt: runtime.systemPrompt,
|
|
160
|
+
mcpServers: resolvedMcp,
|
|
161
|
+
permissions: selection.permissions
|
|
162
|
+
});
|
|
163
|
+
for (const w of spec.warnings)
|
|
164
|
+
process.stderr.write(`warning: ${w}\n`);
|
|
165
|
+
const finalArgs = spec.initialPrompt ? [...spec.args, spec.initialPrompt] : [...spec.args];
|
|
166
|
+
// Print a sanitized summary rather than raw argv: spec.args for the claude
|
|
167
|
+
// harness contains the resolved --mcp-config JSON and the full system
|
|
168
|
+
// prompt, either of which can carry secrets (Bearer tokens, API keys) once
|
|
169
|
+
// env refs are interpolated. We show the bin, model, and the *names* of
|
|
170
|
+
// the servers / permission fields so the user can verify the shape without
|
|
171
|
+
// leaking credentials to stderr or CI logs.
|
|
172
|
+
const summary = [`model=${runtime.model}`];
|
|
173
|
+
if (runtime.harness === 'claude') {
|
|
174
|
+
const servers = Object.keys(resolvedMcp ?? {});
|
|
175
|
+
summary.push(`mcp-strict=${servers.length ? servers.join(',') : '(none)'}`);
|
|
176
|
+
if (selection.permissions?.allow?.length) {
|
|
177
|
+
summary.push(`allow=${selection.permissions.allow.length} rule(s)`);
|
|
178
|
+
}
|
|
179
|
+
if (selection.permissions?.deny?.length) {
|
|
180
|
+
summary.push(`deny=${selection.permissions.deny.length} rule(s)`);
|
|
181
|
+
}
|
|
182
|
+
if (selection.permissions?.mode) {
|
|
183
|
+
summary.push(`mode=${selection.permissions.mode}`);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
if (spec.initialPrompt)
|
|
187
|
+
summary.push('initial-prompt=<systemPrompt>');
|
|
188
|
+
process.stderr.write(`• spawning ${spec.bin} (${summary.join(', ')})\n`);
|
|
189
|
+
return new Promise((resolve) => {
|
|
190
|
+
let settled = false;
|
|
191
|
+
const finish = (code) => {
|
|
192
|
+
if (settled)
|
|
193
|
+
return;
|
|
194
|
+
settled = true;
|
|
195
|
+
runCleanup(install.cleanupCommand, install.cleanupCommandString);
|
|
196
|
+
resolve(code);
|
|
197
|
+
};
|
|
198
|
+
const child = spawn(spec.bin, finalArgs, {
|
|
199
|
+
stdio: 'inherit',
|
|
200
|
+
env: resolvedEnv ? { ...process.env, ...resolvedEnv } : process.env
|
|
201
|
+
});
|
|
202
|
+
const forward = (signal) => {
|
|
203
|
+
if (!child.killed)
|
|
204
|
+
child.kill(signal);
|
|
205
|
+
};
|
|
206
|
+
process.on('SIGINT', () => forward('SIGINT'));
|
|
207
|
+
process.on('SIGTERM', () => forward('SIGTERM'));
|
|
208
|
+
child.on('exit', (code, signal) => {
|
|
209
|
+
finish(code ?? signalExitCode(signal));
|
|
210
|
+
});
|
|
211
|
+
child.on('error', (err) => {
|
|
212
|
+
if (err.code === 'ENOENT') {
|
|
213
|
+
process.stderr.write(`Failed to spawn "${spec.bin}": binary not found on PATH. Install the ${runtime.harness} CLI and retry.\n`);
|
|
214
|
+
}
|
|
215
|
+
else {
|
|
216
|
+
process.stderr.write(`Failed to spawn "${spec.bin}": ${err.message}\n`);
|
|
217
|
+
}
|
|
218
|
+
finish(127);
|
|
219
|
+
});
|
|
220
|
+
});
|
|
221
|
+
}
|
|
222
|
+
async function main() {
|
|
223
|
+
const argv = process.argv.slice(2);
|
|
224
|
+
const [subcommand, ...rest] = argv;
|
|
225
|
+
if (!subcommand || subcommand === '-h' || subcommand === '--help') {
|
|
226
|
+
process.stdout.write(USAGE);
|
|
227
|
+
process.exit(subcommand ? 0 : 1);
|
|
228
|
+
}
|
|
229
|
+
if (subcommand !== 'agent') {
|
|
230
|
+
die(`Unknown subcommand "${subcommand}".`);
|
|
231
|
+
}
|
|
232
|
+
const [selector, ...taskParts] = rest;
|
|
233
|
+
if (!selector)
|
|
234
|
+
die('agent: missing persona selector.');
|
|
235
|
+
const target = parseSelector(selector);
|
|
236
|
+
const selection = buildSelection(target.spec, target.tier, target.kind);
|
|
237
|
+
if (taskParts.length > 0) {
|
|
238
|
+
await runOneShot(selection, taskParts.join(' '));
|
|
239
|
+
}
|
|
240
|
+
else {
|
|
241
|
+
const code = await runInteractive(selection);
|
|
242
|
+
process.exit(code);
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
main().catch((err) => {
|
|
246
|
+
process.stderr.write(`${err?.stack ?? String(err)}\n`);
|
|
247
|
+
process.exit(1);
|
|
248
|
+
});
|
|
249
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAEpC,OAAO,EACL,aAAa,EACb,cAAc,EACd,YAAY,EAIb,MAAM,iCAAiC,CAAC;AACzC,OAAO,EACL,oBAAoB,EACpB,kBAAkB,EAClB,wBAAwB,EACxB,uBAAuB,EAExB,MAAM,6BAA6B,CAAC;AACrC,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAExD,MAAM,KAAK,GAAG;;;eAGC,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC;;;;;;;;;;;;;;CAcvC,CAAC;AAEF,SAAS,GAAG,CAAC,GAAW,EAAE,SAAS,GAAG,IAAI;IACxC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,GAAG,IAAI,CAAC,CAAC;IACjC,IAAI,SAAS;QAAE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,KAAK,EAAE,CAAC,CAAC;IAClD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC;AAED,MAAM,KAAK,GAAG,iBAAiB,EAAE,CAAC;AAClC,KAAK,MAAM,OAAO,IAAI,KAAK,CAAC,QAAQ,EAAE,CAAC;IACrC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,YAAY,OAAO,IAAI,CAAC,CAAC;AAChD,CAAC;AAMD,SAAS,WAAW,CAAC,GAAW;IAC9B,MAAM,SAAS,GAAG,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACtC,IAAI,SAAS;QAAE,OAAO,SAAS,CAAC;IAChC,MAAM,eAAe,GAAI,cAA8C,CAAC,GAAG,CAAC,CAAC;IAC7E,IAAI,eAAe;QAAE,OAAO,eAAe,CAAC;IAC5C,MAAM,IAAI,GAAG,MAAM,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,GAAG,CAAC,CAAC;IACrE,IAAI,IAAI;QAAE,OAAO,IAAI,CAAC;IAEtB,MAAM,WAAW,GAAG,MAAM,CAAC,MAAM,CAAC,cAAc,CAAC;SAC9C,KAAK,EAAE;SACP,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;SACxC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,cAAc,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC;IAClD,MAAM,YAAY,GAAG,CAAC,GAAG,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;SAC1C,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;SACxC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,MAAM,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,OAAO,GAAG,CAAC,CAAC;IACpE,MAAM,OAAO,GAAG,CAAC,GAAG,WAAW,EAAE,GAAG,YAAY,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC7D,OAAO,EAAE,KAAK,EAAE,oBAAoB,GAAG,uBAAuB,OAAO,EAAE,EAAE,CAAC;AAC5E,CAAC;AAED,SAAS,aAAa,CAAC,GAAW;IAChC,MAAM,EAAE,GAAG,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IAC5B,MAAM,GAAG,GAAG,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IAC/C,MAAM,OAAO,GAAG,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC;IAC1D,IAAI,CAAC,GAAG;QAAE,GAAG,CAAC,iCAAiC,CAAC,CAAC;IACjD,MAAM,IAAI,GAAG,CAAC,OAAO,IAAI,YAAY,CAAgB,CAAC;IACtD,IAAI,OAAO,KAAK,SAAS,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QAC3D,GAAG,CAAC,iBAAiB,OAAO,sBAAsB,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAChF,CAAC;IACD,MAAM,MAAM,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC;IAChC,IAAI,OAAO,IAAI,MAAM;QAAE,GAAG,CAAC,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;IAChD,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC;IACpD,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;AACtC,CAAC;AAED,SAAS,cAAc,CAAC,IAAiB,EAAE,IAAiB,EAAE,IAAsB;IAClF,OAAO;QACL,SAAS,EAAE,IAAI,CAAC,EAAE;QAClB,IAAI;QACJ,OAAO,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC;QACzB,MAAM,EAAE,IAAI,CAAC,MAAM;QACnB,SAAS,EAAE,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,mBAAmB,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,sBAAsB,IAAI,EAAE;QACzF,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACtC,GAAG,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC3D,GAAG,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAC/D,CAAC;AACJ,CAAC;AAED,SAAS,gBAAgB,CAAC,KAAe;IACvC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO;IAC/B,KAAK,MAAM,IAAI,IAAI,KAAK;QAAE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,YAAY,IAAI,IAAI,CAAC,CAAC;IACrE,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,wKAAwK,CACzK,CAAC;AACJ,CAAC;AAED,KAAK,UAAU,UAAU,CACvB,SAA2B,EAC3B,IAAY;IAEZ,MAAM,EAAE,OAAO,EAAE,GAAG,SAAS,CAAC;IAC9B,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,KAAK,SAAS,CAAC,SAAS,KAAK,SAAS,CAAC,IAAI,SAAS,OAAO,CAAC,OAAO,KAAK,OAAO,CAAC,KAAK,KAAK,CAC3F,CAAC;IAEF,MAAM,aAAa,GAAG,uBAAuB,CAAC,SAAS,CAAC,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;IACjF,gBAAgB,CAAC,kBAAkB,CAAC,aAAa,CAAC,OAAO,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC;IAEpE,IAAI,SAAS,CAAC,UAAU,IAAI,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACzE,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,uJAAuJ,CACxJ,CAAC;IACJ,CAAC;IAED,MAAM,GAAG,GAAG,YAAY,CAAC,SAAS,CAAC,CAAC;IACpC,MAAM,SAAS,GAAG,GAAG,CAAC,WAAW,CAAC,IAAI,EAAE;QACtC,GAAG,EAAE,aAAa,CAAC,KAAK;QACxB,UAAU,EAAE,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE,EAAE;YAC/B,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACtE,CAAC;KACF,CAAC,CAAC;IACH,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC;QAC/B,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,IAAI,CAAC,CAAC,CAAC;IACrC,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,KAAK,GAAG,GAEb,CAAC;QACF,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,EAAE,MAAM,IAAI,QAAQ,CAAC;QAChD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,MAAM,KAAK,KAAK,CAAC,OAAO,IAAI,CAAC,CAAC;QACzD,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,QAAQ,IAAI,CAAC,CAAC,CAAC;IAC5C,CAAC;AACH,CAAC;AAED,SAAS,cAAc,CAAC,MAA6B;IACnD,IAAI,CAAC,MAAM;QAAE,OAAO,CAAC,CAAC;IACtB,MAAM,GAAG,GAAI,SAAS,CAAC,OAA8C,CAAC,MAAM,CAAC,CAAC;IAC9E,OAAO,GAAG,GAAG,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC;AAC1B,CAAC;AAED,SAAS,UAAU,CAAC,OAA0B,EAAE,KAAa;IAC3D,MAAM,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,GAAG,OAAO,CAAC;IAC/B,IAAI,CAAC,GAAG;QAAE,OAAO;IACjB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,KAAK,IAAI,CAAC,CAAC;IACrC,MAAM,GAAG,GAAG,SAAS,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;IACrE,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACrB,MAAM,IAAI,GAAG,GAAG,CAAC,MAAM,IAAI,CAAC,CAAC;QAC7B,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,KAAK,iBAAiB,IAAI,gBAAgB,CAAC,CAAC;QACpE,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACrB,CAAC;AACH,CAAC;AAED,SAAS,UAAU,CAAC,OAA0B,EAAE,aAAqB;IACnE,IAAI,aAAa,KAAK,GAAG;QAAE,OAAO;IAClC,MAAM,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,GAAG,OAAO,CAAC;IAC/B,IAAI,CAAC,GAAG;QAAE,OAAO;IACjB,SAAS,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;AAC3D,CAAC;AAED,SAAS,cAAc,CAAC,SAA2B;IACjD,MAAM,GAAG,GAAG,YAAY,CAAC,SAAS,CAAC,CAAC;IACpC,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,GAAG,SAAS,CAAC;IAC/C,MAAM,EAAE,OAAO,EAAE,GAAG,GAAG,CAAC;IACxB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,SAAS,KAAK,IAAI,SAAS,OAAO,CAAC,OAAO,KAAK,OAAO,CAAC,KAAK,KAAK,CAAC,CAAC;IAE7F,MAAM,aAAa,GAAG,uBAAuB,CAAC,SAAS,CAAC,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;IACjF,MAAM,aAAa,GAAG,wBAAwB,CAAC,SAAS,CAAC,UAAU,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC;IAClF,gBAAgB,CACd,kBAAkB,CAAC,aAAa,CAAC,OAAO,EAAE,aAAa,CAAC,OAAO,EAAE,aAAa,CAAC,cAAc,CAAC,CAC/F,CAAC;IACF,MAAM,WAAW,GAAG,aAAa,CAAC,KAAK,CAAC;IACxC,MAAM,WAAW,GAAG,aAAa,CAAC,OAAO,CAAC;IAE1C,IAAI,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACrC,MAAM,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACxE,UAAU,CAAC,OAAO,CAAC,OAAO,EAAE,sBAAsB,QAAQ,EAAE,CAAC,CAAC;IAChE,CAAC;IAED,MAAM,IAAI,GAAG,oBAAoB,CAAC;QAChC,OAAO,EAAE,OAAO,CAAC,OAAO;QACxB,KAAK,EAAE,OAAO,CAAC,KAAK;QACpB,YAAY,EAAE,OAAO,CAAC,YAAY;QAClC,UAAU,EAAE,WAAW;QACvB,WAAW,EAAE,SAAS,CAAC,WAAW;KACnC,CAAC,CAAC;IACH,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,QAAQ;QAAE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC;IACvE,MAAM,SAAS,GAAG,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC;IAE3F,2EAA2E;IAC3E,sEAAsE;IACtE,2EAA2E;IAC3E,wEAAwE;IACxE,2EAA2E;IAC3E,4CAA4C;IAC5C,MAAM,OAAO,GAAa,CAAC,SAAS,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC;IACrD,IAAI,OAAO,CAAC,OAAO,KAAK,QAAQ,EAAE,CAAC;QACjC,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,WAAW,IAAI,EAAE,CAAC,CAAC;QAC/C,OAAO,CAAC,IAAI,CAAC,cAAc,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC;QAC5E,IAAI,SAAS,CAAC,WAAW,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC;YACzC,OAAO,CAAC,IAAI,CAAC,SAAS,SAAS,CAAC,WAAW,CAAC,KAAK,CAAC,MAAM,UAAU,CAAC,CAAC;QACtE,CAAC;QACD,IAAI,SAAS,CAAC,WAAW,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;YACxC,OAAO,CAAC,IAAI,CAAC,QAAQ,SAAS,CAAC,WAAW,CAAC,IAAI,CAAC,MAAM,UAAU,CAAC,CAAC;QACpE,CAAC;QACD,IAAI,SAAS,CAAC,WAAW,EAAE,IAAI,EAAE,CAAC;YAChC,OAAO,CAAC,IAAI,CAAC,QAAQ,SAAS,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC,CAAC;QACrD,CAAC;IACH,CAAC;IACD,IAAI,IAAI,CAAC,aAAa;QAAE,OAAO,CAAC,IAAI,CAAC,+BAA+B,CAAC,CAAC;IACtE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,cAAc,IAAI,CAAC,GAAG,KAAK,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAEzE,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QAC7B,IAAI,OAAO,GAAG,KAAK,CAAC;QACpB,MAAM,MAAM,GAAG,CAAC,IAAY,EAAE,EAAE;YAC9B,IAAI,OAAO;gBAAE,OAAO;YACpB,OAAO,GAAG,IAAI,CAAC;YACf,UAAU,CAAC,OAAO,CAAC,cAAc,EAAE,OAAO,CAAC,oBAAoB,CAAC,CAAC;YACjE,OAAO,CAAC,IAAI,CAAC,CAAC;QAChB,CAAC,CAAC;QAEF,MAAM,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,SAAS,EAAE;YACvC,KAAK,EAAE,SAAS;YAChB,GAAG,EAAE,WAAW,CAAC,CAAC,CAAC,EAAE,GAAG,OAAO,CAAC,GAAG,EAAE,GAAG,WAAW,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG;SACpE,CAAC,CAAC;QAEH,MAAM,OAAO,GAAG,CAAC,MAAsB,EAAE,EAAE;YACzC,IAAI,CAAC,KAAK,CAAC,MAAM;gBAAE,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACxC,CAAC,CAAC;QACF,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC;QAC9C,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC;QAEhD,KAAK,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE;YAChC,MAAM,CAAC,IAAI,IAAI,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC;QACzC,CAAC,CAAC,CAAC;QACH,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,GAA0B,EAAE,EAAE;YAC/C,IAAI,GAAG,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;gBAC1B,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,oBAAoB,IAAI,CAAC,GAAG,4CAA4C,OAAO,CAAC,OAAO,mBAAmB,CAC3G,CAAC;YACJ,CAAC;iBAAM,CAAC;gBACN,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,oBAAoB,IAAI,CAAC,GAAG,MAAM,GAAG,CAAC,OAAO,IAAI,CAAC,CAAC;YAC1E,CAAC;YACD,MAAM,CAAC,GAAG,CAAC,CAAC;QACd,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC;AAED,KAAK,UAAU,IAAI;IACjB,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IACnC,MAAM,CAAC,UAAU,EAAE,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC;IAEnC,IAAI,CAAC,UAAU,IAAI,UAAU,KAAK,IAAI,IAAI,UAAU,KAAK,QAAQ,EAAE,CAAC;QAClE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QAC5B,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACnC,CAAC;IAED,IAAI,UAAU,KAAK,OAAO,EAAE,CAAC;QAC3B,GAAG,CAAC,uBAAuB,UAAU,IAAI,CAAC,CAAC;IAC7C,CAAC;IAED,MAAM,CAAC,QAAQ,EAAE,GAAG,SAAS,CAAC,GAAG,IAAI,CAAC;IACtC,IAAI,CAAC,QAAQ;QAAE,GAAG,CAAC,kCAAkC,CAAC,CAAC;IAEvD,MAAM,MAAM,GAAG,aAAa,CAAC,QAAQ,CAAC,CAAC;IACvC,MAAM,SAAS,GAAG,cAAc,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC;IAExE,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACzB,MAAM,UAAU,CAAC,SAAS,EAAE,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;IACnD,CAAC;SAAM,CAAC;QACN,MAAM,IAAI,GAAG,MAAM,cAAc,CAAC,SAAS,CAAC,CAAC;QAC7C,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACrB,CAAC;AACH,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;IACnB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAI,GAAa,EAAE,KAAK,IAAI,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAClE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
|