@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.
Files changed (80) hide show
  1. package/dist/ai-sdk.cjs +150 -27
  2. package/dist/ai-sdk.d.cts +59 -36
  3. package/dist/ai-sdk.d.mts +59 -36
  4. package/dist/ai-sdk.mjs +148 -24
  5. package/dist/{decision-RQ0iv0oZ.mjs → decision-BHkvuImD.mjs} +74 -8
  6. package/dist/{decision-CmM8-HHz.cjs → decision-CIb7ddIv.cjs} +113 -30
  7. package/dist/{text-logic-f5F5sCdc.cjs → event-log-BZRfBRd7.cjs} +814 -7
  8. package/dist/{text-logic-CIqHAmBi.mjs → event-log-DJCMHek_.mjs} +680 -4
  9. package/dist/{event-log-store-BIPOz-di.d.mts → event-log-store-CIIJohjj.d.mts} +90 -5
  10. package/dist/{event-log-store-2xzFmgr2.d.cts → event-log-store-CLAC9q2Y.d.cts} +90 -5
  11. package/dist/event-log-store-DZR4IIWe.cjs +95 -0
  12. package/dist/event-log-store-DsP6GCRh.mjs +84 -0
  13. package/dist/index.cjs +576 -58
  14. package/dist/index.d.cts +104 -510
  15. package/dist/index.d.mts +104 -510
  16. package/dist/index.mjs +547 -32
  17. package/dist/log.cjs +77 -20
  18. package/dist/log.d.cts +5 -5
  19. package/dist/log.d.mts +5 -5
  20. package/dist/log.mjs +58 -3
  21. package/dist/machines.cjs +1 -1
  22. package/dist/machines.d.cts +15 -15
  23. package/dist/machines.d.mts +15 -15
  24. package/dist/machines.mjs +1 -1
  25. package/dist/model-source-BCKg4qJ1.cjs +44 -0
  26. package/dist/model-source-BaHwJ1wK.mjs +39 -0
  27. package/dist/openai.cjs +11 -11
  28. package/dist/openai.d.cts +28 -26
  29. package/dist/openai.d.mts +28 -26
  30. package/dist/openai.mjs +3 -3
  31. package/dist/otel.cjs +5 -4
  32. package/dist/otel.d.cts +5 -7
  33. package/dist/otel.d.mts +5 -7
  34. package/dist/otel.mjs +5 -3
  35. package/dist/{run-agent-xNTxpt82.mjs → run-agent-BpHqkaZw.mjs} +181 -44
  36. package/dist/{run-agent-COXXc0RW.d.mts → run-agent-CAVt5R-r.d.mts} +95 -30
  37. package/dist/{run-agent-ByO-Bxyd.d.cts → run-agent-CTlMc3Jb.d.cts} +95 -30
  38. package/dist/{run-agent-Dmf8GV2d.cjs → run-agent-ctLCvNgL.cjs} +230 -88
  39. package/dist/{setup-agent-BuanDXeh.mjs → setup-agent-7rV_cujV.mjs} +15 -9
  40. package/dist/setup-agent-CGELn1qZ.d.mts +577 -0
  41. package/dist/setup-agent-CLPCkXsu.d.cts +577 -0
  42. package/dist/{setup-agent-DV4cTou-.cjs → setup-agent-DoUk7EdC.cjs} +31 -20
  43. package/dist/tanstack-ai.cjs +627 -0
  44. package/dist/tanstack-ai.d.cts +204 -0
  45. package/dist/tanstack-ai.d.mts +204 -0
  46. package/dist/tanstack-ai.mjs +618 -0
  47. package/dist/testing.cjs +204 -985
  48. package/dist/testing.d.cts +132 -347
  49. package/dist/testing.d.mts +132 -347
  50. package/dist/testing.mjs +191 -973
  51. package/dist/{text-logic-IjfYy9DP.d.cts → text-logic-BRYOPWvY.d.mts} +52 -12
  52. package/dist/{text-logic-D-czVPYp.d.mts → text-logic-DmciuVUQ.d.cts} +52 -12
  53. package/dist/{types-BgNbNKnJ.d.mts → types-Dp5_Ru4R.d.cts} +2 -2
  54. package/dist/{types-hR5f5YXa.d.cts → types-Dp5_Ru4R.d.mts} +2 -2
  55. package/dist/usage-BkM3z02Y.d.mts +17 -0
  56. package/dist/usage-Cm_ovz9V.d.cts +17 -0
  57. package/dist/{utils-_q7F-AZu.d.mts → utils-BnXdWih3.d.mts} +1 -2
  58. package/dist/{utils-o4YRdHJX.d.cts → utils-ebVpCYoF.d.cts} +1 -2
  59. package/dist/validate.cjs +239 -8
  60. package/dist/validate.d.cts +110 -3
  61. package/dist/validate.d.mts +110 -3
  62. package/dist/validate.mjs +238 -7
  63. package/dist/verify-COFWyprJ.mjs +1181 -0
  64. package/dist/verify-CVlsTZ-V.cjs +1222 -0
  65. package/dist/verify-Cn86rT8l.d.mts +414 -0
  66. package/dist/verify-Dzwd4Mvk.d.cts +414 -0
  67. package/package.json +44 -31
  68. package/readme.md +40 -28
  69. package/skills/add-evals/SKILL.md +129 -0
  70. package/skills/add-traces/SKILL.md +135 -0
  71. package/skills/generate-machine/SKILL.md +143 -69
  72. package/skills/graph-engineering/SKILL.md +33 -0
  73. package/skills/improve-machine/SKILL.md +241 -0
  74. package/skills/improve-machine/reference.md +101 -0
  75. package/skills/loop-to-machine/SKILL.md +183 -0
  76. package/skills/loop-to-machine/policy.md +158 -0
  77. package/dist/event-log-store-2pAFiWuc.mjs +0 -576
  78. package/dist/event-log-store-C-COhIXP.cjs +0 -702
  79. package/dist/usage-BdEjFuIi.mjs +0 -5
  80. package/dist/usage-efOQPdf_.cjs +0 -10
