@arnilo/prism 0.2.9 → 0.3.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.
Files changed (77) hide show
  1. package/CHANGELOG.md +39 -0
  2. package/README.md +12 -5
  3. package/dist/agent-loops.js +45 -8
  4. package/dist/agent-session/helpers.js +2 -2
  5. package/dist/cache-helpers.d.ts +11 -0
  6. package/dist/cache-helpers.js +29 -5
  7. package/dist/cli-provider-add.js +2 -1
  8. package/dist/context-budget.js +9 -6
  9. package/dist/contracts-core/agent.d.ts +2 -0
  10. package/dist/contracts-core/provider.d.ts +2 -0
  11. package/dist/contracts-protocol.d.ts +31 -1
  12. package/dist/delegated-agent-step.d.ts +20 -0
  13. package/dist/delegated-agent-step.js +99 -0
  14. package/dist/event-multiplexer.js +0 -4
  15. package/dist/index.d.ts +6 -2
  16. package/dist/index.js +5 -2
  17. package/dist/input.js +19 -11
  18. package/dist/node/session-store-jsonl.js +7 -3
  19. package/dist/providers/openai-compatible.js +2 -1
  20. package/dist/providers/openai-primitives.js +2 -1
  21. package/dist/providers/schema.d.ts +7 -0
  22. package/dist/providers/schema.js +25 -0
  23. package/dist/testing/provider-conformance.d.ts +10 -0
  24. package/dist/testing/provider-conformance.js +37 -0
  25. package/dist/trim-trailing-slashes.d.ts +8 -0
  26. package/dist/trim-trailing-slashes.js +14 -0
  27. package/docs/0.1.0-readiness.md +8 -8
  28. package/docs/acp.md +5 -3
  29. package/docs/ag-ui.md +6 -2
  30. package/docs/agent-events.md +8 -1
  31. package/docs/agent-loops.md +3 -0
  32. package/docs/agent-session-runtime.md +1 -0
  33. package/docs/antigravity-agent.md +207 -0
  34. package/docs/browser-automation.md +1 -0
  35. package/docs/coding-agent-tools.md +32 -4
  36. package/docs/computer-use-linux.md +122 -0
  37. package/docs/database-persistence.md +1 -1
  38. package/docs/device-adapters.md +4 -3
  39. package/docs/graft.md +125 -0
  40. package/docs/host-security.md +3 -1
  41. package/docs/index.md +21 -10
  42. package/docs/input-and-prompt-assembly.md +11 -6
  43. package/docs/instruction-injection.md +1 -1
  44. package/docs/mcp-tools.md +2 -1
  45. package/docs/migration.md +25 -2
  46. package/docs/node-jsonl-session-store.md +1 -1
  47. package/docs/obscura.md +175 -0
  48. package/docs/observability.md +21 -1
  49. package/docs/performance.md +58 -4
  50. package/docs/ponytail.md +1 -1
  51. package/docs/provider-caching.md +13 -11
  52. package/docs/provider-conformance.md +6 -0
  53. package/docs/provider-packages.md +1 -1
  54. package/docs/provider-primitives.md +15 -2
  55. package/docs/providers/ai-sdk.md +1 -1
  56. package/docs/providers/anthropic.md +1 -1
  57. package/docs/providers/azure.md +1 -0
  58. package/docs/providers/bedrock.md +1 -0
  59. package/docs/providers/kimi.md +2 -1
  60. package/docs/providers/openai.md +19 -7
  61. package/docs/providers/opencode-go.md +3 -1
  62. package/docs/providers/openrouter.md +4 -3
  63. package/docs/providers/vertex.md +1 -0
  64. package/docs/public-contracts.md +2 -1
  65. package/docs/rag.md +55 -8
  66. package/docs/release-and-install.md +105 -25
  67. package/docs/server.md +1 -0
  68. package/docs/supervisors.md +3 -2
  69. package/docs/system-prompts.md +1 -1
  70. package/docs/tools.md +1 -1
  71. package/docs/web-tools.md +2 -0
  72. package/docs/wiki.md +140 -0
  73. package/docs/workflows.md +4 -3
  74. package/docs/working-and-semantic-memory.md +20 -0
  75. package/package.json +14 -5
  76. package/docs/api-page-template.md +0 -32
  77. package/docs/release-0.2.7-evidence.md +0 -514
