@orkestrel/scaffold 0.0.66 → 0.0.68
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/dist/bin/main.js +67 -44
- package/dist/bin/main.js.map +1 -1
- package/dist/host/agents/templates/brief.md +9 -0
- package/dist/host/claude/agents/orkestrel.md +8 -8
- package/dist/host/claude/rules/names.md +15 -0
- package/dist/host/claude/rules/tests.md +33 -4
- package/dist/host/claude/rules/workspace.md +14 -2
- package/dist/host/dotfiles/prettierignore +3 -0
- package/dist/host/guides/README.md +65 -0
- package/dist/host/guides/abort.md +169 -0
- package/dist/host/guides/agent.md +1509 -0
- package/dist/host/guides/brief.md +1266 -0
- package/dist/host/guides/browser.md +2200 -0
- package/dist/host/guides/budget.md +196 -0
- package/dist/host/guides/codec.md +519 -0
- package/dist/host/guides/console.md +785 -0
- package/dist/host/guides/contract.md +1193 -0
- package/dist/host/guides/csv.md +541 -0
- package/dist/host/guides/database.md +2518 -0
- package/dist/host/guides/emitter.md +233 -0
- package/dist/host/guides/form.md +1791 -0
- package/dist/host/guides/html.md +717 -0
- package/dist/host/guides/indexeddb.md +505 -0
- package/dist/host/guides/interpret.md +1029 -0
- package/dist/host/guides/lsp.md +515 -0
- package/dist/host/guides/markdown.md +964 -0
- package/dist/host/guides/mcp.md +5554 -0
- package/dist/host/guides/middleware.md +927 -0
- package/dist/host/guides/msg.md +440 -0
- package/dist/host/guides/ndjson.md +120 -0
- package/dist/host/guides/ollama.md +380 -0
- package/dist/host/guides/pool.md +280 -0
- package/dist/host/guides/probe.md +1210 -0
- package/dist/host/guides/process.md +1620 -0
- package/dist/host/guides/program.md +1110 -0
- package/dist/host/guides/qualifier.md +854 -0
- package/dist/host/guides/queue.md +370 -0
- package/dist/host/guides/rater.md +330 -0
- package/dist/host/guides/reason.md +1122 -0
- package/dist/host/guides/relation.md +373 -0
- package/dist/host/guides/router.md +753 -0
- package/dist/host/guides/scaffold.md +192 -31
- package/dist/host/guides/sea.md +383 -0
- package/dist/host/guides/server.md +752 -0
- package/dist/host/guides/sqlite.md +330 -0
- package/dist/host/guides/sse.md +187 -0
- package/dist/host/guides/supervisor.md +4890 -0
- package/dist/host/guides/table.md +1556 -0
- package/dist/host/guides/template.md +280 -0
- package/dist/host/guides/terminal.md +1145 -0
- package/dist/host/guides/test.md +2969 -0
- package/dist/host/guides/timeout.md +252 -0
- package/dist/host/guides/tool.md +311 -0
- package/dist/host/guides/toolbox.md +1038 -0
- package/dist/host/guides/websocket.md +282 -0
- package/dist/host/guides/worker.md +615 -0
- package/dist/host/guides/workflow.md +1507 -0
- package/dist/host/guides/workspace.md +595 -0
- package/dist/host/manifest.json +1218 -10
- package/dist/host/tests/policy.test.ts +279 -2
- package/dist/host/tests/setupPolicy.ts +437 -6
- package/dist/src/core/index.cjs +44 -22
- package/dist/src/core/index.cjs.map +1 -1
- package/dist/src/core/index.d.cts +33 -9
- package/dist/src/core/index.d.ts +33 -9
- package/dist/src/core/index.js +43 -23
- package/dist/src/core/index.js.map +1 -1
- package/dist/src/server/index.cjs +1750 -1567
- package/dist/src/server/index.cjs.map +1 -1
- package/dist/src/server/index.d.cts +106 -24
- package/dist/src/server/index.d.ts +106 -24
- package/dist/src/server/index.js +1751 -1570
- package/dist/src/server/index.js.map +1 -1
- package/package.json +9 -9
|
@@ -0,0 +1,1029 @@
|
|
|
1
|
+
# Interpret
|
|
2
|
+
|
|
3
|
+
> A synchronous, deterministic bidirectional bridge between natural language and the
|
|
4
|
+
> `@orkestrel/reason` engine: a forward pipeline that normalizes raw text, classifies its
|
|
5
|
+
> intent, matches an added `Template`, clarifies the fields extraction left open, and
|
|
6
|
+
> generates a `Subject` and `Definition` pair ready for `Reason.reason`, plus a reverse
|
|
7
|
+
> direction that renders a `Definition`, a `Subject`, or a `ReasonResult` to
|
|
8
|
+
> display-neutral prose through a lexicon-driven `Narrator`.
|
|
9
|
+
|
|
10
|
+
Nothing here is an LLM, a provider, or an agent: the `prompt` a result carries is written for
|
|
11
|
+
an external model and is never consumed internally, and the reverse direction complements the
|
|
12
|
+
raters' `describe*` family rather than duplicating it. `normalize` applies contraction,
|
|
13
|
+
abbreviation, and correction substitutions; `extract` classifies intent without ever seeing a
|
|
14
|
+
template and mines the raw numbers; `clarify` resolves same-domain carry-over, template
|
|
15
|
+
defaults, and dependency-ordered computed fields. Every discriminant names its axis rather
|
|
16
|
+
than `kind` or `type`: `stage` splits the pipeline phases, `category` splits provenance, and
|
|
17
|
+
`code` splits coded errors. Source: [`src/core`](../src/core). Surfaced through the
|
|
18
|
+
`@src/core` barrel.
|
|
19
|
+
|
|
20
|
+
## Surface
|
|
21
|
+
|
|
22
|
+
### Interpret text against an added template
|
|
23
|
+
|
|
24
|
+
Add a template, interpret text through the normalize, extract, clarify, format, and generate
|
|
25
|
+
pipeline, then render the result back to prose:
|
|
26
|
+
|
|
27
|
+
```ts
|
|
28
|
+
import { createExtractor, createInterpret } from '@orkestrel/interpret'
|
|
29
|
+
import {
|
|
30
|
+
createFactorGroup,
|
|
31
|
+
createFieldFactor,
|
|
32
|
+
createQuantitativeDefinition,
|
|
33
|
+
} from '@orkestrel/reason'
|
|
34
|
+
|
|
35
|
+
const interpret = createInterpret({
|
|
36
|
+
extractor: createExtractor({
|
|
37
|
+
actions: { calculate: 'calculate' },
|
|
38
|
+
domains: { arithmetic: ['arithmetic'] },
|
|
39
|
+
}),
|
|
40
|
+
templates: [
|
|
41
|
+
{
|
|
42
|
+
id: 't1',
|
|
43
|
+
name: 'Arithmetic',
|
|
44
|
+
domain: 'arithmetic',
|
|
45
|
+
intents: ['calculate'],
|
|
46
|
+
mappings: [{ entity: 'value', aliases: [], field: 'value' }],
|
|
47
|
+
defaults: [],
|
|
48
|
+
computations: [],
|
|
49
|
+
definition: createQuantitativeDefinition('t1', 'Arithmetic', [
|
|
50
|
+
createFactorGroup('total', 'sum', [createFieldFactor('value', 'value')]),
|
|
51
|
+
]),
|
|
52
|
+
},
|
|
53
|
+
],
|
|
54
|
+
})
|
|
55
|
+
|
|
56
|
+
const result = interpret.interpret('calculate arithmetic 42')
|
|
57
|
+
result.subject // { value: 42 }
|
|
58
|
+
result.ambiguities // []
|
|
59
|
+
result.failures // []
|
|
60
|
+
|
|
61
|
+
interpret.emitter.on('interpret', (interpretation) => interpretation.digest)
|
|
62
|
+
interpret.describe(result.definition ?? createQuantitativeDefinition('t1', 'Arithmetic', []))
|
|
63
|
+
interpret.destroy()
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
`interpret()` is genuinely synchronous and runs the fixed pipeline
|
|
67
|
+
`[normalize, extract, clarify, format, generate]`. A `NO_TEMPLATE` or `LOW_CONFIDENCE`
|
|
68
|
+
non-match, and a thrown stage, each yield a visible incomplete `Interpretation` rather than
|
|
69
|
+
throwing, and never an arbitrary fallback template. An interpretation is complete when
|
|
70
|
+
`ambiguities` and `failures` are both empty; no stored flag repeats that fact.
|
|
71
|
+
|
|
72
|
+
### Types
|
|
73
|
+
|
|
74
|
+
A `Shape` cell holds an interface's data members as bare names in braces, `?` marking an optional member and `plus` introducing its call-signature members, and a type alias's own type literal with a union's arms escaped as `\|`.
|
|
75
|
+
|
|
76
|
+
| Type | Kind | Shape | Summary |
|
|
77
|
+
| ---------------------------- | --------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
78
|
+
| `ProvenanceCategory` | type | `'extracted' \| 'carried' \| 'default' \| 'computed' \| 'subject'` | Names how one `FieldMapping` or `Entity` value was obtained. |
|
|
79
|
+
| `InterpretStage` | type | `'normalize' \| 'extract' \| 'clarify' \| 'format' \| 'generate'` | Names the fixed pipeline phases an `InterpretInterface#interpret` run produces one `StageRecord` for, in order. |
|
|
80
|
+
| `InterpretErrorCode` | type | `'NORMALIZE_FAILED' \| 'EXTRACT_FAILED' \| 'CLARIFY_FAILED' \| 'FORMAT_FAILED' \| 'GENERATE_FAILED' \| 'NO_TEMPLATE' \| 'LOW_CONFIDENCE' \| 'DESTROYED'` | Names the coded misuse or failure conditions thrown as an `InterpretError` or carried on a `StageFailure`. |
|
|
81
|
+
| `EntityMapping` | interface | `{ entity, aliases, field, required? }` | Represents one entity-extraction rule inside a `Template`: which literal alias phrases identify a value, and which subject field it lands on. |
|
|
82
|
+
| `FieldDefault` | interface | `{ field, value }` | Represents a fallback value a `Template` fills onto a field left unresolved by extraction. |
|
|
83
|
+
| `ComputedField` | interface | `{ field, expression }` | Represents a declaratively computed field: evaluate `expression` against the entities already resolved for this interpretation, and land the result on `field`. |
|
|
84
|
+
| `Template` | interface | `{ id, name, domain, intents, mappings, defaults, computations, definition }` | Represents a named, versionable interpretation template: which intents it answers, how to mine entities for it, its fallback data, its computed fields, and the reasons `Definition` it ultimately produces a `Subject` for. |
|
|
85
|
+
| `Provenance` | interface | `{ category, detail? }` | Describes how one value landed — its origin category plus an optional strategy detail. |
|
|
86
|
+
| `Intent` | interface | `{ action?, domain?, confidence }` | Represents the classified action + domain for one interpretation, with a combined confidence. |
|
|
87
|
+
| `Entity` | interface | `{ name, value, provenance, confidence }` | Represents one value assigned to a template's entity mapping, with its provenance and confidence. |
|
|
88
|
+
| `Ambiguity` | interface | `{ field, question, candidates, required }` | Represents an unresolved field surfaced as a human-readable question, never bare prose. |
|
|
89
|
+
| `FieldMapping` | interface | `{ field, entity?, value, provenance, confidence }` | Represents one audited field of the built subject — its resolved value, provenance, and confidence. |
|
|
90
|
+
| `TextChange` | interface | `{ from, to }` | Represents one normalization substitution applied to the raw text. |
|
|
91
|
+
| `StageRecord` | interface | `{ stage, input, output, failed, error? }` | Represents a structured input/output snapshot of one pipeline phase. |
|
|
92
|
+
| `StageFailure` | interface | `{ stage, code, message }` | Represents a visible marker for a stage that threw, carrying its coded reason. |
|
|
93
|
+
| `NormalizeResult` | interface | `{ text, changes }` | Represents the `Normalizer` stage's output: the cleaned text plus every substitution applied. |
|
|
94
|
+
| `ExtractResult` | interface | `{ intent, numbers }` | Represents the `Extractor` stage's output: intent classification plus raw numbers. |
|
|
95
|
+
| `ClarifyResult` | interface | `{ entities, ambiguities }` | Represents the `Clarifier` stage's output: resolved entities plus any remaining ambiguities. |
|
|
96
|
+
| `FormatResult` | interface | `{ prompt }` | Represents the `Formatter` stage's output: the refined natural-language prompt. |
|
|
97
|
+
| `GenerateResult` | interface | `{ subject, definition, mappings, confidence }` | Represents the `Generator` stage's output: the built subject/definition pair plus its full field audit. |
|
|
98
|
+
| `Interpretation` | interface | `{ text, normalized, intent, entities, subject?, definition?, mappings, ambiguities, prompt, stages, failures, confidence, digest }` | Represents the full, replayable outcome of one `interpret()` call. |
|
|
99
|
+
| `TemplateRecord` | interface | `{ id, template, version, hash }` | Represents a versioned, content-hashed `Template` as held by a `TemplateManagerInterface`. |
|
|
100
|
+
| `SubjectRecord` | interface | `{ id, subject, version, hash }` | Represents a versioned, content-hashed `Subject` as held by a `SubjectManagerInterface`. |
|
|
101
|
+
| `DefinitionRecord` | interface | `{ id, definition, version, hash }` | Represents a versioned, content-hashed `Definition` as held by a `DefinitionManagerInterface`. |
|
|
102
|
+
| `InterpretEventMap` | type | `{ interpret, add, error, destroy }` | Represents the push observation surface of an `InterpretInterface`. |
|
|
103
|
+
| `RecordEventMap` | type | `{ add, remove, destroy }` | Represents the push observation surface shared by every record registry — an id-keyed collection, so `add` and `remove` are the events (never ordered-list `append`/`prepend`). |
|
|
104
|
+
| `TemplateManagerEventMap` | type | `RecordEventMap` | Represents the push observation surface of a `TemplateManagerInterface`. |
|
|
105
|
+
| `SubjectManagerEventMap` | type | `RecordEventMap` | Represents the push observation surface of a `SubjectManagerInterface`, whose `add` carries the own-minted record id. |
|
|
106
|
+
| `DefinitionManagerEventMap` | type | `RecordEventMap` | Represents the push observation surface of a `DefinitionManagerInterface`. |
|
|
107
|
+
| `InterpretContextEventMap` | type | `{ add, clear, destroy }` | Represents the push observation surface of an `InterpretContextInterface`. |
|
|
108
|
+
| `NarratorFormatter` | type | `(value: unknown) => string` | Represents a pure formatting function for one lexicon `value()` unit. |
|
|
109
|
+
| `Lexicon` | interface | `{ phrases?, labels?, templates? }` | Represents caller-injected wording data for the reverse direction — mechanism, never policy. Every phrase, label, and template string a `Narrator` renders is data supplied here, never a core literal. |
|
|
110
|
+
| `NarratorOptions` | interface | `{ lexicon?, formatters? }` | Represents the options for `createNarrator` and the `Narrator` constructor. |
|
|
111
|
+
| `NormalizerOptions` | interface | `{ contractions?, abbreviations?, corrections? }` | Represents the options for `createNormalizer` and the `Normalizer` constructor. |
|
|
112
|
+
| `ExtractorOptions` | interface | `{ actions?, domains? }` | Represents the options for `createExtractor` and the `Extractor` constructor. |
|
|
113
|
+
| `ClarifierOptions` | interface | `{ floor?, narrator? }` | Represents the options for `createClarifier` and the `Clarifier` constructor. |
|
|
114
|
+
| `FormatterOptions` | interface | `{ verbs?, narrator? }` | Represents the options for `createFormatter` and the `Formatter` constructor. |
|
|
115
|
+
| `TemplateManagerOptions` | interface | `{ templates?, on?, error? }` | Represents the options for `createTemplateManager` and the `TemplateManager` constructor — the initial seed collection. |
|
|
116
|
+
| `SubjectManagerOptions` | interface | `{ subjects?, on?, error? }` | Represents the options for `createSubjectManager` and the `SubjectManager` constructor — the initial seed collection. |
|
|
117
|
+
| `DefinitionManagerOptions` | interface | `{ definitions?, on?, error? }` | Represents the options for `createDefinitionManager` and the `DefinitionManager` constructor — the initial seed collection. |
|
|
118
|
+
| `RecordStamp` | interface | `{ id, version, hash }` | Represents the identity, version, and content hash a `RecordManagerInterface` derives for one record before its concrete shape is built. |
|
|
119
|
+
| `RecordFunction` | type | `(stamp: RecordStamp, value: TValue) => TRecord` | Builds one concrete record from the `RecordStamp` its registry derived and the value that record holds. |
|
|
120
|
+
| `RecordManagerOptions` | interface | `{ entity, on?, error? }` | Represents the options for the `RecordManager` constructor. |
|
|
121
|
+
| `RecordManagerInterface` | interface | `{ emitter, count } plus has, record, records, add, remove, destroy` | Represents the shared registry engine every record manager composes — the `Map`, the content-hash and version rule, the batch `remove` overloads, and teardown. |
|
|
122
|
+
| `RecordOptions` | interface | `{ id? }` | Represents the per-call options for the record a manager's `add` mints. |
|
|
123
|
+
| `InterpretContextOptions` | interface | `{ session?, history?, on?, error? }` | Represents the options for `createInterpretContext` and the `InterpretContext` constructor. |
|
|
124
|
+
| `InterpretOptions` | interface | `{ templates?, context?, normalizer?, extractor?, clarifier?, formatter?, generator?, similarity?, floor?, history?, narrator?, on?, error? }` | Represents the options for `createInterpret` and the `Interpret` constructor. |
|
|
125
|
+
| `NormalizerInterface` | interface | `{} plus normalize` | Represents the `Normalizer` stage contract: raw text in, cleaned text + applied changes out. |
|
|
126
|
+
| `ExtractorInterface` | interface | `{} plus extract` | Represents the `Extractor` stage contract: template-agnostic intent classification + raw number mining. |
|
|
127
|
+
| `ClarifierInterface` | interface | `{} plus clarify` | Represents the `Clarifier` stage contract: resolve carry-over, defaults, and computed fields against a set of already-assigned entities, surfacing ambiguities for anything required that stays unresolved. |
|
|
128
|
+
| `FormatterInterface` | interface | `{} plus format` | Represents the `Formatter` stage contract: render the refined natural-language prompt for a matched template. |
|
|
129
|
+
| `GeneratorInterface` | interface | `{} plus generate` | Represents the `Generator` stage contract: build the final subject/definition pair plus its field audit. |
|
|
130
|
+
| `NarratorInterface` | interface | `{} plus phrase, label, line, value, describe, narrate` | Represents the `Narrator` contract — a stateless, total, lexicon-driven rendering engine for the reverse direction. |
|
|
131
|
+
| `TemplateManagerInterface` | interface | `{ emitter, count } plus has, template, templates, add, remove, destroy` | Represents the template registry — a self-owning, versioned/hashed record-holder with the singular/plural accessor pair and the batch `remove` overloads. |
|
|
132
|
+
| `SubjectManagerInterface` | interface | `{ emitter, count } plus has, subject, subjects, add, remove, destroy` | Represents the subject registry — a self-owning, versioned/hashed record-holder that mints its own record ids (a `Subject` carries none). |
|
|
133
|
+
| `DefinitionManagerInterface` | interface | `{ emitter, count } plus has, definition, definitions, add, remove, destroy` | Represents the definition registry — a self-owning, versioned/hashed record-holder. |
|
|
134
|
+
| `InterpretContextInterface` | interface | `{ emitter, session, subjects, definitions } plus previous, entities, add, clear, destroy` | Represents the cross-turn interpretation context: a capped, replayable history plus the subject/definition registries carry-over reads from. |
|
|
135
|
+
| `InterpretInterface` | interface | `{ emitter } plus interpret, add, remove, template, templates, describe, narrate, destroy` | Represents the interpretation orchestrator — the sole public entry point, mirroring `reasons`' `Reason` orchestrator shape. |
|
|
136
|
+
|
|
137
|
+
### Constants
|
|
138
|
+
|
|
139
|
+
A `Shape` cell holds the constant's declared type.
|
|
140
|
+
|
|
141
|
+
| API | Kind | Shape | Summary |
|
|
142
|
+
| ------------------------------ | ----- | ---------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
143
|
+
| `DEFAULT_INTERPRET_SIMILARITY` | const | `number` | Names the default `similarity` for `createInterpret` and `matchAlias`, 0.8 — the fuzzy alias-match score threshold, between 0 and 1. |
|
|
144
|
+
| `DEFAULT_INTERPRET_FLOOR` | const | `number` | Names the default `floor` for `createInterpret` and `matchTemplate`, 0.3 — the minimum intent confidence a template match, or the classified intent itself, must clear. |
|
|
145
|
+
| `DEFAULT_INTERPRET_HISTORY` | const | `number` | Names the default `history` cap for an `InterpretContext`'s `previous()` ring buffer, 16. |
|
|
146
|
+
| `PROVENANCE_CATEGORIES` | const | `readonly ProvenanceCategory[]` | Lists every `ProvenanceCategory` literal, frozen — the one home the result guards check the union from, so a new category added to `types.ts` is added here rather than silently rejected by `isProvenance`. |
|
|
147
|
+
| `INTERPRET_STAGES` | const | `readonly InterpretStage[]` | Lists every `InterpretStage` literal in pipeline order, frozen — the one home the result guards check the union from. |
|
|
148
|
+
| `INTERPRET_ERROR_CODES` | const | `readonly InterpretErrorCode[]` | Lists every `InterpretErrorCode` literal, frozen — the one home the result guards check the union from. |
|
|
149
|
+
| `CONFIDENCE_EXACT` | const | `number` | Names the confidence assigned to an exact keyword-proximity entity match, 1. |
|
|
150
|
+
| `CONFIDENCE_ALIAS` | const | `number` | Names the confidence assigned to an exact alias-phrase entity match, 0.9. |
|
|
151
|
+
| `CONFIDENCE_COLLECT` | const | `number` | Names the confidence assigned when a single entity mapping collects every extracted number, 0.9. |
|
|
152
|
+
| `CONFIDENCE_POSITIONAL` | const | `number` | Names the confidence assigned to a positional (order-based) entity match fallback, 0.7. |
|
|
153
|
+
| `CONFIDENCE_CARRIED` | const | `number` | Names the confidence assigned to a same-domain carried-over field, 0.7. |
|
|
154
|
+
| `CONFIDENCE_DEFAULT` | const | `number` | Names the confidence assigned to a template default fill, 1. |
|
|
155
|
+
| `CONFIDENCE_COMPUTED` | const | `number` | Names the confidence assigned to a successfully resolved computed field, 0.9. |
|
|
156
|
+
| `NUMBER_PATTERN` | const | `RegExp` | Holds the numeric-entity extraction pattern shared by `extractNumbers` and `assignEntities` — an optional leading `$`, thousands-comma-grouped digits, an optional decimal fraction, and an optional trailing `%`. |
|
|
157
|
+
| `UNSAFE_FIELD_SEGMENTS` | const | `readonly string[]` | Lists the prototype-pollution-unsafe field-path segments, `__proto__`, `prototype`, and `constructor` — `setField` refuses to write any path containing one, and returns its input unchanged. |
|
|
158
|
+
| `DEFAULT_CONTRACTIONS` | const | `Readonly<Record<string, string>>` | Holds the neutral built-in contraction expansions for `Normalizer` — small on purpose; callers merge their own map over this one. |
|
|
159
|
+
| `DEFAULT_LEXICON` | const | `Lexicon` | Holds the neutral default `Lexicon` a `Narrator` merges caller data over. |
|
|
160
|
+
|
|
161
|
+
```ts
|
|
162
|
+
import {
|
|
163
|
+
CONFIDENCE_ALIAS,
|
|
164
|
+
CONFIDENCE_CARRIED,
|
|
165
|
+
CONFIDENCE_COLLECT,
|
|
166
|
+
CONFIDENCE_COMPUTED,
|
|
167
|
+
CONFIDENCE_DEFAULT,
|
|
168
|
+
CONFIDENCE_EXACT,
|
|
169
|
+
CONFIDENCE_POSITIONAL,
|
|
170
|
+
DEFAULT_CONTRACTIONS,
|
|
171
|
+
DEFAULT_INTERPRET_FLOOR,
|
|
172
|
+
DEFAULT_INTERPRET_HISTORY,
|
|
173
|
+
DEFAULT_INTERPRET_SIMILARITY,
|
|
174
|
+
DEFAULT_LEXICON,
|
|
175
|
+
NUMBER_PATTERN,
|
|
176
|
+
UNSAFE_FIELD_SEGMENTS,
|
|
177
|
+
} from '@orkestrel/interpret'
|
|
178
|
+
|
|
179
|
+
DEFAULT_INTERPRET_SIMILARITY // 0.8
|
|
180
|
+
DEFAULT_INTERPRET_FLOOR // 0.3
|
|
181
|
+
DEFAULT_INTERPRET_HISTORY // 16
|
|
182
|
+
CONFIDENCE_EXACT // 1
|
|
183
|
+
CONFIDENCE_ALIAS // 0.9
|
|
184
|
+
CONFIDENCE_COLLECT // 0.9
|
|
185
|
+
CONFIDENCE_POSITIONAL // 0.7
|
|
186
|
+
CONFIDENCE_CARRIED // 0.7
|
|
187
|
+
CONFIDENCE_DEFAULT // 1
|
|
188
|
+
CONFIDENCE_COMPUTED // 0.9
|
|
189
|
+
NUMBER_PATTERN.source // the numeric-entity pattern
|
|
190
|
+
UNSAFE_FIELD_SEGMENTS // ['__proto__', 'prototype', 'constructor']
|
|
191
|
+
DEFAULT_CONTRACTIONS["can't"] // 'cannot'
|
|
192
|
+
DEFAULT_LEXICON.templates?.['subject.empty'] // 'with no fields'
|
|
193
|
+
DEFAULT_LEXICON.templates?.['prompt.base'] // '{{verb}} {{name}}'
|
|
194
|
+
DEFAULT_LEXICON.templates?.['ambiguity.entity'] // 'What is your {{entity}}?'
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
### Errors
|
|
198
|
+
|
|
199
|
+
| API | Kind | Summary |
|
|
200
|
+
| ------------------ | -------- | ---------------------------------------------------------------------------------------------------------------------- |
|
|
201
|
+
| `InterpretError` | class | Represents an error thrown by the interprets layer, carrying an `InterpretErrorCode` and an optional `context` record. |
|
|
202
|
+
| `isInterpretError` | function | Narrows an unknown caught value to an `InterpretError`. |
|
|
203
|
+
|
|
204
|
+
```ts
|
|
205
|
+
import { InterpretError, isInterpretError } from '@orkestrel/interpret'
|
|
206
|
+
|
|
207
|
+
try {
|
|
208
|
+
throw new InterpretError('DESTROYED', 'Interpret has been destroyed')
|
|
209
|
+
} catch (error) {
|
|
210
|
+
if (isInterpretError(error)) error.code // 'DESTROYED'
|
|
211
|
+
}
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
### Validators
|
|
215
|
+
|
|
216
|
+
Total guards composed from `@orkestrel/contract` combinators and `@orkestrel/reason` guards —
|
|
217
|
+
adversarial input (junk, cycles, hostile prototypes) returns `false`, never throws.
|
|
218
|
+
|
|
219
|
+
The posture splits by who produces the value. An input-record guard is exact: an extra key
|
|
220
|
+
fails, because an input this package owns that drifted from its declared shape is rejected
|
|
221
|
+
loudly. A result guard is open: an unknown member and a class instance pass when every
|
|
222
|
+
published member conforms, because a foreign engine's return is not this package's to narrow.
|
|
223
|
+
`InterpretInterface` is borrowable, so a consumer holding a borrowed engine guards its
|
|
224
|
+
`interpret` return with `isInterpretation` before dereferencing `intent`, `entities`, or
|
|
225
|
+
`ambiguities`. Each row's `Summary` names the posture its guard takes.
|
|
226
|
+
|
|
227
|
+
In a guard table a `Shape` cell holds the type the guard narrows to.
|
|
228
|
+
|
|
229
|
+
| API | Kind | Shape | Summary |
|
|
230
|
+
| ------------------ | -------- | ---------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
231
|
+
| `isEntityMapping` | function | `EntityMapping` | Determines whether a value is an exact `EntityMapping` input record — a literal alias-phrase extraction rule pointing at a subject field. |
|
|
232
|
+
| `isFieldDefault` | function | `FieldDefault` | Determines whether a value is an exact `FieldDefault` input record — a fallback value a `Template` fills onto an unresolved field. |
|
|
233
|
+
| `isComputedField` | function | `ComputedField` | Determines whether a value is an exact `ComputedField` input record — a declaratively computed field carrying a reasons `SymbolicExpression` tree. |
|
|
234
|
+
| `isTemplate` | function | `Template` | Determines whether a value is an exact `Template` input record — a named, versionable interpretation template. |
|
|
235
|
+
| `isProvenance` | function | `Provenance` | Determines whether a value is an open `Provenance` result record. |
|
|
236
|
+
| `isIntent` | function | `Intent` | Determines whether a value is an open `Intent` result record. |
|
|
237
|
+
| `isEntity` | function | `Entity` | Determines whether a value is an open `Entity` result record. |
|
|
238
|
+
| `isFieldMapping` | function | `FieldMapping` | Determines whether a value is an open `FieldMapping` result record. |
|
|
239
|
+
| `isAmbiguity` | function | `Ambiguity` | Determines whether a value is an open `Ambiguity` result record. |
|
|
240
|
+
| `isStageRecord` | function | `StageRecord` | Determines whether a value is an open `StageRecord` result record. |
|
|
241
|
+
| `isStageFailure` | function | `StageFailure` | Determines whether a value is an open `StageFailure` result record. |
|
|
242
|
+
| `isInterpretation` | function | `Interpretation` | Determines whether a value is an open `Interpretation` result record. |
|
|
243
|
+
|
|
244
|
+
```ts
|
|
245
|
+
import {
|
|
246
|
+
createInterpret,
|
|
247
|
+
isAmbiguity,
|
|
248
|
+
isComputedField,
|
|
249
|
+
isEntity,
|
|
250
|
+
isEntityMapping,
|
|
251
|
+
isFieldDefault,
|
|
252
|
+
isFieldMapping,
|
|
253
|
+
isIntent,
|
|
254
|
+
isInterpretation,
|
|
255
|
+
isProvenance,
|
|
256
|
+
isStageFailure,
|
|
257
|
+
isStageRecord,
|
|
258
|
+
isTemplate,
|
|
259
|
+
} from '@orkestrel/interpret'
|
|
260
|
+
import {
|
|
261
|
+
createFactorGroup,
|
|
262
|
+
createFieldFactor,
|
|
263
|
+
createQuantitativeDefinition,
|
|
264
|
+
} from '@orkestrel/reason'
|
|
265
|
+
|
|
266
|
+
isEntityMapping({ entity: 'age', aliases: ['years old'], field: 'age' }) // true
|
|
267
|
+
isFieldDefault({ field: 'term', value: 12 }) // true
|
|
268
|
+
isComputedField({
|
|
269
|
+
field: 'monthly',
|
|
270
|
+
expression: {
|
|
271
|
+
form: 'operation',
|
|
272
|
+
operator: 'divide',
|
|
273
|
+
left: { form: 'variable', name: 'deductible' },
|
|
274
|
+
right: { form: 'constant', value: 12 },
|
|
275
|
+
},
|
|
276
|
+
}) // true
|
|
277
|
+
isTemplate({
|
|
278
|
+
id: 't1',
|
|
279
|
+
name: 'Arithmetic',
|
|
280
|
+
domain: 'arithmetic',
|
|
281
|
+
intents: ['calculate'],
|
|
282
|
+
mappings: [],
|
|
283
|
+
defaults: [],
|
|
284
|
+
computations: [],
|
|
285
|
+
definition: createQuantitativeDefinition('t1', 'Arithmetic', [
|
|
286
|
+
createFactorGroup('total', 'sum', [createFieldFactor('value', 'value')]),
|
|
287
|
+
]),
|
|
288
|
+
}) // true
|
|
289
|
+
isProvenance({ category: 'extracted', detail: 'alias', metadata: true }) // true — open
|
|
290
|
+
isIntent({ action: 'calculate', domain: 'arithmetic', confidence: 1 }) // true
|
|
291
|
+
isEntity({ name: 'value', value: 42, provenance: { category: 'extracted' }, confidence: 1 }) // true
|
|
292
|
+
isFieldMapping({ field: 'value', provenance: { category: 'extracted' }, confidence: 1 }) // true
|
|
293
|
+
isAmbiguity({ field: 'value', question: 'Which value?', candidates: ['42'], required: true }) // true
|
|
294
|
+
isStageRecord({ stage: 'normalize', input: 'raw', output: 'clean', failed: false }) // true
|
|
295
|
+
isStageFailure({ stage: 'format', code: 'FORMAT_FAILED', message: 'failed' }) // true
|
|
296
|
+
|
|
297
|
+
const guardEngine = createInterpret()
|
|
298
|
+
isInterpretation(guardEngine.interpret('unmatched text')) // true
|
|
299
|
+
guardEngine.destroy()
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
### Helpers
|
|
303
|
+
|
|
304
|
+
Pure, exported utility functions — the referentially-transparent leaves
|
|
305
|
+
behind the `Interpret` orchestrator and its stages.
|
|
306
|
+
|
|
307
|
+
| API | Kind | Summary |
|
|
308
|
+
| -------------------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------- |
|
|
309
|
+
| `escapeRegExp` | function | Escapes every regex metacharacter in `text` so it matches literally when compiled into a `RegExp`. |
|
|
310
|
+
| `setField` | function | Writes a value at a (possibly nested) field path on a subject, copy-on-write. |
|
|
311
|
+
| `applyReplacements` | function | Replaces every whole-word occurrence of a map's keys with their values. |
|
|
312
|
+
| `collapseWhitespace` | function | Collapses every run of whitespace to a single space and trims the ends. |
|
|
313
|
+
| `tokenize` | function | Splits text into lowercase tokens, stripping punctuation outside a small numeric/currency-safe allowlist. |
|
|
314
|
+
| `extractNumbers` | function | Mines every numeric literal from text — optional leading `$`, thousands commas, an optional decimal fraction, an optional trailing `%`. |
|
|
315
|
+
| `assignEntities` | function | Assigns already-extracted numbers to a matched template's entity mappings. |
|
|
316
|
+
| `classifyIntent` | function | Classifies the action + domain intent of a text against caller-supplied vocabularies. |
|
|
317
|
+
| `scoreSimilarity` | function | Measures bigram (Dice coefficient) string similarity, case-insensitive. |
|
|
318
|
+
| `matchAlias` | function | Returns the best `scoreSimilarity` a token achieves against a list of aliases, gated by a threshold. |
|
|
319
|
+
| `canonicalize` | function | Renders a value into a canonical, key-order-stable string — the pre-image of `digestValue`. |
|
|
320
|
+
| `canonicalizeNode` | function | Renders one node of a value into its canonical, key-order-stable string, against the object ancestors already on the recursion path. |
|
|
321
|
+
| `digestValue` | function | Computes a canonical structural digest of a pure-JSON value — a key-order-stable FNV-1a hash rendered as an 8-hex-digit string. |
|
|
322
|
+
| `scoreTemplate` | function | Scores how well a classified intent matches one template's domain + action. |
|
|
323
|
+
| `matchTemplate` | function | Finds the best-scoring added template for a classified intent, gated by a confidence floor. |
|
|
324
|
+
| `variablesOf` | function | Collects every variable name referenced by a symbolic expression tree, in first-occurrence order. |
|
|
325
|
+
| `resolveExpression` | function | Evaluates a symbolic expression tree against resolved bindings. |
|
|
326
|
+
| `renderSubject` | function | Renders a one-line, display-neutral description of a reasons `Subject`, through an injected `Narrator`. |
|
|
327
|
+
|
|
328
|
+
```ts
|
|
329
|
+
import {
|
|
330
|
+
applyReplacements,
|
|
331
|
+
collapseWhitespace,
|
|
332
|
+
escapeRegExp,
|
|
333
|
+
setField,
|
|
334
|
+
tokenize,
|
|
335
|
+
} from '@orkestrel/interpret'
|
|
336
|
+
|
|
337
|
+
escapeRegExp('a.b*c') // 'a\\.b\\*c'
|
|
338
|
+
setField({ age: 25 }, 'age', 30) // { age: 30 }
|
|
339
|
+
setField({}, ['address', 'city'], 'Reno') // { address: { city: 'Reno' } }
|
|
340
|
+
applyReplacements("can't stop", { "can't": 'cannot' }) // 'cannot stop'
|
|
341
|
+
collapseWhitespace(' a b\t c ') // 'a b c'
|
|
342
|
+
tokenize('The rate is 85%.') // ['the', 'rate', 'is', '85%.']
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
Extraction, classification, and fuzzy matching — the leaves behind
|
|
346
|
+
`Extractor#extract` and template entity assignment:
|
|
347
|
+
|
|
348
|
+
```ts
|
|
349
|
+
import {
|
|
350
|
+
assignEntities,
|
|
351
|
+
classifyIntent,
|
|
352
|
+
extractNumbers,
|
|
353
|
+
matchAlias,
|
|
354
|
+
scoreSimilarity,
|
|
355
|
+
} from '@orkestrel/interpret'
|
|
356
|
+
|
|
357
|
+
extractNumbers('income was $50,000, age 25') // [50000, 25]
|
|
358
|
+
const mappings = [
|
|
359
|
+
{ entity: 'age', aliases: ['years old'], field: 'age' },
|
|
360
|
+
{ entity: 'score', aliases: ['credit score'], field: 'score' },
|
|
361
|
+
]
|
|
362
|
+
assignEntities([25, 720], mappings, '25 year old with score 720', 0.8)
|
|
363
|
+
classifyIntent('calculate my rate', { calculate: 'compute' }, { rating: ['rate'] })
|
|
364
|
+
scoreSimilarity('rate', 'rate') // 1
|
|
365
|
+
matchAlias('valu', ['value', 'amount'], 0.6) // ~0.86 — fuzzy hit on 'value'
|
|
366
|
+
```
|
|
367
|
+
|
|
368
|
+
Digest, template matching, computed-field resolution, and the reverse
|
|
369
|
+
direction:
|
|
370
|
+
|
|
371
|
+
```ts
|
|
372
|
+
import type { Template } from '@orkestrel/interpret'
|
|
373
|
+
import {
|
|
374
|
+
canonicalize,
|
|
375
|
+
canonicalizeNode,
|
|
376
|
+
createNarrator,
|
|
377
|
+
digestValue,
|
|
378
|
+
matchTemplate,
|
|
379
|
+
renderSubject,
|
|
380
|
+
resolveExpression,
|
|
381
|
+
scoreTemplate,
|
|
382
|
+
variablesOf,
|
|
383
|
+
} from '@orkestrel/interpret'
|
|
384
|
+
|
|
385
|
+
canonicalize({ b: 1, a: 2 }) === canonicalize({ a: 2, b: 1 }) // true
|
|
386
|
+
canonicalizeNode({ b: 1, a: 2 }, new Set()) // '{"a":2,"b":1}'
|
|
387
|
+
digestValue({ a: 1 }) === digestValue({ a: 1 }) // true — deterministic
|
|
388
|
+
matchTemplate({ confidence: 0 }, [], 0.3) // undefined — empty registry
|
|
389
|
+
variablesOf({
|
|
390
|
+
form: 'operation',
|
|
391
|
+
operator: 'divide',
|
|
392
|
+
left: { form: 'variable', name: 'deductible' },
|
|
393
|
+
right: { form: 'constant', value: 12 },
|
|
394
|
+
}) // ['deductible']
|
|
395
|
+
resolveExpression(
|
|
396
|
+
{
|
|
397
|
+
form: 'operation',
|
|
398
|
+
operator: 'divide',
|
|
399
|
+
left: { form: 'variable', name: 'deductible' },
|
|
400
|
+
right: { form: 'constant', value: 12 },
|
|
401
|
+
},
|
|
402
|
+
{ deductible: 6000 },
|
|
403
|
+
) // 500
|
|
404
|
+
renderSubject({ age: 25, income: 50000 }, createNarrator()) // 'with age: 25, income: 50000'
|
|
405
|
+
|
|
406
|
+
const gate = { action: 'compute', domain: 'rating', confidence: 1 }
|
|
407
|
+
const template: Template = {
|
|
408
|
+
id: 't1',
|
|
409
|
+
name: 'T',
|
|
410
|
+
domain: 'rating',
|
|
411
|
+
intents: ['compute'],
|
|
412
|
+
mappings: [],
|
|
413
|
+
defaults: [],
|
|
414
|
+
computations: [],
|
|
415
|
+
definition: { reasoning: 'symbolic', id: 't1', name: 'T', equations: [], variables: {} },
|
|
416
|
+
}
|
|
417
|
+
scoreTemplate(gate, template) // 1
|
|
418
|
+
```
|
|
419
|
+
|
|
420
|
+
### Parsers
|
|
421
|
+
|
|
422
|
+
Coercers — each returns its type or `undefined` off-shape, and never throws.
|
|
423
|
+
Template intake is total: an off-shape template returns `undefined`, and a
|
|
424
|
+
caller who wants a throw raises its own error from that `undefined`.
|
|
425
|
+
|
|
426
|
+
| API | Kind | Summary |
|
|
427
|
+
| --------------- | -------- | ---------------------------------------------------------------------------------------------------------- |
|
|
428
|
+
| `parseTemplate` | function | Parses a JSON string into a `Template`, or `undefined` on invalid JSON or a shape that fails `isTemplate`. |
|
|
429
|
+
|
|
430
|
+
```ts
|
|
431
|
+
import { parseTemplate } from '@orkestrel/interpret'
|
|
432
|
+
|
|
433
|
+
parseTemplate('not json') // undefined
|
|
434
|
+
```
|
|
435
|
+
|
|
436
|
+
### Factories
|
|
437
|
+
|
|
438
|
+
| API | Kind | Summary |
|
|
439
|
+
| ------------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
440
|
+
| `createInterpret` | function | Creates an interpretation orchestrator, returning an `InterpretInterface` seeded from `InterpretOptions`. |
|
|
441
|
+
| `createNormalizer` | function | Creates a text normalizer, returning a stateless `NormalizerInterface`. |
|
|
442
|
+
| `createExtractor` | function | Creates a template-agnostic intent classifier and number extractor, returning a stateless `ExtractorInterface`. |
|
|
443
|
+
| `createClarifier` | function | Creates a clarifier — carry-over, defaults, and computed-field resolution against an assigned entity set — returning a stateless `ClarifierInterface`. |
|
|
444
|
+
| `createFormatter` | function | Creates a prompt formatter, returning a stateless `FormatterInterface`. |
|
|
445
|
+
| `createGenerator` | function | Creates a subject and definition generator, returning a stateless `GeneratorInterface`. |
|
|
446
|
+
| `createTemplateManager` | function | Creates a template registry, returning a working `TemplateManagerInterface`. |
|
|
447
|
+
| `createSubjectManager` | function | Creates a subject registry, returning a working `SubjectManagerInterface`. |
|
|
448
|
+
| `createDefinitionManager` | function | Creates a definition registry, returning a working `DefinitionManagerInterface`. |
|
|
449
|
+
| `createInterpretContext` | function | Creates a cross-turn interpretation context, returning a working `InterpretContextInterface`. |
|
|
450
|
+
| `createNarrator` | function | Creates a lexicon-driven reverse-direction rendering engine, returning a stateless `NarratorInterface`. |
|
|
451
|
+
|
|
452
|
+
```ts
|
|
453
|
+
import {
|
|
454
|
+
createClarifier,
|
|
455
|
+
createDefinitionManager,
|
|
456
|
+
createExtractor,
|
|
457
|
+
createFormatter,
|
|
458
|
+
createGenerator,
|
|
459
|
+
createInterpret,
|
|
460
|
+
createInterpretContext,
|
|
461
|
+
createNarrator,
|
|
462
|
+
createNormalizer,
|
|
463
|
+
createSubjectManager,
|
|
464
|
+
createTemplateManager,
|
|
465
|
+
} from '@orkestrel/interpret'
|
|
466
|
+
import {
|
|
467
|
+
createFactorGroup,
|
|
468
|
+
createFieldFactor,
|
|
469
|
+
createQuantitativeDefinition,
|
|
470
|
+
} from '@orkestrel/reason'
|
|
471
|
+
|
|
472
|
+
const interpret = createInterpret()
|
|
473
|
+
interpret.destroy()
|
|
474
|
+
|
|
475
|
+
createNormalizer().normalize("it's cold") // { text: 'it is cold', changes: [...] }
|
|
476
|
+
createExtractor({ actions: { calculate: 'calculate' }, domains: { arithmetic: ['arithmetic'] } })
|
|
477
|
+
createClarifier({ floor: 0.5 })
|
|
478
|
+
createFormatter({ verbs: { calculate: 'Calculate' } })
|
|
479
|
+
createGenerator()
|
|
480
|
+
createInterpretContext({ session: 'turn-1', history: 4 })
|
|
481
|
+
createNarrator({ lexicon: { templates: { 'subject.empty': 'nothing here' } } })
|
|
482
|
+
|
|
483
|
+
const templates = createTemplateManager({
|
|
484
|
+
templates: [
|
|
485
|
+
{
|
|
486
|
+
id: 't1',
|
|
487
|
+
name: 'Arithmetic',
|
|
488
|
+
domain: 'arithmetic',
|
|
489
|
+
intents: ['calculate'],
|
|
490
|
+
mappings: [{ entity: 'value', aliases: [], field: 'value' }],
|
|
491
|
+
defaults: [],
|
|
492
|
+
computations: [],
|
|
493
|
+
definition: createQuantitativeDefinition('t1', 'Arithmetic', [
|
|
494
|
+
createFactorGroup('total', 'sum', [createFieldFactor('value', 'value')]),
|
|
495
|
+
]),
|
|
496
|
+
},
|
|
497
|
+
],
|
|
498
|
+
})
|
|
499
|
+
templates.count // 1
|
|
500
|
+
templates.destroy()
|
|
501
|
+
|
|
502
|
+
createSubjectManager({ subjects: [{ value: 1 }] }).count // 1
|
|
503
|
+
createDefinitionManager({
|
|
504
|
+
definitions: [
|
|
505
|
+
createQuantitativeDefinition('d1', 'D1', [
|
|
506
|
+
createFactorGroup('total', 'sum', [createFieldFactor('value', 'value')]),
|
|
507
|
+
]),
|
|
508
|
+
],
|
|
509
|
+
}).count // 1
|
|
510
|
+
```
|
|
511
|
+
|
|
512
|
+
### Classes
|
|
513
|
+
|
|
514
|
+
| API | Kind | Summary |
|
|
515
|
+
| ------------------- | ----- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
516
|
+
| `Interpret` | class | Implements the interpretation orchestrator — the sole public entry point of the `interprets` module, mirroring the reasons `Reason` orchestrator shape: it runs the `[normalize, extract, clarify, format, generate]` pipeline, owns the template registry and the context, and exposes the reverse direction. |
|
|
517
|
+
| `Narrator` | class | Implements a stateless, total, lexicon-driven rendering engine for the reverse direction — the reverse-direction mirror of the forward `Formatter`'s `verbs` seam, supplying mechanism rather than wording policy. |
|
|
518
|
+
| `Normalizer` | class | Implements the normalize stage: applies contraction, abbreviation, and correction substitutions in order, then collapses whitespace. |
|
|
519
|
+
| `Extractor` | class | Implements the extract stage: template-agnostic intent classification plus raw numeric-entity mining. |
|
|
520
|
+
| `Clarifier` | class | Implements the clarify stage: resolves same-domain carry-over, template defaults, and declaratively computed fields against an already-assigned entity set, surfacing an `Ambiguity` for every required mapping that stays unresolved. |
|
|
521
|
+
| `Formatter` | class | Implements the format stage: renders the refined natural-language prompt for a matched template. |
|
|
522
|
+
| `Generator` | class | Implements the generate stage: builds the final `Subject` from a fully resolved entity set, plus its complete field audit. |
|
|
523
|
+
| `RecordManager` | class | Implements the shared registry engine behind every record manager in this module — it owns the `Map`, the content-hash and version rule, the batch `remove` overloads, and teardown. |
|
|
524
|
+
| `TemplateManager` | class | Implements the template registry — a self-owning, versioned and content-hashed record-holder for the `Template`s an `Interpret` orchestrator matches against. |
|
|
525
|
+
| `SubjectManager` | class | Implements the subject registry — a self-owning, versioned and content-hashed record-holder that mints its own record identity for every `Subject` (a `Subject` carries no `id` field of its own). |
|
|
526
|
+
| `DefinitionManager` | class | Implements the definition registry — a self-owning, versioned and content-hashed record-holder for the reasons `Definition`s an interpretation produces. |
|
|
527
|
+
| `InterpretContext` | class | Implements the cross-turn interpretation context — a capped, replayable history of completed `Interpretation`s plus the subject and definition registries carry-over reads from. |
|
|
528
|
+
|
|
529
|
+
## Methods
|
|
530
|
+
|
|
531
|
+
The public methods of each behavioral interface — one table per type, keyed
|
|
532
|
+
by its backticked name, every call-signature member listed (the `readonly`
|
|
533
|
+
data members — `emitter` on every stage-adjacent manager and `Interpret`;
|
|
534
|
+
`count` on every record registry; `session`, `subjects`, and `definitions` on
|
|
535
|
+
`InterpretContext` — stay off the method tables). Each implementing class
|
|
536
|
+
exposes exactly its interface's methods, so this doubles as the per-instance
|
|
537
|
+
method surface.
|
|
538
|
+
|
|
539
|
+
#### `NormalizerInterface`
|
|
540
|
+
|
|
541
|
+
| Method | Returns | Summary |
|
|
542
|
+
| ----------- | ----------------- | -------------------------------------------------------------------------------------------------------- |
|
|
543
|
+
| `normalize` | `NormalizeResult` | Applies the contraction, abbreviation, and correction substitutions in order, then collapses whitespace. |
|
|
544
|
+
|
|
545
|
+
```ts
|
|
546
|
+
import { createNormalizer } from '@orkestrel/interpret'
|
|
547
|
+
|
|
548
|
+
const normalizer = createNormalizer({ contractions: { "can't": 'cannot' } })
|
|
549
|
+
normalizer.normalize("can't stop") // { text: 'cannot stop', changes: [{ from: "can't", to: 'cannot' }] }
|
|
550
|
+
```
|
|
551
|
+
|
|
552
|
+
#### `ExtractorInterface`
|
|
553
|
+
|
|
554
|
+
| Method | Returns | Summary |
|
|
555
|
+
| --------- | --------------- | -------------------------------------------------------------------- |
|
|
556
|
+
| `extract` | `ExtractResult` | Classifies the intent and mines every numeric literal from the text. |
|
|
557
|
+
|
|
558
|
+
```ts
|
|
559
|
+
import { createExtractor } from '@orkestrel/interpret'
|
|
560
|
+
|
|
561
|
+
const extractor = createExtractor({
|
|
562
|
+
actions: { calculate: 'compute' },
|
|
563
|
+
domains: { rating: ['rate'] },
|
|
564
|
+
})
|
|
565
|
+
extractor.extract('calculate my rate at 85')
|
|
566
|
+
// { intent: { action: 'compute', domain: 'rating', confidence: 1 }, numbers: [85] }
|
|
567
|
+
```
|
|
568
|
+
|
|
569
|
+
#### `ClarifierInterface`
|
|
570
|
+
|
|
571
|
+
| Method | Returns | Summary |
|
|
572
|
+
| --------- | --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
573
|
+
| `clarify` | `ClarifyResult` | Resolves carry-over, template defaults, and computed fields, and surfaces an `Ambiguity` for every unresolved required field, worded through the narrator's `ambiguity.entity` line. |
|
|
574
|
+
|
|
575
|
+
```ts
|
|
576
|
+
import { createClarifier } from '@orkestrel/interpret'
|
|
577
|
+
|
|
578
|
+
const clarifier = createClarifier({ floor: 0.3 })
|
|
579
|
+
clarifier.clarify(
|
|
580
|
+
[],
|
|
581
|
+
{
|
|
582
|
+
id: 't1',
|
|
583
|
+
name: 'Arithmetic',
|
|
584
|
+
domain: 'arithmetic',
|
|
585
|
+
intents: ['calculate'],
|
|
586
|
+
mappings: [{ entity: 'value', aliases: [], field: 'value', required: true }],
|
|
587
|
+
defaults: [],
|
|
588
|
+
computations: [],
|
|
589
|
+
definition: {
|
|
590
|
+
reasoning: 'symbolic',
|
|
591
|
+
id: 't1',
|
|
592
|
+
name: 'Arithmetic',
|
|
593
|
+
equations: [],
|
|
594
|
+
variables: {},
|
|
595
|
+
},
|
|
596
|
+
},
|
|
597
|
+
undefined,
|
|
598
|
+
{ action: 'calculate', domain: 'arithmetic', confidence: 1 },
|
|
599
|
+
) // { entities: [], ambiguities: [{ field: 'value', ... }] }
|
|
600
|
+
```
|
|
601
|
+
|
|
602
|
+
A computation addresses one numeric element of an array-valued field as
|
|
603
|
+
`{field}.{index}`, so a template whose collection has a known length declares an
|
|
604
|
+
aggregate over it:
|
|
605
|
+
|
|
606
|
+
```ts
|
|
607
|
+
import { createClarifier } from '@orkestrel/interpret'
|
|
608
|
+
import { createOperation, createVariable } from '@orkestrel/reason'
|
|
609
|
+
|
|
610
|
+
// `value.0` and `value.1` name the first two elements of the array-valued
|
|
611
|
+
// `value` field. A collection whose length varies per turn has no declarable
|
|
612
|
+
// aggregate: `resolveExpression` returns `undefined` for an unbound variable,
|
|
613
|
+
// so a template naming `value.2` against a two-element array lands no `total`
|
|
614
|
+
// at all.
|
|
615
|
+
const clarifier = createClarifier({ floor: 0.3 })
|
|
616
|
+
clarifier.clarify(
|
|
617
|
+
[{ name: 'value', value: [2, 3], provenance: { category: 'extracted' }, confidence: 1 }],
|
|
618
|
+
{
|
|
619
|
+
id: 't2',
|
|
620
|
+
name: 'Total',
|
|
621
|
+
domain: 'arithmetic',
|
|
622
|
+
intents: ['calculate'],
|
|
623
|
+
mappings: [{ entity: 'value', aliases: [], field: 'value' }],
|
|
624
|
+
defaults: [],
|
|
625
|
+
computations: [
|
|
626
|
+
{
|
|
627
|
+
field: 'total',
|
|
628
|
+
expression: createOperation('add', createVariable('value.0'), createVariable('value.1')),
|
|
629
|
+
},
|
|
630
|
+
],
|
|
631
|
+
definition: {
|
|
632
|
+
reasoning: 'symbolic',
|
|
633
|
+
id: 't2',
|
|
634
|
+
name: 'Total',
|
|
635
|
+
equations: [],
|
|
636
|
+
variables: {},
|
|
637
|
+
},
|
|
638
|
+
},
|
|
639
|
+
undefined,
|
|
640
|
+
{ action: 'calculate', domain: 'arithmetic', confidence: 1 },
|
|
641
|
+
) // total lands as 5, at CONFIDENCE_COMPUTED, with no ambiguity
|
|
642
|
+
```
|
|
643
|
+
|
|
644
|
+
#### `FormatterInterface`
|
|
645
|
+
|
|
646
|
+
| Method | Returns | Summary |
|
|
647
|
+
| -------- | -------------- | ----------------------------------------------------------------------------------------------------------------------------- |
|
|
648
|
+
| `format` | `FormatResult` | Renders the refined natural-language prompt for a matched template, clause by clause through the narrator's `prompt.*` lines. |
|
|
649
|
+
|
|
650
|
+
```ts
|
|
651
|
+
import { createFormatter } from '@orkestrel/interpret'
|
|
652
|
+
|
|
653
|
+
const formatter = createFormatter({ verbs: { calculate: 'Calculate' } })
|
|
654
|
+
formatter.format(
|
|
655
|
+
{ action: 'calculate', domain: 'arithmetic', confidence: 1 },
|
|
656
|
+
{
|
|
657
|
+
id: 't1',
|
|
658
|
+
name: 'Arithmetic',
|
|
659
|
+
domain: 'arithmetic',
|
|
660
|
+
intents: ['calculate'],
|
|
661
|
+
mappings: [],
|
|
662
|
+
defaults: [],
|
|
663
|
+
computations: [],
|
|
664
|
+
definition: {
|
|
665
|
+
reasoning: 'symbolic',
|
|
666
|
+
id: 't1',
|
|
667
|
+
name: 'Arithmetic',
|
|
668
|
+
equations: [],
|
|
669
|
+
variables: {},
|
|
670
|
+
},
|
|
671
|
+
},
|
|
672
|
+
[],
|
|
673
|
+
[],
|
|
674
|
+
) // { prompt: 'Calculate Arithmetic' }
|
|
675
|
+
```
|
|
676
|
+
|
|
677
|
+
#### `GeneratorInterface`
|
|
678
|
+
|
|
679
|
+
| Method | Returns | Summary |
|
|
680
|
+
| ---------- | ---------------- | --------------------------------------------------------------------------------------------------------------------------- |
|
|
681
|
+
| `generate` | `GenerateResult` | Builds the final subject and definition pair plus its complete field audit, deriving no field the template did not declare. |
|
|
682
|
+
|
|
683
|
+
```ts
|
|
684
|
+
import { createGenerator } from '@orkestrel/interpret'
|
|
685
|
+
|
|
686
|
+
const generator = createGenerator()
|
|
687
|
+
generator.generate(
|
|
688
|
+
[
|
|
689
|
+
{
|
|
690
|
+
name: 'value',
|
|
691
|
+
value: 42,
|
|
692
|
+
provenance: { category: 'extracted', detail: 'collect' },
|
|
693
|
+
confidence: 0.9,
|
|
694
|
+
},
|
|
695
|
+
],
|
|
696
|
+
{
|
|
697
|
+
id: 't1',
|
|
698
|
+
name: 'Arithmetic',
|
|
699
|
+
domain: 'arithmetic',
|
|
700
|
+
intents: ['calculate'],
|
|
701
|
+
mappings: [{ entity: 'value', aliases: [], field: 'value' }],
|
|
702
|
+
defaults: [],
|
|
703
|
+
computations: [],
|
|
704
|
+
definition: {
|
|
705
|
+
reasoning: 'symbolic',
|
|
706
|
+
id: 't1',
|
|
707
|
+
name: 'Arithmetic',
|
|
708
|
+
equations: [],
|
|
709
|
+
variables: {},
|
|
710
|
+
},
|
|
711
|
+
},
|
|
712
|
+
) // { subject: { value: 42 }, mappings: [...], confidence: 0.9, ... }
|
|
713
|
+
```
|
|
714
|
+
|
|
715
|
+
#### `NarratorInterface`
|
|
716
|
+
|
|
717
|
+
Every method is total and never throws: a lookup miss degrades to its documented fallback,
|
|
718
|
+
because wording is mechanism rather than policy.
|
|
719
|
+
|
|
720
|
+
| Method | Returns | Summary |
|
|
721
|
+
| ---------- | -------- | --------------------------------------------------------------------------------------------------------------- |
|
|
722
|
+
| `phrase` | `string` | Looks up a two-level `table` and `key` pair in the lexicon's `phrases`, falling back to `fallback` or to `key`. |
|
|
723
|
+
| `label` | `string` | Renders a field's display label from `labels`, falling back to `formatField`. |
|
|
724
|
+
| `line` | `string` | Interpolates a named `templates` entry against `values`, falling back to an empty string when the id is absent. |
|
|
725
|
+
| `value` | `string` | Runs a named formatter over a raw value, catching a throw and falling back to `String(raw)`. |
|
|
726
|
+
| `describe` | `string` | Renders a reasons `Definition` to a one-line, display-neutral description. |
|
|
727
|
+
| `narrate` | `string` | Renders a reasons `ReasonResult` to a one-line, display-neutral description. |
|
|
728
|
+
|
|
729
|
+
```ts
|
|
730
|
+
import { createNarrator } from '@orkestrel/interpret'
|
|
731
|
+
import { createQuantitativeDefinition } from '@orkestrel/reason'
|
|
732
|
+
|
|
733
|
+
const narrator = createNarrator({
|
|
734
|
+
lexicon: { phrases: { comparison: { equals: 'is' } } },
|
|
735
|
+
formatters: { money: (value) => `$${String(value)}` },
|
|
736
|
+
})
|
|
737
|
+
narrator.phrase('comparison', 'equals', 'equals') // 'is'
|
|
738
|
+
narrator.label('age') // 'age'
|
|
739
|
+
narrator.line('subject.empty', {}) // 'with no fields'
|
|
740
|
+
narrator.value('money', 5) // '$5'
|
|
741
|
+
narrator.describe(createQuantitativeDefinition('risk', 'Risk', []))
|
|
742
|
+
narrator.narrate({
|
|
743
|
+
reasoning: 'quantitative',
|
|
744
|
+
value: 5,
|
|
745
|
+
count: 1,
|
|
746
|
+
groups: [],
|
|
747
|
+
trace: [],
|
|
748
|
+
errors: [],
|
|
749
|
+
success: true,
|
|
750
|
+
})
|
|
751
|
+
```
|
|
752
|
+
|
|
753
|
+
#### `RecordManagerInterface`
|
|
754
|
+
|
|
755
|
+
The shared registry engine every record manager composes. `add` derives each record's `hash`
|
|
756
|
+
from the value's content and bumps `version` only when that hash changes at a reused id; the
|
|
757
|
+
concrete record shape comes from the `RecordFunction` the caller passes, which is where a
|
|
758
|
+
manager names its own value field. `count` is the registry's lone tally. `remove`'s array form
|
|
759
|
+
is all-or-nothing. A call after `destroy()` throws `InterpretError('DESTROYED', …)` naming the
|
|
760
|
+
configured `entity`.
|
|
761
|
+
|
|
762
|
+
| Method | Returns | Summary |
|
|
763
|
+
| --------- | ---------------------- | --------------------------------------------------------------------------------------------------------------------- |
|
|
764
|
+
| `has` | `boolean` | Reports whether a record with the given id is held. |
|
|
765
|
+
| `record` | `TRecord \| undefined` | Looks up one held record by id — the singular accessor. |
|
|
766
|
+
| `records` | `readonly TRecord[]` | Lists every held record — the plural accessor. |
|
|
767
|
+
| `add` | `TRecord` | Stamps a value with its id, version, and content hash, builds the record, holds it, and emits `add`. |
|
|
768
|
+
| `remove` | `boolean` (or `void`) | Removes the listed records by id, one record by id, or every record, and emits `remove` per removed id. |
|
|
769
|
+
| `destroy` | `void` | Tears the record registry down idempotently — clears the collection, emits `destroy`, then destroys the emitter last. |
|
|
770
|
+
|
|
771
|
+
```ts
|
|
772
|
+
import { RecordManager } from '@orkestrel/interpret'
|
|
773
|
+
|
|
774
|
+
interface NoteRecord {
|
|
775
|
+
readonly id: string
|
|
776
|
+
readonly note: string
|
|
777
|
+
readonly version: number
|
|
778
|
+
readonly hash: string
|
|
779
|
+
}
|
|
780
|
+
|
|
781
|
+
const notes = new RecordManager<string, NoteRecord>({ entity: 'Note' })
|
|
782
|
+
const note = notes.add('n1', 'first', (stamp, value) => ({
|
|
783
|
+
id: stamp.id,
|
|
784
|
+
note: value,
|
|
785
|
+
version: stamp.version,
|
|
786
|
+
hash: stamp.hash,
|
|
787
|
+
}))
|
|
788
|
+
note.version // 1
|
|
789
|
+
notes.count // 1
|
|
790
|
+
notes.has('n1') // true
|
|
791
|
+
notes.record('n1') // the NoteRecord, or undefined
|
|
792
|
+
notes.records() // every held record
|
|
793
|
+
notes.remove('n1') // true
|
|
794
|
+
notes.destroy()
|
|
795
|
+
```
|
|
796
|
+
|
|
797
|
+
#### `TemplateManagerInterface`
|
|
798
|
+
|
|
799
|
+
The self-owning, ordered registry over templates. `add` derives each record's `hash` from the
|
|
800
|
+
template's content and bumps `version` only when that hash changes. `remove`'s array form is
|
|
801
|
+
all-or-nothing. A call after `destroy()` throws `InterpretError('DESTROYED', …)`.
|
|
802
|
+
|
|
803
|
+
| Method | Returns | Summary |
|
|
804
|
+
| ----------- | ----------------------------- | ----------------------------------------------------------------------------------------------------------------------- |
|
|
805
|
+
| `has` | `boolean` | Reports whether a template with the given id has been added. |
|
|
806
|
+
| `template` | `TemplateRecord \| undefined` | Looks up one added template record by id — the singular accessor. |
|
|
807
|
+
| `templates` | `readonly TemplateRecord[]` | Lists every added template record — the plural accessor. |
|
|
808
|
+
| `add` | `TemplateRecord` | Adds, or re-adds, one template from its data, and emits `add`. |
|
|
809
|
+
| `remove` | `boolean` (or `void`) | Removes the listed templates by id, one template by id, or every template, and emits `remove` per removed id. |
|
|
810
|
+
| `destroy` | `void` | Tears the template registry down idempotently — clears the collection, emits `destroy`, then destroys the emitter last. |
|
|
811
|
+
|
|
812
|
+
```ts
|
|
813
|
+
import { createTemplateManager } from '@orkestrel/interpret'
|
|
814
|
+
import {
|
|
815
|
+
createFactorGroup,
|
|
816
|
+
createFieldFactor,
|
|
817
|
+
createQuantitativeDefinition,
|
|
818
|
+
} from '@orkestrel/reason'
|
|
819
|
+
|
|
820
|
+
const templates = createTemplateManager()
|
|
821
|
+
const record = templates.add({
|
|
822
|
+
id: 't1',
|
|
823
|
+
name: 'Arithmetic',
|
|
824
|
+
domain: 'arithmetic',
|
|
825
|
+
intents: ['calculate'],
|
|
826
|
+
mappings: [],
|
|
827
|
+
defaults: [],
|
|
828
|
+
computations: [],
|
|
829
|
+
definition: createQuantitativeDefinition('t1', 'Arithmetic', [
|
|
830
|
+
createFactorGroup('total', 'sum', [createFieldFactor('value', 'value')]),
|
|
831
|
+
]),
|
|
832
|
+
})
|
|
833
|
+
record.version // 1
|
|
834
|
+
templates.count // 1
|
|
835
|
+
templates.has('t1') // true
|
|
836
|
+
templates.template('t1') // the TemplateRecord, or undefined
|
|
837
|
+
templates.templates() // every added record
|
|
838
|
+
templates.remove('t1') // true
|
|
839
|
+
templates.destroy()
|
|
840
|
+
```
|
|
841
|
+
|
|
842
|
+
#### `SubjectManagerInterface`
|
|
843
|
+
|
|
844
|
+
Mirrors `TemplateManagerInterface`, minting its own record ids (a `Subject`
|
|
845
|
+
carries no `id` field of its own) unless the caller overrides through
|
|
846
|
+
`RecordOptions.id`.
|
|
847
|
+
|
|
848
|
+
| Method | Returns | Summary |
|
|
849
|
+
| ---------- | ---------------------------- | ---------------------------------------------------------------------------------------------------------------------- |
|
|
850
|
+
| `has` | `boolean` | Reports whether a subject with the given id has been added. |
|
|
851
|
+
| `subject` | `SubjectRecord \| undefined` | Looks up one added subject record by id — the singular accessor. |
|
|
852
|
+
| `subjects` | `readonly SubjectRecord[]` | Lists every added subject record — the plural accessor. |
|
|
853
|
+
| `add` | `SubjectRecord` | Adds one subject, minting a fresh record id when the caller supplies none, and emits `add`. |
|
|
854
|
+
| `remove` | `boolean` (or `void`) | Removes the listed subjects by id, one subject by id, or every subject, and emits `remove` per removed id. |
|
|
855
|
+
| `destroy` | `void` | Tears the subject registry down idempotently — clears the collection, emits `destroy`, then destroys the emitter last. |
|
|
856
|
+
|
|
857
|
+
```ts
|
|
858
|
+
import { createSubjectManager } from '@orkestrel/interpret'
|
|
859
|
+
|
|
860
|
+
const subjects = createSubjectManager()
|
|
861
|
+
const first = subjects.add({ age: 25 })
|
|
862
|
+
subjects.count // 1
|
|
863
|
+
subjects.has(first.id) // true
|
|
864
|
+
subjects.subject(first.id) // the SubjectRecord
|
|
865
|
+
subjects.subjects() // every added record
|
|
866
|
+
subjects.remove(first.id) // true
|
|
867
|
+
subjects.destroy()
|
|
868
|
+
```
|
|
869
|
+
|
|
870
|
+
#### `DefinitionManagerInterface`
|
|
871
|
+
|
|
872
|
+
Mirrors `TemplateManagerInterface`, defaulting each record id to the
|
|
873
|
+
definition's own `id`.
|
|
874
|
+
|
|
875
|
+
| Method | Returns | Summary |
|
|
876
|
+
| ------------- | ------------------------------- | ------------------------------------------------------------------------------------------------------------------------- |
|
|
877
|
+
| `has` | `boolean` | Reports whether a definition with the given id has been added. |
|
|
878
|
+
| `definition` | `DefinitionRecord \| undefined` | Looks up one added definition record by id — the singular accessor. |
|
|
879
|
+
| `definitions` | `readonly DefinitionRecord[]` | Lists every added definition record — the plural accessor. |
|
|
880
|
+
| `add` | `DefinitionRecord` | Adds, or re-adds, one definition, and emits `add`. |
|
|
881
|
+
| `remove` | `boolean` (or `void`) | Removes the listed definitions by id, one definition by id, or every definition, and emits `remove` per removed id. |
|
|
882
|
+
| `destroy` | `void` | Tears the definition registry down idempotently — clears the collection, emits `destroy`, then destroys the emitter last. |
|
|
883
|
+
|
|
884
|
+
```ts
|
|
885
|
+
import { createDefinitionManager } from '@orkestrel/interpret'
|
|
886
|
+
import {
|
|
887
|
+
createFactorGroup,
|
|
888
|
+
createFieldFactor,
|
|
889
|
+
createQuantitativeDefinition,
|
|
890
|
+
} from '@orkestrel/reason'
|
|
891
|
+
|
|
892
|
+
const definitions = createDefinitionManager()
|
|
893
|
+
const record = definitions.add(
|
|
894
|
+
createQuantitativeDefinition('d1', 'D1', [
|
|
895
|
+
createFactorGroup('total', 'sum', [createFieldFactor('value', 'value')]),
|
|
896
|
+
]),
|
|
897
|
+
)
|
|
898
|
+
definitions.count // 1
|
|
899
|
+
definitions.has(record.id) // true
|
|
900
|
+
definitions.definition(record.id) // the DefinitionRecord
|
|
901
|
+
definitions.definitions() // every added record
|
|
902
|
+
definitions.remove(record.id) // true
|
|
903
|
+
definitions.destroy()
|
|
904
|
+
```
|
|
905
|
+
|
|
906
|
+
#### `InterpretContextInterface`
|
|
907
|
+
|
|
908
|
+
`previous()` returns the ring buffer newest-last, capped at the configured
|
|
909
|
+
`history`. `entities()` flattens every entity across the buffered history,
|
|
910
|
+
most recent last. `clear()` resets the history, the subject registry, and the
|
|
911
|
+
definition registry without tearing the context down.
|
|
912
|
+
|
|
913
|
+
| Method | Returns | Summary |
|
|
914
|
+
| ---------- | --------------------------- | ---------------------------------------------------------------------------------------------------------------- |
|
|
915
|
+
| `previous` | `readonly Interpretation[]` | Lists the buffered history, newest last, capped at `history`. |
|
|
916
|
+
| `entities` | `readonly Entity[]` | Flattens every entity recorded across the buffered history, most recent last. |
|
|
917
|
+
| `add` | `void` | Pushes one completed `Interpretation`, dropping the oldest entry past the cap. |
|
|
918
|
+
| `clear` | `void` | Resets the history, the subject registry, and the definition registry without destroying the context. |
|
|
919
|
+
| `destroy` | `void` | Tears the context down idempotently — the subject registry, then the definition registry, then the emitter last. |
|
|
920
|
+
|
|
921
|
+
```ts
|
|
922
|
+
import { createInterpretContext } from '@orkestrel/interpret'
|
|
923
|
+
|
|
924
|
+
const context = createInterpretContext({ session: 'turn-1', history: 4 })
|
|
925
|
+
context.previous() // []
|
|
926
|
+
context.entities() // []
|
|
927
|
+
context.add({
|
|
928
|
+
text: '42',
|
|
929
|
+
normalized: '42',
|
|
930
|
+
intent: { confidence: 0 },
|
|
931
|
+
entities: [],
|
|
932
|
+
mappings: [],
|
|
933
|
+
ambiguities: [],
|
|
934
|
+
prompt: '',
|
|
935
|
+
stages: [],
|
|
936
|
+
failures: [],
|
|
937
|
+
confidence: 0,
|
|
938
|
+
digest: 'abc',
|
|
939
|
+
})
|
|
940
|
+
context.clear()
|
|
941
|
+
context.destroy()
|
|
942
|
+
```
|
|
943
|
+
|
|
944
|
+
#### `InterpretInterface`
|
|
945
|
+
|
|
946
|
+
`interpret` is genuinely synchronous. `add`, `remove`, `template`, and `templates` name the
|
|
947
|
+
same acts as the internal `TemplateManagerInterface` they delegate to, and `add` returns
|
|
948
|
+
`void` where the manager returns the record it minted. `describe` and `narrate` are the
|
|
949
|
+
reverse direction. After `destroy()` every method except the `emitter` getter and `destroy`
|
|
950
|
+
itself throws `InterpretError('DESTROYED', …)`; `destroy()` is idempotent, leaves a `context`
|
|
951
|
+
the caller supplied alive, and tears the emitter down last. You observe only the
|
|
952
|
+
supplied-context half of that rule: `InterpretInterface` publishes no context accessor, so
|
|
953
|
+
nothing outside reads the state of a context the orchestrator constructed itself or
|
|
954
|
+
subscribes to its emitter.
|
|
955
|
+
|
|
956
|
+
| Method | Returns | Summary |
|
|
957
|
+
| ----------- | ----------------------- | --------------------------------------------------------------------------------------------------------------------------------------- |
|
|
958
|
+
| `interpret` | `Interpretation` | Runs the `[normalize, extract, clarify, format, generate]` pipeline over raw text, returning a complete or a visibly incomplete result. |
|
|
959
|
+
| `add` | `void` | Adds one template, and emits `add`. |
|
|
960
|
+
| `remove` | `boolean` (or `void`) | Removes the listed templates by id, one template by id, or every template. |
|
|
961
|
+
| `template` | `Template \| undefined` | Looks up one added template's plain data by id. |
|
|
962
|
+
| `templates` | `readonly Template[]` | Lists every added template's plain data. |
|
|
963
|
+
| `describe` | `string` | Renders a reasons `Definition` to a one-line, display-neutral description. |
|
|
964
|
+
| `narrate` | `string` | Renders a reasons `ReasonResult` to a one-line, display-neutral description. |
|
|
965
|
+
| `destroy` | `void` | Tears the orchestrator down idempotently — the template registry, the context it constructed itself, then the emitter last. |
|
|
966
|
+
|
|
967
|
+
```ts
|
|
968
|
+
import { createExtractor, createInterpret } from '@orkestrel/interpret'
|
|
969
|
+
import {
|
|
970
|
+
createFactorGroup,
|
|
971
|
+
createFieldFactor,
|
|
972
|
+
createQuantitativeDefinition,
|
|
973
|
+
} from '@orkestrel/reason'
|
|
974
|
+
|
|
975
|
+
const interpret = createInterpret({
|
|
976
|
+
extractor: createExtractor({
|
|
977
|
+
actions: { calculate: 'calculate' },
|
|
978
|
+
domains: { arithmetic: ['arithmetic'] },
|
|
979
|
+
}),
|
|
980
|
+
})
|
|
981
|
+
interpret.add({
|
|
982
|
+
id: 't1',
|
|
983
|
+
name: 'Arithmetic',
|
|
984
|
+
domain: 'arithmetic',
|
|
985
|
+
intents: ['calculate'],
|
|
986
|
+
mappings: [{ entity: 'value', aliases: [], field: 'value' }],
|
|
987
|
+
defaults: [],
|
|
988
|
+
computations: [],
|
|
989
|
+
definition: createQuantitativeDefinition('t1', 'Arithmetic', [
|
|
990
|
+
createFactorGroup('total', 'sum', [createFieldFactor('value', 'value')]),
|
|
991
|
+
]),
|
|
992
|
+
})
|
|
993
|
+
const result = interpret.interpret('calculate arithmetic 42')
|
|
994
|
+
result.subject // { value: 42 }
|
|
995
|
+
interpret.template('t1') // the plain Template data
|
|
996
|
+
interpret.templates() // every added template
|
|
997
|
+
interpret.describe(createQuantitativeDefinition('t1', 'Arithmetic', []))
|
|
998
|
+
interpret.narrate({
|
|
999
|
+
reasoning: 'symbolic',
|
|
1000
|
+
solutions: {},
|
|
1001
|
+
solved: [],
|
|
1002
|
+
trace: [],
|
|
1003
|
+
errors: [],
|
|
1004
|
+
success: true,
|
|
1005
|
+
})
|
|
1006
|
+
interpret.remove('t1') // true
|
|
1007
|
+
interpret.destroy()
|
|
1008
|
+
```
|
|
1009
|
+
|
|
1010
|
+
## Tests
|
|
1011
|
+
|
|
1012
|
+
- [`tests/guides.test.ts`](../tests/guides.test.ts) — the `## Surface` ↔ `src/core` bijection (value and type exports), each behavioral interface ↔ its implementing class method bijection, and the equality gate: every `Summary` cell against its declaration's description paragraph, the titled `Interpret text against an added template` fence against the `@example` block of that title (pinned so the titled pair cannot be retired silently), and the README pitch against this guide's tagline. It also runs the flagship fences and asserts the values their comments claim.
|
|
1013
|
+
- [`tests/src/core/Interpret.test.ts`](../tests/src/core/Interpret.test.ts) — the orchestrator: the fixed pipeline and its per-stage records, the `NO_TEMPLATE` and `LOW_CONFIDENCE` incomplete results, a thrown stage marked on its record and on `failures`, the replay digest, the emitter surface, and teardown.
|
|
1014
|
+
- [`tests/src/core/InterpretContext.test.ts`](../tests/src/core/InterpretContext.test.ts) — the capped ring buffer, the flattened entity read carry-over consults, `clear` against `destroy`, and the emitted events.
|
|
1015
|
+
- [`tests/src/core/Narrator.test.ts`](../tests/src/core/Narrator.test.ts) — every lookup total against an adversarial key, the documented fallback of each primitive, and the composed `describe` and `narrate` renderings.
|
|
1016
|
+
- [`tests/src/core/factories.test.ts`](../tests/src/core/factories.test.ts) — each factory returns a working entity, and honors the options it declares.
|
|
1017
|
+
- [`tests/src/core/helpers.test.ts`](../tests/src/core/helpers.test.ts) — the pure leaves: escaping, copy-on-write field writes and their prototype-pollution refusal, replacement and whitespace collapse, tokenizing, numeric mining, entity assignment, intent classification, similarity and alias matching, canonicalization and digesting, template scoring and matching, expression variables and resolution, and subject rendering.
|
|
1018
|
+
- [`tests/src/core/parsers.test.ts`](../tests/src/core/parsers.test.ts) — `parseTemplate` returns a template, or `undefined` on invalid JSON and on a shape that fails `isTemplate`.
|
|
1019
|
+
- [`tests/src/core/validators.test.ts`](../tests/src/core/validators.test.ts) — every guard stays total against junk, cycles, and hostile prototypes, with the exact posture for an input record and the open posture for a result record.
|
|
1020
|
+
- [`tests/src/core/stages/Normalizer.test.ts`](../tests/src/core/stages/Normalizer.test.ts) — the substitution order, the recorded changes, and the final whitespace collapse.
|
|
1021
|
+
- [`tests/src/core/stages/Extractor.test.ts`](../tests/src/core/stages/Extractor.test.ts) — intent classification against caller vocabularies, and numeric mining, with no template in sight.
|
|
1022
|
+
- [`tests/src/core/stages/Clarifier.test.ts`](../tests/src/core/stages/Clarifier.test.ts) — resolution order across fresh entities, same-domain carry-over, defaults, and dependency-ordered computed fields, plus the ambiguity every unresolved required mapping raises.
|
|
1023
|
+
- [`tests/src/core/stages/Formatter.test.ts`](../tests/src/core/stages/Formatter.test.ts) — the clause assembly through the narrator's `prompt.*` lines, and the verb fallback.
|
|
1024
|
+
- [`tests/src/core/stages/Generator.test.ts`](../tests/src/core/stages/Generator.test.ts) — the entity-to-field rule, the single-element unwrap, the mean confidence, and the field audit.
|
|
1025
|
+
- [`tests/src/core/managers/RecordManager.test.ts`](../tests/src/core/managers/RecordManager.test.ts) — the content hash and version rule, the all-or-nothing batch `remove`, the emitted events, and idempotent teardown.
|
|
1026
|
+
- [`tests/src/core/managers/TemplateManager.test.ts`](../tests/src/core/managers/TemplateManager.test.ts) — the template accessors, the record id defaulting to `template.id`, and re-add versioning.
|
|
1027
|
+
- [`tests/src/core/managers/SubjectManager.test.ts`](../tests/src/core/managers/SubjectManager.test.ts) — the minted record identity, the caller override, and the subject accessors.
|
|
1028
|
+
- [`tests/src/core/managers/DefinitionManager.test.ts`](../tests/src/core/managers/DefinitionManager.test.ts) — the definition accessors and the record id defaulting to the definition's own `id`.
|
|
1029
|
+
- [`tests/src/core/integration.test.ts`](../tests/src/core/integration.test.ts) — the forward and reverse directions driven together over a real corpus, through the public API.
|