@llamaventures/cli 1.25.0 → 2.0.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.
@@ -1,9 +1,9 @@
1
1
  {
2
2
  "format": "llama.core-api-contract.v1",
3
3
  "name": "llama-core-api",
4
- "apiVersion": "3.26.0",
4
+ "apiVersion": "4.0.0",
5
5
  "openapiVersion": "3.0.3",
6
- "sha256": "1ab4db8774b6dc0d94d6d6b4dd79f8272c6a405a3474710ac4162cc8a0dc6981",
7
- "pathCount": 236,
8
- "operationCount": 307
6
+ "sha256": "69b5e29ae9585915da0fa9578abfd41099545f11eba8b2d12f14aa42cc970e4e",
7
+ "pathCount": 247,
8
+ "operationCount": 323
9
9
  }
@@ -2,361 +2,32 @@
2
2
  "format": "llama.cli-core-api-operations.v1",
3
3
  "coreApiContract": "contracts/core-api.json",
4
4
  "requiredOperations": [
5
- {
6
- "method": "GET",
7
- "path": "/api/admin/agent-events"
8
- },
9
- {
10
- "method": "GET",
11
- "path": "/api/admin/auth-events"
12
- },
13
- {
14
- "method": "GET",
15
- "path": "/api/admin/deal-events"
16
- },
17
- {
18
- "method": "GET",
19
- "path": "/api/admin/workflow-audit"
20
- },
21
- {
22
- "method": "POST",
23
- "path": "/api/admin/workflow-remediation"
24
- },
25
- {
26
- "method": "GET",
27
- "path": "/api/agent/activity"
28
- },
29
- {
30
- "method": "GET",
31
- "path": "/api/agent/briefing"
32
- },
33
- {
34
- "method": "POST",
35
- "path": "/api/agent/client-events"
36
- },
37
- {
38
- "method": "GET",
39
- "path": "/api/agent/explain"
40
- },
41
- {
42
- "method": "GET",
43
- "path": "/api/agent/manifest"
44
- },
45
- {
46
- "method": "GET",
47
- "path": "/api/agent/preferences"
48
- },
49
- {
50
- "method": "POST",
51
- "path": "/api/agent/preferences"
52
- },
53
- {
54
- "method": "PATCH",
55
- "path": "/api/agent/preferences/{id}"
56
- },
57
- {
58
- "method": "GET",
59
- "path": "/api/agent/skills"
60
- },
61
- {
62
- "method": "GET",
63
- "path": "/api/agent/skills/{slug}"
64
- },
65
- {
66
- "method": "GET",
67
- "path": "/api/deals"
68
- },
69
- {
70
- "method": "POST",
71
- "path": "/api/deals/create"
72
- },
73
- {
74
- "method": "GET",
75
- "path": "/api/deals/deleted"
76
- },
77
- {
78
- "method": "POST",
79
- "path": "/api/deals/update"
80
- },
81
- {
82
- "method": "DELETE",
83
- "path": "/api/deals/{dealId}"
84
- },
85
- {
86
- "method": "GET",
87
- "path": "/api/deals/{dealId}"
88
- },
89
- {
90
- "method": "GET",
91
- "path": "/api/deals/{dealId}/workflow"
92
- },
93
- {
94
- "method": "POST",
95
- "path": "/api/deals/{dealId}/workflow"
96
- },
97
- {
98
- "method": "POST",
99
- "path": "/api/deals/{dealId}/agent-runs/{runId}/revert"
100
- },
101
- {
102
- "method": "GET",
103
- "path": "/api/deals/{dealId}/blocks"
104
- },
105
- {
106
- "method": "PUT",
107
- "path": "/api/deals/{dealId}/blocks"
108
- },
109
- {
110
- "method": "DELETE",
111
- "path": "/api/deals/{dealId}/blocks/{blockId}"
112
- },
113
- {
114
- "method": "GET",
115
- "path": "/api/deals/{dealId}/blocks/{blockId}"
116
- },
117
- {
118
- "method": "PATCH",
119
- "path": "/api/deals/{dealId}/blocks/{blockId}"
120
- },
121
- {
122
- "method": "GET",
123
- "path": "/api/deals/{dealId}/blocks/{blockId}/history"
124
- },
125
- {
126
- "method": "POST",
127
- "path": "/api/deals/{dealId}/blocks/{blockId}/history"
128
- },
129
- {
130
- "method": "POST",
131
- "path": "/api/deals/{dealId}/blocks/{blockId}/restore"
132
- },
133
- {
134
- "method": "GET",
135
- "path": "/api/deals/{dealId}/collaborators"
136
- },
137
- {
138
- "method": "POST",
139
- "path": "/api/deals/{dealId}/collaborators"
140
- },
141
- {
142
- "method": "DELETE",
143
- "path": "/api/deals/{dealId}/collaborators/{userId}"
144
- },
145
- {
146
- "method": "POST",
147
- "path": "/api/deals/{dealId}/collaborators/{userId}/restore"
148
- },
149
- {
150
- "method": "GET",
151
- "path": "/api/deals/{dealId}/command-center"
152
- },
153
- {
154
- "method": "GET",
155
- "path": "/api/deals/{dealId}/documents"
156
- },
157
- {
158
- "method": "POST",
159
- "path": "/api/deals/{dealId}/documents"
160
- },
161
- {
162
- "method": "DELETE",
163
- "path": "/api/deals/{dealId}/documents/{slug}"
164
- },
165
- {
166
- "method": "PATCH",
167
- "path": "/api/deals/{dealId}/documents/{slug}"
168
- },
169
- {
170
- "method": "DELETE",
171
- "path": "/api/deals/{dealId}/documents/{slug}/html"
172
- },
173
- {
174
- "method": "GET",
175
- "path": "/api/deals/{dealId}/documents/{slug}/html"
176
- },
177
- {
178
- "method": "PUT",
179
- "path": "/api/deals/{dealId}/documents/{slug}/html"
180
- },
181
- {
182
- "method": "GET",
183
- "path": "/api/deals/{dealId}/documents/{slug}/html/history"
184
- },
185
- {
186
- "method": "POST",
187
- "path": "/api/deals/{dealId}/documents/{slug}/html/restore/{version}"
188
- },
189
- {
190
- "method": "POST",
191
- "path": "/api/deals/{dealId}/enrich"
192
- },
193
- {
194
- "method": "GET",
195
- "path": "/api/deals/{dealId}/facts"
196
- },
197
- {
198
- "method": "POST",
199
- "path": "/api/deals/{dealId}/facts"
200
- },
201
- {
202
- "method": "PATCH",
203
- "path": "/api/deals/{dealId}/facts/{factId}"
204
- },
205
- {
206
- "method": "POST",
207
- "path": "/api/deals/{dealId}/facts/{factId}/uncontest"
208
- },
209
- {
210
- "method": "GET",
211
- "path": "/api/deals/{dealId}/feed"
212
- },
213
- {
214
- "method": "PUT",
215
- "path": "/api/deals/{dealId}/founders"
216
- },
217
- {
218
- "method": "POST",
219
- "path": "/api/deals/{dealId}/ingest"
220
- },
221
- {
222
- "method": "GET",
223
- "path": "/api/deals/{dealId}/links"
224
- },
225
- {
226
- "method": "POST",
227
- "path": "/api/deals/{dealId}/links"
228
- },
229
- {
230
- "method": "DELETE",
231
- "path": "/api/deals/{dealId}/links/{linkId}"
232
- },
233
- {
234
- "method": "POST",
235
- "path": "/api/deals/{dealId}/links/{linkId}/restore"
236
- },
237
- {
238
- "method": "DELETE",
239
- "path": "/api/deals/{dealId}/memo"
240
- },
241
- {
242
- "method": "GET",
243
- "path": "/api/deals/{dealId}/memo"
244
- },
245
- {
246
- "method": "POST",
247
- "path": "/api/deals/{dealId}/memo"
248
- },
249
- {
250
- "method": "PUT",
251
- "path": "/api/deals/{dealId}/memo"
252
- },
253
- {
254
- "method": "POST",
255
- "path": "/api/deals/{dealId}/posts"
256
- },
257
- {
258
- "method": "POST",
259
- "path": "/api/deals/{dealId}/propose-owner"
260
- },
261
- {
262
- "method": "POST",
263
- "path": "/api/deals/{dealId}/refresh-brief"
264
- },
265
- {
266
- "method": "POST",
267
- "path": "/api/deals/{dealId}/restore"
268
- },
269
- {
270
- "method": "POST",
271
- "path": "/api/deals/{dealId}/threads"
272
- },
273
- {
274
- "method": "POST",
275
- "path": "/api/deals/{dealId}/threads/{threadId}"
276
- },
277
- {
278
- "method": "GET",
279
- "path": "/api/deals/{dealId}/timeline"
280
- },
281
- {
282
- "method": "POST",
283
- "path": "/api/external/chat"
284
- },
285
- {
286
- "method": "POST",
287
- "path": "/api/external/start-session"
288
- },
289
- {
290
- "method": "POST",
291
- "path": "/api/external/upload"
292
- },
293
- {
294
- "method": "GET",
295
- "path": "/api/me"
296
- },
297
- {
298
- "method": "GET",
299
- "path": "/api/me/nominations"
300
- },
301
- {
302
- "method": "GET",
303
- "path": "/api/mentions"
304
- },
305
- {
306
- "method": "GET",
307
- "path": "/api/mentions/unread-count"
308
- },
309
- {
310
- "method": "POST",
311
- "path": "/api/mentions/{id}/resolve"
312
- },
313
- {
314
- "method": "POST",
315
- "path": "/api/nominations/{approvalId}"
316
- },
317
- {
318
- "method": "GET",
319
- "path": "/api/oauth/authorize"
320
- },
321
- {
322
- "method": "POST",
323
- "path": "/api/oauth/revoke"
324
- },
325
- {
326
- "method": "POST",
327
- "path": "/api/oauth/token"
328
- },
329
- {
330
- "method": "GET",
331
- "path": "/api/partner/approvals"
332
- },
333
- {
334
- "method": "POST",
335
- "path": "/api/partner/approvals"
336
- },
337
- {
338
- "method": "GET",
339
- "path": "/api/users"
340
- },
341
- {
342
- "method": "POST",
343
- "path": "/api/wiki/save"
344
- },
345
- {
346
- "method": "GET",
347
- "path": "/api/wiki/search"
348
- },
349
- {
350
- "method": "DELETE",
351
- "path": "/api/wiki/{slug}"
352
- },
353
- {
354
- "method": "GET",
355
- "path": "/api/wiki/{slug}"
356
- },
357
- {
358
- "method": "POST",
359
- "path": "/api/wiki/{slug}/restore"
360
- }
5
+ { "method": "DELETE", "path": "/api/wiki/{slug}" },
6
+ { "method": "GET", "path": "/api/admin/agent-events" },
7
+ { "method": "GET", "path": "/api/admin/auth-events" },
8
+ { "method": "GET", "path": "/api/admin/deal-events" },
9
+ { "method": "GET", "path": "/api/agent/briefing" },
10
+ { "method": "GET", "path": "/api/agent/explain" },
11
+ { "method": "GET", "path": "/api/agent/manifest" },
12
+ { "method": "GET", "path": "/api/agent/preferences" },
13
+ { "method": "GET", "path": "/api/agent/skills" },
14
+ { "method": "GET", "path": "/api/agent/skills/{slug}" },
15
+ { "method": "GET", "path": "/api/me" },
16
+ { "method": "GET", "path": "/api/oauth/authorize" },
17
+ { "method": "GET", "path": "/api/occam/deals" },
18
+ { "method": "GET", "path": "/api/occam/deals/{dealId}" },
19
+ { "method": "GET", "path": "/api/wiki/{slug}" },
20
+ { "method": "GET", "path": "/api/wiki/search" },
21
+ { "method": "PATCH", "path": "/api/agent/preferences/{id}" },
22
+ { "method": "POST", "path": "/api/agent/client-events" },
23
+ { "method": "POST", "path": "/api/agent/preferences" },
24
+ { "method": "POST", "path": "/api/external/chat" },
25
+ { "method": "POST", "path": "/api/external/start-session" },
26
+ { "method": "POST", "path": "/api/external/upload" },
27
+ { "method": "POST", "path": "/api/oauth/revoke" },
28
+ { "method": "POST", "path": "/api/oauth/token" },
29
+ { "method": "POST", "path": "/api/occam/deals/commands" },
30
+ { "method": "POST", "path": "/api/wiki/{slug}/restore" },
31
+ { "method": "POST", "path": "/api/wiki/save" }
361
32
  ]
