@arnilo/prism 0.2.9 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,3 +1,15 @@
1
+ ## [0.3.0] - 2026-08-20
2
+
3
+ ### Added
4
+ - **Release 0.3.0 (plans 030, 031)** is the final lockstep cut and first independent-versioning line. The graph contains 57 publishable manifests; internal first-party ranges use `^0.3.0`, Decision B permits changed packages to patch/minor independently inside `<0.4.0`, and later publication uses `@arnilo/<package>@<version>` tags.
5
+ - Optional `@arnilo/prism-antigravity-agent` delegates autonomous coding sessions to the official Google Antigravity CLI (`agy`) with per-run loopback HTTP MCP capability exposure, AG-UI timeline projection, secret redaction, and `--conversation` continuation. Host owns the official binary and `agy login` authentication state.
6
+ - Optional `@arnilo/prism-computer-use-linux` wraps a host-owned Linux `computer-use-linux` MCP binary. DeviceAdapter admission is deny-by-default, setup tools are opt-in, mutating calls require approval/ExecutionPolicy, results are bounded and untrusted, input is serialized, and the package is omitted from umbrellas.
7
+ - Coding/ACP closeouts: `read.findText`, visible fuzzy edit outcomes and nearby miss context, ACP editor-buffer filesystem operations, spawnable per-session coding registries, and delete/move result locations.
8
+
9
+ ### Changed
10
+ - Release automation keeps explicit `--lockstep --version 0.3.0` for the final cut, then defaults to changed-package validation/publication and package tags. No Changesets or new core runtime dependency.
11
+ - No persisted store migration. Live-service canaries and delegated Cursor adapter remain later demand-gated 0.3.x work.
12
+
1
13
  ## [0.2.9] - 2026-08-19
2
14
 
3
15
  ### Changed
package/README.md CHANGED
@@ -4,7 +4,9 @@
4
4
  bring their tools, providers, credentials, storage, and UI; Prism supplies the
5
5
  common contracts, registries, agent/session runtime, replaceable input/prompt
6
6
  and compaction strategies, CLI/RPC adapters, and first-party provider/compaction
7
- packages. Prism defines contracts, not apps.
7
+ packages. The current 0.3.0 line contains 56 publishable manifests, including
8
+ optional Linux desktop control and independent package versioning after the final
9
+ lockstep cut. Prism defines contracts, not apps.
8
10
 
9
11
  ## Current scope
10
12
 
@@ -18,9 +20,10 @@ packages. Prism defines contracts, not apps.
18
20
  OpenAI/OpenRouter use best-effort explicit cache hints, NeuralWatt uses
19
21
  best-effort implicit prefix caching, and other providers have route/model-specific
20
22
  or no cache-control support; see [docs/provider-caching.md](docs/provider-caching.md).
21
- - **First-party packages**: fourteen provider adapters, two compaction strategies,
23
+ - **First-party packages**: seventeen provider adapters, two compaction strategies,
22
24
  coding tools/security, JSON Schema validation, MCP, workflows, OpenTelemetry,
23
- encrypted credentials, SQLite/PostgreSQL persistence, and manifest-only install profiles.
25
+ encrypted credentials, SQLite/PostgreSQL persistence, Linux desktop control,
26
+ and manifest-only install profiles.
24
27
  - **Tools, context, skills**: host-owned tool registry with allow/deny filtering
25
28
  and dispatch, context providers, and a skill registry with progressive
26
29
  disclosure.
@@ -56,7 +59,7 @@ npm install @arnilo/prism @arnilo/prism-provider-openai # core + one provider
56
59
  npm install @arnilo/prism-base # core + compaction + validation
57
60
  npm install @arnilo/prism-code @arnilo/prism-provider-openai # coding-agent profile
58
61
  npm install @arnilo/prism-sdk @arnilo/prism-provider-openai # application profile
59
- npm install @arnilo/prism-all # broad umbrella (21 direct / 44 transitive packages)
62
+ npm install @arnilo/prism-all # broad umbrella (21 direct / 47 workspace packages)
60
63
  npm install @arnilo/prism-server @arnilo/prism-workflows # optional Web API boundary
61
64
  npm install @arnilo/prism-supervisor # optional local delegation + A2A 1.0
62
65
  npm install @arnilo/prism-web-tools # optional bounded Brave/Exa/Firecrawl research
@@ -168,6 +171,8 @@ printf '{"id":"1","command":"prompt","params":{"input":"Hi"}}\n' \
168
171
  | `@arnilo/prism-provider-vertex` | Google Vertex provider |
169
172
  | `@arnilo/prism-provider-ai-sdk` | AI SDK interoperability adapter |
170
173
  | `@arnilo/prism-browser` | optional host-wired Playwright browser automation (not core; not auto-activated) |
174
+ | `@arnilo/prism-computer-use-linux` | optional Linux desktop-control tools over a host-owned `computer-use-linux` MCP binary |
175
+ | `@arnilo/prism-antigravity-agent` | optional Antigravity CLI delegated agent adapter with per-run Prism MCP capability exposure |
171
176
  | `@arnilo/prism-compaction-llm` | provider-backed compaction strategy |
172
177
  | `@arnilo/prism-compaction-observational-memory` | source-backed memory + recall tool |
173
178
  | `@arnilo/prism-coding-agent` | bounded shell/read/write/edit tools |
@@ -186,7 +191,7 @@ printf '{"id":"1","command":"prompt","params":{"input":"Hi"}}\n' \
186
191
  | `@arnilo/prism-base` | profile: core + compaction + JSON Schema validation |
187
192
  | `@arnilo/prism-code` | profile: base + coding tools/security + MCP |
188
193
  | `@arnilo/prism-sdk` | profile: base + workflows + MCP + credentials + OpenTelemetry |
