@manifesto-ai/sdk 2.3.0 → 3.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,240 +1,116 @@
1
+ import {
2
+ ACTION_PARAM_NAMES,
3
+ AlreadyActivatedError,
4
+ CompileError,
5
+ DisposedError,
6
+ ManifestoError,
7
+ ReservedEffectError,
8
+ attachRuntimeKernelFactory,
9
+ createBaseRuntimeInstance,
10
+ createRuntimeKernel
11
+ } from "./chunk-CMZQTFX2.js";
12
+
1
13
  // src/create-manifesto.ts
2
14
  import {
3
15
  createHost
4
16
  } from "@manifesto-ai/host";
5
17
  import {
6
- getAvailableActions as queryAvailableActions,
7
- isActionAvailable as queryActionAvailable,
8
- semanticPathToPatchPath,
9
- extractDefaults
18
+ createIntent as createCoreIntent,
19
+ extractDefaults,
20
+ hashSchemaSync,
21
+ semanticPathToPatchPath
10
22
  } 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
23
+ import {
24
+ compileMelDomain,
25
+ parse as parseMel,
26
+ tokenize as tokenizeMel
27
+ } from "@manifesto-ai/compiler";
49
28
  var RESERVED_EFFECT_TYPE = "system.get";
50
29
  var RESERVED_NAMESPACE_PREFIX = "system.";
51
- function createManifesto(config) {
52
- const schema = resolveSchema(config.schema);
53
- if (RESERVED_EFFECT_TYPE in config.effects) {
30
+ var BASE_LAWS = Object.freeze({ __baseLaws: true });
31
+ function createManifesto(schemaInput, effects) {
32
+ if (RESERVED_EFFECT_TYPE in effects) {
54
33
  throw new ReservedEffectError(RESERVED_EFFECT_TYPE);
55
34
  }
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();
67
- }
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;
35
+ const resolved = resolveSchema(schemaInput);
36
+ validateReservedNamespaces(resolved.schema);
37
+ let activated = false;
38
+ const manifesto = {
39
+ _laws: BASE_LAWS,
40
+ schema: resolved.schema,
41
+ activate() {
42
+ if (activated) {
43
+ throw new AlreadyActivatedError();
95
44
  }
45
+ activated = true;
46
+ return createBaseRuntimeInstance(
47
+ createRuntimeKernel({
48
+ schema: resolved.schema,
49
+ host: createInternalHost(resolved.schema, effects),
50
+ MEL: buildTypedMel(resolved.schema, resolved.actionParamMetadata),
51
+ createIntent: buildCreateIntent()
52
+ })
53
+ );
96
54
  }
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;
55
+ };
56
+ return attachRuntimeKernelFactory(
57
+ manifesto,
58
+ () => createRuntimeKernel({
59
+ schema: resolved.schema,
60
+ host: createInternalHost(resolved.schema, effects),
61
+ MEL: buildTypedMel(resolved.schema, resolved.actionParamMetadata),
62
+ createIntent: buildCreateIntent()
63
+ })
64
+ );
65
+ }
66
+ function resolveSchema(schema) {
67
+ const resolved = typeof schema === "string" ? compileSchema(schema) : {
68
+ schema,
69
+ actionParamMetadata: deriveActionParamMetadata(schema)
70
+ };
71
+ return {
72
+ schema: withPlatformNamespaces(resolved.schema),
73
+ actionParamMetadata: resolved.actionParamMetadata
74
+ };
75
+ }
76
+ function compileSchema(source) {
77
+ const result = compileMelDomain(source, { mode: "domain" });
78
+ if (result.errors.length > 0) {
79
+ const formatted = result.errors.map((diagnostic) => {
80
+ const loc = diagnostic.location;
81
+ if (!loc || loc.start.line === 0 && loc.start.column === 0) {
82
+ return `[${diagnostic.code}] ${diagnostic.message}`;
108
83
  }
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;
84
+ const header = `[${diagnostic.code}] ${diagnostic.message} (${loc.start.line}:${loc.start.column})`;
85
+ const line = source.split("\n")[loc.start.line - 1];
86
+ if (!line) {
87
+ return header;
172
88
  }
173
- sub.lastValue = selected;
174
- sub.initialized = true;
175
- sub.listener(selected);
176
- }
89
+ const lineNum = String(loc.start.line).padStart(4, " ");
90
+ const underlineLen = Math.max(
91
+ 1,
92
+ loc.end.line === loc.start.line ? Math.min(loc.end.column - loc.start.column, Math.max(1, line.length - loc.start.column + 1)) : 1
93
+ );
94
+ const padding = " ".repeat(lineNum.length + 3 + loc.start.column - 1);
95
+ return `${header}
96
+ ${lineNum} | ${line}
97
+ ${padding}${"^".repeat(underlineLen)}`;
98
+ }).join("\n\n");
99
+ throw new CompileError(result.errors, `MEL compilation failed:
100
+ ${formatted}`);
177
101
  }
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
- }
102
+ if (!result.schema) {
103
+ throw new ManifestoError("COMPILE_ERROR", "MEL compilation produced no schema");
187
104
  }
