@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/README.md +50 -29
- package/dist/chunk-CMZQTFX2.js +332 -0
- package/dist/chunk-CMZQTFX2.js.map +1 -0
- package/dist/index.d.ts +15 -386
- package/dist/index.js +267 -375
- 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,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
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
18
|
+
createIntent as createCoreIntent,
|
|
19
|
+
extractDefaults,
|
|
20
|
+
hashSchemaSync,
|
|
21
|
+
semanticPathToPatchPath
|
|
10
22
|
} from "@manifesto-ai/core";
|
|
11
|
-
import {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
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
|
-
|
|
52
|
-
|
|
53
|
-
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) {
|
|
54
33
|
throw new ReservedEffectError(RESERVED_EFFECT_TYPE);
|
|
55
34
|
}
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
let
|
|
59
|
-
const
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
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
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
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
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
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
|
-
|
|
174
|
-
|
|
175
|
-
|
|
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
|
-
|
|
179
|
-
|
|
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
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
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 (
|
|
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)
|
|
368
|
-
|
|
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
|
|
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
|
|
388
|
-
const
|
|
389
|
-
|
|
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
|
-
|
|
392
|
-
|
|
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
|
|
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
|
|
425
|
-
|
|
426
|
-
|
|
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
|
|
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
|
|
505
|
-
return
|
|
471
|
+
function freezeSnapshot(snapshot) {
|
|
472
|
+
return Object.freeze(structuredClone(snapshot));
|
|
506
473
|
}
|
|
507
|
-
|
|
508
|
-
|
|
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, (
|
|
553
|
-
const
|
|
554
|
-
const
|
|
555
|
-
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);
|
|
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 {
|
|
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
|