@spendgraph/graph 0.5.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 (82) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +25 -134
  3. package/dist/compile/ceiling.d.ts +3 -0
  4. package/dist/compile/ceiling.js +1 -0
  5. package/dist/compile/compile.d.ts +6 -15
  6. package/dist/compile/compile.js +1 -17
  7. package/dist/compile/covered.d.ts +3 -0
  8. package/dist/compile/covered.js +1 -0
  9. package/dist/compile/edges.d.ts +5 -0
  10. package/dist/compile/edges.js +1 -0
  11. package/dist/compile/errors.d.ts +14 -0
  12. package/dist/compile/errors.js +1 -0
  13. package/dist/compile/index.d.ts +2 -0
  14. package/dist/compile/index.js +1 -1
  15. package/dist/compile/nodes.d.ts +4 -0
  16. package/dist/compile/nodes.js +1 -0
  17. package/dist/compile/reachable.d.ts +9 -0
  18. package/dist/compile/reachable.js +1 -0
  19. package/dist/execute/context.d.ts +4 -0
  20. package/dist/execute/context.js +1 -0
  21. package/dist/execute/errors.d.ts +6 -0
  22. package/dist/execute/errors.js +1 -0
  23. package/dist/execute/index.d.ts +3 -3
  24. package/dist/execute/index.js +1 -2
  25. package/dist/execute/outcome.d.ts +5 -30
  26. package/dist/execute/outcome.js +1 -44
  27. package/dist/execute/resume.d.ts +16 -0
  28. package/dist/execute/resume.js +1 -0
  29. package/dist/execute/run.d.ts +33 -0
  30. package/dist/execute/run.js +1 -0
  31. package/dist/execute/steps.d.ts +7 -0
  32. package/dist/execute/steps.js +1 -0
  33. package/dist/execute/visit.d.ts +10 -0
  34. package/dist/execute/visit.js +1 -0
  35. package/dist/execute/walk.d.ts +4 -0
  36. package/dist/execute/walk.js +1 -0
  37. package/dist/index.d.ts +5 -3
  38. package/dist/index.js +1 -2
  39. package/dist/node/edge.d.ts +1 -6
  40. package/dist/node/edge.js +1 -6
  41. package/dist/node/index.js +1 -2
  42. package/dist/node/node.d.ts +1 -7
  43. package/dist/node/node.js +1 -25
  44. package/dist/stream/events.d.ts +22 -0
  45. package/dist/stream/events.js +1 -0
  46. package/dist/stream/index.d.ts +2 -0
  47. package/dist/stream/index.js +1 -0
  48. package/dist/stream/stream.d.ts +9 -0
  49. package/dist/stream/stream.js +1 -0
  50. package/dist/types/args.d.ts +2 -15
  51. package/dist/types/args.js +0 -1
  52. package/dist/types/context.d.ts +39 -14
  53. package/dist/types/context.js +0 -1
  54. package/dist/types/edge.d.ts +1 -4
  55. package/dist/types/edge.js +0 -1
  56. package/dist/types/event.d.ts +17 -7
  57. package/dist/types/event.js +0 -1
  58. package/dist/types/index.d.ts +3 -2
  59. package/dist/types/index.js +1 -1
  60. package/dist/types/node.d.ts +2 -10
  61. package/dist/types/node.js +0 -1
  62. package/dist/types/result.d.ts +15 -6
  63. package/dist/types/result.js +0 -1
  64. package/dist/types/spec.d.ts +14 -5
  65. package/dist/types/spec.js +0 -1
  66. package/dist/types/wait.d.ts +24 -0
  67. package/dist/types/wait.js +1 -0
  68. package/docs/nodes.mdx +59 -0
  69. package/docs/overview.mdx +96 -0
  70. package/docs/pausing.mdx +109 -0
  71. package/docs/running.mdx +71 -0
  72. package/docs/streaming.mdx +62 -0
  73. package/docs/wiring.mdx +76 -0
  74. package/package.json +11 -8
  75. package/dist/compile/validate.d.ts +0 -17
  76. package/dist/compile/validate.js +0 -51
  77. package/dist/execute/execute.d.ts +0 -16
  78. package/dist/execute/execute.js +0 -92
  79. package/dist/execute/step.d.ts +0 -5
  80. package/dist/execute/step.js +0 -19
  81. package/dist/execute/stream.d.ts +0 -19
  82. package/dist/execute/stream.js +0 -49
