@manifesto-ai/sdk 2.3.0 → 3.1.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/dist/index.js CHANGED
@@ -1,240 +1,113 @@
1
+ import {
2
+ ACTION_PARAM_NAMES,
3
+ AlreadyActivatedError,
4
+ CompileError,
5
+ DisposedError,
6
+ ManifestoError,
7
+ ReservedEffectError,
8
+ activateComposable,
9
+ attachRuntimeKernelFactory,
10
+ createBaseRuntimeInstance,
11
+ createRuntimeKernel
12
+ } from "./chunk-NGW654NU.js";
13
+
1
14
  // src/create-manifesto.ts
2
15
  import {
3
16
  createHost
4
17
  } from "@manifesto-ai/host";
5
18
  import {
6
- getAvailableActions as queryAvailableActions,
7
- isActionAvailable as queryActionAvailable,
8
- semanticPathToPatchPath,
9
- extractDefaults
19
+ createIntent as createCoreIntent,
20
+ extractDefaults,
21
+ hashSchemaSync,
22
+ semanticPathToPatchPath
10
23
  } from "@manifesto-ai/core";
11
- import { compileMelDomain } from "@manifesto-ai/compiler";
12
-
13
- // src/errors.ts
14
- var ManifestoError = class extends Error {
15
- code;
16
- constructor(code, message, options) {
17
- super(message, options);
18
- this.name = "ManifestoError";
19
- this.code = code;
20
- }
21
- };
22
- var ReservedEffectError = class extends ManifestoError {
23
- effectType;
24
- constructor(effectType) {
25
- super(
26
- "RESERVED_EFFECT",
27
- `Effect type "${effectType}" is reserved and cannot be overridden`
28
- );
29
- this.name = "ReservedEffectError";
30
- this.effectType = effectType;
31
- }
32
- };
33
- var CompileError = class extends ManifestoError {
34
- diagnostics;
35
- constructor(diagnostics, formattedMessage) {
36
- super("COMPILE_ERROR", formattedMessage);
37
- this.name = "CompileError";
38
- this.diagnostics = diagnostics;
39
- }
40
- };
41
- var DisposedError = class extends ManifestoError {
42
- constructor() {
43
- super("DISPOSED", "Cannot dispatch on a disposed ManifestoInstance");
44
- this.name = "DisposedError";
45
- }
46
- };
47
-
48
- // src/create-manifesto.ts
24
+ import {
25
+ compileMelDomain,
26
+ parse as parseMel,
27
+ tokenize as tokenizeMel
28
+ } from "@manifesto-ai/compiler";
49
29
  var RESERVED_EFFECT_TYPE = "system.get";
50
30
  var RESERVED_NAMESPACE_PREFIX = "system.";
