@graphorin/agent 0.5.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 (72) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/LICENSE +21 -0
  3. package/README.md +159 -0
  4. package/dist/errors/index.d.ts +170 -0
  5. package/dist/errors/index.d.ts.map +1 -0
  6. package/dist/errors/index.js +204 -0
  7. package/dist/errors/index.js.map +1 -0
  8. package/dist/evaluator-optimizer/index.d.ts +91 -0
  9. package/dist/evaluator-optimizer/index.d.ts.map +1 -0
  10. package/dist/evaluator-optimizer/index.js +85 -0
  11. package/dist/evaluator-optimizer/index.js.map +1 -0
  12. package/dist/factory.d.ts +13 -0
  13. package/dist/factory.d.ts.map +1 -0
  14. package/dist/factory.js +1853 -0
  15. package/dist/factory.js.map +1 -0
  16. package/dist/fallback/index.d.ts +52 -0
  17. package/dist/fallback/index.d.ts.map +1 -0
  18. package/dist/fallback/index.js +53 -0
  19. package/dist/fallback/index.js.map +1 -0
  20. package/dist/fanout/index.d.ts +142 -0
  21. package/dist/fanout/index.d.ts.map +1 -0
  22. package/dist/fanout/index.js +252 -0
  23. package/dist/fanout/index.js.map +1 -0
  24. package/dist/filters/index.d.ts +137 -0
  25. package/dist/filters/index.d.ts.map +1 -0
  26. package/dist/filters/index.js +273 -0
  27. package/dist/filters/index.js.map +1 -0
  28. package/dist/index.d.ts +51 -0
  29. package/dist/index.d.ts.map +1 -0
  30. package/dist/index.js +49 -0
  31. package/dist/index.js.map +1 -0
  32. package/dist/internal/ids.js +46 -0
  33. package/dist/internal/ids.js.map +1 -0
  34. package/dist/internal/usage-accumulator.js +62 -0
  35. package/dist/internal/usage-accumulator.js.map +1 -0
  36. package/dist/lateral-leak/causality-monitor.d.ts +97 -0
  37. package/dist/lateral-leak/causality-monitor.d.ts.map +1 -0
  38. package/dist/lateral-leak/causality-monitor.js +139 -0
  39. package/dist/lateral-leak/causality-monitor.js.map +1 -0
  40. package/dist/lateral-leak/index.d.ts +4 -0
  41. package/dist/lateral-leak/index.js +5 -0
  42. package/dist/lateral-leak/merge-guard.d.ts +89 -0
  43. package/dist/lateral-leak/merge-guard.d.ts.map +1 -0
  44. package/dist/lateral-leak/merge-guard.js +65 -0
  45. package/dist/lateral-leak/merge-guard.js.map +1 -0
  46. package/dist/lateral-leak/protocol-guard.d.ts +76 -0
  47. package/dist/lateral-leak/protocol-guard.d.ts.map +1 -0
  48. package/dist/lateral-leak/protocol-guard.js +147 -0
  49. package/dist/lateral-leak/protocol-guard.js.map +1 -0
  50. package/dist/preferred-model/index.d.ts +53 -0
  51. package/dist/preferred-model/index.d.ts.map +1 -0
  52. package/dist/preferred-model/index.js +141 -0
  53. package/dist/preferred-model/index.js.map +1 -0
  54. package/dist/progress/index.d.ts +62 -0
  55. package/dist/progress/index.d.ts.map +1 -0
  56. package/dist/progress/index.js +150 -0
  57. package/dist/progress/index.js.map +1 -0
  58. package/dist/run-state/index.d.ts +152 -0
  59. package/dist/run-state/index.d.ts.map +1 -0
  60. package/dist/run-state/index.js +311 -0
  61. package/dist/run-state/index.js.map +1 -0
  62. package/dist/tooling/adapters.js +154 -0
  63. package/dist/tooling/adapters.js.map +1 -0
  64. package/dist/tooling/catalogue.js +37 -0
  65. package/dist/tooling/catalogue.js.map +1 -0
  66. package/dist/tooling/dataflow.js +99 -0
  67. package/dist/tooling/dataflow.js.map +1 -0
  68. package/dist/tooling/registry-build.js +85 -0
  69. package/dist/tooling/registry-build.js.map +1 -0
  70. package/dist/types.d.ts +413 -0
  71. package/dist/types.d.ts.map +1 -0
  72. package/package.json +115 -0