package/dist/validate.mjs CHANGED
@@ -1,3 +1,6 @@
1
+ import { D as STREAM_TEXT_ACTOR, E as GENERATE_TEXT_ACTOR, T as DECIDE_ACTOR } from "./event-log-DJCMHek_.mjs";
2
+ import { i as setupAgentFromConfig } from "./setup-agent-7rV_cujV.mjs";
3
+ import { a as explorePaths, o as lintAgentMachine } from "./verify-COFWyprJ.mjs";
1
4
  import Ajv2020 from "ajv/dist/2020.js";
2
5
  //#region schemas/agent-workflow.json
3
6
  var agent_workflow_default = {
@@ -359,13 +362,10 @@ var agent_workflow_default = {
359
362
  }
360
363
  };
361
364
  //#endregion
362
- //#region src/validate/index.ts
365
+ //#region src/validate/validate-config.ts
363
366
  /**
364
- * Schema validation for agent workflow configs.
365
- *
366
- * Lives behind the `@statelyai/agent/validate` subpath so the core package
367
- * stays dependency-free. This module imports `ajv`, which is declared as an
368
- * optional peer dependency.
367
+ * Schema validation for agent workflow configs. Imports `ajv`, an optional
368
+ * peer dependency of the package.
369
369
  */
370
370
  let compiledWorkflowValidator;
371
371
  function getWorkflowValidator() {
@@ -400,4 +400,235 @@ function validateAgentConfig(config) {
400
400
  };
401
401
  }
402
402
  //#endregion
