@arnilo/prism-acp-agent 0.2.8

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/CHANGELOG.md ADDED
@@ -0,0 +1,21 @@
1
+ # Changelog
2
+
3
+ ## [0.2.8] - 2026-08-18
4
+
5
+ ### Added
6
+ - First published cut with the 0.2.8 graph (plan 028 Task 10 / Task 18).
7
+
8
+ ## [0.2.7] - 2026-08-18
9
+
10
+ ### Added
11
+ - Initial release: spawnable ACP agent entrypoint (plan 028 Task 10 / adoption F3). `prism-acp-agent` bin serves `createPrismAcpAgent` over stdio from a validated config file (`userId`, `cwd`, sqlite/memory session store, MCP allow-list, modes, config options, limits); `createSpawnableAgent`/`loadConfig`/`parseConfig`/`selectMcpServers` library surface; mock provider by default, real providers wire via the `provider` option.
12
+
13
+ ## [0.1.0] - 2026-08-09
14
+
15
+ ### Changed
16
+ - Released with exact 0.1.0 graph.
17
+
18
+ ## [0.0.28] - 2026-08-08
19
+
20
+ ### Changed
21
+ - Released with exact 0.0.28 graph.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Prism contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,69 @@
1
+ # @arnilo/prism-acp-agent
2
+
3
+ Spawnable ACP agent: a thin binary that serves [`createPrismAcpAgent`](https://github.com/ashiqrniloy/prism/tree/main/packages/ag-ui) over stdio from a config file.
4
+
5
+ The binary is pure wiring — every protocol detail lives in `@arnilo/prism-ag-ui`. It wires the common seams for a single-workspace, single-local-user deployment:
6
+
7
+ - `authorize` — single local user from config
8
+ - `sessionFactory` — real Prism sessions backed by the [coding tools](https://github.com/ashiqrniloy/prism/tree/main/packages/coding-agent) (`shell`, `read`, `write`, `edit`, `repo_list`, `repo_search`, `glob`, `delete`, `move`)
9
+ - session store — in-memory or [SQLite](https://github.com/ashiqrniloy/prism/tree/main/packages/session-store-sqlite) (sessions, runs, checkpoints, leases)
10
+ - MCP allow-list gate — http/sse servers must match a URL prefix; stdio servers require the `"stdio"` marker
11
+ - modes and config options tables
12
+
13
+ ## Usage
14
+
15
+ ```sh
16
+ npx prism-acp-agent [--config prism-acp-agent.json]
17
+ ```
18
+
19
+ The agent speaks ACP over newline-delimited JSON on stdio. It serves until the client closes stdin.
20
+
21
+ ### Config file
22
+
23
+ The config file is the trust boundary: unknown keys are rejected and invalid values fail closed with a clear error. Relative paths resolve against the config file's directory.
24
+
25
+ ```json
26
+ {
27
+ "userId": "local",
28
+ "cwd": ".",
29
+ "sessionStore": { "type": "sqlite", "path": ".prism/sessions.db" },
30
+ "mcp": { "allow": ["https://mcp.example.com"] },
31
+ "modes": { "modes": [{ "id": "edit", "name": "Edit" }], "defaultModeId": "edit" },
32
+ "configOptions": [{ "type": "boolean", "id": "verbose", "name": "Verbose", "defaultValue": false }]
33
+ }
34
+ ```
35
+
36
+ | Key | Required | Description |
37
+ | --- | --- | --- |
38
+ | `userId` | yes | Ownership user id for every session. |
39
+ | `cwd` | yes | Workspace root the coding tools are bound to (must exist). |
40
+ | `sessionStore` | no | `{ "type": "sqlite", "path" }` or `{ "type": "memory" }` (default). |
41
+ | `mcp.allow` | no | URL prefixes allowed for http/sse MCP servers; the marker `"stdio"` allows stdio servers. |
42
+ | `modes` | no | Mode table; `defaultModeId` must name a mode. |
43
+ | `configOptions` | no | Boolean or select options with `defaultValue`. |
44
+ | `limits` | no | AG-UI/ACP caps passthrough (see `AgUiLimitOptions`). |
45
+
46
+ The served agent uses the mock provider by default (full lifecycle, no tokens). Wire a real provider programmatically:
47
+
48
+ ```ts
49
+ import { createSpawnableAgent, loadConfig } from "@arnilo/prism-acp-agent";
50
+ import { createOpenAIResponsesProvider } from "@arnilo/prism-provider-openai";
51
+
52
+ const agent = createSpawnableAgent({
53
+ config: loadConfig("prism-acp-agent.json"),
54
+ provider: createOpenAIResponsesProvider({ apiKey: process.env.OPENAI_API_KEY }),
55
+ });
56
+ ```
57
+
58
+ ## Library surface
59
+
60
+ - `loadConfig(path)` / `parseConfig(text, baseDir)` — read and validate a config; throws `ConfigError` with a clear message.
61
+ - `createSpawnableAgent({ config, provider? })` — build the ACP `AgentApp`.
62
+ - `selectMcpServers(allow, servers)` — the allow-list gate (exported for reuse).
63
+
64
+ ## Development
65
+
66
+ ```sh
67
+ npm run build --workspace @arnilo/prism-acp-agent
68
+ npm test --workspace @arnilo/prism-acp-agent
69
+ ```
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
@@ -0,0 +1,37 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Spawnable ACP agent entrypoint (0.2.8 Task 10 / adoption F3).
4
+ *
5
+ * Reads a config file (default `prism-acp-agent.json`, override with
6
+ * `--config <path>`), builds the ACP agent seams, and serves the protocol
7
+ * over stdio via the SDK's ndjson stream adapter. The process lives until
8
+ * the client closes stdin; EPIPE on stdout is a normal client disconnect.
9
+ */
10
+ import { Readable, Writable } from "node:stream";
11
+ import { parseArgs } from "node:util";
12
+ import { ndJsonStream } from "@agentclientprotocol/sdk";
13
+ import { createSpawnableAgent, loadConfig } from "../src/index.js";
14
+ const { values } = parseArgs({
15
+ options: { config: { type: "string", short: "c" } },
16
+ allowPositionals: false,
17
+ });
18
+ let agent;
19
+ try {
20
+ agent = createSpawnableAgent({ config: loadConfig(values.config ?? "prism-acp-agent.json") });
21
+ }
22
+ catch (error) {
23
+ console.error(`prism-acp-agent: ${error instanceof Error ? error.message : String(error)}`);
24
+ process.exit(1);
25
+ }
26
+ const stream = ndJsonStream(Writable.toWeb(process.stdout), Readable.toWeb(process.stdin));
27
+ try {
28
+ const connection = await agent.connect(stream);
29
+ await connection?.closed;
30
+ }
31
+ catch (error) {
32
+ const code = error && typeof error === "object" && "code" in error ? error.code : undefined;
33
+ if (code !== "EPIPE")
34
+ console.error(`prism-acp-agent: ${error instanceof Error ? error.message : String(error)}`);
35
+ process.exit(code === "EPIPE" ? 0 : 1);
36
+ }
37
+ //# sourceMappingURL=prism-acp-agent.js.map
@@ -0,0 +1,37 @@
1
+ import type { AgUiLimitOptions } from "@arnilo/prism-ag-ui";
2
+ import type { AcpConfigOption, AcpSessionMode } from "@arnilo/prism-ag-ui/acp";
3
+ export declare class ConfigError extends Error {
4
+ readonly code = "PRISM_ACP_AGENT_CONFIG";
5
+ }
6
+ export interface PrismAcpAgentMcpConfig {
7
+ /** URL prefixes allowed for http/sse MCP servers; the marker "stdio" allows stdio servers. */
8
+ readonly allow: readonly string[];
9
+ }
10
+ export interface PrismAcpAgentModesConfig {
11
+ readonly modes: readonly AcpSessionMode[];
12
+ readonly defaultModeId?: string;
13
+ }
14
+ export interface PrismAcpAgentConfigOptionsConfig {
15
+ readonly options: readonly AcpConfigOption[];
16
+ }
17
+ export interface PrismAcpAgentConfig {
18
+ /** Ownership user id for every ACP session (single-local-user authorization). */
19
+ readonly userId: string;
20
+ /** Workspace root the coding tools are bound to (resolved against the config dir). */
21
+ readonly cwd: string;
22
+ /** Durable store for Prism sessions/runs; default: in-memory. */
23
+ readonly sessionStore: {
24
+ readonly type: "sqlite";
25
+ readonly path: string;
26
+ } | {
27
+ readonly type: "memory";
28
+ };
29
+ readonly mcp?: PrismAcpAgentMcpConfig;
30
+ readonly modes?: PrismAcpAgentModesConfig;
31
+ readonly configOptions?: PrismAcpAgentConfigOptionsConfig;
32
+ /** AG-UI/ACP caps (see @arnilo/prism-ag-ui AgUiLimitOptions); optional passthrough. */
33
+ readonly limits?: AgUiLimitOptions;
34
+ }
35
+ export declare function loadConfig(path: string): PrismAcpAgentConfig;
36
+ export declare function parseConfig(text: string, baseDir: string, source?: string): PrismAcpAgentConfig;
37
+ export declare function validateConfig(raw: unknown, baseDir: string, source: string): PrismAcpAgentConfig;
@@ -0,0 +1,164 @@
1
+ /**
2
+ * Config parsing and validation for the spawnable ACP agent (0.2.8 Task 10).
3
+ *
4
+ * The config file is the trust boundary: every field is validated with a
5
+ * clear error, and unknown keys are rejected so a typo cannot silently
6
+ * disable a security-relevant option (fail closed). Paths in the config are
7
+ * resolved against the config file's directory, so the file is relocatable.
8
+ */
9
+ import { existsSync, readFileSync, statSync } from "node:fs";
10
+ import { dirname, resolve } from "node:path";
11
+ export class ConfigError extends Error {
12
+ code = "PRISM_ACP_AGENT_CONFIG";
13
+ }
14
+ const KNOWN_KEYS = new Set(["userId", "cwd", "sessionStore", "mcp", "modes", "configOptions", "limits"]);
15
+ const KNOWN_SESSION_STORE_KEYS = new Set(["type", "path"]);
16
+ const KNOWN_MCP_KEYS = new Set(["allow"]);
17
+ export function loadConfig(path) {
18
+ const resolved = resolve(path);
19
+ let text;
20
+ try {
21
+ text = readFileSync(resolved, "utf8");
22
+ }
23
+ catch (error) {
24
+ throw new ConfigError(`cannot read config file ${resolved}: ${error instanceof Error ? error.message : String(error)}`);
25
+ }
26
+ return parseConfig(text, dirname(resolved), resolved);
27
+ }
28
+ export function parseConfig(text, baseDir, source = "config") {
29
+ let raw;
30
+ try {
31
+ raw = JSON.parse(text);
32
+ }
33
+ catch (error) {
34
+ throw new ConfigError(`${source}: invalid JSON: ${error instanceof Error ? error.message : String(error)}`);
35
+ }
36
+ return validateConfig(raw, baseDir, source);
37
+ }
38
+ function isRecord(value) {
39
+ return typeof value === "object" && value !== null && !Array.isArray(value);
40
+ }
41
+ function fail(source, message) {
42
+ throw new ConfigError(`${source}: ${message}`);
43
+ }
44
+ function requireString(value, source, field) {
45
+ if (typeof value !== "string" || value.length === 0)
46
+ fail(source, `${field} must be a non-empty string`);
47
+ return value;
48
+ }
49
+ function rejectUnknown(record, known, source) {
50
+ const unknown = Object.keys(record).filter((key) => !known.has(key));
51
+ if (unknown.length > 0)
52
+ fail(source, `unknown key(s): ${unknown.join(", ")}`);
53
+ }
54
+ export function validateConfig(raw, baseDir, source) {
55
+ if (!isRecord(raw))
56
+ fail(source, "config must be a JSON object");
57
+ rejectUnknown(raw, KNOWN_KEYS, source);
58
+ const userId = requireString(raw.userId, source, "userId");
59
+ const cwd = resolve(baseDir, requireString(raw.cwd, source, "cwd"));
60
+ if (!existsSync(cwd) || !statSync(cwd).isDirectory())
61
+ fail(source, `cwd is not an existing directory: ${cwd}`);
62
+ let sessionStore = { type: "memory" };
63
+ if (raw.sessionStore !== undefined) {
64
+ if (!isRecord(raw.sessionStore))
65
+ fail(source, "sessionStore must be an object");
66
+ rejectUnknown(raw.sessionStore, KNOWN_SESSION_STORE_KEYS, `${source}.sessionStore`);
67
+ if (raw.sessionStore.type === "sqlite") {
68
+ const path = requireString(raw.sessionStore.path, `${source}.sessionStore`, "path");
69
+ sessionStore = { type: "sqlite", path: resolve(baseDir, path) };
70
+ }
71
+ else if (raw.sessionStore.type !== "memory") {
72
+ fail(source, `sessionStore.type must be "sqlite" or "memory", got ${JSON.stringify(raw.sessionStore.type)}`);
73
+ }
74
+ }
75
+ let mcp;
76
+ if (raw.mcp !== undefined) {
77
+ if (!isRecord(raw.mcp))
78
+ fail(source, "mcp must be an object");
79
+ rejectUnknown(raw.mcp, KNOWN_MCP_KEYS, `${source}.mcp`);
80
+ if (!Array.isArray(raw.mcp.allow) || raw.mcp.allow.some((entry) => typeof entry !== "string" || entry.length === 0)) {
81
+ fail(source, "mcp.allow must be an array of non-empty strings");
82
+ }
83
+ mcp = { allow: raw.mcp.allow };
84
+ }
85
+ let modes;
86
+ if (raw.modes !== undefined) {
87
+ if (!isRecord(raw.modes))
88
+ fail(source, "modes must be an object");
89
+ const modeList = raw.modes.modes;
90
+ if (!Array.isArray(modeList) || modeList.length === 0)
91
+ fail(source, "modes.modes must be a non-empty array");
92
+ const ids = new Set();
93
+ for (const [index, mode] of modeList.entries()) {
94
+ if (!isRecord(mode))
95
+ fail(source, `modes.modes[${index}] must be an object`);
96
+ rejectUnknown(mode, new Set(["id", "name", "description"]), `${source}.modes.modes[${index}]`);
97
+ const id = requireString(mode.id, `${source}.modes.modes[${index}]`, "id");
98
+ requireString(mode.name, `${source}.modes.modes[${index}]`, "name");
99
+ if (ids.has(id))
100
+ fail(source, `duplicate mode id: ${id}`);
101
+ ids.add(id);
102
+ }
103
+ const defaultModeId = raw.modes.defaultModeId === undefined ? undefined : requireString(raw.modes.defaultModeId, `${source}.modes`, "defaultModeId");
104
+ if (defaultModeId !== undefined && !ids.has(defaultModeId))
105
+ fail(source, `defaultModeId '${defaultModeId}' is not a known mode`);
106
+ modes = {
107
+ modes: modeList,
108
+ ...(defaultModeId !== undefined ? { defaultModeId } : {}),
109
+ };
110
+ }
111
+ let configOptions;
112
+ if (raw.configOptions !== undefined) {
113
+ if (!isRecord(raw.configOptions))
114
+ fail(source, "configOptions must be an object");
115
+ const optionList = raw.configOptions.options;
116
+ if (!Array.isArray(optionList) || optionList.length === 0)
117
+ fail(source, "configOptions.options must be a non-empty array");
118
+ const ids = new Set();
119
+ for (const [index, option] of optionList.entries()) {
120
+ const at = `${source}.configOptions.options[${index}]`;
121
+ if (!isRecord(option))
122
+ fail(source, `${at} must be an object`);
123
+ rejectUnknown(option, new Set(["type", "id", "name", "description", "defaultValue", "options"]), at);
124
+ const type = option.type;
125
+ if (type !== "boolean" && type !== "select")
126
+ fail(source, `${at}.type must be "boolean" or "select"`);
127
+ const id = requireString(option.id, at, "id");
128
+ requireString(option.name, at, "name");
129
+ if (ids.has(id))
130
+ fail(source, `duplicate config option id: ${id}`);
131
+ ids.add(id);
132
+ if (type === "boolean" && typeof option.defaultValue !== "boolean")
133
+ fail(source, `${at}.defaultValue must be a boolean`);
134
+ if (type === "select") {
135
+ if (typeof option.defaultValue !== "string")
136
+ fail(source, `${at}.defaultValue must be a string`);
137
+ if (!Array.isArray(option.options) || option.options.length === 0)
138
+ fail(source, `${at}.options must be a non-empty array`);
139
+ for (const [choiceIndex, choice] of option.options.entries()) {
140
+ if (!isRecord(choice) || typeof choice.value !== "string" || choice.value.length === 0) {
141
+ fail(source, `${at}.options[${choiceIndex}].value must be a non-empty string`);
142
+ }
143
+ }
144
+ }
145
+ }
146
+ configOptions = { options: optionList };
147
+ }
148
+ let limits;
149
+ if (raw.limits !== undefined) {
150
+ if (!isRecord(raw.limits))
151
+ fail(source, "limits must be an object");
152
+ limits = raw.limits;
153
+ }
154
+ return {
155
+ userId,
156
+ cwd,
157
+ sessionStore,
158
+ ...(mcp ? { mcp } : {}),
159
+ ...(modes ? { modes } : {}),
160
+ ...(configOptions ? { configOptions } : {}),
161
+ ...(limits ? { limits } : {}),
162
+ };
163
+ }
164
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1,13 @@
1
+ import type { AgentApp, McpServer } from "@agentclientprotocol/sdk";
2
+ import { type AIProvider } from "@arnilo/prism";
3
+ import type { PrismAcpAgentConfig } from "./config.js";
4
+ export type { PrismAcpAgentConfig } from "./config.js";
5
+ export { ConfigError, loadConfig, parseConfig } from "./config.js";
6
+ export interface CreateSpawnableAgentOptions {
7
+ readonly config: PrismAcpAgentConfig;
8
+ /** Model provider for the served Prism agent; default: mock (no tokens). */
9
+ readonly provider?: AIProvider;
10
+ }
11
+ /** MCP allow-list gate: http/sse servers must match an allow prefix; stdio needs the "stdio" marker. */
12
+ export declare function selectMcpServers(allow: readonly string[], servers: readonly McpServer[]): boolean;
13
+ export declare function createSpawnableAgent(options: CreateSpawnableAgentOptions): AgentApp;
@@ -0,0 +1,70 @@
1
+ /**
2
+ * Spawnable ACP agent (0.2.8 Task 10 / adoption F3).
3
+ *
4
+ * Thin wiring only: config parsing (src/config.ts) plus this seam builder.
5
+ * Every protocol detail lives in `createPrismAcpAgent` (@arnilo/prism-ag-ui);
6
+ * this package never re-implements ACP. The default provider is the mock
7
+ * provider so the lifecycle works out of the box; wire a real `AIProvider`
8
+ * (e.g. @arnilo/prism-provider-openai) for actual generation.
9
+ */
10
+ import { randomUUID } from "node:crypto";
11
+ import { createAgent, createAgentRunLifecycle, createMemoryCheckpointStore, createMemorySessionStore, createMockProvider, createToolRegistry, } from "@arnilo/prism";
12
+ import { createPrismAcpAgent } from "@arnilo/prism-ag-ui/acp";
13
+ import { createCodingTools } from "@arnilo/prism-coding-agent";
14
+ import { createSqlitePersistence } from "@arnilo/prism-session-store-sqlite";
15
+ export { ConfigError, loadConfig, parseConfig } from "./config.js";
16
+ /** MCP allow-list gate: http/sse servers must match an allow prefix; stdio needs the "stdio" marker. */
17
+ export function selectMcpServers(allow, servers) {
18
+ return servers.every((server) => {
19
+ if ("type" in server) {
20
+ // acp transport is UNSTABLE v2 surface — never bridged.
21
+ return server.type !== "acp" && allow.some((entry) => server.url.startsWith(entry));
22
+ }
23
+ return allow.includes("stdio");
24
+ });
25
+ }
26
+ export function createSpawnableAgent(options) {
27
+ const { config } = options;
28
+ const ownership = { userId: config.userId };
29
+ let store;
30
+ let checkpoints;
31
+ if (config.sessionStore.type === "sqlite") {
32
+ const persistence = createSqlitePersistence({ filename: config.sessionStore.path });
33
+ store = persistence;
34
+ checkpoints = persistence.checkpoints;
35
+ }
36
+ else {
37
+ store = createMemorySessionStore();
38
+ checkpoints = createMemoryCheckpointStore();
39
+ }
40
+ const tools = createToolRegistry(createCodingTools(config.cwd));
41
+ const prismAgent = createAgent({
42
+ id: "prism-acp-agent",
43
+ model: { provider: "mock", model: "mock" },
44
+ provider: options.provider ?? createMockProvider(),
45
+ store,
46
+ tools,
47
+ ownership,
48
+ runState: { checkpoints, definitionRevision: "1", interruptBeforeTool: true },
49
+ });
50
+ return createPrismAcpAgent({
51
+ name: "Prism ACP Agent",
52
+ authorize: () => ({ ownership }),
53
+ sessionFactory: async (input) => ({
54
+ session: prismAgent.createSession({ id: input.sessionId ?? randomUUID() }),
55
+ agentId: "prism-acp-agent",
56
+ tools,
57
+ }),
58
+ lifecycle: createAgentRunLifecycle({
59
+ checkpoints,
60
+ resolveAgent: () => ({ agent: prismAgent, definitionRevision: "1" }),
61
+ }),
62
+ mcp: config.mcp ? { transports: ["http", "sse"], select: ({ servers }) => selectMcpServers(config.mcp.allow, servers) } : undefined,
63
+ modes: config.modes
64
+ ? { modes: config.modes.modes, ...(config.modes.defaultModeId !== undefined ? { defaultModeId: config.modes.defaultModeId } : {}) }
65
+ : undefined,
66
+ configOptions: config.configOptions ? { options: config.configOptions.options } : undefined,
67
+ limits: config.limits,
68
+ });
69
+ }
70
+ //# sourceMappingURL=index.js.map
package/package.json ADDED
@@ -0,0 +1,67 @@
1
+ {
2
+ "name": "@arnilo/prism-acp-agent",
3
+ "version": "0.2.8",
4
+ "description": "Spawnable ACP agent: serves createPrismAcpAgent over stdio from a config file.",
5
+ "type": "module",
6
+ "main": "./dist/src/index.js",
7
+ "types": "./dist/src/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/src/index.d.ts",
11
+ "default": "./dist/src/index.js"
12
+ }
13
+ },
14
+ "bin": {
15
+ "prism-acp-agent": "dist/bin/prism-acp-agent.js"
16
+ },
17
+ "files": [
18
+ "dist",
19
+ "!dist/**/__tests__",
20
+ "!dist/**/*.map",
21
+ "README.md",
22
+ "CHANGELOG.md"
23
+ ],
24
+ "scripts": {
25
+ "build": "node ../../scripts/with-build-lock.mjs tsc -p tsconfig.json",
26
+ "typecheck": "tsc -p tsconfig.json --noEmit",
27
+ "test": "node ../../scripts/with-build-lock.mjs node --test dist/src/__tests__/*.test.js",
28
+ "pack:dry-run": "npm pack --dry-run"
29
+ },
30
+ "dependencies": {
31
+ "@agentclientprotocol/sdk": "1.3.0",
32
+ "@arnilo/prism-coding-agent": "0.2.8",
33
+ "@arnilo/prism-session-store-sqlite": "0.2.8"
34
+ },
35
+ "peerDependencies": {
36
+ "@arnilo/prism": "0.2.8",
37
+ "@arnilo/prism-ag-ui": "0.2.8"
38
+ },
39
+ "devDependencies": {
40
+ "@arnilo/prism": "file:../..",
41
+ "@arnilo/prism-ag-ui": "file:../ag-ui"
42
+ },
43
+ "engines": {
44
+ "node": ">=20"
45
+ },
46
+ "license": "MIT",
47
+ "repository": {
48
+ "type": "git",
49
+ "url": "git+https://github.com/ashiqrniloy/prism.git",
50
+ "directory": "packages/acp-agent"
51
+ },
52
+ "bugs": {
53
+ "url": "https://github.com/ashiqrniloy/prism/issues"
54
+ },
55
+ "homepage": "https://github.com/ashiqrniloy/prism/tree/main/packages/acp-agent#readme",
56
+ "keywords": [
57
+ "prism",
58
+ "acp",
59
+ "agent",
60
+ "stdio",
61
+ "mcp"
62
+ ],
63
+ "sideEffects": false,
64
+ "publishConfig": {
65
+ "access": "public"
66
+ }
67
+ }