@graphorin/agent 0.6.0 → 0.7.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.
Files changed (110) hide show
  1. package/CHANGELOG.md +96 -0
  2. package/README.md +31 -11
  3. package/dist/errors/index.d.ts +17 -4
  4. package/dist/errors/index.d.ts.map +1 -1
  5. package/dist/errors/index.js +19 -3
  6. package/dist/errors/index.js.map +1 -1
  7. package/dist/factory.d.ts.map +1 -1
  8. package/dist/factory.js +153 -1930
  9. package/dist/factory.js.map +1 -1
  10. package/dist/fanout/index.d.ts +13 -1
  11. package/dist/fanout/index.d.ts.map +1 -1
  12. package/dist/fanout/index.js +13 -4
  13. package/dist/fanout/index.js.map +1 -1
  14. package/dist/index.d.ts +7 -6
  15. package/dist/index.d.ts.map +1 -1
  16. package/dist/index.js +11 -9
  17. package/dist/index.js.map +1 -1
  18. package/dist/lateral-leak/index.js +1 -1
  19. package/dist/package.js +6 -0
  20. package/dist/package.js.map +1 -0
  21. package/dist/run-state/index.d.ts +32 -6
  22. package/dist/run-state/index.d.ts.map +1 -1
  23. package/dist/run-state/index.js +46 -22
  24. package/dist/run-state/index.js.map +1 -1
  25. package/dist/runtime/agent-surface.js +122 -0
  26. package/dist/runtime/agent-surface.js.map +1 -0
  27. package/dist/runtime/agent-to-tool.d.ts +51 -0
  28. package/dist/runtime/agent-to-tool.d.ts.map +1 -0
  29. package/dist/runtime/agent-to-tool.js +145 -0
  30. package/dist/runtime/agent-to-tool.js.map +1 -0
  31. package/dist/runtime/approvals.js +0 -0
  32. package/dist/runtime/approvals.js.map +1 -0
  33. package/dist/runtime/dispatch.js +108 -0
  34. package/dist/runtime/dispatch.js.map +1 -0
  35. package/dist/runtime/executor-wiring.js +128 -0
  36. package/dist/runtime/executor-wiring.js.map +1 -0
  37. package/dist/runtime/fallback-chain.js +139 -0
  38. package/dist/runtime/fallback-chain.js.map +1 -0
  39. package/dist/runtime/handoff.js +307 -0
  40. package/dist/runtime/handoff.js.map +1 -0
  41. package/dist/runtime/messages.d.ts +22 -0
  42. package/dist/runtime/messages.d.ts.map +1 -0
  43. package/dist/runtime/messages.js +204 -0
  44. package/dist/runtime/messages.js.map +1 -0
  45. package/dist/runtime/provider-events.js +117 -0
  46. package/dist/runtime/provider-events.js.map +1 -0
  47. package/dist/runtime/run-compaction.js +210 -0
  48. package/dist/runtime/run-compaction.js.map +1 -0
  49. package/dist/runtime/run-finish.js +48 -0
  50. package/dist/runtime/run-finish.js.map +1 -0
  51. package/dist/runtime/run-gates.js +336 -0
  52. package/dist/runtime/run-gates.js.map +1 -0
  53. package/dist/runtime/run-init.js +81 -0
  54. package/dist/runtime/run-init.js.map +1 -0
  55. package/dist/runtime/run-input.js +46 -0
  56. package/dist/runtime/run-input.js.map +1 -0
  57. package/dist/runtime/step-catalogue.js +173 -0
  58. package/dist/runtime/step-catalogue.js.map +1 -0
  59. package/dist/runtime/tool-call-walk.js +189 -0
  60. package/dist/runtime/tool-call-walk.js.map +1 -0
  61. package/dist/runtime/tool-wiring.js +159 -0
  62. package/dist/runtime/tool-wiring.js.map +1 -0
  63. package/dist/tooling/adapters.js +1 -1
  64. package/dist/tooling/dataflow.js +1 -1
  65. package/dist/tooling/policy.js +2 -0
  66. package/dist/tooling/policy.js.map +1 -1
  67. package/dist/types.d.ts +63 -13
  68. package/dist/types.d.ts.map +1 -1
  69. package/package.json +20 -20
  70. package/src/errors/index.ts +320 -0
  71. package/src/evaluator-optimizer/index.ts +212 -0
  72. package/src/factory.ts +957 -0
  73. package/src/fallback/index.ts +108 -0
  74. package/src/fanout/index.ts +523 -0
  75. package/src/filters/index.ts +347 -0
  76. package/src/index.ts +180 -0
  77. package/src/internal/ids.ts +46 -0
  78. package/src/internal/usage-accumulator.ts +90 -0
  79. package/src/lateral-leak/causality-monitor.ts +221 -0
  80. package/src/lateral-leak/index.ts +35 -0
  81. package/src/lateral-leak/merge-guard.ts +151 -0
  82. package/src/lateral-leak/protocol-guard.ts +222 -0
  83. package/src/preferred-model/index.ts +210 -0
  84. package/src/progress/index.ts +238 -0
  85. package/src/run-state/index.ts +607 -0
  86. package/src/runtime/agent-surface.ts +218 -0
  87. package/src/runtime/agent-to-tool.ts +323 -0
  88. package/src/runtime/approvals.ts +0 -0
  89. package/src/runtime/dispatch.ts +183 -0
  90. package/src/runtime/executor-wiring.ts +331 -0
  91. package/src/runtime/fallback-chain.ts +250 -0
  92. package/src/runtime/handoff.ts +428 -0
  93. package/src/runtime/messages.ts +309 -0
  94. package/src/runtime/provider-events.ts +175 -0
  95. package/src/runtime/run-compaction.ts +288 -0
  96. package/src/runtime/run-finish.ts +93 -0
  97. package/src/runtime/run-gates.ts +419 -0
  98. package/src/runtime/run-init.ts +169 -0
  99. package/src/runtime/run-input.ts +102 -0
  100. package/src/runtime/step-catalogue.ts +338 -0
  101. package/src/runtime/tool-call-walk.ts +301 -0
  102. package/src/runtime/tool-wiring.ts +218 -0
  103. package/src/testing/replay-provider.ts +121 -0
  104. package/src/tooling/adapters.ts +403 -0
  105. package/src/tooling/catalogue.ts +36 -0
  106. package/src/tooling/dataflow.ts +171 -0
  107. package/src/tooling/plan.ts +123 -0
  108. package/src/tooling/policy.ts +67 -0
  109. package/src/tooling/registry-build.ts +191 -0
  110. package/src/types.ts +696 -0
