@statelyai/agent 2.0.0-alpha.29 → 2.0.0-alpha.31
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/CHANGELOG.md +1733 -0
- package/dist/ai-sdk.cjs +9 -9
- package/dist/ai-sdk.d.cts +5 -5
- package/dist/ai-sdk.d.mts +5 -5
- package/dist/ai-sdk.mjs +4 -4
- package/dist/{decision-Bl_rKQnU.mjs → decision-DqO018Tp.mjs} +23 -10
- package/dist/{decision-oevZnkBe.cjs → decision-Iys2hzg3.cjs} +31 -18
- package/dist/{event-log-Dtb16p1p.cjs → event-log-Bdww2l1D.cjs} +104 -25
- package/dist/{event-log-GPZO9p7_.mjs → event-log-DE430ZCa.mjs} +87 -26
- package/dist/{event-log-store-bCdskPNS.cjs → event-log-store-BWMLi6oh.cjs} +1 -1
- package/dist/{event-log-store-yalq8C77.mjs → event-log-store-CCWdTPEP.mjs} +1 -1
- package/dist/{event-log-store-CN9ygggF.d.cts → event-log-store-DTf_OzB-.d.cts} +1 -1
- package/dist/{event-log-store-DS836wch.d.mts → event-log-store-RziIobdW.d.mts} +1 -1
- package/dist/index.cjs +136 -23
- package/dist/index.d.cts +58 -11
- package/dist/index.d.mts +58 -11
- package/dist/index.mjs +133 -21
- package/dist/log.cjs +2 -2
- package/dist/log.d.cts +1 -1
- package/dist/log.d.mts +1 -1
- package/dist/log.mjs +2 -2
- package/dist/machines.cjs +1 -1
- package/dist/machines.mjs +1 -1
- package/dist/{model-source-C7FFP2Sj.mjs → model-source-CXsSZPq0.mjs} +1 -2
- package/dist/{model-source-DjJPjGSP.cjs → model-source-DQ7KgJaT.cjs} +4 -5
- package/dist/openai.cjs +3 -3
- package/dist/openai.d.cts +2 -2
- package/dist/openai.d.mts +2 -2
- package/dist/openai.mjs +3 -3
- package/dist/otel.d.cts +1 -1
- package/dist/otel.d.mts +1 -1
- package/dist/{run-agent-C9ubX8Tx.d.cts → run-agent-B5opVUxx.d.cts} +25 -6
- package/dist/{run-agent-CxSyZmIE.d.mts → run-agent-D4MwS5GY.d.mts} +25 -6
- package/dist/{run-agent-CuQT1xSS.mjs → run-agent-DWZ1uyBJ.mjs} +100 -37
- package/dist/{run-agent-cToZ3K42.cjs → run-agent-tmk58M0x.cjs} +100 -37
- package/dist/{setup-agent-DniLvDu7.mjs → setup-agent-BaffhCcM.mjs} +38 -3
- package/dist/{setup-agent-tsc3vm5I.d.mts → setup-agent-CPyg2ic7.d.mts} +11 -3
- package/dist/{setup-agent-DTF3NQg3.cjs → setup-agent-D0L8Anl_.cjs} +38 -3
- package/dist/{setup-agent-DlbgwsIJ.d.cts → setup-agent-yFFVXf5s.d.cts} +11 -3
- package/dist/tanstack-ai.cjs +3 -3
- package/dist/tanstack-ai.d.cts +2 -2
- package/dist/tanstack-ai.d.mts +2 -2
- package/dist/tanstack-ai.mjs +3 -3
- package/dist/testing.cjs +176 -26
- package/dist/testing.d.cts +128 -10
- package/dist/testing.d.mts +128 -10
- package/dist/testing.mjs +168 -20
- package/dist/{text-logic-BDbGjYMh.d.mts → text-logic-BwdrDpO9.d.mts} +6 -2
- package/dist/{text-logic-9fv1i9aK.d.cts → text-logic-j9hShB7d.d.cts} +6 -2
- package/dist/{usage-D8UphgEA.d.mts → usage-BYqv7VBw.d.cts} +1 -1
- package/dist/{usage-R1NTmLxY.d.cts → usage-Bl4nK8D-.d.mts} +1 -1
- package/dist/validate.cjs +3 -3
- package/dist/validate.d.cts +2 -2
- package/dist/validate.d.mts +2 -2
- package/dist/validate.mjs +3 -3
- package/dist/{verify-B5qGC5WN.mjs → verify-BH5e0XLK.mjs} +55 -5
- package/dist/{verify-DYH_2VzU.d.cts → verify-CPKDPMwY.d.cts} +14 -6
- package/dist/{verify-Cqghu4gz.cjs → verify-CS_xxvVU.cjs} +57 -7
- package/dist/{verify-CBuYIpsa.d.mts → verify-tkymWz6X.d.mts} +14 -6
- package/package.json +34 -4
- package/readme.md +72 -42
- package/skills/add-evals/SKILL.md +144 -0
- package/skills/add-traces/SKILL.md +147 -0
- package/skills/generate-machine/SKILL.md +6 -6
- package/skills/graph-engineering/SKILL.md +33 -0
- package/skills/improve-machine/SKILL.md +73 -21
- package/skills/improve-machine/reference.md +12 -7
- package/skills/loop-to-machine/SKILL.md +210 -0
- package/skills/loop-to-machine/policy.md +154 -0
package/dist/testing.mjs
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import { $ as getStateMeta, F as normalizeGeneratorResult, N as getCallUsage,
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import { a as explorePaths, i as canReach, n as AgentUnknownStateError, o as lintAgentMachine, r as assertAgentMachine, s as simulateAgent, t as AgentLintError } from "./verify-B5qGC5WN.mjs";
|
|
1
|
+
import { $ as getStateMeta, F as normalizeGeneratorResult, N as getCallUsage, lt as isRecord, ut as AgentError } from "./event-log-DE430ZCa.mjs";
|
|
2
|
+
import { p as runToQuiescence, s as createAgentRuntime } from "./run-agent-DWZ1uyBJ.mjs";
|
|
3
|
+
import { a as explorePaths, i as canReach, n as AgentUnknownStateError, o as lintAgentMachine, r as assertAgentMachine, s as simulateAgent, t as AgentLintError } from "./verify-BH5e0XLK.mjs";
|
|
5
4
|
//#region src/trajectory.ts
|
|
6
5
|
/**
|
|
7
6
|
* Classifies one item. Event-shaped things (log entries, events) become events;
|
|
@@ -320,7 +319,7 @@ async function runSeam(machine, options) {
|
|
|
320
319
|
...event ? { event } : {}
|
|
321
320
|
});
|
|
322
321
|
if (result.status !== "idle" || turn === maxTurns) break;
|
|
323
|
-
const next = options.respond?.({
|
|
322
|
+
const next = await options.respond?.({
|
|
324
323
|
snapshot: result.snapshot,
|
|
325
324
|
state: result.snapshot.value,
|
|
326
325
|
meta: getStateMeta(result.snapshot),
|
|
@@ -360,13 +359,36 @@ async function runSeam(machine, options) {
|
|
|
360
359
|
};
|
|
361
360
|
}
|
|
362
361
|
//#endregion
|
|
362
|
+
//#region src/internal/trace-states.ts
|
|
363
|
+
/** The `value` of a trace event's `from` or `snapshot`. @internal */
|
|
364
|
+
function valueOf(holder) {
|
|
365
|
+
return isRecord(holder) ? holder.value : void 0;
|
|
366
|
+
}
|
|
367
|
+
/** A decision request on its first attempt (no failed attempts yet). @internal */
|
|
368
|
+
function isFirstDecision(request) {
|
|
369
|
+
return isRecord(request) && request.kind === "decision" && (!Array.isArray(request.attempts) || request.attempts.length === 0);
|
|
370
|
+
}
|
|
371
|
+
/**
|
|
372
|
+
* Every active leaf of a state value as a dot path:
|
|
373
|
+
* `'a'` → `['a']`; `{ a: 'b' }` → `['a.b']`; `{ p: { x: 'one', y: {} } }` → `['p.x.one', 'p.y']`.
|
|
374
|
+
* @internal
|
|
375
|
+
*/
|
|
376
|
+
function statePaths(value, prefix = "") {
|
|
377
|
+
if (typeof value === "string") return [prefix + value];
|
|
378
|
+
if (!isRecord(value)) return [];
|
|
379
|
+
const entries = Object.entries(value);
|
|
380
|
+
if (entries.length === 0) return prefix ? [prefix.slice(0, -1)] : [];
|
|
381
|
+
return entries.flatMap(([key, child]) => statePaths(child, `${prefix}${key}.`));
|
|
382
|
+
}
|
|
383
|
+
//#endregion
|
|
363
384
|
//#region src/fold-traces.ts
|
|
364
385
|
/**
|
|
365
386
|
* Folds many runs' traces into per-state stats: how many runs visited each
|
|
366
|
-
* state, how many of those failed,
|
|
367
|
-
* at decisions made there. Pure; reads only:
|
|
387
|
+
* state, how many of those failed, how many options the guards withheld
|
|
388
|
+
* at decisions made there, and how many events it ignored. Pure; reads only:
|
|
368
389
|
*
|
|
369
|
-
* - `machine.transition`: the run visited `from.value` and `snapshot.value
|
|
390
|
+
* - `machine.transition`: the run visited `from.value` and `snapshot.value`;
|
|
391
|
+
* with `ignored`, each of those states ignored one event.
|
|
370
392
|
* - `request.start` of a decision, first attempt only: its `request.withheld`
|
|
371
393
|
* counts toward the state the run was in, the `from.value` of the
|
|
372
394
|
* transition its choice causes.
|
|
@@ -392,7 +414,8 @@ function foldTraces(traces, options) {
|
|
|
392
414
|
state,
|
|
393
415
|
visits: 0,
|
|
394
416
|
failures: 0,
|
|
395
|
-
withheld: 0
|
|
417
|
+
withheld: 0,
|
|
418
|
+
ignored: 0
|
|
396
419
|
};
|
|
397
420
|
stats.set(state, entry);
|
|
398
421
|
}
|
|
@@ -409,6 +432,7 @@ function foldTraces(traces, options) {
|
|
|
409
432
|
for (const state of statePaths(valueOf(event.from))) visit(state);
|
|
410
433
|
current = statePaths(valueOf(event.snapshot));
|
|
411
434
|
for (const state of current) visit(state);
|
|
435
|
+
if (event.ignored === true) for (const state of current) statsFor(state).ignored++;
|
|
412
436
|
} else if (event.type === "request.start" && isFirstDecision(event.request)) {
|
|
413
437
|
const withheld = event.request.withheld;
|
|
414
438
|
if (!Array.isArray(withheld)) continue;
|
|
@@ -423,18 +447,142 @@ function foldTraces(traces, options) {
|
|
|
423
447
|
}
|
|
424
448
|
return [...stats.values()];
|
|
425
449
|
}
|
|
426
|
-
|
|
427
|
-
|
|
450
|
+
//#endregion
|
|
451
|
+
//#region src/decision-requests.ts
|
|
452
|
+
/**
|
|
453
|
+
* The decisions a run asked for, read from its trace: each decision's first
|
|
454
|
+
* `request.start`, with the states the run was in. A trace is one run's events,
|
|
455
|
+
* live or serialized with `serializeTraceEvent`. Retries of the same decision
|
|
456
|
+
* are left out, so each decision appears once.
|
|
457
|
+
*
|
|
458
|
+
* Use the requests as eval rows (run a decider on each and compare its event
|
|
459
|
+
* with a label) or as probe inputs for a policy. A serialized request keeps its
|
|
460
|
+
* `options`, `metadata`, `system`, and `prompt`; event schemas do not survive
|
|
461
|
+
* serialization, so replay closed choices (`options`) rather than open ones.
|
|
462
|
+
*
|
|
463
|
+
* @example
|
|
464
|
+
* ```ts no-check
|
|
465
|
+
* const rows = traces.flatMap((trace) => getDecisionRequests(trace, { name: "chooseResolution" }));
|
|
466
|
+
* for (const { request } of rows) console.log((await decide(request)).event);
|
|
467
|
+
* ```
|
|
468
|
+
*/
|
|
469
|
+
function getDecisionRequests(trace, options = {}) {
|
|
470
|
+
const requests = [];
|
|
471
|
+
let current = [];
|
|
472
|
+
for (const event of trace) if (event.type === "machine.transition") current = statePaths(valueOf(event.snapshot));
|
|
473
|
+
else if (event.type === "request.start" && isFirstDecision(event.request)) {
|
|
474
|
+
if (options.name !== void 0 && event.request.name !== options.name) continue;
|
|
475
|
+
requests.push({
|
|
476
|
+
states: [...current],
|
|
477
|
+
request: event.request
|
|
478
|
+
});
|
|
479
|
+
}
|
|
480
|
+
return requests;
|
|
428
481
|
}
|
|
429
|
-
|
|
430
|
-
|
|
482
|
+
//#endregion
|
|
483
|
+
//#region src/compare-runs.ts
|
|
484
|
+
/**
|
|
485
|
+
* Runs every scenario through a baseline and a candidate implementation and
|
|
486
|
+
* labels each difference, so a port can show where it behaves like the code it
|
|
487
|
+
* replaces and where it differs on purpose.
|
|
488
|
+
*
|
|
489
|
+
* Parity is outcome-level: the terminal outcome and the effects in the world,
|
|
490
|
+
* not the sequence of tool calls, since a machine usually reorders steps. A
|
|
491
|
+
* candidate that broke no rule where the baseline broke one is intended, even
|
|
492
|
+
* when the outcome matches. A difference also counts as intended when only the
|
|
493
|
+
* candidate reached the scenario's `expected` outcome. Every other difference,
|
|
494
|
+
* and every candidate rule break, is a regression for a person to review.
|
|
495
|
+
*
|
|
496
|
+
* Runs are sequential, baseline first. A run that throws is recorded with
|
|
497
|
+
* outcome `'threw'` and the error message as its `detail`. Parity holds for
|
|
498
|
+
* these scenarios and these runs only; with a live model, run it more than once.
|
|
499
|
+
*
|
|
500
|
+
* @example
|
|
501
|
+
* ```ts no-check
|
|
502
|
+
* const report = await compareRuns({
|
|
503
|
+
* scenarios,
|
|
504
|
+
* baseline: async (s) => toParityRun(await runRawLoop(s)),
|
|
505
|
+
* candidate: async (s) => toParityRun(await runDesk(s)),
|
|
506
|
+
* });
|
|
507
|
+
* expect(report.ok).toBe(true);
|
|
508
|
+
* ```
|
|
509
|
+
*/
|
|
510
|
+
async function compareRuns(options) {
|
|
511
|
+
const scenarios = [];
|
|
512
|
+
const counts = {
|
|
513
|
+
same: 0,
|
|
514
|
+
intended: 0,
|
|
515
|
+
regression: 0
|
|
516
|
+
};
|
|
517
|
+
for (const scenario of options.scenarios) {
|
|
518
|
+
const baseline = await settle(() => options.baseline(scenario));
|
|
519
|
+
const candidate = await settle(() => options.candidate(scenario));
|
|
520
|
+
const { label, reason } = labelRun(scenario.expected, baseline, candidate);
|
|
521
|
+
counts[label]++;
|
|
522
|
+
scenarios.push({
|
|
523
|
+
id: scenario.id,
|
|
524
|
+
scenario,
|
|
525
|
+
label,
|
|
526
|
+
reason,
|
|
527
|
+
baseline,
|
|
528
|
+
candidate
|
|
529
|
+
});
|
|
530
|
+
}
|
|
531
|
+
return {
|
|
532
|
+
scenarios,
|
|
533
|
+
counts,
|
|
534
|
+
ok: counts.regression === 0
|
|
535
|
+
};
|
|
431
536
|
}
|
|
432
|
-
function
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
537
|
+
async function settle(run) {
|
|
538
|
+
try {
|
|
539
|
+
return await run();
|
|
540
|
+
} catch (error) {
|
|
541
|
+
return {
|
|
542
|
+
outcome: "threw",
|
|
543
|
+
detail: error instanceof Error ? error.message : String(error)
|
|
544
|
+
};
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
function labelRun(expected, baseline, candidate) {
|
|
548
|
+
if (candidate.violations?.length) return {
|
|
549
|
+
label: "regression",
|
|
550
|
+
reason: `candidate broke a rule: ${list(candidate.violations)}`
|
|
551
|
+
};
|
|
552
|
+
if (candidate.outcome === "threw") return {
|
|
553
|
+
label: "regression",
|
|
554
|
+
reason: `candidate threw: ${String(candidate.detail)}`
|
|
555
|
+
};
|
|
556
|
+
if (baseline.violations?.length) return {
|
|
557
|
+
label: "intended",
|
|
558
|
+
reason: `baseline broke a rule: ${list(baseline.violations)}`
|
|
559
|
+
};
|
|
560
|
+
const sameOutcome = baseline.outcome === candidate.outcome;
|
|
561
|
+
if (sameOutcome && structurallyEqual(baseline.effects, candidate.effects)) return {
|
|
562
|
+
label: "same",
|
|
563
|
+
reason: ""
|
|
564
|
+
};
|
|
565
|
+
if (expected !== void 0 && candidate.outcome === expected && baseline.outcome !== expected) return {
|
|
566
|
+
label: "intended",
|
|
567
|
+
reason: `only the candidate reached the expected '${expected}'`
|
|
568
|
+
};
|
|
569
|
+
return {
|
|
570
|
+
label: "regression",
|
|
571
|
+
reason: sameOutcome ? "effects differ" : `outcome differs: ${baseline.outcome} → ${candidate.outcome}`
|
|
572
|
+
};
|
|
573
|
+
}
|
|
574
|
+
function list(items) {
|
|
575
|
+
return items.map((item) => typeof item === "string" ? item : JSON.stringify(item)).join(", ");
|
|
576
|
+
}
|
|
577
|
+
function structurallyEqual(a, b) {
|
|
578
|
+
if (Object.is(a, b)) return true;
|
|
579
|
+
if (a instanceof Date || b instanceof Date) return a instanceof Date && b instanceof Date && a.getTime() === b.getTime();
|
|
580
|
+
if (a instanceof Map || b instanceof Map) return a instanceof Map && b instanceof Map && structurallyEqual([...a], [...b]);
|
|
581
|
+
if (a instanceof Set || b instanceof Set) return a instanceof Set && b instanceof Set && structurallyEqual([...a], [...b]);
|
|
582
|
+
if (Array.isArray(a) || Array.isArray(b)) return Array.isArray(a) && Array.isArray(b) && a.length === b.length && a.every((item, index) => structurallyEqual(item, b[index]));
|
|
583
|
+
if (!isRecord(a) || !isRecord(b)) return false;
|
|
584
|
+
const keys = Object.keys(a);
|
|
585
|
+
return keys.length === Object.keys(b).length && keys.every((key) => Object.hasOwn(b, key) && structurallyEqual(a[key], b[key]));
|
|
438
586
|
}
|
|
439
587
|
//#endregion
|
|
440
|
-
export { AgentLintError, AgentUnknownStateError, assertAgentMachine, canReach, explorePaths, foldTraces, lintAgentMachine, matchesTrajectory, runSeam, simulateAgent };
|
|
588
|
+
export { AgentLintError, AgentUnknownStateError, assertAgentMachine, canReach, compareRuns, explorePaths, foldTraces, getDecisionRequests, lintAgentMachine, matchesTrajectory, runSeam, simulateAgent };
|
|
@@ -130,9 +130,13 @@ declare function parseAgentEvent<TSource extends AnyStateMachine | AnyMachineSna
|
|
|
130
130
|
* ({@link RESERVED_AGENT_EVENT_PREFIX}) event types are always excluded, before
|
|
131
131
|
* any `allowedEvents` matching — a machine that handles `'@agent.usage'` still
|
|
132
132
|
* never offers it to a model.
|
|
133
|
+
*
|
|
134
|
+
* Pass `actor: "agent"` for the list a model may choose from: it also drops an
|
|
135
|
+
* event the state handles through a transition tagged `meta: { actor: "human" }`.
|
|
133
136
|
*/
|
|
134
137
|
declare function getAcceptedEvents(snapshot: AnyMachineSnapshot, options?: Pick<AgentRequestOptions, "events" | "schemas"> & {
|
|
135
138
|
eventTypes?: readonly string[];
|
|
139
|
+
actor?: "agent";
|
|
136
140
|
}): AgentEventDescriptor[];
|
|
137
141
|
//#endregion
|
|
138
142
|
//#region src/decision.d.ts
|
|
@@ -228,7 +232,7 @@ interface DecisionLogic<TInputSchema extends StandardSchemaV1 = StandardSchemaV1
|
|
|
228
232
|
*
|
|
229
233
|
* export const chooseMove = createDecisionLogic({
|
|
230
234
|
* schemas: { input: z.object({ playerHp: z.number(), enemyHp: z.number() }) },
|
|
231
|
-
* model: 'openai/gpt-
|
|
235
|
+
* model: 'openai/gpt-6-luna',
|
|
232
236
|
* system: 'You are playing a turn-based game. Choose exactly one legal move.',
|
|
233
237
|
* prompt: ({ input }) => `Player HP: ${input.playerHp}\nEnemy HP: ${input.enemyHp}`,
|
|
234
238
|
* allowedEvents: ({ input }) =>
|
|
@@ -733,7 +737,7 @@ interface TextLogic<TInputSchema extends StandardSchemaV1 = StandardSchemaV1, TO
|
|
|
733
737
|
* export const tellJoke = createTextLogic({
|
|
734
738
|
* mode: 'stream',
|
|
735
739
|
* schemas: { input: z.object({ topic: z.string() }), output: z.string() },
|
|
736
|
-
* model: 'openai/gpt-
|
|
740
|
+
* model: 'openai/gpt-6-luna',
|
|
737
741
|
* system: 'You tell short, punchy jokes.',
|
|
738
742
|
* prompt: ({ input }) => `Tell a joke about ${input.topic}.`,
|
|
739
743
|
* });
|
|
@@ -130,9 +130,13 @@ declare function parseAgentEvent<TSource extends AnyStateMachine | AnyMachineSna
|
|
|
130
130
|
* ({@link RESERVED_AGENT_EVENT_PREFIX}) event types are always excluded, before
|
|
131
131
|
* any `allowedEvents` matching — a machine that handles `'@agent.usage'` still
|
|
132
132
|
* never offers it to a model.
|
|
133
|
+
*
|
|
134
|
+
* Pass `actor: "agent"` for the list a model may choose from: it also drops an
|
|
135
|
+
* event the state handles through a transition tagged `meta: { actor: "human" }`.
|
|
133
136
|
*/
|
|
134
137
|
declare function getAcceptedEvents(snapshot: AnyMachineSnapshot, options?: Pick<AgentRequestOptions, "events" | "schemas"> & {
|
|
135
138
|
eventTypes?: readonly string[];
|
|
139
|
+
actor?: "agent";
|
|
136
140
|
}): AgentEventDescriptor[];
|
|
137
141
|
//#endregion
|
|
138
142
|
//#region src/decision.d.ts
|
|
@@ -228,7 +232,7 @@ interface DecisionLogic<TInputSchema extends StandardSchemaV1 = StandardSchemaV1
|
|
|
228
232
|
*
|
|
229
233
|
* export const chooseMove = createDecisionLogic({
|
|
230
234
|
* schemas: { input: z.object({ playerHp: z.number(), enemyHp: z.number() }) },
|
|
231
|
-
* model: 'openai/gpt-
|
|
235
|
+
* model: 'openai/gpt-6-luna',
|
|
232
236
|
* system: 'You are playing a turn-based game. Choose exactly one legal move.',
|
|
233
237
|
* prompt: ({ input }) => `Player HP: ${input.playerHp}\nEnemy HP: ${input.enemyHp}`,
|
|
234
238
|
* allowedEvents: ({ input }) =>
|
|
@@ -733,7 +737,7 @@ interface TextLogic<TInputSchema extends StandardSchemaV1 = StandardSchemaV1, TO
|
|
|
733
737
|
* export const tellJoke = createTextLogic({
|
|
734
738
|
* mode: 'stream',
|
|
735
739
|
* schemas: { input: z.object({ topic: z.string() }), output: z.string() },
|
|
736
|
-
* model: 'openai/gpt-
|
|
740
|
+
* model: 'openai/gpt-6-luna',
|
|
737
741
|
* system: 'You tell short, punchy jokes.',
|
|
738
742
|
* prompt: ({ input }) => `Tell a joke about ${input.topic}.`,
|
|
739
743
|
* });
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { t as AgentCallUsage } from "./text-logic-
|
|
1
|
+
import { t as AgentCallUsage } from "./text-logic-j9hShB7d.cjs";
|
|
2
2
|
import { EventObject } from "xstate";
|
|
3
3
|
//#region src/usage.d.ts
|
|
4
4
|
/** Reserved event delivered after a model call reports token usage. */
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { t as AgentCallUsage } from "./text-logic-
|
|
1
|
+
import { t as AgentCallUsage } from "./text-logic-BwdrDpO9.mjs";
|
|
2
2
|
import { EventObject } from "xstate";
|
|
3
3
|
//#region src/usage.d.ts
|
|
4
4
|
/** Reserved event delivered after a model call reports token usage. */
|
package/dist/validate.cjs
CHANGED
|
@@ -21,9 +21,9 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
21
21
|
enumerable: true
|
|
22
22
|
}) : target, mod));
|
|
23
23
|
//#endregion
|
|
24
|
-
const require_event_log = require("./event-log-
|
|
25
|
-
const require_setup_agent = require("./setup-agent-
|
|
26
|
-
const require_verify = require("./verify-
|
|
24
|
+
const require_event_log = require("./event-log-Bdww2l1D.cjs");
|
|
25
|
+
const require_setup_agent = require("./setup-agent-D0L8Anl_.cjs");
|
|
26
|
+
const require_verify = require("./verify-CS_xxvVU.cjs");
|
|
27
27
|
let ajv_dist_2020_js = require("ajv/dist/2020.js");
|
|
28
28
|
ajv_dist_2020_js = __toESM(ajv_dist_2020_js, 1);
|
|
29
29
|
//#region schemas/agent-workflow.json
|
package/dist/validate.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { d as AgentWorkflowConfig, g as FromConfigOptions, v as SchemaCompiler } from "./setup-agent-
|
|
2
|
-
import {
|
|
1
|
+
import { d as AgentWorkflowConfig, g as FromConfigOptions, v as SchemaCompiler } from "./setup-agent-yFFVXf5s.cjs";
|
|
2
|
+
import { u as ExplorePathsOptions } from "./verify-CPKDPMwY.cjs";
|
|
3
3
|
import { AnyActorLogic, AnyStateMachine } from "xstate";
|
|
4
4
|
//#region src/validate/validate-config.d.ts
|
|
5
5
|
/**
|
package/dist/validate.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { d as AgentWorkflowConfig, g as FromConfigOptions, v as SchemaCompiler } from "./setup-agent-
|
|
2
|
-
import {
|
|
1
|
+
import { d as AgentWorkflowConfig, g as FromConfigOptions, v as SchemaCompiler } from "./setup-agent-CPyg2ic7.mjs";
|
|
2
|
+
import { u as ExplorePathsOptions } from "./verify-tkymWz6X.mjs";
|
|
3
3
|
import { AnyActorLogic, AnyStateMachine } from "xstate";
|
|
4
4
|
//#region src/validate/validate-config.d.ts
|
|
5
5
|
/**
|
package/dist/validate.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { D as STREAM_TEXT_ACTOR, E as GENERATE_TEXT_ACTOR, T as DECIDE_ACTOR } from "./event-log-
|
|
2
|
-
import { i as setupAgentFromConfig } from "./setup-agent-
|
|
3
|
-
import { a as explorePaths, o as lintAgentMachine } from "./verify-
|
|
1
|
+
import { D as STREAM_TEXT_ACTOR, E as GENERATE_TEXT_ACTOR, T as DECIDE_ACTOR } from "./event-log-DE430ZCa.mjs";
|
|
2
|
+
import { i as setupAgentFromConfig } from "./setup-agent-BaffhCcM.mjs";
|
|
3
|
+
import { a as explorePaths, o as lintAgentMachine } from "./verify-BH5e0XLK.mjs";
|
|
4
4
|
import Ajv2020 from "ajv/dist/2020.js";
|
|
5
5
|
//#region schemas/agent-workflow.json
|
|
6
6
|
var agent_workflow_default = {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { P as isTextLogic, U as getRegisteredAgentExecutionOptions, V as executorBoundLogics, X as getJsonSchemaSync,
|
|
2
|
-
import { d as getAcceptedEvents,
|
|
3
|
-
import { getNextTransitions, initialTransition, transition } from "xstate";
|
|
1
|
+
import { P as isTextLogic, U as getRegisteredAgentExecutionOptions, V as executorBoundLogics, X as getJsonSchemaSync, lt as isRecord, ut as AgentError } from "./event-log-DE430ZCa.mjs";
|
|
2
|
+
import { d as getAcceptedEvents, f as getHumanEventTypes, l as resolveDecision, n as acceptedDecisionOptions, p as isEventPattern, s as isDecisionLogic, t as AgentDecisionExhaustedError } from "./decision-DqO018Tp.mjs";
|
|
3
|
+
import { getNextTransitions, initialTransition, machineToJSON, transition } from "xstate";
|
|
4
4
|
//#region src/steps.ts
|
|
5
5
|
/**
|
|
6
6
|
* Internal: the pure `(state, event) => (nextState, requests)` view of an
|
|
@@ -79,12 +79,15 @@ function getAgentRequests(actions, { machine, ...options } = {}) {
|
|
|
79
79
|
const events = options.snapshot ? getAcceptedEvents(options.snapshot, {
|
|
80
80
|
events: options.events,
|
|
81
81
|
schemas: options.schemas,
|
|
82
|
-
eventTypes: allowedEventTypes
|
|
82
|
+
eventTypes: allowedEventTypes,
|
|
83
|
+
actor: "agent"
|
|
83
84
|
}) : [];
|
|
85
|
+
const humanEventTypes = options.snapshot ? getHumanEventTypes(options.snapshot) : /* @__PURE__ */ new Set();
|
|
84
86
|
return [{
|
|
85
87
|
...decisionRequest,
|
|
86
88
|
id: params.id,
|
|
87
|
-
events
|
|
89
|
+
events,
|
|
90
|
+
...decisionRequest.options ? { options: decisionRequest.options.filter((option) => !humanEventTypes.has(option.event.type)) } : {}
|
|
88
91
|
}];
|
|
89
92
|
}
|
|
90
93
|
const textLogic = isTextLogic(registeredLogic) ? registeredLogic : void 0;
|
|
@@ -335,6 +338,45 @@ function checkDecideWithoutEvents(ctx) {
|
|
|
335
338
|
}
|
|
336
339
|
return out;
|
|
337
340
|
}
|
|
341
|
+
function literalAllowedEvents(json, path, index) {
|
|
342
|
+
let node = json;
|
|
343
|
+
for (const key of path.split(".")) node = node?.states?.[key];
|
|
344
|
+
let input = normalizeInvokes(node?.invoke)[index]?.input;
|
|
345
|
+
if (isRecord(input) && typeof input["@expr"] === "string") try {
|
|
346
|
+
input = JSON.parse(input["@expr"]);
|
|
347
|
+
} catch {
|
|
348
|
+
return;
|
|
349
|
+
}
|
|
350
|
+
const allowedEvents = isRecord(input) ? input.allowedEvents : void 0;
|
|
351
|
+
return typeof allowedEvents === "string" ? [allowedEvents] : Array.isArray(allowedEvents) ? allowedEvents : void 0;
|
|
352
|
+
}
|
|
353
|
+
function handlesAsHuman(config, eventType) {
|
|
354
|
+
const transitions = config.on?.[eventType];
|
|
355
|
+
return (Array.isArray(transitions) ? transitions : [transitions]).some((transition) => !!transition && typeof transition === "object" && transition.meta?.actor === "human");
|
|
356
|
+
}
|
|
357
|
+
function checkDecideAllowsHumanEvent(ctx) {
|
|
358
|
+
const out = [];
|
|
359
|
+
for (const node of ctx.index.values()) for (const [index, invoke] of node.invokes.entries()) {
|
|
360
|
+
if (!isDecisionInvoke(invoke.src, ctx.actors)) continue;
|
|
361
|
+
const allowedEvents = literalAllowedEvents(ctx.json, node.path, index);
|
|
362
|
+
if (!allowedEvents) continue;
|
|
363
|
+
const configs = [
|
|
364
|
+
node.config,
|
|
365
|
+
...ancestorChain(node, ctx.index).map((ancestor) => ancestor.config),
|
|
366
|
+
ctx.config
|
|
367
|
+
];
|
|
368
|
+
for (const type of allowedEvents) {
|
|
369
|
+
if (typeof type !== "string" || isEventPattern(type) || !configs.some((config) => handlesAsHuman(config, type))) continue;
|
|
370
|
+
out.push({
|
|
371
|
+
code: "decide-allows-human-event",
|
|
372
|
+
severity: "error",
|
|
373
|
+
path: node.path,
|
|
374
|
+
message: `State '${node.path}' lets a decision choose '${type}', but a transition tagged 'meta: { actor: "human" }' handles it, so the model is never offered it. Remove '${type}' from 'allowedEvents', or drop the tag if a model may send it.`
|
|
375
|
+
});
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
return out;
|
|
379
|
+
}
|
|
338
380
|
function checkDirectObjectSrc(ctx) {
|
|
339
381
|
const out = [];
|
|
340
382
|
for (const node of ctx.index.values()) for (const invoke of node.invokes) {
|
|
@@ -371,6 +413,7 @@ function checkInvokeWithoutOnError(ctx) {
|
|
|
371
413
|
}
|
|
372
414
|
const LINT_CHECKS = [
|
|
373
415
|
checkDecideWithoutEvents,
|
|
416
|
+
checkDecideAllowsHumanEvent,
|
|
374
417
|
checkDirectObjectSrc,
|
|
375
418
|
checkInvokeWithoutOnError
|
|
376
419
|
];
|
|
@@ -408,8 +451,15 @@ function lintAgentMachine(machine, options = {}) {
|
|
|
408
451
|
const config = machine.config ?? {};
|
|
409
452
|
const index = buildStateIndex(config);
|
|
410
453
|
const registered = getRegisteredAgentExecutionOptions(machine);
|
|
454
|
+
let json;
|
|
455
|
+
try {
|
|
456
|
+
json = machineToJSON(machine);
|
|
457
|
+
} catch {
|
|
458
|
+
json = void 0;
|
|
459
|
+
}
|
|
411
460
|
const ctx = {
|
|
412
461
|
config,
|
|
462
|
+
json,
|
|
413
463
|
index,
|
|
414
464
|
schemas: registered.schemas,
|
|
415
465
|
actors: registered.actors ?? machine.sources?.actors ?? {}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { u as ChosenEvent } from "./types-Dp5_Ru4R.cjs";
|
|
2
|
-
import { Q as AgentError } from "./text-logic-
|
|
2
|
+
import { Q as AgentError } from "./text-logic-j9hShB7d.cjs";
|
|
3
3
|
import { AnyMachineSnapshot, AnyStateMachine } from "xstate";
|
|
4
4
|
//#region src/verify.d.ts
|
|
5
5
|
/** Severity of an {@link AgentLintDiagnostic}. `error` findings fail CI/the CLI; `warning`s are advisory. */
|
|
@@ -10,7 +10,7 @@ type AgentLintSeverity = "error" | "warning";
|
|
|
10
10
|
* or config location, and `message` explains the problem and its remedy.
|
|
11
11
|
*/
|
|
12
12
|
interface AgentLintDiagnostic {
|
|
13
|
-
code: "decide-without-events" | "direct-object-src" | "invoke-without-on-error";
|
|
13
|
+
code: "decide-without-events" | "decide-allows-human-event" | "direct-object-src" | "invoke-without-on-error";
|
|
14
14
|
severity: AgentLintSeverity;
|
|
15
15
|
/** State path (`parent.child`) or config pointer (e.g. `(root)`, `context`) the finding is about. */
|
|
16
16
|
path: string;
|
|
@@ -212,6 +212,14 @@ interface SimulateAgentResult {
|
|
|
212
212
|
*/
|
|
213
213
|
declare function simulateAgent(machine: AnyStateMachine, options: SimulateAgentOptions): Promise<SimulateAgentResult>;
|
|
214
214
|
/** Options for {@link explorePaths}. */
|
|
215
|
+
/**
|
|
216
|
+
* The snapshot type the exploration callbacks (`payloads`, `dedupeBy`, a
|
|
217
|
+
* `canReach` predicate) receive. Import it from here rather than from your
|
|
218
|
+
* own `xstate`, which can be another version than the one this package uses.
|
|
219
|
+
*/
|
|
220
|
+
type ExploreSnapshot = AnyMachineSnapshot;
|
|
221
|
+
/** What {@link canReach} looks for: a state id or path, or a snapshot predicate. */
|
|
222
|
+
type CanReachTarget = string | ((snapshot: ExploreSnapshot) => boolean);
|
|
215
223
|
interface ExplorePathsOptions {
|
|
216
224
|
input?: unknown;
|
|
217
225
|
/** Max branch points (decisions + external-event forks) along any path. Default 8. */
|
|
@@ -274,7 +282,7 @@ interface ExplorePathsOptions {
|
|
|
274
282
|
* were not all tried, so it is listed in `unexpandedEvents`. A type with no
|
|
275
283
|
* schema at all is applied as `{ type }`.
|
|
276
284
|
*/
|
|
277
|
-
payloads?: (snapshot:
|
|
285
|
+
payloads?: (snapshot: ExploreSnapshot) => Partial<Record<string, Record<string, unknown>[]>>;
|
|
278
286
|
/**
|
|
279
287
|
* A projection of the snapshot that determines its future. Settled
|
|
280
288
|
* snapshots with an equal key are explored once (again only when reached
|
|
@@ -283,7 +291,7 @@ interface ExplorePathsOptions {
|
|
|
283
291
|
* a key that drops a field the machine reads makes the search unsound.
|
|
284
292
|
* Without it, every path is explored in full.
|
|
285
293
|
*/
|
|
286
|
-
dedupeBy?: (snapshot:
|
|
294
|
+
dedupeBy?: (snapshot: ExploreSnapshot) => string;
|
|
287
295
|
}
|
|
288
296
|
/** A single explored path's terminal outcome. */
|
|
289
297
|
interface AgentPathTerminal {
|
|
@@ -409,6 +417,6 @@ declare class AgentUnknownStateError extends AgentError {
|
|
|
409
417
|
* // violation.reachable → false is the safety proof
|
|
410
418
|
* ```
|
|
411
419
|
*/
|
|
412
|
-
declare function canReach(machine: AnyStateMachine, target:
|
|
420
|
+
declare function canReach(machine: AnyStateMachine, target: CanReachTarget, options?: ExplorePathsOptions): Promise<CanReachResult>;
|
|
413
421
|
//#endregion
|
|
414
|
-
export {
|
|
422
|
+
export { assertAgentMachine as _, AgentPathTerminal as a, lintAgentMachine as b, CanReachResult as c, ExploreSnapshot as d, LintAgentMachineOptions as f, SimulationTrailEntry as g, SimulationScript as h, AgentPathReport as i, CanReachTarget as l, SimulateAgentResult as m, AgentLintError as n, AgentUnknownStateError as o, SimulateAgentOptions as p, AgentLintSeverity as r, AssertAgentMachineOptions as s, AgentLintDiagnostic as t, ExplorePathsOptions as u, canReach as v, simulateAgent as x, explorePaths as y };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
const require_event_log = require("./event-log-
|
|
2
|
-
const require_decision = require("./decision-
|
|
1
|
+
const require_event_log = require("./event-log-Bdww2l1D.cjs");
|
|
2
|
+
const require_decision = require("./decision-Iys2hzg3.cjs");
|
|
3
3
|
let xstate = require("xstate");
|
|
4
4
|
//#region src/steps.ts
|
|
5
5
|
/**
|
|
@@ -79,12 +79,15 @@ function getAgentRequests(actions, { machine, ...options } = {}) {
|
|
|
79
79
|
const events = options.snapshot ? require_decision.getAcceptedEvents(options.snapshot, {
|
|
80
80
|
events: options.events,
|
|
81
81
|
schemas: options.schemas,
|
|
82
|
-
eventTypes: allowedEventTypes
|
|
82
|
+
eventTypes: allowedEventTypes,
|
|
83
|
+
actor: "agent"
|
|
83
84
|
}) : [];
|
|
85
|
+
const humanEventTypes = options.snapshot ? require_decision.getHumanEventTypes(options.snapshot) : /* @__PURE__ */ new Set();
|
|
84
86
|
return [{
|
|
85
87
|
...decisionRequest,
|
|
86
88
|
id: params.id,
|
|
87
|
-
events
|
|
89
|
+
events,
|
|
90
|
+
...decisionRequest.options ? { options: decisionRequest.options.filter((option) => !humanEventTypes.has(option.event.type)) } : {}
|
|
88
91
|
}];
|
|
89
92
|
}
|
|
90
93
|
const textLogic = require_event_log.isTextLogic(registeredLogic) ? registeredLogic : void 0;
|
|
@@ -335,6 +338,45 @@ function checkDecideWithoutEvents(ctx) {
|
|
|
335
338
|
}
|
|
336
339
|
return out;
|
|
337
340
|
}
|
|
341
|
+
function literalAllowedEvents(json, path, index) {
|
|
342
|
+
let node = json;
|
|
343
|
+
for (const key of path.split(".")) node = node?.states?.[key];
|
|
344
|
+
let input = normalizeInvokes(node?.invoke)[index]?.input;
|
|
345
|
+
if (require_event_log.isRecord(input) && typeof input["@expr"] === "string") try {
|
|
346
|
+
input = JSON.parse(input["@expr"]);
|
|
347
|
+
} catch {
|
|
348
|
+
return;
|
|
349
|
+
}
|
|
350
|
+
const allowedEvents = require_event_log.isRecord(input) ? input.allowedEvents : void 0;
|
|
351
|
+
return typeof allowedEvents === "string" ? [allowedEvents] : Array.isArray(allowedEvents) ? allowedEvents : void 0;
|
|
352
|
+
}
|
|
353
|
+
function handlesAsHuman(config, eventType) {
|
|
354
|
+
const transitions = config.on?.[eventType];
|
|
355
|
+
return (Array.isArray(transitions) ? transitions : [transitions]).some((transition) => !!transition && typeof transition === "object" && transition.meta?.actor === "human");
|
|
356
|
+
}
|
|
357
|
+
function checkDecideAllowsHumanEvent(ctx) {
|
|
358
|
+
const out = [];
|
|
359
|
+
for (const node of ctx.index.values()) for (const [index, invoke] of node.invokes.entries()) {
|
|
360
|
+
if (!isDecisionInvoke(invoke.src, ctx.actors)) continue;
|
|
361
|
+
const allowedEvents = literalAllowedEvents(ctx.json, node.path, index);
|
|
362
|
+
if (!allowedEvents) continue;
|
|
363
|
+
const configs = [
|
|
364
|
+
node.config,
|
|
365
|
+
...ancestorChain(node, ctx.index).map((ancestor) => ancestor.config),
|
|
366
|
+
ctx.config
|
|
367
|
+
];
|
|
368
|
+
for (const type of allowedEvents) {
|
|
369
|
+
if (typeof type !== "string" || require_decision.isEventPattern(type) || !configs.some((config) => handlesAsHuman(config, type))) continue;
|
|
370
|
+
out.push({
|
|
371
|
+
code: "decide-allows-human-event",
|
|
372
|
+
severity: "error",
|
|
373
|
+
path: node.path,
|
|
374
|
+
message: `State '${node.path}' lets a decision choose '${type}', but a transition tagged 'meta: { actor: "human" }' handles it, so the model is never offered it. Remove '${type}' from 'allowedEvents', or drop the tag if a model may send it.`
|
|
375
|
+
});
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
return out;
|
|
379
|
+
}
|
|
338
380
|
function checkDirectObjectSrc(ctx) {
|
|
339
381
|
const out = [];
|
|
340
382
|
for (const node of ctx.index.values()) for (const invoke of node.invokes) {
|
|
@@ -371,6 +413,7 @@ function checkInvokeWithoutOnError(ctx) {
|
|
|
371
413
|
}
|
|
372
414
|
const LINT_CHECKS = [
|
|
373
415
|
checkDecideWithoutEvents,
|
|
416
|
+
checkDecideAllowsHumanEvent,
|
|
374
417
|
checkDirectObjectSrc,
|
|
375
418
|
checkInvokeWithoutOnError
|
|
376
419
|
];
|
|
@@ -408,8 +451,15 @@ function lintAgentMachine(machine, options = {}) {
|
|
|
408
451
|
const config = machine.config ?? {};
|
|
409
452
|
const index = buildStateIndex(config);
|
|
410
453
|
const registered = require_event_log.getRegisteredAgentExecutionOptions(machine);
|
|
454
|
+
let json;
|
|
455
|
+
try {
|
|
456
|
+
json = (0, xstate.machineToJSON)(machine);
|
|
457
|
+
} catch {
|
|
458
|
+
json = void 0;
|
|
459
|
+
}
|
|
411
460
|
const ctx = {
|
|
412
461
|
config,
|
|
462
|
+
json,
|
|
413
463
|
index,
|
|
414
464
|
schemas: registered.schemas,
|
|
415
465
|
actors: registered.actors ?? machine.sources?.actors ?? {}
|
|
@@ -716,7 +766,7 @@ const MAX_ADVANCE_STEPS = 1e3;
|
|
|
716
766
|
const FINITE_PAYLOAD_CAP = 64;
|
|
717
767
|
const DEFAULT_MAX_NODES = 1e5;
|
|
718
768
|
function finiteDomain(schema) {
|
|
719
|
-
if (!
|
|
769
|
+
if (!require_event_log.isRecord(schema)) return;
|
|
720
770
|
if ("const" in schema) return [schema["const"]];
|
|
721
771
|
if (Array.isArray(schema["enum"])) return schema["enum"];
|
|
722
772
|
const union = schema["anyOf"] ?? schema["oneOf"];
|
|
@@ -733,8 +783,8 @@ function finitePayloads(jsonSchema) {
|
|
|
733
783
|
payloads: [{}],
|
|
734
784
|
complete: false
|
|
735
785
|
};
|
|
736
|
-
if (!
|
|
737
|
-
const properties =
|
|
786
|
+
if (!require_event_log.isRecord(jsonSchema) || jsonSchema["type"] !== "object" && !require_event_log.isRecord(jsonSchema["properties"])) return bare;
|
|
787
|
+
const properties = require_event_log.isRecord(jsonSchema["properties"]) ? jsonSchema["properties"] : {};
|
|
738
788
|
const required = new Set(Array.isArray(jsonSchema["required"]) ? jsonSchema["required"] : []);
|
|
739
789
|
if ([...required].some((key) => key !== "type" && !(key in properties))) return bare;
|
|
740
790
|
let product = [{}];
|