package/CHANGELOG.md CHANGED
@@ -1,3 +1,42 @@
1
+ ## [0.3.1] - 2026-08-29
2
+
3
+ > Root + 28 changed packages move to 0.3.1 in the plan 039 changed-package cut; `@arnilo/prism-rag` moves 0.3.1 → 0.3.2; `@arnilo/prism-obscura` publishes new at 0.3.0. Distinct from the 2026-08-26 rag/memory/otel 0.3.1 patch below (independent Decision B tags).
4
+
5
+ ### Added
6
+ - `@arnilo/prism-obscura` (new workspace package, 0.3.0): optional Obscura headless-browser engine over a **host-installed** binary — fail-closed `spawnObscuraProcess` lifecycle (absolute shell-free command, Docker argv, bounded readiness, group close), `createObscuraMcpTools` bridging the complete advertised MCP surface (reads effect-free; mutations and unknown future tools exclusive/serialized; `obscura_` prefix; loopback-default HTTP), `connectObscuraCdp` managed/external CDP + Playwright `connectOverCDP` composition, and `createObscuraWebTools` (standard `web_search`/`web_fetch` through one replaceable HTML search profile plus native `obscura_fetch`/`obscura_scrape`; public-HTTP(S)-only URL validation, byte/count/timeout caps, `allowEval`-gated custom expressions, untrusted-content labeling). Deliberately omitted from `prism-all`/`prism-base`/`prism-sdk` umbrella profiles — installation does not supply the binary/image; consumers install it explicitly.
7
+ - Cross-host conformance (`scripts/obscura-host-conformance.test.mjs`, wired into `npm test`): the same Obscura `ToolDefinition[]` executes through core agent sessions, the Prism MCP server, the server handler, AG-UI, ACP, workflow nodes, supervisor children, and Antigravity delegated exposure — no host branch; host authorization/selection deny before execution; abort kills owned children.
8
+ - New required peers: `@arnilo/prism-obscura` peers `@arnilo/prism` and `@arnilo/prism-web-tools` (reused citation/normalized shapes; `WebProvider` widened with `"obscura"`); `@arnilo/prism-obscura` also peers `@arnilo/prism-mcp`, `@arnilo/prism-browser`, and optional `playwright-core@1.61.0`.
9
+
10
+ ## [0.3.1] - 2026-08-26
11
+
12
+ ### Added
13
+ - **Release 0.3.1 (plan 034)** is the first Decision B independent patch: only `@arnilo/prism-rag`, `@arnilo/prism-memory`, and `@arnilo/prism-observability-opentelemetry` move `0.3.0 → 0.3.1`. Internal `^0.3.0` ranges stay valid; root and every other workspace package stay at their pre-plan versions. Production RAG engine (P1–P8):
14
+ - **P1 transactional pgvector store** — `createPostgresVectorStore` (standalone) plus the existing `createPostgresMemoryStores().vectorStore` now implement `getBySource` + `transaction`. Additive DDL: `embedder_id` / `content_hash` / `generation`, `text_tsv` + GIN, HNSW when the embedding dimension is pinned, per-scope generation pointer table. Host names schema/table and owns the knowledge database.
15
+ - **P2 hybrid retrieve** — `retrieveContext({ lexical: "fts" | "bm25" | "off" })` fuses vector + lexical legs with RRF (`fusion: "rrf"`, `rrfK` 60 / cap 1,000). Provenance `retrieval` is `vector` | `lexical` | `hybrid`. Stores advertise `lexicalModes`; unsupported `bm25` fails closed. `fuseReciprocalRank` / `tokenizeLexical` exported.
16
+ - **P3 embedder identity** — `Embedder.id` is required and stamped as `embedderId`. Retrieve fails closed with `ERR_PRISM_RAG_EMBEDDER_MISMATCH` on id/dimension drift or legacy rows without an id (re-index path named). **TypeScript break for Embedder implementers** — add `readonly id: string`; see `docs/migration.md` `0.3.0 → 0.3.1`.
17
+ - **P4 content-hash skip** — `replaceSource({ contentHash })` skips unchanged sources (`{ indexed: 0, skipped: true }`) and reuses embeddings when chunk text matches (`reuseEmbeddings`, `isValidContentHash`).
18
+ - **P5 heading metadata** — `chunkMarkdown` stamps `metadata.heading` (parent-first ATX stack) unless the caller supplied one; parser metadata (`page`, `section`, …) copies onto chunks.
19
+ - **P6 generation visibility** — `replaceSource` bumps a scope-level generation; retrieval filters to the current generation (legacy generation-less rows stay visible). `getCurrentGeneration` / `setCurrentGeneration` support rollback.
20
+ - **P7 RAG telemetry** — dependency-free `RagTelemetry` seam; `createRagTelemetry()` in the OpenTelemetry package maps the `rag_request` / `rag_index` span tree. Span-name + `rag.*` allow-list drops raw chunk text.
21
+ - **P8 TEI reranker** — `createTeiReranker({ baseUrl })` posts `{query, texts, raw_scores:false}` to host TEI `/rerank`, permutation-only, fail-closed parse, 65,536-byte ceiling, `pinnedFetch` default. SSRF/URL policy stays host-side.
22
+ - **multi-scope retrieve** — `retrieveContext({ scopes: [org, user, session] })` embeds once, runs per-scope vector/lexical legs, fuses with one RRF, reranks once, and cuts `topK`. `scope` still valid; empty `scopes` returns zero hits with no embed/search/rerank (host “no allowed corpora” path). `HARD_RETRIEVE_SCOPE_CAP` is 8. Provenance carries `tenantId`/`resourceId`/`corpusId`. Telemetry: `rag.scope_count` + chunk tenant/corpus.
23
+ - Compat baselines regenerated (`--update-baseline`). Scanner sees additive exports only; the Embedder.id implementer break is documented, not a name-level removal. No `--allow-break`. Publication remains the operator handoff (`docs/release-and-install.md` `0.3.1 independent RAG engine patch` — package tags `@arnilo/prism-memory@0.3.1`, `@arnilo/prism-rag@0.3.1`, `@arnilo/prism-observability-opentelemetry@0.3.1`).
24
+
25
+ ### Changed
26
+ - Store compatibility with 0.3.0: **compatible, additive**. New columns/indexes/tables are `IF NOT EXISTS`; 0.3.0 rows remain readable. Rollback = restore the 0.3.0 package versions (generation-less retrieve still works; heading/hash/telemetry/TEI simply disappear). No root/core persisted-shape change.
27
+
28
+ ## [0.3.0] - 2026-08-20
29
+
30
+ ### Added
31
+ - **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.
32
+ - 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.
33
+ - 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.
34
+ - 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.
35
+
36
+ ### Changed
37
+ - 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.
38
+ - No persisted store migration. Live-service canaries and delegated Cursor adapter remain later demand-gated 0.3.x work.
39
+
1
40
  ## [0.2.9] - 2026-08-19
