@happyvertical/smrt-core 0.55.9 → 0.55.11
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/AGENTS.md +2 -0
- package/agents/build-knowledge.md +40 -0
- package/agents/cookbook-engine.md +102 -0
- package/agents/cookbook.md +63 -0
- package/dist/consumer-plugin/artifact-publication.js +3 -3
- package/dist/consumer-plugin/artifact-publication.js.map +1 -1
- package/dist/consumer-plugin/hosted-sti-collections.d.ts +10 -0
- package/dist/consumer-plugin/hosted-sti-collections.d.ts.map +1 -0
- package/dist/consumer-plugin/hosted-sti-collections.js +92 -0
- package/dist/consumer-plugin/hosted-sti-collections.js.map +1 -0
- package/dist/consumer-plugin/index.d.ts +1 -1
- package/dist/consumer-plugin/index.d.ts.map +1 -1
- package/dist/consumer-plugin/index.js +76 -51
- package/dist/consumer-plugin/index.js.map +1 -1
- package/dist/cookbook/engine/commands.d.ts +37 -0
- package/dist/cookbook/engine/commands.d.ts.map +1 -0
- package/dist/cookbook/engine/commands.js +275 -0
- package/dist/cookbook/engine/commands.js.map +1 -0
- package/dist/cookbook/engine/defaults.d.ts +10 -0
- package/dist/cookbook/engine/defaults.d.ts.map +1 -0
- package/dist/cookbook/engine/defaults.js +49 -0
- package/dist/cookbook/engine/defaults.js.map +1 -0
- package/dist/cookbook/engine/document.d.ts +66 -0
- package/dist/cookbook/engine/document.d.ts.map +1 -0
- package/dist/cookbook/engine/document.js +357 -0
- package/dist/cookbook/engine/document.js.map +1 -0
- package/dist/cookbook/engine/engine.d.ts +49 -0
- package/dist/cookbook/engine/engine.d.ts.map +1 -0
- package/dist/cookbook/engine/engine.js +399 -0
- package/dist/cookbook/engine/engine.js.map +1 -0
- package/dist/cookbook/engine/index.d.ts +14 -0
- package/dist/cookbook/engine/index.d.ts.map +1 -0
- package/dist/cookbook/engine/index.js +8 -0
- package/dist/cookbook/engine/nav.d.ts +45 -0
- package/dist/cookbook/engine/nav.d.ts.map +1 -0
- package/dist/cookbook/engine/nav.js +191 -0
- package/dist/cookbook/engine/nav.js.map +1 -0
- package/dist/cookbook/engine/schemas.d.ts +29 -0
- package/dist/cookbook/engine/schemas.d.ts.map +1 -0
- package/dist/cookbook/engine/schemas.js +363 -0
- package/dist/cookbook/engine/schemas.js.map +1 -0
- package/dist/cookbook/engine/types.d.ts +331 -0
- package/dist/cookbook/engine/types.d.ts.map +1 -0
- package/dist/cookbook/engine/types.js +10 -0
- package/dist/cookbook/engine/types.js.map +1 -0
- package/dist/cookbook/engine.d.ts +2 -0
- package/dist/cookbook/engine.d.ts.map +1 -0
- package/dist/cookbook/engine.js +9 -0
- package/dist/cookbook/index.d.ts +6 -0
- package/dist/cookbook/index.d.ts.map +1 -0
- package/dist/cookbook/v1.schema.json +131 -0
- package/dist/cookbook/validate.d.ts +37 -0
- package/dist/cookbook/validate.d.ts.map +1 -0
- package/dist/cookbook/validate.js +172 -0
- package/dist/cookbook/validate.js.map +1 -0
- package/dist/cookbook.d.ts +7 -0
- package/dist/cookbook.d.ts.map +1 -0
- package/dist/cookbook.js +2 -0
- package/dist/manifest/browser-capability.generated.d.ts.map +1 -1
- package/dist/manifest/browser-capability.generated.js +48 -2
- package/dist/manifest/browser-capability.generated.js.map +1 -1
- package/dist/manifest/static-manifest.js +1 -1
- package/dist/manifest/static-manifest.js.map +1 -1
- package/dist/manifest/store.js +1 -1
- package/dist/manifest/store.js.map +1 -1
- package/dist/manifest.json +1 -1
- package/dist/prebuild/index.js +13 -13
- package/dist/prebuild/index.js.map +1 -1
- package/dist/smrt-knowledge.json +23 -7
- package/dist/vite-plugin/web-collections.d.ts +5 -0
- package/dist/vite-plugin/web-collections.d.ts.map +1 -1
- package/dist/vite-plugin/web-collections.js +1 -1
- package/dist/vite-plugin/web-collections.js.map +1 -1
- package/dist/vite-preset/cookbook-exposure.d.ts +11 -0
- package/dist/vite-preset/cookbook-exposure.d.ts.map +1 -0
- package/dist/vite-preset/cookbook-exposure.js +95 -0
- package/dist/vite-preset/cookbook-exposure.js.map +1 -0
- package/dist/vite-preset/index.d.ts +9 -0
- package/dist/vite-preset/index.d.ts.map +1 -1
- package/dist/vite-preset/index.js +17 -7
- package/dist/vite-preset/index.js.map +1 -1
- package/package.json +18 -6
|
@@ -0,0 +1,357 @@
|
|
|
1
|
+
import { COOKBOOK_SCHEMA_URL, validateCookbook } from "../validate.js";
|
|
2
|
+
import { COMMERCE_SETTING_TARGETS, DEFAULT_THEME_PRESETS } from "./defaults.js";
|
|
3
|
+
import { buildNav, findModel } from "./nav.js";
|
|
4
|
+
//#region src/cookbook/engine/document.ts
|
|
5
|
+
var clone = (value) => value === void 0 ? value : structuredClone(value);
|
|
6
|
+
var same = (a, b) => JSON.stringify(a ?? null) === JSON.stringify(b ?? null);
|
|
7
|
+
var emptyCookbook = () => ({
|
|
8
|
+
$schema: COOKBOOK_SCHEMA_URL,
|
|
9
|
+
version: 1,
|
|
10
|
+
recipes: [],
|
|
11
|
+
features: [],
|
|
12
|
+
policies: []
|
|
13
|
+
});
|
|
14
|
+
/** Does the document hold nothing yet (so replacing it needs no say-so)? */
|
|
15
|
+
function isEmptyCookbook(doc) {
|
|
16
|
+
return !doc.recipes.length && !doc.features.length && !doc.policies.length && !Object.keys(doc.exposure ?? {}).length && !doc.layout && !doc.theme && !Object.keys(doc.overviews ?? {}).length;
|
|
17
|
+
}
|
|
18
|
+
var sortedUnique = (ids) => [...new Set(ids)].sort();
|
|
19
|
+
/**
|
|
20
|
+
* The document in its stable shape: sorted ids, sorted policies, empty optional
|
|
21
|
+
* sections absent, key order fixed. Unknown top-level keys are kept (additive
|
|
22
|
+
* fields in v1). Two engines given the same commands export identical text.
|
|
23
|
+
*/
|
|
24
|
+
function canonical(doc) {
|
|
25
|
+
const known = /* @__PURE__ */ new Set([
|
|
26
|
+
"$schema",
|
|
27
|
+
"version",
|
|
28
|
+
"name",
|
|
29
|
+
"description",
|
|
30
|
+
"recipes",
|
|
31
|
+
"features",
|
|
32
|
+
"policies",
|
|
33
|
+
"exposure",
|
|
34
|
+
"layout",
|
|
35
|
+
"theme",
|
|
36
|
+
"overviews"
|
|
37
|
+
]);
|
|
38
|
+
const out = {
|
|
39
|
+
$schema: COOKBOOK_SCHEMA_URL,
|
|
40
|
+
version: 1,
|
|
41
|
+
...doc.name ? { name: doc.name } : {},
|
|
42
|
+
...doc.description ? { description: doc.description } : {},
|
|
43
|
+
recipes: sortedUnique(doc.recipes),
|
|
44
|
+
features: sortedUnique(doc.features),
|
|
45
|
+
policies: [...doc.policies].sort((a, b) => a.objectRef.localeCompare(b.objectRef) || a.fieldName.localeCompare(b.fieldName)).map((row) => ({ ...row }))
|
|
46
|
+
};
|
|
47
|
+
const exposure = Object.fromEntries(Object.keys(doc.exposure ?? {}).sort().filter((ref) => doc.exposure?.[ref]?.length).map((ref) => [ref, [...doc.exposure?.[ref] ?? []].sort()]));
|
|
48
|
+
if (Object.keys(exposure).length) out.exposure = exposure;
|
|
49
|
+
if (doc.layout) out.layout = clone(doc.layout);
|
|
50
|
+
const theme = compactTheme(doc.theme);
|
|
51
|
+
if (theme) out.theme = theme;
|
|
52
|
+
const overviews = Object.entries(doc.overviews ?? {}).sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0);
|
|
53
|
+
if (overviews.length) out.overviews = Object.fromEntries(overviews.map(([id, value]) => [id, clone(value)]));
|
|
54
|
+
for (const [key, value] of Object.entries(doc)) if (!known.has(key)) out[key] = clone(value);
|
|
55
|
+
return out;
|
|
56
|
+
}
|
|
57
|
+
var recipeMap = (catalog) => new Map(catalog.recipes.map((r) => [r.id, r]));
|
|
58
|
+
/** `ids` plus everything they transitively require, as a sorted set. */
|
|
59
|
+
function withRequirements(ids, recipes) {
|
|
60
|
+
const result = /* @__PURE__ */ new Set();
|
|
61
|
+
const visit = (id) => {
|
|
62
|
+
const recipe = recipes.get(id);
|
|
63
|
+
if (!recipe || result.has(id)) return;
|
|
64
|
+
result.add(id);
|
|
65
|
+
for (const required of recipe.requires) visit(required);
|
|
66
|
+
};
|
|
67
|
+
for (const id of ids) visit(id);
|
|
68
|
+
let changed = true;
|
|
69
|
+
while (changed) {
|
|
70
|
+
changed = false;
|
|
71
|
+
for (const id of [...result]) for (const alternatives of recipes.get(id)?.requiresAny ?? []) {
|
|
72
|
+
if (alternatives.some((alt) => result.has(alt))) continue;
|
|
73
|
+
const first = alternatives.find((alt) => recipes.has(alt));
|
|
74
|
+
if (first) {
|
|
75
|
+
visit(first);
|
|
76
|
+
changed = true;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
return sortedUnique(result);
|
|
81
|
+
}
|
|
82
|
+
/** Models the added recipes and features cover. */
|
|
83
|
+
function coveredModels(catalog, doc) {
|
|
84
|
+
const byId = recipeMap(catalog);
|
|
85
|
+
return /* @__PURE__ */ new Set([...doc.recipes.flatMap((id) => byId.get(id)?.models ?? []), ...doc.features]);
|
|
86
|
+
}
|
|
87
|
+
function settingTargets(catalog) {
|
|
88
|
+
return catalog.settingTargets ?? COMMERCE_SETTING_TARGETS;
|
|
89
|
+
}
|
|
90
|
+
function isSettingRow(catalog, row) {
|
|
91
|
+
return Object.values(settingTargets(catalog)).some((targets) => targets.some((t) => t.model === row.objectRef && t.field === row.fieldName));
|
|
92
|
+
}
|
|
93
|
+
/** Drop options for models nothing covers any more (settings rows stay). */
|
|
94
|
+
function prune(catalog, doc) {
|
|
95
|
+
const covered = coveredModels(catalog, doc);
|
|
96
|
+
const next = {
|
|
97
|
+
...doc,
|
|
98
|
+
policies: doc.policies.filter((r) => covered.has(r.objectRef) || isSettingRow(catalog, r))
|
|
99
|
+
};
|
|
100
|
+
if (doc.exposure) {
|
|
101
|
+
const exposure = Object.fromEntries(Object.entries(doc.exposure).filter(([ref]) => covered.has(ref)));
|
|
102
|
+
if (Object.keys(exposure).length) next.exposure = exposure;
|
|
103
|
+
else delete next.exposure;
|
|
104
|
+
}
|
|
105
|
+
return next;
|
|
106
|
+
}
|
|
107
|
+
var knownRecipeIds = (catalog, doc) => {
|
|
108
|
+
const byId = recipeMap(catalog);
|
|
109
|
+
return doc.recipes.filter((id) => byId.has(id));
|
|
110
|
+
};
|
|
111
|
+
var unknownRecipeIds = (catalog, doc) => {
|
|
112
|
+
const byId = recipeMap(catalog);
|
|
113
|
+
return doc.recipes.filter((id) => !byId.has(id));
|
|
114
|
+
};
|
|
115
|
+
function diff(before, after) {
|
|
116
|
+
const b = new Set(before);
|
|
117
|
+
const a = new Set(after);
|
|
118
|
+
return {
|
|
119
|
+
added: after.filter((id) => !b.has(id)),
|
|
120
|
+
removed: before.filter((id) => !a.has(id))
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
function withRecipesAdded(catalog, doc, ids) {
|
|
124
|
+
const byId = recipeMap(catalog);
|
|
125
|
+
const before = knownRecipeIds(catalog, doc);
|
|
126
|
+
const known = withRequirements([...before, ...ids], byId);
|
|
127
|
+
return {
|
|
128
|
+
doc: {
|
|
129
|
+
...doc,
|
|
130
|
+
recipes: sortedUnique([...known, ...unknownRecipeIds(catalog, doc)])
|
|
131
|
+
},
|
|
132
|
+
changes: {
|
|
133
|
+
...diff(before, known),
|
|
134
|
+
kept: []
|
|
135
|
+
}
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
function withRecipesRemoved(catalog, doc, ids) {
|
|
139
|
+
const byId = recipeMap(catalog);
|
|
140
|
+
const before = knownRecipeIds(catalog, doc);
|
|
141
|
+
const removing = new Set(ids);
|
|
142
|
+
const known = withRequirements(before.filter((id) => !removing.has(id)), byId);
|
|
143
|
+
const next = prune(catalog, {
|
|
144
|
+
...doc,
|
|
145
|
+
recipes: sortedUnique([...known, ...unknownRecipeIds(catalog, doc)])
|
|
146
|
+
});
|
|
147
|
+
const { added, removed } = diff(before, known);
|
|
148
|
+
return {
|
|
149
|
+
doc: next,
|
|
150
|
+
changes: {
|
|
151
|
+
added,
|
|
152
|
+
removed,
|
|
153
|
+
kept: ids.filter((id) => known.includes(id) && before.includes(id))
|
|
154
|
+
}
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
function withFeaturesChanged(catalog, doc, ids, on) {
|
|
158
|
+
const set = new Set(doc.features);
|
|
159
|
+
for (const id of ids) if (on) set.add(id);
|
|
160
|
+
else set.delete(id);
|
|
161
|
+
const features = [...set].sort();
|
|
162
|
+
let next = {
|
|
163
|
+
...doc,
|
|
164
|
+
features
|
|
165
|
+
};
|
|
166
|
+
if (!on) next = prune(catalog, next);
|
|
167
|
+
return {
|
|
168
|
+
doc: next,
|
|
169
|
+
changes: {
|
|
170
|
+
...diff(doc.features, features),
|
|
171
|
+
kept: []
|
|
172
|
+
}
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
var mergeChanges = (a, b) => ({
|
|
176
|
+
added: [...a.added, ...b.added],
|
|
177
|
+
removed: [...a.removed, ...b.removed],
|
|
178
|
+
kept: [...a.kept, ...b.kept]
|
|
179
|
+
});
|
|
180
|
+
var DEFAULT_SETTINGS = {
|
|
181
|
+
currency: "USD",
|
|
182
|
+
taxRate: 0,
|
|
183
|
+
paymentTerms: ""
|
|
184
|
+
};
|
|
185
|
+
var SETTING_KEYS = [
|
|
186
|
+
"currency",
|
|
187
|
+
"taxRate",
|
|
188
|
+
"paymentTerms"
|
|
189
|
+
];
|
|
190
|
+
function rowValue(row) {
|
|
191
|
+
if (row?.defaultValue === void 0 || row.defaultValue === null) return void 0;
|
|
192
|
+
try {
|
|
193
|
+
return JSON.parse(row.defaultValue);
|
|
194
|
+
} catch {
|
|
195
|
+
return;
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
var findRow = (policies, model, field) => policies.find((r) => r.scopeType === "app" && r.objectRef === model && r.fieldName === field);
|
|
199
|
+
/** The app's settings: the first stored row of each, else the defaults. */
|
|
200
|
+
function readSettings(catalog, doc) {
|
|
201
|
+
const targets = settingTargets(catalog);
|
|
202
|
+
const out = { ...DEFAULT_SETTINGS };
|
|
203
|
+
const first = (key, type) => {
|
|
204
|
+
for (const { model, field } of targets[key]) {
|
|
205
|
+
const value = rowValue(findRow(doc.policies, model, field));
|
|
206
|
+
if (typeof value === type) return value;
|
|
207
|
+
}
|
|
208
|
+
};
|
|
209
|
+
const currency = first("currency", "string");
|
|
210
|
+
const taxRate = first("taxRate", "number");
|
|
211
|
+
const paymentTerms = first("paymentTerms", "string");
|
|
212
|
+
if (typeof currency === "string") out.currency = currency;
|
|
213
|
+
if (typeof taxRate === "number") out.taxRate = taxRate;
|
|
214
|
+
if (typeof paymentTerms === "string") out.paymentTerms = paymentTerms;
|
|
215
|
+
return out;
|
|
216
|
+
}
|
|
217
|
+
var isUnset = (v) => v === void 0 || v === null || v === "";
|
|
218
|
+
function seedDefault(catalog, doc, modelId, field) {
|
|
219
|
+
const byId = recipeMap(catalog);
|
|
220
|
+
for (const id of doc.recipes) {
|
|
221
|
+
const hint = byId.get(id)?.options?.[modelId]?.fields?.[field];
|
|
222
|
+
if (hint && "default" in hint) return hint.default;
|
|
223
|
+
}
|
|
224
|
+
return findModel(catalog, modelId)?.fields?.find((f) => f.name === field)?.default;
|
|
225
|
+
}
|
|
226
|
+
/**
|
|
227
|
+
* The document with the settings written as app-scope policy rows. A row is
|
|
228
|
+
* written for every model a setting covers (covered or not, so a recipe added
|
|
229
|
+
* later picks it up) and only where the value differs from what the model
|
|
230
|
+
* starts as; otherwise the row's default is removed. Other row keys are kept.
|
|
231
|
+
*/
|
|
232
|
+
function writeSettings(catalog, doc, settings) {
|
|
233
|
+
const targets = settingTargets(catalog);
|
|
234
|
+
let policies = doc.policies.map((row) => ({ ...row }));
|
|
235
|
+
for (const key of SETTING_KEYS) {
|
|
236
|
+
const raw = settings[key];
|
|
237
|
+
const value = key === "paymentTerms" ? String(raw).trim() : key === "currency" ? String(raw).trim().toUpperCase() : raw;
|
|
238
|
+
for (const { model, field } of targets[key]) {
|
|
239
|
+
const seed = seedDefault(catalog, doc, model, field);
|
|
240
|
+
const wanted = !isUnset(value) && !(!isUnset(seed) && seed === value) && !(isUnset(seed) && key === "taxRate" && value === 0);
|
|
241
|
+
const existing = findRow(policies, model, field);
|
|
242
|
+
if (wanted) {
|
|
243
|
+
const encoded = JSON.stringify(value);
|
|
244
|
+
if (existing) existing.defaultValue = encoded;
|
|
245
|
+
else policies.push({
|
|
246
|
+
objectRef: model,
|
|
247
|
+
fieldName: field,
|
|
248
|
+
scopeType: "app",
|
|
249
|
+
defaultValue: encoded
|
|
250
|
+
});
|
|
251
|
+
} else if (existing) {
|
|
252
|
+
delete existing.defaultValue;
|
|
253
|
+
if (Object.keys(existing).length <= 3) policies = policies.filter((r) => r !== existing);
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
return {
|
|
258
|
+
...doc,
|
|
259
|
+
policies
|
|
260
|
+
};
|
|
261
|
+
}
|
|
262
|
+
function compactTheme(theme) {
|
|
263
|
+
if (!theme) return void 0;
|
|
264
|
+
const out = {};
|
|
265
|
+
if (theme.preset) out.preset = theme.preset;
|
|
266
|
+
if (theme.colorScheme) out.colorScheme = theme.colorScheme;
|
|
267
|
+
if (theme.custom) out.custom = { ...theme.custom };
|
|
268
|
+
return Object.keys(out).length ? out : void 0;
|
|
269
|
+
}
|
|
270
|
+
function describeTheme(theme) {
|
|
271
|
+
const scheme = theme?.colorScheme ?? "system";
|
|
272
|
+
const base = theme?.custom ? `brand colour ${theme.custom.primary}` : theme?.preset ?? "smrt";
|
|
273
|
+
return scheme === "system" ? base : `${base}, ${scheme}`;
|
|
274
|
+
}
|
|
275
|
+
/** A preset replaces a brand colour; a brand colour sits on the preset; the scheme is kept. */
|
|
276
|
+
function withThemePatch(doc, patch) {
|
|
277
|
+
const next = { ...doc.theme ?? {} };
|
|
278
|
+
if (patch.preset) {
|
|
279
|
+
next.preset = patch.preset;
|
|
280
|
+
delete next.custom;
|
|
281
|
+
}
|
|
282
|
+
if (patch.primary) next.custom = {
|
|
283
|
+
primary: patch.primary.toLowerCase(),
|
|
284
|
+
...doc.theme?.custom?.fontFamily ? { fontFamily: doc.theme.custom.fontFamily } : {}
|
|
285
|
+
};
|
|
286
|
+
if (patch.colorScheme) next.colorScheme = patch.colorScheme;
|
|
287
|
+
const theme = compactTheme(next);
|
|
288
|
+
const out = { ...doc };
|
|
289
|
+
if (theme) out.theme = theme;
|
|
290
|
+
else delete out.theme;
|
|
291
|
+
return out;
|
|
292
|
+
}
|
|
293
|
+
/**
|
|
294
|
+
* Check a document against the catalog. Structural errors come from
|
|
295
|
+
* `validateCookbook`; the rest need the catalog: unknown ids, unmet `requires`,
|
|
296
|
+
* policy targets nothing covers, layout ids the menu does not have, theme
|
|
297
|
+
* values. Errors mean the app would not build as written; warnings mean
|
|
298
|
+
* something is carried but unused.
|
|
299
|
+
*/
|
|
300
|
+
function diagnose(catalog, input) {
|
|
301
|
+
const out = [];
|
|
302
|
+
const add = (severity, code, path, message) => out.push({
|
|
303
|
+
severity,
|
|
304
|
+
code,
|
|
305
|
+
path,
|
|
306
|
+
message
|
|
307
|
+
});
|
|
308
|
+
const structural = validateCookbook(input);
|
|
309
|
+
if (!structural.ok) {
|
|
310
|
+
for (const message of structural.errors) add("error", "invalid_document", "", message);
|
|
311
|
+
return out;
|
|
312
|
+
}
|
|
313
|
+
for (const message of structural.warnings) add("warning", "migrated", "", message);
|
|
314
|
+
const doc = structural.cookbook;
|
|
315
|
+
const byId = recipeMap(catalog);
|
|
316
|
+
for (const [i, id] of doc.recipes.entries()) if (!byId.has(id)) add("error", "unknown_recipe", `recipes[${i}]`, `Unknown recipe "${id}".`);
|
|
317
|
+
const closure = new Set(withRequirements(doc.recipes, byId));
|
|
318
|
+
for (const id of closure) if (!doc.recipes.includes(id)) add("error", "missing_requirement", "recipes", `A recipe needs "${id}", which is not listed.`);
|
|
319
|
+
for (const [i, id] of doc.features.entries()) {
|
|
320
|
+
const model = findModel(catalog, id);
|
|
321
|
+
if (!model) add("error", "unknown_model", `features[${i}]`, `Unknown model "${id}".`);
|
|
322
|
+
else if (model.exposed === false) add("error", "model_not_exposed", `features[${i}]`, `${id} cannot be added as a feature.`);
|
|
323
|
+
}
|
|
324
|
+
const covered = coveredModels(catalog, doc);
|
|
325
|
+
for (const [i, row] of doc.policies.entries()) {
|
|
326
|
+
const at = `policies[${i}]`;
|
|
327
|
+
const model = findModel(catalog, row.objectRef);
|
|
328
|
+
if (!model) {
|
|
329
|
+
add("error", "unknown_model", `${at}.objectRef`, `Unknown model "${row.objectRef}".`);
|
|
330
|
+
continue;
|
|
331
|
+
}
|
|
332
|
+
if (model.fields && !model.fields.some((f) => f.name === row.fieldName && !f.system)) add("error", "unknown_field", `${at}.fieldName`, `${model.name} has no field "${row.fieldName}".`);
|
|
333
|
+
if (!covered.has(row.objectRef) && !isSettingRow(catalog, row)) add("warning", "policy_not_covered", at, `${model.name} is not in the app, so this row has no effect.`);
|
|
334
|
+
}
|
|
335
|
+
for (const ref of Object.keys(doc.exposure ?? {})) if (!findModel(catalog, ref)) add("error", "unknown_model", `exposure.${ref}`, `Unknown model "${ref}".`);
|
|
336
|
+
const presets = catalog.themePresets ?? DEFAULT_THEME_PRESETS;
|
|
337
|
+
if (doc.theme?.preset && !presets.includes(doc.theme.preset)) add("error", "unknown_preset", "theme.preset", `Unknown theme preset "${doc.theme.preset}".`);
|
|
338
|
+
if (doc.layout) {
|
|
339
|
+
const nav = buildNav(catalog, {
|
|
340
|
+
...doc,
|
|
341
|
+
layout: void 0
|
|
342
|
+
});
|
|
343
|
+
const ids = /* @__PURE__ */ new Set([...nav.flatMap((s) => [s.id, ...s.items.map((i) => i.id)]), ...(doc.layout.customSections ?? []).map((c) => c.id)]);
|
|
344
|
+
const refs = [
|
|
345
|
+
...(doc.layout.hidden ?? []).map((id, i) => [`layout.hidden[${i}]`, id]),
|
|
346
|
+
...Object.keys(doc.layout.sections ?? {}).map((id) => [`layout.sections.${id}`, id]),
|
|
347
|
+
...Object.keys(doc.layout.items ?? {}).map((id) => [`layout.items.${id}`, id]),
|
|
348
|
+
...(doc.layout.sectionOrder ?? []).map((id, i) => [`layout.sectionOrder[${i}]`, id])
|
|
349
|
+
];
|
|
350
|
+
for (const [path, id] of refs) if (!ids.has(id)) add("warning", "unknown_layout_id", path, `The menu has no section or entry "${id}".`);
|
|
351
|
+
}
|
|
352
|
+
return out;
|
|
353
|
+
}
|
|
354
|
+
//#endregion
|
|
355
|
+
export { DEFAULT_SETTINGS, canonical, clone, compactTheme, coveredModels, describeTheme, diagnose, emptyCookbook, isEmptyCookbook, mergeChanges, prune, readSettings, same, settingTargets, withFeaturesChanged, withRecipesAdded, withRecipesRemoved, withRequirements, withThemePatch, writeSettings };
|
|
356
|
+
|
|
357
|
+
//# sourceMappingURL=document.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"document.js","names":[],"sources":["../../../src/cookbook/engine/document.ts"],"sourcesContent":["import type {\n Cookbook,\n CookbookPolicyRow,\n CookbookTheme,\n} from '@happyvertical/smrt-types';\nimport {\n COOKBOOK_SCHEMA_URL,\n COOKBOOK_VERSION,\n validateCookbook,\n} from '../validate.js';\nimport {\n COMMERCE_SETTING_TARGETS,\n DEFAULT_COLOR_SCHEME,\n DEFAULT_PRESET,\n DEFAULT_THEME_PRESETS,\n} from './defaults.js';\nimport { buildNav, findModel } from './nav.js';\nimport type {\n Diagnostic,\n EngineCatalog,\n EngineRecipe,\n RecipeChanges,\n SettingTargets,\n} from './types.js';\n\n/*\n * Pure document rules: every function takes a cookbook and returns a new one.\n * The engine holds a document and calls these; nothing here keeps state.\n */\n\nexport const clone = <T>(value: T): T =>\n value === undefined ? value : structuredClone(value);\n\nexport const same = (a: unknown, b: unknown): boolean =>\n JSON.stringify(a ?? null) === JSON.stringify(b ?? null);\n\nexport const emptyCookbook = (): Cookbook => ({\n $schema: COOKBOOK_SCHEMA_URL,\n version: COOKBOOK_VERSION,\n recipes: [],\n features: [],\n policies: [],\n});\n\n/** Does the document hold nothing yet (so replacing it needs no say-so)? */\nexport function isEmptyCookbook(doc: Cookbook): boolean {\n return (\n !doc.recipes.length &&\n !doc.features.length &&\n !doc.policies.length &&\n !Object.keys(doc.exposure ?? {}).length &&\n !doc.layout &&\n !doc.theme &&\n !Object.keys(doc.overviews ?? {}).length\n );\n}\n\nconst sortedUnique = (ids: Iterable<string>) => [...new Set(ids)].sort();\n\n/**\n * The document in its stable shape: sorted ids, sorted policies, empty optional\n * sections absent, key order fixed. Unknown top-level keys are kept (additive\n * fields in v1). Two engines given the same commands export identical text.\n */\nexport function canonical(doc: Cookbook): Cookbook {\n const known = new Set([\n '$schema',\n 'version',\n 'name',\n 'description',\n 'recipes',\n 'features',\n 'policies',\n 'exposure',\n 'layout',\n 'theme',\n 'overviews',\n ]);\n const out: Cookbook = {\n $schema: COOKBOOK_SCHEMA_URL,\n version: COOKBOOK_VERSION,\n ...(doc.name ? { name: doc.name } : {}),\n ...(doc.description ? { description: doc.description } : {}),\n recipes: sortedUnique(doc.recipes),\n features: sortedUnique(doc.features),\n policies: [...doc.policies]\n .sort(\n (a, b) =>\n a.objectRef.localeCompare(b.objectRef) ||\n a.fieldName.localeCompare(b.fieldName),\n )\n .map((row) => ({ ...row })),\n };\n const exposure = Object.fromEntries(\n Object.keys(doc.exposure ?? {})\n .sort()\n .filter((ref) => doc.exposure?.[ref]?.length)\n .map((ref) => [ref, [...(doc.exposure?.[ref] ?? [])].sort()]),\n );\n if (Object.keys(exposure).length) {\n out.exposure = exposure as NonNullable<Cookbook['exposure']>;\n }\n if (doc.layout) out.layout = clone(doc.layout);\n const theme = compactTheme(doc.theme);\n if (theme) out.theme = theme;\n const overviews = Object.entries(doc.overviews ?? {}).sort(([a], [b]) =>\n a < b ? -1 : a > b ? 1 : 0,\n );\n if (overviews.length) {\n out.overviews = Object.fromEntries(\n overviews.map(([id, value]) => [id, clone(value)]),\n );\n }\n for (const [key, value] of Object.entries(doc)) {\n if (!known.has(key))\n (out as unknown as Record<string, unknown>)[key] = clone(value);\n }\n return out;\n}\n\n// ---- recipes ---------------------------------------------------------------\n\nconst recipeMap = (catalog: EngineCatalog) =>\n new Map(catalog.recipes.map((r) => [r.id, r]));\n\n/** `ids` plus everything they transitively require, as a sorted set. */\nexport function withRequirements(\n ids: Iterable<string>,\n recipes: ReadonlyMap<string, EngineRecipe>,\n): string[] {\n const result = new Set<string>();\n const visit = (id: string) => {\n const recipe = recipes.get(id);\n if (!recipe || result.has(id)) return;\n result.add(id);\n for (const required of recipe.requires) visit(required);\n };\n for (const id of ids) visit(id);\n let changed = true;\n while (changed) {\n changed = false;\n for (const id of [...result]) {\n for (const alternatives of recipes.get(id)?.requiresAny ?? []) {\n if (alternatives.some((alt) => result.has(alt))) continue;\n const first = alternatives.find((alt) => recipes.has(alt));\n if (first) {\n visit(first);\n changed = true;\n }\n }\n }\n }\n return sortedUnique(result);\n}\n\n/** Models the added recipes and features cover. */\nexport function coveredModels(\n catalog: EngineCatalog,\n doc: Cookbook,\n): Set<string> {\n const byId = recipeMap(catalog);\n return new Set([\n ...doc.recipes.flatMap((id) => byId.get(id)?.models ?? []),\n ...doc.features,\n ]);\n}\n\nexport function settingTargets(catalog: EngineCatalog): SettingTargets {\n return catalog.settingTargets ?? COMMERCE_SETTING_TARGETS;\n}\n\nfunction isSettingRow(catalog: EngineCatalog, row: CookbookPolicyRow): boolean {\n return Object.values(settingTargets(catalog)).some((targets) =>\n targets.some((t) => t.model === row.objectRef && t.field === row.fieldName),\n );\n}\n\n/** Drop options for models nothing covers any more (settings rows stay). */\nexport function prune(catalog: EngineCatalog, doc: Cookbook): Cookbook {\n const covered = coveredModels(catalog, doc);\n const next: Cookbook = {\n ...doc,\n policies: doc.policies.filter(\n (r) => covered.has(r.objectRef) || isSettingRow(catalog, r),\n ),\n };\n if (doc.exposure) {\n const exposure = Object.fromEntries(\n Object.entries(doc.exposure).filter(([ref]) => covered.has(ref)),\n );\n if (Object.keys(exposure).length) next.exposure = exposure;\n else delete next.exposure;\n }\n return next;\n}\n\nconst knownRecipeIds = (catalog: EngineCatalog, doc: Cookbook) => {\n const byId = recipeMap(catalog);\n return doc.recipes.filter((id) => byId.has(id));\n};\n\nconst unknownRecipeIds = (catalog: EngineCatalog, doc: Cookbook) => {\n const byId = recipeMap(catalog);\n return doc.recipes.filter((id) => !byId.has(id));\n};\n\nfunction diff(\n before: string[],\n after: string[],\n): Pick<RecipeChanges, 'added' | 'removed'> {\n const b = new Set(before);\n const a = new Set(after);\n return {\n added: after.filter((id) => !b.has(id)),\n removed: before.filter((id) => !a.has(id)),\n };\n}\n\nexport function withRecipesAdded(\n catalog: EngineCatalog,\n doc: Cookbook,\n ids: readonly string[],\n): { doc: Cookbook; changes: RecipeChanges } {\n const byId = recipeMap(catalog);\n const before = knownRecipeIds(catalog, doc);\n const known = withRequirements([...before, ...ids], byId);\n const next = {\n ...doc,\n recipes: sortedUnique([...known, ...unknownRecipeIds(catalog, doc)]),\n };\n return { doc: next, changes: { ...diff(before, known), kept: [] } };\n}\n\nexport function withRecipesRemoved(\n catalog: EngineCatalog,\n doc: Cookbook,\n ids: readonly string[],\n): { doc: Cookbook; changes: RecipeChanges } {\n const byId = recipeMap(catalog);\n const before = knownRecipeIds(catalog, doc);\n const removing = new Set(ids);\n const known = withRequirements(\n before.filter((id) => !removing.has(id)),\n byId,\n );\n const next = prune(catalog, {\n ...doc,\n recipes: sortedUnique([...known, ...unknownRecipeIds(catalog, doc)]),\n });\n const { added, removed } = diff(before, known);\n return {\n doc: next,\n changes: {\n added,\n removed,\n kept: ids.filter((id) => known.includes(id) && before.includes(id)),\n },\n };\n}\n\nexport function withFeaturesChanged(\n catalog: EngineCatalog,\n doc: Cookbook,\n ids: readonly string[],\n on: boolean,\n): { doc: Cookbook; changes: RecipeChanges } {\n const set = new Set(doc.features);\n for (const id of ids) {\n if (on) set.add(id);\n else set.delete(id);\n }\n const features = [...set].sort();\n let next: Cookbook = { ...doc, features };\n if (!on) next = prune(catalog, next);\n return {\n doc: next,\n changes: { ...diff(doc.features, features), kept: [] },\n };\n}\n\nexport const mergeChanges = (\n a: RecipeChanges,\n b: RecipeChanges,\n): RecipeChanges => ({\n added: [...a.added, ...b.added],\n removed: [...a.removed, ...b.removed],\n kept: [...a.kept, ...b.kept],\n});\n\n// ---- settings --------------------------------------------------------------\n\nexport interface AppSettings {\n currency: string;\n /** A fraction: 0.0825 is 8.25%. */\n taxRate: number;\n paymentTerms: string;\n}\n\nexport const DEFAULT_SETTINGS: Readonly<AppSettings> = {\n currency: 'USD',\n taxRate: 0,\n paymentTerms: '',\n};\n\nconst SETTING_KEYS = ['currency', 'taxRate', 'paymentTerms'] as const;\n\nfunction rowValue(row: CookbookPolicyRow | undefined): unknown {\n if (row?.defaultValue === undefined || row.defaultValue === null)\n return undefined;\n try {\n return JSON.parse(row.defaultValue);\n } catch {\n return undefined;\n }\n}\n\nconst findRow = (\n policies: readonly CookbookPolicyRow[],\n model: string,\n field: string,\n) =>\n policies.find(\n (r) =>\n r.scopeType === 'app' && r.objectRef === model && r.fieldName === field,\n );\n\n/** The app's settings: the first stored row of each, else the defaults. */\nexport function readSettings(\n catalog: EngineCatalog,\n doc: Cookbook,\n): AppSettings {\n const targets = settingTargets(catalog);\n const out: AppSettings = { ...DEFAULT_SETTINGS };\n const first = (key: keyof AppSettings, type: 'number' | 'string') => {\n for (const { model, field } of targets[key]) {\n const value = rowValue(findRow(doc.policies, model, field));\n if (typeof value === type) return value;\n }\n return undefined;\n };\n const currency = first('currency', 'string');\n const taxRate = first('taxRate', 'number');\n const paymentTerms = first('paymentTerms', 'string');\n if (typeof currency === 'string') out.currency = currency;\n if (typeof taxRate === 'number') out.taxRate = taxRate;\n if (typeof paymentTerms === 'string') out.paymentTerms = paymentTerms;\n return out;\n}\n\nconst isUnset = (v: unknown) => v === undefined || v === null || v === '';\n\nfunction seedDefault(\n catalog: EngineCatalog,\n doc: Cookbook,\n modelId: string,\n field: string,\n): unknown {\n const byId = recipeMap(catalog);\n for (const id of doc.recipes) {\n const hint = byId.get(id)?.options?.[modelId]?.fields?.[field];\n if (hint && 'default' in hint) return hint.default;\n }\n return findModel(catalog, modelId)?.fields?.find((f) => f.name === field)\n ?.default;\n}\n\n/**\n * The document with the settings written as app-scope policy rows. A row is\n * written for every model a setting covers (covered or not, so a recipe added\n * later picks it up) and only where the value differs from what the model\n * starts as; otherwise the row's default is removed. Other row keys are kept.\n */\nexport function writeSettings(\n catalog: EngineCatalog,\n doc: Cookbook,\n settings: AppSettings,\n): Cookbook {\n const targets = settingTargets(catalog);\n let policies = doc.policies.map((row) => ({ ...row }));\n for (const key of SETTING_KEYS) {\n const raw = settings[key];\n const value =\n key === 'paymentTerms'\n ? String(raw).trim()\n : key === 'currency'\n ? String(raw).trim().toUpperCase()\n : raw;\n for (const { model, field } of targets[key]) {\n const seed = seedDefault(catalog, doc, model, field);\n const wanted =\n !isUnset(value) &&\n !(!isUnset(seed) && seed === value) &&\n !(isUnset(seed) && key === 'taxRate' && value === 0);\n const existing = findRow(policies, model, field);\n if (wanted) {\n const encoded = JSON.stringify(value);\n if (existing) existing.defaultValue = encoded;\n else\n policies.push({\n objectRef: model,\n fieldName: field,\n scopeType: 'app',\n defaultValue: encoded,\n });\n } else if (existing) {\n delete existing.defaultValue;\n if (Object.keys(existing).length <= 3) {\n policies = policies.filter((r) => r !== existing);\n }\n }\n }\n }\n return { ...doc, policies };\n}\n\n// ---- theme -----------------------------------------------------------------\n\nexport function compactTheme(\n theme: CookbookTheme | undefined,\n): CookbookTheme | undefined {\n if (!theme) return undefined;\n const out: CookbookTheme = {};\n if (theme.preset) out.preset = theme.preset;\n if (theme.colorScheme) out.colorScheme = theme.colorScheme;\n if (theme.custom) out.custom = { ...theme.custom };\n return Object.keys(out).length ? out : undefined;\n}\n\nexport function describeTheme(theme: CookbookTheme | undefined): string {\n const scheme = theme?.colorScheme ?? DEFAULT_COLOR_SCHEME;\n const base = theme?.custom\n ? `brand colour ${theme.custom.primary}`\n : (theme?.preset ?? DEFAULT_PRESET);\n return scheme === 'system' ? base : `${base}, ${scheme}`;\n}\n\n/** A preset replaces a brand colour; a brand colour sits on the preset; the scheme is kept. */\nexport function withThemePatch(\n doc: Cookbook,\n patch: {\n preset?: string;\n primary?: string;\n colorScheme?: CookbookTheme['colorScheme'];\n },\n): Cookbook {\n const next: CookbookTheme = { ...(doc.theme ?? {}) };\n if (patch.preset) {\n next.preset = patch.preset;\n delete next.custom;\n }\n if (patch.primary) {\n next.custom = {\n primary: patch.primary.toLowerCase(),\n ...(doc.theme?.custom?.fontFamily\n ? { fontFamily: doc.theme.custom.fontFamily }\n : {}),\n };\n }\n if (patch.colorScheme) next.colorScheme = patch.colorScheme;\n const theme = compactTheme(next);\n const out = { ...doc };\n if (theme) out.theme = theme;\n else delete out.theme;\n return out;\n}\n\n// ---- validation ------------------------------------------------------------\n\n/**\n * Check a document against the catalog. Structural errors come from\n * `validateCookbook`; the rest need the catalog: unknown ids, unmet `requires`,\n * policy targets nothing covers, layout ids the menu does not have, theme\n * values. Errors mean the app would not build as written; warnings mean\n * something is carried but unused.\n */\nexport function diagnose(\n catalog: EngineCatalog,\n input: Cookbook,\n): Diagnostic[] {\n const out: Diagnostic[] = [];\n const add = (\n severity: Diagnostic['severity'],\n code: string,\n path: string,\n message: string,\n ) => out.push({ severity, code, path, message });\n\n const structural = validateCookbook(input);\n if (!structural.ok) {\n for (const message of structural.errors) {\n add('error', 'invalid_document', '', message);\n }\n return out;\n }\n for (const message of structural.warnings)\n add('warning', 'migrated', '', message);\n const doc = structural.cookbook;\n const byId = recipeMap(catalog);\n\n for (const [i, id] of doc.recipes.entries()) {\n if (!byId.has(id))\n add(\n 'error',\n 'unknown_recipe',\n `recipes[${i}]`,\n `Unknown recipe \"${id}\".`,\n );\n }\n const closure = new Set(withRequirements(doc.recipes, byId));\n for (const id of closure) {\n if (!doc.recipes.includes(id)) {\n add(\n 'error',\n 'missing_requirement',\n 'recipes',\n `A recipe needs \"${id}\", which is not listed.`,\n );\n }\n }\n for (const [i, id] of doc.features.entries()) {\n const model = findModel(catalog, id);\n if (!model)\n add('error', 'unknown_model', `features[${i}]`, `Unknown model \"${id}\".`);\n else if (model.exposed === false) {\n add(\n 'error',\n 'model_not_exposed',\n `features[${i}]`,\n `${id} cannot be added as a feature.`,\n );\n }\n }\n const covered = coveredModels(catalog, doc);\n for (const [i, row] of doc.policies.entries()) {\n const at = `policies[${i}]`;\n const model = findModel(catalog, row.objectRef);\n if (!model) {\n add(\n 'error',\n 'unknown_model',\n `${at}.objectRef`,\n `Unknown model \"${row.objectRef}\".`,\n );\n continue;\n }\n if (\n model.fields &&\n !model.fields.some((f) => f.name === row.fieldName && !f.system)\n ) {\n add(\n 'error',\n 'unknown_field',\n `${at}.fieldName`,\n `${model.name} has no field \"${row.fieldName}\".`,\n );\n }\n if (!covered.has(row.objectRef) && !isSettingRow(catalog, row)) {\n add(\n 'warning',\n 'policy_not_covered',\n at,\n `${model.name} is not in the app, so this row has no effect.`,\n );\n }\n }\n for (const ref of Object.keys(doc.exposure ?? {})) {\n if (!findModel(catalog, ref)) {\n add(\n 'error',\n 'unknown_model',\n `exposure.${ref}`,\n `Unknown model \"${ref}\".`,\n );\n }\n }\n const presets = catalog.themePresets ?? DEFAULT_THEME_PRESETS;\n if (doc.theme?.preset && !presets.includes(doc.theme.preset)) {\n add(\n 'error',\n 'unknown_preset',\n 'theme.preset',\n `Unknown theme preset \"${doc.theme.preset}\".`,\n );\n }\n if (doc.layout) {\n const nav = buildNav(catalog, { ...doc, layout: undefined });\n const ids = new Set([\n ...nav.flatMap((s) => [s.id, ...s.items.map((i) => i.id)]),\n ...(doc.layout.customSections ?? []).map((c) => c.id),\n ]);\n const refs: [string, string][] = [\n ...(doc.layout.hidden ?? []).map((id, i): [string, string] => [\n `layout.hidden[${i}]`,\n id,\n ]),\n ...Object.keys(doc.layout.sections ?? {}).map((id): [string, string] => [\n `layout.sections.${id}`,\n id,\n ]),\n ...Object.keys(doc.layout.items ?? {}).map((id): [string, string] => [\n `layout.items.${id}`,\n id,\n ]),\n ...(doc.layout.sectionOrder ?? []).map((id, i): [string, string] => [\n `layout.sectionOrder[${i}]`,\n id,\n ]),\n ];\n for (const [path, id] of refs) {\n if (!ids.has(id)) {\n add(\n 'warning',\n 'unknown_layout_id',\n path,\n `The menu has no section or entry \"${id}\".`,\n );\n }\n }\n }\n return out;\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { type PlanState } from './commands.js';
|
|
2
|
+
import { clone } from './document.js';
|
|
3
|
+
import { type BatchResult, type CommandBatch, type CommandResult, type CommandTool, type EngineCatalog, type EngineState, type JsonSchema, type PlanSnapshot, type RunOptions } from './types.js';
|
|
4
|
+
export interface CookbookEngineOptions {
|
|
5
|
+
catalog: EngineCatalog;
|
|
6
|
+
/** Start from this document (strictly checked; the call throws if invalid). */
|
|
7
|
+
cookbook?: unknown;
|
|
8
|
+
/** Resume from a saved {@link EngineState} (wins over `cookbook`). */
|
|
9
|
+
state?: EngineState;
|
|
10
|
+
/** How many command ids are remembered for retries; default 500. */
|
|
11
|
+
maxJournal?: number;
|
|
12
|
+
/** How many undo entries are kept; default 20. */
|
|
13
|
+
maxUndo?: number;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* The cookbook command engine: typed, versioned commands over one cookbook
|
|
17
|
+
* document, held in plain objects. Never throws from `run`/`batch`; every
|
|
18
|
+
* refusal is a typed error and leaves the document untouched.
|
|
19
|
+
*/
|
|
20
|
+
export interface CookbookEngine {
|
|
21
|
+
/**
|
|
22
|
+
* Run one command (`{ name, input, id?, expectedRevision? }`). A repeated
|
|
23
|
+
* `id` returns the first result with `replayed: true` and applies nothing.
|
|
24
|
+
*/
|
|
25
|
+
run(command: unknown, options?: RunOptions): CommandResult;
|
|
26
|
+
/**
|
|
27
|
+
* Run several commands all-or-nothing. On any failure the state is exactly
|
|
28
|
+
* as before and the error names the failing command.
|
|
29
|
+
*/
|
|
30
|
+
batch(batch: CommandBatch | unknown): BatchResult;
|
|
31
|
+
/** The compact plan state, cheap enough for a model prompt. */
|
|
32
|
+
snapshot(): PlanSnapshot;
|
|
33
|
+
/** The document (a copy). */
|
|
34
|
+
cookbook(): ReturnType<typeof clone<PlanState['doc']>>;
|
|
35
|
+
/** Serializable state to persist and resume from, retries included. */
|
|
36
|
+
state(): EngineState;
|
|
37
|
+
/** Call `listener` with the snapshot now and after every change. */
|
|
38
|
+
subscribe(listener: (snapshot: PlanSnapshot) => void): () => void;
|
|
39
|
+
/** Command tool definitions (JSON Schema inputs), enums narrowed to the catalog. */
|
|
40
|
+
readonly tools: readonly CommandTool[];
|
|
41
|
+
/** The atomic-batch tool definition. */
|
|
42
|
+
readonly batchTool: {
|
|
43
|
+
name: 'run_batch';
|
|
44
|
+
description: string;
|
|
45
|
+
inputSchema: JsonSchema;
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
export declare function createCookbookEngine(options: CookbookEngineOptions): CookbookEngine;
|
|
49
|
+
//# sourceMappingURL=engine.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../../../src/cookbook/engine/engine.ts"],"names":[],"mappings":"AACA,OAAO,EAKL,KAAK,SAAS,EACf,MAAM,eAAe,CAAC;AAEvB,OAAO,EACL,KAAK,EAKN,MAAM,eAAe,CAAC;AASvB,OAAO,EACL,KAAK,WAAW,EAEhB,KAAK,YAAY,EAGjB,KAAK,aAAa,EAClB,KAAK,WAAW,EAChB,KAAK,aAAa,EAClB,KAAK,WAAW,EAEhB,KAAK,UAAU,EACf,KAAK,YAAY,EACjB,KAAK,UAAU,EAChB,MAAM,YAAY,CAAC;AAEpB,MAAM,WAAW,qBAAqB;IACpC,OAAO,EAAE,aAAa,CAAC;IACvB,+EAA+E;IAC/E,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,sEAAsE;IACtE,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,oEAAoE;IACpE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,kDAAkD;IAClD,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;;GAIG;AACH,MAAM,WAAW,cAAc;IAC7B;;;OAGG;IACH,GAAG,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,UAAU,GAAG,aAAa,CAAC;IAC3D;;;OAGG;IACH,KAAK,CAAC,KAAK,EAAE,YAAY,GAAG,OAAO,GAAG,WAAW,CAAC;IAClD,+DAA+D;IAC/D,QAAQ,IAAI,YAAY,CAAC;IACzB,6BAA6B;IAC7B,QAAQ,IAAI,UAAU,CAAC,OAAO,KAAK,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IACvD,uEAAuE;IACvE,KAAK,IAAI,WAAW,CAAC;IACrB,oEAAoE;IACpE,SAAS,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE,YAAY,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC;IAClE,oFAAoF;IACpF,QAAQ,CAAC,KAAK,EAAE,SAAS,WAAW,EAAE,CAAC;IACvC,wCAAwC;IACxC,QAAQ,CAAC,SAAS,EAAE;QAClB,IAAI,EAAE,WAAW,CAAC;QAClB,WAAW,EAAE,MAAM,CAAC;QACpB,WAAW,EAAE,UAAU,CAAC;KACzB,CAAC;CACH;AAsGD,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,qBAAqB,GAC7B,cAAc,CA8fhB"}
|