@arnilo/prism 0.5.6 → 0.6.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.
Files changed (64) hide show
  1. package/CHANGELOG.md +37 -0
  2. package/README.md +10 -10
  3. package/dist/agent-approval.js +7 -6
  4. package/dist/agent-loops.js +51 -12
  5. package/dist/agent-session/session.d.ts +1 -0
  6. package/dist/agent-session/session.js +20 -2
  7. package/dist/agent-tool-dispatch.js +5 -4
  8. package/dist/content.d.ts +3 -16
  9. package/dist/content.js +9 -99
  10. package/dist/context-budget.d.ts +12 -1
  11. package/dist/context-budget.js +42 -19
  12. package/dist/contracts-core/agent.d.ts +11 -0
  13. package/dist/contracts-core/agent.js +4 -1
  14. package/dist/index.d.ts +4 -4
  15. package/dist/index.js +3 -3
  16. package/dist/input.d.ts +6 -0
  17. package/dist/input.js +12 -1
  18. package/dist/media-types.d.ts +34 -0
  19. package/dist/media-types.js +158 -0
  20. package/dist/pinned-fetch.d.ts +2 -2
  21. package/dist/pinned-fetch.js +11 -12
  22. package/dist/redaction.js +74 -1
  23. package/dist/session-stores.d.ts +11 -0
  24. package/dist/session-stores.js +23 -8
  25. package/docs/acp.md +1 -1
  26. package/docs/ag-ui.md +4 -2
  27. package/docs/agent-events.md +2 -0
  28. package/docs/agent-loops.md +1 -1
  29. package/docs/agent-session-runtime.md +3 -1
  30. package/docs/browser-automation.md +5 -2
  31. package/docs/contributing.md +37 -0
  32. package/docs/core.md +2 -0
  33. package/docs/document-reader.md +2 -0
  34. package/docs/documents.md +1 -1
  35. package/docs/graft.md +3 -1
  36. package/docs/history/release-handoffs.md +33 -0
  37. package/docs/host-security.md +2 -2
  38. package/docs/index.md +27 -14
  39. package/docs/input-and-prompt-assembly.md +4 -4
  40. package/docs/language-intelligence.md +1 -1
  41. package/docs/migrate-to-0.5.md +7 -2
  42. package/docs/migrate-to-0.6.md +89 -0
  43. package/docs/migration.md +30 -0
  44. package/docs/model-registry.md +1 -1
  45. package/docs/multimodal-content.md +1 -1
  46. package/docs/obscura.md +3 -1
  47. package/docs/options-index.md +286 -0
  48. package/docs/peer-dependencies.md +94 -0
  49. package/docs/performance.md +34 -2
  50. package/docs/ponytail.md +2 -0
  51. package/docs/postgres-persistence.md +3 -1
  52. package/docs/provider-conformance.md +1 -1
  53. package/docs/provider-packages.md +21 -21
  54. package/docs/provider-primitives.md +2 -1
  55. package/docs/providers/ai-sdk.md +5 -2
  56. package/docs/public-contracts.md +2 -2
  57. package/docs/release-and-install.md +75 -55
  58. package/docs/server.md +1 -1
  59. package/docs/session-stores.md +3 -1
  60. package/docs/sqlite-persistence.md +2 -0
  61. package/docs/testing.md +38 -0
  62. package/docs/tools.md +1 -1
  63. package/docs/wiki.md +1 -1
  64. package/package.json +5 -5
@@ -31,7 +31,7 @@ Public helpers:
31
31
  | Helper | Purpose |
32
32
  | --- | --- |
33
33
  | `createSessionEntry(options)` | Build a `SessionEntry` with generated `id`/`timestamp` when omitted. |
34
- | `createMemorySessionStore(initialEntries?, options?)` | Built-in in-memory `SessionStore`. `options.sessionSearchMode`: `"linear"` (default) or `"unsupported"` (throws `SessionSearchUnsupportedError`). |
34
+ | `createMemorySessionStore(initialEntries?, options?: CreateMemorySessionStoreOptions)` | Built-in in-memory `SessionStore`. `options.sessionSearchMode`: `"linear"` (default) or `"unsupported"` (throws `SessionSearchUnsupportedError`); `options.search` may override the linear scan caps (`maxLinearSessions` / `maxLinearEntries` / `maxLinearBytes`), each bounded by its `HARD_MAX_SESSION_SEARCH_LINEAR_*` value and validated at construction (`TypeError` below 1 or above the hard cap). |
35
35
  | `resolveSessionSearchQuery(query)` | Validate/clamp search limits (page, query bytes, snippet, cursor, linear/FTS caps). |