189
- | `@arnilo/prism-all` | broad umbrella: 21 first-party packages (47 transitive) across runtime, capability, provider, and persistence — omits document-reader, OpenAPI tools, NATS, Caveman, Ponytail, and Impeccable |
194
+ | `@arnilo/prism-all` | broad umbrella: 21 first-party packages (47 transitive) across a 47-package workspace closure — omits document-reader, OpenAPI tools, NATS, Caveman, Ponytail, Impeccable, computer-use-linux, and antigravity-agent |
190
195
 
191
196
  ## Scripts
192
197
 
@@ -108,6 +108,36 @@ export interface ToolExecutionMetadata {
108
108
  readonly durationMs: number;
109
109
  readonly status: ToolCallStatus;
110
110
  }
111
+ export type DelegatedAgentStepState = "active" | "done" | "error";
112
+ export type DelegatedAgentStepKind = "assistant" | "tool" | "subagent" | "checkpoint" | "unknown";
113
+ /** Token counters only; delegated adapters must never put thought text in this shape. */
114
+ export interface DelegatedAgentStepUsage {
115
+ readonly inputTokens?: number;
116
+ readonly outputTokens?: number;
117
+ readonly thinkingTokens?: number;
118
+ readonly cacheReadTokens?: number;
119
+ readonly cacheWriteTokens?: number;
120
+ readonly totalTokens?: number;
121
+ }
122
+ /** Safe delegated timeline metadata. Raw arguments, results, paths, URIs, and event bodies are not fields. */
123
+ export interface DelegatedAgentStep {
124
+ readonly type: "delegated_agent_step";
125
+ readonly sessionId: string;
126
+ readonly runId: string;
127
+ readonly adapterId: string;
128
+ readonly externalConversationId: string;
129
+ readonly stepIndex: number;
130
+ readonly state: DelegatedAgentStepState;
131
+ readonly kind: DelegatedAgentStepKind;
132
+ readonly durationMs?: number;
133
+ readonly usage?: DelegatedAgentStepUsage;
134
+ readonly toolName?: string;
135
+ readonly subagentType?: string;
136
+ readonly detail?: {
137
+ readonly referenceId?: string;
138
+ readonly label?: string;
139
+ };
140
+ }
111
141
  export type AgentFinishReason = "turn_limit" | "token_limit" | "refusal";