362
33
  }
@@ -1,15 +1,15 @@
1
1
  {
2
2
  "format": "llama.cli-build.v1",
3
3
  "packageName": "@llamaventures/cli",
4
- "packageVersion": "1.25.0",
5
- "sourceSha": "4b70d873886c521d02cc7c75659425ed6e2989f6",
4
+ "packageVersion": "2.0.0",
5
+ "sourceSha": "1564eee5aa59c89fc4e245f0a5be0fcbe96d7bf9",
6
6
  "sourceKind": "github",
7
7
  "sourceDirty": false,
8
8
  "coreApiContract": {
9
9
  "format": "llama.core-api-contract.v1",
10
10
  "name": "llama-core-api",
11
- "apiVersion": "3.26.0",
11
+ "apiVersion": "4.0.0",
12
12
  "openapiVersion": "3.0.3",
13
- "sha256": "1ab4db8774b6dc0d94d6d6b4dd79f8272c6a405a3474710ac4162cc8a0dc6981"
13
+ "sha256": "69b5e29ae9585915da0fa9578abfd41099545f11eba8b2d12f14aa42cc970e4e"
14
14
  }
15
15
  }
package/lib/client.mjs CHANGED
@@ -59,11 +59,11 @@ export function getPackageVersion() {
59
59
  return packageVersionCache;
60
60
  }
