@statelyai/agent 2.0.0-alpha.28 → 2.0.0-alpha.30
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/ai-sdk.cjs +150 -27
- package/dist/ai-sdk.d.cts +59 -36
- package/dist/ai-sdk.d.mts +59 -36
- package/dist/ai-sdk.mjs +148 -24
- package/dist/{decision-RQ0iv0oZ.mjs → decision-BHkvuImD.mjs} +74 -8
- package/dist/{decision-CmM8-HHz.cjs → decision-CIb7ddIv.cjs} +113 -30
- package/dist/{text-logic-f5F5sCdc.cjs → event-log-BZRfBRd7.cjs} +814 -7
- package/dist/{text-logic-CIqHAmBi.mjs → event-log-DJCMHek_.mjs} +680 -4
- package/dist/{event-log-store-BIPOz-di.d.mts → event-log-store-CIIJohjj.d.mts} +90 -5
- package/dist/{event-log-store-2xzFmgr2.d.cts → event-log-store-CLAC9q2Y.d.cts} +90 -5
- package/dist/event-log-store-DZR4IIWe.cjs +95 -0
- package/dist/event-log-store-DsP6GCRh.mjs +84 -0
- package/dist/index.cjs +576 -58
- package/dist/index.d.cts +104 -510
- package/dist/index.d.mts +104 -510
- package/dist/index.mjs +547 -32
- package/dist/log.cjs +77 -20
- package/dist/log.d.cts +5 -5
- package/dist/log.d.mts +5 -5
- package/dist/log.mjs +58 -3
- package/dist/machines.cjs +1 -1
- package/dist/machines.d.cts +15 -15
- package/dist/machines.d.mts +15 -15
- package/dist/machines.mjs +1 -1
- package/dist/model-source-BCKg4qJ1.cjs +44 -0
- package/dist/model-source-BaHwJ1wK.mjs +39 -0
- package/dist/openai.cjs +11 -11
- package/dist/openai.d.cts +28 -26
- package/dist/openai.d.mts +28 -26
- package/dist/openai.mjs +3 -3
- package/dist/otel.cjs +5 -4
- package/dist/otel.d.cts +5 -7
- package/dist/otel.d.mts +5 -7
- package/dist/otel.mjs +5 -3
- package/dist/{run-agent-xNTxpt82.mjs → run-agent-BpHqkaZw.mjs} +181 -44
- package/dist/{run-agent-COXXc0RW.d.mts → run-agent-CAVt5R-r.d.mts} +95 -30
- package/dist/{run-agent-ByO-Bxyd.d.cts → run-agent-CTlMc3Jb.d.cts} +95 -30
- package/dist/{run-agent-Dmf8GV2d.cjs → run-agent-ctLCvNgL.cjs} +230 -88
- package/dist/{setup-agent-BuanDXeh.mjs → setup-agent-7rV_cujV.mjs} +15 -9
- package/dist/setup-agent-CGELn1qZ.d.mts +577 -0
- package/dist/setup-agent-CLPCkXsu.d.cts +577 -0
- package/dist/{setup-agent-DV4cTou-.cjs → setup-agent-DoUk7EdC.cjs} +31 -20
- package/dist/tanstack-ai.cjs +627 -0
- package/dist/tanstack-ai.d.cts +204 -0
- package/dist/tanstack-ai.d.mts +204 -0
- package/dist/tanstack-ai.mjs +618 -0
- package/dist/testing.cjs +204 -985
- package/dist/testing.d.cts +132 -347
- package/dist/testing.d.mts +132 -347
- package/dist/testing.mjs +191 -973
- package/dist/{text-logic-IjfYy9DP.d.cts → text-logic-BRYOPWvY.d.mts} +52 -12
- package/dist/{text-logic-D-czVPYp.d.mts → text-logic-DmciuVUQ.d.cts} +52 -12
- package/dist/{types-BgNbNKnJ.d.mts → types-Dp5_Ru4R.d.cts} +2 -2
- package/dist/{types-hR5f5YXa.d.cts → types-Dp5_Ru4R.d.mts} +2 -2
- package/dist/usage-BkM3z02Y.d.mts +17 -0
- package/dist/usage-Cm_ovz9V.d.cts +17 -0
- package/dist/{utils-_q7F-AZu.d.mts → utils-BnXdWih3.d.mts} +1 -2
- package/dist/{utils-o4YRdHJX.d.cts → utils-ebVpCYoF.d.cts} +1 -2
- package/dist/validate.cjs +239 -8
- package/dist/validate.d.cts +110 -3
- package/dist/validate.d.mts +110 -3
- package/dist/validate.mjs +238 -7
- package/dist/verify-COFWyprJ.mjs +1181 -0
- package/dist/verify-CVlsTZ-V.cjs +1222 -0
- package/dist/verify-Cn86rT8l.d.mts +414 -0
- package/dist/verify-Dzwd4Mvk.d.cts +414 -0
- package/package.json +44 -31
- package/readme.md +40 -28
- package/skills/add-evals/SKILL.md +129 -0
- package/skills/add-traces/SKILL.md +135 -0
- package/skills/generate-machine/SKILL.md +143 -69
- package/skills/graph-engineering/SKILL.md +33 -0
- package/skills/improve-machine/SKILL.md +241 -0
- package/skills/improve-machine/reference.md +101 -0
- package/skills/loop-to-machine/SKILL.md +183 -0
- package/skills/loop-to-machine/policy.md +158 -0
- package/dist/event-log-store-2pAFiWuc.mjs +0 -576
- package/dist/event-log-store-C-COhIXP.cjs +0 -702
- package/dist/usage-BdEjFuIi.mjs +0 -5
- package/dist/usage-efOQPdf_.cjs +0 -10
package/dist/validate.cjs
CHANGED
|
@@ -16,11 +16,14 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
16
16
|
}
|
|
17
17
|
return to;
|
|
18
18
|
};
|
|
19
|
-
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
|
|
19
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule || !__hasOwnProp.call(mod, "default") ? __defProp(target, "default", {
|
|
20
20
|
value: mod,
|
|
21
21
|
enumerable: true
|
|
22
22
|
}) : target, mod));
|
|
23
23
|
//#endregion
|
|
24
|
+
const require_event_log = require("./event-log-BZRfBRd7.cjs");
|
|
25
|
+
const require_setup_agent = require("./setup-agent-DoUk7EdC.cjs");
|
|
26
|
+
const require_verify = require("./verify-CVlsTZ-V.cjs");
|
|
24
27
|
let ajv_dist_2020_js = require("ajv/dist/2020.js");
|
|
25
28
|
ajv_dist_2020_js = __toESM(ajv_dist_2020_js, 1);
|
|
26
29
|
//#region schemas/agent-workflow.json
|
|
@@ -383,13 +386,10 @@ var agent_workflow_default = {
|
|
|
383
386
|
}
|
|
384
387
|
};
|
|
385
388
|
//#endregion
|
|
386
|
-
//#region src/validate/
|
|
389
|
+
//#region src/validate/validate-config.ts
|
|
387
390
|
/**
|
|
388
|
-
* Schema validation for agent workflow configs.
|
|
389
|
-
*
|
|
390
|
-
* Lives behind the `@statelyai/agent/validate` subpath so the core package
|
|
391
|
-
* stays dependency-free. This module imports `ajv`, which is declared as an
|
|
392
|
-
* optional peer dependency.
|
|
391
|
+
* Schema validation for agent workflow configs. Imports `ajv`, an optional
|
|
392
|
+
* peer dependency of the package.
|
|
393
393
|
*/
|
|
394
394
|
let compiledWorkflowValidator;
|
|
395
395
|
function getWorkflowValidator() {
|
|
@@ -424,5 +424,236 @@ function validateAgentConfig(config) {
|
|
|
424
424
|
};
|
|
425
425
|
}
|
|
426
426
|
//#endregion
|
|
427
|
-
|
|
427
|
+
//#region src/validate/verify-config.ts
|
|
428
|
+
const BUILTIN_SRCS = [
|
|
429
|
+
require_event_log.DECIDE_ACTOR,
|
|
430
|
+
require_event_log.GENERATE_TEXT_ACTOR,
|
|
431
|
+
require_event_log.STREAM_TEXT_ACTOR
|
|
432
|
+
];
|
|
433
|
+
const MAX_DETAIL_LINES = 10;
|
|
434
|
+
/**
|
|
435
|
+
* Runs every pre-run gate on a model-authored workflow config and stops at
|
|
436
|
+
* the first failure. Never throws on a bad config: each failure becomes a gate
|
|
437
|
+
* record whose `detail` is a repair prompt.
|
|
438
|
+
*
|
|
439
|
+
* - `validate`: the config's shape, against the shipped JSON Schema.
|
|
440
|
+
* - `vocabulary`: names the config references, against `allow`.
|
|
441
|
+
* - `lower`: `setupAgent.fromConfig` (unresolved guards/actions, bad targets).
|
|
442
|
+
* - `lint`: `lintAgentMachine` (errors fail; warnings fail with `lint.warnings`).
|
|
443
|
+
* - `explore`: `explorePaths` from each `explore.inputs` entry; every terminal
|
|
444
|
+
* must be one of `explore.terminals`, no cap (`maxPaths`, `maxNodes`) may cut
|
|
445
|
+
* it short, every event's payloads must be tried (`unexpandedEvents`), and
|
|
446
|
+
* every reached text request or invoke needs an `explore.outputs` entry.
|
|
447
|
+
*
|
|
448
|
+
* @example
|
|
449
|
+
* ```ts
|
|
450
|
+
* const result = await verifyAgentConfig(candidate, { compileSchema, allow: { events: ["APPROVE", "DENY"] } });
|
|
451
|
+
* const failed = result.gates.find((gate) => !gate.ok);
|
|
452
|
+
* if (failed) feedback.push(`gate '${failed.name}' failed: ${failed.detail}`);
|
|
453
|
+
* ```
|
|
454
|
+
*/
|
|
455
|
+
async function verifyAgentConfig(config, options) {
|
|
456
|
+
const gates = [];
|
|
457
|
+
const record = (name, problems, notes = []) => {
|
|
458
|
+
const lines = problems.length ? problems : notes;
|
|
459
|
+
gates.push({
|
|
460
|
+
name,
|
|
461
|
+
ok: problems.length === 0,
|
|
462
|
+
...lines.length ? { detail: formatDetail(lines) } : {}
|
|
463
|
+
});
|
|
464
|
+
return problems.length === 0;
|
|
465
|
+
};
|
|
466
|
+
const fail = (extra = {}) => ({
|
|
467
|
+
ok: false,
|
|
468
|
+
gates,
|
|
469
|
+
...extra
|
|
470
|
+
});
|
|
471
|
+
if (!record("validate", validateAgentConfig(config).errors.map((error) => `${error.path} ${error.message}`))) return fail();
|
|
472
|
+
const typed = config;
|
|
473
|
+
if (options.allow && !record("vocabulary", checkVocabulary(typed, options.allow))) return fail({ config: typed });
|
|
474
|
+
let machine;
|
|
475
|
+
try {
|
|
476
|
+
machine = require_setup_agent.setupAgentFromConfig(typed, {
|
|
477
|
+
compileSchema: options.compileSchema,
|
|
478
|
+
...options.guards ? { guards: options.guards } : {},
|
|
479
|
+
...options.actions ? { actions: options.actions } : {}
|
|
480
|
+
}).machine;
|
|
481
|
+
if (options.actors) machine = machine.provide({ actors: options.actors });
|
|
482
|
+
} catch (error) {
|
|
483
|
+
record("lower", [errorMessage(error)]);
|
|
484
|
+
return fail({ config: typed });
|
|
485
|
+
}
|
|
486
|
+
record("lower", []);
|
|
487
|
+
const diagnostics = require_verify.lintAgentMachine(machine).map((d) => ({
|
|
488
|
+
failing: d.severity === "error" || options.lint?.warnings === true,
|
|
489
|
+
line: `${d.severity} ${d.code} at '${d.path}': ${d.message}`
|
|
490
|
+
}));
|
|
491
|
+
if (!record("lint", diagnostics.filter((d) => d.failing).map((d) => d.line), diagnostics.map((d) => d.line))) return fail({
|
|
492
|
+
config: typed,
|
|
493
|
+
machine
|
|
494
|
+
});
|
|
495
|
+
if (options.explore && !record("explore", await checkExplore(machine, options.explore))) return fail({
|
|
496
|
+
config: typed,
|
|
497
|
+
machine
|
|
498
|
+
});
|
|
499
|
+
return {
|
|
500
|
+
ok: true,
|
|
501
|
+
gates,
|
|
502
|
+
config: typed,
|
|
503
|
+
machine
|
|
504
|
+
};
|
|
505
|
+
}
|
|
506
|
+
/** A config's `T | T[]` field as a list of objects. */
|
|
507
|
+
const nodes = (value) => (value === void 0 ? [] : Array.isArray(value) ? value : [value]).filter((node) => !!node && typeof node === "object");
|
|
508
|
+
const hasTemplate = (value) => typeof value === "string" && value.includes("{{");
|
|
509
|
+
const list = (names) => names.length ? names.join(", ") : "(none)";
|
|
510
|
+
/** Every state in the config, depth-first, with its dotted path. */
|
|
511
|
+
function walkStates(states, prefix = "") {
|
|
512
|
+
if (!states || typeof states !== "object") return [];
|
|
513
|
+
return Object.entries(states).flatMap(([key, state]) => {
|
|
514
|
+
const path = prefix ? `${prefix}.${key}` : key;
|
|
515
|
+
return [{
|
|
516
|
+
path,
|
|
517
|
+
state
|
|
518
|
+
}, ...walkStates(state?.states, path)];
|
|
519
|
+
});
|
|
520
|
+
}
|
|
521
|
+
/** Every transition on a state: `on`, `after`, `always`, `choice`, `onDone`, and invoke done/error. */
|
|
522
|
+
function transitionsOf(state) {
|
|
523
|
+
return [
|
|
524
|
+
...Object.values(state.on ?? {}).flatMap(nodes),
|
|
525
|
+
...Object.values(state.after ?? {}).flatMap(nodes),
|
|
526
|
+
...nodes(state.always),
|
|
527
|
+
...nodes(state.choice),
|
|
528
|
+
...nodes(state.onDone),
|
|
529
|
+
...nodes(state.invoke).flatMap((invoke) => [...nodes(invoke.onDone), ...nodes(invoke.onError)])
|
|
530
|
+
];
|
|
531
|
+
}
|
|
532
|
+
/**
|
|
533
|
+
* Paths of raw xstate expression slots (`{ "@expr": ... }`, `{ "@code": ... }`).
|
|
534
|
+
* xstate evaluates such an object whole, ignoring its literal siblings, so a
|
|
535
|
+
* slot would hide the model ref or `allowedEvents` the checks below read.
|
|
536
|
+
*/
|
|
537
|
+
function rawExpressionPaths(value, path) {
|
|
538
|
+
if (Array.isArray(value)) return value.flatMap((item, index) => rawExpressionPaths(item, `${path}[${index}]`));
|
|
539
|
+
if (!value || typeof value !== "object") return [];
|
|
540
|
+
const node = value;
|
|
541
|
+
if (typeof node["@expr"] === "string" || typeof node["@code"] === "string") return [path];
|
|
542
|
+
return Object.entries(node).flatMap(([key, item]) => rawExpressionPaths(item, path ? `${path}.${key}` : key));
|
|
543
|
+
}
|
|
544
|
+
function checkVocabulary(config, allow) {
|
|
545
|
+
const problems = rawExpressionPaths(config, "").map((path) => `${path || "(root)"} uses a raw '@expr' slot, which the vocabulary cannot check; write {{ }} templates instead`);
|
|
546
|
+
const checkModel = (where, model) => {
|
|
547
|
+
if (!allow.models) return;
|
|
548
|
+
if (typeof model !== "string" || hasTemplate(model)) problems.push(`${where} needs a literal string model ref; allowed: ${list(allow.models)}`);
|
|
549
|
+
else if (!allow.models.includes(model)) problems.push(`${where} uses model '${model}'; allowed: ${list(allow.models)}`);
|
|
550
|
+
};
|
|
551
|
+
for (const [kind, declared, allowed] of [[
|
|
552
|
+
"request",
|
|
553
|
+
config.requests,
|
|
554
|
+
allow.requests
|
|
555
|
+
], [
|
|
556
|
+
"actor",
|
|
557
|
+
config.actors,
|
|
558
|
+
allow.actors
|
|
559
|
+
]]) {
|
|
560
|
+
if (!allowed) continue;
|
|
561
|
+
for (const key of Object.keys(declared ?? {})) if (!allowed.includes(key)) problems.push(`${kind} '${key}' is not in the vocabulary; allowed: ${list(allowed)}`);
|
|
562
|
+
}
|
|
563
|
+
for (const [key, request] of Object.entries(config.requests ?? {})) checkModel(`request '${key}'`, request.model);
|
|
564
|
+
const srcs = allow.actors ? [
|
|
565
|
+
...BUILTIN_SRCS,
|
|
566
|
+
...allow.actors,
|
|
567
|
+
...allow.requests ?? Object.keys(config.requests ?? {})
|
|
568
|
+
] : void 0;
|
|
569
|
+
for (const { path, state } of walkStates(config.states)) {
|
|
570
|
+
for (const invoke of nodes(state.invoke)) {
|
|
571
|
+
const src = String(invoke.src);
|
|
572
|
+
if (srcs && !srcs.includes(src)) {
|
|
573
|
+
problems.push(`state '${path}' invokes unknown src '${src}'; allowed: ${list(srcs)}`);
|
|
574
|
+
continue;
|
|
575
|
+
}
|
|
576
|
+
if (!BUILTIN_SRCS.includes(src)) continue;
|
|
577
|
+
const input = invoke.input;
|
|
578
|
+
if ((allow.models || src === "agent.decide" && allow.events) && !isPlainObject(input)) {
|
|
579
|
+
problems.push(`state '${path}': '${src}' input must be a literal object`);
|
|
580
|
+
continue;
|
|
581
|
+
}
|
|
582
|
+
checkModel(`state '${path}': '${src}'`, input?.model);
|
|
583
|
+
if (src !== "agent.decide" || !allow.events) continue;
|
|
584
|
+
const allowedEvents = input.allowedEvents;
|
|
585
|
+
if (!Array.isArray(allowedEvents) || allowedEvents.length === 0) {
|
|
586
|
+
problems.push(`state '${path}': agent.decide needs a literal, non-empty allowedEvents list; allowed: ${list(allow.events)}`);
|
|
587
|
+
continue;
|
|
588
|
+
}
|
|
589
|
+
for (const type of allowedEvents) if (typeof type !== "string" || !allow.events.includes(type)) problems.push(`state '${path}': agent.decide allowedEvents entry '${String(type)}' is not allowed; allowed: ${list(allow.events)}`);
|
|
590
|
+
}
|
|
591
|
+
const actionsAt = [["entry", state.entry], ["exit", state.exit]];
|
|
592
|
+
for (const transition of transitionsOf(state)) {
|
|
593
|
+
const guard = transition.guard;
|
|
594
|
+
if (allow.guards && typeof guard === "string" && !hasTemplate(guard) && !allow.guards.includes(guard)) problems.push(`state '${path}' uses unknown named guard '${guard}'; allowed: ${list(allow.guards)}`);
|
|
595
|
+
actionsAt.push(["a transition", transition.actions]);
|
|
596
|
+
}
|
|
597
|
+
if (!allow.actions) continue;
|
|
598
|
+
for (const [where, actions] of actionsAt) for (const action of nodes(actions)) if (typeof action.type === "string" && !allow.actions.includes(action.type)) problems.push(`state '${path}' ${where} uses unknown named action '${action.type}'; allowed: ${list(allow.actions)}`);
|
|
599
|
+
}
|
|
600
|
+
return problems;
|
|
601
|
+
}
|
|
602
|
+
const isPlainObject = (value) => !!value && typeof value === "object" && !Array.isArray(value);
|
|
603
|
+
async function checkExplore(machine, options) {
|
|
604
|
+
const { inputs, terminals = ["done"], ...rest } = options;
|
|
605
|
+
if (inputs.length === 0) return ["explore.inputs is empty, so no path was explored; give at least one input"];
|
|
606
|
+
const allowed = terminals;
|
|
607
|
+
const maxDepth = options.maxDepth ?? 8;
|
|
608
|
+
const problems = /* @__PURE__ */ new Set();
|
|
609
|
+
for (const [index, input] of inputs.entries()) {
|
|
610
|
+
const at = inputs.length > 1 ? `input ${index}: ` : "";
|
|
611
|
+
let report;
|
|
612
|
+
try {
|
|
613
|
+
report = await require_verify.explorePaths(machine, {
|
|
614
|
+
...rest,
|
|
615
|
+
input
|
|
616
|
+
});
|
|
617
|
+
} catch (error) {
|
|
618
|
+
problems.add(`${at}exploration threw: ${errorMessage(error)}`);
|
|
619
|
+
continue;
|
|
620
|
+
}
|
|
621
|
+
for (const terminal of report.terminals) {
|
|
622
|
+
if (allowed.includes(terminal.status)) continue;
|
|
623
|
+
const trail = `path [${terminal.path.map((event) => event.type).join(", ")}]`;
|
|
624
|
+
const state = JSON.stringify(terminal.state);
|
|
625
|
+
switch (terminal.status) {
|
|
626
|
+
case "max-depth":
|
|
627
|
+
problems.add(`${at}${trail} hit maxDepth ${maxDepth} in state ${state} without ending; the workflow may loop`);
|
|
628
|
+
break;
|
|
629
|
+
case "needs-output":
|
|
630
|
+
problems.add(`${at}${trail} reached '${terminal.missingSrc}' in state ${state}, which has no output to explore with; add an explore.outputs entry for it`);
|
|
631
|
+
break;
|
|
632
|
+
case "error":
|
|
633
|
+
problems.add(`${at}${trail} errored in state ${state} with no onError: ${errorMessage(terminal.error)}`);
|
|
634
|
+
break;
|
|
635
|
+
default: problems.add(`${at}${trail} ends '${terminal.status}' in state ${state}; every path must end ${allowed.map((t) => `'${t}'`).join(" or ")}`);
|
|
636
|
+
}
|
|
637
|
+
}
|
|
638
|
+
if (report.hitPathCap) problems.add(`${at}a cap (maxPaths ${options.maxPaths ?? 200} or maxNodes ${options.maxNodes ?? 1e5}) cut exploration short; the workflow branches too much to verify`);
|
|
639
|
+
if (report.unexpandedEvents.length > 0) problems.add(`${at}explore did not try every payload of: ${report.unexpandedEvents.join(", ")}; add explore.payloads entries for them`);
|
|
640
|
+
}
|
|
641
|
+
return [...problems];
|
|
642
|
+
}
|
|
643
|
+
function formatDetail(lines) {
|
|
644
|
+
const shown = lines.slice(0, MAX_DETAIL_LINES);
|
|
645
|
+
const hidden = lines.length - shown.length;
|
|
646
|
+
return [...shown, ...hidden > 0 ? [`(${hidden} more)`] : []].join("\n");
|
|
647
|
+
}
|
|
648
|
+
function errorMessage(error) {
|
|
649
|
+
if (error instanceof Error) return error.message;
|
|
650
|
+
if (typeof error === "string") return error;
|
|
651
|
+
try {
|
|
652
|
+
return JSON.stringify(error);
|
|
653
|
+
} catch {
|
|
654
|
+
return String(error);
|
|
655
|
+
}
|
|
656
|
+
}
|
|
657
|
+
//#endregion
|
|
428
658
|
exports.validateAgentConfig = validateAgentConfig;
|
|
659
|
+
exports.verifyAgentConfig = verifyAgentConfig;
|
package/dist/validate.d.cts
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
|
-
|
|
1
|
+
import { d as AgentWorkflowConfig, g as FromConfigOptions, v as SchemaCompiler } from "./setup-agent-CLPCkXsu.cjs";
|
|
2
|
+
import { l as ExplorePathsOptions } from "./verify-Dzwd4Mvk.cjs";
|
|
3
|
+
import { AnyActorLogic, AnyStateMachine } from "xstate";
|
|
4
|
+
//#region src/validate/validate-config.d.ts
|
|
2
5
|
/**
|
|
3
6
|
* One schema-validation finding from {@link validateAgentConfig}. `path` is a
|
|
4
7
|
* JSON Pointer into the config (`/states/idle/invoke`, `/` for the root) and
|
|
@@ -26,6 +29,110 @@ interface AgentConfigValidationResult {
|
|
|
26
29
|
* not check that named guards/actions/actors are implemented, which
|
|
27
30
|
* `fromConfig` does). The compiled validator is cached across calls.
|
|
28
31
|
*/
|
|
29
|
-
declare function validateAgentConfig(config: unknown): AgentConfigValidationResult;
|
|
32
|
+
export declare function validateAgentConfig(config: unknown): AgentConfigValidationResult;
|
|
30
33
|
//#endregion
|
|
31
|
-
|
|
34
|
+
//#region src/validate/verify-config.d.ts
|
|
35
|
+
/** The gates {@link verifyAgentConfig} runs, in order. */
|
|
36
|
+
type AgentConfigGateName = "validate" | "vocabulary" | "lower" | "lint" | "explore";
|
|
37
|
+
/** One gate's outcome. `detail` is a short, model-readable message (one problem per line). */
|
|
38
|
+
interface AgentConfigGate {
|
|
39
|
+
name: AgentConfigGateName;
|
|
40
|
+
ok: boolean;
|
|
41
|
+
detail?: string;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* The names a config may reference. An omitted key is unrestricted; a listed
|
|
45
|
+
* key restricts that kind of reference to exactly these names.
|
|
46
|
+
*
|
|
47
|
+
* Invoke srcs: a config can only invoke an `agent.*` builtin or a key it
|
|
48
|
+
* declares under `requests` or `actors`; any other src fails the `lower` gate
|
|
49
|
+
* (`Missing actor source`), so a host-provided `actors` binding never adds a
|
|
50
|
+
* src. `requests` limits the declared `requests` keys and `actors` the declared
|
|
51
|
+
* `actors` keys. With `actors` listed, every non-builtin src must also be in
|
|
52
|
+
* `actors` or in `requests` (the declared request keys when `requests` is
|
|
53
|
+
* omitted).
|
|
54
|
+
*
|
|
55
|
+
* Raw xstate expression slots (`{ "@expr": ... }`) fail the gate anywhere in
|
|
56
|
+
* the config: xstate evaluates one in place of its literal siblings, which
|
|
57
|
+
* would hide a model ref or `allowedEvents` from these checks.
|
|
58
|
+
*/
|
|
59
|
+
interface AgentConfigVocabulary {
|
|
60
|
+
/** Declared `actors` keys, and (when listed) the non-request invoke srcs. */
|
|
61
|
+
actors?: string[];
|
|
62
|
+
/** Declared `requests` keys. */
|
|
63
|
+
requests?: string[];
|
|
64
|
+
/** Named guard references (`guard: "isReady"`, not `{{ }}` templates). */
|
|
65
|
+
guards?: string[];
|
|
66
|
+
/** Named action types (`{ type: "notify" }`). */
|
|
67
|
+
actions?: string[];
|
|
68
|
+
/** Event types an `agent.decide` invoke may list in `allowedEvents`. */
|
|
69
|
+
events?: string[];
|
|
70
|
+
/** Model refs. Each must be a literal string (not a `{{ }}` template) in this set. */
|
|
71
|
+
models?: string[];
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* The `explore` options of {@link verifyAgentConfig}. Every other
|
|
75
|
+
* {@link ExplorePathsOptions} key (`outputs`, `errors`, `payloads`, caps)
|
|
76
|
+
* passes through to `explorePaths`; script text requests and invoked actors
|
|
77
|
+
* with `outputs`.
|
|
78
|
+
*/
|
|
79
|
+
interface VerifyAgentConfigExploreOptions extends Omit<ExplorePathsOptions, "input"> {
|
|
80
|
+
/** One `explorePaths` run per input. An empty list fails the gate. */
|
|
81
|
+
inputs: unknown[];
|
|
82
|
+
/** Terminal statuses every explored path must end in. Default `['done']`. */
|
|
83
|
+
terminals?: Array<"done" | "idle">;
|
|
84
|
+
}
|
|
85
|
+
/** Options for {@link verifyAgentConfig}. */
|
|
86
|
+
interface VerifyAgentConfigOptions {
|
|
87
|
+
/** The JSON Schema compiler `setupAgent.fromConfig` uses. */
|
|
88
|
+
compileSchema: SchemaCompiler;
|
|
89
|
+
/** Named guard implementations, passed to `setupAgent.fromConfig`. */
|
|
90
|
+
guards?: FromConfigOptions["guards"];
|
|
91
|
+
/** Named action implementations, passed to `setupAgent.fromConfig`. */
|
|
92
|
+
actions?: FromConfigOptions["actions"];
|
|
93
|
+
/** Actor implementations, bound with `machine.provide({ actors })` after lowering. */
|
|
94
|
+
actors?: Record<string, AnyActorLogic>;
|
|
95
|
+
/** The names the config may reference. Omit to skip the vocabulary checks. */
|
|
96
|
+
allow?: AgentConfigVocabulary;
|
|
97
|
+
/** Lint policy. Error findings always fail; `warnings: true` fails on warnings too. */
|
|
98
|
+
lint?: {
|
|
99
|
+
warnings?: boolean;
|
|
100
|
+
};
|
|
101
|
+
/** Path exploration. Omit to skip the `explore` gate. */
|
|
102
|
+
explore?: VerifyAgentConfigExploreOptions;
|
|
103
|
+
}
|
|
104
|
+
/** Result of {@link verifyAgentConfig}. */
|
|
105
|
+
interface VerifyAgentConfigResult {
|
|
106
|
+
/** True when every gate that ran passed. */
|
|
107
|
+
ok: boolean;
|
|
108
|
+
/** The gates that ran, in order. A failing gate is the last entry. */
|
|
109
|
+
gates: AgentConfigGate[];
|
|
110
|
+
/** The lowered machine, set when the `lower` gate passed. */
|
|
111
|
+
machine?: AnyStateMachine;
|
|
112
|
+
/** The typed config, set when the `validate` gate passed. */
|
|
113
|
+
config?: AgentWorkflowConfig;
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Runs every pre-run gate on a model-authored workflow config and stops at
|
|
117
|
+
* the first failure. Never throws on a bad config: each failure becomes a gate
|
|
118
|
+
* record whose `detail` is a repair prompt.
|
|
119
|
+
*
|
|
120
|
+
* - `validate`: the config's shape, against the shipped JSON Schema.
|
|
121
|
+
* - `vocabulary`: names the config references, against `allow`.
|
|
122
|
+
* - `lower`: `setupAgent.fromConfig` (unresolved guards/actions, bad targets).
|
|
123
|
+
* - `lint`: `lintAgentMachine` (errors fail; warnings fail with `lint.warnings`).
|
|
124
|
+
* - `explore`: `explorePaths` from each `explore.inputs` entry; every terminal
|
|
125
|
+
* must be one of `explore.terminals`, no cap (`maxPaths`, `maxNodes`) may cut
|
|
126
|
+
* it short, every event's payloads must be tried (`unexpandedEvents`), and
|
|
127
|
+
* every reached text request or invoke needs an `explore.outputs` entry.
|
|
128
|
+
*
|
|
129
|
+
* @example
|
|
130
|
+
* ```ts
|
|
131
|
+
* const result = await verifyAgentConfig(candidate, { compileSchema, allow: { events: ["APPROVE", "DENY"] } });
|
|
132
|
+
* const failed = result.gates.find((gate) => !gate.ok);
|
|
133
|
+
* if (failed) feedback.push(`gate '${failed.name}' failed: ${failed.detail}`);
|
|
134
|
+
* ```
|
|
135
|
+
*/
|
|
136
|
+
export declare function verifyAgentConfig(config: unknown, options: VerifyAgentConfigOptions): Promise<VerifyAgentConfigResult>;
|
|
137
|
+
//#endregion
|
|
138
|
+
export type { AgentConfigDiagnostic, AgentConfigValidationResult, VerifyAgentConfigOptions, VerifyAgentConfigResult };
|
package/dist/validate.d.mts
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
|
-
|
|
1
|
+
import { d as AgentWorkflowConfig, g as FromConfigOptions, v as SchemaCompiler } from "./setup-agent-CGELn1qZ.mjs";
|
|
2
|
+
import { l as ExplorePathsOptions } from "./verify-Cn86rT8l.mjs";
|
|
3
|
+
import { AnyActorLogic, AnyStateMachine } from "xstate";
|
|
4
|
+
//#region src/validate/validate-config.d.ts
|
|
2
5
|
/**
|
|
3
6
|
* One schema-validation finding from {@link validateAgentConfig}. `path` is a
|
|
4
7
|
* JSON Pointer into the config (`/states/idle/invoke`, `/` for the root) and
|
|
@@ -26,6 +29,110 @@ interface AgentConfigValidationResult {
|
|
|
26
29
|
* not check that named guards/actions/actors are implemented, which
|
|
27
30
|
* `fromConfig` does). The compiled validator is cached across calls.
|
|
28
31
|
*/
|
|
29
|
-
declare function validateAgentConfig(config: unknown): AgentConfigValidationResult;
|
|
32
|
+
export declare function validateAgentConfig(config: unknown): AgentConfigValidationResult;
|
|
30
33
|
//#endregion
|
|
31
|
-
|
|
34
|
+
//#region src/validate/verify-config.d.ts
|
|
35
|
+
/** The gates {@link verifyAgentConfig} runs, in order. */
|
|
36
|
+
type AgentConfigGateName = "validate" | "vocabulary" | "lower" | "lint" | "explore";
|
|
37
|
+
/** One gate's outcome. `detail` is a short, model-readable message (one problem per line). */
|
|
38
|
+
interface AgentConfigGate {
|
|
39
|
+
name: AgentConfigGateName;
|
|
40
|
+
ok: boolean;
|
|
41
|
+
detail?: string;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* The names a config may reference. An omitted key is unrestricted; a listed
|
|
45
|
+
* key restricts that kind of reference to exactly these names.
|
|
46
|
+
*
|
|
47
|
+
* Invoke srcs: a config can only invoke an `agent.*` builtin or a key it
|
|
48
|
+
* declares under `requests` or `actors`; any other src fails the `lower` gate
|
|
49
|
+
* (`Missing actor source`), so a host-provided `actors` binding never adds a
|
|
50
|
+
* src. `requests` limits the declared `requests` keys and `actors` the declared
|
|
51
|
+
* `actors` keys. With `actors` listed, every non-builtin src must also be in
|
|
52
|
+
* `actors` or in `requests` (the declared request keys when `requests` is
|
|
53
|
+
* omitted).
|
|
54
|
+
*
|
|
55
|
+
* Raw xstate expression slots (`{ "@expr": ... }`) fail the gate anywhere in
|
|
56
|
+
* the config: xstate evaluates one in place of its literal siblings, which
|
|
57
|
+
* would hide a model ref or `allowedEvents` from these checks.
|
|
58
|
+
*/
|
|
59
|
+
interface AgentConfigVocabulary {
|
|
60
|
+
/** Declared `actors` keys, and (when listed) the non-request invoke srcs. */
|
|
61
|
+
actors?: string[];
|
|
62
|
+
/** Declared `requests` keys. */
|
|
63
|
+
requests?: string[];
|
|
64
|
+
/** Named guard references (`guard: "isReady"`, not `{{ }}` templates). */
|
|
65
|
+
guards?: string[];
|
|
66
|
+
/** Named action types (`{ type: "notify" }`). */
|
|
67
|
+
actions?: string[];
|
|
68
|
+
/** Event types an `agent.decide` invoke may list in `allowedEvents`. */
|
|
69
|
+
events?: string[];
|
|
70
|
+
/** Model refs. Each must be a literal string (not a `{{ }}` template) in this set. */
|
|
71
|
+
models?: string[];
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* The `explore` options of {@link verifyAgentConfig}. Every other
|
|
75
|
+
* {@link ExplorePathsOptions} key (`outputs`, `errors`, `payloads`, caps)
|
|
76
|
+
* passes through to `explorePaths`; script text requests and invoked actors
|
|
77
|
+
* with `outputs`.
|
|
78
|
+
*/
|
|
79
|
+
interface VerifyAgentConfigExploreOptions extends Omit<ExplorePathsOptions, "input"> {
|
|
80
|
+
/** One `explorePaths` run per input. An empty list fails the gate. */
|
|
81
|
+
inputs: unknown[];
|
|
82
|
+
/** Terminal statuses every explored path must end in. Default `['done']`. */
|
|
83
|
+
terminals?: Array<"done" | "idle">;
|
|
84
|
+
}
|
|
85
|
+
/** Options for {@link verifyAgentConfig}. */
|
|
86
|
+
interface VerifyAgentConfigOptions {
|
|
87
|
+
/** The JSON Schema compiler `setupAgent.fromConfig` uses. */
|
|
88
|
+
compileSchema: SchemaCompiler;
|
|
89
|
+
/** Named guard implementations, passed to `setupAgent.fromConfig`. */
|
|
90
|
+
guards?: FromConfigOptions["guards"];
|
|
91
|
+
/** Named action implementations, passed to `setupAgent.fromConfig`. */
|
|
92
|
+
actions?: FromConfigOptions["actions"];
|
|
93
|
+
/** Actor implementations, bound with `machine.provide({ actors })` after lowering. */
|
|
94
|
+
actors?: Record<string, AnyActorLogic>;
|
|
95
|
+
/** The names the config may reference. Omit to skip the vocabulary checks. */
|
|
96
|
+
allow?: AgentConfigVocabulary;
|
|
97
|
+
/** Lint policy. Error findings always fail; `warnings: true` fails on warnings too. */
|
|
98
|
+
lint?: {
|
|
99
|
+
warnings?: boolean;
|
|
100
|
+
};
|
|
101
|
+
/** Path exploration. Omit to skip the `explore` gate. */
|
|
102
|
+
explore?: VerifyAgentConfigExploreOptions;
|
|
103
|
+
}
|
|
104
|
+
/** Result of {@link verifyAgentConfig}. */
|
|
105
|
+
interface VerifyAgentConfigResult {
|
|
106
|
+
/** True when every gate that ran passed. */
|
|
107
|
+
ok: boolean;
|
|
108
|
+
/** The gates that ran, in order. A failing gate is the last entry. */
|
|
109
|
+
gates: AgentConfigGate[];
|
|
110
|
+
/** The lowered machine, set when the `lower` gate passed. */
|
|
111
|
+
machine?: AnyStateMachine;
|
|
112
|
+
/** The typed config, set when the `validate` gate passed. */
|
|
113
|
+
config?: AgentWorkflowConfig;
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Runs every pre-run gate on a model-authored workflow config and stops at
|
|
117
|
+
* the first failure. Never throws on a bad config: each failure becomes a gate
|
|
118
|
+
* record whose `detail` is a repair prompt.
|
|
119
|
+
*
|
|
120
|
+
* - `validate`: the config's shape, against the shipped JSON Schema.
|
|
121
|
+
* - `vocabulary`: names the config references, against `allow`.
|
|
122
|
+
* - `lower`: `setupAgent.fromConfig` (unresolved guards/actions, bad targets).
|
|
123
|
+
* - `lint`: `lintAgentMachine` (errors fail; warnings fail with `lint.warnings`).
|
|
124
|
+
* - `explore`: `explorePaths` from each `explore.inputs` entry; every terminal
|
|
125
|
+
* must be one of `explore.terminals`, no cap (`maxPaths`, `maxNodes`) may cut
|
|
126
|
+
* it short, every event's payloads must be tried (`unexpandedEvents`), and
|
|
127
|
+
* every reached text request or invoke needs an `explore.outputs` entry.
|
|
128
|
+
*
|
|
129
|
+
* @example
|
|
130
|
+
* ```ts
|
|
131
|
+
* const result = await verifyAgentConfig(candidate, { compileSchema, allow: { events: ["APPROVE", "DENY"] } });
|
|
132
|
+
* const failed = result.gates.find((gate) => !gate.ok);
|
|
133
|
+
* if (failed) feedback.push(`gate '${failed.name}' failed: ${failed.detail}`);
|
|
134
|
+
* ```
|
|
135
|
+
*/
|
|
136
|
+
export declare function verifyAgentConfig(config: unknown, options: VerifyAgentConfigOptions): Promise<VerifyAgentConfigResult>;
|
|
137
|
+
//#endregion
|
|
138
|
+
export type { AgentConfigDiagnostic, AgentConfigValidationResult, VerifyAgentConfigOptions, VerifyAgentConfigResult };
|