@manifesto-ai/sdk 2.2.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/README.md +52 -26
- package/dist/chunk-CMZQTFX2.js +332 -0
- package/dist/chunk-CMZQTFX2.js.map +1 -0
- package/dist/index.d.ts +15 -374
- package/dist/index.js +269 -365
- package/dist/index.js.map +1 -1
- package/dist/internal.d.ts +44 -0
- package/dist/internal.js +17 -0
- package/dist/internal.js.map +1 -0
- package/dist/types-oXciBlAp.d.ts +99 -0
- package/package.json +11 -8
package/dist/index.js
CHANGED
|
@@ -1,223 +1,115 @@
|
|
|
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
|
-
|
|
7
|
-
extractDefaults
|
|
18
|
+
createIntent as createCoreIntent,
|
|
19
|
+
extractDefaults,
|
|
20
|
+
hashSchemaSync,
|
|
21
|
+
semanticPathToPatchPath
|
|
8
22
|
} from "@manifesto-ai/core";
|
|
9
|
-
import {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
constructor(code, message, options) {
|
|
15
|
-
super(message, options);
|
|
16
|
-
this.name = "ManifestoError";
|
|
17
|
-
this.code = code;
|
|
18
|
-
}
|
|
19
|
-
};
|
|
20
|
-
var ReservedEffectError = class extends ManifestoError {
|
|
21
|
-
effectType;
|
|
22
|
-
constructor(effectType) {
|
|
23
|
-
super(
|
|
24
|
-
"RESERVED_EFFECT",
|
|
25
|
-
`Effect type "${effectType}" is reserved and cannot be overridden`
|
|
26
|
-
);
|
|
27
|
-
this.name = "ReservedEffectError";
|
|
28
|
-
this.effectType = effectType;
|
|
29
|
-
}
|
|
30
|
-
};
|
|
31
|
-
var CompileError = class extends ManifestoError {
|
|
32
|
-
diagnostics;
|
|
33
|
-
constructor(diagnostics, formattedMessage) {
|
|
34
|
-
super("COMPILE_ERROR", formattedMessage);
|
|
35
|
-
this.name = "CompileError";
|
|
36
|
-
this.diagnostics = diagnostics;
|
|
37
|
-
}
|
|
38
|
-
};
|
|
39
|
-
var DisposedError = class extends ManifestoError {
|
|
40
|
-
constructor() {
|
|
41
|
-
super("DISPOSED", "Cannot dispatch on a disposed ManifestoInstance");
|
|
42
|
-
this.name = "DisposedError";
|
|
43
|
-
}
|
|
44
|
-
};
|
|
45
|
-
|
|
46
|
-
// src/create-manifesto.ts
|
|
23
|
+
import {
|
|
24
|
+
compileMelDomain,
|
|
25
|
+
parse as parseMel,
|
|
26
|
+
tokenize as tokenizeMel
|
|
27
|
+
} from "@manifesto-ai/compiler";
|
|
47
28
|
var RESERVED_EFFECT_TYPE = "system.get";
|
|
48
29
|
var RESERVED_NAMESPACE_PREFIX = "system.";
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
if (RESERVED_EFFECT_TYPE in
|
|
30
|
+
var BASE_LAWS = Object.freeze({ __baseLaws: true });
|
|
31
|
+
function createManifesto(schemaInput, effects) {
|
|
32
|
+
if (RESERVED_EFFECT_TYPE in effects) {
|
|
52
33
|
throw new ReservedEffectError(RESERVED_EFFECT_TYPE);
|
|
53
34
|
}
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
let
|
|
57
|
-
const
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
if (disposed) {
|
|
64
|
-
throw new DisposedError();
|
|
65
|
-
}
|
|
66
|
-
const enrichedIntent = intent.intentId ? intent : { ...intent, intentId: generateIntentId() };
|
|
67
|
-
const prev = dispatchQueue;
|
|
68
|
-
dispatchQueue = prev.catch(() => {
|
|
69
|
-
}).then(() => processIntent(enrichedIntent));
|
|
70
|
-
dispatchQueue = dispatchQueue.catch(() => {
|
|
71
|
-
});
|
|
72
|
-
}
|
|
73
|
-
async function processIntent(intent) {
|
|
74
|
-
if (disposed) return;
|
|
75
|
-
if (guard) {
|
|
76
|
-
try {
|
|
77
|
-
const allowed = guard(intent, Object.freeze(structuredClone(currentSnapshot)));
|
|
78
|
-
if (!allowed) {
|
|
79
|
-
emitEvent("dispatch:rejected", {
|
|
80
|
-
intentId: intent.intentId,
|
|
81
|
-
intent,
|
|
82
|
-
reason: "Guard rejected the intent"
|
|
83
|
-
});
|
|
84
|
-
return;
|
|
85
|
-
}
|
|
86
|
-
} catch (error) {
|
|
87
|
-
emitEvent("dispatch:failed", {
|
|
88
|
-
intentId: intent.intentId,
|
|
89
|
-
intent,
|
|
90
|
-
error: error instanceof Error ? error : new Error(String(error))
|
|
91
|
-
});
|
|
92
|
-
return;
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
try {
|
|
96
|
-
const result = await host.dispatch(intent);
|
|
97
|
-
if (result.status === "error") {
|
|
98
|
-
currentSnapshot = result.snapshot;
|
|
99
|
-
notifySubscribers();
|
|
100
|
-
emitEvent("dispatch:failed", {
|
|
101
|
-
intentId: intent.intentId,
|
|
102
|
-
intent,
|
|
103
|
-
error: result.error ?? new ManifestoError("HOST_ERROR", "Host dispatch failed")
|
|
104
|
-
});
|
|
105
|
-
return;
|
|
106
|
-
}
|
|
107
|
-
currentSnapshot = result.snapshot;
|
|
108
|
-
notifySubscribers();
|
|
109
|
-
emitEvent("dispatch:completed", {
|
|
110
|
-
intentId: intent.intentId,
|
|
111
|
-
intent,
|
|
112
|
-
snapshot: result.snapshot
|
|
113
|
-
});
|
|
114
|
-
} catch (error) {
|
|
115
|
-
emitEvent("dispatch:failed", {
|
|
116
|
-
intentId: intent.intentId,
|
|
117
|
-
intent,
|
|
118
|
-
error: error instanceof Error ? error : new Error(String(error))
|
|
119
|
-
});
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
function subscribe(selector, listener) {
|
|
123
|
-
if (disposed) return () => {
|
|
124
|
-
};
|
|
125
|
-
const sub = {
|
|
126
|
-
selector,
|
|
127
|
-
listener,
|
|
128
|
-
lastValue: selector(currentSnapshot),
|
|
129
|
-
initialized: true
|
|
130
|
-
};
|
|
131
|
-
subscribers.add(sub);
|
|
132
|
-
return () => {
|
|
133
|
-
subscribers.delete(sub);
|
|
134
|
-
};
|
|
135
|
-
}
|
|
136
|
-
function on(event, handler) {
|
|
137
|
-
if (disposed) return () => {
|
|
138
|
-
};
|
|
139
|
-
let listeners = eventListeners.get(event);
|
|
140
|
-
if (!listeners) {
|
|
141
|
-
listeners = /* @__PURE__ */ new Set();
|
|
142
|
-
eventListeners.set(event, listeners);
|
|
143
|
-
}
|
|
144
|
-
listeners.add(handler);
|
|
145
|
-
return () => {
|
|
146
|
-
listeners.delete(handler);
|
|
147
|
-
};
|
|
148
|
-
}
|
|
149
|
-
function getSnapshot() {
|
|
150
|
-
return Object.freeze(structuredClone(currentSnapshot));
|
|
151
|
-
}
|
|
152
|
-
function dispose() {
|
|
153
|
-
if (disposed) return;
|
|
154
|
-
disposed = true;
|
|
155
|
-
subscribers.clear();
|
|
156
|
-
eventListeners.clear();
|
|
157
|
-
}
|
|
158
|
-
function notifySubscribers() {
|
|
159
|
-
const frozenSnap = Object.freeze(structuredClone(currentSnapshot));
|
|
160
|
-
for (const sub of subscribers) {
|
|
161
|
-
const selected = sub.selector(frozenSnap);
|
|
162
|
-
if (sub.initialized && Object.is(sub.lastValue, selected)) {
|
|
163
|
-
continue;
|
|
164
|
-
}
|
|
165
|
-
sub.lastValue = selected;
|
|
166
|
-
sub.initialized = true;
|
|
167
|
-
sub.listener(selected);
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
function emitEvent(event, payload) {
|
|
171
|
-
const listeners = eventListeners.get(event);
|
|
172
|
-
if (!listeners) return;
|
|
173
|
-
for (const handler of listeners) {
|
|
174
|
-
try {
|
|
175
|
-
handler(payload);
|
|
176
|
-
} catch {
|
|
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();
|
|
177
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
|
+
);
|
|
178
54
|
}
|
|
179
|
-
}
|
|
180
|
-
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
|
+
);
|
|
181
65
|
}
|
|
182
66
|
function resolveSchema(schema) {
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
}
|
|
210
|
-
if (!result.schema) {
|
|
211
|
-
throw new ManifestoError(
|
|
212
|
-
"COMPILE_ERROR",
|
|
213
|
-
"MEL compilation produced no 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}`;
|
|
83
|
+
}
|
|
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;
|
|
88
|
+
}
|
|
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
|
|
214
93
|
);
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
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}`);
|
|
219
101
|
}
|
|
220
|
-
|
|
102
|
+
if (!result.schema) {
|
|
103
|
+
throw new ManifestoError("COMPILE_ERROR", "MEL compilation produced no schema");
|
|
104
|
+
}
|
|
105
|
+
const schema = result.schema;
|
|
106
|
+
return {
|
|
107
|
+
schema,
|
|
108
|
+
actionParamMetadata: deriveActionParamMetadata(
|
|
109
|
+
schema,
|
|
110
|
+
extractActionParamOrderFromMel(source)
|
|
111
|
+
)
|
|
112
|
+
};
|
|
221
113
|
}
|
|
222
114
|
function withPlatformNamespaces(schema) {
|
|
223
115
|
const fields = { ...schema.state.fields };
|
|
@@ -230,10 +122,7 @@ function withPlatformNamespaces(schema) {
|
|
|
230
122
|
};
|
|
231
123
|
changed = true;
|
|
232
124
|
} else if (fields.$host.type !== "object") {
|
|
233
|
-
throw new ManifestoError(
|
|
234
|
-
"SCHEMA_ERROR",
|
|
235
|
-
"Reserved namespace '$host' must be an object field"
|
|
236
|
-
);
|
|
125
|
+
throw new ManifestoError("SCHEMA_ERROR", "Reserved namespace '$host' must be an object field");
|
|
237
126
|
} else if (fields.$host.default === void 0) {
|
|
238
127
|
fields.$host = { ...fields.$host, default: {} };
|
|
239
128
|
changed = true;
|
|
@@ -260,10 +149,7 @@ function withPlatformNamespaces(schema) {
|
|
|
260
149
|
};
|
|
261
150
|
changed = true;
|
|
262
151
|
} else if (fields.$mel.type !== "object") {
|
|
263
|
-
throw new ManifestoError(
|
|
264
|
-
"SCHEMA_ERROR",
|
|
265
|
-
"Reserved namespace '$mel' must be an object field"
|
|
266
|
-
);
|
|
152
|
+
throw new ManifestoError("SCHEMA_ERROR", "Reserved namespace '$mel' must be an object field");
|
|
267
153
|
} else {
|
|
268
154
|
let nextMel = fields.$mel;
|
|
269
155
|
if (nextMel.default === void 0) {
|
|
@@ -293,13 +179,10 @@ function withPlatformNamespaces(schema) {
|
|
|
293
179
|
};
|
|
294
180
|
changed = true;
|
|
295
181
|
} else if (guardsField.type !== "object") {
|
|
296
|
-
throw new ManifestoError(
|
|
297
|
-
"SCHEMA_ERROR",
|
|
298
|
-
"Reserved namespace '$mel.guards' must be an object field"
|
|
299
|
-
);
|
|
182
|
+
throw new ManifestoError("SCHEMA_ERROR", "Reserved namespace '$mel.guards' must be an object field");
|
|
300
183
|
} else {
|
|
301
184
|
let nextGuards = guardsField;
|
|
302
|
-
if (
|
|
185
|
+
if (nextGuards.default === void 0) {
|
|
303
186
|
nextGuards = { ...nextGuards, default: { intent: {} } };
|
|
304
187
|
changed = true;
|
|
305
188
|
}
|
|
@@ -319,10 +202,7 @@ function withPlatformNamespaces(schema) {
|
|
|
319
202
|
};
|
|
320
203
|
changed = true;
|
|
321
204
|
} else if (intentField.type !== "object") {
|
|
322
|
-
throw new ManifestoError(
|
|
323
|
-
"SCHEMA_ERROR",
|
|
324
|
-
"Reserved namespace '$mel.guards.intent' must be an object field"
|
|
325
|
-
);
|
|
205
|
+
throw new ManifestoError("SCHEMA_ERROR", "Reserved namespace '$mel.guards.intent' must be an object field");
|
|
326
206
|
} else if (intentField.default === void 0) {
|
|
327
207
|
nextGuards = {
|
|
328
208
|
...nextGuards,
|
|
@@ -345,21 +225,26 @@ function withPlatformNamespaces(schema) {
|
|
|
345
225
|
}
|
|
346
226
|
if (nextMel !== fields.$mel) {
|
|
347
227
|
fields.$mel = nextMel;
|
|
348
|
-
changed = true;
|
|
349
228
|
}
|
|
350
229
|
}
|
|
351
|
-
if (!changed)
|
|
352
|
-
|
|
230
|
+
if (!changed) {
|
|
231
|
+
return schema;
|
|
232
|
+
}
|
|
233
|
+
const nextSchema = {
|
|
353
234
|
...schema,
|
|
354
235
|
state: {
|
|
355
236
|
...schema.state,
|
|
356
237
|
fields
|
|
357
238
|
}
|
|
358
239
|
};
|
|
240
|
+
const { hash: _hash, ...schemaWithoutHash } = nextSchema;
|
|
241
|
+
return {
|
|
242
|
+
...nextSchema,
|
|
243
|
+
hash: hashSchemaSync(schemaWithoutHash)
|
|
244
|
+
};
|
|
359
245
|
}
|
|
360
246
|
function validateReservedNamespaces(schema) {
|
|
361
|
-
const
|
|
362
|
-
for (const actionType of Object.keys(actions)) {
|
|
247
|
+
for (const actionType of Object.keys(schema.actions ?? {})) {
|
|
363
248
|
if (actionType.startsWith(RESERVED_NAMESPACE_PREFIX)) {
|
|
364
249
|
throw new ManifestoError(
|
|
365
250
|
"RESERVED_NAMESPACE",
|
|
@@ -368,21 +253,131 @@ function validateReservedNamespaces(schema) {
|
|
|
368
253
|
}
|
|
369
254
|
}
|
|
370
255
|
}
|
|
371
|
-
function
|
|
372
|
-
const
|
|
373
|
-
|
|
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)
|
|
374
288
|
});
|
|
375
|
-
|
|
376
|
-
|
|
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 [];
|
|
377
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];
|
|
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
|
+
});
|
|
378
374
|
host.registerEffect(RESERVED_EFFECT_TYPE, async (_type, params, ctx) => {
|
|
379
375
|
const { patches } = executeSystemGet(params, ctx.snapshot);
|
|
380
376
|
return patches;
|
|
381
377
|
});
|
|
382
378
|
for (const [effectType, appHandler] of Object.entries(effects)) {
|
|
383
379
|
const hostHandler = async (_type, params, ctx) => {
|
|
384
|
-
const
|
|
385
|
-
const patches = await appHandler(params, appCtx);
|
|
380
|
+
const patches = await appHandler(params, { snapshot: freezeSnapshot(ctx.snapshot) });
|
|
386
381
|
return patches;
|
|
387
382
|
};
|
|
388
383
|
host.registerEffect(effectType, hostHandler);
|
|
@@ -392,6 +387,29 @@ function createInternalHost(schema, effects, initialSnapshot) {
|
|
|
392
387
|
function isGenerateParams(params) {
|
|
393
388
|
return typeof params === "object" && params !== null && "key" in params && "into" in params;
|
|
394
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
|
+
}
|
|
395
413
|
function generateSystemValue(key) {
|
|
396
414
|
switch (key) {
|
|
397
415
|
case "uuid":
|
|
@@ -405,37 +423,10 @@ function generateSystemValue(key) {
|
|
|
405
423
|
return null;
|
|
406
424
|
}
|
|
407
425
|
}
|
|
408
|
-
function
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => {
|
|
413
|
-
const r = Math.random() * 16 | 0;
|
|
414
|
-
const v = c === "x" ? r : r & 3 | 8;
|
|
415
|
-
return v.toString(16);
|
|
416
|
-
});
|
|
417
|
-
}
|
|
418
|
-
function executeSystemGet(params, snapshot) {
|
|
419
|
-
if (isGenerateParams(params)) {
|
|
420
|
-
const value = generateSystemValue(params.key);
|
|
421
|
-
const patches2 = [{
|
|
422
|
-
op: "set",
|
|
423
|
-
path: normalizeTargetPath(params.into),
|
|
424
|
-
value
|
|
425
|
-
}];
|
|
426
|
-
return { patches: patches2 };
|
|
427
|
-
}
|
|
428
|
-
const { path, target } = params;
|
|
429
|
-
const result = resolvePathValue(path, snapshot);
|
|
430
|
-
const patches = [];
|
|
431
|
-
if (target) {
|
|
432
|
-
patches.push({
|
|
433
|
-
op: "set",
|
|
434
|
-
path: normalizeTargetPath(target),
|
|
435
|
-
value: result.value
|
|
436
|
-
});
|
|
437
|
-
}
|
|
438
|
-
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);
|
|
439
430
|
}
|
|
440
431
|
function normalizePath(path) {
|
|
441
432
|
if (path.startsWith("/")) {
|
|
@@ -443,19 +434,13 @@ function normalizePath(path) {
|
|
|
443
434
|
}
|
|
444
435
|
return path;
|
|
445
436
|
}
|
|
446
|
-
function normalizeTargetPath(path) {
|
|
447
|
-
const normalized = normalizePath(path);
|
|
448
|
-
const withoutDataRoot = normalized.startsWith("data.") ? normalized.slice("data.".length) : normalized;
|
|
449
|
-
return semanticPathToPatchPath(withoutDataRoot);
|
|
450
|
-
}
|
|
451
437
|
function resolvePathValue(path, snapshot) {
|
|
452
438
|
const normalized = normalizePath(path);
|
|
453
439
|
const parts = normalized.split(".");
|
|
454
440
|
if (parts.length === 0) {
|
|
455
441
|
return { value: void 0, found: false };
|
|
456
442
|
}
|
|
457
|
-
const root = parts
|
|
458
|
-
const rest = parts.slice(1);
|
|
443
|
+
const [root, ...rest] = parts;
|
|
459
444
|
let current;
|
|
460
445
|
switch (root) {
|
|
461
446
|
case "data":
|
|
@@ -473,120 +458,39 @@ function resolvePathValue(path, snapshot) {
|
|
|
473
458
|
default:
|
|
474
459
|
current = snapshot.data;
|
|
475
460
|
rest.unshift(root);
|
|
461
|
+
break;
|
|
476
462
|
}
|
|
477
463
|
for (const part of rest) {
|
|
478
|
-
if (current === null || current === void 0) {
|
|
479
|
-
return { value: void 0, found: false };
|
|
480
|
-
}
|
|
481
|
-
if (typeof current !== "object") {
|
|
464
|
+
if (current === null || current === void 0 || typeof current !== "object") {
|
|
482
465
|
return { value: void 0, found: false };
|
|
483
466
|
}
|
|
484
467
|
current = current[part];
|
|
485
468
|
}
|
|
486
469
|
return { value: current, found: current !== void 0 };
|
|
487
470
|
}
|
|
488
|
-
function
|
|
489
|
-
return
|
|
471
|
+
function freezeSnapshot(snapshot) {
|
|
472
|
+
return Object.freeze(structuredClone(snapshot));
|
|
490
473
|
}
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
var DispatchRejectedError = class extends Error {
|
|
494
|
-
code = "DISPATCH_REJECTED";
|
|
495
|
-
intentId;
|
|
496
|
-
constructor(intentId, reason) {
|
|
497
|
-
super(reason ?? "Intent was rejected by guard");
|
|
498
|
-
this.name = "DispatchRejectedError";
|
|
499
|
-
this.intentId = intentId;
|
|
500
|
-
}
|
|
501
|
-
};
|
|
502
|
-
function dispatchAsync(instance, intent) {
|
|
503
|
-
const intentId = intent.intentId ?? generateId();
|
|
504
|
-
const enriched = intent.intentId ? intent : { ...intent, intentId };
|
|
505
|
-
return new Promise((resolve, reject) => {
|
|
506
|
-
const cleanup = () => {
|
|
507
|
-
unsubCompleted();
|
|
508
|
-
unsubFailed();
|
|
509
|
-
unsubRejected();
|
|
510
|
-
};
|
|
511
|
-
const unsubCompleted = instance.on("dispatch:completed", (e) => {
|
|
512
|
-
if (e.intentId === intentId) {
|
|
513
|
-
cleanup();
|
|
514
|
-
resolve(e.snapshot);
|
|
515
|
-
}
|
|
516
|
-
});
|
|
517
|
-
const unsubFailed = instance.on("dispatch:failed", (e) => {
|
|
518
|
-
if (e.intentId === intentId) {
|
|
519
|
-
cleanup();
|
|
520
|
-
reject(e.error ?? new Error("Dispatch failed"));
|
|
521
|
-
}
|
|
522
|
-
});
|
|
523
|
-
const unsubRejected = instance.on("dispatch:rejected", (e) => {
|
|
524
|
-
if (e.intentId === intentId) {
|
|
525
|
-
cleanup();
|
|
526
|
-
reject(new DispatchRejectedError(intentId, e.reason));
|
|
527
|
-
}
|
|
528
|
-
});
|
|
529
|
-
instance.dispatch(enriched);
|
|
530
|
-
});
|
|
531
|
-
}
|
|
532
|
-
function generateId() {
|
|
533
|
-
if (typeof crypto !== "undefined" && crypto.randomUUID) {
|
|
474
|
+
function generateUUID() {
|
|
475
|
+
if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") {
|
|
534
476
|
return crypto.randomUUID();
|
|
535
477
|
}
|
|
536
|
-
return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (
|
|
537
|
-
const
|
|
538
|
-
const
|
|
539
|
-
return
|
|
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);
|
|
540
482
|
});
|
|
541
483
|
}
|
|
542
484
|
|
|
543
|
-
// src/typed-ops.ts
|
|
544
|
-
import { semanticPathToPatchPath as semanticPathToPatchPath2 } from "@manifesto-ai/core";
|
|
545
|
-
function defineOps() {
|
|
546
|
-
const toPatchPath = (path) => semanticPathToPatchPath2(path);
|
|
547
|
-
return {
|
|
548
|
-
set(path, value) {
|
|
549
|
-
return { op: "set", path: toPatchPath(path), value };
|
|
550
|
-
},
|
|
551
|
-
unset(path) {
|
|
552
|
-
return { op: "unset", path: toPatchPath(path) };
|
|
553
|
-
},
|
|
554
|
-
merge(path, value) {
|
|
555
|
-
return { op: "merge", path: toPatchPath(path), value };
|
|
556
|
-
},
|
|
557
|
-
raw: {
|
|
558
|
-
set(path, value) {
|
|
559
|
-
return { op: "set", path: toPatchPath(path), value };
|
|
560
|
-
},
|
|
561
|
-
unset(path) {
|
|
562
|
-
return { op: "unset", path: toPatchPath(path) };
|
|
563
|
-
},
|
|
564
|
-
merge(path, value) {
|
|
565
|
-
return { op: "merge", path: toPatchPath(path), value };
|
|
566
|
-
}
|
|
567
|
-
}
|
|
568
|
-
};
|
|
569
|
-
}
|
|
570
|
-
|
|
571
485
|
// src/index.ts
|
|
572
|
-
import {
|
|
573
|
-
import {
|
|
574
|
-
createInMemoryWorldStore,
|
|
575
|
-
createWorld
|
|
576
|
-
} from "@manifesto-ai/world";
|
|
486
|
+
import { createSnapshot } from "@manifesto-ai/core";
|
|
577
487
|
export {
|
|
488
|
+
AlreadyActivatedError,
|
|
578
489
|
CompileError,
|
|
579
|
-
DispatchRejectedError,
|
|
580
490
|
DisposedError,
|
|
581
491
|
ManifestoError,
|
|
582
492
|
ReservedEffectError,
|
|
583
|
-
createCore,
|
|
584
|
-
createInMemoryWorldStore,
|
|
585
|
-
createIntent,
|
|
586
493
|
createManifesto,
|
|
587
|
-
createSnapshot
|
|
588
|
-
createWorld,
|
|
589
|
-
defineOps,
|
|
590
|
-
dispatchAsync
|
|
494
|
+
createSnapshot
|
|
591
495
|
};
|
|
592
496
|
//# sourceMappingURL=index.js.map
|