112
142
  export type AgentEvent = {
113
143
  readonly type: "agent_started";
@@ -176,7 +206,7 @@ export type AgentEvent = {
176
206
  readonly sessionId: string;
177
207
  readonly runId: string;
178
208
  readonly message: Message;
179
- } | {
209
+ } | DelegatedAgentStep | {
180
210
  readonly type: "tool_execution_started";
181
211
  readonly sessionId: string;
182
212
  readonly runId: string;
@@ -0,0 +1,20 @@
1
+ import type { DelegatedAgentStep } from "./contracts-protocol.js";
2
+ export declare const MAX_DELEGATED_AGENT_EVENT_BYTES: number;
3
+ export declare const MAX_DELEGATED_AGENT_ID_BYTES = 512;
4
+ export declare const MAX_DELEGATED_AGENT_NAME_BYTES = 256;
5
+ export declare const MAX_DELEGATED_AGENT_STEP_INDEX = 1000000;
6
+ export declare const MAX_DELEGATED_AGENT_DURATION_MS: number;
7
+ export declare const MAX_DELEGATED_AGENT_TOKEN_COUNT = 1000000000000;
8
+ export interface DelegatedAgentStepInput extends Omit<DelegatedAgentStep, "type" | "kind" | "state"> {
9
+ readonly kind: string;
10
+ readonly state: string;
11
+ }
12
+ export declare class DelegatedAgentStepError extends Error {
13
+ readonly code = "ERR_PRISM_DELEGATED_AGENT_STEP";
14
+ constructor(message: string);
15
+ }
16
+ /**
17
+ * Builds the only safe core shape for delegated timeline metadata. Unknown step
18
+ * kinds become `unknown`; unbounded or malformed identity/counter fields fail closed.
19
+ */
20
+ export declare function createDelegatedAgentStep(input: DelegatedAgentStepInput): DelegatedAgentStep;
@@ -0,0 +1,99 @@
1
+ export const MAX_DELEGATED_AGENT_EVENT_BYTES = 64 * 1024;
2
+ export const MAX_DELEGATED_AGENT_ID_BYTES = 512;
3
+ export const MAX_DELEGATED_AGENT_NAME_BYTES = 256;
4
+ export const MAX_DELEGATED_AGENT_STEP_INDEX = 1_000_000;
5
+ export const MAX_DELEGATED_AGENT_DURATION_MS = 24 * 60 * 60 * 1000;
6
+ export const MAX_DELEGATED_AGENT_TOKEN_COUNT = 1_000_000_000_000;
7
+ export class DelegatedAgentStepError extends Error {
8
+ code = "ERR_PRISM_DELEGATED_AGENT_STEP";
9
+ constructor(message) {
10
+ super(message);
11
+ this.name = "DelegatedAgentStepError";
12
+ }
13
+ }
14
+ /**
15
+ * Builds the only safe core shape for delegated timeline metadata. Unknown step
16
+ * kinds become `unknown`; unbounded or malformed identity/counter fields fail closed.
17
+ */
18
+ export function createDelegatedAgentStep(input) {
19
+ if (!input || typeof input !== "object")
20
+ throw invalid("event");
21
+ const state = input.state;
22
+ if (state !== "active" && state !== "done" && state !== "error")
23
+ throw invalid("state");
24
+ const kind = normalizeKind(input.kind);
25
+ if (!Number.isSafeInteger(input.stepIndex) || input.stepIndex < 0 || input.stepIndex > MAX_DELEGATED_AGENT_STEP_INDEX) {
26
+ throw invalid("stepIndex");
27
+ }
28
+ const event = {
29
+ type: "delegated_agent_step",
30
+ sessionId: boundedText(input.sessionId, "sessionId", MAX_DELEGATED_AGENT_ID_BYTES),
31
+ runId: boundedText(input.runId, "runId", MAX_DELEGATED_AGENT_ID_BYTES),
32
+ adapterId: boundedText(input.adapterId, "adapterId", MAX_DELEGATED_AGENT_ID_BYTES),
33
+ externalConversationId: boundedText(input.externalConversationId, "externalConversationId", MAX_DELEGATED_AGENT_ID_BYTES),
34
+ stepIndex: input.stepIndex,
35
+ state,
36
+ kind,
37
+ ...(input.durationMs === undefined
38
+ ? {}
39
+ : { durationMs: boundedNumber(input.durationMs, "durationMs", MAX_DELEGATED_AGENT_DURATION_MS) }),
40
+ ...(input.usage === undefined ? {} : { usage: normalizeUsage(input.usage) }),
41
+ ...(input.toolName === undefined ? {} : { toolName: boundedText(input.toolName, "toolName", MAX_DELEGATED_AGENT_NAME_BYTES) }),
42
+ ...(input.subagentType === undefined
43
+ ? {}
44
+ : { subagentType: boundedText(input.subagentType, "subagentType", MAX_DELEGATED_AGENT_NAME_BYTES) }),
45
+ ...(input.detail === undefined ? {} : { detail: normalizeDetail(input.detail) }),
46
+ };
47
+ if (utf8Bytes(JSON.stringify(event)) > MAX_DELEGATED_AGENT_EVENT_BYTES)
48
+ throw invalid("event bytes");
49
+ return event;
50
+ }
51
+ function normalizeKind(value) {
52
+ return value === "assistant" || value === "tool" || value === "subagent" || value === "checkpoint" || value === "unknown"
53
+ ? value
54
+ : "unknown";
55
+ }
56
+ function normalizeUsage(value) {
57
+ if (!value || typeof value !== "object" || Array.isArray(value))
58
+ throw invalid("usage");
59
+ const output = {};
60
+ for (const key of ["inputTokens", "outputTokens", "thinkingTokens", "cacheReadTokens", "cacheWriteTokens", "totalTokens"]) {
61
+ const amount = value[key];
62
+ if (amount === undefined)
63
+ continue;
64
+ output[key] = boundedNumber(amount, key, MAX_DELEGATED_AGENT_TOKEN_COUNT);
65
+ }
66
+ return output;
67
+ }
68
+ function normalizeDetail(value) {
69
+ if (!value || typeof value !== "object" || Array.isArray(value))
70
+ throw invalid("detail");
71
+ const referenceId = value.referenceId === undefined ? undefined : boundedOpaque(value.referenceId, "detail.referenceId", MAX_DELEGATED_AGENT_ID_BYTES);
72
+ const label = value.label === undefined ? undefined : boundedText(value.label, "detail.label", MAX_DELEGATED_AGENT_NAME_BYTES);
73
+ return {
74
+ ...(referenceId === undefined ? {} : { referenceId }),
75
+ ...(label === undefined ? {} : { label }),
76
+ };
77
+ }
78
+ function boundedText(value, name, maxBytes) {
79
+ if (typeof value !== "string" || value.length === 0 || /[\0\r\n]/.test(value) || utf8Bytes(value) > maxBytes)
80
+ throw invalid(name);
81
+ return value;
82
+ }
83
+ function boundedOpaque(value, name, maxBytes) {
84
+ if (typeof value !== "string" || /[\\/:]/.test(value))
85
+ throw invalid(name);
86
+ return boundedText(value, name, maxBytes);
87
+ }
88
+ function boundedNumber(value, name, max) {
89
+ if (typeof value !== "number" || !Number.isSafeInteger(value) || value < 0 || value > max)
90
+ throw invalid(name);
91
+ return value;
92
+ }
93
+ function utf8Bytes(value) {
94
+ return new TextEncoder().encode(value).byteLength;
95
+ }
96
+ function invalid(field) {
97
+ return new DelegatedAgentStepError(`Invalid delegated agent step ${field}`);
98
+ }
99
+ //# sourceMappingURL=delegated-agent-step.js.map
package/dist/index.d.ts CHANGED
@@ -37,6 +37,8 @@ export type { DeviceAdapter, DeviceAdmitRequest, DeviceChunkResult, DeviceConfor
37
37
  export { acceptDeviceChunk, assertDeviceAdmit, DEFAULT_DEVICE_MAX_CHUNK_BYTES, DEFAULT_DEVICE_MAX_CONCURRENT_SESSIONS, DevicePolicyError, HARD_DEVICE_MAX_CHUNK_BYTES, HARD_DEVICE_MAX_CONCURRENT_SESSIONS, redactDeviceTelemetry, resolveDevicePolicy, runDevicePolicyConformance, } from "./devices.js";
38
38
  export type { EventMultiplexer, EventMultiplexerOptions, EventOverflowInfo, EventOverflowPolicy } from "./event-multiplexer.js";
39
39
  export { createEventMultiplexer, EVENT_MULTIPLEXER_SINGLE_CONSUMER_CODE, EventMultiplexerError } from "./event-multiplexer.js";
40
+ export { createDelegatedAgentStep, DelegatedAgentStepError, MAX_DELEGATED_AGENT_DURATION_MS, MAX_DELEGATED_AGENT_EVENT_BYTES, MAX_DELEGATED_AGENT_ID_BYTES, MAX_DELEGATED_AGENT_NAME_BYTES, MAX_DELEGATED_AGENT_STEP_INDEX, MAX_DELEGATED_AGENT_TOKEN_COUNT, } from "./delegated-agent-step.js";
41
+ export type { DelegatedAgentStepInput } from "./delegated-agent-step.js";
40
42
  export type { ExecutionAction, ExecutionDecision, ExecutionPolicy, ExecutionRisk } from "./execution-policy.js";
41
43
  export { applyExecutionDecision, assertExecutionAllowed, checkExecution, ExecutionDeniedError } from "./execution-policy.js";
42
44
  export type { ExtensionErrorPolicy, ExtensionEventBus, ExtensionEventHandler, ExtensionKernel, ExtensionKernelOptions, ExtensionLoadPolicy, LoadedExtension, } from "./extensions.js";
@@ -111,5 +113,5 @@ export { createToolParameterValidator, createToolRegistry, dispatchToolCall, fil
111
113
  export type { ResolvedUseCaseModel, ResolveUseCaseModelInput, UseCaseModelBinding, } from "./use-case-model.js";
112
114
  export { resolveUseCaseModel, resolveUseCaseModelBinding, useCaseCredentialProviderId, } from "./use-case-model.js";
113
115
  export declare const name = "prism";
114
- export declare const version = "0.2.9";
116
+ export declare const version = "0.3.0";
115
117
  export declare const description = "Agent harness for AI providers, agents, sessions, and tools.";
package/dist/index.js CHANGED
@@ -19,6 +19,7 @@ export { CONVERSATION_METADATA_KEY, ConversationError, conversationMarkerMetadat
19
19
  export { createChainedCredentialResolver, createEnvCredentialResolver, createExplicitCredentialResolver, createMemoryCredentialStore, refreshOAuthCredential, resolveCredentialValue, revokeOAuthCredential, } from "./credentials.js";
20
20
  export { acceptDeviceChunk, assertDeviceAdmit, DEFAULT_DEVICE_MAX_CHUNK_BYTES, DEFAULT_DEVICE_MAX_CONCURRENT_SESSIONS, DevicePolicyError, HARD_DEVICE_MAX_CHUNK_BYTES, HARD_DEVICE_MAX_CONCURRENT_SESSIONS, redactDeviceTelemetry, resolveDevicePolicy, runDevicePolicyConformance, } from "./devices.js";
21
21
  export { createEventMultiplexer, EVENT_MULTIPLEXER_SINGLE_CONSUMER_CODE, EventMultiplexerError } from "./event-multiplexer.js";
22
+ export { createDelegatedAgentStep, DelegatedAgentStepError, MAX_DELEGATED_AGENT_DURATION_MS, MAX_DELEGATED_AGENT_EVENT_BYTES, MAX_DELEGATED_AGENT_ID_BYTES, MAX_DELEGATED_AGENT_NAME_BYTES, MAX_DELEGATED_AGENT_STEP_INDEX, MAX_DELEGATED_AGENT_TOKEN_COUNT, } from "./delegated-agent-step.js";
22
23
  export { applyExecutionDecision, assertExecutionAllowed, checkExecution, ExecutionDeniedError } from "./execution-policy.js";
23
24
  export { createExtensionEventBus, createExtensionKernel } from "./extensions.js";
24
25
  export { createMemoryRunFeedbackStore, prepareRunFeedback, RunFeedbackError, requireRunFeedbackOwnership, runFeedbackPageLimit, } from "./feedback.js";
@@ -61,6 +62,6 @@ export { DEFAULT_TOOL_RESULT_FOLD_MAX_SUMMARY_BYTES, DEFAULT_TOOL_RESULT_FOLD_MI
61
62
  export { createToolParameterValidator, createToolRegistry, dispatchToolCall, filterTools } from "./tools.js";
62
63
  export { resolveUseCaseModel, resolveUseCaseModelBinding, useCaseCredentialProviderId, } from "./use-case-model.js";
63
64
  export const name = "prism";
64
- export const version = "0.2.9";
65
+ export const version = "0.3.0";
65
66
  export const description = "Agent harness for AI providers, agents, sessions, and tools.";
66
67
  //# sourceMappingURL=index.js.map
@@ -1,6 +1,6 @@
1
1
  # 0.1.0 / 1.0 Readiness Gates
2
2
 
3
- Status: **0.2.8** is the current release line (the 0.2.x review-remediation line: fail-closed runtime/sandbox security, provider completion and outbound trust boundaries, concurrent-state/durability integrity, build/coverage/release-evidence integrity, package/documentation/compatibility truth, maintainability and bounded performance, fully featured coding-agent readiness, enterprise ERP production readiness, ACP adoption fixes); **0.1.7** was the terminal 0.1.x baseline; **1.0** readiness remains operator-gated, not automatic.
3
+ Status: **0.3.0** is the current release line (the final 0.3.x lockstep cut: Linux desktop wrapper, coding/ACP closeouts, and independent package versions with Decision B `^0.3.0` ranges); **0.1.7** was the terminal 0.1.x baseline; **1.0** readiness remains operator-gated, not automatic.
4
4
 
5
5
  This page distills runnable readiness gates into one command-per-gate table.
6
6
  The **Last evidence** column records the 0.1.0-tree snapshot (plan 012 Tasks
@@ -20,16 +20,16 @@ Historical release lines (0.0.16 floor → 0.0.27 Phase 10 ACP interop → 0.1.0
20
20
  keep their per-phase evidence in the pages above; this page records the 0.2.6
21
21
  snapshot (plan 026) with the 0.1.x tables below as the historical record.
22
22
 
23
- ## Current line (0.2.9)
23
+ ## Current line (0.3.0)
24
24
 
25
25
  | Item | Status |
26
26
  |---|---|
27
- | Published graph | **55** publishable manifests at exact **0.2.9** (root + 54 workspace packages: 17 provider adapters + 10 `prism-*` family/profile + 27 capability; generated by `node scripts/package-truth.mjs` → `scripts/package-truth.json`) |
28
- | Current-line cut | The 0.2.x review-remediation line, additive-only vs the frozen 0.1.x contract: 0.2.0 fail-closed runtime/sandbox, 0.2.1 trust boundaries, 0.2.2 concurrent-state, 0.2.3 evidence integrity, 0.2.4 package truth, 0.2.5 maintainability, 0.2.6 coding-agent readiness, 0.2.7 ERP, 0.2.8 ACP adoption fixes, plus 0.2.9 provider adoption (DeepSeek / xAI SuperGrok OAuth / ClinePass), `@arnilo/prism-impeccable`, Ponytail 4.9.0, Caveman v2.1 extras |
29
- | Upgrade path | `docs/migration.md` `0.2.8 → 0.2.9` (additive; no store migration; rollback = restore 0.2.8 manifests/tag); store-compatible throughout 0.2.x |
30
- | Compat promise | Additive-only vs the frozen 0.1.x contract; `scripts/compat-baseline` regenerated at 0.2.9 (version literal + additive provider/OAuth/impeccable exports), zero breaking deltas |
31
- | Security policy | `npm audit --audit-level=moderate` 0 at 0.2.9; threat-suites legs (phase8–11 + phase20–26) green; SuperGrok live login `PRISM_LIVE_XAI_OAUTH` is protected, never a silent pass |
32
- | Docs freeze | tripwires green including the canonical manifest-count tripwire (50/49/14/9/26), the plan 024 package-truth tests (generator reproducibility + artifact equality + closure asserts + derived docs truth), the plan 025 bounded-accumulation near-limit probe, and the plan 026 freeze tripwires (per-task markers, threat T1–T8 test mapping, exit gate green) |
27
+ | Release graph | **56** publishable manifests at exact **0.3.0** (root + 55 workspace packages: 17 provider adapters + 10 `prism-*` family/profile + 28 capability; generated by `node scripts/package-truth.mjs` → `scripts/package-truth.json`; npm publication remains the operator handoff) |
28
+ | Current-line cut | The 0.3.x line starts with the final lockstep cut: optional host-owned Linux desktop control, coding/ACP tool closeouts, and independent package publication after the cut; live canaries and delegated agents remain later demand-gated work |
29
+ | Upgrade path | `docs/migration.md` `0.2.9 → 0.3.0` (additive; no store migration; rollback = restore 0.2.9 manifests/tag); internal first-party ranges become `^0.3.0` |
30
+ | Compat promise | Additive-only vs the frozen 0.2.9 baseline; package peers use Decision B's `^0.3.0` caret window and `scripts/compat-baseline` remains the reviewed declaration gate |
31
+ | Security policy | `npm audit --audit-level=moderate` 0 target at 0.3.0; desktop admission remains deny-by-default, mutators require approval + `ExecutionPolicy`, and package tags publish only changed packages |
32
+ | Docs freeze | tripwires green including the 56-package truth graph, Decision B range policy, the plan 030 freeze/release tests, coding/ACP tool regressions, and the host-owned desktop wrapper's fail-closed package/docs gates |
33
33
  | 0.1.x line | **0.1.7** (plan 019) is the terminal 0.1.x baseline; the 0.1.1 table below keeps the plan 013 snapshot; the 0.1.0 table keeps the plan 012 snapshot; the **0.0.16** values remain the historical network-free floor |
34
34
 
35
35
  ## Previous line (0.1.1)
package/docs/acp.md CHANGED
@@ -46,7 +46,7 @@ In-stream `SessionUpdate`s:
46
46
  | Assistant text | `agent_message_chunk` |
47
47
  | Assistant thinking | `agent_thought_chunk` (same `messageId` scheme as text; through the shared redactor and byte caps) |
48
48
  | Tool lifecycle | `tool_call` / `tool_call_update` (title/status/content) — `tool_call.kind` comes from the session's tool registry `kind` metadata when present (B4), else the name heuristic |
49
- | Tool result, projected | `tool_call_update` with `locations` (≤ `acpLocationsPerUpdate`) and/or a `diff` block (≤ `acpDiffBytes`) — only from `AgUiProjection.toolLocations`/`toolDiff` allow-lists, at `finish()`. `toolResult` may return a string (text content) or `{ type: "image", data, mimeType }` (F8) — the mapper wraps the image as `{ type: "content", content: { type: "image", data, mimeType } }` and drops payloads over `acpImageBytes` (never truncated). Opt-in turnkey: `createCodingToolProjection()` (F7) recognizes first-party `edit` (path + unified patch as `newText`, `firstChangedLine` location) and `write` (path location only — result has no file body) results; default remains deny-by-default. |
49
+ | Tool result, projected | `tool_call_update` with `locations` (≤ `acpLocationsPerUpdate`) and/or a `diff` block (≤ `acpDiffBytes`) — only from `AgUiProjection.toolLocations`/`toolDiff` allow-lists, at `finish()`. `toolResult` may return a string (text content) or `{ type: "image", data, mimeType }` (F8) — the mapper wraps the image as `{ type: "content", content: { type: "image", data, mimeType } }` and drops payloads over `acpImageBytes` (never truncated). Opt-in turnkey: `createCodingToolProjection()` (F7) recognizes first-party `edit` (path + unified patch as `newText`, `firstChangedLine` location), `write` and `delete` (metadata path locations), and `move` (destination `metadata.to` location) results; moves never emit diffs, and default remains deny-by-default. |
50
50
  | Provider usage | `usage_update` (only when the `capabilities.usage.contextWindow` seam reports a valid window — absent/undefined/throw ⇒ the update is omitted, never `size = used`) |
51
51
  | Run-level failure | No transcript chunk — the `session/prompt` request rejects with `ERR_PRISM_ACP_RUN` (redacted, byte-capped message). Retryable provider-turn failures stay silent and may recover; only a terminal `error` event fails the request. |
52
52
  | Run stop reason | `session/prompt` returns the SDK `StopReason` (F4): `cancelled` when the run was aborted, `max_turn_requests` for the tool-round ceiling (`finishReason: "turn_limit"`), `max_tokens` for `"token_limit"`, `refusal` for `"refusal"`, else `end_turn`. The generic `finishReason` field is set on `agent_finished` by loop strategies (single-shot records `turn_limit` at the `maxToolRounds` ceiling); `token_limit`/`refusal` have no core producer yet — the mapping is ready. |
@@ -112,7 +112,8 @@ const agent = createPrismAcpAgent({
112
112
 
113
113
  - **Seam = capability.** Wiring `sessions.load` advertises `loadSession`; removing it withdraws the method. There is no separate capability flag to keep in sync — the freeze manifest's advertise-when matrix is enforced by construction and asserted by `scripts/phase10-conformance.test.mjs`.
114
114
  - **Transcript replay (F2).** When `sessions.transcript` is wired, `session/load` and `session/resume` replay `user_message_chunk`/`agent_message_chunk` text chunks (from `SessionEntry`s with `kind: "message"` and a user/assistant role, text blocks only) before returning `sessionState`. Each chunk passes the shared redactor and is truncated at `maxTextBytes`; replay stops at `maxReplayEvents` chunks and counts against the stream event/byte caps (an oversized transcript fails the load/resume request closed). Absent seam = no replay, behavior unchanged.
115
- - **Client fs/terminal are adapters, not a second implementation.** `AcpClientFilesystem` / `AcpClientTerminals` wrap the client's `fs/*` and `terminal/*` methods behind the Phase 9 `ProcessSession`-flavored interfaces; the agent pre-generates the session id so terminal requests can carry it. Host repo operations remain default when the client fs is absent.
115
+ - **Client fs/terminal are adapters, not a second implementation.** `AcpClientFilesystem` / `AcpClientTerminals` wrap the client's `fs/*` and `terminal/*` methods behind the Phase 9 `ProcessSession`-flavored interfaces; the agent pre-generates the session id so terminal requests can carry it. `createAcpFilesystemOperations` from `@arnilo/prism-coding-agent` maps that filesystem seam onto the coding tools' `read`/`write`/`edit` operations. This editor-buffer mode is intentionally hybrid: `repo_list`, `repo_search`, `glob`, `delete`, and `move` remain disk-backed unless the host supplies separate operations; binary/image/document handling never falls back to local disk. Host repo operations remain default when the client fs is absent.
116
+ - **Spawnable ACP coding registry (Task 6).** `@arnilo/prism-acp-agent` wires `createAcpClientFilesystem` and creates a separate coding tool registry per ACP session when the client advertises `fs/read_text_file` or `fs/write_text_file`. That session's `read`/`write`/`edit` operations use editor buffers; without fs advertisement, the existing disk registry is used. `shell`, repository search/list/glob, `delete`, and `move` remain disk-backed in this hybrid mode. Durable approvals resolve the same per-session agent, so one session cannot resume through another session's buffer adapter.
116
117
  - **Modes and config options are a pure host overlay.** The agent stores only a thin per-session registry; `apply`/`onChange` hooks narrow the host's own behavior. Mode switches can narrow or host-authorized widen — never a parallel policy evaluator, never a client-enabled tool.
117
118
  - **Lifecycle wiring.** Pass your `createCodingLifecycleEmitter()` as `coding.lifecycle`; `file_changed` etc. then flow to streaming sessions. `configuration_changed` broadcasts `config_option_update` (agent-message fallback if the SDK rejects the kind).
118
119
  - **Stream budgets.** Every lifecycle update counts against the same per-run stream event/byte budget as prompt updates; overflowing closes the update, never the run.
@@ -151,7 +152,7 @@ const agent = createPrismAcpAgent({
151
152
  - **Deny-closed by default.** Unknown mode ids, unadvertised methods, unprojected lifecycle events, oversize diffs/locations/media, thrown projection hooks, and failed elicitation all fail closed. Raw tool arguments/results are never sent unless a projection allow-list says otherwise.
152
153
  - **Slash commands (F9).** `commands.list` is a host-owned slash-command list (not derived from the tool registry). The agent emits `available_commands_update` on session start (`session/new`, `session/load`, `session/resume`). Mid-session refresh is not in this release — re-list by starting a session. Names, descriptions, and input hints pass the shared redactor; the list is sliced at `acpCommandsPerUpdate`. Absent seam or a thrown list ⇒ no update.
153
154
  - **Projected images (F8).** `AgUiProjection.toolResult` may return `{ type: "image", data, mimeType }` (return-type widening — existing string returns stay valid). The mapper emits `{ type: "content", content: { type: "image", data, mimeType } }` (SDK v1 `ToolCallContent` has no top-level image variant). `data` is the host-supplied base64; it is not redacted and not truncated — payloads over `acpImageBytes` are dropped. Default (no hook / non-image return) emits no image.
154
- - **Coding-tool projection (F7).** `createCodingToolProjection({ maxDiffBytes? })` is an opt-in `AgUiProjection` for first-party `@arnilo/prism-coding-agent` `edit`/`write` results: `edit` → `toolDiff` (`path` + unified `patch` as `newText`) and `toolLocations` (`path` + `firstChangedLine`); `write` → `toolLocations` (`path` only — write metadata has no file body, so no honest diff; use `file_changed` + `fileDiff` when bodies are needed). Pass as `projection: createCodingToolProjection()` on the agent/mapper. Mapper still redacts and enforces `acpDiffBytes` / `acpLocationsPerUpdate`; optional `maxDiffBytes` pre-truncates the patch so a slightly-oversize edit is shortened instead of dropped. Without the factory, behavior is unchanged (deny-by-default).
155
+ - **Coding-tool projection (F7).** `createCodingToolProjection({ maxDiffBytes? })` is an opt-in `AgUiProjection` for first-party `@arnilo/prism-coding-agent` results: `edit` → `toolDiff` (`path` + unified `patch` as `newText`) and `toolLocations` (`path` + `firstChangedLine`); `write` and `delete` → `toolLocations` (`path` only); `move` → destination `toolLocations` (`metadata.to`, with `from` fallback). No delete/move diff is fabricated. Pass as `projection: createCodingToolProjection()` on the agent/mapper. Mapper still redacts and enforces `acpDiffBytes` / `acpLocationsPerUpdate`; optional `maxDiffBytes` pre-truncates the patch so a slightly-oversize edit is shortened instead of dropped. Without the factory, behavior is unchanged (deny-by-default).
155
156
  - **No secrets.** Updates carry no raw file bodies, terminal output is capped by the Phase 9 chunk budget, and the shared redactor is applied before anything leaves the host. `permission_denied` never includes raw args.
156
157
  - **Performance.** The adapter is O(1) per update with no unbounded buffering; p95 targets (fs round trip 250 ms, mode switch 250 ms, terminal chunk ack 1000 ms, prompt first update 2000 ms, prompt end 30 s) are recorded by `scripts/benchmark-0.0.27.mjs` and gated in `scripts/budgets.json` `phase10`.
157
158
 
package/docs/ag-ui.md CHANGED
@@ -44,7 +44,9 @@ The handler accepts only `POST` JSON validated with official AG-UI `RunAgentInpu
44
44
 
45
45
  ## Outputs / response / events
46
46
 
47
- The handler returns `text/event-stream`, one `data: <AG-UI event>\n\n` frame per output. Mapper lifecycle is ordered: `RUN_*`, `STEP_*`, `TEXT_MESSAGE_*`, and `TOOL_CALL_*` are deterministic Prism mappings. Host projectors may additionally prove and emit `STATE_SNAPSHOT`/`STATE_DELTA`, `MESSAGES_SNAPSHOT`, `ACTIVITY_*`, current `REASONING_*`, `RAW`, and named `CUSTOM` values. All values revalidate against official `EventSchemas`; deprecated `THINKING_*` and convenience chunk events are not produced. Active message/tool/reasoning/step sequences close before error, interruption, or finish.
47
+ The handler returns `text/event-stream`, one `data: <AG-UI event>\n\n` frame per output. Mapper lifecycle is ordered: `RUN_*`, `STEP_*`, `TEXT_MESSAGE_*`, and `TOOL_CALL_*` are deterministic Prism mappings. Host projectors may additionally prove and emit `STATE_SNAPSHOT`/`STATE_DELTA`, `MESSAGES_SNAPSHOT`, `ACTIVITY_*`, current `REASONING_*`, `RAW`, and named `CUSTOM` values.
48
+
49
+ `delegated_agent_step` maps by default to bounded `ACTIVITY_SNAPSHOT` metadata with activity type `prism.delegated_agent_step`; `includeCustomEvents: true` also emits `CUSTOM prism.delegated_agent_step`. The safe payload contains adapter/conversation identifiers, step index/state/kind, duration, token counts, tool/subagent names, and opaque detail references only. Normal assistant text remains `TEXT_MESSAGE_*`; delegated events never duplicate transcript text. Raw event bodies, tool arguments/results, paths, URIs, logs, and hidden thought text remain absent unless a host explicitly supplies a projection. All values revalidate against official `EventSchemas`; deprecated `THINKING_*` and convenience chunk events are not produced. Active message/tool/reasoning/step sequences close before error, interruption, or finish.
48
50
 
49
51
  A Prism durable `agent_suspended` returns `RUN_FINISHED` with core interrupt id `${runId}:${version}` and a strict `{ decision: "approve" | "deny" }` schema. `projection.interrupt` may attach bounded expiry/metadata or additional host policy interrupts but must retain that core id. Without `interrupts.resume`, one exact entry is required; `cancelled` means deny. An aggregate policy may validate bounded multiple entries, then returns one current-version core decision. Payloads containing `editedArgs`/`args` always deny: Prism does not mutate persisted tool calls. The adapter checks host authorization, selected run, suspended status, and checkpoint version, then calls `AgentRunLifecycle.resumeStream()` once. Claimed/dispatched tools are never replayed.
50
52
 
@@ -122,7 +124,7 @@ See runnable network-free [`examples/ag-ui-server.ts`](../examples/ag-ui-server.
122
124
 
123
125
  All identity, authorization, session/thread mapping, durable checkpoint lookup, persistence selection, replay cursor persistence, transport adaptation, MCP bridge/card configuration, app sandbox DOM, remote A2A task correlation, and optional projection are host-owned. The adapter owns no listener, database, background reconnect loop, credential resolver, or UI state.
124
126
 
125
- `AgUiProjection` is an allow-list. Without a callback, raw tool arguments/results/progress, arbitrary state/patches/transcripts/activity/reasoning/raw events, paths, ACP locations/diffs/terminals/raw I/O, and frontend-supplied tools remain absent. Reasoning signatures do not become AG-UI encrypted values automatically: a host must explicitly provide an already client-encrypted opaque value. `input.project` is also an allow-list: do not merge client state/forwarded props into ownership, identity, tools, permissions, provider options, or media fetch policy.
127
+ `AgUiProjection` is an allow-list. Without a callback, raw tool arguments/results/progress, arbitrary state/patches/transcripts/activity/reasoning/raw events, delegated raw event bodies, paths, ACP locations/diffs/terminals/raw I/O, and frontend-supplied tools remain absent. Reasoning signatures do not become AG-UI encrypted values automatically: a host must explicitly provide an already client-encrypted opaque value. `input.project` is also an allow-list: do not merge client state/forwarded props into ownership, identity, tools, permissions, provider options, or media fetch policy.
126
128
 
127
129
  ### Reasoning encrypted-value helper (FR-3)
128
130
 
@@ -222,4 +224,5 @@ Defaults / hard caps: request 64 KiB / 1 MiB; input 128 / 1024 messages, 32 / 25
222
224
  - [MCP bridge/server](mcp-tools.md): `mcpApps` negotiation, bounded resources, and remote tool trust.
223
225
  - [A2A interoperability](a2a.md): verified rich task client and remote task lifecycle.
224
226
  - [Host security guide](host-security.md): authorization, ownership, redaction, and credential boundaries.
227
+ - [Antigravity delegated agent](antigravity-agent.md): delegated Antigravity CLI execution with timeline step projection.
225
228
  - [Work artifacts and review](work-artifacts-and-review.md): durable artifact service that produces the co-work approval/progress/download-link events projected here.
@@ -2,7 +2,7 @@
2
2
 
3
3
  ## What it does
4
4
 
5
- `AgentEvent` is the single observable stream every `AgentSession` run emits. Subscribers receive normalized, redacted, in-order events covering agent lifecycle, assistant message streaming, tool execution, queue updates, subscriber overflow, compaction, retry, artifact validation/refinement, and terminal errors. The stream is in-memory, live-only, and bounded per subscriber by `SubscribeOptions`; there is no durable queue, no background work, and no extra dependency.
5
+ `AgentEvent` is the single observable stream every `AgentSession` run emits. Subscribers receive normalized, redacted, in-order events covering agent lifecycle, assistant message streaming, delegated-agent activity, tool execution, queue updates, subscriber overflow, compaction, retry, artifact validation/refinement, and terminal errors. The stream is in-memory, live-only, and bounded per subscriber by `SubscribeOptions`; there is no durable queue, no background work, and no extra dependency.
6
6
 
7
7
  Events are emitted by the runtime and by loops through `LoopContext.emit`, both of which route through `redactAgentEvent(event, activeRedactor)` so every payload is secret-redacted before subscribers observe it.
8
8
 
@@ -56,6 +56,7 @@ const subscription = session.subscribe({ maxQueuedEvents: 256, overflow: "close"
56
56
  for await (const event of subscription) {
57
57
  switch (event.type) {
58
58
  case "message_delta": // append event.content
59
+ case "delegated_agent_step": // render bounded external activity
59
60
  case "tool_execution_started": // …
60
61
  case "artifact_failed": // budget exhausted
61
62
  break;
@@ -71,6 +72,7 @@ The `AgentEvent` union (grouped by concern):
71
72
  | Turns | `turn_started`, `turn_finished` |
72
73
  | Provider turns | `provider_turn_started`, `provider_turn_finished` |
73
74
  | Assistant messages | `message_started`, `message_delta`, `message_finished` |
75
+ | Delegated agents | `delegated_agent_step` |
74
76
  | Tool execution | `tool_execution_started`, `tool_execution_progress`, `tool_execution_finished`, `tool_execution_error`, `tool_execution_blocked` |
75
77
  | Guardrails | `guardrail_decision` |
76
78
  | Queue/subscribers | `queue_updated`, `event_subscriber_overflow`, `steer_rejected` |
@@ -95,6 +97,11 @@ Agent / turn / message events:
95
97
  | `turn_started` / `turn_finished` | `sessionId`, `runId`, `turn: number` |
96
98
  | `message_started` / `message_finished` | `sessionId`, `runId`, `message: Message` |
97
99
  | `message_delta` | `sessionId`, `runId`, `content: ContentBlock` (`tool_call_delta` fragments may appear here for live UI streaming; stored messages use final `tool_call` blocks) |
100
+ | `delegated_agent_step` | `sessionId`, `runId`, `adapterId`, `externalConversationId` (≤512 UTF-8 bytes), `stepIndex`, `state`, `kind`, optional `durationMs`, token-only `usage`, `toolName`, `subagentType`, and opaque `detail` references |
101
+
102
+ `delegated_agent_step` is a safe timeline event for an adapter-owned loop. `kind` is one of `assistant`, `tool`, `subagent`, `checkpoint`, or `unknown`; unknown external step kinds normalize to `unknown`. It never carries raw arguments, results, paths, URIs, logs, event bodies, or hidden thought text. `thinkingTokens` is a count only. The constructor and existing event-source default cap keep serialized events at 64 KiB.
103
+
104
+ Adapters should call `createDelegatedAgentStep({ sessionId, runId, adapterId, externalConversationId, stepIndex, state, kind, usage })` rather than forwarding external JSON. The constructor allow-lists fields and fails closed on malformed or oversized identifiers/counters.
98
105
 
99
106
  `message_delta.content.type === "tool_call_delta"` carries `{ index, id?, name?, argumentsText? }`. Treat it as a streaming fragment. The runtime reconstructs and persists a final `tool_call` before executing tools. Deltas missing `id`/`name` at stream end fail the provider turn with `ErrorInfo.code: "incomplete_delta"` (typed `ProviderTransportError`); they never throw a bare `Error`. Malformed JSON with id+name present recovers as a blocked tool result (`invalid_json_arguments`) instead.
100
107