@@ -0,0 +1,212 @@
1
+ /**
2
+ * `evaluatorOptimizer({...})` - Generator → Evaluator iteration
3
+ * loop with three rubric kinds and a REQUIRED iteration cap.
4
+ *
5
+ * Iteration boundary discipline: each iteration is a fresh
6
+ * agent.run-equivalent boundary. Intra-loop reasoning per RB-42 /
7
+ * suggested DEC-158 applies WITHIN one iteration, not ACROSS
8
+ * iterations. The Generator's iteration-N input is the original
9
+ * user input + the Evaluator's iteration-(N-1) critique (NOT the
10
+ * Generator's iteration-(N-1) internal message history).
11
+ *
12
+ * @packageDocumentation
13
+ */
14
+
15
+ import type { AgentEvent } from '@graphorin/core';
16
+ import { EvaluatorOptimizerConfigError } from '../errors/index.js';
17
+
18
+ /**
19
+ * Rubric discriminator. Pick the variant that matches your
20
+ * Evaluator's contract.
21
+ *
22
+ * @stable
23
+ */
24
+ export type Rubric =
25
+ | { readonly kind: 'free-form'; readonly instructions: string }
26
+ | { readonly kind: 'zod'; readonly instructions: string }
27
+ | { readonly kind: 'llm-judge'; readonly promptTemplate: string };
28
+
29
+ /**
30
+ * Per-iteration evaluation outcome returned by the Evaluator.
31
+ *
32
+ * @stable
33
+ */
34
+ export interface EvaluatorOutcome {
35
+ readonly score: number;
36
+ readonly pass: boolean;
37
+ readonly critique: string;
38
+ }
39
+
40
+ /**
41
+ * Generator callable shape. Receives the original user input plus
42
+ * the previous iteration's critique (or `undefined` on the first
43
+ * iteration) and returns the new candidate output.
44
+ *
45
+ * @stable
46
+ */
47
+ export type GeneratorCallable<TOutput> = (
48
+ input: string,
49
+ priorCritique: string | undefined,
50
+ iteration: number,
51
+ ) => Promise<TOutput>;
52
+
53
+ /**
54
+ * Evaluator callable shape. Receives the original user input + the
55
+ * candidate output and returns the structured outcome.
56
+ *
57
+ * @stable
58
+ */
59
+ export type EvaluatorCallable<TOutput> = (
60
+ input: string,
61
+ candidate: TOutput,
62
+ rubric: Rubric,
63
+ iteration: number,
64
+ ) => Promise<EvaluatorOutcome>;
65
+
66
+ /**
67
+ * Options accepted by {@link evaluatorOptimizer}. `maxIterations`
68
+ * is REQUIRED - the helper asserts `>= 1` at construction time.
69
+ *
70
+ * @stable
71
+ */
72
+ export interface EvaluatorOptimizerOptions<TOutput> {
73
+ readonly generator: GeneratorCallable<TOutput>;
74
+ readonly evaluator: EvaluatorCallable<TOutput>;
75
+ readonly maxIterations: number;
76
+ readonly rubric: Rubric;
77
+ readonly mergeStrategy?: 'last-iteration' | 'best-score';
78
+ readonly signal?: AbortSignal;
79
+ /** Optional event emitter for `agent.evaluator.iteration / converged`. */
80
+ readonly emit?: (event: AgentEvent) => void;
81
+ readonly runId: string;
82
+ readonly sessionId: string;
83
+ readonly agentId: string;
84
+ }
85
+
86
+ /**
87
+ * Aggregate outcome of an `evaluatorOptimizer({...})` run.
88
+ *
89
+ * @stable
90
+ */
91
+ export interface EvaluatorOptimizerOutcome<TOutput> {
92
+ readonly output: TOutput;
93
+ readonly iterations: ReadonlyArray<{
94
+ readonly iteration: number;
95
+ readonly candidate: TOutput;
96
+ readonly score: number;
97
+ readonly pass: boolean;
98
+ readonly critique: string;
99
+ readonly durationMs: number;
100
+ }>;
101
+ readonly terminationReason: 'pass' | 'maxIterations' | 'generator-exhausted' | 'cancelled';
102
+ readonly finalScore: number;
103
+ }
104
+
105
+ /**
106
+ * Run the Generator → Evaluator iteration loop.
107
+ *
108
+ * @stable
109
+ */
110
+ export async function evaluatorOptimizer<TOutput>(
111
+ input: string,
112
+ options: EvaluatorOptimizerOptions<TOutput>,
113
+ ): Promise<EvaluatorOptimizerOutcome<TOutput>> {
114
+ if (!Number.isFinite(options.maxIterations) || options.maxIterations < 1) {
115
+ throw new EvaluatorOptimizerConfigError(
116
+ `'maxIterations' must be >= 1 (got ${String(options.maxIterations)})`,
117
+ );
118
+ }
119
+ const mergeStrategy = options.mergeStrategy ?? 'last-iteration';
120
+ const iterations: Array<{
121
+ iteration: number;
122
+ candidate: TOutput;
123
+ score: number;
124
+ pass: boolean;
125
+ critique: string;
126
+ durationMs: number;
127
+ }> = [];
128
+
129
+ let priorCritique: string | undefined;
130
+ let terminationReason: EvaluatorOptimizerOutcome<TOutput>['terminationReason'] = 'maxIterations';
131
+
132
+ for (let i = 1; i <= options.maxIterations; i++) {
133
+ if (options.signal?.aborted) {
134
+ terminationReason = 'cancelled';
135
+ break;
136
+ }
137
+ const iterStart = Date.now();
138
+ let candidate: TOutput;
139
+ try {
140
+ candidate = await options.generator(input, priorCritique, i);
141
+ } catch {
142
+ terminationReason = 'generator-exhausted';
143
+ break;
144
+ }
145
+ const outcome = await options.evaluator(input, candidate, options.rubric, i);
146
+ const iterDuration = Date.now() - iterStart;
147
+
148
+ iterations.push({
149
+ iteration: i,
150
+ candidate,
151
+ score: outcome.score,
152
+ pass: outcome.pass,
153
+ critique: outcome.critique,
154
+ durationMs: iterDuration,
155
+ });
156
+
157
+ options.emit?.({
158
+ type: 'agent.evaluator.iteration',
159
+ runId: options.runId,
160
+ sessionId: options.sessionId,
161
+ agentId: options.agentId,
162
+ iteration: i,
163
+ score: outcome.score,
164
+ pass: outcome.pass,
165
+ critique: outcome.critique,
166
+ durationMs: iterDuration,
167
+ });
168
+
169
+ if (outcome.pass) {
170
+ terminationReason = 'pass';
171
+ break;
172
+ }
173
+ priorCritique = outcome.critique;
174
+ }
175
+
176
+ let finalEntry: (typeof iterations)[number];
177
+ if (iterations.length === 0) {
178
+ // Should only happen on `cancelled` before the first iteration -
179
+ // synthesize a no-op final entry.
180
+ finalEntry = {
181
+ iteration: 0,
182
+ candidate: '' as unknown as TOutput,
183
+ score: 0,
184
+ pass: false,
185
+ critique: '',
186
+ durationMs: 0,
187
+ };
188
+ } else if (mergeStrategy === 'best-score') {
189
+ finalEntry = iterations.reduce((best, current) =>
190
+ current.score > best.score ? current : best,
191
+ );
192
+ } else {
193
+ finalEntry = iterations[iterations.length - 1] as (typeof iterations)[number];
194
+ }
195
+
196
+ options.emit?.({
197
+ type: 'agent.evaluator.converged',
198
+ runId: options.runId,
199
+ sessionId: options.sessionId,
200
+ agentId: options.agentId,
201
+ totalIterations: iterations.length,
202
+ finalScore: finalEntry.score,
203
+ terminationReason,
204
+ });
205
+
206
+ return {
207
+ output: finalEntry.candidate,
208
+ iterations,
209
+ terminationReason,
210
+ finalScore: finalEntry.score,
211
+ };
212
+ }