@fastpaca/cria 0.0.1 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +93 -106
- package/dist/ai-sdk/index.d.ts +43 -0
- package/dist/ai-sdk/index.d.ts.map +1 -0
- package/dist/ai-sdk/index.js +303 -0
- package/dist/ai-sdk/index.js.map +1 -0
- package/dist/ai-sdk/index.test.d.ts +2 -0
- package/dist/ai-sdk/index.test.d.ts.map +1 -0
- package/dist/ai-sdk/index.test.js +101 -0
- package/dist/ai-sdk/index.test.js.map +1 -0
- package/dist/anthropic/index.d.ts +74 -0
- package/dist/anthropic/index.d.ts.map +1 -0
- package/dist/anthropic/index.js +238 -0
- package/dist/anthropic/index.js.map +1 -0
- package/dist/anthropic/index.test.d.ts +2 -0
- package/dist/anthropic/index.test.d.ts.map +1 -0
- package/dist/anthropic/index.test.js +115 -0
- package/dist/anthropic/index.test.js.map +1 -0
- package/dist/components/additional.test.d.ts +2 -0
- package/dist/components/additional.test.d.ts.map +1 -0
- package/dist/components/additional.test.js +31 -0
- package/dist/components/additional.test.js.map +1 -0
- package/dist/components/index.d.ts +148 -0
- package/dist/components/index.d.ts.map +1 -0
- package/dist/components/index.js +184 -0
- package/dist/components/index.js.map +1 -0
- package/dist/components/summary.d.ts +91 -0
- package/dist/components/summary.d.ts.map +1 -0
- package/dist/components/summary.js +118 -0
- package/dist/components/summary.js.map +1 -0
- package/dist/components/summary.test.d.ts +2 -0
- package/dist/components/summary.test.d.ts.map +1 -0
- package/dist/components/summary.test.js +101 -0
- package/dist/components/summary.test.js.map +1 -0
- package/dist/components/vector-search.d.ts +70 -0
- package/dist/components/vector-search.d.ts.map +1 -0
- package/dist/components/vector-search.js +110 -0
- package/dist/components/vector-search.js.map +1 -0
- package/dist/components/vector-search.test.d.ts +2 -0
- package/dist/components/vector-search.test.d.ts.map +1 -0
- package/dist/components/vector-search.test.js +113 -0
- package/dist/components/vector-search.test.js.map +1 -0
- package/dist/index.d.ts +12 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +9 -5
- package/dist/index.js.map +1 -1
- package/dist/instrumentation/otel.d.ts +19 -0
- package/dist/instrumentation/otel.d.ts.map +1 -0
- package/dist/instrumentation/otel.js +102 -0
- package/dist/instrumentation/otel.js.map +1 -0
- package/dist/instrumentation/otel.test.d.ts +2 -0
- package/dist/instrumentation/otel.test.d.ts.map +1 -0
- package/dist/instrumentation/otel.test.js +116 -0
- package/dist/instrumentation/otel.test.js.map +1 -0
- package/dist/jsx-dev-runtime.d.ts +2 -0
- package/dist/jsx-dev-runtime.d.ts.map +1 -0
- package/dist/jsx-dev-runtime.js +2 -0
- package/dist/jsx-dev-runtime.js.map +1 -0
- package/dist/jsx-runtime.d.ts +30 -8
- package/dist/jsx-runtime.d.ts.map +1 -1
- package/dist/jsx-runtime.js +13 -10
- package/dist/jsx-runtime.js.map +1 -1
- package/dist/memory/chroma/index.d.ts +59 -0
- package/dist/memory/chroma/index.d.ts.map +1 -0
- package/dist/memory/chroma/index.js +172 -0
- package/dist/memory/chroma/index.js.map +1 -0
- package/dist/memory/index.d.ts +4 -0
- package/dist/memory/index.d.ts.map +1 -0
- package/dist/memory/index.js +2 -0
- package/dist/memory/index.js.map +1 -0
- package/dist/memory/key-value.d.ts +71 -0
- package/dist/memory/key-value.d.ts.map +1 -0
- package/dist/memory/key-value.js +34 -0
- package/dist/memory/key-value.js.map +1 -0
- package/dist/memory/postgres.d.ts +71 -0
- package/dist/memory/postgres.d.ts.map +1 -0
- package/dist/memory/postgres.js +109 -0
- package/dist/memory/postgres.js.map +1 -0
- package/dist/memory/qdrant/index.d.ts +64 -0
- package/dist/memory/qdrant/index.d.ts.map +1 -0
- package/dist/memory/qdrant/index.js +136 -0
- package/dist/memory/qdrant/index.js.map +1 -0
- package/dist/memory/redis.d.ts +70 -0
- package/dist/memory/redis.d.ts.map +1 -0
- package/dist/memory/redis.js +100 -0
- package/dist/memory/redis.js.map +1 -0
- package/dist/memory/vector.d.ts +53 -0
- package/dist/memory/vector.d.ts.map +1 -0
- package/dist/memory/vector.js +2 -0
- package/dist/memory/vector.js.map +1 -0
- package/dist/openai/index.d.ts +46 -0
- package/dist/openai/index.d.ts.map +1 -0
- package/dist/openai/index.js +260 -0
- package/dist/openai/index.js.map +1 -0
- package/dist/openai/index.test.d.ts +2 -0
- package/dist/openai/index.test.d.ts.map +1 -0
- package/dist/openai/index.test.js +204 -0
- package/dist/openai/index.test.js.map +1 -0
- package/dist/providers/index.d.ts +2 -0
- package/dist/providers/index.d.ts.map +1 -0
- package/dist/providers/index.js +2 -0
- package/dist/providers/index.js.map +1 -0
- package/dist/providers/types.d.ts +2 -0
- package/dist/providers/types.d.ts.map +1 -0
- package/dist/providers/types.js +2 -0
- package/dist/providers/types.js.map +1 -0
- package/dist/render.d.ts +44 -40
- package/dist/render.d.ts.map +1 -1
- package/dist/render.js +162 -148
- package/dist/render.js.map +1 -1
- package/dist/render.test.js +146 -28
- package/dist/render.test.js.map +1 -1
- package/dist/renderers/markdown.d.ts +3 -0
- package/dist/renderers/markdown.d.ts.map +1 -0
- package/dist/renderers/markdown.js +43 -0
- package/dist/renderers/markdown.js.map +1 -0
- package/dist/renderers/shared.d.ts +82 -0
- package/dist/renderers/shared.d.ts.map +1 -0
- package/dist/renderers/shared.js +156 -0
- package/dist/renderers/shared.js.map +1 -0
- package/dist/snapshot.d.ts +47 -0
- package/dist/snapshot.d.ts.map +1 -0
- package/dist/snapshot.js +140 -0
- package/dist/snapshot.js.map +1 -0
- package/dist/snapshot.test.d.ts +2 -0
- package/dist/snapshot.test.d.ts.map +1 -0
- package/dist/snapshot.test.js +68 -0
- package/dist/snapshot.test.js.map +1 -0
- package/dist/tokenizers.d.ts +14 -0
- package/dist/tokenizers.d.ts.map +1 -0
- package/dist/tokenizers.js +45 -0
- package/dist/tokenizers.js.map +1 -0
- package/dist/types.d.ts +212 -84
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +109 -0
- package/dist/types.js.map +1 -1
- package/package.json +88 -3
- package/dist/components.d.ts +0 -78
- package/dist/components.d.ts.map +0 -1
- package/dist/components.js +0 -98
- package/dist/components.js.map +0 -1
package/dist/snapshot.js
ADDED
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import { sha256 } from "@noble/hashes/sha256";
|
|
2
|
+
import { bytesToHex, utf8ToBytes } from "@noble/hashes/utils";
|
|
3
|
+
import { markdownRenderer } from "./renderers/markdown";
|
|
4
|
+
/**
|
|
5
|
+
* Create a deterministic snapshot of a fitted prompt tree.
|
|
6
|
+
*
|
|
7
|
+
* - Keeps the tree structure (no flattening) and mirrors PromptElement shape.
|
|
8
|
+
* - Adds per-node token counts (using renderer.tokenString) and stable hashes.
|
|
9
|
+
* - Excludes strategy/context from the snapshot; this is for observability only.
|
|
10
|
+
*/
|
|
11
|
+
export function createSnapshot(element, { tokenizer, renderer = markdownRenderer }) {
|
|
12
|
+
const root = snapshotElement(element, tokenizer, renderer);
|
|
13
|
+
return {
|
|
14
|
+
root,
|
|
15
|
+
totalTokens: root.tokens,
|
|
16
|
+
hash: root.hash,
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
export function createSnapshotHooks({ tokenizer, renderer, onSnapshot, }) {
|
|
20
|
+
return {
|
|
21
|
+
onFitComplete: async (event) => {
|
|
22
|
+
if (!event.result) {
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
const snapshot = createSnapshot(event.result, {
|
|
26
|
+
tokenizer,
|
|
27
|
+
...(renderer && { renderer }),
|
|
28
|
+
});
|
|
29
|
+
await onSnapshot(snapshot);
|
|
30
|
+
},
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
export function diffSnapshots(before, after) {
|
|
34
|
+
const added = [];
|
|
35
|
+
const removed = [];
|
|
36
|
+
const changed = [];
|
|
37
|
+
compareNodes(before.root, after.root, [], added, removed, changed);
|
|
38
|
+
return { added, removed, changed };
|
|
39
|
+
}
|
|
40
|
+
function compareNodes(before, after, path, added, removed, changed) {
|
|
41
|
+
if (handlePrimitives(before, after, path, added, removed, changed)) {
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
const beforeElement = before;
|
|
45
|
+
const afterElement = after;
|
|
46
|
+
recordElementChange(beforeElement, afterElement, path, changed);
|
|
47
|
+
compareChildren(beforeElement, afterElement, path, added, removed, changed);
|
|
48
|
+
}
|
|
49
|
+
function handlePrimitives(before, after, path, added, removed, changed) {
|
|
50
|
+
if (typeof before === "string" && typeof after === "string") {
|
|
51
|
+
if (before !== after) {
|
|
52
|
+
changed.push({ path, before, after });
|
|
53
|
+
}
|
|
54
|
+
return true;
|
|
55
|
+
}
|
|
56
|
+
if (typeof before === "string") {
|
|
57
|
+
removed.push({ path, node: before });
|
|
58
|
+
added.push({ path, node: after });
|
|
59
|
+
return true;
|
|
60
|
+
}
|
|
61
|
+
if (typeof after === "string") {
|
|
62
|
+
removed.push({ path, node: before });
|
|
63
|
+
added.push({ path, node: after });
|
|
64
|
+
return true;
|
|
65
|
+
}
|
|
66
|
+
return false;
|
|
67
|
+
}
|
|
68
|
+
function recordElementChange(before, after, path, changed) {
|
|
69
|
+
const identityChanged = elementIdentity(before) !== elementIdentity(after);
|
|
70
|
+
const contentChanged = before.hash !== after.hash || before.tokens !== after.tokens;
|
|
71
|
+
if (identityChanged || contentChanged) {
|
|
72
|
+
changed.push({ path, before, after });
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
function compareChildren(before, after, path, added, removed, changed) {
|
|
76
|
+
const maxChildren = Math.max(before.children.length, after.children.length);
|
|
77
|
+
for (let i = 0; i < maxChildren; i++) {
|
|
78
|
+
const beforeChild = before.children[i];
|
|
79
|
+
const afterChild = after.children[i];
|
|
80
|
+
const childPath = [...path, i];
|
|
81
|
+
if (beforeChild === undefined && afterChild !== undefined) {
|
|
82
|
+
added.push({ path: childPath, node: afterChild });
|
|
83
|
+
continue;
|
|
84
|
+
}
|
|
85
|
+
if (beforeChild !== undefined && afterChild === undefined) {
|
|
86
|
+
removed.push({ path: childPath, node: beforeChild });
|
|
87
|
+
continue;
|
|
88
|
+
}
|
|
89
|
+
if (beforeChild !== undefined && afterChild !== undefined) {
|
|
90
|
+
compareNodes(beforeChild, afterChild, childPath, added, removed, changed);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
function elementIdentity(element) {
|
|
95
|
+
return element.id ?? `${element.kind ?? "region"}:${element.priority}`;
|
|
96
|
+
}
|
|
97
|
+
function snapshotElement(element, tokenizer, renderer) {
|
|
98
|
+
const childSnapshots = element.children.map((child) => typeof child === "string"
|
|
99
|
+
? child
|
|
100
|
+
: snapshotElement(child, tokenizer, renderer));
|
|
101
|
+
const contentProjection = renderer.tokenString(element);
|
|
102
|
+
const tokens = tokenizer(contentProjection);
|
|
103
|
+
const childHashes = childSnapshots.map((child) => typeof child === "string" ? hashString(child) : child.hash);
|
|
104
|
+
const hasToolId = element.kind === "tool-call" || element.kind === "tool-result";
|
|
105
|
+
const hash = hashElement({
|
|
106
|
+
kind: element.kind,
|
|
107
|
+
priority: element.priority,
|
|
108
|
+
role: element.kind === "message" ? element.role : undefined,
|
|
109
|
+
text: element.kind === "reasoning" ? element.text : undefined,
|
|
110
|
+
toolCallId: hasToolId ? element.toolCallId : undefined,
|
|
111
|
+
toolName: hasToolId ? element.toolName : undefined,
|
|
112
|
+
id: element.id,
|
|
113
|
+
tokens,
|
|
114
|
+
childHashes,
|
|
115
|
+
});
|
|
116
|
+
return {
|
|
117
|
+
...element,
|
|
118
|
+
children: childSnapshots,
|
|
119
|
+
tokens,
|
|
120
|
+
hash,
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
function hashElement(input) {
|
|
124
|
+
const payload = {
|
|
125
|
+
kind: input.kind ?? "region",
|
|
126
|
+
priority: input.priority,
|
|
127
|
+
role: input.role,
|
|
128
|
+
text: input.text,
|
|
129
|
+
toolCallId: input.toolCallId,
|
|
130
|
+
toolName: input.toolName,
|
|
131
|
+
id: input.id,
|
|
132
|
+
tokens: input.tokens,
|
|
133
|
+
children: input.childHashes,
|
|
134
|
+
};
|
|
135
|
+
return hashString(JSON.stringify(payload));
|
|
136
|
+
}
|
|
137
|
+
function hashString(value) {
|
|
138
|
+
return bytesToHex(sha256(utf8ToBytes(value)));
|
|
139
|
+
}
|
|
140
|
+
//# sourceMappingURL=snapshot.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"snapshot.js","sourceRoot":"","sources":["../src/snapshot.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAC9C,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAE9D,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAmCxD;;;;;;GAMG;AACH,MAAM,UAAU,cAAc,CAC5B,OAAsB,EACtB,EAAE,SAAS,EAAE,QAAQ,GAAG,gBAAgB,EAAmB;IAE3D,MAAM,IAAI,GAAG,eAAe,CAAC,OAAO,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAC;IAC3D,OAAO;QACL,IAAI;QACJ,WAAW,EAAE,IAAI,CAAC,MAAM;QACxB,IAAI,EAAE,IAAI,CAAC,IAAI;KAChB,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,EAClC,SAAS,EACT,QAAQ,EACR,UAAU,GACW;IACrB,OAAO;QACL,aAAa,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE;YAC7B,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC;gBAClB,OAAO;YACT,CAAC;YACD,MAAM,QAAQ,GAAG,cAAc,CAAC,KAAK,CAAC,MAAM,EAAE;gBAC5C,SAAS;gBACT,GAAG,CAAC,QAAQ,IAAI,EAAE,QAAQ,EAAE,CAAC;aAC9B,CAAC,CAAC;YACH,MAAM,UAAU,CAAC,QAAQ,CAAC,CAAC;QAC7B,CAAC;KACF,CAAC;AACJ,CAAC;AAmBD,MAAM,UAAU,aAAa,CAAC,MAAgB,EAAE,KAAe;IAC7D,MAAM,KAAK,GAAgB,EAAE,CAAC;IAC9B,MAAM,OAAO,GAAgB,EAAE,CAAC;IAChC,MAAM,OAAO,GAAiB,EAAE,CAAC;IAEjC,YAAY,CAAC,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;IAEnE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC;AACrC,CAAC;AAED,SAAS,YAAY,CACnB,MAAqB,EACrB,KAAoB,EACpB,IAAc,EACd,KAAkB,EAClB,OAAoB,EACpB,OAAqB;IAErB,IAAI,gBAAgB,CAAC,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,CAAC;QACnE,OAAO;IACT,CAAC;IAED,MAAM,aAAa,GAAG,MAAyB,CAAC;IAChD,MAAM,YAAY,GAAG,KAAwB,CAAC;IAE9C,mBAAmB,CAAC,aAAa,EAAE,YAAY,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;IAChE,eAAe,CAAC,aAAa,EAAE,YAAY,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;AAC9E,CAAC;AAED,SAAS,gBAAgB,CACvB,MAAqB,EACrB,KAAoB,EACpB,IAAuB,EACvB,KAAkB,EAClB,OAAoB,EACpB,OAAqB;IAErB,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC5D,IAAI,MAAM,KAAK,KAAK,EAAE,CAAC;YACrB,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC;QACxC,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE,CAAC;QAC/B,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;QACrC,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;QAClC,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;QACrC,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;QAClC,OAAO,IAAI,CAAC;IACd,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,mBAAmB,CAC1B,MAAuB,EACvB,KAAsB,EACtB,IAAuB,EACvB,OAAqB;IAErB,MAAM,eAAe,GAAG,eAAe,CAAC,MAAM,CAAC,KAAK,eAAe,CAAC,KAAK,CAAC,CAAC;IAC3E,MAAM,cAAc,GAClB,MAAM,CAAC,IAAI,KAAK,KAAK,CAAC,IAAI,IAAI,MAAM,CAAC,MAAM,KAAK,KAAK,CAAC,MAAM,CAAC;IAC/D,IAAI,eAAe,IAAI,cAAc,EAAE,CAAC;QACtC,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC;IACxC,CAAC;AACH,CAAC;AAED,SAAS,eAAe,CACtB,MAAuB,EACvB,KAAsB,EACtB,IAAc,EACd,KAAkB,EAClB,OAAoB,EACpB,OAAqB;IAErB,MAAM,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,EAAE,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;IAC5E,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,WAAW,EAAE,CAAC,EAAE,EAAE,CAAC;QACrC,MAAM,WAAW,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;QACvC,MAAM,UAAU,GAAG,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;QACrC,MAAM,SAAS,GAAG,CAAC,GAAG,IAAI,EAAE,CAAC,CAAC,CAAC;QAE/B,IAAI,WAAW,KAAK,SAAS,IAAI,UAAU,KAAK,SAAS,EAAE,CAAC;YAC1D,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC,CAAC;YAClD,SAAS;QACX,CAAC;QACD,IAAI,WAAW,KAAK,SAAS,IAAI,UAAU,KAAK,SAAS,EAAE,CAAC;YAC1D,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC,CAAC;YACrD,SAAS;QACX,CAAC;QACD,IAAI,WAAW,KAAK,SAAS,IAAI,UAAU,KAAK,SAAS,EAAE,CAAC;YAC1D,YAAY,CAAC,WAAW,EAAE,UAAU,EAAE,SAAS,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;QAC5E,CAAC;IACH,CAAC;AACH,CAAC;AAED,SAAS,eAAe,CAAC,OAAwB;IAC/C,OAAO,OAAO,CAAC,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,IAAI,QAAQ,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC;AACzE,CAAC;AAED,SAAS,eAAe,CACtB,OAAsB,EACtB,SAAoB,EACpB,QAAiC;IAEjC,MAAM,cAAc,GAAG,OAAO,CAAC,QAAQ,CAAC,GAAG,CACzC,CAAC,KAA6B,EAAiB,EAAE,CAC/C,OAAO,KAAK,KAAK,QAAQ;QACvB,CAAC,CAAC,KAAK;QACP,CAAC,CAAC,eAAe,CAAC,KAAK,EAAE,SAAS,EAAE,QAAQ,CAAC,CAClD,CAAC;IAEF,MAAM,iBAAiB,GAAG,QAAQ,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;IACxD,MAAM,MAAM,GAAG,SAAS,CAAC,iBAAiB,CAAC,CAAC;IAC5C,MAAM,WAAW,GAAG,cAAc,CAAC,GAAG,CAAC,CAAC,KAAoB,EAAU,EAAE,CACtE,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAC3D,CAAC;IAEF,MAAM,SAAS,GACb,OAAO,CAAC,IAAI,KAAK,WAAW,IAAI,OAAO,CAAC,IAAI,KAAK,aAAa,CAAC;IAEjE,MAAM,IAAI,GAAG,WAAW,CAAC;QACvB,IAAI,EAAE,OAAO,CAAC,IAAI;QAClB,QAAQ,EAAE,OAAO,CAAC,QAAQ;QAC1B,IAAI,EAAE,OAAO,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS;QAC3D,IAAI,EAAE,OAAO,CAAC,IAAI,KAAK,WAAW,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS;QAC7D,UAAU,EAAE,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,SAAS;QACtD,QAAQ,EAAE,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS;QAClD,EAAE,EAAE,OAAO,CAAC,EAAE;QACd,MAAM;QACN,WAAW;KACZ,CAAC,CAAC;IAEH,OAAO;QACL,GAAG,OAAO;QACV,QAAQ,EAAE,cAAc;QACxB,MAAM;QACN,IAAI;KACL,CAAC;AACJ,CAAC;AAED,SAAS,WAAW,CAAC,KAUpB;IACC,MAAM,OAAO,GAAG;QACd,IAAI,EAAE,KAAK,CAAC,IAAI,IAAI,QAAQ;QAC5B,QAAQ,EAAE,KAAK,CAAC,QAAQ;QACxB,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,UAAU,EAAE,KAAK,CAAC,UAAU;QAC5B,QAAQ,EAAE,KAAK,CAAC,QAAQ;QACxB,EAAE,EAAE,KAAK,CAAC,EAAE;QACZ,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,QAAQ,EAAE,KAAK,CAAC,WAAW;KAC5B,CAAC;IACF,OAAO,UAAU,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC;AAC7C,CAAC;AAED,SAAS,UAAU,CAAC,KAAa;IAC/B,OAAO,UAAU,CAAC,MAAM,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AAChD,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"snapshot.test.d.ts","sourceRoot":"","sources":["../src/snapshot.test.tsx"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "@fastpaca/cria/jsx-runtime";
|
|
2
|
+
import { describe, expect, test } from "vitest";
|
|
3
|
+
import { Omit, Region } from "./components";
|
|
4
|
+
import { render } from "./render";
|
|
5
|
+
import { createSnapshot, createSnapshotHooks, diffSnapshots } from "./snapshot";
|
|
6
|
+
const tokenizer = (text) => text.length;
|
|
7
|
+
const buildBaseTree = () => (_jsxs(Region, { priority: 0, children: ["Intro", _jsx(Region, { priority: 1, children: "Keep" }), _jsx(Omit, { priority: 2, children: "Drop" })] }));
|
|
8
|
+
const buildChangedTree = () => (_jsxs(Region, { priority: 0, children: ["Intro updated", _jsx(Region, { priority: 1, children: "Keep" }), _jsx(Region, { priority: 2, children: "Replace" })] }));
|
|
9
|
+
describe("createSnapshot", () => {
|
|
10
|
+
test("produces deterministic snapshots for the same input", async () => {
|
|
11
|
+
const element = await buildBaseTree();
|
|
12
|
+
const first = await createSnapshot(element, { tokenizer });
|
|
13
|
+
const second = await createSnapshot(element, { tokenizer });
|
|
14
|
+
expect(first.hash).toBe(second.hash);
|
|
15
|
+
expect(first.root).toEqual(second.root);
|
|
16
|
+
expect(first.totalTokens).toBe(second.totalTokens);
|
|
17
|
+
});
|
|
18
|
+
test("hash changes when structural content changes", async () => {
|
|
19
|
+
const base = await createSnapshot(await buildBaseTree(), { tokenizer });
|
|
20
|
+
const changed = await createSnapshot(await buildChangedTree(), {
|
|
21
|
+
tokenizer,
|
|
22
|
+
});
|
|
23
|
+
expect(base.hash).not.toBe(changed.hash);
|
|
24
|
+
});
|
|
25
|
+
});
|
|
26
|
+
describe("diffSnapshots", () => {
|
|
27
|
+
test("reports changed nodes and no false adds/removals when shapes align", async () => {
|
|
28
|
+
const base = await createSnapshot(await buildBaseTree(), { tokenizer });
|
|
29
|
+
const changed = await createSnapshot(await buildChangedTree(), {
|
|
30
|
+
tokenizer,
|
|
31
|
+
});
|
|
32
|
+
const diff = diffSnapshots(base, changed);
|
|
33
|
+
const changedPaths = diff.changed
|
|
34
|
+
.map((entry) => entry.path.join("."))
|
|
35
|
+
.sort();
|
|
36
|
+
expect(diff.added).toHaveLength(0);
|
|
37
|
+
expect(diff.removed).toHaveLength(0);
|
|
38
|
+
expect(changedPaths).toEqual(["", "0", "2", "2.0"]);
|
|
39
|
+
});
|
|
40
|
+
});
|
|
41
|
+
describe("createSnapshotHooks", () => {
|
|
42
|
+
test("invokes callback with snapshot on fit complete", async () => {
|
|
43
|
+
const snapshots = [];
|
|
44
|
+
const element = (_jsxs(Region, { priority: 0, children: ["A", _jsx(Omit, { priority: 1, children: "BBBB" })] }));
|
|
45
|
+
const hooks = createSnapshotHooks({
|
|
46
|
+
tokenizer,
|
|
47
|
+
onSnapshot: (snapshot) => {
|
|
48
|
+
snapshots.push(snapshot.hash);
|
|
49
|
+
},
|
|
50
|
+
});
|
|
51
|
+
const result = await render(element, { tokenizer, budget: 1, hooks });
|
|
52
|
+
expect(result).toBe("A");
|
|
53
|
+
expect(snapshots).toHaveLength(1);
|
|
54
|
+
});
|
|
55
|
+
test("propagates errors from snapshot creation", async () => {
|
|
56
|
+
const element = _jsx(Region, { priority: 0, children: "Hi" });
|
|
57
|
+
const hooks = createSnapshotHooks({
|
|
58
|
+
tokenizer: () => {
|
|
59
|
+
throw new Error("tokenizer failed");
|
|
60
|
+
},
|
|
61
|
+
onSnapshot: () => {
|
|
62
|
+
throw new Error("callback failed");
|
|
63
|
+
},
|
|
64
|
+
});
|
|
65
|
+
await expect(render(element, { tokenizer, budget: 10, hooks })).rejects.toThrow("tokenizer failed");
|
|
66
|
+
});
|
|
67
|
+
});
|
|
68
|
+
//# sourceMappingURL=snapshot.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"snapshot.test.js","sourceRoot":"","sources":["../src/snapshot.test.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { Tokenizer } from "./types";
|
|
2
|
+
/**
|
|
3
|
+
* Rough heuristic tokenizer: ~4 characters per token.
|
|
4
|
+
*
|
|
5
|
+
* Suitable as a default estimate when no model-specific tokenizer is available.
|
|
6
|
+
* For accurate budgeting, pass a model-aware tokenizer (e.g. tiktoken).
|
|
7
|
+
*/
|
|
8
|
+
export declare const approximateTokenizer: Tokenizer;
|
|
9
|
+
/**
|
|
10
|
+
* Best-effort tokenizer using tiktoken. Falls back to approximate if the encoding
|
|
11
|
+
* is unavailable.
|
|
12
|
+
*/
|
|
13
|
+
export declare function tiktokenTokenizer(modelHint?: string): Tokenizer;
|
|
14
|
+
//# sourceMappingURL=tokenizers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tokenizers.d.ts","sourceRoot":"","sources":["../src/tokenizers.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAEzC;;;;;GAKG;AACH,eAAO,MAAM,oBAAoB,EAAE,SACP,CAAC;AA6B7B;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAO/D"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { encodingForModel, getEncoding, } from "js-tiktoken";
|
|
2
|
+
/**
|
|
3
|
+
* Rough heuristic tokenizer: ~4 characters per token.
|
|
4
|
+
*
|
|
5
|
+
* Suitable as a default estimate when no model-specific tokenizer is available.
|
|
6
|
+
* For accurate budgeting, pass a model-aware tokenizer (e.g. tiktoken).
|
|
7
|
+
*/
|
|
8
|
+
export const approximateTokenizer = (text) => Math.ceil(text.length / 4);
|
|
9
|
+
const tiktokenCache = new Map();
|
|
10
|
+
function getTiktokenEncoder(modelHint) {
|
|
11
|
+
const cacheKey = modelHint ?? "cl100k_base";
|
|
12
|
+
const cached = tiktokenCache.get(cacheKey);
|
|
13
|
+
if (cached) {
|
|
14
|
+
return cached;
|
|
15
|
+
}
|
|
16
|
+
try {
|
|
17
|
+
const encoder = modelHint
|
|
18
|
+
? encodingForModel(modelHint)
|
|
19
|
+
: getEncoding("cl100k_base");
|
|
20
|
+
tiktokenCache.set(cacheKey, encoder);
|
|
21
|
+
return encoder;
|
|
22
|
+
}
|
|
23
|
+
catch (error) {
|
|
24
|
+
// Fall through to allow approximate fallback
|
|
25
|
+
const debugEnv = process.env
|
|
26
|
+
.DEBUG;
|
|
27
|
+
if (debugEnv?.includes("cria:tokenizer")) {
|
|
28
|
+
// eslint-disable-next-line no-console
|
|
29
|
+
console.warn("Falling back to approximate tokenizer:", error);
|
|
30
|
+
}
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Best-effort tokenizer using tiktoken. Falls back to approximate if the encoding
|
|
36
|
+
* is unavailable.
|
|
37
|
+
*/
|
|
38
|
+
export function tiktokenTokenizer(modelHint) {
|
|
39
|
+
const encoder = getTiktokenEncoder(modelHint);
|
|
40
|
+
if (!encoder) {
|
|
41
|
+
return approximateTokenizer;
|
|
42
|
+
}
|
|
43
|
+
return (text) => encoder.encode(text).length;
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=tokenizers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tokenizers.js","sourceRoot":"","sources":["../src/tokenizers.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,gBAAgB,EAChB,WAAW,GAGZ,MAAM,aAAa,CAAC;AAGrB;;;;;GAKG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAc,CAAC,IAAI,EAAE,EAAE,CACtD,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;AAE7B,MAAM,aAAa,GAAG,IAAI,GAAG,EAAoB,CAAC;AAElD,SAAS,kBAAkB,CAAC,SAAkB;IAC5C,MAAM,QAAQ,GAAG,SAAS,IAAI,aAAa,CAAC;IAC5C,MAAM,MAAM,GAAG,aAAa,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IAC3C,IAAI,MAAM,EAAE,CAAC;QACX,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,SAAS;YACvB,CAAC,CAAC,gBAAgB,CAAC,SAA0B,CAAC;YAC9C,CAAC,CAAC,WAAW,CAAC,aAAa,CAAC,CAAC;QAC/B,aAAa,CAAC,GAAG,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QACrC,OAAO,OAAO,CAAC;IACjB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,6CAA6C;QAC7C,MAAM,QAAQ,GAAI,OAAO,CAAC,GAA8C;aACrE,KAAK,CAAC;QACT,IAAI,QAAQ,EAAE,QAAQ,CAAC,gBAAgB,CAAC,EAAE,CAAC;YACzC,sCAAsC;YACtC,OAAO,CAAC,IAAI,CAAC,wCAAwC,EAAE,KAAK,CAAC,CAAC;QAChE,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAAC,SAAkB;IAClD,MAAM,OAAO,GAAG,kBAAkB,CAAC,SAAS,CAAC,CAAC;IAC9C,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO,oBAAoB,CAAC;IAC9B,CAAC;IAED,OAAO,CAAC,IAAY,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC;AACvD,CAAC"}
|
package/dist/types.d.ts
CHANGED
|
@@ -1,126 +1,254 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
1
2
|
/**
|
|
2
|
-
*
|
|
3
|
+
* Message role used by semantic `kind: "message"` regions.
|
|
3
4
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
*
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
5
|
+
* This is intentionally compatible with common LLM SDKs (system/user/assistant/tool),
|
|
6
|
+
* while still allowing custom roles for bespoke targets.
|
|
7
|
+
*/
|
|
8
|
+
export declare const PromptRoleSchema: z.ZodString;
|
|
9
|
+
export type PromptRole = z.infer<typeof PromptRoleSchema>;
|
|
10
|
+
/**
|
|
11
|
+
* A message in a completion request.
|
|
12
|
+
*/
|
|
13
|
+
export interface CompletionMessage {
|
|
14
|
+
role: PromptRole;
|
|
15
|
+
content: string;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Request parameters for a completion.
|
|
19
|
+
*/
|
|
20
|
+
export interface CompletionRequest {
|
|
21
|
+
/** Messages to send to the model */
|
|
22
|
+
messages: CompletionMessage[];
|
|
23
|
+
/** Optional system prompt (some providers handle this separately) */
|
|
24
|
+
system?: string;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Result from a completion request.
|
|
16
28
|
*/
|
|
17
|
-
export
|
|
29
|
+
export interface CompletionResult {
|
|
30
|
+
/** The generated text response */
|
|
31
|
+
text: string;
|
|
32
|
+
}
|
|
18
33
|
/**
|
|
19
|
-
*
|
|
34
|
+
* A model provider that can generate completions.
|
|
20
35
|
*
|
|
21
|
-
* This
|
|
22
|
-
*
|
|
36
|
+
* This abstraction allows Cria components to call AI models without
|
|
37
|
+
* being coupled to a specific SDK.
|
|
38
|
+
*/
|
|
39
|
+
export interface ModelProvider {
|
|
40
|
+
/** Provider identifier for debugging */
|
|
41
|
+
name: string;
|
|
42
|
+
/**
|
|
43
|
+
* Tokenizer for this provider's model.
|
|
44
|
+
*
|
|
45
|
+
* Used for budget fitting when the caller doesn't pass a tokenizer directly.
|
|
46
|
+
* Providers should supply an estimate that matches the chosen model; callers
|
|
47
|
+
* can still override via render options.
|
|
48
|
+
*/
|
|
49
|
+
tokenizer?: Tokenizer;
|
|
50
|
+
/**
|
|
51
|
+
* Generate a completion from the model.
|
|
52
|
+
*/
|
|
53
|
+
completion(request: CompletionRequest): MaybePromise<CompletionResult>;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Context that can be provided through the component tree.
|
|
23
57
|
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
|
|
27
|
-
|
|
58
|
+
* Provider components (like `<AISDKProvider>`) inject context that
|
|
59
|
+
* child components can access during rendering and strategy execution.
|
|
60
|
+
*/
|
|
61
|
+
export interface CriaContext {
|
|
62
|
+
/** Model provider for AI-powered operations */
|
|
63
|
+
provider?: ModelProvider | undefined;
|
|
64
|
+
}
|
|
65
|
+
export type MaybePromise<T> = T | Promise<T>;
|
|
66
|
+
/**
|
|
67
|
+
* A function that counts tokens in a string.
|
|
68
|
+
* Cria doesn't bundle a tokenizer. You provide one.
|
|
28
69
|
*
|
|
29
70
|
* @example
|
|
30
|
-
* ```
|
|
31
|
-
*
|
|
32
|
-
* <Region priority={0}>System prompt</Region>
|
|
71
|
+
* ```typescript
|
|
72
|
+
* import { encoding_for_model } from "tiktoken";
|
|
33
73
|
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
74
|
+
* const enc = encoding_for_model("gpt-4");
|
|
75
|
+
* const tokenizer: Tokenizer = (text) => enc.encode(text).length;
|
|
36
76
|
* ```
|
|
37
77
|
*/
|
|
38
|
-
export
|
|
78
|
+
export type Tokenizer = (text: string) => number;
|
|
79
|
+
export declare const PromptKindSchema: z.ZodUnion<[z.ZodObject<{
|
|
80
|
+
kind: z.ZodOptional<z.ZodUndefined>;
|
|
81
|
+
}, "strip", z.ZodTypeAny, {
|
|
82
|
+
kind?: undefined;
|
|
83
|
+
}, {
|
|
84
|
+
kind?: undefined;
|
|
85
|
+
}>, z.ZodObject<{
|
|
86
|
+
kind: z.ZodLiteral<"message">;
|
|
87
|
+
role: z.ZodString;
|
|
88
|
+
}, "strip", z.ZodTypeAny, {
|
|
89
|
+
kind: "message";
|
|
90
|
+
role: string;
|
|
91
|
+
}, {
|
|
92
|
+
kind: "message";
|
|
93
|
+
role: string;
|
|
94
|
+
}>, z.ZodObject<{
|
|
95
|
+
kind: z.ZodLiteral<"tool-call">;
|
|
96
|
+
toolCallId: z.ZodString;
|
|
97
|
+
toolName: z.ZodString;
|
|
98
|
+
input: z.ZodUnknown;
|
|
99
|
+
}, "strip", z.ZodTypeAny, {
|
|
100
|
+
kind: "tool-call";
|
|
101
|
+
toolCallId: string;
|
|
102
|
+
toolName: string;
|
|
103
|
+
input?: unknown;
|
|
104
|
+
}, {
|
|
105
|
+
kind: "tool-call";
|
|
106
|
+
toolCallId: string;
|
|
107
|
+
toolName: string;
|
|
108
|
+
input?: unknown;
|
|
109
|
+
}>, z.ZodObject<{
|
|
110
|
+
kind: z.ZodLiteral<"tool-result">;
|
|
111
|
+
toolCallId: z.ZodString;
|
|
112
|
+
toolName: z.ZodString;
|
|
113
|
+
output: z.ZodUnknown;
|
|
114
|
+
}, "strip", z.ZodTypeAny, {
|
|
115
|
+
kind: "tool-result";
|
|
116
|
+
toolCallId: string;
|
|
117
|
+
toolName: string;
|
|
118
|
+
output?: unknown;
|
|
119
|
+
}, {
|
|
120
|
+
kind: "tool-result";
|
|
121
|
+
toolCallId: string;
|
|
122
|
+
toolName: string;
|
|
123
|
+
output?: unknown;
|
|
124
|
+
}>, z.ZodObject<{
|
|
125
|
+
kind: z.ZodLiteral<"reasoning">;
|
|
126
|
+
text: z.ZodString;
|
|
127
|
+
}, "strip", z.ZodTypeAny, {
|
|
128
|
+
kind: "reasoning";
|
|
129
|
+
text: string;
|
|
130
|
+
}, {
|
|
131
|
+
kind: "reasoning";
|
|
132
|
+
text: string;
|
|
133
|
+
}>]>;
|
|
134
|
+
export type PromptKind = z.infer<typeof PromptKindSchema>;
|
|
135
|
+
export type PromptNodeKind = PromptKind["kind"];
|
|
136
|
+
export interface PromptElementBase {
|
|
39
137
|
priority: number;
|
|
40
|
-
strategy?: Strategy;
|
|
41
|
-
id?: string;
|
|
42
|
-
|
|
138
|
+
strategy?: Strategy | undefined;
|
|
139
|
+
id?: string | undefined;
|
|
140
|
+
context?: CriaContext | undefined;
|
|
141
|
+
children: PromptChildren;
|
|
43
142
|
}
|
|
143
|
+
export type PromptElement = (PromptElementBase & {
|
|
144
|
+
kind?: undefined;
|
|
145
|
+
}) | (PromptElementBase & {
|
|
146
|
+
kind: "message";
|
|
147
|
+
role: PromptRole;
|
|
148
|
+
}) | (PromptElementBase & {
|
|
149
|
+
kind: "tool-call";
|
|
150
|
+
toolCallId: string;
|
|
151
|
+
toolName: string;
|
|
152
|
+
input: unknown;
|
|
153
|
+
}) | (PromptElementBase & {
|
|
154
|
+
kind: "tool-result";
|
|
155
|
+
toolCallId: string;
|
|
156
|
+
toolName: string;
|
|
157
|
+
output: unknown;
|
|
158
|
+
}) | (PromptElementBase & {
|
|
159
|
+
kind: "reasoning";
|
|
160
|
+
text: string;
|
|
161
|
+
});
|
|
162
|
+
export type PromptChild = string | PromptElement;
|
|
163
|
+
export type PromptChildren = PromptChild[];
|
|
164
|
+
export declare const PromptElementSchema: z.ZodType<PromptElement>;
|
|
165
|
+
export declare const PromptChildSchema: z.ZodType<PromptChild>;
|
|
166
|
+
export declare const PromptChildrenSchema: z.ZodType<PromptChildren>;
|
|
44
167
|
/**
|
|
45
|
-
* A
|
|
168
|
+
* A renderer that converts a fitted prompt tree into an output format.
|
|
46
169
|
*
|
|
47
|
-
*
|
|
48
|
-
*
|
|
170
|
+
* Renderers are used for two things:
|
|
171
|
+
* - **Token accounting / fitting** via `tokenString` (a stable string projection)
|
|
172
|
+
* - **Final output** via `render` (can be async, and can produce any type)
|
|
49
173
|
*
|
|
50
|
-
* @
|
|
51
|
-
* @property tokens - Token count (computed via the provided tokenizer)
|
|
52
|
-
* @property priority - Inherited from the emitting element
|
|
53
|
-
* @property regionId - Stable identifier (from element.id or auto-generated)
|
|
54
|
-
* @property strategy - If present, this fragment can be reduced during fitting
|
|
55
|
-
* @property index - Position in the fragment list (for stable ordering)
|
|
174
|
+
* @template TOutput - The produced output type (e.g. `string`, `ModelMessage[]`, etc.).
|
|
56
175
|
*/
|
|
57
|
-
export interface
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
176
|
+
export interface PromptRenderer<TOutput> {
|
|
177
|
+
/** A short identifier for debugging/observability. */
|
|
178
|
+
name: string;
|
|
179
|
+
/**
|
|
180
|
+
* A deterministic string projection of the prompt tree used for token counting.
|
|
181
|
+
*
|
|
182
|
+
* Important properties:
|
|
183
|
+
* - **Pure / deterministic**: same tree => same string
|
|
184
|
+
* - **Cheap**: called frequently during fitting
|
|
185
|
+
* - **Representative**: should correlate with what `render()` produces (especially for string targets)
|
|
186
|
+
*
|
|
187
|
+
* For structured targets (e.g. AI SDK messages), this can be a markdown-ish projection
|
|
188
|
+
* that approximates the effective prompt content for token budgeting.
|
|
189
|
+
*/
|
|
190
|
+
tokenString: (element: PromptElement) => string;
|
|
191
|
+
/**
|
|
192
|
+
* Render the fitted prompt tree to the target output.
|
|
193
|
+
*
|
|
194
|
+
* May be async (e.g. when a renderer needs to fetch/resolve attachments, or when
|
|
195
|
+
* strategies summarized content during fitting).
|
|
196
|
+
*/
|
|
197
|
+
render: (element: PromptElement) => MaybePromise<TOutput>;
|
|
198
|
+
/**
|
|
199
|
+
* The “empty” value for this renderer.
|
|
200
|
+
*
|
|
201
|
+
* Used when the budget is <= 0, or when strategies remove the entire tree.
|
|
202
|
+
*/
|
|
203
|
+
empty: () => TOutput;
|
|
64
204
|
}
|
|
65
205
|
/**
|
|
66
|
-
*
|
|
67
|
-
*
|
|
68
|
-
* Strategies are called during the fit loop, starting with the least important
|
|
69
|
-
* priority (highest number). They receive context about the current state and
|
|
70
|
-
* must return replacement fragments (or empty array to remove entirely).
|
|
71
|
-
*
|
|
72
|
-
* Strategies must be:
|
|
73
|
-
* - **Pure**: Don't mutate the input fragments
|
|
74
|
-
* - **Deterministic**: Same input = same output
|
|
75
|
-
* - **Idempotent**: Applying twice has no additional effect
|
|
76
|
-
*
|
|
77
|
-
* @example
|
|
78
|
-
* ```typescript
|
|
79
|
-
* // A strategy that removes the fragment entirely
|
|
80
|
-
* const omitStrategy: Strategy = () => [];
|
|
206
|
+
* Canonical normalized child node type stored in the IR.
|
|
81
207
|
*
|
|
82
|
-
*
|
|
83
|
-
* const truncateStrategy: Strategy = ({ target, tokenizer }) => {
|
|
84
|
-
* let content = target.content.slice(0, 100);
|
|
85
|
-
* return [{ ...target, content, tokens: tokenizer(content) }];
|
|
86
|
-
* };
|
|
87
|
-
* ```
|
|
208
|
+
* This is the only type you’ll find inside `PromptElement.children` after JSX normalization.
|
|
88
209
|
*/
|
|
89
|
-
export type
|
|
210
|
+
export type JsonValue = null | string | number | boolean | JsonValue[] | {
|
|
211
|
+
[key: string]: JsonValue;
|
|
212
|
+
};
|
|
213
|
+
export declare const JsonValueSchema: z.ZodType<JsonValue>;
|
|
214
|
+
export type StrategyResult = PromptElement | null;
|
|
90
215
|
/**
|
|
91
216
|
* Context passed to strategy functions during the fit loop.
|
|
92
217
|
*
|
|
93
|
-
* @property
|
|
94
|
-
* @property target - The specific fragment this strategy should reduce
|
|
218
|
+
* @property target - The specific region to reduce
|
|
95
219
|
* @property budget - The total token budget we're trying to fit within
|
|
96
220
|
* @property tokenizer - Function to count tokens in a string
|
|
97
|
-
* @property
|
|
221
|
+
* @property tokenString - Renderer-provided projection used for token counting
|
|
222
|
+
* @property totalTokens - Current total token count for the prompt
|
|
98
223
|
* @property iteration - Which iteration of the fit loop (for debugging)
|
|
224
|
+
* @property context - Inherited context from ancestor provider components
|
|
99
225
|
*/
|
|
100
226
|
export interface StrategyInput {
|
|
101
|
-
|
|
102
|
-
target: PromptFragment;
|
|
227
|
+
target: PromptElement;
|
|
103
228
|
budget: number;
|
|
104
229
|
tokenizer: Tokenizer;
|
|
230
|
+
tokenString: (element: PromptElement) => string;
|
|
105
231
|
totalTokens: number;
|
|
106
232
|
iteration: number;
|
|
233
|
+
/** Context inherited from ancestor provider components */
|
|
234
|
+
context: CriaContext;
|
|
107
235
|
}
|
|
108
236
|
/**
|
|
109
|
-
* A function that
|
|
237
|
+
* A Strategy function that rewrites a region subtree when the prompt is over budget.
|
|
110
238
|
*
|
|
111
|
-
*
|
|
112
|
-
*
|
|
113
|
-
*
|
|
239
|
+
* Strategies are applied during fitting, starting from the least important
|
|
240
|
+
* priority (highest number). Strategies run **bottom-up** (post-order) so nested
|
|
241
|
+
* regions get a chance to shrink before their parents.
|
|
114
242
|
*
|
|
115
|
-
*
|
|
116
|
-
*
|
|
117
|
-
*
|
|
243
|
+
* Strategies must be:
|
|
244
|
+
* - **Pure**: don't mutate the input element
|
|
245
|
+
* - **Deterministic**
|
|
246
|
+
* - **Idempotent**
|
|
118
247
|
*
|
|
119
|
-
*
|
|
120
|
-
*
|
|
121
|
-
* ```
|
|
248
|
+
* Strategies have full ownership of their subtree: they can replace the element
|
|
249
|
+
* and/or rewrite any children.
|
|
122
250
|
*/
|
|
123
|
-
export type
|
|
251
|
+
export type Strategy = (input: StrategyInput) => MaybePromise<StrategyResult>;
|
|
124
252
|
/**
|
|
125
253
|
* Error thrown when the prompt cannot be fit within the budget.
|
|
126
254
|
*
|