61
61
 
62
- // Canonical entrypoint. `llama-command.onrender.com` also serves the API
63
- // but its NextAuth callback URL doesn't match, so browser login (needed
64
- // to mint a token at /settings/tokens) fails there with a server-config
65
- // error. Always default to canonical — override with $LLAMA_API_URL only
66
- // if testing.
62
+ // Canonical entrypoint. The hosting provider's assigned hostname also
63
+ // serves the API, but its NextAuth callback URL doesn't match, so browser
64
+ // login (needed to mint a token at /settings/tokens) fails there with a
65
+ // server-config error. Always default to canonical — override with
66
+ // $LLAMA_API_URL only if testing.
67
67
  export const DEFAULT_BASE_URL = "https://command.llamaventures.vc";
68
68
 
69
69
  // Canonical token location (single line, mode 0600). Aligns with the
@@ -212,6 +212,7 @@ function agentClientHeaders(command) {
212
212
  return {
213
213
  "X-Llama-Client": runtimeClient,
214
214
  "X-Llama-Client-Version": getPackageVersion(),
215
+ "X-Llama-Client-Capabilities": "core.read.v1,occam.deal.v1",
215
216
  "X-Llama-Client-Source-Sha": build.sourceSha,
216
217
  "X-Llama-API-Contract-Version": build.coreApiContract.apiVersion,
217
218
  "X-Llama-API-Contract-Digest": build.coreApiContract.sha256,
@@ -290,6 +291,9 @@ function inferCommand(method, endpoint) {
290
291
  if (pathname === "/api/wiki/search") return "wiki.search";
291
292
  if (pathname === "/api/wiki/save") return "wiki.save";
292
293
  if (/^\/api\/wiki\/[^/]+$/.test(pathname)) return verb === "GET" ? "wiki.read" : "wiki.write";
294
+ if (pathname === "/api/occam/deals") return "deal.search";
295
+ if (pathname === "/api/occam/deals/commands") return "deal.write";
296
+ if (/^\/api\/occam\/deals\/[^/]+$/.test(pathname)) return "deal.read";
293
297
  if (pathname === "/api/deals") return verb === "GET" ? "deal.search" : "deal.write";
294
298
  if (pathname === "/api/deals/create") return "deal.create";
295
299
  if (pathname === "/api/deals/update") return "deal.update";
@@ -536,12 +540,14 @@ function apiResponseError(data, status) {
536
540
  );
537
541
  error.code = data.code;
538
542
  error.details = data;
543
+ error.status = status;
539
544
  return error;
540
545
  }
541
546
  if (data?.code !== "MENTION_APPROVAL_REQUIRED") {
542
547
  const error = new Error(message);
543
548
  if (typeof data?.code === "string") error.code = data.code;
544
549
  error.details = data;
550
+ error.status = status;
545
551
  return error;
546
552
  }
547
553
  const recipients = Array.isArray(data?.cue?.recipients)
@@ -563,6 +569,7 @@ function apiResponseError(data, status) {
563
569
  );
564
570
  error.code = data.code;
565
571
  error.details = data;
572
+ error.status = status;
566
573
  return error;
567
574
  }
568
575
 
@@ -0,0 +1,102 @@
1
+ import { createHash } from "node:crypto";
2
+ import { readFile } from "node:fs/promises";
3
+
4
+ export const DEAL_ACTIONS = Object.freeze(["search", "read", "create", "write"]);
5
+ export const DEAL_WRITE_OPERATIONS = Object.freeze([
6
+ "input.submit",
7
+ "information.put",
8
+ "page.patch",
9
+ "artifact.put",
10
+ ]);
11
+
12
+ function canonicalJson(value) {
13
+ if (Array.isArray(value)) return `[${value.map(canonicalJson).join(",")}]`;
14
+ if (value && typeof value === "object") {
15
+ return `{${Object.keys(value)
16
+ .sort()
17
+ .map((key) => `${JSON.stringify(key)}:${canonicalJson(value[key])}`)
18
+ .join(",")}}`;
19
+ }
20
+ return JSON.stringify(value);
21
+ }
22
+
23
+ export function ensureIdempotencyKey(command) {
24
+ if (typeof command?.idempotencyKey === "string" && command.idempotencyKey.trim()) {
25
+ return command;
26
+ }
27
+ const digest = createHash("sha256").update(canonicalJson(command)).digest("hex").slice(0, 40);
28
+ return { ...command, idempotencyKey: `cli:${digest}` };
29
+ }
30
+
31
+ export function validateCommandOrigin(command) {
32
+ const origin = command?.origin;
33
+ if (!origin || !["user", "agent", "system"].includes(origin.kind)) {
34
+ throw new Error("Mutation JSON must include origin.kind: user, agent, or system");
35
+ }
36
+ if (
37
+ origin.kind === "user" &&
38
+ !(typeof origin.originalUserUtterance === "string" && origin.originalUserUtterance.trim()) &&
39
+ !(typeof origin.originatingChatRecordId === "string" && origin.originatingChatRecordId.trim())
40
+ ) {
41
+ throw new Error(
42
+ "User-originated mutation JSON must preserve origin.originalUserUtterance or origin.originatingChatRecordId",
43
+ );
44
+ }
45
+ return command;
46
+ }
47
+
48
+ export async function readJsonInput(path, stdin = process.stdin) {
49
+ if (!path || path === true) throw new Error("--json <file|-> is required");
50
+ const text = path === "-"
51
+ ? await new Promise((resolve, reject) => {
52
+ let value = "";
53
+ stdin.setEncoding("utf8");
54
+ stdin.on("data", (chunk) => { value += chunk; });
55
+ stdin.on("end", () => resolve(value));
56
+ stdin.on("error", reject);
57
+ })
58
+ : await readFile(path, "utf8");
59
+ try {
60
+ return JSON.parse(text);
61
+ } catch (error) {
62
+ throw new Error(`Invalid JSON from ${path}: ${error instanceof Error ? error.message : String(error)}`);
63
+ }
64
+ }
65
+
66
+ export function buildDealSearchPath(query, flags = {}) {
67
+ const params = new URLSearchParams();
68
+ if (query) params.set("q", query);
69
+ if (flags.state && flags.state !== true) params.set("state", String(flags.state));
70
+ if (flags.limit && flags.limit !== true) params.set("limit", String(flags.limit));
71
+ return `/api/occam/deals${params.size ? `?${params}` : ""}`;
72
+ }
73
+
74
+ export function buildDealReadPath(dealId, detail = "overview") {
75
+ if (!dealId || dealId.startsWith("--")) {
76
+ throw new Error("Usage: llama deal read <dealId> [--detail overview|memory|files|conversation|history|all]");
77
+ }
78
+ const expansion = {
79
+ overview: "",
80
+ memory: "information",
81
+ files: "artifacts",
82
+ conversation: "chat",
83
+ history: "feed",
84
+ all: "information,artifacts,chat,feed",
85
+ }[detail];
86
+ if (expansion === undefined) throw new Error(`Unknown detail: ${detail}`);
87
+ return `/api/occam/deals/${encodeURIComponent(dealId)}${expansion ? `?expand=${expansion}` : ""}`;
88
+ }
89
+
90
+ export function prepareDealCommand(action, input) {
91
+ if (!input || typeof input !== "object" || Array.isArray(input)) {
92
+ throw new Error("Mutation JSON must be an object");
93
+ }
94
+ const command = action === "create" ? { operation: "deal.create", ...input } : input;
95
+ if (action === "create" && command.operation !== "deal.create") {
96
+ throw new Error("create JSON must describe one deal.create intent");
97
+ }
98
+ if (action === "write" && !DEAL_WRITE_OPERATIONS.includes(command.operation)) {
99
+ throw new Error(`write JSON operation must be ${DEAL_WRITE_OPERATIONS.join(", ")}`);
100
+ }
101
+ return ensureIdempotencyKey(validateCommandOrigin(command));
102
+ }
package/package.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@llamaventures/cli",
3
- "version": "1.25.0",
3
+ "version": "2.0.0",
4
4
  "description": "CLI + MCP server for the Llama Ventures investment workbench (command.llamaventures.vc).",
5
5
  "type": "module",
6
6
  "scripts": {
7
7
  "test": "npm run test:agent-routing && npm run test:contract",
8
8
  "test:agent-routing": "node scripts/verify-agent-routing.mjs",
9
- "test:contract": "node --test scripts/build-manifest.test.mjs scripts/core-api-call-sites.test.mjs scripts/investment-workflow-contract.test.mjs scripts/server-compatibility.test.mjs scripts/verify-core-api-contract.test.mjs scripts/workflow-audit.test.mjs scripts/workflow-remediation.test.mjs && node scripts/verify-core-api-contract.mjs",
9
+ "test:contract": "node --test scripts/build-manifest.test.mjs scripts/core-api-call-sites.test.mjs scripts/deal-actions-cli.test.mjs scripts/deal-actions.test.mjs scripts/mcp-four-action-surface.test.mjs scripts/server-compatibility.test.mjs scripts/verify-core-api-contract.test.mjs && node scripts/verify-core-api-contract.mjs",
10
10
  "verify:artifact": "node scripts/verify-release-artifact.mjs",
11
11
  "verify:release": "npm test && npm run verify:artifact && node scripts/verify-tarball-clean.mjs",
12
12
  "prepack": "node scripts/prepare-build-manifest.mjs",
@@ -56,7 +56,7 @@
56
56
  "access": "public"
57
57
  },
58
58
  "dependencies": {
59
- "@modelcontextprotocol/sdk": "1.29.0",
59
+ "@modelcontextprotocol/sdk": "1.30.0",
60
60
  "@napi-rs/keyring": "^1.3.0",
61
61
  "zod": "^4.4.3"
62
62
  }
@@ -1,19 +0,0 @@
1
- # Investment Workflow V2 client contract
2
-
3
- CLI and MCP treat `GET/POST /api/deals/{dealId}/workflow` as the only workflow
4
- read/write surface. A write must first read the current revision, submit one
5
- typed command with a unique request id, and display the canonical response.
6
-
7
- Never add a client shortcut that writes `deals.status`,
8
- `extra.investment_workflow_v2` snapshots, `extra.stage_gates`, or
9
- `extra.stage4_gate`. Partner
10
- decisions are always made by the authenticated Partner; admin capability does
11
- not imply permission to impersonate a decision maker.
12
-
13
- `workflow initialize` is the audited bootstrap command for legacy migration.
14
- It persists the state returned by `workflow show` without advancing a stage or
15
- resolving a guard. Never translate legacy approvals into V2 approvals silently.
16
-
17
- Post-IC compatibility status is also owned by V2. Use `workflow
18
- execution-status` / `workflow_update_execution_status` for Term Sheet, Verbal
19
- Commit, and Invested; never reopen direct `deal update ... status` writes.
@@ -1,13 +0,0 @@
1
- export function workflowAuditPath(flags) {
2
- const deal = typeof flags.deal === "string" && flags.deal.trim()
3
- ? flags.deal.trim()
4
- : null;
5
- const all = flags.all === true;
6
- if ((!deal && !all) || (deal && all)) {
7
- throw new Error("Usage: llama admin workflow audit --deal <uuid> | --all");
8
- }
9
- const params = new URLSearchParams();
10
- if (deal) params.set("deal", deal);
11
- if (all) params.set("all", "true");
12
- return `/api/admin/workflow-audit?${params.toString()}`;
13
- }