36
36
  | `SessionIndex` | Narrow search seam (`search(query)`); adapters may expose this instead of `SessionStore.searchSessions`. |
37
37
  | `getSessionBranchEntries(entries, options)` | Return root-to-leaf entries for a leaf id (sync array path). |
@@ -124,6 +124,8 @@ const page = await store.searchSessions!({
124
124
  limit: 20,
125
125
  });
126
126
  // Opt out: createMemorySessionStore([], { sessionSearchMode: "unsupported" })
127
+ // Raise the in-process scan caps for a small but large-query session set (defaults are the contract caps):
128
+ const wide = createMemorySessionStore([], { search: { maxLinearSessions: 5_000, maxLinearEntries: 50_000 } });
127
129
  ```
128
130
 
129
131
  Finite caps (defaults / hard): page 20/100; query string 4 KiB/16 KiB; snippet 512 B/4 KiB; cursor 1 KiB/4 KiB; memory linear sessions 1000/5000, entries 10000/50000, bytes 8 MiB/64 MiB; DB FTS candidates 1000/5000. Overflow fails closed via `resolveSessionSearchQuery`. See [Phase 6 evidence](_evidence/review-coverage-2026-07-22-phase-6.md).
@@ -1,5 +1,7 @@
1
1
  # SQLite persistence
2
2
 
3
+ > **Optional peer install:** `better-sqlite3` — see [Optional peer dependencies](peer-dependencies.md).
4
+
3
5
  ## What it does
4
6
 
5
7
  The optional `@arnilo/prism-core/sessions/sqlite` package ships a production-oriented SQLite adapter that implements:
@@ -0,0 +1,38 @@
1
+ # Test layout and isolation
2
+
3
+ ## What it does
4
+
5
+ Documents how the hermetic suite runs, which stage a new suite belongs to, and the isolation rules that keep tracked fixtures byte-identical between runs. Live and credentialed tiers are separate — see [Live and end-to-end testing](live-testing.md).
6
+
7
+ ## When to use it
8
+
9
+ - Adding or moving a suite: pick its stage and follow the scratch-root rule below.
10
+ - Investigating a report that a test run modified tracked files or scaffolded directories in the repository.
11
+
12
+ ## Running the suite
13
+
14
+ `npm test` delegates to `scripts/run-all-tests.mjs`, which runs five stages and reports every stage even when an earlier one fails:
15
+
16
+ | stage | contents |
17
+ | :--- | :--- |
18
+ | build | `npm run build` (all workspaces) |
19
+ | root suites | `dist/__tests__/*.test.js` |
20
+ | gate suites | `scripts/*.test.mjs` — the protection, truth, benchmark, journey, and conformance gates listed in `GATE_FILES` (`scripts/run-all-tests.mjs`) |
21
+ | build race | `scripts/phase23-build-race.test.mjs` |
22
+ | workspace suites | `npm run test --workspaces --if-present` |
23
+
24
+ Protected-environment legs (Postgres, PTY, NATS, live credentials) are not part of `npm test`; they fail closed with one canonical `BLOCKED GATE <id> requires=<names> evidence=<surface> hint=<how to unblock>` record and a non-zero exit when their infrastructure is absent (registry and audit: `node scripts/blocked-gate.mjs`). Retired phase freeze/release gates live in `scripts/` for audit but are deliberately kept out of the chain.
25
+
26
+ ## Isolation rules
27
+
28
+ - **Scratch roots come from the OS.** A suite that writes anything creates its root with `mkdtempSync(join(tmpdir(), "prism-…"))` and removes it in `after()`. Never rely on `process.cwd()` for write targets: the same suite runs with different working directories (workspace stage vs. root stage), so a cwd-relative root silently writes into the repository.
29
+ - **Pass explicit roots.** Wiki, memory, and store helpers default `workspaceRoot` to `process.cwd()`; suites pass their scratch root (and a `wikiRoot` relative to it) instead of accepting the default.
30
+ - **Tracked fixtures stay byte-identical.** `packages/memory/.wiki/` is a tracked wiki fixture and `docs/` is a tracked corpus. `scripts/wiki-scratch-isolation.test.mjs` runs the wiki suites from the package and from the repository root and fails if the tracked fixture hashes change, if a new file appears inside the fixture, if `<repo>/.wiki/` is scaffolded, or if the old cwd-relative scratch directories reappear.
31
+ - **Gates never write inside the repository.** A gate asserts against tracked content and spawns suites in temporary directories only. A gate that spawns `node --test` must strip `NODE_TEST_CONTEXT`/`NODE_TEST_WORKER_ID` from the child environment (an inherited value makes the nested runner skip every file and still exit 0) and assert the child reported a non-zero pass count.
32
+ - **Wait by polling, not by sleeping.** Async browser state (download quarantine, idle reaping) is not awaitable from the outside — `manager.ts` settles it on a fire-and-forget listener promise — so a fixed sleep is a race that loses under CPU load and fails the assertion for a reason unrelated to the behavior under test. Suites poll observable state through `waitFor(read, ok, label, { timeoutMs, intervalMs })` in `packages/web-tools/src/browser/__tests__/wait-for.ts`, which returns as soon as the state appears and otherwise throws naming the label and the last observed value. Fixed sleeps remain only where real elapsed time is the subject of the test (idle TTLs).
33
+
34
+ ## Related APIs
35
+
36
+ - [Live and end-to-end testing](live-testing.md): live matrix, credential scoping, skip-not-fail contract.
37
+ - [Coverage gates](release-and-install.md): per-package line thresholds and the functional-surface baseline.
38
+ - `scripts/run-all-tests.mjs` — the stage table, `STAGES` and `effectiveTestChain()` exports.
package/docs/tools.md CHANGED
@@ -216,7 +216,7 @@ By default tools without `parameters` skip schema validation (`missingSchema: "a
216
216
 
217
217
  ### Parallel tool execution (single-shot loop)
218
218
 
219
- Opt in through `loop.toolConcurrency` on `AgentConfig` / `RunOptions` (single-shot strategy only). Default is `1` (sequential). Independent calls from one provider turn run concurrently up to the limit; transcript rows and `appendMessage` stay in original call order. Each call still uses `dispatchToolCall` (permission, validation, abort signal). If a worker throws or the run aborts, workers stop claiming new calls, already-claimed calls settle, buffered tool-result rows are not appended, and the first failure is rethrown. Already-claimed side effects are not rolled back; the shared abort signal is still passed to each dispatch. The round-level `chargeToolRound` approval gate runs before any worker starts. See [Agent loops](agent-loops.md).
219
+ Opt in through `loop.toolConcurrency` on `AgentConfig` / `RunOptions` (single-shot strategy only). Default is `1` (sequential). Independent calls from one provider turn run concurrently up to the limit; transcript rows and `appendMessage` stay in original call order. Each call still uses `dispatchToolCall` (permission, validation, abort signal). If a worker throws or the run aborts, workers stop claiming new calls, already-claimed calls settle, and rows are then persisted in call order before the first failure is rethrown: finished calls keep their real results, the call that threw gets an error row carrying that failure, and calls the batch never started get a `tool_call_not_dispatched` error row — a stopped batch never leaves `tool_call` ids without a `tool_result` (run-level suspension errors are exempt: their resume machinery appends the real result). Already-claimed side effects are not rolled back; the shared abort signal is still passed to each dispatch. The round-level `chargeToolRound` approval gate runs before any worker starts. See [Agent loops](agent-loops.md).
220
220
 
221
221
  ```ts
222
222
  await session.run(input, {
package/docs/wiki.md CHANGED
@@ -27,7 +27,7 @@ The Karpathy LLM Wiki pattern is structured into 3 distinct tiers:
27
27
 
28
28
  | Field | Type | Required | Default | Description |
29
29
  | :--- | :--- | :--- | :--- | :--- |
30
- | `wikiRoot` | `string` | No | `".wiki"` | Path to the compiled wiki directory. |
30
+ | `wikiRoot` | `string` | No | `".wiki"` | Path to the compiled wiki directory; a relative path is resolved against `workspaceRoot`, an absolute path is used as-is. |
31
31
  | `rawRoots` | `readonly string[]` | No | `["."]` | Directories containing raw source files (code, notes, docs). |
32
32
  | `profile` | `"codebase" \| "pkm" \| "hybrid" \| "auto"` | No | `"auto"` | Operating strategy for parsing and symbol indexing. |
33
33
  | `qmdPath` | `string` | No | `"qmd"` | Path or executable name for the `qmd` CLI binary. |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@arnilo/prism",
3
- "version": "0.5.6",
3
+ "version": "0.6.0",
4
4
  "description": "Agent harness for AI providers, agents, sessions, and tools.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -139,7 +139,7 @@
139
139
  "typecheck": "npm run build && npm run typecheck --workspaces --if-present && tsc -p examples --noEmit",
140
140
  "sweep:unused": "node scripts/sweep-unused.mjs --json",
141
141
  "test:live": "node scripts/live-matrix.mjs",
142
- "test": "npm run build && node scripts/with-build-lock.mjs node --test dist/__tests__/*.test.js && node scripts/with-build-lock.mjs node --test scripts/release-gate.test.mjs scripts/tooling-gate.test.mjs scripts/budget-gate.test.mjs scripts/phase8-conformance.test.mjs scripts/phase9-conformance.test.mjs scripts/phase10-conformance.test.mjs scripts/phase11-conformance.test.mjs scripts/benchmark-0.1.0.test.mjs scripts/benchmark-multi-agent.test.mjs scripts/benchmark-tool-search.test.mjs scripts/benchmark-workflow-loop.test.mjs scripts/sweep-unused.test.mjs scripts/dead-export-verify.test.mjs scripts/e2e-enterprise-journey.test.mjs scripts/e2e-coding-journey.test.mjs scripts/e2e-full-surface.test.mjs scripts/phase23-quality-gates.test.mjs scripts/phase24-truth.test.mjs scripts/phase25-bounded-accumulation.test.mjs scripts/phase27-ha.test.mjs scripts/phase27-erp-journey.test.mjs scripts/phase37-provider-matrix.test.mjs scripts/phase26-index-benchmark.test.mjs scripts/obscura-host-conformance.test.mjs scripts/phase54-package-map.test.mjs scripts/phase54-legacy-registry.test.mjs scripts/truth-current.test.mjs scripts/packaging-current.test.mjs scripts/import-hygiene.test.mjs scripts/live-matrix.test.mjs scripts/e2e-coverage.test.mjs scripts/live-doc-check.test.mjs && node --test scripts/phase23-build-race.test.mjs && npm run test --workspaces --if-present",
142
+ "test": "node scripts/run-all-tests.mjs",
143
143
  "test:coverage": "node scripts/with-build-lock.mjs node --test --experimental-test-coverage --test-coverage-lines=60 --test-coverage-functions=70 --test-coverage-branches=75 --test-coverage-exclude='**/__tests__/**' --test-coverage-exclude='**/node_modules/**' --test-coverage-exclude='**/scripts/**' --test-coverage-exclude='**/packages/**' --test-coverage-exclude='**/examples/**' dist/__tests__/*.test.js && node scripts/with-build-lock.mjs node scripts/coverage-summary.mjs && node --test scripts/phase23-coverage.test.mjs && node --test scripts/phase23-skip-manifest.test.mjs",
144
144
  "coverage:summary": "node scripts/with-build-lock.mjs node scripts/coverage-summary.mjs",
145
145
  "lint": "biome lint . --reporter=sarif --reporter-file=scripts/lint-report.sarif",
@@ -157,12 +157,12 @@
157
157
  "security:threat-suites": "node --test scripts/phase8-conformance.test.mjs scripts/phase9-conformance.test.mjs scripts/phase10-conformance.test.mjs scripts/phase11-conformance.test.mjs scripts/phase20-security.test.mjs scripts/phase21-security.test.mjs scripts/phase22-security.test.mjs scripts/phase23-security.test.mjs scripts/phase38-codeql-regression.test.mjs scripts/phase40-security.test.mjs scripts/phase46-webhooks-security.test.mjs dist/__tests__/pinned-fetch.test.js packages/prism-core/dist/runtime/server/__tests__/webhooks.test.js"
158
158
  },
159
159
  "devDependencies": {
160
- "@biomejs/biome": "^2.5.11",
161
- "@types/node": "^26.1.1",
160
+ "@biomejs/biome": "^2.5.13",
161
+ "@types/node": "^22.20.0",
162
162
  "typescript": "^7.0.2"
163
163
  },
164
164
  "engines": {
165
- "node": ">=20"
165
+ "node": ">=22"
166
166
  },
167
167
  "license": "MIT",
168
168
  "repository": {