2
41
 
3
42
  ### 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,10 @@ 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-obscura` | optional Obscura headless-browser engine over a host-installed binary: MCP surface, CDP + Playwright, bounded CLI web tools (not in umbrellas; install explicitly) |
175
+ | `@arnilo/prism-computer-use-linux` | optional Linux desktop-control tools over a host-owned `computer-use-linux` MCP binary |
176
+ | `@arnilo/prism-antigravity-agent` | optional Antigravity CLI delegated agent adapter with per-run Prism MCP capability exposure |
177
+ | `@arnilo/prism-wiki` | optional Karpathy LLM Wiki knowledge compiler with local `qmd` hybrid search and Context7 line navigation |
171
178
  | `@arnilo/prism-compaction-llm` | provider-backed compaction strategy |
172
179
  | `@arnilo/prism-compaction-observational-memory` | source-backed memory + recall tool |
173
180
  | `@arnilo/prism-coding-agent` | bounded shell/read/write/edit tools |
@@ -186,7 +193,7 @@ printf '{"id":"1","command":"prompt","params":{"input":"Hi"}}\n' \
186
193
  | `@arnilo/prism-base` | profile: core + compaction + JSON Schema validation |
187
194
  | `@arnilo/prism-code` | profile: base + coding tools/security + MCP |
188
195
  | `@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 |
196
+ | `@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, antigravity-agent, Graft, Obscura, and wiki |
190
197
 
191
198
  ## Scripts
192
199
 