105
+ const schema = result.schema;
188
106
  return {
189
- dispatch,
190
- subscribe,
191
- on,
192
- isActionAvailable,
193
- getAvailableActions,
194
- getSnapshot,
195
- dispose
107
+ schema,
108
+ actionParamMetadata: deriveActionParamMetadata(
109
+ schema,
110
+ extractActionParamOrderFromMel(source)
111
+ )
196
112
  };
197
113
  }
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
114
  function withPlatformNamespaces(schema) {
239
115
  const fields = { ...schema.state.fields };
240
116
  let changed = false;
@@ -246,10 +122,7 @@ function withPlatformNamespaces(schema) {
246
122
  };
247
123
  changed = true;
248
124
  } else if (fields.$host.type !== "object") {
249
- throw new ManifestoError(
250
- "SCHEMA_ERROR",
251
- "Reserved namespace '$host' must be an object field"
252
- );
125
+ throw new ManifestoError("SCHEMA_ERROR", "Reserved namespace '$host' must be an object field");
253
126
  } else if (fields.$host.default === void 0) {
254
127
  fields.$host = { ...fields.$host, default: {} };
255
128
  changed = true;
@@ -276,10 +149,7 @@ function withPlatformNamespaces(schema) {
276
149
  };
277
150
  changed = true;
278
151
  } else if (fields.$mel.type !== "object") {
279
- throw new ManifestoError(
280
- "SCHEMA_ERROR",
281
- "Reserved namespace '$mel' must be an object field"
282
- );
152
+ throw new ManifestoError("SCHEMA_ERROR", "Reserved namespace '$mel' must be an object field");
283
153
  } else {
284
154
  let nextMel = fields.$mel;
285
155
  if (nextMel.default === void 0) {
@@ -309,13 +179,10 @@ function withPlatformNamespaces(schema) {
309
179
  };
310
180
  changed = true;
311
181
  } else if (guardsField.type !== "object") {
312
- throw new ManifestoError(
313
- "SCHEMA_ERROR",
314
- "Reserved namespace '$mel.guards' must be an object field"
315
- );
182
+ throw new ManifestoError("SCHEMA_ERROR", "Reserved namespace '$mel.guards' must be an object field");
316
183
  } else {
317
184
  let nextGuards = guardsField;
318
- if (guardsField.default === void 0) {
185
+ if (nextGuards.default === void 0) {
319
186
  nextGuards = { ...nextGuards, default: { intent: {} } };
320
187
  changed = true;
321
188
  }
@@ -335,10 +202,7 @@ function withPlatformNamespaces(schema) {
335
202
  };
336
203
  changed = true;
337
204
  } else if (intentField.type !== "object") {
338
- throw new ManifestoError(
339
- "SCHEMA_ERROR",
340
- "Reserved namespace '$mel.guards.intent' must be an object field"
341
- );
205
+ throw new ManifestoError("SCHEMA_ERROR", "Reserved namespace '$mel.guards.intent' must be an object field");
342
206
  } else if (intentField.default === void 0) {
343
207
  nextGuards = {
344
208
  ...nextGuards,
@@ -361,21 +225,26 @@ function withPlatformNamespaces(schema) {
361
225
  }
362
226
  if (nextMel !== fields.$mel) {
363
227
  fields.$mel = nextMel;
364
- changed = true;
365
228
  }
366
229
  }
367
- if (!changed) return schema;
368
- return {
230
+ if (!changed) {
231
+ return schema;
232
+ }
233
+ const nextSchema = {
369
234
  ...schema,
370
235
  state: {
371
236
  ...schema.state,
372
237
  fields
373
238
  }
374
239
  };
240
+ const { hash: _hash, ...schemaWithoutHash } = nextSchema;
241
+ return {
242
+ ...nextSchema,
243
+ hash: hashSchemaSync(schemaWithoutHash)
244
+ };
375
245
  }
376
246
  function validateReservedNamespaces(schema) {
377
- const actions = schema.actions || {};
378
- for (const actionType of Object.keys(actions)) {
247
+ for (const actionType of Object.keys(schema.actions ?? {})) {
379
248
  if (actionType.startsWith(RESERVED_NAMESPACE_PREFIX)) {
380
249
  throw new ManifestoError(
381
250
  "RESERVED_NAMESPACE",
@@ -384,21 +253,131 @@ function validateReservedNamespaces(schema) {
384
253
  }
385
254
  }
386
255
  }
387
- function createInternalHost(schema, effects, initialSnapshot) {
388
- const host = createHost(schema, {
389
- initialData: initialSnapshot?.data ?? extractDefaults(schema.state)
256
+ function buildTypedMel(schema, actionParamMetadata) {
257
+ const actions = Object.fromEntries(
258
+ Object.keys(schema.actions).map((name) => {
259
+ const ref = {
260
+ __kind: "ActionRef",
261
+ name
262
+ };
263
+ Object.defineProperty(ref, ACTION_PARAM_NAMES, {
264
+ enumerable: false,
265
+ configurable: false,
266
+ writable: false,
267
+ value: Object.hasOwn(actionParamMetadata, name) ? actionParamMetadata[name] : []
268
+ });
269
+ return [name, Object.freeze(ref)];
270
+ })
271
+ );
272
+ const state = Object.fromEntries(
273
+ Object.keys(schema.state.fields).filter((name) => !name.startsWith("$")).map((name) => [name, Object.freeze({
274
+ __kind: "FieldRef",
275
+ path: name
276
+ })])
277
+ );
278
+ const computed = Object.fromEntries(
279
+ Object.keys(schema.computed.fields).map((name) => [name, Object.freeze({
280
+ __kind: "ComputedRef",
281
+ path: name
282
+ })])
283
+ );
284
+ return Object.freeze({
285
+ actions: Object.freeze(actions),
286
+ state: Object.freeze(state),
287
+ computed: Object.freeze(computed)
390
288
  });
391
- if (initialSnapshot) {
392
- host.reset(initialSnapshot);
289
+ }
290
+ function buildCreateIntent() {
291
+ return (action, ...args) => {
292
+ const actionRef = action;
293
+ const intentId = generateUUID();
294
+ const input = packIntentInput(actionRef, args);
295
+ return createCoreIntent(
296
+ String(action.name),
297
+ input,
298
+ intentId
299
+ );
300
+ };
301
+ }
302
+ function getActionParamNames(input) {
303
+ if (!input || input.type !== "object" || !input.fields) {
304
+ return [];
305
+ }
306
+ return Object.keys(input.fields);
307
+ }
308
+ function deriveActionParamMetadata(schema, actionParamOrder) {
309
+ return Object.freeze(Object.fromEntries(
310
+ Object.entries(schema.actions).map(([name, action]) => {
311
+ const preferredOrder = actionParamOrder?.[name];
312
+ if (preferredOrder && preferredOrder.length > 0) {
313
+ return [name, Object.freeze([...preferredOrder])];
314
+ }
315
+ if (!action.input || action.input.type !== "object" || !action.input.fields) {
316
+ return [name, []];
317
+ }
318
+ const fieldNames = getActionParamNames(action.input);
319
+ return [name, fieldNames.length <= 1 ? fieldNames : null];
320
+ })
321
+ ));
322
+ }
323
+ function extractActionParamOrderFromMel(source) {
324
+ const lexed = tokenizeMel(source);
325
+ if (lexed.diagnostics.some((diagnostic) => diagnostic.severity === "error")) {
326
+ return void 0;
327
+ }
328
+ const parsed = parseMel(lexed.tokens);
329
+ if (!parsed.program) {
330
+ return void 0;
331
+ }
332
+ return Object.freeze(Object.fromEntries(
333
+ parsed.program.domain.members.filter((member) => member.kind === "action").map((action) => [action.name, Object.freeze(action.params.map((param) => param.name))])
334
+ ));
335
+ }
336
+ function packIntentInput(action, args) {
337
+ const paramNames = Object.hasOwn(action, ACTION_PARAM_NAMES) ? action[ACTION_PARAM_NAMES] : [];
338
+ if (args.length === 0) {
339
+ return void 0;
340
+ }
341
+ if (paramNames === null) {
342
+ if (args.length === 1 && isPlainObject(args[0])) {
343
+ return args[0];
344
+ }
345
+ throw new ManifestoError(
346
+ "INVALID_INTENT_ARGS",
347
+ `Action "${String(action.name)}" requires a single object argument because positional parameter metadata is unavailable`
348
+ );
349
+ }
350
+ if (paramNames.length === 0) {
351
+ if (args.length === 1) {
352
+ return args[0];
353
+ }
354
+ throw new ManifestoError(
355
+ "INVALID_INTENT_ARGS",
356
+ `Action "${String(action.name)}" does not accept multiple positional arguments`
357
+ );
358
+ }
359
+ if (args.length === 1 && isPlainObject(args[0]) && paramNames.length > 1) {
360
+ return args[0];
393
361
  }
362
+ return Object.fromEntries(args.map((value, index) => [
363
+ paramNames[index] ?? `arg${index}`,
364
+ value
365
+ ]));
366
+ }
367
+ function isPlainObject(value) {
368
+ return typeof value === "object" && value !== null && !Array.isArray(value);
369
+ }
370
+ function createInternalHost(schema, effects) {
371
+ const host = createHost(schema, {
372
+ initialData: extractDefaults(schema.state)
373
+ });
394
374
  host.registerEffect(RESERVED_EFFECT_TYPE, async (_type, params, ctx) => {
395
375
  const { patches } = executeSystemGet(params, ctx.snapshot);
396
376
  return patches;
397
377
  });
398
378
  for (const [effectType, appHandler] of Object.entries(effects)) {
399
379
  const hostHandler = async (_type, params, ctx) => {
400
- const appCtx = { snapshot: ctx.snapshot };
401
- const patches = await appHandler(params, appCtx);
380
+ const patches = await appHandler(params, { snapshot: freezeSnapshot(ctx.snapshot) });
402
381
  return patches;
403
382
  };
404
383
  host.registerEffect(effectType, hostHandler);
@@ -408,6 +387,29 @@ function createInternalHost(schema, effects, initialSnapshot) {
408
387
  function isGenerateParams(params) {
409
388
  return typeof params === "object" && params !== null && "key" in params && "into" in params;
410
389
  }
390
+ function executeSystemGet(params, snapshot) {
391
+ if (isGenerateParams(params)) {
392
+ return {
393
+ patches: [{
394
+ op: "set",
395
+ path: normalizeTargetPath(params.into),
396
+ value: generateSystemValue(params.key)
397
+ }]
398
+ };
399
+ }
400
+ const { path, target } = params;
401
+ const result = resolvePathValue(path, snapshot);
402
+ if (!target) {
403
+ return { patches: [] };
404
+ }
405
+ return {
406
+ patches: [{
407
+ op: "set",
408
+ path: normalizeTargetPath(target),
409
+ value: result.value
410
+ }]
411
+ };
412
+ }
411
413
  function generateSystemValue(key) {
412
414
  switch (key) {
413
415
  case "uuid":
@@ -421,37 +423,10 @@ function generateSystemValue(key) {
421
423
  return null;
422
424
  }
423
425
  }
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 };
426
+ function normalizeTargetPath(path) {
427
+ const normalized = normalizePath(path);
428
+ const withoutDataRoot = normalized.startsWith("data.") ? normalized.slice("data.".length) : normalized;
429
+ return semanticPathToPatchPath(withoutDataRoot);
455
430
  }
456
431
  function normalizePath(path) {
457
432
  if (path.startsWith("/")) {
@@ -459,19 +434,13 @@ function normalizePath(path) {
459
434
  }
460
435
  return path;
461
436
  }
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
437
  function resolvePathValue(path, snapshot) {
468
438
  const normalized = normalizePath(path);
469
439
  const parts = normalized.split(".");
470
440
  if (parts.length === 0) {
471
441
  return { value: void 0, found: false };
472
442
  }
473
- const root = parts[0];
474
- const rest = parts.slice(1);
443
+ const [root, ...rest] = parts;
475
444
  let current;
476
445
  switch (root) {
477
446
  case "data":
@@ -489,116 +458,39 @@ function resolvePathValue(path, snapshot) {
489
458
  default:
490
459
  current = snapshot.data;
491
460
  rest.unshift(root);
461
+ break;
492
462
  }
493
463
  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") {
464
+ if (current === null || current === void 0 || typeof current !== "object") {
498
465
  return { value: void 0, found: false };
499
466
  }
500
467
  current = current[part];
501
468
  }
502
469
  return { value: current, found: current !== void 0 };
503
470
  }
504
- function generateIntentId() {
505
- return generateUUID();
471
+ function freezeSnapshot(snapshot) {
472
+ return Object.freeze(structuredClone(snapshot));
506
473
  }
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) {
474
+ function generateUUID() {
475
+ if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") {
550
476
  return crypto.randomUUID();
551
477
  }
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);
478
+ return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (char) => {
479
+ const random = Math.random() * 16 | 0;
480
+ const value = char === "x" ? random : random & 3 | 8;
481
+ return value.toString(16);
556
482
  });
557
483
  }
558
484
 
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
485
  // src/index.ts
588
- import { createIntent, createSnapshot, createCore } from "@manifesto-ai/core";
589
- import { createWorld } from "@manifesto-ai/world";
486
+ import { createSnapshot } from "@manifesto-ai/core";
590
487
  export {
488
+ AlreadyActivatedError,
591
489
  CompileError,
592
- DispatchRejectedError,
593
490
  DisposedError,
594
491
  ManifestoError,
595
492
  ReservedEffectError,
596
- createCore,
597
- createIntent,
598
493
  createManifesto,
599
- createSnapshot,
600
- createWorld,
601
- defineOps,
602
- dispatchAsync
494
+ createSnapshot
603
495
  };
604
496
  //# sourceMappingURL=index.js.map