@ai-matrx/content-ir 0.10.4 → 0.11.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 +46 -0
- package/dist/directives.cjs +386 -0
- package/dist/directives.cjs.map +1 -0
- package/dist/directives.d.cts +294 -0
- package/dist/directives.d.ts +294 -0
- package/dist/directives.js +348 -0
- package/dist/directives.js.map +1 -0
- package/dist/index.cjs +378 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +343 -1
- package/dist/index.js.map +1 -1
- package/package.json +14 -1
|
@@ -0,0 +1,294 @@
|
|
|
1
|
+
import { K as KIND_KEY } from './kind-schema.types-CwncWj9U.cjs';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Kind Directives — the grammar, the shell, and the position law (kernel edition).
|
|
5
|
+
*
|
|
6
|
+
* ONE system (Arman, 2026-08-23): the Matrx Envelope/Directive protocol and the
|
|
7
|
+
* Content IR kind system are one system. A directive is an ordinary kind
|
|
8
|
+
* instance — `{ "__kind": "directive_v1_<class>_<noun>", "items": [...] }` —
|
|
9
|
+
* whose registered shape additionally carries execution semantics on the
|
|
10
|
+
* server. This module is the PURE half, ported verbatim from the aidream source
|
|
11
|
+
* of record (`packages/matrx-graph/matrx_graph/content_ir/directives.py`) so
|
|
12
|
+
* every UI parses the grammar identically. It lives in the KERNEL because a
|
|
13
|
+
* host that can parse a kind must be able to recognise a directive without a
|
|
14
|
+
* second copy of these rules (matrx-frontend carried the only copy until
|
|
15
|
+
* 2026-09-08; Workflow Studio had none and rendered directives as raw text).
|
|
16
|
+
*
|
|
17
|
+
* THE SLUG GRAMMAR — `directive_v<version>_<class>_<noun>`:
|
|
18
|
+
* - `directive_v` is a RESERVED prefix; a hand-authored kind may never claim it.
|
|
19
|
+
* - `<class>` comes from a CLOSED vocabulary, so parsing is unambiguous even
|
|
20
|
+
* though nouns contain underscores: `directive_v1_reference_create_task` is
|
|
21
|
+
* `(reference, "create_task")`.
|
|
22
|
+
* - capability is DERIVED from the class, never stored twice.
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
/** The reserved slug prefix. ANY kind slug starting with this belongs to the Kind Directives protocol. */
|
|
26
|
+
declare const RESERVED_PREFIX: "directive_v";
|
|
27
|
+
/** Current directive grammar version. */
|
|
28
|
+
declare const DIRECTIVE_VERSION: 1;
|
|
29
|
+
/** The full prefix of a v1 directive slug. */
|
|
30
|
+
declare const SLUG_PREFIX: "directive_v1_";
|
|
31
|
+
/** The CLOSED class vocabulary. Closed is what makes the grammar parseable. */
|
|
32
|
+
declare const CLASSES: readonly ["reference", "view", "create", "update", "delete", "action", "validation", "secret"];
|
|
33
|
+
type DirectiveClass = (typeof CLASSES)[number];
|
|
34
|
+
type DirectiveCapability = "pure" | "sensitive" | "side_effect";
|
|
35
|
+
/** class → capability. DERIVED, never stored on a shape. */
|
|
36
|
+
declare const CAPABILITY_BY_CLASS: Readonly<Record<DirectiveClass, DirectiveCapability>>;
|
|
37
|
+
/** The classes that EXECUTE at an agent's output root — a durable side effect. */
|
|
38
|
+
declare const SIDE_EFFECT_CLASSES: ReadonlySet<DirectiveClass>;
|
|
39
|
+
/**
|
|
40
|
+
* The classes that resolve to a LIVE VALUE inside content. STRICT BY CHOICE,
|
|
41
|
+
* mirroring the server: exactly `reference` + `secret`.
|
|
42
|
+
*/
|
|
43
|
+
declare const IN_CONTENT_CLASSES: ReadonlySet<DirectiveClass>;
|
|
44
|
+
/** A parsed directive slug. `slug` round-trips through `buildDirectiveSlug`. */
|
|
45
|
+
interface DirectiveSlug {
|
|
46
|
+
slug: string;
|
|
47
|
+
version: number;
|
|
48
|
+
directiveClass: DirectiveClass;
|
|
49
|
+
noun: string;
|
|
50
|
+
capability: DirectiveCapability;
|
|
51
|
+
/** Executes at an agent's output root (THE position law, half one). */
|
|
52
|
+
executes: boolean;
|
|
53
|
+
/** Resolves to a live value inside content (THE position law, half two). */
|
|
54
|
+
inContent: boolean;
|
|
55
|
+
}
|
|
56
|
+
declare function isDirectiveClass(value: unknown): value is DirectiveClass;
|
|
57
|
+
/**
|
|
58
|
+
* Whether `slug` sits in the reserved Kind Directives namespace. Deliberately
|
|
59
|
+
* broader than {@link parseDirectiveSlug}: a MALFORMED `directive_v…` slug is
|
|
60
|
+
* still reserved, so authoring gates reject it instead of letting a near-miss
|
|
61
|
+
* through as an ordinary kind.
|
|
62
|
+
*/
|
|
63
|
+
declare function isReservedDirectiveSlug(slug: unknown): slug is string;
|
|
64
|
+
/**
|
|
65
|
+
* `("create", "task") → "directive_v1_create_task"`. THROWS on a class outside
|
|
66
|
+
* the closed vocabulary or an ill-formed noun — a slug that cannot be parsed
|
|
67
|
+
* back must never be mintable.
|
|
68
|
+
*/
|
|
69
|
+
declare function buildDirectiveSlug(directiveClass: string, noun: string, version?: number): string;
|
|
70
|
+
/**
|
|
71
|
+
* Parse a directive slug, or `null` when `slug` is not one. A slug that IS in
|
|
72
|
+
* the reserved namespace but does not parse returns `null` too — pair with
|
|
73
|
+
* {@link isReservedDirectiveSlug} to tell "ordinary kind" from "malformed
|
|
74
|
+
* directive"; every such caller treats the malformed case as an ERROR.
|
|
75
|
+
*/
|
|
76
|
+
declare function parseDirectiveSlug(slug: unknown): DirectiveSlug | null;
|
|
77
|
+
declare function capabilityOf(directiveClass: DirectiveClass): DirectiveCapability;
|
|
78
|
+
/** THE position law, half one: only a side-effect class executes at an agent's output root. */
|
|
79
|
+
declare function executesAtOutputRoot(directiveClass: string): boolean;
|
|
80
|
+
/** THE position law, half two: only a pointer or a sensitive value resolves to a live value inside content. */
|
|
81
|
+
declare function resolvesInContent(directiveClass: string): boolean;
|
|
82
|
+
/**
|
|
83
|
+
* The `__kind` of `obj` when it is in the reserved namespace, else null. Reads
|
|
84
|
+
* the RESERVED namespace, not the parsed grammar, so a malformed directive is
|
|
85
|
+
* still recognised as a directive (and rejected downstream with a real message).
|
|
86
|
+
*/
|
|
87
|
+
declare function directiveSlugOf(obj: unknown): string | null;
|
|
88
|
+
/** THE detector — a dict whose `__kind` is in the reserved namespace. */
|
|
89
|
+
declare function isKindDirective(obj: unknown): boolean;
|
|
90
|
+
/**
|
|
91
|
+
* The two-key shell, as it travels on the wire. A TYPE alias, not an interface,
|
|
92
|
+
* so a shell is structurally assignable to `Record<string, unknown>`.
|
|
93
|
+
*/
|
|
94
|
+
type KindDirectiveShell<Item = Record<string, unknown>> = {
|
|
95
|
+
/** The slug. Serialized FIRST — see the module doc. */
|
|
96
|
+
[KIND_KEY]: string;
|
|
97
|
+
items: Item[];
|
|
98
|
+
};
|
|
99
|
+
/**
|
|
100
|
+
* Build the two-key shell with `__kind` FIRST. Never hand-assemble the object
|
|
101
|
+
* literal elsewhere: JS preserves insertion order for string keys, and the
|
|
102
|
+
* first-key rule is what lets the streaming detector type a directive early.
|
|
103
|
+
*/
|
|
104
|
+
declare function buildKindDirective<Item>(slug: string, items: Item[]): KindDirectiveShell<Item>;
|
|
105
|
+
/**
|
|
106
|
+
* Mid-stream recognition: the opening of a document whose FIRST key is a
|
|
107
|
+
* reserved directive slug, before the closing brace has arrived. Used by
|
|
108
|
+
* content splitters so a streaming envelope is typed early.
|
|
109
|
+
*/
|
|
110
|
+
declare function looksLikeDirectiveHead(content: string): boolean;
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Decode a Kind Directive — THE one entry point on every client.
|
|
114
|
+
*
|
|
115
|
+
* `decodeDirective()` recognises the shell (current OR, for stored content
|
|
116
|
+
* only, the retired 4-key one), reads the slug, and derives class + noun. A
|
|
117
|
+
* caller only ever sees a parsed {@link DecodedDirective}; nothing downstream
|
|
118
|
+
* inspects a raw shell again.
|
|
119
|
+
*
|
|
120
|
+
* ITEM VALIDATION IS THE SERVER'S. The registered item models live in aidream
|
|
121
|
+
* (`services/content_ir_directives/registry.py`) and validate on apply; a
|
|
122
|
+
* client-side copy of ~120 item models is exactly the drift the merge exists
|
|
123
|
+
* to kill. The client parses identity, routes, and renders. Mirror of aidream
|
|
124
|
+
* `services/content_ir_directives/decode.py`.
|
|
125
|
+
*/
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* A well-formed-looking directive that cannot be honoured (a malformed slug, or
|
|
129
|
+
* a retired shell that does not map onto the grammar). Never thrown for "this
|
|
130
|
+
* isn't a directive" — that is `null`.
|
|
131
|
+
*/
|
|
132
|
+
declare class DirectiveDecodeError extends Error {
|
|
133
|
+
constructor(message: string);
|
|
134
|
+
}
|
|
135
|
+
interface DecodedDirective {
|
|
136
|
+
/** The parsed slug — class, noun, capability and the position law. */
|
|
137
|
+
readonly parsed: DirectiveSlug;
|
|
138
|
+
readonly slug: string;
|
|
139
|
+
readonly directiveClass: DirectiveClass;
|
|
140
|
+
readonly noun: string;
|
|
141
|
+
readonly items: Record<string, unknown>[];
|
|
142
|
+
/** The two-key shell, normalised — what a confirm POST round-trips. */
|
|
143
|
+
readonly shell: Record<string, unknown>;
|
|
144
|
+
/** True when this arrived in the retired 4-key shell and was translated. */
|
|
145
|
+
readonly legacyShell: boolean;
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* A typed directive, or `null` when `value` is not a directive at all. Throws
|
|
149
|
+
* {@link DirectiveDecodeError} when it IS one but cannot be honoured.
|
|
150
|
+
*/
|
|
151
|
+
declare function decodeDirective(value: unknown): DecodedDirective | null;
|
|
152
|
+
/**
|
|
153
|
+
* The forgiving read used at render seams: `decodeDirective`, but a directive
|
|
154
|
+
* that cannot be honoured comes back as `null` after the reason is handed to
|
|
155
|
+
* `onError`. A render seam must never take a whole message block down over one
|
|
156
|
+
* bad fence — but it must never swallow the reason either.
|
|
157
|
+
*/
|
|
158
|
+
declare function tryDecodeDirective(value: unknown, onError?: (message: string) => void): DecodedDirective | null;
|
|
159
|
+
/** `decodeDirective` over a JSON string or an already-parsed value. Non-JSON text is `null`. */
|
|
160
|
+
declare function tryDecodeDirectiveContent(content: unknown, onError?: (message: string) => void): DecodedDirective | null;
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* THE ONE LEGACY SURFACE of the Kind Directives protocol — read-only.
|
|
164
|
+
*
|
|
165
|
+
* Stored content written before 2026-08-23 carries the retired 4-key shell
|
|
166
|
+
* (`matrx_version` / `kind` / `type` / `items`). This module translates it into
|
|
167
|
+
* the current two-key shell so `decodeDirective` sees one shape, forever. It
|
|
168
|
+
* never emits, never registers a shape, has no fallback branch, and every use
|
|
169
|
+
* is counted so the containment can be measured. Only `decode.ts` may import
|
|
170
|
+
* it (matrx-frontend's `check-legacy-shim-containment` and aidream's
|
|
171
|
+
* `test_legacy_shim_containment.py` enforce the mirror).
|
|
172
|
+
*/
|
|
173
|
+
declare function legacyShellUses(): number;
|
|
174
|
+
declare function resetLegacyShellUses(): void;
|
|
175
|
+
/** True ONLY for a genuine retired-shell directive claim (sentinel + a retired kind token). */
|
|
176
|
+
declare function isLegacyShell(obj: unknown): boolean;
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* THE AUTO-VIEW's naming half: every enrolled noun "instantly has a view" —
|
|
180
|
+
* the prefix rule gives it a renderer, and this gives it a NAME. A shape the
|
|
181
|
+
* client has never heard of must still read as "Create Agent · Agents", never
|
|
182
|
+
* as the raw `agent` token and never as a slug.
|
|
183
|
+
*
|
|
184
|
+
* The catalog (`platform.entity_types` → the server's directive catalog) is the
|
|
185
|
+
* authority for `label` / `family` / `title_column`; a host that mirrors it
|
|
186
|
+
* passes a {@link DirectiveNounCatalog}. Without one — or for a noun the
|
|
187
|
+
* catalog does not carry (a Kind Action like `plan_tree`) — the name degrades
|
|
188
|
+
* to a title-cased token: legible, honestly derived, never blank.
|
|
189
|
+
*/
|
|
190
|
+
|
|
191
|
+
interface DirectiveNounEntry {
|
|
192
|
+
/** The noun's human name — "Agent", "Plan tree". */
|
|
193
|
+
label?: string | null;
|
|
194
|
+
/** The catalog family ("Agents"). */
|
|
195
|
+
family?: string | null;
|
|
196
|
+
/** Which field of a row names it (`name`, `title`, …). */
|
|
197
|
+
titleColumn?: string | null;
|
|
198
|
+
}
|
|
199
|
+
/** A host-supplied lookup over the mirrored catalog. `undefined` = not carried. */
|
|
200
|
+
type DirectiveNounCatalog = (noun: string) => DirectiveNounEntry | undefined;
|
|
201
|
+
interface DirectiveDisplay {
|
|
202
|
+
/** The noun's human name — "Agent", "Plan tree". */
|
|
203
|
+
noun: string;
|
|
204
|
+
/** The catalog family ("Agents"), or "" when the catalog has none. */
|
|
205
|
+
family: string;
|
|
206
|
+
/** What this directive DOES, in the user's words — "Create", "Reference". */
|
|
207
|
+
action: string;
|
|
208
|
+
/** One line: "Create Agent". */
|
|
209
|
+
title: string;
|
|
210
|
+
}
|
|
211
|
+
/** `plan_node_patch` → `Plan node patch`. The honest last resort. */
|
|
212
|
+
declare function titleCaseToken(token: string): string;
|
|
213
|
+
/**
|
|
214
|
+
* How a class reads to a human. `action` is deliberately "Run": a Kind Action
|
|
215
|
+
* is a named procedure, and "Action Plan tree" reads like a noun phrase where a
|
|
216
|
+
* verb belongs. Mirrored by the server's kind-catalog label.
|
|
217
|
+
*/
|
|
218
|
+
declare const ACTION_BY_CLASS: Readonly<Record<DirectiveClass, string>>;
|
|
219
|
+
declare function nounLabel(noun: string, catalog?: DirectiveNounCatalog): string;
|
|
220
|
+
declare function nounFamily(noun: string, catalog?: DirectiveNounCatalog): string;
|
|
221
|
+
declare function nounTitleColumn(noun: string, catalog?: DirectiveNounCatalog): string | null;
|
|
222
|
+
/** Everything a generic card needs to name a directive it cannot render. */
|
|
223
|
+
declare function directiveDisplay(directiveClass: DirectiveClass, noun: string, catalog?: DirectiveNounCatalog): DirectiveDisplay;
|
|
224
|
+
|
|
225
|
+
/**
|
|
226
|
+
* Naming and summarising ONE item of a directive, for the compact card.
|
|
227
|
+
*
|
|
228
|
+
* THE RULE: a user is never asked to approve a write they cannot identify. The
|
|
229
|
+
* card must say WHAT is about to be created/updated/deleted, derived from
|
|
230
|
+
* authority rather than guesswork, in this order:
|
|
231
|
+
* 1. the noun's catalog `title_column` — the server's own answer to "what
|
|
232
|
+
* names a row of this table";
|
|
233
|
+
* 2. the conventional identity fields, in a fixed order;
|
|
234
|
+
* 3. the honest last resort — "Item 2 of 3", never a blank chip and never a
|
|
235
|
+
* slug pretending to be a name.
|
|
236
|
+
*
|
|
237
|
+
* Facts are scalars ONLY. Nesting goes to the panel, never into the row.
|
|
238
|
+
*/
|
|
239
|
+
/**
|
|
240
|
+
* What to call this item. `titleColumn` is the noun's catalog title column
|
|
241
|
+
* (consulted first); null when the catalog carries none.
|
|
242
|
+
*/
|
|
243
|
+
declare function itemTitle(item: Record<string, unknown>, titleColumn: string | null, index: number, total: number): string;
|
|
244
|
+
/** A one-line subtitle when the item carries prose about itself. */
|
|
245
|
+
declare function itemSubtitle(item: Record<string, unknown>): string | null;
|
|
246
|
+
interface ItemFact {
|
|
247
|
+
key: string;
|
|
248
|
+
label: string;
|
|
249
|
+
value: string;
|
|
250
|
+
}
|
|
251
|
+
/**
|
|
252
|
+
* Up to `limit` scalar facts about the item — counts for collections, values
|
|
253
|
+
* for scalars. Nested objects are deliberately absent (they belong in the
|
|
254
|
+
* panel), and so is anything already carried by the title/subtitle.
|
|
255
|
+
*/
|
|
256
|
+
declare function itemFacts(item: Record<string, unknown>, limit?: number): ItemFact[];
|
|
257
|
+
|
|
258
|
+
/**
|
|
259
|
+
* THE DIRECTIVE⇄KIND SEAM, client side.
|
|
260
|
+
*
|
|
261
|
+
* Arman, 2026-08-26: the envelope / Matrx-Actions system and the Shape (kind)
|
|
262
|
+
* system are ONE system with several methods inside it. They meet at the ITEM.
|
|
263
|
+
* A directive is a CONTAINER; its items are the payload, and when the server's
|
|
264
|
+
* item model is already a `KindModel`, that payload IS a registered kind
|
|
265
|
+
* instance — so the kind system already knows how to validate, render and copy
|
|
266
|
+
* it.
|
|
267
|
+
*
|
|
268
|
+
* The seam is SERVER-DERIVED (`ShapeSpec.item_kind`). Since 2026-09-08 the ONE
|
|
269
|
+
* kind endpoint publishes every directive shape as a KindDescriptor whose
|
|
270
|
+
* `items` EDGE names the item kind, so a client reads it from the same
|
|
271
|
+
* catalog it already holds — {@link directiveItemKindFromEdges}. A host that
|
|
272
|
+
* mirrors the directive catalog manifest instead passes its map as a
|
|
273
|
+
* {@link DirectiveItemKindLookup}. `null` is HONEST, never a gap-filler.
|
|
274
|
+
*/
|
|
275
|
+
/** A host-supplied lookup: slug → the kind ONE item is, or null. */
|
|
276
|
+
type DirectiveItemKindLookup = (slug: string) => string | null;
|
|
277
|
+
/** The `items` edge of a directive KindDescriptor, as the kind catalog serves it. */
|
|
278
|
+
interface DirectiveItemsEdge {
|
|
279
|
+
field_name?: string;
|
|
280
|
+
fieldPath?: string;
|
|
281
|
+
child_kind?: string;
|
|
282
|
+
childKind?: string;
|
|
283
|
+
}
|
|
284
|
+
/** The item kind named by a directive descriptor's `items` edge, or null. */
|
|
285
|
+
declare function directiveItemKindFromEdges(edges: readonly DirectiveItemsEdge[] | null | undefined): string | null;
|
|
286
|
+
/**
|
|
287
|
+
* The item, presented the way the kind pipeline expects it: `__kind` FIRST so a
|
|
288
|
+
* consumer types the object from its own first key. `__kind` is ADDED, never
|
|
289
|
+
* overwritten: an item that already carries its marker keeps the value it was
|
|
290
|
+
* emitted with. Null when no kind is known — the caller owns the generic floor.
|
|
291
|
+
*/
|
|
292
|
+
declare function asKindInstance(item: Record<string, unknown>, kind: string | null): Record<string, unknown> | null;
|
|
293
|
+
|
|
294
|
+
export { ACTION_BY_CLASS, CAPABILITY_BY_CLASS, CLASSES, DIRECTIVE_VERSION, type DecodedDirective, type DirectiveCapability, type DirectiveClass, DirectiveDecodeError, type DirectiveDisplay, type DirectiveItemKindLookup, type DirectiveItemsEdge, type DirectiveNounCatalog, type DirectiveNounEntry, type DirectiveSlug, IN_CONTENT_CLASSES, type ItemFact, KIND_KEY, type KindDirectiveShell, RESERVED_PREFIX, SIDE_EFFECT_CLASSES, SLUG_PREFIX, asKindInstance, buildDirectiveSlug, buildKindDirective, capabilityOf, decodeDirective, directiveDisplay, directiveItemKindFromEdges, directiveSlugOf, executesAtOutputRoot, isDirectiveClass, isKindDirective, isLegacyShell, isReservedDirectiveSlug, itemFacts, itemSubtitle, itemTitle, legacyShellUses, looksLikeDirectiveHead, nounFamily, nounLabel, nounTitleColumn, parseDirectiveSlug, resetLegacyShellUses, resolvesInContent, titleCaseToken, tryDecodeDirective, tryDecodeDirectiveContent };
|
|
@@ -0,0 +1,294 @@
|
|
|
1
|
+
import { K as KIND_KEY } from './kind-schema.types-CwncWj9U.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Kind Directives — the grammar, the shell, and the position law (kernel edition).
|
|
5
|
+
*
|
|
6
|
+
* ONE system (Arman, 2026-08-23): the Matrx Envelope/Directive protocol and the
|
|
7
|
+
* Content IR kind system are one system. A directive is an ordinary kind
|
|
8
|
+
* instance — `{ "__kind": "directive_v1_<class>_<noun>", "items": [...] }` —
|
|
9
|
+
* whose registered shape additionally carries execution semantics on the
|
|
10
|
+
* server. This module is the PURE half, ported verbatim from the aidream source
|
|
11
|
+
* of record (`packages/matrx-graph/matrx_graph/content_ir/directives.py`) so
|
|
12
|
+
* every UI parses the grammar identically. It lives in the KERNEL because a
|
|
13
|
+
* host that can parse a kind must be able to recognise a directive without a
|
|
14
|
+
* second copy of these rules (matrx-frontend carried the only copy until
|
|
15
|
+
* 2026-09-08; Workflow Studio had none and rendered directives as raw text).
|
|
16
|
+
*
|
|
17
|
+
* THE SLUG GRAMMAR — `directive_v<version>_<class>_<noun>`:
|
|
18
|
+
* - `directive_v` is a RESERVED prefix; a hand-authored kind may never claim it.
|
|
19
|
+
* - `<class>` comes from a CLOSED vocabulary, so parsing is unambiguous even
|
|
20
|
+
* though nouns contain underscores: `directive_v1_reference_create_task` is
|
|
21
|
+
* `(reference, "create_task")`.
|
|
22
|
+
* - capability is DERIVED from the class, never stored twice.
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
/** The reserved slug prefix. ANY kind slug starting with this belongs to the Kind Directives protocol. */
|
|
26
|
+
declare const RESERVED_PREFIX: "directive_v";
|
|
27
|
+
/** Current directive grammar version. */
|
|
28
|
+
declare const DIRECTIVE_VERSION: 1;
|
|
29
|
+
/** The full prefix of a v1 directive slug. */
|
|
30
|
+
declare const SLUG_PREFIX: "directive_v1_";
|
|
31
|
+
/** The CLOSED class vocabulary. Closed is what makes the grammar parseable. */
|
|
32
|
+
declare const CLASSES: readonly ["reference", "view", "create", "update", "delete", "action", "validation", "secret"];
|
|
33
|
+
type DirectiveClass = (typeof CLASSES)[number];
|
|
34
|
+
type DirectiveCapability = "pure" | "sensitive" | "side_effect";
|
|
35
|
+
/** class → capability. DERIVED, never stored on a shape. */
|
|
36
|
+
declare const CAPABILITY_BY_CLASS: Readonly<Record<DirectiveClass, DirectiveCapability>>;
|
|
37
|
+
/** The classes that EXECUTE at an agent's output root — a durable side effect. */
|
|
38
|
+
declare const SIDE_EFFECT_CLASSES: ReadonlySet<DirectiveClass>;
|
|
39
|
+
/**
|
|
40
|
+
* The classes that resolve to a LIVE VALUE inside content. STRICT BY CHOICE,
|
|
41
|
+
* mirroring the server: exactly `reference` + `secret`.
|
|
42
|
+
*/
|
|
43
|
+
declare const IN_CONTENT_CLASSES: ReadonlySet<DirectiveClass>;
|
|
44
|
+
/** A parsed directive slug. `slug` round-trips through `buildDirectiveSlug`. */
|
|
45
|
+
interface DirectiveSlug {
|
|
46
|
+
slug: string;
|
|
47
|
+
version: number;
|
|
48
|
+
directiveClass: DirectiveClass;
|
|
49
|
+
noun: string;
|
|
50
|
+
capability: DirectiveCapability;
|
|
51
|
+
/** Executes at an agent's output root (THE position law, half one). */
|
|
52
|
+
executes: boolean;
|
|
53
|
+
/** Resolves to a live value inside content (THE position law, half two). */
|
|
54
|
+
inContent: boolean;
|
|
55
|
+
}
|
|
56
|
+
declare function isDirectiveClass(value: unknown): value is DirectiveClass;
|
|
57
|
+
/**
|
|
58
|
+
* Whether `slug` sits in the reserved Kind Directives namespace. Deliberately
|
|
59
|
+
* broader than {@link parseDirectiveSlug}: a MALFORMED `directive_v…` slug is
|
|
60
|
+
* still reserved, so authoring gates reject it instead of letting a near-miss
|
|
61
|
+
* through as an ordinary kind.
|
|
62
|
+
*/
|
|
63
|
+
declare function isReservedDirectiveSlug(slug: unknown): slug is string;
|
|
64
|
+
/**
|
|
65
|
+
* `("create", "task") → "directive_v1_create_task"`. THROWS on a class outside
|
|
66
|
+
* the closed vocabulary or an ill-formed noun — a slug that cannot be parsed
|
|
67
|
+
* back must never be mintable.
|
|
68
|
+
*/
|
|
69
|
+
declare function buildDirectiveSlug(directiveClass: string, noun: string, version?: number): string;
|
|
70
|
+
/**
|
|
71
|
+
* Parse a directive slug, or `null` when `slug` is not one. A slug that IS in
|
|
72
|
+
* the reserved namespace but does not parse returns `null` too — pair with
|
|
73
|
+
* {@link isReservedDirectiveSlug} to tell "ordinary kind" from "malformed
|
|
74
|
+
* directive"; every such caller treats the malformed case as an ERROR.
|
|
75
|
+
*/
|
|
76
|
+
declare function parseDirectiveSlug(slug: unknown): DirectiveSlug | null;
|
|
77
|
+
declare function capabilityOf(directiveClass: DirectiveClass): DirectiveCapability;
|
|
78
|
+
/** THE position law, half one: only a side-effect class executes at an agent's output root. */
|
|
79
|
+
declare function executesAtOutputRoot(directiveClass: string): boolean;
|
|
80
|
+
/** THE position law, half two: only a pointer or a sensitive value resolves to a live value inside content. */
|
|
81
|
+
declare function resolvesInContent(directiveClass: string): boolean;
|
|
82
|
+
/**
|
|
83
|
+
* The `__kind` of `obj` when it is in the reserved namespace, else null. Reads
|
|
84
|
+
* the RESERVED namespace, not the parsed grammar, so a malformed directive is
|
|
85
|
+
* still recognised as a directive (and rejected downstream with a real message).
|
|
86
|
+
*/
|
|
87
|
+
declare function directiveSlugOf(obj: unknown): string | null;
|
|
88
|
+
/** THE detector — a dict whose `__kind` is in the reserved namespace. */
|
|
89
|
+
declare function isKindDirective(obj: unknown): boolean;
|
|
90
|
+
/**
|
|
91
|
+
* The two-key shell, as it travels on the wire. A TYPE alias, not an interface,
|
|
92
|
+
* so a shell is structurally assignable to `Record<string, unknown>`.
|
|
93
|
+
*/
|
|
94
|
+
type KindDirectiveShell<Item = Record<string, unknown>> = {
|
|
95
|
+
/** The slug. Serialized FIRST — see the module doc. */
|
|
96
|
+
[KIND_KEY]: string;
|
|
97
|
+
items: Item[];
|
|
98
|
+
};
|
|
99
|
+
/**
|
|
100
|
+
* Build the two-key shell with `__kind` FIRST. Never hand-assemble the object
|
|
101
|
+
* literal elsewhere: JS preserves insertion order for string keys, and the
|
|
102
|
+
* first-key rule is what lets the streaming detector type a directive early.
|
|
103
|
+
*/
|
|
104
|
+
declare function buildKindDirective<Item>(slug: string, items: Item[]): KindDirectiveShell<Item>;
|
|
105
|
+
/**
|
|
106
|
+
* Mid-stream recognition: the opening of a document whose FIRST key is a
|
|
107
|
+
* reserved directive slug, before the closing brace has arrived. Used by
|
|
108
|
+
* content splitters so a streaming envelope is typed early.
|
|
109
|
+
*/
|
|
110
|
+
declare function looksLikeDirectiveHead(content: string): boolean;
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Decode a Kind Directive — THE one entry point on every client.
|
|
114
|
+
*
|
|
115
|
+
* `decodeDirective()` recognises the shell (current OR, for stored content
|
|
116
|
+
* only, the retired 4-key one), reads the slug, and derives class + noun. A
|
|
117
|
+
* caller only ever sees a parsed {@link DecodedDirective}; nothing downstream
|
|
118
|
+
* inspects a raw shell again.
|
|
119
|
+
*
|
|
120
|
+
* ITEM VALIDATION IS THE SERVER'S. The registered item models live in aidream
|
|
121
|
+
* (`services/content_ir_directives/registry.py`) and validate on apply; a
|
|
122
|
+
* client-side copy of ~120 item models is exactly the drift the merge exists
|
|
123
|
+
* to kill. The client parses identity, routes, and renders. Mirror of aidream
|
|
124
|
+
* `services/content_ir_directives/decode.py`.
|
|
125
|
+
*/
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* A well-formed-looking directive that cannot be honoured (a malformed slug, or
|
|
129
|
+
* a retired shell that does not map onto the grammar). Never thrown for "this
|
|
130
|
+
* isn't a directive" — that is `null`.
|
|
131
|
+
*/
|
|
132
|
+
declare class DirectiveDecodeError extends Error {
|
|
133
|
+
constructor(message: string);
|
|
134
|
+
}
|
|
135
|
+
interface DecodedDirective {
|
|
136
|
+
/** The parsed slug — class, noun, capability and the position law. */
|
|
137
|
+
readonly parsed: DirectiveSlug;
|
|
138
|
+
readonly slug: string;
|
|
139
|
+
readonly directiveClass: DirectiveClass;
|
|
140
|
+
readonly noun: string;
|
|
141
|
+
readonly items: Record<string, unknown>[];
|
|
142
|
+
/** The two-key shell, normalised — what a confirm POST round-trips. */
|
|
143
|
+
readonly shell: Record<string, unknown>;
|
|
144
|
+
/** True when this arrived in the retired 4-key shell and was translated. */
|
|
145
|
+
readonly legacyShell: boolean;
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* A typed directive, or `null` when `value` is not a directive at all. Throws
|
|
149
|
+
* {@link DirectiveDecodeError} when it IS one but cannot be honoured.
|
|
150
|
+
*/
|
|
151
|
+
declare function decodeDirective(value: unknown): DecodedDirective | null;
|
|
152
|
+
/**
|
|
153
|
+
* The forgiving read used at render seams: `decodeDirective`, but a directive
|
|
154
|
+
* that cannot be honoured comes back as `null` after the reason is handed to
|
|
155
|
+
* `onError`. A render seam must never take a whole message block down over one
|
|
156
|
+
* bad fence — but it must never swallow the reason either.
|
|
157
|
+
*/
|
|
158
|
+
declare function tryDecodeDirective(value: unknown, onError?: (message: string) => void): DecodedDirective | null;
|
|
159
|
+
/** `decodeDirective` over a JSON string or an already-parsed value. Non-JSON text is `null`. */
|
|
160
|
+
declare function tryDecodeDirectiveContent(content: unknown, onError?: (message: string) => void): DecodedDirective | null;
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* THE ONE LEGACY SURFACE of the Kind Directives protocol — read-only.
|
|
164
|
+
*
|
|
165
|
+
* Stored content written before 2026-08-23 carries the retired 4-key shell
|
|
166
|
+
* (`matrx_version` / `kind` / `type` / `items`). This module translates it into
|
|
167
|
+
* the current two-key shell so `decodeDirective` sees one shape, forever. It
|
|
168
|
+
* never emits, never registers a shape, has no fallback branch, and every use
|
|
169
|
+
* is counted so the containment can be measured. Only `decode.ts` may import
|
|
170
|
+
* it (matrx-frontend's `check-legacy-shim-containment` and aidream's
|
|
171
|
+
* `test_legacy_shim_containment.py` enforce the mirror).
|
|
172
|
+
*/
|
|
173
|
+
declare function legacyShellUses(): number;
|
|
174
|
+
declare function resetLegacyShellUses(): void;
|
|
175
|
+
/** True ONLY for a genuine retired-shell directive claim (sentinel + a retired kind token). */
|
|
176
|
+
declare function isLegacyShell(obj: unknown): boolean;
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* THE AUTO-VIEW's naming half: every enrolled noun "instantly has a view" —
|
|
180
|
+
* the prefix rule gives it a renderer, and this gives it a NAME. A shape the
|
|
181
|
+
* client has never heard of must still read as "Create Agent · Agents", never
|
|
182
|
+
* as the raw `agent` token and never as a slug.
|
|
183
|
+
*
|
|
184
|
+
* The catalog (`platform.entity_types` → the server's directive catalog) is the
|
|
185
|
+
* authority for `label` / `family` / `title_column`; a host that mirrors it
|
|
186
|
+
* passes a {@link DirectiveNounCatalog}. Without one — or for a noun the
|
|
187
|
+
* catalog does not carry (a Kind Action like `plan_tree`) — the name degrades
|
|
188
|
+
* to a title-cased token: legible, honestly derived, never blank.
|
|
189
|
+
*/
|
|
190
|
+
|
|
191
|
+
interface DirectiveNounEntry {
|
|
192
|
+
/** The noun's human name — "Agent", "Plan tree". */
|
|
193
|
+
label?: string | null;
|
|
194
|
+
/** The catalog family ("Agents"). */
|
|
195
|
+
family?: string | null;
|
|
196
|
+
/** Which field of a row names it (`name`, `title`, …). */
|
|
197
|
+
titleColumn?: string | null;
|
|
198
|
+
}
|
|
199
|
+
/** A host-supplied lookup over the mirrored catalog. `undefined` = not carried. */
|
|
200
|
+
type DirectiveNounCatalog = (noun: string) => DirectiveNounEntry | undefined;
|
|
201
|
+
interface DirectiveDisplay {
|
|
202
|
+
/** The noun's human name — "Agent", "Plan tree". */
|
|
203
|
+
noun: string;
|
|
204
|
+
/** The catalog family ("Agents"), or "" when the catalog has none. */
|
|
205
|
+
family: string;
|
|
206
|
+
/** What this directive DOES, in the user's words — "Create", "Reference". */
|
|
207
|
+
action: string;
|
|
208
|
+
/** One line: "Create Agent". */
|
|
209
|
+
title: string;
|
|
210
|
+
}
|
|
211
|
+
/** `plan_node_patch` → `Plan node patch`. The honest last resort. */
|
|
212
|
+
declare function titleCaseToken(token: string): string;
|
|
213
|
+
/**
|
|
214
|
+
* How a class reads to a human. `action` is deliberately "Run": a Kind Action
|
|
215
|
+
* is a named procedure, and "Action Plan tree" reads like a noun phrase where a
|
|
216
|
+
* verb belongs. Mirrored by the server's kind-catalog label.
|
|
217
|
+
*/
|
|
218
|
+
declare const ACTION_BY_CLASS: Readonly<Record<DirectiveClass, string>>;
|
|
219
|
+
declare function nounLabel(noun: string, catalog?: DirectiveNounCatalog): string;
|
|
220
|
+
declare function nounFamily(noun: string, catalog?: DirectiveNounCatalog): string;
|
|
221
|
+
declare function nounTitleColumn(noun: string, catalog?: DirectiveNounCatalog): string | null;
|
|
222
|
+
/** Everything a generic card needs to name a directive it cannot render. */
|
|
223
|
+
declare function directiveDisplay(directiveClass: DirectiveClass, noun: string, catalog?: DirectiveNounCatalog): DirectiveDisplay;
|
|
224
|
+
|
|
225
|
+
/**
|
|
226
|
+
* Naming and summarising ONE item of a directive, for the compact card.
|
|
227
|
+
*
|
|
228
|
+
* THE RULE: a user is never asked to approve a write they cannot identify. The
|
|
229
|
+
* card must say WHAT is about to be created/updated/deleted, derived from
|
|
230
|
+
* authority rather than guesswork, in this order:
|
|
231
|
+
* 1. the noun's catalog `title_column` — the server's own answer to "what
|
|
232
|
+
* names a row of this table";
|
|
233
|
+
* 2. the conventional identity fields, in a fixed order;
|
|
234
|
+
* 3. the honest last resort — "Item 2 of 3", never a blank chip and never a
|
|
235
|
+
* slug pretending to be a name.
|
|
236
|
+
*
|
|
237
|
+
* Facts are scalars ONLY. Nesting goes to the panel, never into the row.
|
|
238
|
+
*/
|
|
239
|
+
/**
|
|
240
|
+
* What to call this item. `titleColumn` is the noun's catalog title column
|
|
241
|
+
* (consulted first); null when the catalog carries none.
|
|
242
|
+
*/
|
|
243
|
+
declare function itemTitle(item: Record<string, unknown>, titleColumn: string | null, index: number, total: number): string;
|
|
244
|
+
/** A one-line subtitle when the item carries prose about itself. */
|
|
245
|
+
declare function itemSubtitle(item: Record<string, unknown>): string | null;
|
|
246
|
+
interface ItemFact {
|
|
247
|
+
key: string;
|
|
248
|
+
label: string;
|
|
249
|
+
value: string;
|
|
250
|
+
}
|
|
251
|
+
/**
|
|
252
|
+
* Up to `limit` scalar facts about the item — counts for collections, values
|
|
253
|
+
* for scalars. Nested objects are deliberately absent (they belong in the
|
|
254
|
+
* panel), and so is anything already carried by the title/subtitle.
|
|
255
|
+
*/
|
|
256
|
+
declare function itemFacts(item: Record<string, unknown>, limit?: number): ItemFact[];
|
|
257
|
+
|
|
258
|
+
/**
|
|
259
|
+
* THE DIRECTIVE⇄KIND SEAM, client side.
|
|
260
|
+
*
|
|
261
|
+
* Arman, 2026-08-26: the envelope / Matrx-Actions system and the Shape (kind)
|
|
262
|
+
* system are ONE system with several methods inside it. They meet at the ITEM.
|
|
263
|
+
* A directive is a CONTAINER; its items are the payload, and when the server's
|
|
264
|
+
* item model is already a `KindModel`, that payload IS a registered kind
|
|
265
|
+
* instance — so the kind system already knows how to validate, render and copy
|
|
266
|
+
* it.
|
|
267
|
+
*
|
|
268
|
+
* The seam is SERVER-DERIVED (`ShapeSpec.item_kind`). Since 2026-09-08 the ONE
|
|
269
|
+
* kind endpoint publishes every directive shape as a KindDescriptor whose
|
|
270
|
+
* `items` EDGE names the item kind, so a client reads it from the same
|
|
271
|
+
* catalog it already holds — {@link directiveItemKindFromEdges}. A host that
|
|
272
|
+
* mirrors the directive catalog manifest instead passes its map as a
|
|
273
|
+
* {@link DirectiveItemKindLookup}. `null` is HONEST, never a gap-filler.
|
|
274
|
+
*/
|
|
275
|
+
/** A host-supplied lookup: slug → the kind ONE item is, or null. */
|
|
276
|
+
type DirectiveItemKindLookup = (slug: string) => string | null;
|
|
277
|
+
/** The `items` edge of a directive KindDescriptor, as the kind catalog serves it. */
|
|
278
|
+
interface DirectiveItemsEdge {
|
|
279
|
+
field_name?: string;
|
|
280
|
+
fieldPath?: string;
|
|
281
|
+
child_kind?: string;
|
|
282
|
+
childKind?: string;
|
|
283
|
+
}
|
|
284
|
+
/** The item kind named by a directive descriptor's `items` edge, or null. */
|
|
285
|
+
declare function directiveItemKindFromEdges(edges: readonly DirectiveItemsEdge[] | null | undefined): string | null;
|
|
286
|
+
/**
|
|
287
|
+
* The item, presented the way the kind pipeline expects it: `__kind` FIRST so a
|
|
288
|
+
* consumer types the object from its own first key. `__kind` is ADDED, never
|
|
289
|
+
* overwritten: an item that already carries its marker keeps the value it was
|
|
290
|
+
* emitted with. Null when no kind is known — the caller owns the generic floor.
|
|
291
|
+
*/
|
|
292
|
+
declare function asKindInstance(item: Record<string, unknown>, kind: string | null): Record<string, unknown> | null;
|
|
293
|
+
|
|
294
|
+
export { ACTION_BY_CLASS, CAPABILITY_BY_CLASS, CLASSES, DIRECTIVE_VERSION, type DecodedDirective, type DirectiveCapability, type DirectiveClass, DirectiveDecodeError, type DirectiveDisplay, type DirectiveItemKindLookup, type DirectiveItemsEdge, type DirectiveNounCatalog, type DirectiveNounEntry, type DirectiveSlug, IN_CONTENT_CLASSES, type ItemFact, KIND_KEY, type KindDirectiveShell, RESERVED_PREFIX, SIDE_EFFECT_CLASSES, SLUG_PREFIX, asKindInstance, buildDirectiveSlug, buildKindDirective, capabilityOf, decodeDirective, directiveDisplay, directiveItemKindFromEdges, directiveSlugOf, executesAtOutputRoot, isDirectiveClass, isKindDirective, isLegacyShell, isReservedDirectiveSlug, itemFacts, itemSubtitle, itemTitle, legacyShellUses, looksLikeDirectiveHead, nounFamily, nounLabel, nounTitleColumn, parseDirectiveSlug, resetLegacyShellUses, resolvesInContent, titleCaseToken, tryDecodeDirective, tryDecodeDirectiveContent };
|