51
- function createManifesto(config) {
52
- const schema = resolveSchema(config.schema);
53
- if (RESERVED_EFFECT_TYPE in config.effects) {
31
+ var BASE_LAWS = Object.freeze({ __baseLaws: true });
32
+ function createManifesto(schemaInput, effects) {
33
+ if (RESERVED_EFFECT_TYPE in effects) {
54
34
  throw new ReservedEffectError(RESERVED_EFFECT_TYPE);
55
35
  }
56
- validateReservedNamespaces(schema);
57
- const host = createInternalHost(schema, config.effects, config.snapshot);
58
- let currentSnapshot = host.getSnapshot();
59
- const subscribers = /* @__PURE__ */ new Set();
60
- const eventListeners = /* @__PURE__ */ new Map();
61
- let dispatchQueue = Promise.resolve();
62
- let disposed = false;
63
- const guard = config.guard ?? null;
64
- function dispatch(intent) {
65
- if (disposed) {
66
- throw new DisposedError();
36
+ const resolved = resolveSchema(schemaInput);
37
+ validateReservedNamespaces(resolved.schema);
38
+ const manifesto = {
39
+ _laws: BASE_LAWS,
40
+ schema: resolved.schema,
41
+ activate() {
42
+ activateComposable(manifesto);
43
+ return createBaseRuntimeInstance(
44
+ createRuntimeKernel({
45
+ schema: resolved.schema,
46
+ host: createInternalHost(resolved.schema, effects),
47
+ MEL: buildTypedMel(resolved.schema, resolved.actionParamMetadata),
48
+ createIntent: buildCreateIntent()
49
+ })
50
+ );
67
51
  }
68
- const enrichedIntent = intent.intentId ? intent : { ...intent, intentId: generateIntentId() };
69
- const prev = dispatchQueue;
70
- dispatchQueue = prev.catch(() => {
71
- }).then(() => processIntent(enrichedIntent));
72
- dispatchQueue = dispatchQueue.catch(() => {
73
- });
74
- }
75
- async function processIntent(intent) {
76
- if (disposed) return;
77
- if (guard) {
78
- try {
79
- const allowed = guard(intent, Object.freeze(structuredClone(currentSnapshot)));
80
- if (!allowed) {
81
- emitEvent("dispatch:rejected", {
82
- intentId: intent.intentId,
83
- intent,
84
- reason: "Guard rejected the intent"
85
- });
86
- return;
87
- }
88
- } catch (error) {
89
- emitEvent("dispatch:failed", {
90
- intentId: intent.intentId,
91
- intent,
92
- error: error instanceof Error ? error : new Error(String(error))
93
- });
94
- return;
52
+ };
53
+ return attachRuntimeKernelFactory(
54
+ manifesto,
55
+ () => createRuntimeKernel({
56
+ schema: resolved.schema,
57
+ host: createInternalHost(resolved.schema, effects),
58
+ MEL: buildTypedMel(resolved.schema, resolved.actionParamMetadata),
59
+ createIntent: buildCreateIntent()
60
+ })
61
+ );
62
+ }
63
+ function resolveSchema(schema) {
64
+ const resolved = typeof schema === "string" ? compileSchema(schema) : {
65
+ schema,
66
+ actionParamMetadata: deriveActionParamMetadata(schema)
67
+ };
68
+ return {
69
+ schema: withPlatformNamespaces(resolved.schema),
70
+ actionParamMetadata: resolved.actionParamMetadata
71
+ };
72
+ }
73
+ function compileSchema(source) {
74
+ const result = compileMelDomain(source, { mode: "domain" });
75
+ if (result.errors.length > 0) {
76
+ const formatted = result.errors.map((diagnostic) => {
77
+ const loc = diagnostic.location;
78
+ if (!loc || loc.start.line === 0 && loc.start.column === 0) {
79
+ return `[${diagnostic.code}] ${diagnostic.message}`;
95
80
  }
96
- }
97
- try {
98
- const result = await host.dispatch(intent);
99
- if (result.status === "error") {
100
- currentSnapshot = result.snapshot;
101
- notifySubscribers();
102
- emitEvent("dispatch:failed", {
103
- intentId: intent.intentId,
104
- intent,
105
- error: result.error ?? new ManifestoError("HOST_ERROR", "Host dispatch failed")
106
- });
107
- return;
81
+ const header = `[${diagnostic.code}] ${diagnostic.message} (${loc.start.line}:${loc.start.column})`;
82
+ const line = source.split("\n")[loc.start.line - 1];
83
+ if (!line) {
84
+ return header;
108
85
  }
109
- currentSnapshot = result.snapshot;
110
- notifySubscribers();
111
- emitEvent("dispatch:completed", {
112
- intentId: intent.intentId,
113
- intent,
114
- snapshot: result.snapshot
115
- });
116
- } catch (error) {
117
- emitEvent("dispatch:failed", {
118
- intentId: intent.intentId,
119
- intent,
120
- error: error instanceof Error ? error : new Error(String(error))
121
- });
122
- }
123
- }
124
- function subscribe(selector, listener) {
125
- if (disposed) return () => {
126
- };
127
- const sub = {
128
- selector,
129
- listener,
130
- lastValue: selector(currentSnapshot),
131
- initialized: true
132
- };
133
- subscribers.add(sub);
134
- return () => {
135
- subscribers.delete(sub);
136
- };
137
- }
138
- function on(event, handler) {
139
- if (disposed) return () => {
140
- };
141
- let listeners = eventListeners.get(event);
142
- if (!listeners) {
143
- listeners = /* @__PURE__ */ new Set();
144
- eventListeners.set(event, listeners);
145
- }
146
- listeners.add(handler);
147
- return () => {
148
- listeners.delete(handler);
149
- };
150
- }
151
- function isActionAvailable(actionName) {
152
- return queryActionAvailable(schema, currentSnapshot, actionName);
153
- }
154
- function getAvailableActions() {
155
- return queryAvailableActions(schema, currentSnapshot);
156
- }
157
- function getSnapshot() {
158
- return Object.freeze(structuredClone(currentSnapshot));
159
- }
160
- function dispose() {
161
- if (disposed) return;
162
- disposed = true;
163
- subscribers.clear();
164
- eventListeners.clear();
165
- }
166
- function notifySubscribers() {
167
- const frozenSnap = Object.freeze(structuredClone(currentSnapshot));
168
- for (const sub of subscribers) {
169
- const selected = sub.selector(frozenSnap);
170
- if (sub.initialized && Object.is(sub.lastValue, selected)) {
171
- continue;
172
- }
173
- sub.lastValue = selected;
174
- sub.initialized = true;
175
- sub.listener(selected);
176
- }
86
+ const lineNum = String(loc.start.line).padStart(4, " ");
87
+ const underlineLen = Math.max(
88
+ 1,
89
+ loc.end.line === loc.start.line ? Math.min(loc.end.column - loc.start.column, Math.max(1, line.length - loc.start.column + 1)) : 1
90
+ );
91
+ const padding = " ".repeat(lineNum.length + 3 + loc.start.column - 1);
92
+ return `${header}
93
+ ${lineNum} | ${line}
94
+ ${padding}${"^".repeat(underlineLen)}`;
95
+ }).join("\n\n");
96
+ throw new CompileError(result.errors, `MEL compilation failed:
97
+ ${formatted}`);
177
98
  }
178
- function emitEvent(event, payload) {
179
- const listeners = eventListeners.get(event);
180
- if (!listeners) return;
181
- for (const handler of listeners) {
182
- try {
183
- handler(payload);
184
- } catch {
185
- }
186
- }
99
+ if (!result.schema) {
100
+ throw new ManifestoError("COMPILE_ERROR", "MEL compilation produced no schema");
187
101
  }
102
+ const schema = result.schema;
188
103
  return {
189
- dispatch,
190
- subscribe,
191
- on,
192
- isActionAvailable,
193
- getAvailableActions,
194
- getSnapshot,
195
- dispose
104
+ schema,
105
+ actionParamMetadata: deriveActionParamMetadata(
106
+ schema,
107
+ extractActionParamOrderFromMel(source)
108
+ )
196
109
  };
197
110
  }
198
- function resolveSchema(schema) {
199
- let domainSchema;
200
- if (typeof schema === "string") {
201
- const result = compileMelDomain(schema, { mode: "domain" });
202
- if (result.errors.length > 0) {
203
- const formatted = result.errors.map((d) => {
204
- const loc = d.location;
205
- const header = loc && (loc.start.line > 0 || loc.start.column > 0) ? `[${d.code}] ${d.message} (${loc.start.line}:${loc.start.column})` : `[${d.code}] ${d.message}`;
206
- if (!loc || loc.start.line === 0) return header;
207
- const sourceLines = schema.split("\n");
208
- const lineContent = sourceLines[loc.start.line - 1];
209
- if (!lineContent) return header;
210
- const lineNumStr = String(loc.start.line).padStart(4, " ");
211
- const underlineLen = Math.max(
212
- 1,
213
- loc.end.line === loc.start.line ? Math.min(loc.end.column - loc.start.column, lineContent.length - loc.start.column + 1) : 1
214
- );
215
- const padding = " ".repeat(lineNumStr.length + 3 + loc.start.column - 1);
216
- return `${header}
217
- ${lineNumStr} | ${lineContent}
218
- ${padding}${"^".repeat(underlineLen)}`;
219
- }).join("\n\n");
220
- throw new CompileError(
221
- result.errors,
222
- `MEL compilation failed:
223
- ${formatted}`
224
- );
225
- }
226
- if (!result.schema) {
227
- throw new ManifestoError(
228
- "COMPILE_ERROR",
229
- "MEL compilation produced no schema"
230
- );
231
- }
232
- domainSchema = result.schema;
233
- } else {
234
- domainSchema = schema;
235
- }
236
- return withPlatformNamespaces(domainSchema);
237
- }
238
111
  function withPlatformNamespaces(schema) {
239
112
  const fields = { ...schema.state.fields };
240
113
  let changed = false;
@@ -246,10 +119,7 @@ function withPlatformNamespaces(schema) {
246
119
  };
247
120
  changed = true;
248
121
  } else if (fields.$host.type !== "object") {
249
- throw new ManifestoError(
250
- "SCHEMA_ERROR",
251
- "Reserved namespace '$host' must be an object field"
252
- );
122
+ throw new ManifestoError("SCHEMA_ERROR", "Reserved namespace '$host' must be an object field");
253
123
  } else if (fields.$host.default === void 0) {
254
124
  fields.$host = { ...fields.$host, default: {} };
255
125
  changed = true;
@@ -276,10 +146,7 @@ function withPlatformNamespaces(schema) {
276
146
  };
277
147
  changed = true;
278
148
  } else if (fields.$mel.type !== "object") {
279
- throw new ManifestoError(
280
- "SCHEMA_ERROR",
281
- "Reserved namespace '$mel' must be an object field"
282
- );
149
+ throw new ManifestoError("SCHEMA_ERROR", "Reserved namespace '$mel' must be an object field");
283
150
  } else {
284
151
  let nextMel = fields.$mel;
285
152
  if (nextMel.default === void 0) {
@@ -309,13 +176,10 @@ function withPlatformNamespaces(schema) {
309
176
  };
310
177
  changed = true;
311
178
  } else if (guardsField.type !== "object") {
312
- throw new ManifestoError(
313
- "SCHEMA_ERROR",
314
- "Reserved namespace '$mel.guards' must be an object field"
315
- );
179
+ throw new ManifestoError("SCHEMA_ERROR", "Reserved namespace '$mel.guards' must be an object field");
316
180
  } else {
317
181
  let nextGuards = guardsField;
318
- if (guardsField.default === void 0) {
182
+ if (nextGuards.default === void 0) {
319
183
  nextGuards = { ...nextGuards, default: { intent: {} } };
320
184
  changed = true;
321
185
  }
@@ -335,10 +199,7 @@ function withPlatformNamespaces(schema) {
335
199
  };
336
200
  changed = true;
337
201
  } else if (intentField.type !== "object") {
338
- throw new ManifestoError(
339
- "SCHEMA_ERROR",
340
- "Reserved namespace '$mel.guards.intent' must be an object field"
341
- );
202
+ throw new ManifestoError("SCHEMA_ERROR", "Reserved namespace '$mel.guards.intent' must be an object field");
342
203
  } else if (intentField.default === void 0) {
343
204
  nextGuards = {
344
205
  ...nextGuards,
@@ -361,21 +222,26 @@ function withPlatformNamespaces(schema) {
361
222
  }
362
223
  if (nextMel !== fields.$mel) {
363
224
  fields.$mel = nextMel;
364
- changed = true;
365
225
  }
366
226
  }
367
- if (!changed) return schema;
368
- return {
227
+ if (!changed) {
228
+ return schema;
229
+ }
230
+ const nextSchema = {
369
231
  ...schema,
370
232
  state: {
371
233
  ...schema.state,
372
234
  fields
373
235
  }
374
236
  };
237
+ const { hash: _hash, ...schemaWithoutHash } = nextSchema;
238
+ return {
239
+ ...nextSchema,
240
+ hash: hashSchemaSync(schemaWithoutHash)
241
+ };
375
242
  }
376
243
  function validateReservedNamespaces(schema) {
377
- const actions = schema.actions || {};
378
- for (const actionType of Object.keys(actions)) {
244
+ for (const actionType of Object.keys(schema.actions ?? {})) {
379
245
  if (actionType.startsWith(RESERVED_NAMESPACE_PREFIX)) {
380
246
  throw new ManifestoError(
381
247
  "RESERVED_NAMESPACE",
@@ -384,21 +250,131 @@ function validateReservedNamespaces(schema) {
384
250
  }
385
251
  }
386
252
  }
387
- function createInternalHost(schema, effects, initialSnapshot) {
388
- const host = createHost(schema, {
389
- initialData: initialSnapshot?.data ?? extractDefaults(schema.state)
253
+ function buildTypedMel(schema, actionParamMetadata) {
254
+ const actions = Object.fromEntries(
255
+ Object.keys(schema.actions).map((name) => {
256
+ const ref = {
257
+ __kind: "ActionRef",
258
+ name
259
+ };
260
+ Object.defineProperty(ref, ACTION_PARAM_NAMES, {
261
+ enumerable: false,
262
+ configurable: false,
263
+ writable: false,
264
+ value: Object.hasOwn(actionParamMetadata, name) ? actionParamMetadata[name] : []
265
+ });
266
+ return [name, Object.freeze(ref)];
267
+ })
268
+ );
269
+ const state = Object.fromEntries(
270
+ Object.keys(schema.state.fields).filter((name) => !name.startsWith("$")).map((name) => [name, Object.freeze({
271
+ __kind: "FieldRef",
272
+ path: name
273
+ })])
274
+ );
275
+ const computed = Object.fromEntries(
276
+ Object.keys(schema.computed.fields).map((name) => [name, Object.freeze({
277
+ __kind: "ComputedRef",
278
+ path: name
279
+ })])
280
+ );
281
+ return Object.freeze({
282
+ actions: Object.freeze(actions),
283
+ state: Object.freeze(state),
284
+ computed: Object.freeze(computed)
390
285
  });
391
- if (initialSnapshot) {
392
- host.reset(initialSnapshot);
286
+ }
287
+ function buildCreateIntent() {
288
+ return (action, ...args) => {
289
+ const actionRef = action;
290
+ const intentId = generateUUID();
291
+ const input = packIntentInput(actionRef, args);
292
+ return createCoreIntent(
293
+ String(action.name),
294
+ input,
295
+ intentId
296
+ );
297
+ };
298
+ }
299
+ function getActionParamNames(input) {
300
+ if (!input || input.type !== "object" || !input.fields) {
301
+ return [];
302
+ }
303
+ return Object.keys(input.fields);
304
+ }
305
+ function deriveActionParamMetadata(schema, actionParamOrder) {
306
+ return Object.freeze(Object.fromEntries(
307
+ Object.entries(schema.actions).map(([name, action]) => {
308
+ const preferredOrder = actionParamOrder?.[name];
309
+ if (preferredOrder && preferredOrder.length > 0) {
310
+ return [name, Object.freeze([...preferredOrder])];
311
+ }
312
+ if (!action.input || action.input.type !== "object" || !action.input.fields) {
313
+ return [name, []];
314
+ }
315
+ const fieldNames = getActionParamNames(action.input);
316
+ return [name, fieldNames.length <= 1 ? fieldNames : null];
317
+ })
318
+ ));
319
+ }
320
+ function extractActionParamOrderFromMel(source) {
321
+ const lexed = tokenizeMel(source);
322
+ if (lexed.diagnostics.some((diagnostic) => diagnostic.severity === "error")) {
323
+ return void 0;
324
+ }
325
+ const parsed = parseMel(lexed.tokens);
326
+ if (!parsed.program) {
327
+ return void 0;
328
+ }
329
+ return Object.freeze(Object.fromEntries(
330
+ parsed.program.domain.members.filter((member) => member.kind === "action").map((action) => [action.name, Object.freeze(action.params.map((param) => param.name))])
331
+ ));
332
+ }
333
+ function packIntentInput(action, args) {
334
+ const paramNames = Object.hasOwn(action, ACTION_PARAM_NAMES) ? action[ACTION_PARAM_NAMES] : [];
335
+ if (args.length === 0) {
336
+ return void 0;
337
+ }
338
+ if (paramNames === null) {
339
+ if (args.length === 1 && isPlainObject(args[0])) {
340
+ return args[0];
341
+ }
342
+ throw new ManifestoError(
343
+ "INVALID_INTENT_ARGS",
344
+ `Action "${String(action.name)}" requires a single object argument because positional parameter metadata is unavailable`
345
+ );
346
+ }
347
+ if (paramNames.length === 0) {
348
+ if (args.length === 1) {
349
+ return args[0];
350
+ }
351
+ throw new ManifestoError(
352
+ "INVALID_INTENT_ARGS",
353
+ `Action "${String(action.name)}" does not accept multiple positional arguments`
354
+ );
355
+ }
356
+ if (args.length === 1 && isPlainObject(args[0]) && paramNames.length > 1) {
357
+ return args[0];
393
358
  }
359
+ return Object.fromEntries(args.map((value, index) => [
360
+ paramNames[index] ?? `arg${index}`,
361
+ value
362
+ ]));
363
+ }
364
+ function isPlainObject(value) {
365
+ return typeof value === "object" && value !== null && !Array.isArray(value);
366
+ }
367
+ function createInternalHost(schema, effects) {
368
+ const host = createHost(schema, {
369
+ initialData: extractDefaults(schema.state)
370
+ });
394
371
  host.registerEffect(RESERVED_EFFECT_TYPE, async (_type, params, ctx) => {
395
372
  const { patches } = executeSystemGet(params, ctx.snapshot);
396
373
  return patches;
397
374
  });
398
375
  for (const [effectType, appHandler] of Object.entries(effects)) {
399
376
  const hostHandler = async (_type, params, ctx) => {
400
- const appCtx = { snapshot: ctx.snapshot };
401
- const patches = await appHandler(params, appCtx);
377
+ const patches = await appHandler(params, { snapshot: freezeSnapshot(ctx.snapshot) });
402
378
  return patches;
403
379
  };
404
380
  host.registerEffect(effectType, hostHandler);
@@ -408,6 +384,29 @@ function createInternalHost(schema, effects, initialSnapshot) {
408
384
  function isGenerateParams(params) {
409
385
  return typeof params === "object" && params !== null && "key" in params && "into" in params;
410
386
  }
387
+ function executeSystemGet(params, snapshot) {
388
+ if (isGenerateParams(params)) {
389
+ return {
390
+ patches: [{
391
+ op: "set",
392
+ path: normalizeTargetPath(params.into),
393
+ value: generateSystemValue(params.key)
394
+ }]
395
+ };
396
+ }
397
+ const { path, target } = params;
398
+ const result = resolvePathValue(path, snapshot);
399
+ if (!target) {
400
+ return { patches: [] };
401
+ }
402
+ return {
403
+ patches: [{
404
+ op: "set",
405
+ path: normalizeTargetPath(target),
406
+ value: result.value
407
+ }]
408
+ };
409
+ }
411
410
  function generateSystemValue(key) {
412
411
  switch (key) {
413
412
  case "uuid":
@@ -421,37 +420,10 @@ function generateSystemValue(key) {
421
420
  return null;
422
421
  }
423
422
  }
424
- function generateUUID() {
425
- if (typeof crypto !== "undefined" && crypto.randomUUID) {
426
- return crypto.randomUUID();
427
- }
428
- return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => {
429
- const r = Math.random() * 16 | 0;
430
- const v = c === "x" ? r : r & 3 | 8;
431
- return v.toString(16);
432
- });
433
- }
434
- function executeSystemGet(params, snapshot) {
435
- if (isGenerateParams(params)) {
436
- const value = generateSystemValue(params.key);
437
- const patches2 = [{
438
- op: "set",
439
- path: normalizeTargetPath(params.into),
440
- value
441
- }];
442
- return { patches: patches2 };
443
- }
444
- const { path, target } = params;
445
- const result = resolvePathValue(path, snapshot);
446
- const patches = [];
447
- if (target) {
448
- patches.push({
449
- op: "set",
450
- path: normalizeTargetPath(target),
451
- value: result.value
452
- });
453
- }
454
- return { patches };
423
+ function normalizeTargetPath(path) {
424
+ const normalized = normalizePath(path);
425
+ const withoutDataRoot = normalized.startsWith("data.") ? normalized.slice("data.".length) : normalized;
426
+ return semanticPathToPatchPath(withoutDataRoot);
455
427
  }
456
428
  function normalizePath(path) {
457
429
  if (path.startsWith("/")) {
@@ -459,19 +431,13 @@ function normalizePath(path) {
459
431
  }
460
432
  return path;
461
433
  }
462
- function normalizeTargetPath(path) {
463
- const normalized = normalizePath(path);
464
- const withoutDataRoot = normalized.startsWith("data.") ? normalized.slice("data.".length) : normalized;
465
- return semanticPathToPatchPath(withoutDataRoot);
466
- }
467
434
  function resolvePathValue(path, snapshot) {
468
435
  const normalized = normalizePath(path);
469
436
  const parts = normalized.split(".");
470
437
  if (parts.length === 0) {
471
438
  return { value: void 0, found: false };
472
439
  }
473
- const root = parts[0];
474
- const rest = parts.slice(1);
440
+ const [root, ...rest] = parts;
475
441
  let current;
476
442
  switch (root) {
477
443
  case "data":
@@ -489,116 +455,39 @@ function resolvePathValue(path, snapshot) {
489
455
  default:
490
456
  current = snapshot.data;
491
457
  rest.unshift(root);
458
+ break;
492
459
  }
493
460
  for (const part of rest) {
494
- if (current === null || current === void 0) {
495
- return { value: void 0, found: false };
496
- }
497
- if (typeof current !== "object") {
461
+ if (current === null || current === void 0 || typeof current !== "object") {
498
462
  return { value: void 0, found: false };
499
463
  }
500
464
  current = current[part];
501
465
  }
502
466
  return { value: current, found: current !== void 0 };
503
467
  }
504
- function generateIntentId() {
505
- return generateUUID();
468
+ function freezeSnapshot(snapshot) {
469
+ return Object.freeze(structuredClone(snapshot));
506
470
  }
507
-
508
- // src/dispatch-async.ts
509
- var DispatchRejectedError = class extends Error {
510
- code = "DISPATCH_REJECTED";
511
- intentId;
512
- constructor(intentId, reason) {
513
- super(reason ?? "Intent was rejected by guard");
514
- this.name = "DispatchRejectedError";
515
- this.intentId = intentId;
516
- }
517
- };
518
- function dispatchAsync(instance, intent) {
519
- const intentId = intent.intentId ?? generateId();
520
- const enriched = intent.intentId ? intent : { ...intent, intentId };
521
- return new Promise((resolve, reject) => {
522
- const cleanup = () => {
523
- unsubCompleted();
524
- unsubFailed();
525
- unsubRejected();
526
- };
527
- const unsubCompleted = instance.on("dispatch:completed", (e) => {
528
- if (e.intentId === intentId) {
529
- cleanup();
530
- resolve(e.snapshot);
531
- }
532
- });
533
- const unsubFailed = instance.on("dispatch:failed", (e) => {
534
- if (e.intentId === intentId) {
535
- cleanup();
536
- reject(e.error ?? new Error("Dispatch failed"));
537
- }
538
- });
539
- const unsubRejected = instance.on("dispatch:rejected", (e) => {
540
- if (e.intentId === intentId) {
541
- cleanup();
542
- reject(new DispatchRejectedError(intentId, e.reason));
543
- }
544
- });
545
- instance.dispatch(enriched);
546
- });
547
- }
548
- function generateId() {
549
- if (typeof crypto !== "undefined" && crypto.randomUUID) {
471
+ function generateUUID() {
472
+ if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") {
550
473
  return crypto.randomUUID();
551
474
  }
552
- return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => {
553
- const r = Math.random() * 16 | 0;
554
- const v = c === "x" ? r : r & 3 | 8;
555
- return v.toString(16);
475
+ return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (char) => {
476
+ const random = Math.random() * 16 | 0;
477
+ const value = char === "x" ? random : random & 3 | 8;
478
+ return value.toString(16);
556
479
  });
557
480
  }
558
481
 
559
- // src/typed-ops.ts
560
- import { semanticPathToPatchPath as semanticPathToPatchPath2 } from "@manifesto-ai/core";
561
- function defineOps() {
562
- const toPatchPath = (path) => semanticPathToPatchPath2(path);
563
- return {
564
- set(path, value) {
565
- return { op: "set", path: toPatchPath(path), value };
566
- },
567
- unset(path) {
568
- return { op: "unset", path: toPatchPath(path) };
569
- },
570
- merge(path, value) {
571
- return { op: "merge", path: toPatchPath(path), value };
572
- },
573
- raw: {
574
- set(path, value) {
575
- return { op: "set", path: toPatchPath(path), value };
576
- },
577
- unset(path) {
578
- return { op: "unset", path: toPatchPath(path) };
579
- },
580
- merge(path, value) {
581
- return { op: "merge", path: toPatchPath(path), value };
582
- }
583
- }
584
- };
585
- }
586
-
587
482
  // src/index.ts
588
- import { createIntent, createSnapshot, createCore } from "@manifesto-ai/core";
589
- import { createWorld } from "@manifesto-ai/world";
483
+ import { createSnapshot } from "@manifesto-ai/core";
590
484
  export {
485
+ AlreadyActivatedError,
591
486
  CompileError,
592
- DispatchRejectedError,
593
487
  DisposedError,
594
488
  ManifestoError,
595
489
  ReservedEffectError,
596
- createCore,
597
- createIntent,
598
490
  createManifesto,
599
- createSnapshot,
600
- createWorld,
601
- defineOps,
602
- dispatchAsync
491
+ createSnapshot
603
492
  };
604
493
  //# sourceMappingURL=index.js.map