@datalabrotterdam/nova-ai-cli 1.1.0 → 1.2.0-alpha.2

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.
Files changed (50) hide show
  1. package/CHANGELOG.md +70 -0
  2. package/README.md +160 -101
  3. package/dist/chunk-NHGIUEIR.js +754 -0
  4. package/dist/chunk-SKAW2KXC.js +10 -0
  5. package/dist/headless-OFJFVJ3O.js +543 -0
  6. package/dist/index.js +155 -17
  7. package/dist/tui-NJWDD5X7.js +4810 -0
  8. package/dist/webui-L4GGMXJ3.js +9 -0
  9. package/package.json +32 -32
  10. package/dist/acp/agent.d.ts +0 -13
  11. package/dist/acp/agent.js +0 -242
  12. package/dist/acp/auth-server.d.ts +0 -10
  13. package/dist/acp/auth-server.js +0 -67
  14. package/dist/acp/credentials.d.ts +0 -11
  15. package/dist/acp/credentials.js +0 -30
  16. package/dist/acp/index.d.ts +0 -2
  17. package/dist/acp/index.js +0 -21
  18. package/dist/acp/mcp.d.ts +0 -11
  19. package/dist/acp/mcp.js +0 -90
  20. package/dist/acp/sessions.d.ts +0 -20
  21. package/dist/acp/sessions.js +0 -91
  22. package/dist/acp/tools/index.d.ts +0 -6
  23. package/dist/acp/tools/index.js +0 -5
  24. package/dist/acp/tools/marker.d.ts +0 -17
  25. package/dist/acp/tools/marker.js +0 -43
  26. package/dist/acp/tools/permission.d.ts +0 -2
  27. package/dist/acp/tools/permission.js +0 -20
  28. package/dist/acp/tools/read-file.d.ts +0 -2
  29. package/dist/acp/tools/read-file.js +0 -20
  30. package/dist/acp/tools/registry.d.ts +0 -4
  31. package/dist/acp/tools/registry.js +0 -10
  32. package/dist/acp/tools/reporting.d.ts +0 -3
  33. package/dist/acp/tools/reporting.js +0 -26
  34. package/dist/acp/tools/run-command.d.ts +0 -2
  35. package/dist/acp/tools/run-command.js +0 -29
  36. package/dist/acp/tools/system-prompt.d.ts +0 -2
  37. package/dist/acp/tools/system-prompt.js +0 -23
  38. package/dist/acp/tools/types.d.ts +0 -18
  39. package/dist/acp/tools/types.js +0 -1
  40. package/dist/acp/tools/write-file.d.ts +0 -2
  41. package/dist/acp/tools/write-file.js +0 -20
  42. package/dist/index.d.ts +0 -2
  43. package/dist/tui/index.d.ts +0 -7
  44. package/dist/tui/index.js +0 -11
  45. package/dist/webui/index.d.ts +0 -6
  46. package/dist/webui/index.js +0 -9
  47. package/src/acp/web/dist/assets/index-CSccI7lJ.css +0 -1
  48. package/src/acp/web/dist/assets/index-D2Z0sfLR.js +0 -1
  49. package/src/acp/web/dist/favicon.svg +0 -46
  50. package/src/acp/web/dist/index.html +0 -32