@@ -80,12 +80,29 @@ export function generateValidateReviseLoop(opts) {
80
80
  const max = opts.maxRevisions ?? 3;
81
81
  const repairer = opts.repairer ?? defaultRepairer();
82
82
  const finalOnly = opts.structuredOutputTiming === "final-turn-only" && opts.toolCalls === "bounded";
83
- // ponytail: per-run state hoisted to factory scope so snapshot/restore can capture it;
84
- // resolveLoop invokes this factory once per run, so there is no cross-run leakage.
83
+ // ponytail: keep only current-run state in this strategy so snapshot/restore can capture it;
84
+ // supplied strategy instances may be reused, so a new non-restored run resets these locals.
85
85
  let attempts = 0;
86
86
  let artifactPhase = !finalOnly;
87
87
  let savedSchema;
88
88
  let pendingHistory = [];
89
+ let stateOwner;
90
+ let restoredStatePending = false;
91
+ const resetState = () => {
92
+ attempts = 0;
93
+ artifactPhase = !finalOnly;
94
+ savedSchema = undefined;
95
+ pendingHistory = [];
96
+ };
97
+ const prepareRunState = (ctx) => {
98
+ const sameRun = stateOwner?.sessionId === ctx.sessionId && stateOwner.runId === ctx.runId;
99
+ if (!sameRun) {
100
+ if (!restoredStatePending)
101
+ resetState();
102
+ stateOwner = { sessionId: ctx.sessionId, runId: ctx.runId };
103
+ }
104
+ restoredStatePending = false;
105
+ };
89
106
  return {
90
107
  name: "generate-validate-revise",
91
108
  revision: "1",
@@ -108,8 +125,10 @@ export function generateValidateReviseLoop(opts) {
108
125
  // Repair messages were appended to the session before suspension, so the rebuilt
109
126
  // history already carries them; re-applying pendingHistory would duplicate them.
110
127
  pendingHistory = [];
128
+ restoredStatePending = true;
111
129
  },
112
130
  async run(ctx) {
131
+ prepareRunState(ctx);
113
132
  let usage;
114
133
  let nextInput = ctx.input;
115
134
  let toolRounds = 0;
@@ -260,17 +279,35 @@ export async function dispatchToolCallsInOrder(calls, ctx) {
260
279
  }
261
280
  const results = new Array(calls.length);
262
281
  let nextIndex = 0;
282
+ let stopped = false;
283
+ let firstFailure;
284
+ const recordFailure = (error) => {
285
+ if (stopped)
286
+ return;
287
+ stopped = true;
288
+ firstFailure = error;
289
+ };
263
290
  const workers = Array.from({ length: concurrency }, async () => {
264
291
  for (;;) {
265
- throwIfAborted(ctx.signal);
266
- const index = nextIndex;
267
- nextIndex += 1;
268
- if (index >= calls.length)
292
+ if (stopped)
269
293
  return;
270
- results[index] = await ctx.dispatchToolCall(calls[index]);
294
+ try {
295
+ throwIfAborted(ctx.signal);
296
+ const index = nextIndex;
297
+ nextIndex += 1;
298
+ if (index >= calls.length)
299
+ return;
300
+ results[index] = await ctx.dispatchToolCall(calls[index]);
301
+ }
302
+ catch (error) {
303
+ recordFailure(error);
304
+ return;
305
+ }
271
306
  }
272
307
  });
273
- await Promise.all(workers);
308
+ await Promise.allSettled(workers);
309
+ if (stopped)
310
+ throw firstFailure;
274
311
  for (const result of results) {
275
312
  throwIfAborted(ctx.signal);
276
313
  if (!result)
@@ -142,10 +142,10 @@ export function throwIfAbortedSignal(signal) {
142
142
  if (signal?.aborted)
143
143
  throw signal.reason instanceof Error ? signal.reason : new Error("Agent run aborted");
144
144
  }
145
- const jsonTextEncoder = new TextEncoder();
146
145
  export function jsonBytes(value) {
147
146
  try {
148
- return jsonTextEncoder.encode(JSON.stringify(value)).byteLength;
147
+ const serialized = JSON.stringify(value);
148
+ return serialized === undefined ? 0 : Buffer.byteLength(serialized, "utf8");
149
149
  }
150
150
  catch {
151
151
  throw new TypeError("Provider request or event must be JSON-serializable for run limits");
@@ -23,6 +23,17 @@ export interface CacheUsageReport {
23
23
  export declare function sanitizeCacheKey(value: string | undefined, maxLength: number): string | undefined;
24
24
  export declare function mapCacheRetention(retention: CacheRetention | undefined, model: ModelConfig): "short" | "long" | undefined;
25
25
  export declare function applyCacheControl(messages: readonly Message[], breakpoints: readonly PromptCacheBreakpoint[], options?: ApplyCacheControlOptions): readonly CacheControlledMessage[];
26
+ export interface SystemCacheControlTextBlock {
27
+ readonly type: "text";
28
+ readonly text: string;
29
+ readonly cache_control?: CacheControlValue;
30
+ }
31
+ /**
32
+ * Provider-style `system` field: plain joined string by default; native text
33
+ * blocks only when cache-control markers must survive (system_prompt breakpoints).
34
+ */
35
+ export declare function systemCacheControlField(messages: readonly CacheControlledMessage[], toText: (message: Message) => string): string | readonly SystemCacheControlTextBlock[] | undefined;
26
36
  export declare function cacheHitRate(usage: Usage | undefined): number | undefined;
27
37
  export declare function cacheSavings(usage: Usage | undefined, model: ModelConfig): number | undefined;
28
38
  export declare function cacheUsageReport(usage: Usage | undefined, model?: ModelConfig): CacheUsageReport | undefined;
39
+ export declare function resolveBreakpoint(messages: readonly Message[], breakpoint: PromptCacheBreakpoint): number;
@@ -1,8 +1,15 @@
1
1
  export function sanitizeCacheKey(value, maxLength) {
2
- const key = value
3
- ?.replace(/[^A-Za-z0-9_.:-]+/g, "-")
4
- .replace(/^-+|-+$/g, "")
5
- .slice(0, Math.max(0, maxLength));
2
+ const replaced = value?.replace(/[^A-Za-z0-9_.:-]+/g, "-");
3
+ if (!replaced)
4
+ return undefined;
5
+ // Index/slice edge trim instead of the `/^-+|-+$/g` alternation (CodeQL js/polynomial-redos, alert 22).
6
+ let start = 0;
7
+ let end = replaced.length;
8
+ while (start < end && replaced.charCodeAt(start) === 45)
9
+ start += 1;
10
+ while (end > start && replaced.charCodeAt(end - 1) === 45)
11
+ end -= 1;
12
+ const key = replaced.slice(start, end).slice(0, Math.max(0, maxLength));
6
13
  return key || undefined;
7
14
  }
8
15
  export function mapCacheRetention(retention, model) {
@@ -29,6 +36,23 @@ export function applyCacheControl(messages, breakpoints, options = {}) {
29
36
  return { ...message, content };
30
37
  });
31
38
  }
39
+ /**
40
+ * Provider-style `system` field: plain joined string by default; native text
41
+ * blocks only when cache-control markers must survive (system_prompt breakpoints).
42
+ */
43
+ export function systemCacheControlField(messages, toText) {
44
+ const system = messages.filter((message) => message.role === "system");
45
+ if (!system.length)
46
+ return undefined;
47
+ if (!system.some((message) => message.content.some((block) => block.cache_control))) {
48
+ return system.map(toText).join("\n\n") || undefined;
49
+ }
50
+ return system.map((message) => {
51
+ const cache_control = message.content.find((block) => block.cache_control)?.cache_control;
52
+ const block = { type: "text", text: toText(message) };
53
+ return cache_control ? { ...block, cache_control } : block;
54
+ });
55
+ }
32
56
  export function cacheHitRate(usage) {
33
57
  const read = usage?.cacheReadTokens;
34
58
  const input = usage?.inputTokens;
@@ -54,7 +78,7 @@ export function cacheUsageReport(usage, model) {
54
78
  currency: estimatedSavings === undefined ? usage.currency : (model?.cost?.currency ?? usage.currency),
55
79
  };
56
80
  }
57
- function resolveBreakpoint(messages, breakpoint) {
81
+ export function resolveBreakpoint(messages, breakpoint) {
58
82
  switch (breakpoint.location) {
59
83
  case "system_prompt":
60
84
  return messages.findIndex((message) => message.role === "system");
@@ -2,6 +2,7 @@ import { accessSync, constants as fsConstants } from "node:fs";
2
2
  import { access, mkdir, readdir, readFile, realpath, writeFile } from "node:fs/promises";
3
3
  import { dirname, isAbsolute, join, relative, resolve, sep } from "node:path";
4
4
  import { fileURLToPath } from "node:url";
5
+ import { trimTrailingSlashes } from "./trim-trailing-slashes.js";
5
6
  export class ProviderAddUsageError extends Error {
6
7
  }
7
8
  const NPM_NAME_PATTERN = /^[a-z0-9][a-z0-9._-]*$/;
@@ -208,7 +209,7 @@ function buildTokens(input) {
208
209
  __PROVIDER_PASCAL__: pascal,
209
210
  __PACKAGE_NAME__: input.name,
210
211
  __PRISM_VERSION__: input.version,
211
- __BASE_URL__: input.baseUrl.replace(/\/+$/, ""),
212
+ __BASE_URL__: trimTrailingSlashes(input.baseUrl),
212
213
  __ENV_KEY__: input.envKey,
213
214
  __MODEL_ID__: input.model,
214
215
  };
@@ -20,7 +20,7 @@ export function estimateTextTokens(text) {
20
20
  return Math.ceil(text.length / 4);
21
21
  }
22
22
  export function estimateTextBytes(text) {
23
- return new TextEncoder().encode(text).byteLength;
23
+ return Buffer.byteLength(text, "utf8");
24
24
  }
25
25
  export function estimateMessageTokens(message) {
26
26
  return estimateTextTokens(messageText(message));
@@ -64,11 +64,12 @@ export function applyContextBudget(options) {
64
64
  const tools = options.tools ? [...options.tools] : undefined;
65
65
  const omitted = [];
66
66
  const demotedBodies = new Set();
67
+ const historyCursor = { index: 0 };
67
68
  // Measure once, then subtract each dropped item's own estimate (dropNext computes it
68
69
  // with the same estimators) — avoids an O(n²) re-scan of the full keep-set per drop.
69
70
  const kept = measureAll(groups, context, skills, tools, skillContext, demotedBodies);
70
71
  while (overBudget(kept, budget)) {
71
- const drop = dropNext(groups, context, skills, layout, skillContext, demotedBodies);
72
+ const drop = dropNext(groups, context, skills, layout, skillContext, demotedBodies, historyCursor);
72
73
  if (!drop) {
73
74
  throw new ContextBudgetError();
74
75
  }
@@ -77,6 +78,8 @@ export function applyContextBudget(options) {
77
78
  if (omitted.length < HARD_MAX_CONTEXT_BUDGET_OMISSIONS)
78
79
  omitted.push(drop);
79
80
  }
81
+ if (historyCursor.index > 0)
82
+ groups.history = groups.history.slice(historyCursor.index);
80
83
  const reportOmissions = omitted.slice(0, DEFAULT_MAX_CONTEXT_BUDGET_OMISSIONS);
81
84
  return {
82
85
  groups,
@@ -94,8 +97,8 @@ export function applyContextBudget(options) {
94
97
  },
95
98
  };
96
99
  }
97
- function dropNext(groups, context, skills, layout, skillContext, demotedBodies) {
98
- // ponytail: drop droppable groups in layout order; within history, drop oldest first (shift).
100
+ function dropNext(groups, context, skills, layout, skillContext, demotedBodies, historyCursor) {
101
+ // ponytail: drop droppable groups in layout order; within history, advance a cursor and slice once.
99
102
  // cache_aware keeps attachments longer so stable prefix stays intact while budget still allows it.
100
103
  const order = layout === "cache_aware"
101
104
  ? ["tool_results", "history", "summaries", "context", "skills", "attachments"]
@@ -105,8 +108,8 @@ function dropNext(groups, context, skills, layout, skillContext, demotedBodies)
105
108
  const message = groups.toolResults.pop();
106
109
  return omission("tool_results", message.id ?? toolResultId(message), message);
107
110
  }
108
- if (kind === "history" && groups.history.length > 0) {
109
- const message = groups.history.shift();
111
+ if (kind === "history" && historyCursor.index < groups.history.length) {
112
+ const message = groups.history[historyCursor.index++];
110
113
  return omission("history", message.id, message);
111
114
  }
112
115
  if (kind === "summaries" && groups.summaries.length > 0) {
@@ -225,6 +225,8 @@ export interface PromptBuilder {
225
225
  }
226
226
  export interface PromptBuildRequest {
227
227
  readonly messages: readonly Message[];
228
+ /** Input layout selected by the host; the default builder uses cache-aware ordering unless legacy is explicit. */
229
+ readonly inputLayout?: InputAssemblyLayout;
228
230
  readonly context?: readonly ContextBlock[];
229
231
  readonly skills?: readonly Skill[];
230
232
  readonly skillsDisclosure?: import("../skill-disclosure.js").SkillsDisclosure;
@@ -11,6 +11,8 @@ export interface ModelCacheCapabilities {
11
11
  readonly maxBreakpoints?: number;
12
12
  readonly minCacheableTokens?: number;
13
13
  readonly longRetention?: boolean;
14
+ /** Model accepts explicit per-block cache breakpoints (e.g. OpenAI GPT-5.6+ `prompt_cache_breakpoint`). */
15
+ readonly explicitBreakpoints?: boolean;
14
16
  }
15
17
  export type PromptCacheMode = "auto" | "on" | "off";
16
18
  export type PromptCacheBreakpointLocation = "system_prompt" | "tools" | "stable_context" | "last_stable_message" | "last_user_message" | "message_id";
@@ -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
@@ -119,10 +119,6 @@ export function createEventMultiplexer(options = {}) {
119
119
  isClosed = true;
120
120
  options.signal?.removeEventListener("abort", abort);
121
121
  finishSources();
122
- queue.length = 0;
123
- // Free the single-consumer slot: a consumer suspended at a yield may never pull
124
- // again, and after close a fresh subscriber terminates immediately anyway.
125
- activeConsumer = false;
126
122
  if (waiter) {
127
123
  const resolve = waiter;
128
124
  waiter = undefined;
package/dist/index.d.ts CHANGED
@@ -10,7 +10,7 @@ export { createAgent, createAgentSession, resumeAgentRun, resumeAgentRunStream }
10
10
  export type { ArtifactApproval, ArtifactApprovalState, ArtifactBodyErrorCode, ArtifactBodyPresignOptions, ArtifactBodyRef, ArtifactBodyStore, ArtifactBodyTransferOptions, ArtifactCitation, ArtifactDecisionState, ArtifactDeliveryToken, ArtifactRecord, ArtifactRevision, } from "./artifacts.js";
11
11
  export { ARTIFACT_BODY_ERROR_CODES, ARTIFACT_CHECKPOINT_NAMESPACE, ArtifactBodyStoreError, ArtifactError, artifactApprovalState, artifactCheckpointKey, } from "./artifacts.js";
12
12
  export type { ApplyCacheControlOptions, CacheControlledContentBlock, CacheControlledMessage, CacheControlValue, CacheUsageReport, } from "./cache-helpers.js";
13
- export { applyCacheControl, cacheHitRate, cacheSavings, cacheUsageReport, mapCacheRetention, sanitizeCacheKey } from "./cache-helpers.js";
13
+ export { applyCacheControl, cacheHitRate, cacheSavings, cacheUsageReport, mapCacheRetention, resolveBreakpoint, sanitizeCacheKey, systemCacheControlField, } from "./cache-helpers.js";
14
14
  export type { CacheTelemetry, CacheTelemetryOptions, CacheTelemetryReport, CacheTelemetrySample, } from "./cache-telemetry.js";
15
15
  export { CACHE_TELEMETRY_OVERFLOW_KEY, CacheTelemetryError, createCacheTelemetry, DEFAULT_CACHE_TELEMETRY_CAP, } from "./cache-telemetry.js";
16
16
  export type { MemoryCheckpointStoreOptions } from "./checkpoints.js";
@@ -33,6 +33,8 @@ export type { ConversationBranchRef, ConversationReplayCursor, ConversationThrea
33
33
  export { CONVERSATION_METADATA_KEY, ConversationError, conversationMarkerMetadata, conversationThreadFromRecord, DEFAULT_MAX_CONVERSATION_CURSOR_BYTES, decodeConversationReplayCursor, encodeConversationReplayCursor, HARD_MAX_CONVERSATION_CURSOR_BYTES, } from "./conversations.js";
34
34
  export type { CredentialRecord, CredentialValueSource, MemoryCredentialStore, RevocableOAuthCredentialStore } from "./credentials.js";
35
35
  export { createChainedCredentialResolver, createEnvCredentialResolver, createExplicitCredentialResolver, createMemoryCredentialStore, refreshOAuthCredential, resolveCredentialValue, revokeOAuthCredential, } from "./credentials.js";
36
+ export type { DelegatedAgentStepInput } from "./delegated-agent-step.js";
37
+ 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";
36
38
  export type { DeviceAdapter, DeviceAdmitRequest, DeviceChunkResult, DeviceConformanceResult, DeviceKind, DevicePolicyErrorCode, DevicePolicyOptions, DeviceStreamLimits, ResolvedDevicePolicy, } from "./devices.js";
37
39
  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
40
  export type { EventMultiplexer, EventMultiplexerOptions, EventOverflowInfo, EventOverflowPolicy } from "./event-multiplexer.js";
@@ -71,6 +73,7 @@ export { providerContentDelta, providerContinuationRequired, providerDone, provi
71
73
  export { authMethodKey, defineProviderPackage, systemPromptContributionKey } from "./provider-packages.js";
72
74
  export type { SessionCachePolicyOptions } from "./provider-request-policy.js";
73
75
  export { createProviderRequestPolicyChain, createSessionCachePolicy, mergeProviderRequestOptions } from "./provider-request-policy.js";
76
+ export { canonicalizeJsonSchema } from "./providers/schema.js";
74
77
  export type { ProviderRegistry, ProviderRegistryOptions } from "./providers.js";
75
78
  export { createProviderRegistry, createProviderResolver } from "./providers.js";
76
79
  export type { SecretRedactor } from "./redaction.js";
@@ -108,8 +111,9 @@ export type { FoldToolResultsContext, ResolvedToolResultFoldOptions, ToolResultF
108
111
  export { DEFAULT_TOOL_RESULT_FOLD_MAX_SUMMARY_BYTES, DEFAULT_TOOL_RESULT_FOLD_MIN_AGE_TURNS, DEFAULT_TOOL_RESULT_FOLD_MIN_BYTES, foldedToolResultHeader, foldToolResultHistory, foldToolResults, formatFoldedToolResult, HARD_TOOL_RESULT_FOLD_MAX_SUMMARY_BYTES, resolveToolResultFold, TOOL_RESULT_FOLD_TURN_METADATA_KEY, } from "./tool-result-fold.js";
109
112
  export type { DispatchToolCallOptions, ToolArgumentValidationError, ToolArgumentValidationResult, ToolArgumentValidator, ToolFilter, ToolFilterInput, ToolParameterValidatorOptions, ToolRegistryOptions, ToolValidator, } from "./tools.js";
110
113
  export { createToolParameterValidator, createToolRegistry, dispatchToolCall, filterTools } from "./tools.js";
114
+ export { trimTrailingSlashes } from "./trim-trailing-slashes.js";
111
115
  export type { ResolvedUseCaseModel, ResolveUseCaseModelInput, UseCaseModelBinding, } from "./use-case-model.js";
112
116
  export { resolveUseCaseModel, resolveUseCaseModelBinding, useCaseCredentialProviderId, } from "./use-case-model.js";
113
117
  export declare const name = "prism";
114
- export declare const version = "0.2.9";
118
+ export declare const version = "0.3.1";
115
119
  export declare const description = "Agent harness for AI providers, agents, sessions, and tools.";
package/dist/index.js CHANGED
@@ -5,7 +5,7 @@ export { createAgentRunLifecycle } from "./agent-run-lifecycle.js";
5
5
  export { AGENT_RUN_STATE_NAMESPACE, AGENT_RUN_STATE_SCHEMA_VERSION, agentFingerprint, DEFAULT_MAX_AGENT_RUN_STATE_BYTES, HARD_MAX_AGENT_RUN_STATE_BYTES, loadAgentRunState, } from "./agent-run-state.js";
6
6
  export { createAgent, createAgentSession, resumeAgentRun, resumeAgentRunStream } from "./agents.js";
7
7
  export { ARTIFACT_BODY_ERROR_CODES, ARTIFACT_CHECKPOINT_NAMESPACE, ArtifactBodyStoreError, ArtifactError, artifactApprovalState, artifactCheckpointKey, } from "./artifacts.js";
8
- export { applyCacheControl, cacheHitRate, cacheSavings, cacheUsageReport, mapCacheRetention, sanitizeCacheKey } from "./cache-helpers.js";
8
+ export { applyCacheControl, cacheHitRate, cacheSavings, cacheUsageReport, mapCacheRetention, resolveBreakpoint, sanitizeCacheKey, systemCacheControlField, } from "./cache-helpers.js";
9
9
  export { CACHE_TELEMETRY_OVERFLOW_KEY, CacheTelemetryError, createCacheTelemetry, DEFAULT_CACHE_TELEMETRY_CAP, } from "./cache-telemetry.js";
10
10
  export { CHECKPOINT_CONFLICT_CODE, CheckpointConflictError, createMemoryCheckpointStore } from "./checkpoints.js";
11
11
  export { createDefaultCompactionStrategy, isCompactionEntryData } from "./compaction.js";
@@ -17,6 +17,7 @@ export { parseAgentFile, parseSkillFile } from "./contribution-parsing.js";
17
17
  export { createContributionRegistries, createContributionRegistry, registerDiscoveredContributions } from "./contributions.js";
18
18
  export { CONVERSATION_METADATA_KEY, ConversationError, conversationMarkerMetadata, conversationThreadFromRecord, DEFAULT_MAX_CONVERSATION_CURSOR_BYTES, decodeConversationReplayCursor, encodeConversationReplayCursor, HARD_MAX_CONVERSATION_CURSOR_BYTES, } from "./conversations.js";
19
19
  export { createChainedCredentialResolver, createEnvCredentialResolver, createExplicitCredentialResolver, createMemoryCredentialStore, refreshOAuthCredential, resolveCredentialValue, revokeOAuthCredential, } from "./credentials.js";
20
+ 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";
20
21
  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
22
  export { createEventMultiplexer, EVENT_MULTIPLEXER_SINGLE_CONSUMER_CODE, EventMultiplexerError } from "./event-multiplexer.js";
22
23
  export { applyExecutionDecision, assertExecutionAllowed, checkExecution, ExecutionDeniedError } from "./execution-policy.js";
@@ -39,6 +40,7 @@ export { boundResponse, defaultResolver, isLoopbackAddress, isLoopbackHostname,
39
40
  export { providerContentDelta, providerContinuationRequired, providerDone, providerError, providerTextDelta, providerThinkingDelta, providerToolCall, providerToolCallDelta, providerUsage, toolCallContent, toolCallFromArgumentsText, } from "./provider-events.js";
40
41
  export { authMethodKey, defineProviderPackage, systemPromptContributionKey } from "./provider-packages.js";
41
42
  export { createProviderRequestPolicyChain, createSessionCachePolicy, mergeProviderRequestOptions } from "./provider-request-policy.js";
43
+ export { canonicalizeJsonSchema } from "./providers/schema.js";
42
44
  export { createProviderRegistry, createProviderResolver } from "./providers.js";
43
45
  export { createSecretRedactor, errorToErrorInfo, redactAgentEvent, redactMessage, redactProviderRequest, redactRunLedgerRecord, redactSecrets, redactSessionEntry, resolveRedactor, } from "./redaction.js";
44
46
  export { loadBinaryResource, loadJsonResource, loadManifestResource, loadTextResource } from "./resources.js";
@@ -59,8 +61,9 @@ export { applyThinkingLevel, isThinkingLevel, normalizeThinkingLevel, THINKING_L
59
61
  export { createMemoryToolEffectStore, ToolEffectError } from "./tool-effects.js";
60
62
  export { DEFAULT_TOOL_RESULT_FOLD_MAX_SUMMARY_BYTES, DEFAULT_TOOL_RESULT_FOLD_MIN_AGE_TURNS, DEFAULT_TOOL_RESULT_FOLD_MIN_BYTES, foldedToolResultHeader, foldToolResultHistory, foldToolResults, formatFoldedToolResult, HARD_TOOL_RESULT_FOLD_MAX_SUMMARY_BYTES, resolveToolResultFold, TOOL_RESULT_FOLD_TURN_METADATA_KEY, } from "./tool-result-fold.js";
61
63
  export { createToolParameterValidator, createToolRegistry, dispatchToolCall, filterTools } from "./tools.js";
64
+ export { trimTrailingSlashes } from "./trim-trailing-slashes.js";
62
65
  export { resolveUseCaseModel, resolveUseCaseModelBinding, useCaseCredentialProviderId, } from "./use-case-model.js";
63
66
  export const name = "prism";
64
- export const version = "0.2.9";
67
+ export const version = "0.3.1";
65
68
  export const description = "Agent harness for AI providers, agents, sessions, and tools.";
66
69
  //# sourceMappingURL=index.js.map