403
- export { validateAgentConfig };
403
+ //#region src/validate/verify-config.ts
404
+ const BUILTIN_SRCS = [
405
+ DECIDE_ACTOR,
406
+ GENERATE_TEXT_ACTOR,
407
+ STREAM_TEXT_ACTOR
408
+ ];
409
+ const MAX_DETAIL_LINES = 10;
410
+ /**
411
+ * Runs every pre-run gate on a model-authored workflow config and stops at
412
+ * the first failure. Never throws on a bad config: each failure becomes a gate
413
+ * record whose `detail` is a repair prompt.
414
+ *
415
+ * - `validate`: the config's shape, against the shipped JSON Schema.
416
+ * - `vocabulary`: names the config references, against `allow`.
417
+ * - `lower`: `setupAgent.fromConfig` (unresolved guards/actions, bad targets).
418
+ * - `lint`: `lintAgentMachine` (errors fail; warnings fail with `lint.warnings`).
419
+ * - `explore`: `explorePaths` from each `explore.inputs` entry; every terminal
420
+ * must be one of `explore.terminals`, no cap (`maxPaths`, `maxNodes`) may cut
421
+ * it short, every event's payloads must be tried (`unexpandedEvents`), and
422
+ * every reached text request or invoke needs an `explore.outputs` entry.
423
+ *
424
+ * @example
425
+ * ```ts
426
+ * const result = await verifyAgentConfig(candidate, { compileSchema, allow: { events: ["APPROVE", "DENY"] } });
427
+ * const failed = result.gates.find((gate) => !gate.ok);
428
+ * if (failed) feedback.push(`gate '${failed.name}' failed: ${failed.detail}`);
429
+ * ```
430
+ */
431
+ async function verifyAgentConfig(config, options) {
432
+ const gates = [];
433
+ const record = (name, problems, notes = []) => {
434
+ const lines = problems.length ? problems : notes;
435
+ gates.push({
436
+ name,
437
+ ok: problems.length === 0,
438
+ ...lines.length ? { detail: formatDetail(lines) } : {}
439
+ });
440
+ return problems.length === 0;
441
+ };
442
+ const fail = (extra = {}) => ({
443
+ ok: false,
444
+ gates,
445
+ ...extra
446
+ });
447
+ if (!record("validate", validateAgentConfig(config).errors.map((error) => `${error.path} ${error.message}`))) return fail();
448
+ const typed = config;
449
+ if (options.allow && !record("vocabulary", checkVocabulary(typed, options.allow))) return fail({ config: typed });
450
+ let machine;
451
+ try {
452
+ machine = setupAgentFromConfig(typed, {
453
+ compileSchema: options.compileSchema,
454
+ ...options.guards ? { guards: options.guards } : {},
455
+ ...options.actions ? { actions: options.actions } : {}
456
+ }).machine;
457
+ if (options.actors) machine = machine.provide({ actors: options.actors });
458
+ } catch (error) {
459
+ record("lower", [errorMessage(error)]);
460
+ return fail({ config: typed });
461
+ }
462
+ record("lower", []);
463
+ const diagnostics = lintAgentMachine(machine).map((d) => ({
464
+ failing: d.severity === "error" || options.lint?.warnings === true,
465
+ line: `${d.severity} ${d.code} at '${d.path}': ${d.message}`
466
+ }));
467
+ if (!record("lint", diagnostics.filter((d) => d.failing).map((d) => d.line), diagnostics.map((d) => d.line))) return fail({
468
+ config: typed,
469
+ machine
470
+ });
471
+ if (options.explore && !record("explore", await checkExplore(machine, options.explore))) return fail({
472
+ config: typed,
473
+ machine
474
+ });
475
+ return {
476
+ ok: true,
477
+ gates,
478
+ config: typed,
479
+ machine
480
+ };
481
+ }
482
+ /** A config's `T | T[]` field as a list of objects. */
483
+ const nodes = (value) => (value === void 0 ? [] : Array.isArray(value) ? value : [value]).filter((node) => !!node && typeof node === "object");
484
+ const hasTemplate = (value) => typeof value === "string" && value.includes("{{");
485
+ const list = (names) => names.length ? names.join(", ") : "(none)";
486
+ /** Every state in the config, depth-first, with its dotted path. */
487
+ function walkStates(states, prefix = "") {
488
+ if (!states || typeof states !== "object") return [];
489
+ return Object.entries(states).flatMap(([key, state]) => {
490
+ const path = prefix ? `${prefix}.${key}` : key;
491
+ return [{
492
+ path,
493
+ state
494
+ }, ...walkStates(state?.states, path)];
495
+ });
496
+ }
497
+ /** Every transition on a state: `on`, `after`, `always`, `choice`, `onDone`, and invoke done/error. */
498
+ function transitionsOf(state) {
499
+ return [
500
+ ...Object.values(state.on ?? {}).flatMap(nodes),
501
+ ...Object.values(state.after ?? {}).flatMap(nodes),
502
+ ...nodes(state.always),
503
+ ...nodes(state.choice),
504
+ ...nodes(state.onDone),
505
+ ...nodes(state.invoke).flatMap((invoke) => [...nodes(invoke.onDone), ...nodes(invoke.onError)])
506
+ ];
507
+ }
508
+ /**
509
+ * Paths of raw xstate expression slots (`{ "@expr": ... }`, `{ "@code": ... }`).
510
+ * xstate evaluates such an object whole, ignoring its literal siblings, so a
511
+ * slot would hide the model ref or `allowedEvents` the checks below read.
512
+ */
513
+ function rawExpressionPaths(value, path) {
514
+ if (Array.isArray(value)) return value.flatMap((item, index) => rawExpressionPaths(item, `${path}[${index}]`));
515
+ if (!value || typeof value !== "object") return [];
516
+ const node = value;
517
+ if (typeof node["@expr"] === "string" || typeof node["@code"] === "string") return [path];
518
+ return Object.entries(node).flatMap(([key, item]) => rawExpressionPaths(item, path ? `${path}.${key}` : key));
519
+ }
520
+ function checkVocabulary(config, allow) {
521
+ const problems = rawExpressionPaths(config, "").map((path) => `${path || "(root)"} uses a raw '@expr' slot, which the vocabulary cannot check; write {{ }} templates instead`);
522
+ const checkModel = (where, model) => {
523
+ if (!allow.models) return;
524
+ if (typeof model !== "string" || hasTemplate(model)) problems.push(`${where} needs a literal string model ref; allowed: ${list(allow.models)}`);
525
+ else if (!allow.models.includes(model)) problems.push(`${where} uses model '${model}'; allowed: ${list(allow.models)}`);
526
+ };
527
+ for (const [kind, declared, allowed] of [[
528
+ "request",
529
+ config.requests,
530
+ allow.requests
531
+ ], [
532
+ "actor",
533
+ config.actors,
534
+ allow.actors
535
+ ]]) {
536
+ if (!allowed) continue;
537
+ for (const key of Object.keys(declared ?? {})) if (!allowed.includes(key)) problems.push(`${kind} '${key}' is not in the vocabulary; allowed: ${list(allowed)}`);
538
+ }
539
+ for (const [key, request] of Object.entries(config.requests ?? {})) checkModel(`request '${key}'`, request.model);
540
+ const srcs = allow.actors ? [
541
+ ...BUILTIN_SRCS,
542
+ ...allow.actors,
543
+ ...allow.requests ?? Object.keys(config.requests ?? {})
544
+ ] : void 0;
545
+ for (const { path, state } of walkStates(config.states)) {
546
+ for (const invoke of nodes(state.invoke)) {
547
+ const src = String(invoke.src);
548
+ if (srcs && !srcs.includes(src)) {
549
+ problems.push(`state '${path}' invokes unknown src '${src}'; allowed: ${list(srcs)}`);
550
+ continue;
551
+ }
552
+ if (!BUILTIN_SRCS.includes(src)) continue;
553
+ const input = invoke.input;
554
+ if ((allow.models || src === "agent.decide" && allow.events) && !isPlainObject(input)) {
555
+ problems.push(`state '${path}': '${src}' input must be a literal object`);
556
+ continue;
557
+ }
558
+ checkModel(`state '${path}': '${src}'`, input?.model);
559
+ if (src !== "agent.decide" || !allow.events) continue;
560
+ const allowedEvents = input.allowedEvents;
561
+ if (!Array.isArray(allowedEvents) || allowedEvents.length === 0) {
562
+ problems.push(`state '${path}': agent.decide needs a literal, non-empty allowedEvents list; allowed: ${list(allow.events)}`);
563
+ continue;
564
+ }
565
+ 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)}`);
566
+ }
567
+ const actionsAt = [["entry", state.entry], ["exit", state.exit]];
568
+ for (const transition of transitionsOf(state)) {
569
+ const guard = transition.guard;
570
+ 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)}`);
571
+ actionsAt.push(["a transition", transition.actions]);
572
+ }
573
+ if (!allow.actions) continue;
574
+ 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)}`);
575
+ }
576
+ return problems;
577
+ }
578
+ const isPlainObject = (value) => !!value && typeof value === "object" && !Array.isArray(value);
579
+ async function checkExplore(machine, options) {
580
+ const { inputs, terminals = ["done"], ...rest } = options;
581
+ if (inputs.length === 0) return ["explore.inputs is empty, so no path was explored; give at least one input"];
582
+ const allowed = terminals;
583
+ const maxDepth = options.maxDepth ?? 8;
584
+ const problems = /* @__PURE__ */ new Set();
585
+ for (const [index, input] of inputs.entries()) {
586
+ const at = inputs.length > 1 ? `input ${index}: ` : "";
587
+ let report;
588
+ try {
589
+ report = await explorePaths(machine, {
590
+ ...rest,
591
+ input
592
+ });
593
+ } catch (error) {
594
+ problems.add(`${at}exploration threw: ${errorMessage(error)}`);
595
+ continue;
596
+ }
597
+ for (const terminal of report.terminals) {
598
+ if (allowed.includes(terminal.status)) continue;
599
+ const trail = `path [${terminal.path.map((event) => event.type).join(", ")}]`;
600
+ const state = JSON.stringify(terminal.state);
601
+ switch (terminal.status) {
602
+ case "max-depth":
603
+ problems.add(`${at}${trail} hit maxDepth ${maxDepth} in state ${state} without ending; the workflow may loop`);
604
+ break;
605
+ case "needs-output":
606
+ problems.add(`${at}${trail} reached '${terminal.missingSrc}' in state ${state}, which has no output to explore with; add an explore.outputs entry for it`);
607
+ break;
608
+ case "error":
609
+ problems.add(`${at}${trail} errored in state ${state} with no onError: ${errorMessage(terminal.error)}`);
610
+ break;
611
+ default: problems.add(`${at}${trail} ends '${terminal.status}' in state ${state}; every path must end ${allowed.map((t) => `'${t}'`).join(" or ")}`);
612
+ }
613
+ }
614
+ 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`);
615
+ if (report.unexpandedEvents.length > 0) problems.add(`${at}explore did not try every payload of: ${report.unexpandedEvents.join(", ")}; add explore.payloads entries for them`);
616
+ }
617
+ return [...problems];
618
+ }
619
+ function formatDetail(lines) {
620
+ const shown = lines.slice(0, MAX_DETAIL_LINES);
621
+ const hidden = lines.length - shown.length;
622
+ return [...shown, ...hidden > 0 ? [`(${hidden} more)`] : []].join("\n");
623
+ }
624
+ function errorMessage(error) {
625
+ if (error instanceof Error) return error.message;
626
+ if (typeof error === "string") return error;
627
+ try {
628
+ return JSON.stringify(error);
629
+ } catch {
630
+ return String(error);
631
+ }
632
+ }
633
+ //#endregion
634
+ export { validateAgentConfig, verifyAgentConfig };