acpx 0.3.1 → 0.4.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 +65 -16
- package/dist/{acp-jsonrpc-BNHXq7qK.js → acp-jsonrpc-BbBgC5gO.js} +15 -2
- package/dist/acp-jsonrpc-BbBgC5gO.js.map +1 -0
- package/dist/cli-idpWyCOs.js +176 -0
- package/dist/cli-idpWyCOs.js.map +1 -0
- package/dist/cli.d.ts +1 -118
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +235 -336
- package/dist/cli.js.map +1 -1
- package/dist/flags-CCcX9fZj.js +194 -0
- package/dist/flags-CCcX9fZj.js.map +1 -0
- package/dist/flows-BL1tSvZT.js +1551 -0
- package/dist/flows-BL1tSvZT.js.map +1 -0
- package/dist/flows.d.ts +292 -0
- package/dist/flows.d.ts.map +1 -0
- package/dist/flows.js +2 -0
- package/dist/{output-BmkPP7qE.js → output-Du3m6oPQ.js} +139 -30
- package/dist/output-Du3m6oPQ.js.map +1 -0
- package/dist/{output-render-DEAaMxg8.js → output-render-Bz58qaQn.js} +10 -10
- package/dist/output-render-Bz58qaQn.js.map +1 -0
- package/dist/{queue-ipc-EQLpBMKv.js → queue-ipc-CE8_QGX3.js} +258 -95
- package/dist/queue-ipc-CE8_QGX3.js.map +1 -0
- package/dist/{session-C2Q8ktsN.js → session-RO_LZUnv.js} +687 -138
- package/dist/session-RO_LZUnv.js.map +1 -0
- package/dist/types-CeRKmEQ1.d.ts +137 -0
- package/dist/types-CeRKmEQ1.d.ts.map +1 -0
- package/package.json +44 -16
- package/skills/acpx/SKILL.md +22 -5
- package/dist/acp-jsonrpc-BNHXq7qK.js.map +0 -1
- package/dist/output-BmkPP7qE.js.map +0 -1
- package/dist/output-render-DEAaMxg8.js.map +0 -1
- package/dist/queue-ipc-EQLpBMKv.js.map +0 -1
- package/dist/runtime-session-id-C544sPPL.js +0 -31
- package/dist/runtime-session-id-C544sPPL.js.map +0 -1
- package/dist/session-C2Q8ktsN.js.map +0 -1
package/README.md
CHANGED
|
@@ -39,6 +39,9 @@ One command surface for Pi, OpenClaw ACP, Codex, Claude, and other ACP-compatibl
|
|
|
39
39
|
- **Structured output**: typed ACP messages (thinking, tool calls, diffs) instead of ANSI scraping
|
|
40
40
|
- **Any ACP agent**: built-in registry + `--agent` escape hatch for custom servers
|
|
41
41
|
- **One-shot mode**: `exec` for stateless fire-and-forget tasks
|
|
42
|
+
- **Experimental flows**: `flow run <file>` for TypeScript workflow modules over multiple prompts
|
|
43
|
+
- **Runtime-owned flow actions**: shell-backed action steps can prepare workspaces and other deterministic mechanics outside the agent turn
|
|
44
|
+
- **Flow workspace isolation**: `acp` nodes can target an explicit per-step cwd, so flows can keep agent work inside disposable worktrees
|
|
42
45
|
|
|
43
46
|
```bash
|
|
44
47
|
$ acpx codex sessions new
|
|
@@ -204,13 +207,49 @@ acpx --cwd ~/repos/backend codex 'review recent auth changes'
|
|
|
204
207
|
acpx --format text codex 'summarize your findings'
|
|
205
208
|
acpx --format json codex exec 'review changed files'
|
|
206
209
|
acpx --format json --json-strict codex exec 'machine-safe JSON only'
|
|
210
|
+
acpx flow run ./my-flow.ts --input-file ./flow-input.json
|
|
211
|
+
acpx --timeout 1800 flow run ./my-flow.ts
|
|
207
212
|
acpx --format quiet codex 'final recommendation only'
|
|
213
|
+
acpx --suppress-reads codex exec 'show tool activity without dumping file bodies'
|
|
208
214
|
|
|
209
215
|
acpx --timeout 90 codex 'investigate intermittent test timeout'
|
|
210
216
|
acpx --ttl 30 codex 'keep queue owner alive for quick follow-ups'
|
|
211
217
|
acpx --verbose codex 'debug why adapter startup is failing'
|
|
212
218
|
```
|
|
213
219
|
|
|
220
|
+
## Flows
|
|
221
|
+
|
|
222
|
+
`acpx flow run <file>` executes a TypeScript flow module through the `acpx/flows`
|
|
223
|
+
runtime and persists run state under `~/.acpx/flows/runs/`.
|
|
224
|
+
|
|
225
|
+
Flows are for multi-step ACP work where one prompt is not enough:
|
|
226
|
+
|
|
227
|
+
- `acp` steps keep model-shaped work in ACP
|
|
228
|
+
- `action` steps handle deterministic mechanics like shell commands or GitHub calls
|
|
229
|
+
- `compute` steps do local routing or shaping
|
|
230
|
+
- `checkpoint` steps pause for something outside the runtime
|
|
231
|
+
|
|
232
|
+
The source tree includes flow examples under [examples/flows/README.md](examples/flows/README.md):
|
|
233
|
+
|
|
234
|
+
- small examples such as `echo`, `branch`, `shell`, `workdir`, and `two-turn`
|
|
235
|
+
- a larger PR-triage example under [examples/flows/pr-triage/README.md](examples/flows/pr-triage/README.md)
|
|
236
|
+
- a replay viewer under [examples/flows/replay-viewer/README.md](examples/flows/replay-viewer/README.md) for inspecting saved run bundles in the browser
|
|
237
|
+
|
|
238
|
+
Example runs:
|
|
239
|
+
|
|
240
|
+
```bash
|
|
241
|
+
acpx flow run ./my-flow.ts --input-file ./flow-input.json
|
|
242
|
+
|
|
243
|
+
acpx flow run examples/flows/branch.flow.ts \
|
|
244
|
+
--input-json '{"task":"FIX: add a regression test for the reconnect bug"}'
|
|
245
|
+
|
|
246
|
+
acpx flow run examples/flows/pr-triage/pr-triage.flow.ts \
|
|
247
|
+
--input-json '{"repo":"openclaw/acpx","prNumber":150}'
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
The PR-triage example is only an example workflow. It can comment on or close
|
|
251
|
+
real GitHub PRs if you run it against a live repository.
|
|
252
|
+
|
|
214
253
|
## Configuration files
|
|
215
254
|
|
|
216
255
|
`acpx` reads config in this order (later wins):
|
|
@@ -257,8 +296,16 @@ acpx --format json --json-strict codex exec 'review this PR'
|
|
|
257
296
|
|
|
258
297
|
# quiet: final assistant text only
|
|
259
298
|
acpx --format quiet codex 'give me a 3-line summary'
|
|
299
|
+
|
|
300
|
+
# suppress read payloads while keeping the selected output format
|
|
301
|
+
acpx --suppress-reads codex exec 'inspect the repo and report tool usage'
|
|
260
302
|
```
|
|
261
303
|
|
|
304
|
+
- `text`: human-readable stream with assistant text and tool updates
|
|
305
|
+
- `json`: raw ACP NDJSON stream for automation
|
|
306
|
+
- `quiet`: final assistant text only
|
|
307
|
+
- `--suppress-reads`: replace raw read-file contents with `[read output suppressed]` in `text` and `json` output
|
|
308
|
+
|
|
262
309
|
JSON events include a stable envelope for correlation:
|
|
263
310
|
|
|
264
311
|
```json
|
|
@@ -279,22 +326,24 @@ Session-control JSON payloads (`sessions new|ensure`, `status`) may also include
|
|
|
279
326
|
|
|
280
327
|
Built-ins:
|
|
281
328
|
|
|
282
|
-
| Agent | Adapter
|
|
283
|
-
| ---------- |
|
|
284
|
-
| `pi` | [pi-acp](https://github.com/svkozak/pi-acp)
|
|
285
|
-
| `openclaw` | native (`openclaw acp`)
|
|
286
|
-
| `codex` | [codex-acp](https://github.com/zed-industries/codex-acp)
|
|
287
|
-
| `claude` | [claude-agent-acp](https://github.com/
|
|
288
|
-
| `gemini` | native (`gemini --acp`)
|
|
289
|
-
| `cursor` | native (`cursor-agent acp`)
|
|
290
|
-
| `copilot` | native (`copilot --acp --stdio`)
|
|
291
|
-
| `droid` | native (`droid exec --output-format acp`)
|
|
292
|
-
| `iflow` | native (`iflow --experimental-acp`)
|
|
293
|
-
| `kilocode` | `npx -y @kilocode/cli acp`
|
|
294
|
-
| `kimi` | native (`kimi acp`)
|
|
295
|
-
| `kiro` | native (`kiro-cli acp`) | [Kiro CLI](https://kiro.dev) |
|
|
296
|
-
| `opencode` | `npx -y opencode-ai acp`
|
|
297
|
-
| `
|
|
329
|
+
| Agent | Adapter | Wraps |
|
|
330
|
+
| ---------- | --------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------- |
|
|
331
|
+
| `pi` | [pi-acp](https://github.com/svkozak/pi-acp) | [Pi Coding Agent](https://github.com/mariozechner/pi) |
|
|
332
|
+
| `openclaw` | native (`openclaw acp`) | [OpenClaw ACP bridge](https://github.com/openclaw/openclaw) |
|
|
333
|
+
| `codex` | [codex-acp](https://github.com/zed-industries/codex-acp) | [Codex CLI](https://codex.openai.com) |
|
|
334
|
+
| `claude` | [claude-agent-acp](https://github.com/agentclientprotocol/claude-agent-acp) | [Claude Code](https://claude.ai/code) |
|
|
335
|
+
| `gemini` | native (`gemini --acp`) | [Gemini CLI](https://github.com/google/gemini-cli) |
|
|
336
|
+
| `cursor` | native (`cursor-agent acp`) | [Cursor CLI](https://cursor.com/docs/cli/acp) |
|
|
337
|
+
| `copilot` | native (`copilot --acp --stdio`) | [GitHub Copilot CLI](https://docs.github.com/copilot/how-tos/copilot-chat/use-copilot-chat-in-the-command-line) |
|
|
338
|
+
| `droid` | native (`droid exec --output-format acp`) | [Factory Droid](https://www.factory.ai) |
|
|
339
|
+
| `iflow` | native (`iflow --experimental-acp`) | [iFlow CLI](https://github.com/iflow-ai/iflow-cli) |
|
|
340
|
+
| `kilocode` | `npx -y @kilocode/cli acp` | [Kilocode](https://kilocode.ai) |
|
|
341
|
+
| `kimi` | native (`kimi acp`) | [Kimi CLI](https://github.com/MoonshotAI/kimi-cli) |
|
|
342
|
+
| `kiro` | native (`kiro-cli-chat acp`) | [Kiro CLI](https://kiro.dev) |
|
|
343
|
+
| `opencode` | `npx -y opencode-ai acp` | [OpenCode](https://opencode.ai) |
|
|
344
|
+
| `qoder` | native (`qodercli --acp`) | [Qoder CLI](https://docs.qoder.com/cli/acp) |
|
|
345
|
+
| `qwen` | native (`qwen --acp`) | [Qwen Code](https://github.com/QwenLM/qwen-code) |
|
|
346
|
+
| `trae` | native (`traecli acp serve`) | [Trae CLI](https://docs.trae.cn/cli) |
|
|
298
347
|
|
|
299
348
|
`factory-droid` and `factorydroid` also resolve to the built-in `droid` adapter.
|
|
300
349
|
|
|
@@ -37,6 +37,19 @@ function isJsonRpcNotification(message) {
|
|
|
37
37
|
function isSessionUpdateNotification(message) {
|
|
38
38
|
return isJsonRpcNotification(message) && message.method === "session/update";
|
|
39
39
|
}
|
|
40
|
+
function extractSessionUpdateNotification(message) {
|
|
41
|
+
if (!isSessionUpdateNotification(message)) return;
|
|
42
|
+
const params = asRecord(message.params);
|
|
43
|
+
if (!params) return;
|
|
44
|
+
const sessionId = typeof params.sessionId === "string" ? params.sessionId : null;
|
|
45
|
+
if (!sessionId) return;
|
|
46
|
+
const update = asRecord(params.update);
|
|
47
|
+
if (!update || typeof update.sessionUpdate !== "string") return;
|
|
48
|
+
return {
|
|
49
|
+
sessionId,
|
|
50
|
+
update
|
|
51
|
+
};
|
|
52
|
+
}
|
|
40
53
|
function parsePromptStopReason(message) {
|
|
41
54
|
if (!Object.hasOwn(message, "id") || !Object.hasOwn(message, "result")) return;
|
|
42
55
|
const record = asRecord(message.result);
|
|
@@ -50,6 +63,6 @@ function parseJsonRpcErrorMessage(message) {
|
|
|
50
63
|
return errorRecord.message;
|
|
51
64
|
}
|
|
52
65
|
//#endregion
|
|
53
|
-
export { parsePromptStopReason as i,
|
|
66
|
+
export { parsePromptStopReason as a, parseJsonRpcErrorMessage as i, isAcpJsonRpcMessage as n, isSessionUpdateNotification as r, extractSessionUpdateNotification as t };
|
|
54
67
|
|
|
55
|
-
//# sourceMappingURL=acp-jsonrpc-
|
|
68
|
+
//# sourceMappingURL=acp-jsonrpc-BbBgC5gO.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"acp-jsonrpc-BbBgC5gO.js","names":[],"sources":["../src/acp-jsonrpc.ts"],"sourcesContent":["import type { AnyMessage, SessionNotification } from \"@agentclientprotocol/sdk\";\n\ntype JsonRpcId = string | number | null;\n\nfunction asRecord(value: unknown): Record<string, unknown> | null {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) {\n return null;\n }\n return value as Record<string, unknown>;\n}\n\nfunction hasValidId(value: unknown): value is JsonRpcId {\n return (\n value === null ||\n typeof value === \"string\" ||\n (typeof value === \"number\" && Number.isFinite(value))\n );\n}\n\nfunction isErrorObject(value: unknown): value is { code: number; message: string } {\n const record = asRecord(value);\n return (\n !!record &&\n typeof record.code === \"number\" &&\n Number.isFinite(record.code) &&\n typeof record.message === \"string\"\n );\n}\n\nfunction hasResultOrError(value: Record<string, unknown>): boolean {\n const hasResult = Object.hasOwn(value, \"result\");\n const hasError = Object.hasOwn(value, \"error\");\n if (hasResult && hasError) {\n return false;\n }\n if (!hasResult && !hasError) {\n return false;\n }\n if (hasError && !isErrorObject(value.error)) {\n return false;\n }\n return true;\n}\n\nexport function isAcpJsonRpcMessage(value: unknown): value is AnyMessage {\n const record = asRecord(value);\n if (!record || record.jsonrpc !== \"2.0\") {\n return false;\n }\n\n const hasMethod = typeof record.method === \"string\" && record.method.length > 0;\n const hasId = Object.hasOwn(record, \"id\");\n\n if (hasMethod && !hasId) {\n // Notification\n return true;\n }\n\n if (hasMethod && hasId) {\n // Request\n return hasValidId(record.id);\n }\n\n if (!hasMethod && hasId) {\n // Response\n if (!hasValidId(record.id)) {\n return false;\n }\n return hasResultOrError(record);\n }\n\n return false;\n}\n\nexport function isJsonRpcNotification(message: AnyMessage): boolean {\n return (\n Object.hasOwn(message, \"method\") &&\n typeof (message as { method?: unknown }).method === \"string\" &&\n !Object.hasOwn(message, \"id\")\n );\n}\n\nexport function isSessionUpdateNotification(message: AnyMessage): boolean {\n return (\n isJsonRpcNotification(message) && (message as { method?: unknown }).method === \"session/update\"\n );\n}\n\nexport function extractSessionUpdateNotification(\n message: AnyMessage,\n): SessionNotification | undefined {\n if (!isSessionUpdateNotification(message)) {\n return undefined;\n }\n\n const params = asRecord((message as { params?: unknown }).params);\n if (!params) {\n return undefined;\n }\n\n const sessionId = typeof params.sessionId === \"string\" ? params.sessionId : null;\n if (!sessionId) {\n return undefined;\n }\n\n const update = asRecord(params.update);\n if (!update || typeof update.sessionUpdate !== \"string\") {\n return undefined;\n }\n\n return {\n sessionId,\n update: update as SessionNotification[\"update\"],\n };\n}\n\nexport function parsePromptStopReason(message: AnyMessage): string | undefined {\n if (!Object.hasOwn(message, \"id\") || !Object.hasOwn(message, \"result\")) {\n return undefined;\n }\n const record = asRecord((message as { result?: unknown }).result);\n if (!record) {\n return undefined;\n }\n return typeof record.stopReason === \"string\" ? record.stopReason : undefined;\n}\n\nexport function parseJsonRpcErrorMessage(message: AnyMessage): string | undefined {\n if (!Object.hasOwn(message, \"error\")) {\n return undefined;\n }\n const errorRecord = asRecord((message as { error?: unknown }).error);\n if (!errorRecord || typeof errorRecord.message !== \"string\") {\n return undefined;\n }\n return errorRecord.message;\n}\n"],"mappings":";AAIA,SAAS,SAAS,OAAgD;AAChE,KAAI,CAAC,SAAS,OAAO,UAAU,YAAY,MAAM,QAAQ,MAAM,CAC7D,QAAO;AAET,QAAO;;AAGT,SAAS,WAAW,OAAoC;AACtD,QACE,UAAU,QACV,OAAO,UAAU,YAChB,OAAO,UAAU,YAAY,OAAO,SAAS,MAAM;;AAIxD,SAAS,cAAc,OAA4D;CACjF,MAAM,SAAS,SAAS,MAAM;AAC9B,QACE,CAAC,CAAC,UACF,OAAO,OAAO,SAAS,YACvB,OAAO,SAAS,OAAO,KAAK,IAC5B,OAAO,OAAO,YAAY;;AAI9B,SAAS,iBAAiB,OAAyC;CACjE,MAAM,YAAY,OAAO,OAAO,OAAO,SAAS;CAChD,MAAM,WAAW,OAAO,OAAO,OAAO,QAAQ;AAC9C,KAAI,aAAa,SACf,QAAO;AAET,KAAI,CAAC,aAAa,CAAC,SACjB,QAAO;AAET,KAAI,YAAY,CAAC,cAAc,MAAM,MAAM,CACzC,QAAO;AAET,QAAO;;AAGT,SAAgB,oBAAoB,OAAqC;CACvE,MAAM,SAAS,SAAS,MAAM;AAC9B,KAAI,CAAC,UAAU,OAAO,YAAY,MAChC,QAAO;CAGT,MAAM,YAAY,OAAO,OAAO,WAAW,YAAY,OAAO,OAAO,SAAS;CAC9E,MAAM,QAAQ,OAAO,OAAO,QAAQ,KAAK;AAEzC,KAAI,aAAa,CAAC,MAEhB,QAAO;AAGT,KAAI,aAAa,MAEf,QAAO,WAAW,OAAO,GAAG;AAG9B,KAAI,CAAC,aAAa,OAAO;AAEvB,MAAI,CAAC,WAAW,OAAO,GAAG,CACxB,QAAO;AAET,SAAO,iBAAiB,OAAO;;AAGjC,QAAO;;AAGT,SAAgB,sBAAsB,SAA8B;AAClE,QACE,OAAO,OAAO,SAAS,SAAS,IAChC,OAAQ,QAAiC,WAAW,YACpD,CAAC,OAAO,OAAO,SAAS,KAAK;;AAIjC,SAAgB,4BAA4B,SAA8B;AACxE,QACE,sBAAsB,QAAQ,IAAK,QAAiC,WAAW;;AAInF,SAAgB,iCACd,SACiC;AACjC,KAAI,CAAC,4BAA4B,QAAQ,CACvC;CAGF,MAAM,SAAS,SAAU,QAAiC,OAAO;AACjE,KAAI,CAAC,OACH;CAGF,MAAM,YAAY,OAAO,OAAO,cAAc,WAAW,OAAO,YAAY;AAC5E,KAAI,CAAC,UACH;CAGF,MAAM,SAAS,SAAS,OAAO,OAAO;AACtC,KAAI,CAAC,UAAU,OAAO,OAAO,kBAAkB,SAC7C;AAGF,QAAO;EACL;EACQ;EACT;;AAGH,SAAgB,sBAAsB,SAAyC;AAC7E,KAAI,CAAC,OAAO,OAAO,SAAS,KAAK,IAAI,CAAC,OAAO,OAAO,SAAS,SAAS,CACpE;CAEF,MAAM,SAAS,SAAU,QAAiC,OAAO;AACjE,KAAI,CAAC,OACH;AAEF,QAAO,OAAO,OAAO,eAAe,WAAW,OAAO,aAAa,KAAA;;AAGrE,SAAgB,yBAAyB,SAAyC;AAChF,KAAI,CAAC,OAAO,OAAO,SAAS,QAAQ,CAClC;CAEF,MAAM,cAAc,SAAU,QAAgC,MAAM;AACpE,KAAI,CAAC,eAAe,OAAO,YAAY,YAAY,SACjD;AAEF,QAAO,YAAY"}
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
import { a as hasExplicitPermissionModeFlag, f as resolveAgentInvocation, h as resolvePermissionMode, m as resolveOutputPolicy, p as resolveGlobalFlags } from "./flags-CCcX9fZj.js";
|
|
2
|
+
import { E as permissionModeSatisfies } from "./session-RO_LZUnv.js";
|
|
3
|
+
import { i as FlowRunner } from "./flows-BL1tSvZT.js";
|
|
4
|
+
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
5
|
+
import fs from "node:fs/promises";
|
|
6
|
+
import path from "node:path";
|
|
7
|
+
import { InvalidArgumentError } from "commander";
|
|
8
|
+
import { randomUUID } from "node:crypto";
|
|
9
|
+
//#region src/flows/cli.ts
|
|
10
|
+
const FLOW_RUNTIME_SPECIFIER = "acpx/flows";
|
|
11
|
+
const TEXT_MODULE_EXTENSIONS = new Set([
|
|
12
|
+
".js",
|
|
13
|
+
".mjs",
|
|
14
|
+
".cjs",
|
|
15
|
+
".ts",
|
|
16
|
+
".tsx",
|
|
17
|
+
".mts",
|
|
18
|
+
".cts"
|
|
19
|
+
]);
|
|
20
|
+
async function handleFlowRun(flowFile, flags, command, config) {
|
|
21
|
+
const globalFlags = resolveGlobalFlags(command, config);
|
|
22
|
+
const permissionMode = resolvePermissionMode(globalFlags, config.defaultPermissions);
|
|
23
|
+
const outputPolicy = resolveOutputPolicy(globalFlags.format, globalFlags.jsonStrict === true);
|
|
24
|
+
const input = await readFlowInput(flags);
|
|
25
|
+
const flowPath = path.resolve(flowFile);
|
|
26
|
+
const flow = await loadFlowModule(flowPath);
|
|
27
|
+
assertFlowPermissionRequirements(flow, permissionMode, globalFlags);
|
|
28
|
+
printFlowRunResult(await new FlowRunner({
|
|
29
|
+
resolveAgent: (profile) => {
|
|
30
|
+
return resolveAgentInvocation(profile ?? flags.defaultAgent, globalFlags, config);
|
|
31
|
+
},
|
|
32
|
+
permissionMode,
|
|
33
|
+
mcpServers: config.mcpServers,
|
|
34
|
+
nonInteractivePermissions: globalFlags.nonInteractivePermissions,
|
|
35
|
+
authCredentials: config.auth,
|
|
36
|
+
authPolicy: globalFlags.authPolicy,
|
|
37
|
+
timeoutMs: globalFlags.timeout,
|
|
38
|
+
ttlMs: globalFlags.ttl,
|
|
39
|
+
verbose: globalFlags.verbose,
|
|
40
|
+
suppressSdkConsoleErrors: outputPolicy.suppressSdkConsoleErrors,
|
|
41
|
+
sessionOptions: {
|
|
42
|
+
model: globalFlags.model,
|
|
43
|
+
allowedTools: globalFlags.allowedTools,
|
|
44
|
+
maxTurns: globalFlags.maxTurns
|
|
45
|
+
}
|
|
46
|
+
}).run(flow, input, { flowPath }), globalFlags);
|
|
47
|
+
}
|
|
48
|
+
function assertFlowPermissionRequirements(flow, permissionMode, globalFlags) {
|
|
49
|
+
const permissions = flow.permissions;
|
|
50
|
+
if (!permissions) return;
|
|
51
|
+
if (permissions.requireExplicitGrant && !hasExplicitPermissionModeFlag(globalFlags)) throw new InvalidArgumentError(buildFlowPermissionFailureMessage(flow, permissions.requiredMode, permissions.reason, true));
|
|
52
|
+
if (!permissionModeSatisfies(permissionMode, permissions.requiredMode)) throw new InvalidArgumentError(buildFlowPermissionFailureMessage(flow, permissions.requiredMode, permissions.reason, false));
|
|
53
|
+
}
|
|
54
|
+
function buildFlowPermissionFailureMessage(flow, requiredMode, reason, explicit = false) {
|
|
55
|
+
return [
|
|
56
|
+
explicit ? `Flow "${flow.name}" requires an explicit ${requiredMode} grant.` : `Flow "${flow.name}" requires permission mode ${requiredMode}.`,
|
|
57
|
+
`Rerun with --${requiredMode}.`,
|
|
58
|
+
...reason ? [`Reason: ${reason}`] : []
|
|
59
|
+
].join(" ");
|
|
60
|
+
}
|
|
61
|
+
async function readFlowInput(flags) {
|
|
62
|
+
if (flags.inputJson && flags.inputFile) throw new InvalidArgumentError("Use only one of --input-json or --input-file");
|
|
63
|
+
if (flags.inputJson) return parseJsonInput(flags.inputJson, "--input-json");
|
|
64
|
+
if (flags.inputFile) {
|
|
65
|
+
const inputPath = path.resolve(flags.inputFile);
|
|
66
|
+
return parseJsonInput(await fs.readFile(inputPath, "utf8"), "--input-file");
|
|
67
|
+
}
|
|
68
|
+
return {};
|
|
69
|
+
}
|
|
70
|
+
async function loadFlowModule(flowPath) {
|
|
71
|
+
const extension = path.extname(flowPath).toLowerCase();
|
|
72
|
+
const prepared = await prepareFlowModuleImport(flowPath, extension);
|
|
73
|
+
try {
|
|
74
|
+
const candidate = findFlowDefinition(await loadFlowRuntimeModule(prepared.flowUrl, extension));
|
|
75
|
+
if (!candidate) throw new Error(`Flow module must export a flow object: ${flowPath}`);
|
|
76
|
+
return candidate;
|
|
77
|
+
} finally {
|
|
78
|
+
await prepared.cleanup?.();
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
async function prepareFlowModuleImport(flowPath, extension) {
|
|
82
|
+
const flowUrl = pathToFileURL(flowPath).href;
|
|
83
|
+
if (!TEXT_MODULE_EXTENSIONS.has(extension)) return { flowUrl };
|
|
84
|
+
const source = await fs.readFile(flowPath, "utf8");
|
|
85
|
+
if (!source.includes(FLOW_RUNTIME_SPECIFIER)) return { flowUrl };
|
|
86
|
+
const runtimeSpecifier = resolveFlowRuntimeImportSpecifier();
|
|
87
|
+
const rewritten = source.replaceAll(/(["'])acpx\/flows\1/g, (_match, quote) => `${quote}${runtimeSpecifier}${quote}`);
|
|
88
|
+
if (rewritten === source) return { flowUrl };
|
|
89
|
+
const tempPath = path.join(path.dirname(flowPath), `.acpx-flow-load-${randomUUID()}${extension}`);
|
|
90
|
+
await fs.writeFile(tempPath, rewritten, "utf8");
|
|
91
|
+
return {
|
|
92
|
+
flowUrl: pathToFileURL(tempPath).href,
|
|
93
|
+
cleanup: async () => {
|
|
94
|
+
await fs.rm(tempPath, { force: true });
|
|
95
|
+
}
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
function resolveFlowRuntimeImportSpecifier() {
|
|
99
|
+
const selfPath = fileURLToPath(import.meta.url);
|
|
100
|
+
if (selfPath.endsWith(`${path.sep}src${path.sep}flows${path.sep}cli.ts`)) return new URL("../flows.ts", import.meta.url).href;
|
|
101
|
+
if (selfPath.endsWith(`${path.sep}src${path.sep}flows${path.sep}cli.js`)) return new URL("../flows.js", import.meta.url).href;
|
|
102
|
+
return new URL("./flows.js", import.meta.url).href;
|
|
103
|
+
}
|
|
104
|
+
async function loadFlowRuntimeModule(flowUrl, extension) {
|
|
105
|
+
if (extension === ".ts" || extension === ".tsx" || extension === ".mts" || extension === ".cts") {
|
|
106
|
+
const { tsImport } = await import("tsx/esm/api");
|
|
107
|
+
return await tsImport(flowUrl, import.meta.url);
|
|
108
|
+
}
|
|
109
|
+
return await import(flowUrl);
|
|
110
|
+
}
|
|
111
|
+
function findFlowDefinition(module) {
|
|
112
|
+
const candidates = [
|
|
113
|
+
module.default,
|
|
114
|
+
module["module.exports"],
|
|
115
|
+
getNestedDefault(module.default),
|
|
116
|
+
getNestedDefault(module["module.exports"])
|
|
117
|
+
];
|
|
118
|
+
for (const candidate of candidates) if (isFlowDefinition(candidate)) return candidate;
|
|
119
|
+
return null;
|
|
120
|
+
}
|
|
121
|
+
function getNestedDefault(value) {
|
|
122
|
+
if (!value || typeof value !== "object" || !("default" in value)) return null;
|
|
123
|
+
return value.default ?? null;
|
|
124
|
+
}
|
|
125
|
+
function isFlowDefinition(value) {
|
|
126
|
+
if (!value || typeof value !== "object") return false;
|
|
127
|
+
const candidate = value;
|
|
128
|
+
return typeof candidate.name === "string" && typeof candidate.startAt === "string" && candidate.nodes !== void 0 && typeof candidate.nodes === "object" && Array.isArray(candidate.edges);
|
|
129
|
+
}
|
|
130
|
+
function parseJsonInput(raw, label) {
|
|
131
|
+
try {
|
|
132
|
+
return JSON.parse(raw);
|
|
133
|
+
} catch (error) {
|
|
134
|
+
throw new InvalidArgumentError(`${label} must contain valid JSON: ${error instanceof Error ? error.message : String(error)}`);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
function printFlowRunResult(result, globalFlags) {
|
|
138
|
+
const payload = {
|
|
139
|
+
action: "flow_run_result",
|
|
140
|
+
runId: result.state.runId,
|
|
141
|
+
flowName: result.state.flowName,
|
|
142
|
+
runTitle: result.state.runTitle,
|
|
143
|
+
flowPath: result.state.flowPath,
|
|
144
|
+
status: result.state.status,
|
|
145
|
+
currentNode: result.state.currentNode,
|
|
146
|
+
currentNodeType: result.state.currentNodeType,
|
|
147
|
+
currentNodeStartedAt: result.state.currentNodeStartedAt,
|
|
148
|
+
lastHeartbeatAt: result.state.lastHeartbeatAt,
|
|
149
|
+
statusDetail: result.state.statusDetail,
|
|
150
|
+
waitingOn: result.state.waitingOn,
|
|
151
|
+
runDir: result.runDir,
|
|
152
|
+
outputs: result.state.outputs,
|
|
153
|
+
sessionBindings: result.state.sessionBindings
|
|
154
|
+
};
|
|
155
|
+
if (globalFlags.format === "json") {
|
|
156
|
+
process.stdout.write(`${JSON.stringify(payload)}\n`);
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
if (globalFlags.format === "quiet") {
|
|
160
|
+
process.stdout.write(`${result.state.runId}\n`);
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
process.stdout.write(`runId: ${payload.runId}\n`);
|
|
164
|
+
process.stdout.write(`flow: ${payload.flowName}\n`);
|
|
165
|
+
if (payload.runTitle) process.stdout.write(`title: ${payload.runTitle}\n`);
|
|
166
|
+
process.stdout.write(`status: ${payload.status}\n`);
|
|
167
|
+
process.stdout.write(`runDir: ${payload.runDir}\n`);
|
|
168
|
+
if (payload.currentNode) process.stdout.write(`currentNode: ${payload.currentNode}\n`);
|
|
169
|
+
if (payload.statusDetail) process.stdout.write(`statusDetail: ${payload.statusDetail}\n`);
|
|
170
|
+
if (payload.waitingOn) process.stdout.write(`waitingOn: ${payload.waitingOn}\n`);
|
|
171
|
+
process.stdout.write(`${JSON.stringify(payload.outputs, null, 2)}\n`);
|
|
172
|
+
}
|
|
173
|
+
//#endregion
|
|
174
|
+
export { handleFlowRun };
|
|
175
|
+
|
|
176
|
+
//# sourceMappingURL=cli-idpWyCOs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli-idpWyCOs.js","names":[],"sources":["../src/flows/cli.ts"],"sourcesContent":["import { randomUUID } from \"node:crypto\";\nimport fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { fileURLToPath, pathToFileURL } from \"node:url\";\nimport { InvalidArgumentError, type Command } from \"commander\";\nimport {\n hasExplicitPermissionModeFlag,\n resolveAgentInvocation,\n resolveGlobalFlags,\n resolveOutputPolicy,\n resolvePermissionMode,\n type GlobalFlags,\n} from \"../cli/flags.js\";\nimport type { ResolvedAcpxConfig } from \"../config.js\";\nimport { type FlowDefinition, FlowRunner } from \"../flows.js\";\nimport { permissionModeSatisfies } from \"../permissions.js\";\nimport type { PermissionMode } from \"../types.js\";\n\ntype FlowRunFlags = {\n inputJson?: string;\n inputFile?: string;\n defaultAgent?: string;\n};\n\nconst FLOW_RUNTIME_SPECIFIER = \"acpx/flows\";\nconst TEXT_MODULE_EXTENSIONS = new Set([\".js\", \".mjs\", \".cjs\", \".ts\", \".tsx\", \".mts\", \".cts\"]);\n\nexport async function handleFlowRun(\n flowFile: string,\n flags: FlowRunFlags,\n command: Command,\n config: ResolvedAcpxConfig,\n): Promise<void> {\n const globalFlags = resolveGlobalFlags(command, config);\n const permissionMode = resolvePermissionMode(globalFlags, config.defaultPermissions);\n const outputPolicy = resolveOutputPolicy(globalFlags.format, globalFlags.jsonStrict === true);\n const input = await readFlowInput(flags);\n const flowPath = path.resolve(flowFile);\n const flow = await loadFlowModule(flowPath);\n assertFlowPermissionRequirements(flow, permissionMode, globalFlags);\n\n const runner = new FlowRunner({\n resolveAgent: (profile?: string) => {\n return resolveAgentInvocation(profile ?? flags.defaultAgent, globalFlags, config);\n },\n permissionMode,\n mcpServers: config.mcpServers,\n nonInteractivePermissions: globalFlags.nonInteractivePermissions,\n authCredentials: config.auth,\n authPolicy: globalFlags.authPolicy,\n timeoutMs: globalFlags.timeout,\n ttlMs: globalFlags.ttl,\n verbose: globalFlags.verbose,\n suppressSdkConsoleErrors: outputPolicy.suppressSdkConsoleErrors,\n sessionOptions: {\n model: globalFlags.model,\n allowedTools: globalFlags.allowedTools,\n maxTurns: globalFlags.maxTurns,\n },\n });\n\n const result = await runner.run(flow, input, {\n flowPath,\n });\n\n printFlowRunResult(result, globalFlags);\n}\n\nfunction assertFlowPermissionRequirements(\n flow: FlowDefinition,\n permissionMode: PermissionMode,\n globalFlags: GlobalFlags,\n): void {\n const permissions = flow.permissions;\n if (!permissions) {\n return;\n }\n\n if (permissions.requireExplicitGrant && !hasExplicitPermissionModeFlag(globalFlags)) {\n throw new InvalidArgumentError(\n buildFlowPermissionFailureMessage(flow, permissions.requiredMode, permissions.reason, true),\n );\n }\n\n if (!permissionModeSatisfies(permissionMode, permissions.requiredMode)) {\n throw new InvalidArgumentError(\n buildFlowPermissionFailureMessage(flow, permissions.requiredMode, permissions.reason, false),\n );\n }\n}\n\nfunction buildFlowPermissionFailureMessage(\n flow: FlowDefinition,\n requiredMode: PermissionMode,\n reason?: string,\n explicit = false,\n): string {\n return [\n explicit\n ? `Flow \"${flow.name}\" requires an explicit ${requiredMode} grant.`\n : `Flow \"${flow.name}\" requires permission mode ${requiredMode}.`,\n `Rerun with --${requiredMode}.`,\n ...(reason ? [`Reason: ${reason}`] : []),\n ].join(\" \");\n}\n\nasync function readFlowInput(flags: FlowRunFlags): Promise<unknown> {\n if (flags.inputJson && flags.inputFile) {\n throw new InvalidArgumentError(\"Use only one of --input-json or --input-file\");\n }\n\n if (flags.inputJson) {\n return parseJsonInput(flags.inputJson, \"--input-json\");\n }\n\n if (flags.inputFile) {\n const inputPath = path.resolve(flags.inputFile);\n const payload = await fs.readFile(inputPath, \"utf8\");\n return parseJsonInput(payload, \"--input-file\");\n }\n\n return {};\n}\n\nasync function loadFlowModule(flowPath: string): Promise<FlowDefinition> {\n const extension = path.extname(flowPath).toLowerCase();\n const prepared = await prepareFlowModuleImport(flowPath, extension);\n try {\n const module = await loadFlowRuntimeModule(prepared.flowUrl, extension);\n\n const candidate = findFlowDefinition(module);\n if (!candidate) {\n throw new Error(`Flow module must export a flow object: ${flowPath}`);\n }\n return candidate;\n } finally {\n await prepared.cleanup?.();\n }\n}\n\nasync function prepareFlowModuleImport(\n flowPath: string,\n extension: string,\n): Promise<{\n flowUrl: string;\n cleanup?: () => Promise<void>;\n}> {\n const flowUrl = pathToFileURL(flowPath).href;\n if (!TEXT_MODULE_EXTENSIONS.has(extension)) {\n return { flowUrl };\n }\n\n const source = await fs.readFile(flowPath, \"utf8\");\n if (!source.includes(FLOW_RUNTIME_SPECIFIER)) {\n return { flowUrl };\n }\n\n const runtimeSpecifier = resolveFlowRuntimeImportSpecifier();\n const rewritten = source.replaceAll(\n /([\"'])acpx\\/flows\\1/g,\n (_match, quote: string) => `${quote}${runtimeSpecifier}${quote}`,\n );\n if (rewritten === source) {\n return { flowUrl };\n }\n\n const tempPath = path.join(path.dirname(flowPath), `.acpx-flow-load-${randomUUID()}${extension}`);\n await fs.writeFile(tempPath, rewritten, \"utf8\");\n return {\n flowUrl: pathToFileURL(tempPath).href,\n cleanup: async () => {\n await fs.rm(tempPath, { force: true });\n },\n };\n}\n\nfunction resolveFlowRuntimeImportSpecifier(): string {\n const selfPath = fileURLToPath(import.meta.url);\n\n if (selfPath.endsWith(`${path.sep}src${path.sep}flows${path.sep}cli.ts`)) {\n return new URL(\"../flows.ts\", import.meta.url).href;\n }\n if (selfPath.endsWith(`${path.sep}src${path.sep}flows${path.sep}cli.js`)) {\n return new URL(\"../flows.js\", import.meta.url).href;\n }\n return new URL(\"./flows.js\", import.meta.url).href;\n}\n\nasync function loadFlowRuntimeModule(\n flowUrl: string,\n extension: string,\n): Promise<{\n default?: unknown;\n \"module.exports\"?: unknown;\n}> {\n if (extension === \".ts\" || extension === \".tsx\" || extension === \".mts\" || extension === \".cts\") {\n const { tsImport } = (await import(\"tsx/esm/api\")) as {\n tsImport: (\n specifier: string,\n parentURL: string,\n ) => Promise<{\n default?: unknown;\n \"module.exports\"?: unknown;\n }>;\n };\n return (await tsImport(flowUrl, import.meta.url)) as {\n default?: unknown;\n \"module.exports\"?: unknown;\n };\n }\n\n return (await import(flowUrl)) as {\n default?: unknown;\n \"module.exports\"?: unknown;\n };\n}\n\nfunction findFlowDefinition(module: {\n default?: unknown;\n \"module.exports\"?: unknown;\n}): FlowDefinition | null {\n const candidates = [\n module.default,\n module[\"module.exports\"],\n getNestedDefault(module.default),\n getNestedDefault(module[\"module.exports\"]),\n ];\n\n for (const candidate of candidates) {\n if (isFlowDefinition(candidate)) {\n return candidate;\n }\n }\n\n return null;\n}\n\nfunction getNestedDefault(value: unknown): unknown {\n if (!value || typeof value !== \"object\" || !(\"default\" in value)) {\n return null;\n }\n return (value as { default?: unknown }).default ?? null;\n}\n\nfunction isFlowDefinition(value: unknown): value is FlowDefinition {\n if (!value || typeof value !== \"object\") {\n return false;\n }\n\n const candidate = value as Partial<FlowDefinition>;\n return (\n typeof candidate.name === \"string\" &&\n typeof candidate.startAt === \"string\" &&\n candidate.nodes !== undefined &&\n typeof candidate.nodes === \"object\" &&\n Array.isArray(candidate.edges)\n );\n}\n\nfunction parseJsonInput(raw: string, label: string): unknown {\n try {\n return JSON.parse(raw);\n } catch (error) {\n throw new InvalidArgumentError(\n `${label} must contain valid JSON: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n}\n\nfunction printFlowRunResult(\n result: Awaited<ReturnType<FlowRunner[\"run\"]>>,\n globalFlags: GlobalFlags,\n): void {\n const payload = {\n action: \"flow_run_result\",\n runId: result.state.runId,\n flowName: result.state.flowName,\n runTitle: result.state.runTitle,\n flowPath: result.state.flowPath,\n status: result.state.status,\n currentNode: result.state.currentNode,\n currentNodeType: result.state.currentNodeType,\n currentNodeStartedAt: result.state.currentNodeStartedAt,\n lastHeartbeatAt: result.state.lastHeartbeatAt,\n statusDetail: result.state.statusDetail,\n waitingOn: result.state.waitingOn,\n runDir: result.runDir,\n outputs: result.state.outputs,\n sessionBindings: result.state.sessionBindings,\n };\n\n if (globalFlags.format === \"json\") {\n process.stdout.write(`${JSON.stringify(payload)}\\n`);\n return;\n }\n\n if (globalFlags.format === \"quiet\") {\n process.stdout.write(`${result.state.runId}\\n`);\n return;\n }\n\n process.stdout.write(`runId: ${payload.runId}\\n`);\n process.stdout.write(`flow: ${payload.flowName}\\n`);\n if (payload.runTitle) {\n process.stdout.write(`title: ${payload.runTitle}\\n`);\n }\n process.stdout.write(`status: ${payload.status}\\n`);\n process.stdout.write(`runDir: ${payload.runDir}\\n`);\n if (payload.currentNode) {\n process.stdout.write(`currentNode: ${payload.currentNode}\\n`);\n }\n if (payload.statusDetail) {\n process.stdout.write(`statusDetail: ${payload.statusDetail}\\n`);\n }\n if (payload.waitingOn) {\n process.stdout.write(`waitingOn: ${payload.waitingOn}\\n`);\n }\n process.stdout.write(`${JSON.stringify(payload.outputs, null, 2)}\\n`);\n}\n"],"mappings":"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"}
|
package/dist/cli.d.ts
CHANGED
|
@@ -1,123 +1,6 @@
|
|
|
1
|
+
import { a as SessionRecord } from "./types-CeRKmEQ1.js";
|
|
1
2
|
import { Command } from "commander";
|
|
2
|
-
import { AgentCapabilities, SessionConfigOption } from "@agentclientprotocol/sdk";
|
|
3
3
|
|
|
4
|
-
//#region src/types.d.ts
|
|
5
|
-
type SessionEventLog = {
|
|
6
|
-
active_path: string;
|
|
7
|
-
segment_count: number;
|
|
8
|
-
max_segment_bytes: number;
|
|
9
|
-
max_segments: number;
|
|
10
|
-
last_write_at?: string;
|
|
11
|
-
last_write_error?: string | null;
|
|
12
|
-
};
|
|
13
|
-
declare const SESSION_RECORD_SCHEMA: "acpx.session.v1";
|
|
14
|
-
type SessionMessageImage = {
|
|
15
|
-
source: string;
|
|
16
|
-
size?: {
|
|
17
|
-
width: number;
|
|
18
|
-
height: number;
|
|
19
|
-
} | null;
|
|
20
|
-
};
|
|
21
|
-
type SessionUserContent = {
|
|
22
|
-
Text: string;
|
|
23
|
-
} | {
|
|
24
|
-
Mention: {
|
|
25
|
-
uri: string;
|
|
26
|
-
content: string;
|
|
27
|
-
};
|
|
28
|
-
} | {
|
|
29
|
-
Image: SessionMessageImage;
|
|
30
|
-
};
|
|
31
|
-
type SessionToolUse = {
|
|
32
|
-
id: string;
|
|
33
|
-
name: string;
|
|
34
|
-
raw_input: string;
|
|
35
|
-
input: unknown;
|
|
36
|
-
is_input_complete: boolean;
|
|
37
|
-
thought_signature?: string | null;
|
|
38
|
-
};
|
|
39
|
-
type SessionToolResultContent = {
|
|
40
|
-
Text: string;
|
|
41
|
-
} | {
|
|
42
|
-
Image: SessionMessageImage;
|
|
43
|
-
};
|
|
44
|
-
type SessionToolResult = {
|
|
45
|
-
tool_use_id: string;
|
|
46
|
-
tool_name: string;
|
|
47
|
-
is_error: boolean;
|
|
48
|
-
content: SessionToolResultContent;
|
|
49
|
-
output?: unknown;
|
|
50
|
-
};
|
|
51
|
-
type SessionAgentContent = {
|
|
52
|
-
Text: string;
|
|
53
|
-
} | {
|
|
54
|
-
Thinking: {
|
|
55
|
-
text: string;
|
|
56
|
-
signature?: string | null;
|
|
57
|
-
};
|
|
58
|
-
} | {
|
|
59
|
-
RedactedThinking: string;
|
|
60
|
-
} | {
|
|
61
|
-
ToolUse: SessionToolUse;
|
|
62
|
-
};
|
|
63
|
-
type SessionUserMessage = {
|
|
64
|
-
id: string;
|
|
65
|
-
content: SessionUserContent[];
|
|
66
|
-
};
|
|
67
|
-
type SessionAgentMessage = {
|
|
68
|
-
content: SessionAgentContent[];
|
|
69
|
-
tool_results: Record<string, SessionToolResult>;
|
|
70
|
-
reasoning_details?: unknown;
|
|
71
|
-
};
|
|
72
|
-
type SessionMessage = {
|
|
73
|
-
User: SessionUserMessage;
|
|
74
|
-
} | {
|
|
75
|
-
Agent: SessionAgentMessage;
|
|
76
|
-
} | "Resume";
|
|
77
|
-
type SessionTokenUsage = {
|
|
78
|
-
input_tokens?: number;
|
|
79
|
-
output_tokens?: number;
|
|
80
|
-
cache_creation_input_tokens?: number;
|
|
81
|
-
cache_read_input_tokens?: number;
|
|
82
|
-
};
|
|
83
|
-
type SessionAcpxState = {
|
|
84
|
-
current_mode_id?: string;
|
|
85
|
-
desired_mode_id?: string;
|
|
86
|
-
available_commands?: string[];
|
|
87
|
-
config_options?: SessionConfigOption[];
|
|
88
|
-
};
|
|
89
|
-
type SessionRecord = {
|
|
90
|
-
schema: typeof SESSION_RECORD_SCHEMA;
|
|
91
|
-
acpxRecordId: string;
|
|
92
|
-
acpSessionId: string;
|
|
93
|
-
agentSessionId?: string;
|
|
94
|
-
agentCommand: string;
|
|
95
|
-
cwd: string;
|
|
96
|
-
name?: string;
|
|
97
|
-
createdAt: string;
|
|
98
|
-
lastUsedAt: string;
|
|
99
|
-
lastSeq: number;
|
|
100
|
-
lastRequestId?: string;
|
|
101
|
-
eventLog: SessionEventLog;
|
|
102
|
-
closed?: boolean;
|
|
103
|
-
closedAt?: string;
|
|
104
|
-
pid?: number;
|
|
105
|
-
agentStartedAt?: string;
|
|
106
|
-
lastPromptAt?: string;
|
|
107
|
-
lastAgentExitCode?: number | null;
|
|
108
|
-
lastAgentExitSignal?: NodeJS.Signals | null;
|
|
109
|
-
lastAgentExitAt?: string;
|
|
110
|
-
lastAgentDisconnectReason?: string;
|
|
111
|
-
protocolVersion?: number;
|
|
112
|
-
agentCapabilities?: AgentCapabilities;
|
|
113
|
-
title?: string | null;
|
|
114
|
-
messages: SessionMessage[];
|
|
115
|
-
updated_at: string;
|
|
116
|
-
cumulative_token_usage: SessionTokenUsage;
|
|
117
|
-
request_token_usage: Record<string, SessionTokenUsage>;
|
|
118
|
-
acpx?: SessionAcpxState;
|
|
119
|
-
};
|
|
120
|
-
//#endregion
|
|
121
4
|
//#region src/cli/flags.d.ts
|
|
122
5
|
declare function parseTtlSeconds(value: string): number;
|
|
123
6
|
declare function parseAllowedTools(value: string): string[];
|
package/dist/cli.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.d.ts","names":[],"sources":["../src/
|
|
1
|
+
{"version":3,"file":"cli.d.ts","names":[],"sources":["../src/cli/flags.ts","../src/cli/output-render.ts"],"mappings":";;;;iBAyGgB,eAAA,CAAgB,KAAA;AAAA,iBAgChB,iBAAA,CAAkB,KAAA;AAAA,iBAgBlB,aAAA,CAAc,KAAA;;;KCvIzB,uBAAA;AAAA,iBA0IW,6BAAA,CACd,MAAA,EAAQ,aAAA,EACR,UAAA,UACA,gBAAA,GAAkB,uBAAA"}
|