@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,399 @@
|
|
|
1
|
+
import { validateCookbook } from "../validate.js";
|
|
2
|
+
import "./defaults.js";
|
|
3
|
+
import { buildNav } from "./nav.js";
|
|
4
|
+
import { clone, describeTheme, emptyCookbook, readSettings, same } from "./document.js";
|
|
5
|
+
import { adopt, execute, libraryName } from "./commands.js";
|
|
6
|
+
import { buildBatchTool, buildCommandTools, checkSchema, commandSchemas } from "./schemas.js";
|
|
7
|
+
import "./types.js";
|
|
8
|
+
//#region src/cookbook/engine/engine.ts
|
|
9
|
+
var err = (code, message, extra = {}) => ({
|
|
10
|
+
code,
|
|
11
|
+
message,
|
|
12
|
+
...extra
|
|
13
|
+
});
|
|
14
|
+
/** Key order never changes a payload's identity: `{a, b}` and `{b, a}` match. */
|
|
15
|
+
var canonical = (value) => {
|
|
16
|
+
if (Array.isArray(value)) return value.map(canonical);
|
|
17
|
+
if (value && typeof value === "object") return Object.fromEntries(Object.keys(value).sort().map((key) => [key, canonical(value[key])]));
|
|
18
|
+
return value;
|
|
19
|
+
};
|
|
20
|
+
var fingerprint = (value) => {
|
|
21
|
+
try {
|
|
22
|
+
return JSON.stringify(canonical(value)) ?? "undefined";
|
|
23
|
+
} catch {
|
|
24
|
+
return "unserializable";
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
function readCommand(value, schemas, extraKeys) {
|
|
28
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return {
|
|
29
|
+
ok: false,
|
|
30
|
+
error: err("unknown_command", "A command is an object: { name, input }.")
|
|
31
|
+
};
|
|
32
|
+
const record = value;
|
|
33
|
+
const { name, input = {} } = record;
|
|
34
|
+
if (typeof name !== "string" || !Object.hasOwn(schemas, name)) return {
|
|
35
|
+
ok: false,
|
|
36
|
+
error: err("unknown_command", `Unknown command ${JSON.stringify(name)}.`)
|
|
37
|
+
};
|
|
38
|
+
for (const key of Object.keys(record)) if (key !== "name" && key !== "input" && !extraKeys.includes(key)) return {
|
|
39
|
+
ok: false,
|
|
40
|
+
error: err("invalid_input", `${key} is not part of a command.`, { path: key })
|
|
41
|
+
};
|
|
42
|
+
const problem = checkSchema(schemas[name], input);
|
|
43
|
+
if (problem) return {
|
|
44
|
+
ok: false,
|
|
45
|
+
error: err("invalid_input", problem.message, { path: problem.path })
|
|
46
|
+
};
|
|
47
|
+
return {
|
|
48
|
+
ok: true,
|
|
49
|
+
name,
|
|
50
|
+
input
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
var checkId = (id) => id === void 0 || typeof id === "string" && id.length > 0 && id.length <= 200 ? null : err("invalid_input", "id must be a non-empty string of at most 200 characters.", { path: "id" });
|
|
54
|
+
var checkRevision = (value) => value === void 0 || Number.isInteger(value) && value >= 0 ? null : err("invalid_input", "expectedRevision must be a whole number.", { path: "expectedRevision" });
|
|
55
|
+
function createCookbookEngine(options) {
|
|
56
|
+
const { catalog } = options;
|
|
57
|
+
const schemas = commandSchemas(catalog);
|
|
58
|
+
const tools = buildCommandTools(catalog);
|
|
59
|
+
const batchTool = buildBatchTool(catalog);
|
|
60
|
+
const maxJournal = options.maxJournal ?? 500;
|
|
61
|
+
const maxUndo = options.maxUndo ?? 20;
|
|
62
|
+
let current;
|
|
63
|
+
let revision = 0;
|
|
64
|
+
const journal = /* @__PURE__ */ new Map();
|
|
65
|
+
if (options.state) {
|
|
66
|
+
const saved = options.state;
|
|
67
|
+
const checked = validateCookbook(saved.cookbook);
|
|
68
|
+
if (!checked.ok) throw new Error(`Invalid saved cookbook: ${checked.errors.join("; ")}`);
|
|
69
|
+
if (!Number.isInteger(saved.revision) || saved.revision < 0) throw new Error("Invalid saved revision.");
|
|
70
|
+
current = {
|
|
71
|
+
doc: adopt(catalog, checked.cookbook),
|
|
72
|
+
applied: saved.applied ?? null
|
|
73
|
+
};
|
|
74
|
+
revision = saved.revision;
|
|
75
|
+
for (const entry of saved.journal ?? []) journal.set(entry.id, clone(entry));
|
|
76
|
+
} else if (options.cookbook !== void 0) {
|
|
77
|
+
const checked = validateCookbook(options.cookbook);
|
|
78
|
+
if (!checked.ok) throw new Error(`Invalid cookbook: ${checked.errors.join("; ")}`);
|
|
79
|
+
current = {
|
|
80
|
+
doc: adopt(catalog, checked.cookbook),
|
|
81
|
+
applied: null
|
|
82
|
+
};
|
|
83
|
+
} else current = {
|
|
84
|
+
doc: adopt(catalog, emptyCookbook()),
|
|
85
|
+
applied: null
|
|
86
|
+
};
|
|
87
|
+
const undos = /* @__PURE__ */ new Map();
|
|
88
|
+
let undoIds = [];
|
|
89
|
+
let undoCounter = 0;
|
|
90
|
+
const listeners = /* @__PURE__ */ new Map();
|
|
91
|
+
function snapshotOf(state, rev) {
|
|
92
|
+
const { doc } = state;
|
|
93
|
+
const byId = new Map(catalog.recipes.map((r) => [r.id, r]));
|
|
94
|
+
const settings = readSettings(catalog, doc);
|
|
95
|
+
const exposed = new Set(catalog.models.filter((m) => m.exposed !== false).map((m) => m.id));
|
|
96
|
+
return {
|
|
97
|
+
version: 1,
|
|
98
|
+
revision: rev,
|
|
99
|
+
app: {
|
|
100
|
+
name: doc.name ?? libraryName(catalog, state.applied) ?? "my-app",
|
|
101
|
+
description: doc.description ?? null,
|
|
102
|
+
cookbook: state.applied
|
|
103
|
+
},
|
|
104
|
+
recipes: doc.recipes.flatMap((id) => {
|
|
105
|
+
const recipe = byId.get(id);
|
|
106
|
+
return recipe ? [{
|
|
107
|
+
id,
|
|
108
|
+
label: recipe.label
|
|
109
|
+
}] : [];
|
|
110
|
+
}),
|
|
111
|
+
features: doc.features.filter((id) => exposed.has(id)),
|
|
112
|
+
unavailable: [...doc.recipes.filter((id) => !byId.has(id)), ...doc.features.filter((id) => !exposed.has(id))],
|
|
113
|
+
settings: {
|
|
114
|
+
currency: settings.currency,
|
|
115
|
+
taxRate: Number((settings.taxRate * 100).toFixed(4)),
|
|
116
|
+
paymentTerms: settings.paymentTerms
|
|
117
|
+
},
|
|
118
|
+
theme: {
|
|
119
|
+
text: describeTheme(doc.theme),
|
|
120
|
+
preset: doc.theme?.preset ?? null,
|
|
121
|
+
primary: doc.theme?.custom?.primary ?? null,
|
|
122
|
+
colorScheme: doc.theme?.colorScheme ?? "system"
|
|
123
|
+
},
|
|
124
|
+
sections: buildNav(catalog, doc).map((s) => ({
|
|
125
|
+
id: s.id,
|
|
126
|
+
label: s.label,
|
|
127
|
+
hidden: s.hidden,
|
|
128
|
+
items: s.items.map((i) => ({
|
|
129
|
+
id: i.id,
|
|
130
|
+
label: i.label,
|
|
131
|
+
hidden: i.hidden
|
|
132
|
+
}))
|
|
133
|
+
})),
|
|
134
|
+
policies: doc.policies.length,
|
|
135
|
+
undo: [...undoIds]
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
const snapshot = () => snapshotOf(current, revision);
|
|
139
|
+
function notify() {
|
|
140
|
+
for (const [listener, last] of listeners) {
|
|
141
|
+
if (last === revision) continue;
|
|
142
|
+
listeners.set(listener, revision);
|
|
143
|
+
listener(snapshot());
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
function remember(id, print, result) {
|
|
147
|
+
if (id === void 0) return;
|
|
148
|
+
journal.set(id, {
|
|
149
|
+
id,
|
|
150
|
+
fingerprint: print,
|
|
151
|
+
result: clone(result)
|
|
152
|
+
});
|
|
153
|
+
while (journal.size > maxJournal) {
|
|
154
|
+
const oldest = journal.keys().next().value;
|
|
155
|
+
if (oldest === void 0) break;
|
|
156
|
+
journal.delete(oldest);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
function replay(id, print) {
|
|
160
|
+
if (id === void 0) return null;
|
|
161
|
+
const hit = journal.get(id);
|
|
162
|
+
if (!hit) return null;
|
|
163
|
+
if (hit.fingerprint !== print) return {
|
|
164
|
+
ok: false,
|
|
165
|
+
id,
|
|
166
|
+
error: err("id_reuse", `The id "${id}" was already used for a different command.`, { path: "id" })
|
|
167
|
+
};
|
|
168
|
+
return {
|
|
169
|
+
...clone(hit.result),
|
|
170
|
+
replayed: true
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
function recordUndo(before, after) {
|
|
174
|
+
const undoId = `undo-${++undoCounter}`;
|
|
175
|
+
undos.set(undoId, {
|
|
176
|
+
before: clone(before),
|
|
177
|
+
after: clone(after)
|
|
178
|
+
});
|
|
179
|
+
undoIds = [...undoIds, undoId].slice(-maxUndo);
|
|
180
|
+
for (const key of [...undos.keys()]) if (!undoIds.includes(key)) undos.delete(key);
|
|
181
|
+
return undoId;
|
|
182
|
+
}
|
|
183
|
+
const changedBetween = (a, b) => a.applied !== b.applied || !same(a.doc, b.doc);
|
|
184
|
+
function toSuccess(id, name, outcome, revisionBefore, revisionAfter, snap, undoId) {
|
|
185
|
+
return {
|
|
186
|
+
ok: true,
|
|
187
|
+
...id !== void 0 ? { id } : {},
|
|
188
|
+
snapshot: snap,
|
|
189
|
+
receipt: {
|
|
190
|
+
name,
|
|
191
|
+
...id !== void 0 ? { id } : {},
|
|
192
|
+
summary: revisionAfter !== revisionBefore ? outcome.summary : "",
|
|
193
|
+
changed: revisionAfter !== revisionBefore,
|
|
194
|
+
revisionBefore,
|
|
195
|
+
revisionAfter,
|
|
196
|
+
...undoId ? { undoId } : {},
|
|
197
|
+
...outcome.changes ? { changes: outcome.changes } : {},
|
|
198
|
+
...outcome.warnings ? { warnings: outcome.warnings } : {}
|
|
199
|
+
},
|
|
200
|
+
...outcome.data !== void 0 ? { data: outcome.data } : {}
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
function runUndo(id, input) {
|
|
204
|
+
const entry = undos.get(input.undoId);
|
|
205
|
+
if (!entry) return {
|
|
206
|
+
ok: false,
|
|
207
|
+
...id !== void 0 ? { id } : {},
|
|
208
|
+
error: err("not_found", `Nothing to undo for "${input.undoId}".`, { path: "input.undoId" })
|
|
209
|
+
};
|
|
210
|
+
if (!input.force && changedBetween(current, entry.after)) return {
|
|
211
|
+
ok: false,
|
|
212
|
+
...id !== void 0 ? { id } : {},
|
|
213
|
+
error: err("conflict", "The plan changed since; send force: true to undo anyway.", { details: { currentRevision: revision } })
|
|
214
|
+
};
|
|
215
|
+
const before = revision;
|
|
216
|
+
const restored = clone(entry.before);
|
|
217
|
+
const changed = changedBetween(current, restored);
|
|
218
|
+
current = restored;
|
|
219
|
+
if (changed) revision += 1;
|
|
220
|
+
undos.delete(input.undoId);
|
|
221
|
+
undoIds = undoIds.filter((u) => u !== input.undoId);
|
|
222
|
+
const result = toSuccess(id, "undo", {
|
|
223
|
+
ok: true,
|
|
224
|
+
state: current,
|
|
225
|
+
summary: "Undone."
|
|
226
|
+
}, before, revision, snapshot());
|
|
227
|
+
notify();
|
|
228
|
+
return result;
|
|
229
|
+
}
|
|
230
|
+
function run(command, runOptions = {}) {
|
|
231
|
+
try {
|
|
232
|
+
const raw = command && typeof command === "object" && !Array.isArray(command) ? command : void 0;
|
|
233
|
+
const id = raw?.id;
|
|
234
|
+
const idProblem = checkId(id);
|
|
235
|
+
if (idProblem) return {
|
|
236
|
+
ok: false,
|
|
237
|
+
error: idProblem
|
|
238
|
+
};
|
|
239
|
+
const expected = raw?.expectedRevision ?? runOptions.expectedRevision;
|
|
240
|
+
const revProblem = checkRevision(expected);
|
|
241
|
+
if (revProblem) return {
|
|
242
|
+
ok: false,
|
|
243
|
+
...id !== void 0 ? { id } : {},
|
|
244
|
+
error: revProblem
|
|
245
|
+
};
|
|
246
|
+
const print = fingerprint({
|
|
247
|
+
name: raw?.name,
|
|
248
|
+
input: raw?.input ?? {},
|
|
249
|
+
expectedRevision: expected
|
|
250
|
+
});
|
|
251
|
+
const replayed = replay(id, print);
|
|
252
|
+
if (replayed) return replayed;
|
|
253
|
+
const finish = (result) => {
|
|
254
|
+
remember(id, print, result);
|
|
255
|
+
return result;
|
|
256
|
+
};
|
|
257
|
+
const withId = (error) => ({
|
|
258
|
+
ok: false,
|
|
259
|
+
...id !== void 0 ? { id } : {},
|
|
260
|
+
error
|
|
261
|
+
});
|
|
262
|
+
const parsed = readCommand(command, schemas, ["id", "expectedRevision"]);
|
|
263
|
+
if (!parsed.ok) return finish(withId(parsed.error));
|
|
264
|
+
if (expected !== void 0 && expected !== revision) return finish(withId(err("conflict", `The plan is at revision ${revision}, not ${expected}. Read the snapshot and try again.`, { details: {
|
|
265
|
+
expectedRevision: expected,
|
|
266
|
+
currentRevision: revision
|
|
267
|
+
} })));
|
|
268
|
+
if (parsed.name === "undo") return finish(runUndo(id, parsed.input));
|
|
269
|
+
const before = current;
|
|
270
|
+
const outcome = execute(catalog, before, parsed.name, parsed.input);
|
|
271
|
+
if (!outcome.ok) return finish(withId(outcome.error));
|
|
272
|
+
const revisionBefore = revision;
|
|
273
|
+
const changed = changedBetween(before, outcome.state);
|
|
274
|
+
let undoId;
|
|
275
|
+
if (changed) {
|
|
276
|
+
current = outcome.state;
|
|
277
|
+
revision += 1;
|
|
278
|
+
undoId = recordUndo(before, outcome.state);
|
|
279
|
+
}
|
|
280
|
+
const result = finish(toSuccess(id, parsed.name, outcome, revisionBefore, revision, snapshot(), undoId));
|
|
281
|
+
notify();
|
|
282
|
+
return result;
|
|
283
|
+
} catch (cause) {
|
|
284
|
+
return {
|
|
285
|
+
ok: false,
|
|
286
|
+
error: err("failed", cause instanceof Error ? cause.message : String(cause))
|
|
287
|
+
};
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
function batch(input) {
|
|
291
|
+
const unchanged = (error, id) => ({
|
|
292
|
+
ok: false,
|
|
293
|
+
...id !== void 0 ? { id } : {},
|
|
294
|
+
error,
|
|
295
|
+
snapshot: snapshot()
|
|
296
|
+
});
|
|
297
|
+
try {
|
|
298
|
+
if (!input || typeof input !== "object" || Array.isArray(input)) return unchanged(err("invalid_input", "A batch is an object: { commands }."));
|
|
299
|
+
const raw = input;
|
|
300
|
+
const id = raw.id;
|
|
301
|
+
const idProblem = checkId(id);
|
|
302
|
+
if (idProblem) return unchanged(idProblem);
|
|
303
|
+
const revProblem = checkRevision(raw.expectedRevision);
|
|
304
|
+
if (revProblem) return unchanged(revProblem, id);
|
|
305
|
+
const print = fingerprint({
|
|
306
|
+
commands: raw.commands,
|
|
307
|
+
expectedRevision: raw.expectedRevision
|
|
308
|
+
});
|
|
309
|
+
const replayed = replay(id, print);
|
|
310
|
+
if (replayed) return "results" in replayed || "snapshot" in replayed ? replayed : unchanged(replayed.error, id);
|
|
311
|
+
const finish = (result) => {
|
|
312
|
+
remember(id, print, result);
|
|
313
|
+
return result;
|
|
314
|
+
};
|
|
315
|
+
const commands = raw.commands;
|
|
316
|
+
if (!Array.isArray(commands) || commands.length === 0 || commands.length > 50) return finish(unchanged(err("invalid_input", "commands must be a list of 1 to 50 commands.", { path: "commands" }), id));
|
|
317
|
+
const expected = raw.expectedRevision;
|
|
318
|
+
if (expected !== void 0 && expected !== revision) return finish(unchanged(err("conflict", `The plan is at revision ${revision}, not ${expected}. Read the snapshot and try again.`, { details: {
|
|
319
|
+
expectedRevision: expected,
|
|
320
|
+
currentRevision: revision
|
|
321
|
+
} }), id));
|
|
322
|
+
const failAt = (index, name, cause) => finish(unchanged(err("batch_failed", `Command ${index + 1} (${String(name)}) failed: ${cause.message}`, {
|
|
323
|
+
path: `commands[${index}]`,
|
|
324
|
+
details: {
|
|
325
|
+
index,
|
|
326
|
+
cause
|
|
327
|
+
}
|
|
328
|
+
}), id));
|
|
329
|
+
const base = current;
|
|
330
|
+
const baseRevision = revision;
|
|
331
|
+
let working = base;
|
|
332
|
+
let rev = baseRevision;
|
|
333
|
+
const results = [];
|
|
334
|
+
for (const [index, command] of commands.entries()) {
|
|
335
|
+
const parsed = readCommand(command, schemas, []);
|
|
336
|
+
if (!parsed.ok) return failAt(index, command?.name, parsed.error);
|
|
337
|
+
if (parsed.name === "undo") return failAt(index, "undo", err("invalid_input", "undo cannot run inside a batch."));
|
|
338
|
+
const outcome = execute(catalog, working, parsed.name, parsed.input);
|
|
339
|
+
if (!outcome.ok) return failAt(index, parsed.name, outcome.error);
|
|
340
|
+
const before = rev;
|
|
341
|
+
if (changedBetween(working, outcome.state)) rev += 1;
|
|
342
|
+
working = outcome.state;
|
|
343
|
+
results.push(toSuccess(void 0, parsed.name, outcome, before, rev, snapshotOf(working, rev)));
|
|
344
|
+
}
|
|
345
|
+
const changed = rev !== baseRevision;
|
|
346
|
+
let undoId;
|
|
347
|
+
if (changed) {
|
|
348
|
+
current = working;
|
|
349
|
+
revision = rev;
|
|
350
|
+
undoId = recordUndo(base, working);
|
|
351
|
+
for (const r of results) if (r.receipt.changed) delete r.receipt.undoId;
|
|
352
|
+
}
|
|
353
|
+
const result = finish({
|
|
354
|
+
ok: true,
|
|
355
|
+
...id !== void 0 ? { id } : {},
|
|
356
|
+
snapshot: snapshot(),
|
|
357
|
+
receipt: {
|
|
358
|
+
...id !== void 0 ? { id } : {},
|
|
359
|
+
count: results.length,
|
|
360
|
+
changed,
|
|
361
|
+
revisionBefore: baseRevision,
|
|
362
|
+
revisionAfter: rev,
|
|
363
|
+
...undoId ? { undoId } : {}
|
|
364
|
+
},
|
|
365
|
+
results
|
|
366
|
+
});
|
|
367
|
+
notify();
|
|
368
|
+
return result;
|
|
369
|
+
} catch (cause) {
|
|
370
|
+
return unchanged(err("failed", cause instanceof Error ? cause.message : String(cause)));
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
return {
|
|
374
|
+
run,
|
|
375
|
+
batch,
|
|
376
|
+
snapshot,
|
|
377
|
+
cookbook: () => clone(current.doc),
|
|
378
|
+
state: () => ({
|
|
379
|
+
version: 1,
|
|
380
|
+
revision,
|
|
381
|
+
applied: current.applied,
|
|
382
|
+
cookbook: clone(current.doc),
|
|
383
|
+
journal: [...journal.values()].map((entry) => clone(entry))
|
|
384
|
+
}),
|
|
385
|
+
subscribe(listener) {
|
|
386
|
+
listeners.set(listener, revision);
|
|
387
|
+
listener(snapshot());
|
|
388
|
+
return () => {
|
|
389
|
+
listeners.delete(listener);
|
|
390
|
+
};
|
|
391
|
+
},
|
|
392
|
+
tools,
|
|
393
|
+
batchTool
|
|
394
|
+
};
|
|
395
|
+
}
|
|
396
|
+
//#endregion
|
|
397
|
+
export { createCookbookEngine };
|
|
398
|
+
|
|
399
|
+
//# sourceMappingURL=engine.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"engine.js","names":[],"sources":["../../../src/cookbook/engine/engine.ts"],"sourcesContent":["import { validateCookbook } from '../validate.js';\nimport {\n adopt,\n execute,\n libraryName,\n type Outcome,\n type PlanState,\n} from './commands.js';\nimport { DEFAULT_APP_NAME, DEFAULT_COLOR_SCHEME } from './defaults.js';\nimport {\n clone,\n describeTheme,\n emptyCookbook,\n readSettings,\n same,\n} from './document.js';\nimport { buildNav } from './nav.js';\nimport {\n buildBatchTool,\n buildCommandTools,\n type CommandSchemas,\n checkSchema,\n commandSchemas,\n} from './schemas.js';\nimport {\n type BatchResult,\n COOKBOOK_COMMANDS_VERSION,\n type CommandBatch,\n type CommandError,\n type CommandName,\n type CommandResult,\n type CommandTool,\n type EngineCatalog,\n type EngineState,\n type JournalEntry,\n type JsonSchema,\n type PlanSnapshot,\n type RunOptions,\n} from './types.js';\n\nexport interface CookbookEngineOptions {\n catalog: EngineCatalog;\n /** Start from this document (strictly checked; the call throws if invalid). */\n cookbook?: unknown;\n /** Resume from a saved {@link EngineState} (wins over `cookbook`). */\n state?: EngineState;\n /** How many command ids are remembered for retries; default 500. */\n maxJournal?: number;\n /** How many undo entries are kept; default 20. */\n maxUndo?: number;\n}\n\n/**\n * The cookbook command engine: typed, versioned commands over one cookbook\n * document, held in plain objects. Never throws from `run`/`batch`; every\n * refusal is a typed error and leaves the document untouched.\n */\nexport interface CookbookEngine {\n /**\n * Run one command (`{ name, input, id?, expectedRevision? }`). A repeated\n * `id` returns the first result with `replayed: true` and applies nothing.\n */\n run(command: unknown, options?: RunOptions): CommandResult;\n /**\n * Run several commands all-or-nothing. On any failure the state is exactly\n * as before and the error names the failing command.\n */\n batch(batch: CommandBatch | unknown): BatchResult;\n /** The compact plan state, cheap enough for a model prompt. */\n snapshot(): PlanSnapshot;\n /** The document (a copy). */\n cookbook(): ReturnType<typeof clone<PlanState['doc']>>;\n /** Serializable state to persist and resume from, retries included. */\n state(): EngineState;\n /** Call `listener` with the snapshot now and after every change. */\n subscribe(listener: (snapshot: PlanSnapshot) => void): () => void;\n /** Command tool definitions (JSON Schema inputs), enums narrowed to the catalog. */\n readonly tools: readonly CommandTool[];\n /** The atomic-batch tool definition. */\n readonly batchTool: {\n name: 'run_batch';\n description: string;\n inputSchema: JsonSchema;\n };\n}\n\ninterface UndoEntry {\n before: PlanState;\n /** What the change left; undo is a conflict while the plan differs from it. */\n after: PlanState;\n}\n\nconst err = (\n code: CommandError['code'],\n message: string,\n extra: Pick<CommandError, 'path' | 'details'> = {},\n): CommandError => ({ code, message, ...extra });\n\n/** Key order never changes a payload's identity: `{a, b}` and `{b, a}` match. */\nconst canonical = (value: unknown): unknown => {\n if (Array.isArray(value)) return value.map(canonical);\n if (value && typeof value === 'object') {\n return Object.fromEntries(\n Object.keys(value)\n .sort()\n .map((key) => [\n key,\n canonical((value as Record<string, unknown>)[key]),\n ]),\n );\n }\n return value;\n};\n\nconst fingerprint = (value: unknown): string => {\n try {\n return JSON.stringify(canonical(value)) ?? 'undefined';\n } catch {\n return 'unserializable';\n }\n};\n\ntype Parsed =\n | { ok: true; name: CommandName; input: Record<string, unknown> }\n | { ok: false; error: CommandError };\n\nfunction readCommand(\n value: unknown,\n schemas: CommandSchemas,\n extraKeys: readonly string[],\n): Parsed {\n if (!value || typeof value !== 'object' || Array.isArray(value)) {\n return {\n ok: false,\n error: err('unknown_command', 'A command is an object: { name, input }.'),\n };\n }\n const record = value as Record<string, unknown>;\n const { name, input = {} } = record;\n if (typeof name !== 'string' || !Object.hasOwn(schemas, name)) {\n return {\n ok: false,\n error: err('unknown_command', `Unknown command ${JSON.stringify(name)}.`),\n };\n }\n for (const key of Object.keys(record)) {\n if (key !== 'name' && key !== 'input' && !extraKeys.includes(key)) {\n return {\n ok: false,\n error: err('invalid_input', `${key} is not part of a command.`, {\n path: key,\n }),\n };\n }\n }\n const problem = checkSchema(schemas[name as CommandName], input);\n if (problem) {\n return {\n ok: false,\n error: err('invalid_input', problem.message, { path: problem.path }),\n };\n }\n return {\n ok: true,\n name: name as CommandName,\n input: input as Record<string, unknown>,\n };\n}\n\nconst checkId = (id: unknown): CommandError | null =>\n id === undefined ||\n (typeof id === 'string' && id.length > 0 && id.length <= 200)\n ? null\n : err(\n 'invalid_input',\n 'id must be a non-empty string of at most 200 characters.',\n { path: 'id' },\n );\n\nconst checkRevision = (value: unknown): CommandError | null =>\n value === undefined || (Number.isInteger(value) && (value as number) >= 0)\n ? null\n : err('invalid_input', 'expectedRevision must be a whole number.', {\n path: 'expectedRevision',\n });\n\nexport function createCookbookEngine(\n options: CookbookEngineOptions,\n): CookbookEngine {\n const { catalog } = options;\n const schemas = commandSchemas(catalog);\n const tools = buildCommandTools(catalog);\n const batchTool = buildBatchTool(catalog);\n const maxJournal = options.maxJournal ?? 500;\n const maxUndo = options.maxUndo ?? 20;\n\n let current: PlanState;\n let revision = 0;\n const journal = new Map<string, JournalEntry>();\n\n if (options.state) {\n const saved = options.state;\n const checked = validateCookbook(saved.cookbook);\n if (!checked.ok)\n throw new Error(`Invalid saved cookbook: ${checked.errors.join('; ')}`);\n if (!Number.isInteger(saved.revision) || saved.revision < 0) {\n throw new Error('Invalid saved revision.');\n }\n current = {\n doc: adopt(catalog, checked.cookbook),\n applied: saved.applied ?? null,\n };\n revision = saved.revision;\n for (const entry of saved.journal ?? [])\n journal.set(entry.id, clone(entry));\n } else if (options.cookbook !== undefined) {\n const checked = validateCookbook(options.cookbook);\n if (!checked.ok)\n throw new Error(`Invalid cookbook: ${checked.errors.join('; ')}`);\n current = { doc: adopt(catalog, checked.cookbook), applied: null };\n } else {\n current = { doc: adopt(catalog, emptyCookbook()), applied: null };\n }\n\n const undos = new Map<string, UndoEntry>();\n let undoIds: string[] = [];\n let undoCounter = 0;\n const listeners = new Map<(s: PlanSnapshot) => void, number>();\n\n function snapshotOf(state: PlanState, rev: number): PlanSnapshot {\n const { doc } = state;\n const byId = new Map(catalog.recipes.map((r) => [r.id, r]));\n const settings = readSettings(catalog, doc);\n const exposed = new Set(\n catalog.models.filter((m) => m.exposed !== false).map((m) => m.id),\n );\n return {\n version: COOKBOOK_COMMANDS_VERSION,\n revision: rev,\n app: {\n name:\n doc.name ?? libraryName(catalog, state.applied) ?? DEFAULT_APP_NAME,\n description: doc.description ?? null,\n cookbook: state.applied,\n },\n recipes: doc.recipes.flatMap((id) => {\n const recipe = byId.get(id);\n return recipe ? [{ id, label: recipe.label }] : [];\n }),\n features: doc.features.filter((id) => exposed.has(id)),\n unavailable: [\n ...doc.recipes.filter((id) => !byId.has(id)),\n ...doc.features.filter((id) => !exposed.has(id)),\n ],\n settings: {\n currency: settings.currency,\n taxRate: Number((settings.taxRate * 100).toFixed(4)),\n paymentTerms: settings.paymentTerms,\n },\n theme: {\n text: describeTheme(doc.theme),\n preset: doc.theme?.preset ?? null,\n primary: doc.theme?.custom?.primary ?? null,\n colorScheme: doc.theme?.colorScheme ?? DEFAULT_COLOR_SCHEME,\n },\n sections: buildNav(catalog, doc).map((s) => ({\n id: s.id,\n label: s.label,\n hidden: s.hidden,\n items: s.items.map((i) => ({\n id: i.id,\n label: i.label,\n hidden: i.hidden,\n })),\n })),\n policies: doc.policies.length,\n undo: [...undoIds],\n };\n }\n\n const snapshot = () => snapshotOf(current, revision);\n\n function notify(): void {\n for (const [listener, last] of listeners) {\n if (last === revision) continue;\n listeners.set(listener, revision);\n listener(snapshot());\n }\n }\n\n function remember(\n id: string | undefined,\n print: string,\n result: CommandResult | BatchResult,\n ) {\n if (id === undefined) return;\n journal.set(id, { id, fingerprint: print, result: clone(result) });\n while (journal.size > maxJournal) {\n const oldest = journal.keys().next().value;\n if (oldest === undefined) break;\n journal.delete(oldest);\n }\n }\n\n function replay<R extends CommandResult | BatchResult>(\n id: string | undefined,\n print: string,\n ): R | CommandResult | null {\n if (id === undefined) return null;\n const hit = journal.get(id);\n if (!hit) return null;\n if (hit.fingerprint !== print) {\n return {\n ok: false,\n id,\n error: err(\n 'id_reuse',\n `The id \"${id}\" was already used for a different command.`,\n {\n path: 'id',\n },\n ),\n };\n }\n return { ...(clone(hit.result) as R), replayed: true };\n }\n\n function recordUndo(before: PlanState, after: PlanState): string {\n const undoId = `undo-${++undoCounter}`;\n undos.set(undoId, { before: clone(before), after: clone(after) });\n undoIds = [...undoIds, undoId].slice(-maxUndo);\n for (const key of [...undos.keys()])\n if (!undoIds.includes(key)) undos.delete(key);\n return undoId;\n }\n\n const changedBetween = (a: PlanState, b: PlanState) =>\n a.applied !== b.applied || !same(a.doc, b.doc);\n\n function toSuccess(\n id: string | undefined,\n name: CommandName,\n outcome: Extract<Outcome, { ok: true }>,\n revisionBefore: number,\n revisionAfter: number,\n snap: PlanSnapshot,\n undoId?: string,\n ): Extract<CommandResult, { ok: true }> {\n return {\n ok: true,\n ...(id !== undefined ? { id } : {}),\n snapshot: snap,\n receipt: {\n name,\n ...(id !== undefined ? { id } : {}),\n summary: revisionAfter !== revisionBefore ? outcome.summary : '',\n changed: revisionAfter !== revisionBefore,\n revisionBefore,\n revisionAfter,\n ...(undoId ? { undoId } : {}),\n ...(outcome.changes ? { changes: outcome.changes } : {}),\n ...(outcome.warnings ? { warnings: outcome.warnings } : {}),\n },\n ...(outcome.data !== undefined ? { data: outcome.data } : {}),\n };\n }\n\n function runUndo(\n id: string | undefined,\n input: { undoId: string; force?: boolean },\n ): CommandResult {\n const entry = undos.get(input.undoId);\n if (!entry) {\n return {\n ok: false,\n ...(id !== undefined ? { id } : {}),\n error: err('not_found', `Nothing to undo for \"${input.undoId}\".`, {\n path: 'input.undoId',\n }),\n };\n }\n if (!input.force && changedBetween(current, entry.after)) {\n return {\n ok: false,\n ...(id !== undefined ? { id } : {}),\n error: err(\n 'conflict',\n 'The plan changed since; send force: true to undo anyway.',\n {\n details: { currentRevision: revision },\n },\n ),\n };\n }\n const before = revision;\n const restored = clone(entry.before);\n const changed = changedBetween(current, restored);\n current = restored;\n if (changed) revision += 1;\n undos.delete(input.undoId);\n undoIds = undoIds.filter((u) => u !== input.undoId);\n const result = toSuccess(\n id,\n 'undo',\n { ok: true, state: current, summary: 'Undone.' },\n before,\n revision,\n snapshot(),\n );\n notify();\n return result;\n }\n\n function run(command: unknown, runOptions: RunOptions = {}): CommandResult {\n try {\n const raw =\n command && typeof command === 'object' && !Array.isArray(command)\n ? (command as Record<string, unknown>)\n : undefined;\n const id = raw?.id as string | undefined;\n const idProblem = checkId(id);\n if (idProblem) return { ok: false, error: idProblem };\n const expected = (raw?.expectedRevision ?? runOptions.expectedRevision) as\n | number\n | undefined;\n const revProblem = checkRevision(expected);\n if (revProblem)\n return {\n ok: false,\n ...(id !== undefined ? { id } : {}),\n error: revProblem,\n };\n\n const print = fingerprint({\n name: raw?.name,\n input: raw?.input ?? {},\n expectedRevision: expected,\n });\n const replayed = replay<CommandResult>(id, print);\n if (replayed) return replayed as CommandResult;\n\n const finish = (result: CommandResult) => {\n remember(id, print, result);\n return result;\n };\n const withId = (error: CommandError): CommandResult => ({\n ok: false,\n ...(id !== undefined ? { id } : {}),\n error,\n });\n\n const parsed = readCommand(command, schemas, ['id', 'expectedRevision']);\n if (!parsed.ok) return finish(withId(parsed.error));\n if (expected !== undefined && expected !== revision) {\n return finish(\n withId(\n err(\n 'conflict',\n `The plan is at revision ${revision}, not ${expected}. Read the snapshot and try again.`,\n {\n details: {\n expectedRevision: expected,\n currentRevision: revision,\n },\n },\n ),\n ),\n );\n }\n if (parsed.name === 'undo') {\n return finish(\n runUndo(id, parsed.input as { undoId: string; force?: boolean }),\n );\n }\n const before = current;\n const outcome = execute(\n catalog,\n before,\n parsed.name,\n parsed.input as never,\n );\n if (!outcome.ok) return finish(withId(outcome.error));\n const revisionBefore = revision;\n const changed = changedBetween(before, outcome.state);\n let undoId: string | undefined;\n if (changed) {\n current = outcome.state;\n revision += 1;\n undoId = recordUndo(before, outcome.state);\n }\n const result = finish(\n toSuccess(\n id,\n parsed.name,\n outcome,\n revisionBefore,\n revision,\n snapshot(),\n undoId,\n ),\n );\n notify();\n return result;\n } catch (cause) {\n return {\n ok: false,\n error: err(\n 'failed',\n cause instanceof Error ? cause.message : String(cause),\n ),\n };\n }\n }\n\n function batch(input: CommandBatch | unknown): BatchResult {\n const unchanged = (error: CommandError, id?: string): BatchResult => ({\n ok: false,\n ...(id !== undefined ? { id } : {}),\n error,\n snapshot: snapshot(),\n });\n try {\n if (!input || typeof input !== 'object' || Array.isArray(input)) {\n return unchanged(\n err('invalid_input', 'A batch is an object: { commands }.'),\n );\n }\n const raw = input as Record<string, unknown>;\n const id = raw.id as string | undefined;\n const idProblem = checkId(id);\n if (idProblem) return unchanged(idProblem);\n const revProblem = checkRevision(raw.expectedRevision);\n if (revProblem) return unchanged(revProblem, id);\n const print = fingerprint({\n commands: raw.commands,\n expectedRevision: raw.expectedRevision,\n });\n const replayed = replay<BatchResult>(id, print);\n if (replayed) {\n return 'results' in replayed || 'snapshot' in replayed\n ? (replayed as BatchResult)\n : unchanged(\n (replayed as Extract<CommandResult, { ok: false }>).error,\n id,\n );\n }\n const finish = (result: BatchResult) => {\n remember(id, print, result);\n return result;\n };\n\n const commands = raw.commands;\n if (\n !Array.isArray(commands) ||\n commands.length === 0 ||\n commands.length > 50\n ) {\n return finish(\n unchanged(\n err(\n 'invalid_input',\n 'commands must be a list of 1 to 50 commands.',\n { path: 'commands' },\n ),\n id,\n ),\n );\n }\n const expected = raw.expectedRevision as number | undefined;\n if (expected !== undefined && expected !== revision) {\n return finish(\n unchanged(\n err(\n 'conflict',\n `The plan is at revision ${revision}, not ${expected}. Read the snapshot and try again.`,\n {\n details: {\n expectedRevision: expected,\n currentRevision: revision,\n },\n },\n ),\n id,\n ),\n );\n }\n\n const failAt = (index: number, name: unknown, cause: CommandError) =>\n finish(\n unchanged(\n err(\n 'batch_failed',\n `Command ${index + 1} (${String(name)}) failed: ${cause.message}`,\n {\n path: `commands[${index}]`,\n details: { index, cause },\n },\n ),\n id,\n ),\n );\n\n // Everything runs on a working copy; the live state is replaced once, at the end.\n const base = current;\n const baseRevision = revision;\n let working = base;\n let rev = baseRevision;\n const results: Extract<CommandResult, { ok: true }>[] = [];\n for (const [index, command] of commands.entries()) {\n const parsed = readCommand(command, schemas, []);\n if (!parsed.ok)\n return failAt(\n index,\n (command as { name?: unknown })?.name,\n parsed.error,\n );\n if (parsed.name === 'undo') {\n return failAt(\n index,\n 'undo',\n err('invalid_input', 'undo cannot run inside a batch.'),\n );\n }\n const outcome = execute(\n catalog,\n working,\n parsed.name,\n parsed.input as never,\n );\n if (!outcome.ok) return failAt(index, parsed.name, outcome.error);\n const before = rev;\n if (changedBetween(working, outcome.state)) rev += 1;\n working = outcome.state;\n results.push(\n toSuccess(\n undefined,\n parsed.name,\n outcome,\n before,\n rev,\n snapshotOf(working, rev),\n ),\n );\n }\n const changed = rev !== baseRevision;\n let undoId: string | undefined;\n if (changed) {\n current = working;\n revision = rev;\n undoId = recordUndo(base, working);\n // The batch's one undo restores the state before all of it.\n for (const r of results) if (r.receipt.changed) delete r.receipt.undoId;\n }\n const result = finish({\n ok: true,\n ...(id !== undefined ? { id } : {}),\n snapshot: snapshot(),\n receipt: {\n ...(id !== undefined ? { id } : {}),\n count: results.length,\n changed,\n revisionBefore: baseRevision,\n revisionAfter: rev,\n ...(undoId ? { undoId } : {}),\n },\n results,\n });\n notify();\n return result;\n } catch (cause) {\n return unchanged(\n err('failed', cause instanceof Error ? cause.message : String(cause)),\n );\n }\n }\n\n return {\n run: run as CookbookEngine['run'],\n batch,\n snapshot,\n cookbook: () => clone(current.doc),\n state: () => ({\n version: COOKBOOK_COMMANDS_VERSION,\n revision,\n applied: current.applied,\n cookbook: clone(current.doc),\n journal: [...journal.values()].map((entry) => clone(entry)),\n }),\n subscribe(listener) {\n listeners.set(listener, revision);\n listener(snapshot());\n return () => {\n listeners.delete(listener);\n };\n },\n tools,\n batchTool,\n };\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cookbook command engine (#3753): versioned typed commands, idempotent
|
|
3
|
+
* retries, atomic batches, revision conflicts, receipts and JSON-Schema tool
|
|
4
|
+
* definitions over one cookbook document. Browser- and Node-safe; see
|
|
5
|
+
* `agents/cookbook-engine.md`.
|
|
6
|
+
*/
|
|
7
|
+
export * from './commands.js';
|
|
8
|
+
export * from './defaults.js';
|
|
9
|
+
export { canonical, diagnose, isEmptyCookbook } from './document.js';
|
|
10
|
+
export * from './engine.js';
|
|
11
|
+
export { buildNav, navItemId } from './nav.js';
|
|
12
|
+
export * from './schemas.js';
|
|
13
|
+
export * from './types.js';
|
|
14
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/cookbook/engine/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,cAAc,eAAe,CAAC;AAC9B,cAAc,eAAe,CAAC;AAC9B,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AACrE,cAAc,aAAa,CAAC;AAC5B,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAC/C,cAAc,cAAc,CAAC;AAC7B,cAAc,YAAY,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { COMMERCE_SETTING_TARGETS, DEFAULT_APP_NAME, DEFAULT_COLOR_SCHEME, DEFAULT_PRESET, DEFAULT_THEME_PRESETS, MAX_TERMS_LENGTH } from "./defaults.js";
|
|
2
|
+
import { buildNav, navItemId } from "./nav.js";
|
|
3
|
+
import { canonical, diagnose, isEmptyCookbook } from "./document.js";
|
|
4
|
+
import { adopt, execute, exportFileName, fail, libraryName, serializeCookbook } from "./commands.js";
|
|
5
|
+
import { buildBatchTool, buildCommandTools, checkSchema, commandSchemas } from "./schemas.js";
|
|
6
|
+
import { COOKBOOK_COMMANDS_VERSION } from "./types.js";
|
|
7
|
+
import { createCookbookEngine } from "./engine.js";
|
|
8
|
+
export { COMMERCE_SETTING_TARGETS, COOKBOOK_COMMANDS_VERSION, DEFAULT_APP_NAME, DEFAULT_COLOR_SCHEME, DEFAULT_PRESET, DEFAULT_THEME_PRESETS, MAX_TERMS_LENGTH, adopt, buildBatchTool, buildCommandTools, buildNav, canonical, checkSchema, commandSchemas, createCookbookEngine, diagnose, execute, exportFileName, fail, isEmptyCookbook, libraryName, navItemId, serializeCookbook };
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import type { Cookbook, CookbookLayout } from '@happyvertical/smrt-types';
|
|
2
|
+
import type { EngineCatalog, EngineModel } from './types.js';
|
|
3
|
+
/** A menu entry after the layout is applied. */
|
|
4
|
+
export interface NavItem {
|
|
5
|
+
id: string;
|
|
6
|
+
label: string;
|
|
7
|
+
defaultLabel: string;
|
|
8
|
+
hidden: boolean;
|
|
9
|
+
}
|
|
10
|
+
export interface NavSection {
|
|
11
|
+
/** `section:<id>`, or the id of a custom section. */
|
|
12
|
+
id: string;
|
|
13
|
+
label: string;
|
|
14
|
+
defaultLabel: string;
|
|
15
|
+
custom: boolean;
|
|
16
|
+
hidden: boolean;
|
|
17
|
+
items: NavItem[];
|
|
18
|
+
}
|
|
19
|
+
/** The section that holds feature models no recipe covers. */
|
|
20
|
+
export declare const FEATURE_SECTION: {
|
|
21
|
+
readonly id: "more";
|
|
22
|
+
readonly label: "More";
|
|
23
|
+
};
|
|
24
|
+
/** Class name and package id of a qualified model name, from the catalog or the name itself. */
|
|
25
|
+
export declare function modelParts(catalog: EngineCatalog, qualified: string): {
|
|
26
|
+
packageId: string;
|
|
27
|
+
name: string;
|
|
28
|
+
};
|
|
29
|
+
/** The stable layout id of a navigation item (same as smrt-svelte's `navItemId`). */
|
|
30
|
+
export declare const navItemId: (packageId: string, modelName: string, key?: string) => string;
|
|
31
|
+
/** `Purchase Order` from `PurchaseOrder`. */
|
|
32
|
+
export declare const humanize: (name: string) => string;
|
|
33
|
+
export declare const modelLabel: (catalog: EngineCatalog, id: string) => string;
|
|
34
|
+
/** The menu with the document's layout applied: moves, order, hides, renames. */
|
|
35
|
+
export declare function buildNav(catalog: EngineCatalog, doc: Pick<Cookbook, 'recipes' | 'features'> & {
|
|
36
|
+
layout?: CookbookLayout;
|
|
37
|
+
}): NavSection[];
|
|
38
|
+
/** Is this model known as exposed by the catalog? */
|
|
39
|
+
export declare const findModel: (catalog: EngineCatalog, id: string) => EngineModel | undefined;
|
|
40
|
+
/** A section rename; blank or the default label removes the override. */
|
|
41
|
+
export declare function withSectionRenamed(layout: CookbookLayout | undefined, section: NavSection, label: string): CookbookLayout | undefined;
|
|
42
|
+
/** An item rename; `null`, blank or the default label removes the override. */
|
|
43
|
+
export declare function withItemRenamed(layout: CookbookLayout | undefined, item: NavItem, label: string | null): CookbookLayout | undefined;
|
|
44
|
+
export declare function withHidden(layout: CookbookLayout | undefined, id: string, hide: boolean): CookbookLayout | undefined;
|
|
45
|
+
//# sourceMappingURL=nav.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nav.d.ts","sourceRoot":"","sources":["../../../src/cookbook/engine/nav.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAC1E,OAAO,KAAK,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE7D,gDAAgD;AAChD,MAAM,WAAW,OAAO;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,WAAW,UAAU;IACzB,qDAAqD;IACrD,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,OAAO,CAAC;IAChB,MAAM,EAAE,OAAO,CAAC;IAChB,KAAK,EAAE,OAAO,EAAE,CAAC;CAClB;AAED,8DAA8D;AAC9D,eAAO,MAAM,eAAe;;;CAAyC,CAAC;AAItE,gGAAgG;AAChG,wBAAgB,UAAU,CACxB,OAAO,EAAE,aAAa,EACtB,SAAS,EAAE,MAAM,GAChB;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAOrC;AAED,qFAAqF;AACrF,eAAO,MAAM,SAAS,GACpB,WAAW,MAAM,EACjB,WAAW,MAAM,EACjB,MAAM,MAAM,KACX,MAAiE,CAAC;AAErE,6CAA6C;AAC7C,eAAO,MAAM,QAAQ,GAAI,MAAM,MAAM,KAAG,MAGE,CAAC;AAE3C,eAAO,MAAM,UAAU,GAAI,SAAS,aAAa,EAAE,IAAI,MAAM,KAAG,MACxB,CAAC;AAmEzC,iFAAiF;AACjF,wBAAgB,QAAQ,CACtB,OAAO,EAAE,aAAa,EACtB,GAAG,EAAE,IAAI,CAAC,QAAQ,EAAE,SAAS,GAAG,UAAU,CAAC,GAAG;IAAE,MAAM,CAAC,EAAE,cAAc,CAAA;CAAE,GACxE,UAAU,EAAE,CAmDd;AAED,qDAAqD;AACrD,eAAO,MAAM,SAAS,GACpB,SAAS,aAAa,EACtB,IAAI,MAAM,KACT,WAAW,GAAG,SAAoD,CAAC;AAqBtE,yEAAyE;AACzE,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,cAAc,GAAG,SAAS,EAClC,OAAO,EAAE,UAAU,EACnB,KAAK,EAAE,MAAM,GACZ,cAAc,GAAG,SAAS,CAoB5B;AAED,+EAA+E;AAC/E,wBAAgB,eAAe,CAC7B,MAAM,EAAE,cAAc,GAAG,SAAS,EAClC,IAAI,EAAE,OAAO,EACb,KAAK,EAAE,MAAM,GAAG,IAAI,GACnB,cAAc,GAAG,SAAS,CAa5B;AAED,wBAAgB,UAAU,CACxB,MAAM,EAAE,cAAc,GAAG,SAAS,EAClC,EAAE,EAAE,MAAM,EACV,IAAI,EAAE,OAAO,GACZ,cAAc,GAAG,SAAS,CAO5B"}
|