@arnilo/prism 0.3.2 → 0.5.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 +50 -1
- package/README.md +42 -62
- package/dist/agent-run-lifecycle.js +4 -0
- package/dist/agent-run-state.d.ts +5 -2
- package/dist/agent-run-state.js +18 -8
- package/dist/agent-session/session/assemble.d.ts +6 -0
- package/dist/agent-session/session/assemble.js +391 -0
- package/dist/agent-session/session/persist.d.ts +28 -0
- package/dist/agent-session/session/persist.js +166 -0
- package/dist/agent-session/session/provider-round.d.ts +6 -0
- package/dist/agent-session/session/provider-round.js +231 -0
- package/dist/agent-session/session/tool-round.d.ts +31 -0
- package/dist/agent-session/session/tool-round.js +473 -0
- package/dist/agent-session/session/types.d.ts +115 -0
- package/dist/agent-session/session/types.js +5 -0
- package/dist/agent-session/session.d.ts +54 -41
- package/dist/agent-session/session.js +23 -1132
- package/dist/capture.d.ts +63 -0
- package/dist/capture.js +67 -0
- package/dist/cli-dev.d.ts +29 -0
- package/dist/cli-dev.js +52 -0
- package/dist/cli-init.d.ts +34 -3
- package/dist/cli-init.js +192 -24
- package/dist/cli-runner.d.ts +6 -2
- package/dist/cli-runner.js +57 -10
- package/dist/content.d.ts +3 -3
- package/dist/content.js +3 -1
- package/dist/contracts-core/agent.d.ts +8 -0
- package/dist/contracts-core/batch.d.ts +97 -0
- package/dist/contracts-core/batch.js +65 -0
- package/dist/contracts-core/content.d.ts +72 -1
- package/dist/contracts-core/embeddings.d.ts +30 -0
- package/dist/contracts-core/embeddings.js +17 -0
- package/dist/contracts-core/images.d.ts +60 -0
- package/dist/contracts-core/images.js +17 -0
- package/dist/contracts-core/moderation.d.ts +46 -0
- package/dist/contracts-core/moderation.js +34 -0
- package/dist/contracts-core/speech.d.ts +39 -0
- package/dist/contracts-core/speech.js +17 -0
- package/dist/contracts-core/transcription.d.ts +48 -0
- package/dist/contracts-core/transcription.js +17 -0
- package/dist/contracts-core/video.d.ts +61 -0
- package/dist/contracts-core/video.js +17 -0
- package/dist/contracts-core.d.ts +7 -0
- package/dist/contracts-core.js +7 -0
- package/dist/contracts-protocol.d.ts +18 -0
- package/dist/contracts-run-state.d.ts +1 -2
- package/dist/index.d.ts +7 -3
- package/dist/index.js +5 -3
- package/dist/input.d.ts +8 -0
- package/dist/input.js +4 -0
- package/dist/node/agent-definitions.d.ts +1 -8
- package/dist/node/agent-definitions.js +0 -34
- package/dist/node/settings.d.ts +0 -1
- package/dist/node/settings.js +0 -5
- package/dist/pinned-fetch.js +29 -3
- package/dist/provider-events.js +3 -4
- package/dist/providers/media.d.ts +1 -2
- package/dist/providers/media.js +1 -4
- package/dist/rpc.d.ts +1 -1
- package/dist/rpc.js +4 -4
- package/dist/testing/persistence-schema.d.ts +1 -1
- package/dist/testing/persistence-schema.js +32 -28
- package/dist/testing/provider-conformance.d.ts +114 -5
- package/dist/testing/provider-conformance.js +342 -0
- package/dist/testing/tool-conformance.d.ts +25 -0
- package/dist/testing/tool-conformance.js +128 -1
- package/dist/testing/tool-effect-store-conformance.d.ts +0 -1
- package/dist/testing/tool-effect-store-conformance.js +0 -3
- package/dist/thinking.d.ts +48 -9
- package/dist/thinking.js +134 -8
- package/dist/tool-search.d.ts +76 -0
- package/dist/tool-search.js +199 -0
- package/docs/0.1.0-readiness.md +3 -3
- package/docs/a2a.md +2 -2
- package/docs/acp-agent.md +1 -1
- package/docs/acp.md +3 -3
- package/docs/ag-ui-adoption.md +1 -1
- package/docs/ag-ui.md +1 -2
- package/docs/agent-definitions.md +1 -1
- package/docs/agent-events.md +5 -5
- package/docs/agent-identity.md +13 -2
- package/docs/audit-export.md +3 -3
- package/docs/batch-jobs.md +120 -0
- package/docs/browser-automation.md +5 -5
- package/docs/caveman.md +2 -2
- package/docs/cli-rpc.md +43 -9
- package/docs/coding-agent-tools.md +19 -19
- package/docs/coding-review-and-diagnostics.md +2 -2
- package/docs/coding-security.md +5 -5
- package/docs/coding-tools.md +82 -0
- package/docs/coding-workspaces.md +2 -2
- package/docs/compaction-and-retry.md +2 -2
- package/docs/compaction-llm.md +4 -4
- package/docs/compaction-observational-memory.md +3 -3
- package/docs/computer-use-linux.md +13 -2
- package/docs/context-and-skills.md +3 -1
- package/docs/conversations.md +4 -4
- package/docs/core.md +85 -0
- package/docs/credential-storage.md +12 -8
- package/docs/credentials-and-redaction.md +1 -1
- package/docs/data-classification.md +1 -1
- package/docs/database-persistence.md +7 -3
- package/docs/dev-inspector.md +103 -0
- package/docs/device-adapters.md +2 -2
- package/docs/diagrams.md +247 -0
- package/docs/document-reader.md +6 -6
- package/docs/documents.md +214 -0
- package/docs/embeddings.md +112 -0
- package/docs/enterprise-postgres-state.md +7 -7
- package/docs/evaluations.md +41 -7
- package/docs/extensions.md +3 -3
- package/docs/forge-integration.md +3 -3
- package/docs/graft.md +5 -5
- package/docs/guardrails.md +2 -2
- package/docs/host-security.md +16 -15
- package/docs/image-generation.md +129 -0
- package/docs/impeccable.md +7 -5
- package/docs/index.md +84 -46
- package/docs/indexed-code-search.md +2 -2
- package/docs/language-intelligence.md +4 -4
- package/docs/live-testing.md +126 -0
- package/docs/mcp-tools.md +44 -13
- package/docs/middleware-hooks.md +1 -1
- package/docs/migrate-to-0.4.md +312 -0
- package/docs/migrate-to-0.5.md +122 -0
- package/docs/migration.md +51 -1
- package/docs/model-registry.md +38 -0
- package/docs/model-routing.md +6 -6
- package/docs/moderation.md +117 -0
- package/docs/multi-agent-patterns.md +177 -0
- package/docs/multimodal-content.md +27 -3
- package/docs/obscura.md +12 -12
- package/docs/observability.md +32 -7
- package/docs/openapi-tools.md +14 -4
- package/docs/operations.md +11 -0
- package/docs/performance.md +30 -10
- package/docs/persistence-credentials-multimodality-primitives.md +7 -7
- package/docs/policy-and-audit.md +18 -8
- package/docs/ponytail.md +3 -3
- package/docs/postgres-persistence.md +5 -5
- package/docs/process-sessions.md +2 -2
- package/docs/prompt-registry.md +106 -0
- package/docs/provider-caching.md +36 -32
- package/docs/provider-conformance.md +24 -2
- package/docs/provider-packages.md +58 -22
- package/docs/provider-primitives.md +5 -5
- package/docs/provider-request-policies.md +1 -1
- package/docs/providers/ai-sdk.md +18 -6
- package/docs/providers/alibaba.md +10 -6
- package/docs/providers/anthropic.md +10 -6
- package/docs/providers/azure.md +20 -4
- package/docs/providers/bedrock.md +18 -3
- package/docs/providers/clinepass.md +7 -3
- package/docs/providers/commandcode.md +253 -0
- package/docs/providers/deepseek.md +7 -3
- package/docs/providers/google.md +8 -4
- package/docs/providers/hyper.md +284 -0
- package/docs/providers/kimi.md +7 -3
- package/docs/providers/neuralwatt.md +12 -8
- package/docs/providers/ollama.md +18 -3
- package/docs/providers/openai-compatible.md +5 -1
- package/docs/providers/openai.md +9 -5
- package/docs/providers/opencode-go.md +8 -4
- package/docs/providers/openrouter.md +8 -4
- package/docs/providers/vertex.md +21 -5
- package/docs/providers/xai.md +7 -3
- package/docs/providers/zai.md +7 -3
- package/docs/rag.md +31 -9
- package/docs/release-and-install.md +181 -76
- package/docs/resource-loading.md +1 -1
- package/docs/runs-and-usage.md +28 -3
- package/docs/server.md +94 -5
- package/docs/settings-auth-trust-security.md +7 -5
- package/docs/sheets.md +229 -0
- package/docs/speech.md +126 -0
- package/docs/sqlite-persistence.md +4 -4
- package/docs/supervisors.md +4 -3
- package/docs/thinking-and-reasoning.md +93 -60
- package/docs/tool-conformance.md +28 -3
- package/docs/tool-execution-primitives.md +8 -8
- package/docs/tools.md +32 -5
- package/docs/web-tools.md +3 -3
- package/docs/wiki.md +7 -7
- package/docs/work-artifacts-and-review.md +17 -6
- package/docs/work-connectors.md +4 -4
- package/docs/work-tools.md +5 -5
- package/docs/workflow-orchestration-primitives.md +35 -11
- package/docs/workflows.md +74 -13
- package/docs/working-and-semantic-memory.md +53 -5
- package/package.json +14 -31
- package/templates/README.md +23 -0
- package/templates/deep-research/README.md.tmpl +47 -0
- package/templates/deep-research/env.example.tmpl +12 -0
- package/templates/deep-research/gitignore.tmpl +7 -0
- package/templates/deep-research/manifest.json +12 -0
- package/templates/deep-research/package.json.tmpl +23 -0
- package/templates/deep-research/src/agent.ts.tmpl +81 -0
- package/templates/deep-research/src/index.ts.tmpl +53 -0
- package/templates/deep-research/src/tests/research.test.ts.tmpl +114 -0
- package/templates/deep-research/src/tools.ts.tmpl +86 -0
- package/templates/deep-research/src/types.ts.tmpl +45 -0
- package/templates/deep-research/src/workflow.ts.tmpl +156 -0
- package/templates/deep-research/tsconfig.json.tmpl +15 -0
- package/templates/init/manifest.json +5 -0
- package/templates/init/package.json.tmpl +2 -1
- package/templates/init/providers.json +40 -24
- package/docs/antigravity-agent.md +0 -207
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
# Documents, spreadsheets, and presentations (`@arnilo/prism-office/documents`)
|
|
2
|
+
|
|
3
|
+
## What it does
|
|
4
|
+
|
|
5
|
+
The `@arnilo/prism-office/documents` package provides specification-compliant, AI-native OpenXML document generation, parsing, patching, and bounded preview rendering for Microsoft Word (`.docx`), Microsoft Excel (`.xlsx`), and Microsoft PowerPoint (`.pptx`) artifacts.
|
|
6
|
+
|
|
7
|
+
It operates on a canonical, typed abstract syntax tree (AST) called the **Prism Document Model** (`DocModel`, `SheetModel`, `DeckModel`):
|
|
8
|
+
- **Pure in-memory doctrine**: Functions accept `Uint8Array` container buffers or typed model objects and emit `Uint8Array` buffers or JSON models. Zero filesystem reads, zero network I/O, zero `process.env` lookups, and zero child process spawns.
|
|
9
|
+
- **Draft-07 JSON Schema validation & slicing**: Full runtime structural validation with transitive closure slicing (`getDocumentModelSchema`) allowing LLM tools and agent prompts to extract minimal, self-contained sub-schemas (e.g. `doc.paragraph`, `doc.table`).
|
|
10
|
+
- **Bidirectional round-trip fidelity**: Prism-generated documents parse back into structurally equivalent models verified against a per-kind equality specification.
|
|
11
|
+
- **Typed model patch engine**: Immutably applies `set`, `insert`, `remove`, and `move` operations to document blocks, worksheet cells, and presentation slides with schema re-validation and an interactive `createPatchHistory` undo/redo stack.
|
|
12
|
+
- **Framework-neutral preview blocks & bounded HTML**: Generates structured snapshots (`PreviewBlock[]`) for native desktop/web UI grids and outline trees, as well as safe, sanitize-by-construction HTML fragments (`renderPreviewHtml`) guaranteed to contain no executable scripts, no active pseudo-protocols, and no external hyperlinks.
|
|
13
|
+
- **Boundary text redaction**: Pluggable `SecretRedactor` hook to sanitize extracted text content (paragraphs, cells, notes, tables) at the parse boundary before models are returned.
|
|
14
|
+
- **Dependency-free telemetry seam**: Zero-overhead `DocumentsTelemetry` hook for OpenTelemetry-compatible span tracing without leaking document or chunk text into telemetry collectors.
|
|
15
|
+
|
|
16
|
+
## When to use it
|
|
17
|
+
|
|
18
|
+
Use `@arnilo/prism-office/documents` whenever autonomous agents, coding assistants, workflow orchestrators, or enterprise applications need to:
|
|
19
|
+
1. Synthesize professional DOCX reports, financial XLSX spreadsheets, or PPTX presentation decks from structured LLM outputs.
|
|
20
|
+
2. Ingest existing OOXML artifacts into a structured, validated document model for analysis or automated summarization.
|
|
21
|
+
3. Perform atomic, validated updates or localized edits to documents using typed patch operations.
|
|
22
|
+
4. Render safe, bounded HTML previews or framework-neutral outline and grid snapshots in web and desktop hosts.
|
|
23
|
+
|
|
24
|
+
Do **not** use this package for collaborative real-time editing (OT/CRDT), macro execution, or in-memory spreadsheet formula evaluation (formulas are preserved verbatim as `{ formula, cachedValue? }` read-only pairs).
|
|
25
|
+
|
|
26
|
+
## Inputs / request
|
|
27
|
+
|
|
28
|
+
### Generation & Parsing Functions
|
|
29
|
+
|
|
30
|
+
| Function | Signature | Description |
|
|
31
|
+
| --- | --- | --- |
|
|
32
|
+
| `generateDocument` | `(model: DocumentModel, options: GenerateDocumentOptions) => Promise<GenerateDocumentResult>` | Translates a typed model into spec-compliant OOXML binary bytes (PK zip container) with a SHA-256 content hash. |
|
|
33
|
+
| `parseDocument` | `(bytes: Uint8Array, options: ParseDocumentOptions) => Promise<DocumentModel>` | Verifies PK zip signature, enforces caps, translates OOXML parts, applies optional redaction, and returns a validated model. |
|
|
34
|
+
| `patchDocument` | `(model: DocumentModel, patches: readonly DocumentPatch[], options?: PatchDocumentOptions) => DocumentModel` | Clones the model, applies typed structural patch operations, and validates the resulting model against Draft-07 schemas. |
|
|
35
|
+
| `createPatchHistory` | `(initialModel: DocumentModel) => PatchHistory` | Creates an interactive undo/redo history manager for host editing workflows. |
|
|
36
|
+
| `renderPreviewBlocks` | `(model: DocumentModel, options?: PreviewBlocksOptions) => PreviewBlock[]` | Emits framework-neutral structured blocks (document outlines, bounded sheet grid chunks, slide summaries). |
|
|
37
|
+
| `renderPreviewHtml` | `(model: DocumentModel, options?: PreviewHtmlOptions) => string` | Emits safe, bounded HTML fragments with all entities escaped and external URLs neutralized. |
|
|
38
|
+
| `getDocumentModelSchema`| `(options: GetDocumentModelSchemaOptions) => Record<string, unknown>` | Retrieves full Draft-07 JSON Schema or a self-contained sliced sub-schema with resolved `$defs`. |
|
|
39
|
+
| `validateDocumentModel`| `(model: unknown) => asserts model is DocumentModel` | Validates arbitrary JSON objects against Draft-07 document schemas and structural invariants. |
|
|
40
|
+
|
|
41
|
+
### Capacity Limits and Defaults
|
|
42
|
+
|
|
43
|
+
Caps are strictly enforced in memory before compute-intensive translation or parsing:
|
|
44
|
+
|
|
45
|
+
| Cap | Default | Hard Ceiling | Target |
|
|
46
|
+
| --- | --- | --- | --- |
|
|
47
|
+
| `maxBytes` | 32 MiB (`33,554,432`) | 512 MiB (`536,870,912`) | Binary input buffer & generated OOXML bytes |
|
|
48
|
+
| `maxBlocks` | 10,000 | 50,000 | Total blocks in a `DocModel` |
|
|
49
|
+
| `maxSheets` | 50 | 250 | Worksheets in a `SheetModel` |
|
|
50
|
+
| `maxRows` | 100,000 | 1,000,000 | Rows per worksheet |
|
|
51
|
+
| `maxColumns` | 1,000 | 16,384 | Columns per worksheet |
|
|
52
|
+
| `maxCells` | 1,000,000 | 10,000,000 | Total cells across all worksheets |
|
|
53
|
+
| `maxSlides` | 500 | 2,000 | Total slides in a `DeckModel` |
|
|
54
|
+
| `maxParagraphs` | 10,000 | 50,000 | Total paragraphs in a document |
|
|
55
|
+
| `maxRuns` | 50,000 | 250,000 | Total formatted text runs in a document |
|
|
56
|
+
|
|
57
|
+
## Outputs / response / events
|
|
58
|
+
|
|
59
|
+
### Error Hierarchy
|
|
60
|
+
|
|
61
|
+
All package operations throw typed exceptions derived from `DocumentsError`:
|
|
62
|
+
|
|
63
|
+
| Error Class | Error Code | Trigger Condition |
|
|
64
|
+
| --- | --- | --- |
|
|
65
|
+
| `DocumentsValidationError` | `ERR_PRISM_DOCUMENTS_INVALID_MODEL` | Input JSON fails Draft-07 schema validation, has dimension mismatches, or invalid decimal string syntax. |
|
|
66
|
+
| `DocumentsCapExceededError` | `ERR_PRISM_DOCUMENTS_CAP_EXCEEDED` | Document exceeds byte size, block count, cell count, or slide count caps. |
|
|
67
|
+
| `DocumentsParseError` | `ERR_PRISM_DOCUMENTS_PARSE_FAILED` | Input buffer lacks PK zip signature, is corrupted, or fails OOXML part parsing. |
|
|
68
|
+
| `DocumentsFormatError` | `ERR_PRISM_DOCUMENTS_UNSUPPORTED_FORMAT` | Format mismatch (e.g. attempting to generate PPTX from a `DocModel`). |
|
|
69
|
+
| `DocumentsPatchError` | `ERR_PRISM_DOCUMENTS_UNSAFE_PATH` | `__proto__`, `prototype`, or `constructor` appears as a `metadata` target or inside a block/slide/sheet `patch` segment (rejected before mutation to prevent `Object.prototype` pollution). |
|
|
70
|
+
| `DocumentsPatchError` | `ERR_PRISM_DOCUMENTS_PATCH_FAILED` | Out-of-bounds index target, unknown patch operation, or invalid patch structure. |
|
|
71
|
+
|
|
72
|
+
## Request/response example
|
|
73
|
+
|
|
74
|
+
### JSON Schema Document Models
|
|
75
|
+
|
|
76
|
+
```json
|
|
77
|
+
{
|
|
78
|
+
"kind": "sheet",
|
|
79
|
+
"modelVersion": 1,
|
|
80
|
+
"title": "Q3 Financial Summary",
|
|
81
|
+
"sheets": [
|
|
82
|
+
{
|
|
83
|
+
"name": "Revenue",
|
|
84
|
+
"columnWidths": [{ "column": 0, "width": 25 }, { "column": 1, "width": 15 }],
|
|
85
|
+
"frozenPanes": { "rows": 1, "columns": 0 },
|
|
86
|
+
"cells": [
|
|
87
|
+
["Department", "Operating Budget", "Actual Expense"],
|
|
88
|
+
["Engineering", { "type": "decimal", "value": "1500000.00" }, { "type": "decimal", "value": "1420000.50" }],
|
|
89
|
+
["Operations", { "type": "decimal", "value": "450000.00" }, { "type": "decimal", "value": "435000.00" }],
|
|
90
|
+
["Total", { "formula": "=SUM(B2:B3)", "cachedValue": 1950000 }, { "formula": "=SUM(C2:C3)", "cachedValue": 1855000.5 }]
|
|
91
|
+
]
|
|
92
|
+
}
|
|
93
|
+
]
|
|
94
|
+
}
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
## Implementation example
|
|
98
|
+
|
|
99
|
+
```ts
|
|
100
|
+
import {
|
|
101
|
+
generateDocument,
|
|
102
|
+
parseDocument,
|
|
103
|
+
patchDocument,
|
|
104
|
+
createPatchHistory,
|
|
105
|
+
renderPreviewBlocks,
|
|
106
|
+
renderPreviewHtml,
|
|
107
|
+
type DocModel,
|
|
108
|
+
} from "@arnilo/prism-office/documents";
|
|
109
|
+
|
|
110
|
+
// 1. Define typed document model
|
|
111
|
+
const doc: DocModel = {
|
|
112
|
+
kind: "doc",
|
|
113
|
+
modelVersion: 1,
|
|
114
|
+
title: "Architecture Review",
|
|
115
|
+
blocks: [
|
|
116
|
+
{ type: "heading", level: 1, text: "System Architecture" },
|
|
117
|
+
{
|
|
118
|
+
type: "paragraph",
|
|
119
|
+
runs: [
|
|
120
|
+
{ text: "Prism operates purely in memory with ", bold: false },
|
|
121
|
+
{ text: "zero-trust security boundaries.", bold: true, italic: true },
|
|
122
|
+
],
|
|
123
|
+
},
|
|
124
|
+
{
|
|
125
|
+
type: "table",
|
|
126
|
+
rows: 2,
|
|
127
|
+
columns: 2,
|
|
128
|
+
cells: [
|
|
129
|
+
["Module", "Latency"],
|
|
130
|
+
["Parser", "12ms"],
|
|
131
|
+
],
|
|
132
|
+
},
|
|
133
|
+
],
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
// 2. Generate in-memory DOCX binary with SHA-256 contentHash
|
|
137
|
+
const { bytes, contentHash } = await generateDocument(doc, { format: "docx" });
|
|
138
|
+
console.log(`Generated DOCX (${bytes.byteLength} bytes, SHA-256: ${contentHash})`);
|
|
139
|
+
|
|
140
|
+
// 3. Parse OOXML bytes back to a validated model
|
|
141
|
+
const parsed = await parseDocument(bytes, { kind: "doc" });
|
|
142
|
+
|
|
143
|
+
// 4. Apply typed model patches
|
|
144
|
+
const patched = patchDocument(parsed, [
|
|
145
|
+
{ op: "set", target: { block: 0 }, block: { type: "heading", level: 1, text: "Executive Summary" } },
|
|
146
|
+
{ op: "insert", target: { afterBlock: 0 }, block: { type: "paragraph", text: "New introduction." } },
|
|
147
|
+
]);
|
|
148
|
+
|
|
149
|
+
// 5. Interactive Undo/Redo editing
|
|
150
|
+
const history = createPatchHistory(patched);
|
|
151
|
+
history.apply([{ op: "set", target: { title: true }, value: "Updated Review" }]);
|
|
152
|
+
console.log(history.canUndo()); // true
|
|
153
|
+
const restored = history.undo(); // restored to "Executive Summary" state
|
|
154
|
+
|
|
155
|
+
// 6. Generate structured preview blocks & safe HTML
|
|
156
|
+
const blocks = renderPreviewBlocks(restored);
|
|
157
|
+
const htmlSnippet = renderPreviewHtml(restored, { maxHtmlBytes: 256 * 1024 });
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
## Extension and configuration notes
|
|
161
|
+
|
|
162
|
+
### Sub-package Pinning
|
|
163
|
+
To avoid pulling in CLI frameworks or extraneous dependencies, `@arnilo/prism-office/documents` directly pins the exact underlying modular packages:
|
|
164
|
+
- `@office-open/docx@0.12.3`
|
|
165
|
+
- `@office-open/xlsx@0.12.3`
|
|
166
|
+
- `@office-open/pptx@0.12.3`
|
|
167
|
+
|
|
168
|
+
### Draft-07 JSON Schema Slicing
|
|
169
|
+
For AI agent tool generation where token budgets are constrained, `getDocumentModelSchema` provides closure slicing:
|
|
170
|
+
```ts
|
|
171
|
+
// Returns only TableBlock, CellValue, and their transitively required definitions in $defs
|
|
172
|
+
const tableSchema = getDocumentModelSchema({ kind: "doc", slice: "table" });
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
### Text Redaction Hook (`SecretRedactor`)
|
|
176
|
+
When parsing untrusted or sensitive OOXML containers, hosts can inject a redaction hook to scrub PII or secrets before the document model enters memory:
|
|
177
|
+
```ts
|
|
178
|
+
const sanitizedModel = await parseDocument(rawBytes, {
|
|
179
|
+
kind: "doc",
|
|
180
|
+
redactor: {
|
|
181
|
+
redact: (text: string) => text.replace(/\b\d{3}-\d{2}-\d{4}\b/g, "[REDACTED-SSN]"),
|
|
182
|
+
},
|
|
183
|
+
});
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
### Telemetry Seam
|
|
187
|
+
The dependency-free `DocumentsTelemetry` seam allows optional OpenTelemetry instrumentation without adding runtime telemetry dependencies:
|
|
188
|
+
```ts
|
|
189
|
+
const telemetry: DocumentsTelemetry = {
|
|
190
|
+
startSpan(name, attributes) {
|
|
191
|
+
// Maps to tracer.startSpan with allow-listed metadata (kind, format, bytes, counts)
|
|
192
|
+
// Model content and document text are NEVER passed to telemetry spans.
|
|
193
|
+
return activeSpan;
|
|
194
|
+
},
|
|
195
|
+
};
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
### Decimal Fidelity Ceiling
|
|
199
|
+
Financial worksheets often require exact decimal representations that JavaScript 64-bit binary floating-point numbers cannot represent without precision loss. `@arnilo/prism-office/documents` supports canonical string decimals (`{ type: "decimal", value: "1500000.00" }`), preserving exact numerical formatting without IEEE 754 precision artifacts.
|
|
200
|
+
|
|
201
|
+
## Security and performance notes
|
|
202
|
+
|
|
203
|
+
- **Pure In-Memory Operation**: No temporary files, no shell execution, no binary spawning, and zero network sockets.
|
|
204
|
+
- **ZIP Signature Gating**: Buffers must begin with PK zip container signatures (`0x50, 0x4B, 0x03, 0x04`). Extension-based type inference is strictly prohibited.
|
|
205
|
+
- **Fail-Closed Caps**: Input size and element count caps are evaluated before entering XML translation passes, preventing zip-bomb and decompression amplification attacks.
|
|
206
|
+
- **Sanitize-by-Construction HTML**: `renderPreviewHtml` strictly entity-encodes all text fields, neutralizes dangerous protocols (`javascript:`, `http://`, `https://`), strips raw script/image tags, and caps output size to prevent DOM-based XSS and memory exhaustion.
|
|
207
|
+
- **Performance Budget**: Warm generation of 200-block documents completes in under 15 ms; parse and round-trip equality checks complete in under 100 ms.
|
|
208
|
+
|
|
209
|
+
## Related APIs
|
|
210
|
+
|
|
211
|
+
- [`@arnilo/prism-coding-tools/document-reader`](./document-reader.md): Bounded literal text extraction from PDF and DOCX documents for coding agent tools.
|
|
212
|
+
- [`@arnilo/prism-core/integrations/work`](./work-tools.md): Microsoft 365 and Google Workspace identity-scoped connectors.
|
|
213
|
+
- [`@arnilo/prism-coding-tools/agent`](./coding-agent-tools.md): Coding tools and file operations.
|
|
214
|
+
- [`@arnilo/prism-core/governance/observability`](./observability.md): OpenTelemetry instrumentation and trace adapters.
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
# Embeddings
|
|
2
|
+
|
|
3
|
+
## What it does
|
|
4
|
+
|
|
5
|
+
`EmbeddingsProvider` is the provider-neutral embeddings contract: one-shot batch
|
|
6
|
+
text→vector generation with usage accounting, per-item error mapping, and
|
|
7
|
+
capability-gated models. First-party adapters ship in
|
|
8
|
+
[`@arnilo/prism-providers/openai`](providers/openai.md) (OpenAI-compatible
|
|
9
|
+
`POST {base}/embeddings`) and [`@arnilo/prism-providers/alibaba`](providers/alibaba.md)
|
|
10
|
+
(DashScope `compatible-mode/v1/embeddings`); offline conformance runs via
|
|
11
|
+
`runEmbeddingsConformance` from `@arnilo/prism/testing/provider-conformance`.
|
|
12
|
+
|
|
13
|
+
## When to use it
|
|
14
|
+
|
|
15
|
+
Use it when a host owns its embedding pipeline (RAG ingestion, memory indexing,
|
|
16
|
+
semantic search) and wants a portable contract instead of per-provider HTTP code.
|
|
17
|
+
Do not use it as a live integration runner: the contract is caller-gated, adapters
|
|
18
|
+
perform no network on construction, and batch caps are enforced with typed errors
|
|
19
|
+
rather than silent auto-chunking — chunk callers themselves (for example,
|
|
20
|
+
`@arnilo/prism-memory`'s `embedBatched`).
|
|
21
|
+
|
|
22
|
+
## Inputs / request
|
|
23
|
+
|
|
24
|
+
| Field | Type | Meaning |
|
|
25
|
+
| --- | --- | --- |
|
|
26
|
+
| `model` | `string` | Embedding model id, e.g. `text-embedding-3-small` or `text-embedding-v4`. |
|
|
27
|
+
| `inputs` | `readonly string[]` | Texts to embed; order is preserved on `result.vectors`. Non-empty and within the provider batch cap. |
|
|
28
|
+
| `dimensions` | `number?` | Output-dimensions override; only for models that support reduced dimensions (OpenAI `dimensions` param, DashScope 64–2048). |
|
|
29
|
+
| `signal` | `AbortSignal?` | Cancellation; observed by the adapter transport. |
|
|
30
|
+
|
|
31
|
+
Adapter options: `apiKey` (`CredentialValueSource` — the existing credential seam,
|
|
32
|
+
resolved per call and redacted from errors), `baseUrl`/`preset` (Alibaba),
|
|
33
|
+
`fetch` (inject a fake transport for offline tests), `headers`, and default
|
|
34
|
+
`dimensions`/`encodingFormat` where the provider supports them.
|
|
35
|
+
|
|
36
|
+
## Outputs / response / events
|
|
37
|
+
|
|
38
|
+
| Field | Type | Meaning |
|
|
39
|
+
| --- | --- | --- |
|
|
40
|
+
| `vectors` | `readonly (readonly number[])[]` | Vectors in input order; `vectors[i]` corresponds to `inputs[i]`. |
|
|
41
|
+
| `usage` | `Usage` | Provider-reported token usage (`inputTokens`, `totalTokens`); empty object when the provider omits it. |
|
|
42
|
+
| `dimensions` | `number` | Actual vector dimensionality reported by the response. |
|
|
43
|
+
|
|
44
|
+
Failures throw `EmbeddingsError` with a stable `code`:
|
|
45
|
+
`empty_input` (no inputs), `batch_too_large` (over the provider cap — OpenAI 2048,
|
|
46
|
+
DashScope 10), `request_failed` (non-2xx, secret-redacted message),
|
|
47
|
+
`response_malformed` (missing index, wrong dimensionality), `unsupported_model`
|
|
48
|
+
(via `assertEmbeddingsSupported` when the host checks
|
|
49
|
+
`ModelCapabilities.embeddings`).
|
|
50
|
+
|
|
51
|
+
## Request/response example
|
|
52
|
+
|
|
53
|
+
```json
|
|
54
|
+
{ "model": "text-embedding-3-small", "input": ["hello", "world"], "dimensions": 256 }
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## Implementation example
|
|
58
|
+
|
|
59
|
+
```ts
|
|
60
|
+
import { createOpenAIEmbeddingsProvider } from "@arnilo/prism-providers/openai";
|
|
61
|
+
import { runEmbeddingsConformance } from "@arnilo/prism/testing/provider-conformance";
|
|
62
|
+
|
|
63
|
+
const embeddings = createOpenAIEmbeddingsProvider({ apiKey: process.env.OPENAI_API_KEY });
|
|
64
|
+
const result = await embeddings.embedMany({
|
|
65
|
+
model: "text-embedding-3-small",
|
|
66
|
+
inputs: ["hello", "world"],
|
|
67
|
+
});
|
|
68
|
+
// result.vectors.length === 2; result.usage.inputTokens reported
|
|
69
|
+
|
|
70
|
+
// Offline conformance (fake transport, no network):
|
|
71
|
+
await runEmbeddingsConformance({
|
|
72
|
+
provider: createOpenAIEmbeddingsProvider({ apiKey: "sk-test", fetch: fakeFetch }),
|
|
73
|
+
model: "text-embedding-3-small",
|
|
74
|
+
maxBatchSize: 2048,
|
|
75
|
+
sample: { inputs: ["a", "b"], dimensions: 2 },
|
|
76
|
+
});
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## Extension and configuration notes
|
|
80
|
+
|
|
81
|
+
- Implement `EmbeddingsProvider` (`{ id, embedMany }`) for other vendors; the
|
|
82
|
+
contract is structural — no base class, no registry.
|
|
83
|
+
- Models declare support with `capabilities.embeddings`; hosts gate with
|
|
84
|
+
`modelSupportsEmbeddings(capabilities)` / `assertEmbeddingsSupported(model)`,
|
|
85
|
+
mirroring the structured-output guard pattern.
|
|
86
|
+
- `@arnilo/prism-memory` keeps its dependency-free `Embedder` host seam; adapters
|
|
87
|
+
bridge structurally (`createAlibabaEmbedder` remains assignable to `Embedder`
|
|
88
|
+
without importing it). The contract is a superset: it adds usage and per-item
|
|
89
|
+
error mapping.
|
|
90
|
+
- Adapters never auto-chunk: a batch over the provider cap rejects with
|
|
91
|
+
`batch_too_large`, so `embedBatched`-style callers own batching and preserve
|
|
92
|
+
per-item error attribution.
|
|
93
|
+
|
|
94
|
+
## Security and performance notes
|
|
95
|
+
|
|
96
|
+
- API keys resolve through the existing `CredentialValueSource` seam and are
|
|
97
|
+
redacted from every thrown error (`redactSecrets`); no new secret paths.
|
|
98
|
+
- Responses are read through the bounded transport (`readBoundedResponseJson` /
|
|
99
|
+
`readBoundedResponseText`) — response bodies cannot exhaust memory.
|
|
100
|
+
- Input text is never logged; error messages carry status and redacted body only.
|
|
101
|
+
- One HTTP request per `embedMany` call; response mapping allocates one vector
|
|
102
|
+
copy per input and nothing else. Per-item token caps are server-enforced;
|
|
103
|
+
the local cap is batch count.
|
|
104
|
+
|
|
105
|
+
## Related APIs
|
|
106
|
+
|
|
107
|
+
- [`@arnilo/prism-memory`](working-and-semantic-memory.md): `Embedder` host seam and `embedBatched` —
|
|
108
|
+
consumption side of the structural bridge.
|
|
109
|
+
- [Provider conformance](provider-conformance.md): `runEmbeddingsConformance` and
|
|
110
|
+
the offline conformance matrix this contract joins.
|
|
111
|
+
- [Provider packages](provider-packages.md): subpath import rules for
|
|
112
|
+
`@arnilo/prism-providers/openai` and `@arnilo/prism-providers/alibaba`.
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
## What it does
|
|
4
4
|
|
|
5
|
-
`@arnilo/prism-enterprise
|
|
5
|
+
`@arnilo/prism-core/enterprise/postgres` is one optional PostgreSQL composition for existing enterprise state seams:
|
|
6
6
|
|
|
7
7
|
| State | Composition property | Durable behavior |
|
|
8
8
|
| --- | --- | --- |
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
| ERP messaging | `erpMessaging` | Transactional outbox/inbox markers plus bounded, tenant-scoped at-least-once dispatch (migration 004). |
|
|
15
15
|
| Multi-party approvals | `createPostgresApprovalStore({ pool, schema, authority })` | Immutable approval requests, role/quorum decisions, revocation, bounded delegation, and atomic grant consumption (migration 005). |
|
|
16
16
|
|
|
17
|
-
`createPostgresEnterpriseState()` opens a host-supplied or adapter-owned `pg` pool, verifies/applies checksum-protected enterprise migrations (`001_enterprise_state`, `002_tool_effects`, `003_router_reservations`, `004_erp_messaging`, `005_erp_approvals`), and returns those stores plus explicit cleanup and close operations. Importing it performs no I/O. It is separate from session/run persistence in [`@arnilo/prism-
|
|
17
|
+
`createPostgresEnterpriseState()` opens a host-supplied or adapter-owned `pg` pool, verifies/applies checksum-protected enterprise migrations (`001_enterprise_state`, `002_tool_effects`, `003_router_reservations`, `004_erp_messaging`, `005_erp_approvals`), and returns those stores plus explicit cleanup and close operations. Importing it performs no I/O. It is separate from session/run persistence in [`@arnilo/prism-core/sessions/postgres`](postgres-persistence.md).
|
|
18
18
|
|
|
19
19
|
## When to use it
|
|
20
20
|
|
|
@@ -25,7 +25,7 @@ Use memory/file stores only for tests, demos, or a deliberately single-process h
|
|
|
25
25
|
## Inputs / request
|
|
26
26
|
|
|
27
27
|
```ts
|
|
28
|
-
import { createPostgresEnterpriseState } from "@arnilo/prism-enterprise
|
|
28
|
+
import { createPostgresEnterpriseState } from "@arnilo/prism-core/enterprise/postgres";
|
|
29
29
|
import { Pool } from "pg";
|
|
30
30
|
|
|
31
31
|
const pool = new Pool({
|
|
@@ -95,7 +95,7 @@ A migration creates `prism_policy_decisions`, `prism_evaluations`, `prism_work_i
|
|
|
95
95
|
## Implementation example
|
|
96
96
|
|
|
97
97
|
```ts
|
|
98
|
-
import { createPostgresErpMessaging } from "@arnilo/prism-enterprise
|
|
98
|
+
import { createPostgresErpMessaging } from "@arnilo/prism-core/enterprise/postgres";
|
|
99
99
|
|
|
100
100
|
const messaging = createPostgresErpMessaging({ pool, schema: "prism" });
|
|
101
101
|
const client = await pool.connect();
|
|
@@ -141,7 +141,7 @@ await messaging.dispatcher.replay({
|
|
|
141
141
|
|
|
142
142
|
```ts
|
|
143
143
|
import type { AgentIdentity } from "@arnilo/prism";
|
|
144
|
-
import { createPostgresEnterpriseState, type PostgresEnterpriseState } from "@arnilo/prism-enterprise
|
|
144
|
+
import { createPostgresEnterpriseState, type PostgresEnterpriseState } from "@arnilo/prism-core/enterprise/postgres";
|
|
145
145
|
|
|
146
146
|
const identity: AgentIdentity = {
|
|
147
147
|
tenantId: "tenant-1",
|
|
@@ -202,13 +202,13 @@ export async function recordEnterpriseState(state: PostgresEnterpriseState) {
|
|
|
202
202
|
|
|
203
203
|
## Extension and configuration notes
|
|
204
204
|
|
|
205
|
-
- `createModelRouter({ resolver, stateStore: state.modelRouter })` keeps allow-list, residency, fallback, and diagnostics behavior in `@arnilo/prism-model-router`; this package only supplies durable state. Router admission reservations (`reserveBudget`/`commitBudget`/`releaseBudget` on `state.modelRouter`) live in the `reservations` JSONB column of `prism_model_router_budgets`: one atomic UPSERT per admission, fencing-token-guarded commit/release in a SERIALIZABLE transaction, and TTL reconciliation as unknown usage; see [Model routing](model-routing.md).
|
|
205
|
+
- `createModelRouter({ resolver, stateStore: state.modelRouter })` keeps allow-list, residency, fallback, and diagnostics behavior in `@arnilo/prism-core/governance/model-router`; this package only supplies durable state. Router admission reservations (`reserveBudget`/`commitBudget`/`releaseBudget` on `state.modelRouter`) live in the `reservations` JSONB column of `prism_model_router_budgets`: one atomic UPSERT per admission, fencing-token-guarded commit/release in a SERIALIZABLE transaction, and TTL reconciliation as unknown usage; see [Model routing](model-routing.md).
|
|
206
206
|
- `createPostgresErpMessaging({ pool, schema? })` is the direct messaging composition. `outbox.append` and `inbox.record` accept a caller-owned `PoolClient`; the host must put them in the same transaction as its local mutation. The dispatcher owns only short claim/transition transactions and never invokes business callbacks or stores executable handlers.
|
|
207
207
|
- `createPostgresApprovalStore({ pool, schema?, authority })` is the direct approval composition (migration 005). `authority.resolveRoles(actor, request)` and `policyRevision` are host-owned; Prism persists only accepted role grants and delegation chains. `decide`/`revoke` lock the request row and revision-check the terminal transition in one transaction. `consume` accepts an optional caller-owned `client`; grant consumption and the protected action commit (or roll back) together.
|
|
208
208
|
- Rate/budget/circuit tables are capped like the memory store: `consumeRate`/`readBudget`/`addUsage`/`reserveBudget` accept `maxRateKeys`/`maxBudgetKeys` (the router passes its resolved limits) and evict the least-recently-used row on new-key insert — never the row just inserted, never a budget row holding an active reservation — else fail closed with `ERR_PRISM_MODEL_ROUTER_STATE`. Cleanup prunes expired reservations within its bounded batch.
|
|
209
209
|
- Policy/evaluation/query public contracts stay in their owning packages. This package exports `createPostgresEnterpriseState`, `createPostgresApprovalStore`, `createPostgresErpMessaging`, their options/result/types, and `EnterprisePostgresError`; it has no SQL, DDL, codec, queryable, or migration subpath.
|
|
210
210
|
- The fixed schema has no generic key/value table and no background cleanup scheduler. Schedule `state.cleanup()` from an authorized host job, size its bounded batch for the deployment, and monitor unknown work rows for reconciliation. Run protected integration checks with `PRISM_TEST_POSTGRES_URL="$DATABASE_URL" npm run test:postgres`; the command rejects an absent URL instead of silently skipping database coverage.
|
|
211
|
-
- The OPA adapter (`@arnilo/prism-policy/opa`, 0.0.28) records decisions into the same `state.policy` store unchanged via `evaluateAndAppend` — see [Policy and audit](policy-and-audit.md#opa-external-policy-adapter-arniloprism-policyopa-008).
|
|
211
|
+
- The OPA adapter (`@arnilo/prism-core/governance/policy/opa`, 0.0.28) records decisions into the same `state.policy` store unchanged via `evaluateAndAppend` — see [Policy and audit](policy-and-audit.md#opa-external-policy-adapter-arniloprism-policyopa-008).
|
|
212
212
|
- Request-path state SQL uses `SELECT`, `INSERT`, `UPDATE`, and `DELETE` on the eight state tables. The open/migration lifecycle additionally needs schema/catalog/advisory-lock and DDL permissions. Use a deployment migration principal for that lifecycle and a least-privilege request role for request traffic; this release intentionally does not ship a migration CLI or worker.
|
|
213
213
|
|
|
214
214
|
## Security and performance notes
|
package/docs/evaluations.md
CHANGED
|
@@ -2,11 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
## What it does
|
|
4
4
|
|
|
5
|
-
`@arnilo/prism-evals` adds optional deterministic scorers, immutable datasets, bounded persistence-trace grading, explicit host model judges, pairwise comparisons, CI thresholds, live post-run scoring, and batch experiments over `AgentRunResult`. Scores are finite numbers in `[0, 1]` with optional reason/metadata and linkage to run/session/trace/experiment IDs.
|
|
5
|
+
`@arnilo/prism-core/governance/evals` adds optional deterministic scorers, immutable datasets, bounded persistence-trace grading, explicit host model judges, pairwise comparisons, CI thresholds, live post-run scoring, and batch experiments over `AgentRunResult`. Scores are finite numbers in `[0, 1]` with optional reason/metadata and linkage to run/session/trace/experiment IDs.
|
|
6
6
|
|
|
7
7
|
## When to use it
|
|
8
8
|
|
|
9
|
-
Use this package when a host needs offline quality checks or sampled live scoring without coupling scorers into core agent execution. Install it directly or through `@arnilo/prism-
|
|
9
|
+
Use this package when a host needs offline quality checks or sampled live scoring without coupling scorers into core agent execution. Install it directly or through the `@arnilo/prism-core` family package; installation does not attach scorers to runs.
|
|
10
10
|
|
|
11
11
|
## Inputs / request
|
|
12
12
|
|
|
@@ -19,6 +19,7 @@ Use this package when a host needs offline quality checks or sampled live scorin
|
|
|
19
19
|
| `createMemoryEvaluationStore` | optional seed records |
|
|
20
20
|
| `appendEvaluationFeedback` | `RunFeedbackStore`, `EvaluationStore`, feedback fields, and 1–64 known evaluation IDs |
|
|
21
21
|
| `createPersistenceTraceResolver` | explicit `ProductionPersistenceStore`, exact session/run/ownership, page/byte bounds |
|
|
22
|
+
| `datasetFromRuns` | `runIds` and/or `sessionIds`, existing dataset, `ProductionPersistenceStore`, ownership, redactor/secrets, optional `toItem` |
|
|
22
23
|
| `createModelJudge` | host judge callback, stable rubric/version, timeout/attempt/output bounds |
|
|
23
24
|
| `runComparison` | immutable dataset, 2–8 named candidates by default, pairwise scorers |
|
|
24
25
|
| `assertEvaluationThreshold` / `serializeEvaluationReport` | mean/failure/per-scorer gates and bounded redacted JSON |
|
|
@@ -32,6 +33,7 @@ Use this package when a host needs offline quality checks or sampled live scorin
|
|
|
32
33
|
| `runExperiment` | `ExperimentReport` with stable item order, evaluations, and aggregates |
|
|
33
34
|
| `EvaluationStore.query` | cursor-paginated, ownership-filtered page |
|
|
34
35
|
| `appendEvaluationFeedback` | immutable `RunFeedbackRecord` containing only evaluation/scorer IDs |
|
|
36
|
+
| `datasetFromRuns` | `{ dataset, version, added, skipped }` — new immutable dataset version with one item per added run; skips carry reasons (missing run, ownership mismatch, empty output) |
|
|
35
37
|
|
|
36
38
|
## Request/response example
|
|
37
39
|
|
|
@@ -58,7 +60,7 @@ import {
|
|
|
58
60
|
defineScorer,
|
|
59
61
|
runExperiment,
|
|
60
62
|
scoreRunLive,
|
|
61
|
-
} from "@arnilo/prism-evals";
|
|
63
|
+
} from "@arnilo/prism-core/governance/evals";
|
|
62
64
|
|
|
63
65
|
const scorer = defineScorer({
|
|
64
66
|
id: "contains-citation",
|
|
@@ -121,6 +123,7 @@ console.log(report.aggregate.meanScore, linked.evaluationIds);
|
|
|
121
123
|
- Model judges are host callbacks, not providers: Prism passes rubric/version plus bounded target only—never credential resolvers, tools, or workspace. Defaults are one attempt, 30 seconds, and 16 KiB output; failures become redacted evaluation records.
|
|
122
124
|
- Pairwise candidates are sorted by name, executed once per item, compared in stable item/pair/scorer order, and record ties/failures without choosing a winner. Candidate and scorer outputs have byte caps.
|
|
123
125
|
- `assertEvaluationThreshold()` throws `ERR_PRISM_EVAL_THRESHOLD`; an uncaught error gives CI a non-zero exit. Keep model-judge/live gates credential-gated and outside the network-free default suite. `serializeEvaluationReport()` bounds/redacts checked-in artifacts.
|
|
126
|
+
- `datasetFromRuns` redacts before item construction and never stores an unredactable item; curated items are byte-capped (`ERR_PRISM_EVAL_CURATE`), ownership is verified exactly per run, and a failed append leaves the prior dataset version untouched.
|
|
124
127
|
|
|
125
128
|
## Trace, judge, comparison, and CI example
|
|
126
129
|
|
|
@@ -137,14 +140,45 @@ assertEvaluationThreshold(report, { minimumMean: 0.9, maximumFailures: 0 });
|
|
|
137
140
|
|
|
138
141
|
`traceResolver` is explicit; no arbitrary run search occurs. `baseline`/`candidate` are host functions returning `AgentRunResult`. See `examples/evaluation-gate.ts` for a network-free gate and `examples/coding-browser-evaluation.ts` for coding/browser adversarial fixtures.
|
|
139
142
|
|
|
143
|
+
## Curating datasets from production runs
|
|
144
|
+
|
|
145
|
+
Plan 043 adds `datasetFromRuns`: it turns recorded runs (production incident transcripts included) into dataset items in one call — resolve through `createPersistenceTraceResolver`, redact, map through an optional host `toItem`, and append as a **new immutable dataset version**. The prior version object is never mutated.
|
|
146
|
+
|
|
147
|
+
```ts
|
|
148
|
+
import { datasetFromRuns, defineDataset } from "@arnilo/prism-core/governance/evals";
|
|
149
|
+
|
|
150
|
+
const result = await datasetFromRuns({
|
|
151
|
+
runIds: ["run_9f2", "run_a71"],
|
|
152
|
+
dataset: defineDataset({ id: "support-regressions", items: [] }),
|
|
153
|
+
store: persistence,
|
|
154
|
+
ownership: { tenantId: "t1", userId: "u1" },
|
|
155
|
+
redactor,
|
|
156
|
+
toItem: (run) => ({
|
|
157
|
+
input: run.input,
|
|
158
|
+
expected: run.feedback?.metadata?.expected, // human-graded gold from the feedback seam
|
|
159
|
+
metadata: { graded: run.feedback?.rating },
|
|
160
|
+
}),
|
|
161
|
+
});
|
|
162
|
+
// result.added === 2, result.dataset.version === "2"
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
Omit `toItem` and the default mapping is used: `input` = first user message, `expected` = the recorded feedback's `metadata.expected` when present, `output` = final assistant text under `metadata.output`.
|
|
166
|
+
|
|
167
|
+
- Session ids (`sessionIds`) expand to every run recorded under the session; bare `runIds` are located by one ownership-bounded scan of the run ledger (page/byte caps apply).
|
|
168
|
+
- Each resolved run maps to one item keyed by the run id. The default `toItem` carries the first user message as `input`; `expected` comes **only from the feedback seam** (`metadata.expected` of the latest human-graded `RunFeedbackRecord`) — never re-derived from untrusted outputs, and omitted entirely (not fabricated) when a run has no feedback. The recorded output rides `metadata.output` for provenance. A host `toItem` always wins and may return `undefined` to drop a run (`host filter` skip).
|
|
169
|
+
- Feedback costs one bounded, owner-scoped query per curation batch (`store.feedback`); records are read id-only per the feedback linkage contract — scorer payloads are never copied. A feedback query failure (e.g. scope contract mismatch) omits `expected` instead of aborting the batch.
|
|
170
|
+
- Every item field passes the host `redactor` after host mapping — fail closed: a redactor failure or an item over the frozen 4 MiB cap (`ERR_PRISM_EVAL_CURATE`) skips the run or aborts the append before anything is persisted. Cross-tenant runs are never readable (resolver ownership check → `ownership mismatch` skip).
|
|
171
|
+
|
|
172
|
+
Prompt versions can ride the same primitives: [`assertPromptPromotion`](prompt-registry.md#eval-gated-promotion) in `@arnilo/prism-core/governance/prompts` resolves two prompt versions, runs them through `runComparison`, and returns a `promote`/`hold` verdict with per-scorer aggregates and a bounded report — never applying the change itself.
|
|
173
|
+
|
|
140
174
|
## Coding and browser adversarial evaluations (0.0.9)
|
|
141
175
|
|
|
142
176
|
Release 0.0.9 ships curated network-free adversarial fixtures in package tests:
|
|
143
177
|
|
|
144
|
-
- `@arnilo/prism-coding-agent` `eval-fixtures.test.ts`: safe native list vs shell, Git path/ref injection, dirty-tree rollback, unknown named-check failure, PR-handoff artifact completeness, and prompt-injection file content under read-only tools.
|
|
145
|
-
-
|
|
178
|
+
- `@arnilo/prism-coding-tools/agent` `eval-fixtures.test.ts`: safe native list vs shell, Git path/ref injection, dirty-tree rollback, unknown named-check failure, PR-handoff artifact completeness, and prompt-injection file content under read-only tools.
|
|
179
|
+
- `browser` `eval-fixtures.test.ts`: stale snapshot refs, side-effect approval, private/loopback/file deny, upload/download/screenshot policy, CSS/evaluate target rejection, and hostile accessible-name text.
|
|
146
180
|
|
|
147
|
-
Fixtures reuse `@arnilo/prism-evals` (`defineDataset` / `defineScorer` / `scoreRun` / `assertEvaluationThreshold` / `serializeEvaluationReport`). Optional SWE-bench-compatible or live-browser harnesses remain host adapters — they are not default dependencies or quality claims. Protected real Docker/Playwright gates stay env-gated (`PRISM_TEST_DOCKER_SANDBOX`, `PRISM_LIVE_PLAYWRIGHT`) and never enter `sdk:ready`.
|
|
181
|
+
Fixtures reuse `@arnilo/prism-core/governance/evals` (`defineDataset` / `defineScorer` / `scoreRun` / `assertEvaluationThreshold` / `serializeEvaluationReport`). Optional SWE-bench-compatible or live-browser harnesses remain host adapters — they are not default dependencies or quality claims. Protected real Docker/Playwright gates stay env-gated (`PRISM_TEST_DOCKER_SANDBOX`, `PRISM_LIVE_PLAYWRIGHT`) and never enter `sdk:ready`.
|
|
148
182
|
|
|
149
183
|
## PostgreSQL enterprise state (0.0.23)
|
|
150
184
|
|
|
@@ -180,7 +214,7 @@ The protected runner (`scripts/phase27-erp-journey.test.mjs`) carries the journe
|
|
|
180
214
|
### Hard-gate usage
|
|
181
215
|
|
|
182
216
|
```ts
|
|
183
|
-
import { createErpInvariantScorers, erpInvariantDataset, scoreRun } from "@arnilo/prism-evals";
|
|
217
|
+
import { createErpInvariantScorers, erpInvariantDataset, scoreRun } from "@arnilo/prism-core/governance/evals";
|
|
184
218
|
|
|
185
219
|
const scorers = createErpInvariantScorers();
|
|
186
220
|
const records = await scoreRun({
|
package/docs/extensions.md
CHANGED
|
@@ -140,9 +140,9 @@ await kernel.middleware.run("provider_request", { metadata: {} });
|
|
|
140
140
|
- [Compaction and retry policies](compaction-and-retry.md): compaction strategy/retry policy contributions and `compaction`/`retry` middleware runtime behavior.
|
|
141
141
|
- [LLM compaction package](compaction-llm.md): optional extension helper that registers a provider-backed compaction strategy.
|
|
142
142
|
- [Observational memory compaction package](compaction-observational-memory.md): optional extension helper that registers an inert fast memory compaction strategy.
|
|
143
|
-
- [Caveman behavior integration](caveman.md): optional `@arnilo/prism-caveman` upstream Caveman skills, commands, level injector, and session `caveman-level` persistence.
|
|
144
|
-
- [Ponytail behavior integration](ponytail.md): optional `@arnilo/prism-ponytail` upstream Ponytail skills, commands, mode injector, and session `ponytail-mode` persistence.
|
|
145
|
-
- [Impeccable behavior integration](impeccable.md): optional `@arnilo/prism-impeccable` upstream Impeccable skill and `load_skill` command.
|
|
143
|
+
- [Caveman behavior integration](caveman.md): optional `@arnilo/prism-coding-tools/caveman` upstream Caveman skills, commands, level injector, and session `caveman-level` persistence.
|
|
144
|
+
- [Ponytail behavior integration](ponytail.md): optional `@arnilo/prism-coding-tools/ponytail` upstream Ponytail skills, commands, mode injector, and session `ponytail-mode` persistence.
|
|
145
|
+
- [Impeccable behavior integration](impeccable.md): optional `@arnilo/prism-coding-tools/impeccable` upstream Impeccable skill and `load_skill` command.
|
|
146
146
|
- [Public contracts](public-contracts.md): `Extension`, `ExtensionAPI`, and contribution contract types.
|
|
147
147
|
- [Credentials and redaction](credentials-and-redaction.md): secret-redaction behavior used for extension errors.
|
|
148
148
|
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
## What it does
|
|
4
4
|
|
|
5
|
-
`createGitHubForge` is an optional host-activated adapter in `@arnilo/prism-coding-agent` for the six **proven** GitHub operations: issue context read, authenticated push, pull-request create/update, review comments, and check/status retrieval, plus bounded handoff reconciliation. It is GitHub-first by freeze decision — there is no multi-forge generic abstraction, and no octokit dependency: HTTP uses Node's global `fetch` with a bounded streaming reader, timeout, and rate-limit backoff; push reuses the existing `BoundGitRunner` with the token injected via `GIT_CONFIG_*` environment variables (`http.extraHeader`) — never argv, never persisted, never in logs/events. Every mutation flows through Phase 8 approval (`ExecutionPolicy`) and Phase 7 `ToolEffectStore` idempotency keys; a retry after a completed call returns the existing record instead of duplicating the PR or comment.
|
|
5
|
+
`createGitHubForge` is an optional host-activated adapter in `@arnilo/prism-coding-tools/agent` for the six **proven** GitHub operations: issue context read, authenticated push, pull-request create/update, review comments, and check/status retrieval, plus bounded handoff reconciliation. It is GitHub-first by freeze decision — there is no multi-forge generic abstraction, and no octokit dependency: HTTP uses Node's global `fetch` with a bounded streaming reader, timeout, and rate-limit backoff; push reuses the existing `BoundGitRunner` with the token injected via `GIT_CONFIG_*` environment variables (`http.extraHeader`) — never argv, never persisted, never in logs/events. Every mutation flows through Phase 8 approval (`ExecutionPolicy`) and Phase 7 `ToolEffectStore` idempotency keys; a retry after a completed call returns the existing record instead of duplicating the PR or comment.
|
|
6
6
|
|
|
7
7
|
| Export | Purpose |
|
|
8
8
|
| --- | --- |
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
Use when a coding agent needs to open/update PRs, comment on reviews, push a branch with scoped credentials, or verify handoff state against GitHub before deciding the next step. Do not use as a general GitHub SDK, an auto-merge engine (`reconcileHandoff` never merges), or a replacement for host-owned App installation flows — the adapter resolves credentials through the host's `CredentialResolverSource`-compatible resolver and never stores them.
|
|
19
19
|
|
|
20
20
|
```ts
|
|
21
|
-
import { createGitHubForge } from "@arnilo/prism-coding-agent";
|
|
21
|
+
import { createGitHubForge } from "@arnilo/prism-coding-tools/agent";
|
|
22
22
|
|
|
23
23
|
const forge = createGitHubForge({
|
|
24
24
|
credentials: { name: "github", resolver: myCredentialResolver }, // App installation token preferred; PAT allowed
|
|
@@ -75,7 +75,7 @@ Every mutation result is recorded in the `effectStore` with a stable key derived
|
|
|
75
75
|
## Implementation example
|
|
76
76
|
|
|
77
77
|
```ts
|
|
78
|
-
import { createGitHubForge } from "@arnilo/prism-coding-agent";
|
|
78
|
+
import { createGitHubForge } from "@arnilo/prism-coding-tools/agent";
|
|
79
79
|
|
|
80
80
|
const forge = createGitHubForge({
|
|
81
81
|
credentials: { name: "github-app", resolver },
|
package/docs/graft.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
## What it does
|
|
4
4
|
|
|
5
|
-
`@arnilo/prism-graft` is an optional
|
|
5
|
+
`@arnilo/prism-memory/graft` is an optional subpath that wires [nanonets/graft](https://github.com/nanonets/graft) — a repository context-graph CLI (`graft/` directory, INDEX.md orientation, symbol-level wiring graph) — into Prism contribution contracts.
|
|
6
6
|
|
|
7
7
|
It registers six pull tools backed by the graft CLI (`--json`, argv-safe), a push-mode retrieval-pack context provider plus first-turn orientation injector carried on the `graft` skill, commands (`graft`, `graft-build`, `graft-check`, `graft-viz`), and an edit-watch middleware that computes blast radius after mutating tool calls. Import is inert; a missing graft CLI fails closed at `setup` with a bounded redacted error.
|
|
8
8
|
|
|
@@ -14,7 +14,7 @@ Use it when a host wants agents to locate code by architecture, callers, and cou
|
|
|
14
14
|
- `"push"` — per-turn retrieval pack (pointers only) + first-turn orientation, injected automatically.
|
|
15
15
|
- `"both"` — everything.
|
|
16
16
|
|
|
17
|
-
Install optional peer `@nanonets/graft@^0.
|
|
17
|
+
Install optional peer `@nanonets/graft@^0.16.0` **or** pass `packageRoot`/`cliPath` explicitly. Pair with progressive disclosure: the `graft` skill body stays small; tool schemas carry the details. Graft complements indexed code search (`repository_search`): graph/semantic locators vs literal search — neither replaces the other.
|
|
18
18
|
|
|
19
19
|
Zero-code alternative (L0): hosts can skip this package entirely and let agents call `graft <command> --json` through their shell tool, optionally seeding context with graft's own generated instruction files. This package exists for native-tool ergonomics, budgeted subprocesses, session persistence, and push mode.
|
|
20
20
|
|
|
@@ -74,7 +74,7 @@ Tool call (pull):
|
|
|
74
74
|
Status event:
|
|
75
75
|
|
|
76
76
|
```json
|
|
77
|
-
{ "type": "graft:status", "extension": "@arnilo/prism-graft", "metadata": { "fresh": true, "missing": 0, "stale": 2 } }
|
|
77
|
+
{ "type": "graft:status", "extension": "@arnilo/prism-memory/graft", "metadata": { "fresh": true, "missing": 0, "stale": 2 } }
|
|
78
78
|
```
|
|
79
79
|
|
|
80
80
|
## Implementation example
|
|
@@ -83,7 +83,7 @@ See [`examples/graft-extension.ts`](../examples/graft-extension.ts) — network-
|
|
|
83
83
|
|
|
84
84
|
```ts
|
|
85
85
|
import { createExtensionKernel, createMemorySessionStore } from "@arnilo/prism";
|
|
86
|
-
import { createGraftExtension } from "@arnilo/prism-graft";
|
|
86
|
+
import { createGraftExtension } from "@arnilo/prism-memory/graft";
|
|
87
87
|
|
|
88
88
|
const store = createMemorySessionStore();
|
|
89
89
|
const kernel = createExtensionKernel({ errorPolicy: "throw" });
|
|
@@ -105,7 +105,7 @@ await kernel.load([
|
|
|
105
105
|
- Import alone registers nothing (`sideEffects: false`); no timers, watchers, or network. The only child processes are budgeted graft CLI calls.
|
|
106
106
|
- Retrieval happens in-process via Prism primitives (context provider, injector, tool_result middleware) — no external hook shims.
|
|
107
107
|
- Ask result shape is parsed tolerantly (`nodes|results|matches|hits`) because graft is pre-1.0; formatters emit pointers (`title` + `file:line` + `[[wikilink]]`), never source bodies.
|
|
108
|
-
- Not included in `@arnilo/prism-
|
|
108
|
+
- Not included in `@arnilo/prism-coding-tools`, `@arnilo/prism-core`, or the `prism-all` umbrella (deliberate opt-out, like Caveman/Ponytail) — opt-in install only.
|
|
109
109
|
- Multi-repo layouts work as upstream graft defines them (workspaces, submodules with `--follow-submodules`, sibling repos); point `projectDir` at the graft root that owns the target repo.
|
|
110
110
|
|
|
111
111
|
## Security and performance notes
|
package/docs/guardrails.md
CHANGED
|
@@ -76,9 +76,9 @@ Guardrails are callbacks supplied by the host. Prism does not discover, load, re
|
|
|
76
76
|
|
|
77
77
|
## Security and performance notes
|
|
78
78
|
|
|
79
|
-
Optional `@arnilo/prism-policy` can record guardrail outcomes via `recordGuardrailDecision` (evidence refs only; see [Policy and audit](policy-and-audit.md)).
|
|
79
|
+
Optional `@arnilo/prism-core/governance/policy` can record guardrail outcomes via `recordGuardrailDecision` (evidence refs only; see [Policy and audit](policy-and-audit.md)).
|
|
80
80
|
|
|
81
|
-
Output buffering prevents blocked provider content from reaching subscribers, session entries, ledgers, parsers, delegation, or tools. Tool-output checks receive raw results but Prism discards blocked raw output before event, ledger, transcript, or MCP exposure. Redaction replaces exact known values only; it is not general secret detection. Parallel checks receive an abort signal, but callback code must honor it to stop in-flight work. Browser snapshots and page text from
|
|
81
|
+
Output buffering prevents blocked provider content from reaching subscribers, session entries, ledgers, parsers, delegation, or tools. Tool-output checks receive raw results but Prism discards blocked raw output before event, ledger, transcript, or MCP exposure. Redaction replaces exact known values only; it is not general secret detection. Parallel checks receive an abort signal, but callback code must honor it to stop in-flight work. Browser snapshots and page text from the `browser` subpath are untrusted external content: never allow them to modify tools, permissions, credentials, or policy. Browser mutations still require host `ExecutionPolicy`/approval; prompt-injection text in a page cannot grant upload/download release.
|
|
82
82
|
|
|
83
83
|
## Related APIs
|
|
84
84
|
|