@@ -1,92 +0,0 @@
1
- import { FieldValidationError, validateFields } from "@spendgraph/sdk";
2
- import { nestedSteps, outputOf, tokensOf, totalTokens } from "./outcome.js";
3
- import { failedStep, message } from "./step.js";
4
- function ended(node, index, status, latencyMs, output, error) {
5
- return { type: "node_end", node, index, status, output, error, latencyMs };
6
- }
7
- export async function executeGraph(byName, edgesFrom, entry, maxSteps, values, now, sink = () => { }) {
8
- const startedAt = now();
9
- const steps = [];
10
- const outputs = {};
11
- const context = (node) => ({
12
- values,
13
- outputs,
14
- steps: [...steps],
15
- emit: (text) => sink({ type: "token", node, text }),
16
- });
17
- const finish = (status, error) => ({
18
- status,
19
- output: status === "completed" ? (steps.at(-1)?.output ?? "") : "",
20
- error,
21
- steps,
22
- outputs,
23
- latencyMs: now() - startedAt,
24
- ...totalTokens(steps),
25
- });
26
- let current = entry;
27
- while (current) {
28
- if (steps.length >= maxSteps) {
29
- return finish("failed", `Ran ${maxSteps} steps without reaching an end, stopping at "${current}". ` +
30
- `Either a conditional edge never turns false, or maxSteps is too low for this graph.`);
31
- }
32
- const node = byName.get(current);
33
- const startedNode = now();
34
- const ctx = context(current);
35
- const index = steps.length;
36
- let input;
37
- try {
38
- input = node.input ? node.input(ctx) : values;
39
- }
40
- catch (err) {
41
- steps.push(failedStep(index, node.name, {}, now() - startedNode, message(err)));
42
- sink(ended(node.name, index, "failed", now() - startedNode, undefined, message(err)));
43
- return finish("failed", `Building the input for "${node.name}" threw: ${message(err)}`);
44
- }
45
- sink({ type: "node_start", node: node.name, index, input });
46
- if (node.args?.length) {
47
- const errors = validateFields(input, node.args);
48
- if (errors.length > 0) {
49
- const detail = new FieldValidationError(errors).message;
50
- steps.push(failedStep(index, node.name, input, now() - startedNode, detail));
51
- sink(ended(node.name, index, "failed", now() - startedNode, undefined, detail));
52
- return finish("failed", `"${node.name}" was given ${detail}`);
53
- }
54
- }
55
- let value;
56
- try {
57
- value = await node.run(input, ctx);
58
- }
59
- catch (err) {
60
- steps.push(failedStep(index, node.name, input, now() - startedNode, message(err)));
61
- sink(ended(node.name, index, "failed", now() - startedNode, undefined, message(err)));
62
- return finish("failed", `"${node.name}" failed: ${message(err)}`);
63
- }
64
- outputs[node.name] = value;
65
- steps.push({
66
- index,
67
- source: node.name,
68
- input,
69
- output: outputOf(value),
70
- status: "completed",
71
- latencyMs: now() - startedNode,
72
- ...tokensOf(value),
73
- });
74
- steps.push(...nestedSteps(value, steps.length, node.name));
75
- sink(ended(node.name, index, "completed", now() - startedNode, value));
76
- let next = null;
77
- try {
78
- const after = context(node.name);
79
- for (const e of edgesFrom.get(node.name) ?? []) {
80
- if (e.when && !e.when(after))
81
- continue;
82
- next = e.to;
83
- break;
84
- }
85
- }
86
- catch (err) {
87
- return finish("failed", `Choosing what runs after "${node.name}" threw: ${message(err)}`);
88
- }
89
- current = next;
90
- }
91
- return finish("completed");
92
- }
@@ -1,5 +0,0 @@
1
- import type { RolloutStep } from "@spendgraph/sdk";
2
- /** Same convention as a tool result: a string is itself, anything else is JSON. */
3
- export declare function stringify(value: unknown): string;
4
- export declare function failedStep(index: number, source: string, input: Record<string, unknown>, latencyMs: number, error: string): RolloutStep;
5
- export declare function message(err: unknown): string;
@@ -1,19 +0,0 @@
1
- export function stringify(value) {
2
- if (value === undefined || value === null)
3
- return "";
4
- return typeof value === "string" ? value : JSON.stringify(value);
5
- }
6
- export function failedStep(index, source, input, latencyMs, error) {
7
- return {
8
- index,
9
- source,
10
- input,
11
- output: "",
12
- status: "failed",
13
- error,
14
- latencyMs,
15
- };
16
- }
17
- export function message(err) {
18
- return err instanceof Error ? err.message : String(err);
19
- }
@@ -1,19 +0,0 @@
1
- import type { Edge, GraphEvent, GraphResult, Node } from "../types/index.js";
2
- /** A run as it happens, and the same run once it is over. */
3
- export interface GraphStream extends AsyncIterable<GraphEvent> {
4
- /**
5
- * The finished run.
6
- *
7
- * Resolves whether or not anyone iterated, so a caller can pipe the events to
8
- * a client and still record the rollout from the same run.
9
- */
10
- result: Promise<GraphResult>;
11
- }
12
- /**
13
- * Runs a compiled graph, narrating it as it goes.
14
- *
15
- * The run starts immediately rather than on the first read: a caller who only
16
- * wants the result should not have to iterate to get one, and a client that
17
- * connects late should see what already happened.
18
- */
19
- export declare function streamGraph(byName: Map<string, Node<never>>, edgesFrom: Map<string, Edge[]>, entry: string, maxSteps: number, values: Record<string, unknown>, now: () => number): GraphStream;
@@ -1,49 +0,0 @@
1
- import { executeGraph } from "./execute.js";
2
- class Events {
3
- waiting = [];
4
- wake = null;
5
- closed = false;
6
- push(event) {
7
- this.waiting.push(event);
8
- this.release();
9
- }
10
- close() {
11
- this.closed = true;
12
- this.release();
13
- }
14
- release() {
15
- const wake = this.wake;
16
- this.wake = null;
17
- wake?.();
18
- }
19
- async *drain() {
20
- while (true) {
21
- while (this.waiting.length > 0) {
22
- yield this.waiting.shift();
23
- }
24
- if (this.closed)
25
- return;
26
- await new Promise((resolve) => {
27
- this.wake = resolve;
28
- });
29
- }
30
- }
31
- }
32
- export function streamGraph(byName, edgesFrom, entry, maxSteps, values, now) {
33
- const events = new Events();
34
- const result = (async () => {
35
- try {
36
- const finished = await executeGraph(byName, edgesFrom, entry, maxSteps, values, now, (e) => events.push(e));
37
- events.push({ type: "result", result: finished });
38
- return finished;
39
- }
40
- finally {
41
- events.close();
42
- }
43
- })();
44
- void result.catch(() => { });
45
- return {
46
- result,
47
- [Symbol.asyncIterator]: () => events.drain(),
48
- };
49
- }