@@ -0,0 +1,91 @@
1
+ import { AgentEvent } from "@graphorin/core";
2
+
3
+ //#region src/evaluator-optimizer/index.d.ts
4
+
5
+ /**
6
+ * Rubric discriminator. Pick the variant that matches your
7
+ * Evaluator's contract.
8
+ *
9
+ * @stable
10
+ */
11
+ type Rubric = {
12
+ readonly kind: 'free-form';
13
+ readonly instructions: string;
14
+ } | {
15
+ readonly kind: 'zod';
16
+ readonly instructions: string;
17
+ } | {
18
+ readonly kind: 'llm-judge';
19
+ readonly promptTemplate: string;
20
+ };
21
+ /**
22
+ * Per-iteration evaluation outcome returned by the Evaluator.
23
+ *
24
+ * @stable
25
+ */
26
+ interface EvaluatorOutcome {
27
+ readonly score: number;
28
+ readonly pass: boolean;
29
+ readonly critique: string;
30
+ }
31
+ /**
32
+ * Generator callable shape. Receives the original user input plus
33
+ * the previous iteration's critique (or `undefined` on the first
34
+ * iteration) and returns the new candidate output.
35
+ *
36
+ * @stable
37
+ */
38
+ type GeneratorCallable<TOutput> = (input: string, priorCritique: string | undefined, iteration: number) => Promise<TOutput>;
39
+ /**
40
+ * Evaluator callable shape. Receives the original user input + the
41
+ * candidate output and returns the structured outcome.
42
+ *
43
+ * @stable
44
+ */
45
+ type EvaluatorCallable<TOutput> = (input: string, candidate: TOutput, rubric: Rubric, iteration: number) => Promise<EvaluatorOutcome>;
46
+ /**
47
+ * Options accepted by {@link evaluatorOptimizer}. `maxIterations`
48
+ * is REQUIRED — the helper asserts `>= 1` at construction time.
49
+ *
50
+ * @stable
51
+ */
52
+ interface EvaluatorOptimizerOptions<TOutput> {
53
+ readonly generator: GeneratorCallable<TOutput>;
54
+ readonly evaluator: EvaluatorCallable<TOutput>;
55
+ readonly maxIterations: number;
56
+ readonly rubric: Rubric;
57
+ readonly mergeStrategy?: 'last-iteration' | 'best-score';
58
+ readonly signal?: AbortSignal;
59
+ /** Optional event emitter for `agent.evaluator.iteration / converged`. */
60
+ readonly emit?: (event: AgentEvent) => void;
61
+ readonly runId: string;
62
+ readonly sessionId: string;
63
+ readonly agentId: string;
64
+ }
65
+ /**
66
+ * Aggregate outcome of an `evaluatorOptimizer({...})` run.
67
+ *
68
+ * @stable
69
+ */
70
+ interface EvaluatorOptimizerOutcome<TOutput> {
71
+ readonly output: TOutput;
72
+ readonly iterations: ReadonlyArray<{
73
+ readonly iteration: number;
74
+ readonly candidate: TOutput;
75
+ readonly score: number;
76
+ readonly pass: boolean;
77
+ readonly critique: string;
78
+ readonly durationMs: number;
79
+ }>;
80
+ readonly terminationReason: 'pass' | 'maxIterations' | 'generator-exhausted' | 'cancelled';
81
+ readonly finalScore: number;
82
+ }
83
+ /**
84
+ * Run the Generator → Evaluator iteration loop.
85
+ *
86
+ * @stable
87
+ */
88
+ declare function evaluatorOptimizer<TOutput>(input: string, options: EvaluatorOptimizerOptions<TOutput>): Promise<EvaluatorOptimizerOutcome<TOutput>>;
89
+ //#endregion
90
+ export { EvaluatorCallable, EvaluatorOptimizerOptions, EvaluatorOptimizerOutcome, EvaluatorOutcome, GeneratorCallable, Rubric, evaluatorOptimizer };
91
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../../src/evaluator-optimizer/index.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;AA+EoC,KAxDxB,MAAA,GAwDwB;EAWnB,SAAA,IAAA,EAAA,WAAA;EACE,SAAA,YAAA,EAAA,MAAA;CAGK,GAAA;EAFD,SAAA,IAAA,EAAA,KAAA;EAAa,SAAA,YAAA,EAAA,MAAA;AAiBpC,CAAA,GAAsB;EAEe,SAAA,IAAA,EAAA,WAAA;EAA1B,SAAA,cAAA,EAAA,MAAA;CAC0B;;;;;;UA/EpB,gBAAA;;;;;;;;;;;;KAaL,sGAIP,QAAQ;;;;;;;KAQD,wDAEC,iBACH,8BAEL,QAAQ;;;;;;;UAQI;sBACK,kBAAkB;sBAClB,kBAAkB;;mBAErB;;oBAEC;;0BAEM;;;;;;;;;;UAWT;mBACE;uBACI;;wBAEC;;;;;;;;;;;;;;iBAeF,oDAEX,0BAA0B,WAClC,QAAQ,0BAA0B"}
@@ -0,0 +1,85 @@
1
+ import { EvaluatorOptimizerConfigError } from "../errors/index.js";
2
+
3
+ //#region src/evaluator-optimizer/index.ts
4
+ /**
5
+ * Run the Generator → Evaluator iteration loop.
6
+ *
7
+ * @stable
8
+ */
9
+ async function evaluatorOptimizer(input, options) {
10
+ if (!Number.isFinite(options.maxIterations) || options.maxIterations < 1) throw new EvaluatorOptimizerConfigError(`'maxIterations' must be >= 1 (got ${String(options.maxIterations)})`);
11
+ const mergeStrategy = options.mergeStrategy ?? "last-iteration";
12
+ const iterations = [];
13
+ let priorCritique;
14
+ let terminationReason = "maxIterations";
15
+ for (let i = 1; i <= options.maxIterations; i++) {
16
+ if (options.signal?.aborted) {
17
+ terminationReason = "cancelled";
18
+ break;
19
+ }
20
+ const iterStart = Date.now();
21
+ let candidate;
22
+ try {
23
+ candidate = await options.generator(input, priorCritique, i);
24
+ } catch {
25
+ terminationReason = "generator-exhausted";
26
+ break;
27
+ }
28
+ const outcome = await options.evaluator(input, candidate, options.rubric, i);
29
+ const iterDuration = Date.now() - iterStart;
30
+ iterations.push({
31
+ iteration: i,
32
+ candidate,
33
+ score: outcome.score,
34
+ pass: outcome.pass,
35
+ critique: outcome.critique,
36
+ durationMs: iterDuration
37
+ });
38
+ options.emit?.({
39
+ type: "agent.evaluator.iteration",
40
+ runId: options.runId,
41
+ sessionId: options.sessionId,
42
+ agentId: options.agentId,
43
+ iteration: i,
44
+ score: outcome.score,
45
+ pass: outcome.pass,
46
+ critique: outcome.critique,
47
+ durationMs: iterDuration
48
+ });
49
+ if (outcome.pass) {
50
+ terminationReason = "pass";
51
+ break;
52
+ }
53
+ priorCritique = outcome.critique;
54
+ }
55
+ let finalEntry;
56
+ if (iterations.length === 0) finalEntry = {
57
+ iteration: 0,
58
+ candidate: "",
59
+ score: 0,
60
+ pass: false,
61
+ critique: "",
62
+ durationMs: 0
63
+ };
64
+ else if (mergeStrategy === "best-score") finalEntry = iterations.reduce((best, current) => current.score > best.score ? current : best);
65
+ else finalEntry = iterations[iterations.length - 1];
66
+ options.emit?.({
67
+ type: "agent.evaluator.converged",
68
+ runId: options.runId,
69
+ sessionId: options.sessionId,
70
+ agentId: options.agentId,
71
+ totalIterations: iterations.length,
72
+ finalScore: finalEntry.score,
73
+ terminationReason
74
+ });
75
+ return {
76
+ output: finalEntry.candidate,
77
+ iterations,
78
+ terminationReason,
79
+ finalScore: finalEntry.score
80
+ };
81
+ }
82
+
83
+ //#endregion
84
+ export { evaluatorOptimizer };
85
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","names":["iterations: Array<{\n iteration: number;\n candidate: TOutput;\n score: number;\n pass: boolean;\n critique: string;\n durationMs: number;\n }>","priorCritique: string | undefined","terminationReason: EvaluatorOptimizerOutcome<TOutput>['terminationReason']","candidate: TOutput","finalEntry: (typeof iterations)[number]"],"sources":["../../src/evaluator-optimizer/index.ts"],"sourcesContent":["/**\n * `evaluatorOptimizer({...})` — Generator → Evaluator iteration\n * loop with three rubric kinds and a REQUIRED iteration cap.\n *\n * Iteration boundary discipline: each iteration is a fresh\n * agent.run-equivalent boundary. Intra-loop reasoning per RB-42 /\n * suggested DEC-158 applies WITHIN one iteration, not ACROSS\n * iterations. The Generator's iteration-N input is the original\n * user input + the Evaluator's iteration-(N-1) critique (NOT the\n * Generator's iteration-(N-1) internal message history).\n *\n * @packageDocumentation\n */\n\nimport type { AgentEvent } from '@graphorin/core';\nimport { EvaluatorOptimizerConfigError } from '../errors/index.js';\n\n/**\n * Rubric discriminator. Pick the variant that matches your\n * Evaluator's contract.\n *\n * @stable\n */\nexport type Rubric =\n | { readonly kind: 'free-form'; readonly instructions: string }\n | { readonly kind: 'zod'; readonly instructions: string }\n | { readonly kind: 'llm-judge'; readonly promptTemplate: string };\n\n/**\n * Per-iteration evaluation outcome returned by the Evaluator.\n *\n * @stable\n */\nexport interface EvaluatorOutcome {\n readonly score: number;\n readonly pass: boolean;\n readonly critique: string;\n}\n\n/**\n * Generator callable shape. Receives the original user input plus\n * the previous iteration's critique (or `undefined` on the first\n * iteration) and returns the new candidate output.\n *\n * @stable\n */\nexport type GeneratorCallable<TOutput> = (\n input: string,\n priorCritique: string | undefined,\n iteration: number,\n) => Promise<TOutput>;\n\n/**\n * Evaluator callable shape. Receives the original user input + the\n * candidate output and returns the structured outcome.\n *\n * @stable\n */\nexport type EvaluatorCallable<TOutput> = (\n input: string,\n candidate: TOutput,\n rubric: Rubric,\n iteration: number,\n) => Promise<EvaluatorOutcome>;\n\n/**\n * Options accepted by {@link evaluatorOptimizer}. `maxIterations`\n * is REQUIRED — the helper asserts `>= 1` at construction time.\n *\n * @stable\n */\nexport interface EvaluatorOptimizerOptions<TOutput> {\n readonly generator: GeneratorCallable<TOutput>;\n readonly evaluator: EvaluatorCallable<TOutput>;\n readonly maxIterations: number;\n readonly rubric: Rubric;\n readonly mergeStrategy?: 'last-iteration' | 'best-score';\n readonly signal?: AbortSignal;\n /** Optional event emitter for `agent.evaluator.iteration / converged`. */\n readonly emit?: (event: AgentEvent) => void;\n readonly runId: string;\n readonly sessionId: string;\n readonly agentId: string;\n}\n\n/**\n * Aggregate outcome of an `evaluatorOptimizer({...})` run.\n *\n * @stable\n */\nexport interface EvaluatorOptimizerOutcome<TOutput> {\n readonly output: TOutput;\n readonly iterations: ReadonlyArray<{\n readonly iteration: number;\n readonly candidate: TOutput;\n readonly score: number;\n readonly pass: boolean;\n readonly critique: string;\n readonly durationMs: number;\n }>;\n readonly terminationReason: 'pass' | 'maxIterations' | 'generator-exhausted' | 'cancelled';\n readonly finalScore: number;\n}\n\n/**\n * Run the Generator → Evaluator iteration loop.\n *\n * @stable\n */\nexport async function evaluatorOptimizer<TOutput>(\n input: string,\n options: EvaluatorOptimizerOptions<TOutput>,\n): Promise<EvaluatorOptimizerOutcome<TOutput>> {\n if (!Number.isFinite(options.maxIterations) || options.maxIterations < 1) {\n throw new EvaluatorOptimizerConfigError(\n `'maxIterations' must be >= 1 (got ${String(options.maxIterations)})`,\n );\n }\n const mergeStrategy = options.mergeStrategy ?? 'last-iteration';\n const iterations: Array<{\n iteration: number;\n candidate: TOutput;\n score: number;\n pass: boolean;\n critique: string;\n durationMs: number;\n }> = [];\n\n let priorCritique: string | undefined;\n let terminationReason: EvaluatorOptimizerOutcome<TOutput>['terminationReason'] = 'maxIterations';\n\n for (let i = 1; i <= options.maxIterations; i++) {\n if (options.signal?.aborted) {\n terminationReason = 'cancelled';\n break;\n }\n const iterStart = Date.now();\n let candidate: TOutput;\n try {\n candidate = await options.generator(input, priorCritique, i);\n } catch {\n terminationReason = 'generator-exhausted';\n break;\n }\n const outcome = await options.evaluator(input, candidate, options.rubric, i);\n const iterDuration = Date.now() - iterStart;\n\n iterations.push({\n iteration: i,\n candidate,\n score: outcome.score,\n pass: outcome.pass,\n critique: outcome.critique,\n durationMs: iterDuration,\n });\n\n options.emit?.({\n type: 'agent.evaluator.iteration',\n runId: options.runId,\n sessionId: options.sessionId,\n agentId: options.agentId,\n iteration: i,\n score: outcome.score,\n pass: outcome.pass,\n critique: outcome.critique,\n durationMs: iterDuration,\n });\n\n if (outcome.pass) {\n terminationReason = 'pass';\n break;\n }\n priorCritique = outcome.critique;\n }\n\n let finalEntry: (typeof iterations)[number];\n if (iterations.length === 0) {\n // Should only happen on `cancelled` before the first iteration —\n // synthesize a no-op final entry.\n finalEntry = {\n iteration: 0,\n candidate: '' as unknown as TOutput,\n score: 0,\n pass: false,\n critique: '',\n durationMs: 0,\n };\n } else if (mergeStrategy === 'best-score') {\n finalEntry = iterations.reduce((best, current) =>\n current.score > best.score ? current : best,\n );\n } else {\n finalEntry = iterations[iterations.length - 1] as (typeof iterations)[number];\n }\n\n options.emit?.({\n type: 'agent.evaluator.converged',\n runId: options.runId,\n sessionId: options.sessionId,\n agentId: options.agentId,\n totalIterations: iterations.length,\n finalScore: finalEntry.score,\n terminationReason,\n });\n\n return {\n output: finalEntry.candidate,\n iterations,\n terminationReason,\n finalScore: finalEntry.score,\n };\n}\n"],"mappings":";;;;;;;;AA6GA,eAAsB,mBACpB,OACA,SAC6C;AAC7C,KAAI,CAAC,OAAO,SAAS,QAAQ,cAAc,IAAI,QAAQ,gBAAgB,EACrE,OAAM,IAAI,8BACR,qCAAqC,OAAO,QAAQ,cAAc,CAAC,GACpE;CAEH,MAAM,gBAAgB,QAAQ,iBAAiB;CAC/C,MAAMA,aAOD,EAAE;CAEP,IAAIC;CACJ,IAAIC,oBAA6E;AAEjF,MAAK,IAAI,IAAI,GAAG,KAAK,QAAQ,eAAe,KAAK;AAC/C,MAAI,QAAQ,QAAQ,SAAS;AAC3B,uBAAoB;AACpB;;EAEF,MAAM,YAAY,KAAK,KAAK;EAC5B,IAAIC;AACJ,MAAI;AACF,eAAY,MAAM,QAAQ,UAAU,OAAO,eAAe,EAAE;UACtD;AACN,uBAAoB;AACpB;;EAEF,MAAM,UAAU,MAAM,QAAQ,UAAU,OAAO,WAAW,QAAQ,QAAQ,EAAE;EAC5E,MAAM,eAAe,KAAK,KAAK,GAAG;AAElC,aAAW,KAAK;GACd,WAAW;GACX;GACA,OAAO,QAAQ;GACf,MAAM,QAAQ;GACd,UAAU,QAAQ;GAClB,YAAY;GACb,CAAC;AAEF,UAAQ,OAAO;GACb,MAAM;GACN,OAAO,QAAQ;GACf,WAAW,QAAQ;GACnB,SAAS,QAAQ;GACjB,WAAW;GACX,OAAO,QAAQ;GACf,MAAM,QAAQ;GACd,UAAU,QAAQ;GAClB,YAAY;GACb,CAAC;AAEF,MAAI,QAAQ,MAAM;AAChB,uBAAoB;AACpB;;AAEF,kBAAgB,QAAQ;;CAG1B,IAAIC;AACJ,KAAI,WAAW,WAAW,EAGxB,cAAa;EACX,WAAW;EACX,WAAW;EACX,OAAO;EACP,MAAM;EACN,UAAU;EACV,YAAY;EACb;UACQ,kBAAkB,aAC3B,cAAa,WAAW,QAAQ,MAAM,YACpC,QAAQ,QAAQ,KAAK,QAAQ,UAAU,KACxC;KAED,cAAa,WAAW,WAAW,SAAS;AAG9C,SAAQ,OAAO;EACb,MAAM;EACN,OAAO,QAAQ;EACf,WAAW,QAAQ;EACnB,SAAS,QAAQ;EACjB,iBAAiB,WAAW;EAC5B,YAAY,WAAW;EACvB;EACD,CAAC;AAEF,QAAO;EACL,QAAQ,WAAW;EACnB;EACA;EACA,YAAY,WAAW;EACxB"}
@@ -0,0 +1,13 @@
1
+ import { Agent, AgentConfig } from "./types.js";
2
+
3
+ //#region src/factory.d.ts
4
+
5
+ /**
6
+ * Build a fresh {@link Agent} from the supplied configuration.
7
+ *
8
+ * @stable
9
+ */
10
+ declare function createAgent<TDeps = unknown, TOutput = string>(config: AgentConfig<TDeps, TOutput>): Agent<TDeps, TOutput>;
11
+ //#endregion
12
+ export { createAgent };
13
+ //# sourceMappingURL=factory.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"factory.d.ts","names":[],"sources":["../src/factory.ts"],"sourcesContent":[],"mappings":";;;;;;;;;iBAovBgB,uDACN,YAAY,OAAO,WAC1B,MAAM,OAAO"}