@@ -0,0 +1,10 @@
1
+ // src/version.ts
2
+ import { readPackageVersion } from "@datalabrotterdam/nova-ai-agent/core/version.js";
3
+ var CLI_PACKAGE_NAME = "@datalabrotterdam/nova-ai-cli";
4
+ function cliVersion() {
5
+ return readPackageVersion(CLI_PACKAGE_NAME, import.meta.url);
6
+ }
7
+
8
+ export {
9
+ cliVersion
10
+ };
@@ -0,0 +1,543 @@
1
+ import {
2
+ TuiAcpClient,
3
+ choosePermissionOption,
4
+ createStore,
5
+ readWorkspaceMcpConfiguration
6
+ } from "./chunk-NHGIUEIR.js";
7
+
8
+ // src/headless/index.ts
9
+ import { resolve } from "path";
10
+ import { NOVA_NOTIFICATIONS } from "@datalabrotterdam/nova-ai-agent/acp/extensions.js";
11
+ import * as acp from "@agentclientprotocol/sdk";
12
+ import { NovaAgent } from "@datalabrotterdam/nova-ai-agent/acp/agent.js";
13
+ import { clientFromContext } from "@datalabrotterdam/nova-ai-agent/client/context-client.js";
14
+ import { startInProcessAgent } from "@datalabrotterdam/nova-ai-agent/client/in-process.js";
15
+ import { setWorkspaceTrusted } from "@datalabrotterdam/nova-ai-agent/core/nova-home.js";
16
+ import { listStoredSessions, loadStoredSession } from "@datalabrotterdam/nova-ai-agent/core/sessions.js";
17
+
18
+ // src/headless/client.ts
19
+ var HeadlessAcpClient = class {
20
+ constructor(cwd, permissionMode, emit) {
21
+ this.permissionMode = permissionMode;
22
+ this.emit = emit;
23
+ const store = createStore({
24
+ messages: [],
25
+ plan: [],
26
+ pendingPermission: null,
27
+ pendingQuestion: null,
28
+ inputHistory: [],
29
+ busy: false,
30
+ mode: "chat",
31
+ permissionMode: "ask",
32
+ interactionMode: "agent",
33
+ sessionId: "headless",
34
+ cwd,
35
+ statusLine: null,
36
+ queuedCount: 0,
37
+ contextUsage: null,
38
+ updateAvailable: null
39
+ });
40
+ this.base = new TuiAcpClient(store, cwd);
41
+ this.baseContext = this.base.context();
42
+ }
43
+ permissionMode;
44
+ emit;
45
+ capabilities = {
46
+ fs: { readTextFile: true, writeTextFile: true },
47
+ terminal: true
48
+ };
49
+ base;
50
+ baseContext;
51
+ toolNames = /* @__PURE__ */ new Map();
52
+ context() {
53
+ return {
54
+ request: (method, params, options) => this.handleRequest(method, params, options),
55
+ notify: (method, params) => this.handleNotification(method, params)
56
+ };
57
+ }
58
+ async close() {
59
+ await this.base.releaseAllTerminals();
60
+ }
61
+ async handleRequest(method, params, options) {
62
+ options?.cancellationSignal?.throwIfAborted();
63
+ if (method === "session/request_permission") {
64
+ return this.requestPermission(params);
65
+ }
66
+ if (method === "elicitation/create") {
67
+ return { action: "decline" };
68
+ }
69
+ return this.baseContext.request(method, params, options);
70
+ }
71
+ async handleNotification(method, params) {
72
+ await this.emit({ type: "notification", method, params });
73
+ if (method === "session/update") await this.reportAgentDecision(params);
74
+ await this.baseContext.notify(method, params);
75
+ }
76
+ /**
77
+ * The agent's policy already applied rules and the mode (set from
78
+ * --permission-mode); what still reaches us needs a person, and there is
79
+ * none: only bypass-all approves it.
80
+ */
81
+ async requestPermission(params) {
82
+ const toolName = this.toolName(params.toolCall);
83
+ const allow = this.permissionMode === "bypass-all";
84
+ const optionId = choosePermissionOption(params.options, allow, "once") ?? (allow ? "allow_once" : "reject_once");
85
+ await this.emit({
86
+ type: "permission",
87
+ toolCallId: params.toolCall.toolCallId,
88
+ toolName,
89
+ decision: allow ? "allow" : "reject",
90
+ source: this.permissionMode
91
+ });
92
+ return { outcome: { outcome: "selected", optionId } };
93
+ }
94
+ /** Reports decisions the agent's policy made without asking. */
95
+ async reportAgentDecision(params) {
96
+ const update = params?.update;
97
+ if (!update) return;
98
+ const toolCallId = typeof update.toolCallId === "string" ? update.toolCallId : null;
99
+ if (!toolCallId) return;
100
+ if (update.sessionUpdate === "tool_call") {
101
+ this.toolNames.set(toolCallId, this.toolName(update));
102
+ return;
103
+ }
104
+ const permission = update._meta?.["nova-ai-cli/permission"];
105
+ if (update.sessionUpdate !== "tool_call_update" || !permission) return;
106
+ await this.emit({
107
+ type: "permission",
108
+ toolCallId,
109
+ toolName: this.toolNames.get(toolCallId) ?? "tool",
110
+ decision: permission.decision === "allow" ? "allow" : "reject",
111
+ source: permission.reason === "mode" ? this.permissionMode : "rule"
112
+ });
113
+ }
114
+ toolName(call) {
115
+ const fromMeta = call._meta?.["nova-ai-cli/tool"];
116
+ return typeof fromMeta === "string" ? fromMeta : call.title ?? "tool";
117
+ }
118
+ };
119
+
120
+ // src/headless/index.ts
121
+ var AGENT_PERMISSION_MODE = {
122
+ "read-only": "default",
123
+ "accept-edits": "acceptEdits",
124
+ "bypass-all": "bypassPermissions"
125
+ };
126
+ async function runHeadless(args, dependencies = {}) {
127
+ const stdout = dependencies.stdout ?? process.stdout;
128
+ const stderr = dependencies.stderr ?? process.stderr;
129
+ let options;
130
+ try {
131
+ options = parseHeadlessArgs(args, process.cwd());
132
+ } catch (error) {
133
+ const message = errorMessage(error);
134
+ if (args.includes("--json") || args.some((arg) => /^--output-format(=|$)/.test(arg) && !arg.endsWith("=text"))) {
135
+ return writeFailure(true, stdout, stderr, message);
136
+ }
137
+ stderr.write(`${message}
138
+
139
+ ${HEADLESS_HELP}
140
+ `);
141
+ return 1;
142
+ }
143
+ if (options.help) {
144
+ stdout.write(`${HEADLESS_HELP}
145
+ `);
146
+ return 0;
147
+ }
148
+ let prompt = options.prompt;
149
+ if (!prompt) {
150
+ const canReadStdin = dependencies.readStdin || !process.stdin.isTTY;
151
+ if (canReadStdin) {
152
+ prompt = (await (dependencies.readStdin ?? readStdin)()).trim();
153
+ }
154
+ }
155
+ if (!prompt) {
156
+ return writeFailure(
157
+ options.outputFormat !== "text",
158
+ stdout,
159
+ stderr,
160
+ "Headless mode requires a prompt argument or piped stdin."
161
+ );
162
+ }
163
+ if (options.continueLast) {
164
+ const latest = listStoredSessions(options.cwd)[0];
165
+ if (!latest) {
166
+ return writeFailure(
167
+ options.outputFormat !== "text",
168
+ stdout,
169
+ stderr,
170
+ `No earlier session in ${options.cwd} to continue.`
171
+ );
172
+ }
173
+ options.resume = latest.sessionId;
174
+ }
175
+ if (options.resume) {
176
+ const stored = loadStoredSession(options.resume);
177
+ if (!stored) {
178
+ return writeFailure(
179
+ options.outputFormat !== "text",
180
+ stdout,
181
+ stderr,
182
+ `Session ${options.resume} not found.`
183
+ );
184
+ }
185
+ options.cwd = stored.cwd;
186
+ }
187
+ const output = createOutput(options.outputFormat, stdout, stderr);
188
+ const client = (dependencies.clientFactory ?? ((cwd, permissionMode, emit) => new HeadlessAcpClient(cwd, permissionMode, emit)))(options.cwd, options.permissionMode, output.event);
189
+ const connection = startInProcessAgent(
190
+ () => clientFromContext(client.context()),
191
+ dependencies.agent ?? new NovaAgent()
192
+ );
193
+ const agent = connection.client;
194
+ if (options.trustWorkspace) setWorkspaceTrusted(options.cwd, true);
195
+ const mcpConfiguration = options.mcp ? readWorkspaceMcpConfiguration(options.cwd) : { servers: [], failures: [] };
196
+ for (const failure of mcpConfiguration.failures) {
197
+ output.write({
198
+ type: "mcp.configuration_error",
199
+ serverName: failure.serverName,
200
+ message: failure.message
201
+ });
202
+ }
203
+ let sessionId = null;
204
+ let interrupted = false;
205
+ const onInterrupt = () => {
206
+ interrupted = true;
207
+ if (sessionId) void agent.cancel({ sessionId }).catch(() => {
208
+ });
209
+ };
210
+ if (dependencies.registerSignals !== false)
211
+ process.once("SIGINT", onInterrupt);
212
+ try {
213
+ await agent.initialize({
214
+ protocolVersion: acp.PROTOCOL_VERSION,
215
+ clientCapabilities: client.capabilities,
216
+ clientInfo: { name: "nova-ai-cli-headless", version: "1" }
217
+ });
218
+ if (options.resume) {
219
+ await agent.resumeSession({
220
+ sessionId: options.resume,
221
+ cwd: options.cwd,
222
+ mcpServers: mcpConfiguration.servers
223
+ });
224
+ sessionId = options.resume;
225
+ } else {
226
+ const created = await agent.newSession({
227
+ cwd: options.cwd,
228
+ mcpServers: mcpConfiguration.servers
229
+ });
230
+ sessionId = created.sessionId;
231
+ }
232
+ await agent.setSessionConfigOption({
233
+ sessionId,
234
+ configId: "permission_mode",
235
+ value: AGENT_PERMISSION_MODE[options.permissionMode]
236
+ });
237
+ output.write({
238
+ type: "session.started",
239
+ sessionId,
240
+ cwd: options.cwd,
241
+ model: options.model,
242
+ resumed: Boolean(options.resume),
243
+ permissionMode: options.permissionMode
244
+ });
245
+ output.write({ type: "message", role: "user", text: prompt });
246
+ const response = await agent.prompt({
247
+ sessionId,
248
+ prompt: [{ type: "text", text: prompt }],
249
+ ...options.model ? { _meta: { "nova-ai-cli/model": options.model } } : {}
250
+ });
251
+ const exitCode = interrupted ? 130 : response.stopReason === "max_turn_requests" ? 3 : response.stopReason === "cancelled" ? 2 : 0;
252
+ output.finishText();
253
+ output.write({
254
+ type: "result",
255
+ sessionId,
256
+ stopReason: response.stopReason,
257
+ exitCode
258
+ });
259
+ return exitCode;
260
+ } catch (error) {
261
+ output.finishText();
262
+ output.error(errorMessage(error));
263
+ return 1;
264
+ } finally {
265
+ if (dependencies.registerSignals !== false)
266
+ process.removeListener("SIGINT", onInterrupt);
267
+ if (sessionId) await agent.closeSession({ sessionId }).catch(() => ({}));
268
+ await connection.close().catch(() => {
269
+ });
270
+ await client.close().catch(() => {
271
+ });
272
+ }
273
+ }
274
+ function parseHeadlessArgs(args, defaultCwd) {
275
+ const options = {
276
+ prompt: null,
277
+ cwd: resolve(defaultCwd),
278
+ model: null,
279
+ resume: null,
280
+ continueLast: false,
281
+ outputFormat: "text",
282
+ mcp: true,
283
+ trustWorkspace: false,
284
+ permissionMode: "read-only",
285
+ help: false
286
+ };
287
+ const positional = [];
288
+ for (let index = 0; index < args.length; index++) {
289
+ const arg = args[index];
290
+ if (arg === "--") {
291
+ positional.push(...args.slice(index + 1));
292
+ break;
293
+ }
294
+ if (arg === "--json") options.outputFormat = "stream-json";
295
+ else if (arg === "--continue" || arg === "-c") options.continueLast = true;
296
+ else if (arg === "--output-format")
297
+ options.outputFormat = parseOutputFormat(takeValue(args, ++index, arg));
298
+ else if (arg.startsWith("--output-format="))
299
+ options.outputFormat = parseOutputFormat(arg.slice("--output-format=".length));
300
+ else if (arg === "--print" || arg === "-p") {
301
+ const next = args[index + 1];
302
+ if (next !== void 0 && !next.startsWith("-")) {
303
+ options.prompt = next;
304
+ index++;
305
+ }
306
+ } else if (arg === "--no-mcp") options.mcp = false;
307
+ else if (arg === "--trust-workspace") options.trustWorkspace = true;
308
+ else if (arg === "--help" || arg === "-h") options.help = true;
309
+ else if (arg === "--prompt")
310
+ options.prompt = takeValue(args, ++index, arg);
311
+ else if (arg.startsWith("--prompt="))
312
+ options.prompt = arg.slice("--prompt=".length);
313
+ else if (arg === "--cwd")
314
+ options.cwd = resolve(takeValue(args, ++index, arg));
315
+ else if (arg.startsWith("--cwd="))
316
+ options.cwd = resolve(arg.slice("--cwd=".length));
317
+ else if (arg === "--model") options.model = takeValue(args, ++index, arg);
318
+ else if (arg.startsWith("--model="))
319
+ options.model = arg.slice("--model=".length);
320
+ else if (arg === "--resume") options.resume = takeValue(args, ++index, arg);
321
+ else if (arg.startsWith("--resume="))
322
+ options.resume = arg.slice("--resume=".length);
323
+ else if (arg === "--permission-mode")
324
+ options.permissionMode = parsePermissionMode(
325
+ takeValue(args, ++index, arg)
326
+ );
327
+ else if (arg.startsWith("--permission-mode="))
328
+ options.permissionMode = parsePermissionMode(
329
+ arg.slice("--permission-mode=".length)
330
+ );
331
+ else if (arg.startsWith("-")) throw new Error(`Unknown option: ${arg}`);
332
+ else positional.push(arg);
333
+ }
334
+ if (options.prompt && positional.length) {
335
+ throw new Error(
336
+ "Provide the prompt either with --prompt or positionally, not both."
337
+ );
338
+ }
339
+ if (!options.prompt && positional.length)
340
+ options.prompt = positional.join(" ");
341
+ if (options.continueLast && options.resume) {
342
+ throw new Error("Use either --continue or --resume, not both.");
343
+ }
344
+ if (options.prompt !== null && !options.prompt.trim()) {
345
+ throw new Error("Prompt cannot be empty.");
346
+ }
347
+ return options;
348
+ }
349
+ function createOutput(format, stdout, stderr) {
350
+ let wroteText = false;
351
+ const summary = {
352
+ text: "",
353
+ tools: [],
354
+ permissions: []
355
+ };
356
+ const write = (record) => {
357
+ if (format === "stream-json") {
358
+ stdout.write(`${JSON.stringify({ schemaVersion: 1, ...record })}
359
+ `);
360
+ return;
361
+ }
362
+ if (format !== "json") return;
363
+ if (record.type === "result") {
364
+ stdout.write(
365
+ `${JSON.stringify({ schemaVersion: 1, ...record, text: summary.text, tools: summary.tools, permissions: summary.permissions })}
366
+ `
367
+ );
368
+ } else if (record.type === "error") {
369
+ stdout.write(`${JSON.stringify({ schemaVersion: 1, ...record })}
370
+ `);
371
+ } else if (record.type === "message.delta" && record.role === "assistant") {
372
+ summary.text += String(record.text ?? "");
373
+ } else if (record.type === "tool.finished") {
374
+ summary.tools.push({ toolCallId: record.toolCallId, status: record.status });
375
+ } else if (record.type === "permission") {
376
+ summary.permissions.push(record);
377
+ }
378
+ };
379
+ return {
380
+ write,
381
+ event: async (event) => {
382
+ if (event.type === "permission") {
383
+ write(event);
384
+ return;
385
+ }
386
+ const record = notificationRecord(event.method, event.params);
387
+ if (record) write(record);
388
+ if (format === "text" && record?.type === "message.delta" && record.role === "assistant") {
389
+ stdout.write(String(record.text ?? ""));
390
+ wroteText = true;
391
+ }
392
+ },
393
+ finishText: () => {
394
+ if (format === "text" && wroteText) {
395
+ stdout.write("\n");
396
+ wroteText = false;
397
+ }
398
+ },
399
+ error: (message) => {
400
+ if (format === "text") stderr.write(`${message}
401
+ `);
402
+ else write({ type: "error", message });
403
+ }
404
+ };
405
+ }
406
+ function notificationRecord(method, params) {
407
+ if (method === NOVA_NOTIFICATIONS.backgroundUpdate) {
408
+ return { type: "background.update", ...toRecord(params) ?? {} };
409
+ }
410
+ if (method === NOVA_NOTIFICATIONS.queueChanged) {
411
+ return { type: "queue.changed", ...toRecord(params) ?? {} };
412
+ }
413
+ if (method !== "session/update") {
414
+ return { type: "acp.notification", method, params };
415
+ }
416
+ const root = toRecord(params);
417
+ const update = toRecord(root?.update);
418
+ const sessionId = root?.sessionId;
419
+ switch (update?.sessionUpdate) {
420
+ case "agent_message_chunk":
421
+ return {
422
+ type: "message.delta",
423
+ sessionId,
424
+ role: "assistant",
425
+ text: textContent(update.content)
426
+ };
427
+ case "user_message_chunk":
428
+ return {
429
+ type: "message.delta",
430
+ sessionId,
431
+ role: "user",
432
+ text: textContent(update.content)
433
+ };
434
+ case "agent_thought_chunk":
435
+ return {
436
+ type: "thought",
437
+ sessionId,
438
+ text: textContent(update.content)
439
+ };
440
+ case "tool_call": {
441
+ const toolName = toRecord(update._meta)?.["nova-ai-cli/tool"];
442
+ return {
443
+ type: "tool.started",
444
+ sessionId,
445
+ toolCallId: update.toolCallId,
446
+ name: typeof toolName === "string" ? toolName : update.title,
447
+ title: update.title,
448
+ kind: update.kind,
449
+ input: update.rawInput
450
+ };
451
+ }
452
+ case "tool_call_update":
453
+ return {
454
+ type: update.status === "completed" || update.status === "failed" ? "tool.finished" : "tool.updated",
455
+ sessionId,
456
+ toolCallId: update.toolCallId,
457
+ status: update.status,
458
+ output: toRecord(update.rawOutput)?.output,
459
+ content: update.content
460
+ };
461
+ case "current_mode_update":
462
+ return {
463
+ type: "mode.changed",
464
+ sessionId,
465
+ mode: update.currentModeId
466
+ };
467
+ default:
468
+ return null;
469
+ }
470
+ }
471
+ function textContent(value) {
472
+ const content = toRecord(value);
473
+ return content?.type === "text" && typeof content.text === "string" ? content.text : "";
474
+ }
475
+ function toRecord(value) {
476
+ return value && typeof value === "object" && !Array.isArray(value) ? value : null;
477
+ }
478
+ function parseOutputFormat(value) {
479
+ if (value === "text" || value === "json" || value === "stream-json") return value;
480
+ throw new Error(`Unknown output format: ${value}. Expected text, json, or stream-json.`);
481
+ }
482
+ function parsePermissionMode(value) {
483
+ if (value === "read-only" || value === "accept-edits" || value === "bypass-all") {
484
+ return value;
485
+ }
486
+ throw new Error(
487
+ `Unknown permission mode: ${value}. Expected read-only, accept-edits, or bypass-all.`
488
+ );
489
+ }
490
+ function takeValue(args, index, option) {
491
+ const value = args[index];
492
+ if (!value || value.startsWith("--")) {
493
+ throw new Error(`${option} requires a value.`);
494
+ }
495
+ return value;
496
+ }
497
+ async function readStdin() {
498
+ const chunks = [];
499
+ for await (const chunk of process.stdin) chunks.push(Buffer.from(chunk));
500
+ return Buffer.concat(chunks).toString("utf8");
501
+ }
502
+ function writeFailure(json, stdout, stderr, message) {
503
+ if (json)
504
+ stdout.write(
505
+ `${JSON.stringify({ schemaVersion: 1, type: "error", message })}
506
+ `
507
+ );
508
+ else stderr.write(`${message}
509
+ `);
510
+ return 1;
511
+ }
512
+ function errorMessage(error) {
513
+ return error instanceof Error ? error.message : String(error);
514
+ }
515
+ var HEADLESS_HELP = `Usage: nova-ai -p [options] [prompt]
516
+
517
+ Run one Nova agent request without the interactive terminal UI. The prompt
518
+ can also be piped on stdin.
519
+
520
+ Options:
521
+ -p, --print [prompt] Run headless (the prompt may follow)
522
+ --output-format <format> text (default), json (one object at the end)
523
+ or stream-json (JSON Lines while it runs)
524
+ --json Same as --output-format stream-json
525
+ --cwd <path> Workspace directory (default: current directory)
526
+ --model <id> Override the configured model
527
+ --resume <session-id> Continue a persisted session
528
+ -c, --continue Continue the most recent session of the workspace
529
+ --no-mcp Ignore workspace MCP configuration
530
+ --trust-workspace Trust this workspace (remembered): start the MCP
531
+ servers and apply the allow rules it declares
532
+ --permission-mode <mode> read-only (default), accept-edits, or bypass-all
533
+ -h, --help Show this help
534
+
535
+ Exit codes: 0 success, 1 configuration/runtime error, 2 cancelled,
536
+ 3 tool-turn safety limit, 130 interrupted.`;
537
+ var headless_default = runHeadless;
538
+ export {
539
+ HEADLESS_HELP,
540
+ headless_default as default,
541
+ parseHeadlessArgs,
542
+ runHeadless
543
+ };