graph-mode 0.1.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.
- package/LICENSE +21 -0
- package/README.md +158 -0
- package/dist/core.d.ts +37 -0
- package/dist/core.d.ts.map +1 -0
- package/dist/core.js +125 -0
- package/dist/core.js.map +1 -0
- package/dist/index.d.ts +49 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +50 -0
- package/dist/index.js.map +1 -0
- package/dist/logger.d.ts +48 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +39 -0
- package/dist/logger.js.map +1 -0
- package/dist/loggers/bun-sqlite.d.ts +51 -0
- package/dist/loggers/bun-sqlite.d.ts.map +1 -0
- package/dist/loggers/bun-sqlite.js +110 -0
- package/dist/loggers/bun-sqlite.js.map +1 -0
- package/dist/utils.d.ts +3 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/utils.js +29 -0
- package/dist/utils.js.map +1 -0
- package/package.json +61 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
# graph-mode
|
|
2
|
+
|
|
3
|
+
A graph-based workflow execution framework for TypeScript. Define nodes with execution and routing logic, then let GraphRunner orchestrate the flow.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install graph-mode
|
|
9
|
+
# or
|
|
10
|
+
bun add graph-mode
|
|
11
|
+
# or
|
|
12
|
+
yarn add graph-mode
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Quick Start
|
|
16
|
+
|
|
17
|
+
```typescript
|
|
18
|
+
import { GraphNode, GraphRunner } from 'graph-mode';
|
|
19
|
+
|
|
20
|
+
// Define your node types
|
|
21
|
+
enum Nodes {
|
|
22
|
+
START = 'START',
|
|
23
|
+
PROCESS = 'PROCESS',
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// Create nodes with exec and routing functions
|
|
27
|
+
const startNode = new GraphNode({
|
|
28
|
+
nodeType: Nodes.START,
|
|
29
|
+
description: 'Initial node that prepares data',
|
|
30
|
+
exec: (input: { data: string }) => ({ ...input, started: true }),
|
|
31
|
+
routing: () => Nodes.PROCESS, // Route to PROCESS node
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
const processNode = new GraphNode({
|
|
35
|
+
nodeType: Nodes.PROCESS,
|
|
36
|
+
description: 'Process the data',
|
|
37
|
+
exec: (input) => ({ ...input, processed: true }),
|
|
38
|
+
routing: () => null, // End of graph (return null to stop)
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
// Create and run the graph
|
|
42
|
+
const runner = new GraphRunner({
|
|
43
|
+
graphName: 'my-workflow',
|
|
44
|
+
nodes: [startNode, processNode],
|
|
45
|
+
startNode: Nodes.START,
|
|
46
|
+
input: { data: 'hello' },
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
const result = await runner.run();
|
|
50
|
+
console.log(result); // { data: 'hello', started: true, processed: true }
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Features
|
|
54
|
+
|
|
55
|
+
- **Type-safe**: Full TypeScript support with generics for input/output types
|
|
56
|
+
- **Async support**: Node exec functions can be sync or async
|
|
57
|
+
- **Automatic retry**: Built-in retry with exponential backoff
|
|
58
|
+
- **Pluggable logging**: Optional execution logging with customizable backends
|
|
59
|
+
- **Universal**: Works with Node.js, Bun, and Deno
|
|
60
|
+
|
|
61
|
+
## Logging
|
|
62
|
+
|
|
63
|
+
By default, graph-mode doesn't log executions. You can enable logging by providing a logger:
|
|
64
|
+
|
|
65
|
+
### Console Logger (for debugging)
|
|
66
|
+
|
|
67
|
+
```typescript
|
|
68
|
+
import { GraphRunner, ConsoleLogger } from 'graph-mode';
|
|
69
|
+
|
|
70
|
+
const runner = new GraphRunner({
|
|
71
|
+
graphName: 'my-workflow',
|
|
72
|
+
nodes: [...],
|
|
73
|
+
startNode: 'START',
|
|
74
|
+
input: {},
|
|
75
|
+
logger: new ConsoleLogger(),
|
|
76
|
+
});
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### Bun SQLite Logger (for persistence)
|
|
80
|
+
|
|
81
|
+
If you're using Bun, you can use the built-in SQLite logger:
|
|
82
|
+
|
|
83
|
+
```typescript
|
|
84
|
+
import { GraphRunner } from 'graph-mode';
|
|
85
|
+
import { BunSQLiteLogger } from 'graph-mode/bun';
|
|
86
|
+
import { Database } from 'bun:sqlite';
|
|
87
|
+
|
|
88
|
+
const db = new Database('./executions.db');
|
|
89
|
+
const logger = new BunSQLiteLogger(db);
|
|
90
|
+
|
|
91
|
+
const runner = new GraphRunner({
|
|
92
|
+
graphName: 'my-workflow',
|
|
93
|
+
nodes: [...],
|
|
94
|
+
startNode: 'START',
|
|
95
|
+
input: {},
|
|
96
|
+
logger,
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
await runner.run();
|
|
100
|
+
|
|
101
|
+
// Query execution history
|
|
102
|
+
const runs = logger.getRuns('my-workflow');
|
|
103
|
+
const executions = logger.getExecutions(runs[0]);
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
### Custom Logger
|
|
107
|
+
|
|
108
|
+
Implement the `Logger` interface to create your own logging backend:
|
|
109
|
+
|
|
110
|
+
```typescript
|
|
111
|
+
import { Logger, ExecutionLog } from 'graph-mode';
|
|
112
|
+
|
|
113
|
+
class MyCustomLogger implements Logger {
|
|
114
|
+
registerGraph(graphName: string): string {
|
|
115
|
+
// Register graph and return a unique ID
|
|
116
|
+
return crypto.randomUUID();
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
logExecution(log: ExecutionLog): void {
|
|
120
|
+
// Log the execution however you want
|
|
121
|
+
console.log(log);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
## API Reference
|
|
127
|
+
|
|
128
|
+
### GraphNode
|
|
129
|
+
|
|
130
|
+
```typescript
|
|
131
|
+
new GraphNode<InputType, OutputType, NodeEnum>({
|
|
132
|
+
nodeType: string, // Unique identifier for this node
|
|
133
|
+
description: string, // Human-readable description
|
|
134
|
+
exec: (input) => output, // Execution function (sync or async)
|
|
135
|
+
routing: (output) => next, // Return next node ID or null to end
|
|
136
|
+
})
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
### GraphRunner
|
|
140
|
+
|
|
141
|
+
```typescript
|
|
142
|
+
new GraphRunner<NodeEnum>({
|
|
143
|
+
graphName: string, // Name for the workflow
|
|
144
|
+
nodes: GraphNode[], // Array of all nodes
|
|
145
|
+
startNode: NodeEnum, // Starting node identifier
|
|
146
|
+
input: any, // Initial input to the graph
|
|
147
|
+
logger?: Logger, // Optional logger (default: NoOpLogger)
|
|
148
|
+
maxExecutions?: number, // Max iterations (default: 100)
|
|
149
|
+
})
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
#### Methods
|
|
153
|
+
|
|
154
|
+
- `run(): Promise<any>` - Execute the graph and return the final output
|
|
155
|
+
|
|
156
|
+
## License
|
|
157
|
+
|
|
158
|
+
MIT
|
package/dist/core.d.ts
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { type Logger } from "./logger.js";
|
|
2
|
+
export declare class GraphNode<InputType, OutputType, NodeEnum> {
|
|
3
|
+
exec: (input: InputType) => OutputType | Promise<OutputType>;
|
|
4
|
+
nodeType: string;
|
|
5
|
+
description: string;
|
|
6
|
+
routing: (output?: OutputType) => NodeEnum | null;
|
|
7
|
+
constructor(params: {
|
|
8
|
+
nodeType: string;
|
|
9
|
+
description: string;
|
|
10
|
+
exec: (input: InputType) => OutputType | Promise<OutputType>;
|
|
11
|
+
routing: (output?: OutputType) => NodeEnum | null;
|
|
12
|
+
});
|
|
13
|
+
}
|
|
14
|
+
export interface GraphRunnerOptions<NodeEnum> {
|
|
15
|
+
graphName: string;
|
|
16
|
+
nodes: GraphNode<any, any, NodeEnum>[];
|
|
17
|
+
startNode: NodeEnum;
|
|
18
|
+
input: any;
|
|
19
|
+
logger?: Logger;
|
|
20
|
+
maxExecutions?: number;
|
|
21
|
+
}
|
|
22
|
+
export declare class GraphRunner<NodeEnum> {
|
|
23
|
+
graphName: string;
|
|
24
|
+
nodes: GraphNode<any, any, NodeEnum>[];
|
|
25
|
+
logger: Logger;
|
|
26
|
+
startNode: NodeEnum;
|
|
27
|
+
input: any;
|
|
28
|
+
maxExecutions: number;
|
|
29
|
+
private nodeMap;
|
|
30
|
+
private graphId;
|
|
31
|
+
constructor(params: GraphRunnerOptions<NodeEnum>);
|
|
32
|
+
private initializeNodeMap;
|
|
33
|
+
private ensureGraphId;
|
|
34
|
+
run(): Promise<any>;
|
|
35
|
+
private executeNode;
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=core.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"core.d.ts","sourceRoot":"","sources":["../src/core.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,MAAM,EAAiC,MAAM,aAAa,CAAC;AAKzE,qBAAa,SAAS,CAAC,SAAS,EAAE,UAAU,EAAE,QAAQ;IACrD,IAAI,EAAE,CAAC,KAAK,EAAE,SAAS,KAAK,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;IAC7D,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,CAAC,MAAM,CAAC,EAAE,UAAU,KAAK,QAAQ,GAAG,IAAI,CAAC;gBAEtC,MAAM,EAAE;QACnB,QAAQ,EAAE,MAAM,CAAC;QACjB,WAAW,EAAE,MAAM,CAAC;QACpB,IAAI,EAAE,CAAC,KAAK,EAAE,SAAS,KAAK,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;QAC7D,OAAO,EAAE,CAAC,MAAM,CAAC,EAAE,UAAU,KAAK,QAAQ,GAAG,IAAI,CAAC;KAClD;CAMD;AAED,MAAM,WAAW,kBAAkB,CAAC,QAAQ;IAC3C,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,SAAS,CAAC,GAAG,EAAE,GAAG,EAAE,QAAQ,CAAC,EAAE,CAAC;IACvC,SAAS,EAAE,QAAQ,CAAC;IACpB,KAAK,EAAE,GAAG,CAAC;IACX,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,aAAa,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,qBAAa,WAAW,CAAC,QAAQ;IAChC,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,SAAS,CAAC,GAAG,EAAE,GAAG,EAAE,QAAQ,CAAC,EAAE,CAAC;IACvC,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,QAAQ,CAAC;IACpB,KAAK,EAAE,GAAG,CAAC;IACX,aAAa,EAAE,MAAM,CAAC;IACtB,OAAO,CAAC,OAAO,CAAsD;IACrE,OAAO,CAAC,OAAO,CAAuB;gBAE1B,MAAM,EAAE,kBAAkB,CAAC,QAAQ,CAAC;IAYhD,OAAO,CAAC,iBAAiB;YAMX,aAAa;IAOrB,GAAG,IAAI,OAAO,CAAC,GAAG,CAAC;YA8CX,WAAW;CA4CzB"}
|
package/dist/core.js
ADDED
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import { NoOpLogger } from "./logger.js";
|
|
2
|
+
import { serializeValue, retry } from "./utils.js";
|
|
3
|
+
const MAX_NODE_EXECUTIONS = 100;
|
|
4
|
+
export class GraphNode {
|
|
5
|
+
exec;
|
|
6
|
+
nodeType;
|
|
7
|
+
description;
|
|
8
|
+
routing;
|
|
9
|
+
constructor(params) {
|
|
10
|
+
this.exec = params.exec;
|
|
11
|
+
this.nodeType = params.nodeType;
|
|
12
|
+
this.description = params.description;
|
|
13
|
+
this.routing = params.routing;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
export class GraphRunner {
|
|
17
|
+
graphName;
|
|
18
|
+
nodes;
|
|
19
|
+
logger;
|
|
20
|
+
startNode;
|
|
21
|
+
input;
|
|
22
|
+
maxExecutions;
|
|
23
|
+
nodeMap;
|
|
24
|
+
graphId = null;
|
|
25
|
+
constructor(params) {
|
|
26
|
+
this.graphName = params.graphName;
|
|
27
|
+
this.nodes = params.nodes;
|
|
28
|
+
this.startNode = params.startNode;
|
|
29
|
+
this.input = params.input;
|
|
30
|
+
this.logger = params.logger ?? new NoOpLogger();
|
|
31
|
+
this.maxExecutions = params.maxExecutions ?? MAX_NODE_EXECUTIONS;
|
|
32
|
+
this.nodeMap = {};
|
|
33
|
+
this.initializeNodeMap();
|
|
34
|
+
}
|
|
35
|
+
initializeNodeMap() {
|
|
36
|
+
for (const node of this.nodes) {
|
|
37
|
+
this.nodeMap[node.nodeType] = node;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
async ensureGraphId() {
|
|
41
|
+
if (!this.graphId) {
|
|
42
|
+
this.graphId = await this.logger.registerGraph(this.graphName);
|
|
43
|
+
}
|
|
44
|
+
return this.graphId;
|
|
45
|
+
}
|
|
46
|
+
async run() {
|
|
47
|
+
const runId = crypto.randomUUID();
|
|
48
|
+
const graphId = await this.ensureGraphId();
|
|
49
|
+
let nextNode = this.nodeMap[String(this.startNode)];
|
|
50
|
+
if (!nextNode)
|
|
51
|
+
return;
|
|
52
|
+
let input = this.input;
|
|
53
|
+
let nextNodeId = null;
|
|
54
|
+
let execution = await this.executeNode(nextNode, input, runId, graphId);
|
|
55
|
+
if (!execution)
|
|
56
|
+
return;
|
|
57
|
+
let output = execution.output;
|
|
58
|
+
nextNodeId = execution.nextNodeId;
|
|
59
|
+
nextNode = nextNodeId ? this.nodeMap[String(nextNodeId)] : null;
|
|
60
|
+
let numExecutions = 1;
|
|
61
|
+
while (nextNode && numExecutions < this.maxExecutions) {
|
|
62
|
+
input = structuredClone(output);
|
|
63
|
+
execution = await this.executeNode(nextNode, input, runId, graphId);
|
|
64
|
+
if (!execution)
|
|
65
|
+
return;
|
|
66
|
+
output = execution.output;
|
|
67
|
+
nextNodeId = execution.nextNodeId;
|
|
68
|
+
nextNode = nextNodeId ? this.nodeMap[String(nextNodeId)] : null;
|
|
69
|
+
numExecutions += 1;
|
|
70
|
+
}
|
|
71
|
+
if (numExecutions === this.maxExecutions) {
|
|
72
|
+
const log = {
|
|
73
|
+
id: crypto.randomUUID(),
|
|
74
|
+
runId,
|
|
75
|
+
graphId,
|
|
76
|
+
nodeType: String(nextNode?.nodeType ?? "UNKNOWN"),
|
|
77
|
+
input: serializeValue(input),
|
|
78
|
+
output: "MAX ITERATIONS reached",
|
|
79
|
+
routed: String(nextNode?.nodeType ?? "UNKNOWN"),
|
|
80
|
+
datetime: new Date().toISOString(),
|
|
81
|
+
success: false,
|
|
82
|
+
};
|
|
83
|
+
await this.logger.logExecution(log);
|
|
84
|
+
}
|
|
85
|
+
return output;
|
|
86
|
+
}
|
|
87
|
+
async executeNode(node, input, runId, graphId) {
|
|
88
|
+
try {
|
|
89
|
+
const { output, nextNodeId } = await retry(async () => {
|
|
90
|
+
const output = await node.exec(input);
|
|
91
|
+
const nextNodeId = node.routing(output);
|
|
92
|
+
const log = {
|
|
93
|
+
id: crypto.randomUUID(),
|
|
94
|
+
runId,
|
|
95
|
+
graphId,
|
|
96
|
+
nodeType: String(node.nodeType),
|
|
97
|
+
input,
|
|
98
|
+
output,
|
|
99
|
+
routed: nextNodeId ? String(nextNodeId) : "END",
|
|
100
|
+
datetime: new Date().toISOString(),
|
|
101
|
+
success: true,
|
|
102
|
+
};
|
|
103
|
+
await this.logger.logExecution(log);
|
|
104
|
+
return { output, nextNodeId };
|
|
105
|
+
}, 1, 1);
|
|
106
|
+
return { output, nextNodeId };
|
|
107
|
+
}
|
|
108
|
+
catch (err) {
|
|
109
|
+
const log = {
|
|
110
|
+
id: crypto.randomUUID(),
|
|
111
|
+
runId,
|
|
112
|
+
graphId,
|
|
113
|
+
nodeType: String(node.nodeType),
|
|
114
|
+
input,
|
|
115
|
+
output: err,
|
|
116
|
+
routed: String(node.nodeType),
|
|
117
|
+
datetime: new Date().toISOString(),
|
|
118
|
+
success: false,
|
|
119
|
+
};
|
|
120
|
+
await this.logger.logExecution(log);
|
|
121
|
+
return null;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
//# sourceMappingURL=core.js.map
|
package/dist/core.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"core.js","sourceRoot":"","sources":["../src/core.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* graph-mode
|
|
3
|
+
*
|
|
4
|
+
* A graph-based workflow execution framework for TypeScript.
|
|
5
|
+
* Define nodes with exec and routing functions, then let GraphRunner
|
|
6
|
+
* orchestrate the execution flow.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```ts
|
|
10
|
+
* import { GraphNode, GraphRunner } from 'graph-mode';
|
|
11
|
+
*
|
|
12
|
+
* enum Nodes {
|
|
13
|
+
* START = 'START',
|
|
14
|
+
* PROCESS = 'PROCESS',
|
|
15
|
+
* END = 'END',
|
|
16
|
+
* }
|
|
17
|
+
*
|
|
18
|
+
* const startNode = new GraphNode({
|
|
19
|
+
* nodeType: Nodes.START,
|
|
20
|
+
* description: 'Initial node',
|
|
21
|
+
* exec: (input) => ({ ...input, started: true }),
|
|
22
|
+
* routing: () => Nodes.PROCESS,
|
|
23
|
+
* });
|
|
24
|
+
*
|
|
25
|
+
* const processNode = new GraphNode({
|
|
26
|
+
* nodeType: Nodes.PROCESS,
|
|
27
|
+
* description: 'Process data',
|
|
28
|
+
* exec: (input) => ({ ...input, processed: true }),
|
|
29
|
+
* routing: () => null, // End of graph
|
|
30
|
+
* });
|
|
31
|
+
*
|
|
32
|
+
* const runner = new GraphRunner({
|
|
33
|
+
* graphName: 'my-workflow',
|
|
34
|
+
* nodes: [startNode, processNode],
|
|
35
|
+
* startNode: Nodes.START,
|
|
36
|
+
* input: { data: 'hello' },
|
|
37
|
+
* });
|
|
38
|
+
*
|
|
39
|
+
* const result = await runner.run();
|
|
40
|
+
* ```
|
|
41
|
+
*
|
|
42
|
+
* @packageDocumentation
|
|
43
|
+
*/
|
|
44
|
+
export { GraphNode, GraphRunner } from "./core.js";
|
|
45
|
+
export type { GraphRunnerOptions } from "./core.js";
|
|
46
|
+
export { NoOpLogger, ConsoleLogger } from "./logger.js";
|
|
47
|
+
export type { Logger, ExecutionLog } from "./logger.js";
|
|
48
|
+
export { retry, serializeValue } from "./utils.js";
|
|
49
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AAGH,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AACnD,YAAY,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAC;AAGpD,OAAO,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACxD,YAAY,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAGxD,OAAO,EAAE,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* graph-mode
|
|
3
|
+
*
|
|
4
|
+
* A graph-based workflow execution framework for TypeScript.
|
|
5
|
+
* Define nodes with exec and routing functions, then let GraphRunner
|
|
6
|
+
* orchestrate the execution flow.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```ts
|
|
10
|
+
* import { GraphNode, GraphRunner } from 'graph-mode';
|
|
11
|
+
*
|
|
12
|
+
* enum Nodes {
|
|
13
|
+
* START = 'START',
|
|
14
|
+
* PROCESS = 'PROCESS',
|
|
15
|
+
* END = 'END',
|
|
16
|
+
* }
|
|
17
|
+
*
|
|
18
|
+
* const startNode = new GraphNode({
|
|
19
|
+
* nodeType: Nodes.START,
|
|
20
|
+
* description: 'Initial node',
|
|
21
|
+
* exec: (input) => ({ ...input, started: true }),
|
|
22
|
+
* routing: () => Nodes.PROCESS,
|
|
23
|
+
* });
|
|
24
|
+
*
|
|
25
|
+
* const processNode = new GraphNode({
|
|
26
|
+
* nodeType: Nodes.PROCESS,
|
|
27
|
+
* description: 'Process data',
|
|
28
|
+
* exec: (input) => ({ ...input, processed: true }),
|
|
29
|
+
* routing: () => null, // End of graph
|
|
30
|
+
* });
|
|
31
|
+
*
|
|
32
|
+
* const runner = new GraphRunner({
|
|
33
|
+
* graphName: 'my-workflow',
|
|
34
|
+
* nodes: [startNode, processNode],
|
|
35
|
+
* startNode: Nodes.START,
|
|
36
|
+
* input: { data: 'hello' },
|
|
37
|
+
* });
|
|
38
|
+
*
|
|
39
|
+
* const result = await runner.run();
|
|
40
|
+
* ```
|
|
41
|
+
*
|
|
42
|
+
* @packageDocumentation
|
|
43
|
+
*/
|
|
44
|
+
// Core exports
|
|
45
|
+
export { GraphNode, GraphRunner } from "./core.js";
|
|
46
|
+
// Logger exports
|
|
47
|
+
export { NoOpLogger, ConsoleLogger } from "./logger.js";
|
|
48
|
+
// Utility exports
|
|
49
|
+
export { retry, serializeValue } from "./utils.js";
|
|
50
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AAEH,eAAe;AACf,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAGnD,iBAAiB;AACjB,OAAO,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAGxD,kBAAkB;AAClB,OAAO,EAAE,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC"}
|
package/dist/logger.d.ts
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Represents a single node execution log entry
|
|
3
|
+
*/
|
|
4
|
+
export interface ExecutionLog {
|
|
5
|
+
id: string;
|
|
6
|
+
runId: string;
|
|
7
|
+
graphId: string;
|
|
8
|
+
nodeType: string;
|
|
9
|
+
input: any;
|
|
10
|
+
output: any;
|
|
11
|
+
routed: string;
|
|
12
|
+
datetime: string;
|
|
13
|
+
success: boolean;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Logger interface for tracking graph executions.
|
|
17
|
+
* Implement this interface to create custom logging backends.
|
|
18
|
+
*/
|
|
19
|
+
export interface Logger {
|
|
20
|
+
/**
|
|
21
|
+
* Register a graph and return its unique identifier.
|
|
22
|
+
* If the graph already exists, return the existing ID.
|
|
23
|
+
*/
|
|
24
|
+
registerGraph(graphName: string): string | Promise<string>;
|
|
25
|
+
/**
|
|
26
|
+
* Log a node execution event.
|
|
27
|
+
*/
|
|
28
|
+
logExecution(log: ExecutionLog): void | Promise<void>;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* A no-op logger that discards all logs.
|
|
32
|
+
* Used as the default when no logger is provided.
|
|
33
|
+
*/
|
|
34
|
+
export declare class NoOpLogger implements Logger {
|
|
35
|
+
private graphIds;
|
|
36
|
+
registerGraph(graphName: string): string;
|
|
37
|
+
logExecution(_log: ExecutionLog): void;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* A simple console logger for debugging.
|
|
41
|
+
* Logs execution events to the console.
|
|
42
|
+
*/
|
|
43
|
+
export declare class ConsoleLogger implements Logger {
|
|
44
|
+
private graphIds;
|
|
45
|
+
registerGraph(graphName: string): string;
|
|
46
|
+
logExecution(log: ExecutionLog): void;
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=logger.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,WAAW,YAAY;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,GAAG,CAAC;IACX,MAAM,EAAE,GAAG,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,OAAO,CAAC;CACjB;AAED;;;GAGG;AACH,MAAM,WAAW,MAAM;IACtB;;;OAGG;IACH,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAE3D;;OAEG;IACH,YAAY,CAAC,GAAG,EAAE,YAAY,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACtD;AAED;;;GAGG;AACH,qBAAa,UAAW,YAAW,MAAM;IACxC,OAAO,CAAC,QAAQ,CAAkC;IAElD,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM;IASxC,YAAY,CAAC,IAAI,EAAE,YAAY,GAAG,IAAI;CAGtC;AAED;;;GAGG;AACH,qBAAa,aAAc,YAAW,MAAM;IAC3C,OAAO,CAAC,QAAQ,CAAkC;IAElD,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM;IAUxC,YAAY,CAAC,GAAG,EAAE,YAAY,GAAG,IAAI;CAMrC"}
|
package/dist/logger.js
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A no-op logger that discards all logs.
|
|
3
|
+
* Used as the default when no logger is provided.
|
|
4
|
+
*/
|
|
5
|
+
export class NoOpLogger {
|
|
6
|
+
graphIds = new Map();
|
|
7
|
+
registerGraph(graphName) {
|
|
8
|
+
let graphId = this.graphIds.get(graphName);
|
|
9
|
+
if (!graphId) {
|
|
10
|
+
graphId = crypto.randomUUID();
|
|
11
|
+
this.graphIds.set(graphName, graphId);
|
|
12
|
+
}
|
|
13
|
+
return graphId;
|
|
14
|
+
}
|
|
15
|
+
logExecution(_log) {
|
|
16
|
+
// No-op: discard the log
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* A simple console logger for debugging.
|
|
21
|
+
* Logs execution events to the console.
|
|
22
|
+
*/
|
|
23
|
+
export class ConsoleLogger {
|
|
24
|
+
graphIds = new Map();
|
|
25
|
+
registerGraph(graphName) {
|
|
26
|
+
let graphId = this.graphIds.get(graphName);
|
|
27
|
+
if (!graphId) {
|
|
28
|
+
graphId = crypto.randomUUID();
|
|
29
|
+
this.graphIds.set(graphName, graphId);
|
|
30
|
+
console.log(`[graph-mode] Registered graph: ${graphName} (${graphId})`);
|
|
31
|
+
}
|
|
32
|
+
return graphId;
|
|
33
|
+
}
|
|
34
|
+
logExecution(log) {
|
|
35
|
+
const status = log.success ? "SUCCESS" : "FAILURE";
|
|
36
|
+
console.log(`[graph-mode] [${status}] ${log.nodeType} -> ${log.routed} | Run: ${log.runId.slice(0, 8)}...`);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=logger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAgCA;;;GAGG;AACH,MAAM,OAAO,UAAU;IACd,QAAQ,GAAwB,IAAI,GAAG,EAAE,CAAC;IAElD,aAAa,CAAC,SAAiB;QAC9B,IAAI,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QAC3C,IAAI,CAAC,OAAO,EAAE,CAAC;YACd,OAAO,GAAG,MAAM,CAAC,UAAU,EAAE,CAAC;YAC9B,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;QACvC,CAAC;QACD,OAAO,OAAO,CAAC;IAChB,CAAC;IAED,YAAY,CAAC,IAAkB;QAC9B,yBAAyB;IAC1B,CAAC;CACD;AAED;;;GAGG;AACH,MAAM,OAAO,aAAa;IACjB,QAAQ,GAAwB,IAAI,GAAG,EAAE,CAAC;IAElD,aAAa,CAAC,SAAiB;QAC9B,IAAI,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QAC3C,IAAI,CAAC,OAAO,EAAE,CAAC;YACd,OAAO,GAAG,MAAM,CAAC,UAAU,EAAE,CAAC;YAC9B,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;YACtC,OAAO,CAAC,GAAG,CAAC,kCAAkC,SAAS,KAAK,OAAO,GAAG,CAAC,CAAC;QACzE,CAAC;QACD,OAAO,OAAO,CAAC;IAChB,CAAC;IAED,YAAY,CAAC,GAAiB;QAC7B,MAAM,MAAM,GAAG,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC;QACnD,OAAO,CAAC,GAAG,CACV,iBAAiB,MAAM,KAAK,GAAG,CAAC,QAAQ,OAAO,GAAG,CAAC,MAAM,WAAW,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,KAAK,CAC9F,CAAC;IACH,CAAC;CACD"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bun SQLite Logger for graph-mode
|
|
3
|
+
*
|
|
4
|
+
* This logger requires Bun runtime and uses the built-in bun:sqlite module.
|
|
5
|
+
* Import from 'graph-mode/bun' to use this logger.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```ts
|
|
9
|
+
* import { GraphRunner } from 'graph-mode';
|
|
10
|
+
* import { BunSQLiteLogger } from 'graph-mode/bun';
|
|
11
|
+
* import { Database } from 'bun:sqlite';
|
|
12
|
+
*
|
|
13
|
+
* const db = new Database('./my-graph.db');
|
|
14
|
+
* const logger = new BunSQLiteLogger(db);
|
|
15
|
+
*
|
|
16
|
+
* const runner = new GraphRunner({
|
|
17
|
+
* graphName: 'my-graph',
|
|
18
|
+
* nodes: [...],
|
|
19
|
+
* startNode: 'START',
|
|
20
|
+
* input: {},
|
|
21
|
+
* logger,
|
|
22
|
+
* });
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
import { Database } from "bun:sqlite";
|
|
26
|
+
import type { Logger, ExecutionLog } from "../logger.js";
|
|
27
|
+
export declare class BunSQLiteLogger implements Logger {
|
|
28
|
+
private db;
|
|
29
|
+
private initialized;
|
|
30
|
+
/**
|
|
31
|
+
* Create a new BunSQLiteLogger.
|
|
32
|
+
* @param db - A Bun SQLite Database instance. If not provided, uses an in-memory database.
|
|
33
|
+
*/
|
|
34
|
+
constructor(db?: Database);
|
|
35
|
+
private initializeDb;
|
|
36
|
+
registerGraph(graphName: string): string;
|
|
37
|
+
logExecution(log: ExecutionLog): void;
|
|
38
|
+
/**
|
|
39
|
+
* Get the underlying database instance for custom queries.
|
|
40
|
+
*/
|
|
41
|
+
getDatabase(): Database;
|
|
42
|
+
/**
|
|
43
|
+
* Get all executions for a specific run.
|
|
44
|
+
*/
|
|
45
|
+
getExecutions(runId: string): ExecutionLog[];
|
|
46
|
+
/**
|
|
47
|
+
* Get all runs for a specific graph.
|
|
48
|
+
*/
|
|
49
|
+
getRuns(graphName: string): string[];
|
|
50
|
+
}
|
|
51
|
+
//# sourceMappingURL=bun-sqlite.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bun-sqlite.d.ts","sourceRoot":"","sources":["../../src/loggers/bun-sqlite.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAGzD,qBAAa,eAAgB,YAAW,MAAM;IAC7C,OAAO,CAAC,EAAE,CAAW;IACrB,OAAO,CAAC,WAAW,CAAS;IAE5B;;;OAGG;gBACS,EAAE,CAAC,EAAE,QAAQ;IAKzB,OAAO,CAAC,YAAY;IA2BpB,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM;IAiBxC,YAAY,CAAC,GAAG,EAAE,YAAY,GAAG,IAAI;IAmBrC;;OAEG;IACH,WAAW,IAAI,QAAQ;IAIvB;;OAEG;IACH,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,YAAY,EAAE;IAM5C;;OAEG;IACH,OAAO,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,EAAE;CAapC"}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bun SQLite Logger for graph-mode
|
|
3
|
+
*
|
|
4
|
+
* This logger requires Bun runtime and uses the built-in bun:sqlite module.
|
|
5
|
+
* Import from 'graph-mode/bun' to use this logger.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```ts
|
|
9
|
+
* import { GraphRunner } from 'graph-mode';
|
|
10
|
+
* import { BunSQLiteLogger } from 'graph-mode/bun';
|
|
11
|
+
* import { Database } from 'bun:sqlite';
|
|
12
|
+
*
|
|
13
|
+
* const db = new Database('./my-graph.db');
|
|
14
|
+
* const logger = new BunSQLiteLogger(db);
|
|
15
|
+
*
|
|
16
|
+
* const runner = new GraphRunner({
|
|
17
|
+
* graphName: 'my-graph',
|
|
18
|
+
* nodes: [...],
|
|
19
|
+
* startNode: 'START',
|
|
20
|
+
* input: {},
|
|
21
|
+
* logger,
|
|
22
|
+
* });
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
import { Database } from "bun:sqlite";
|
|
26
|
+
import { serializeValue } from "../utils.js";
|
|
27
|
+
export class BunSQLiteLogger {
|
|
28
|
+
db;
|
|
29
|
+
initialized = false;
|
|
30
|
+
/**
|
|
31
|
+
* Create a new BunSQLiteLogger.
|
|
32
|
+
* @param db - A Bun SQLite Database instance. If not provided, uses an in-memory database.
|
|
33
|
+
*/
|
|
34
|
+
constructor(db) {
|
|
35
|
+
this.db = db ?? new Database(":memory:");
|
|
36
|
+
this.initializeDb();
|
|
37
|
+
}
|
|
38
|
+
initializeDb() {
|
|
39
|
+
if (this.initialized)
|
|
40
|
+
return;
|
|
41
|
+
this.db.exec(`
|
|
42
|
+
CREATE TABLE IF NOT EXISTS Graphs(
|
|
43
|
+
id TEXT PRIMARY KEY,
|
|
44
|
+
graphName TEXT UNIQUE
|
|
45
|
+
)
|
|
46
|
+
`);
|
|
47
|
+
this.db.exec(`
|
|
48
|
+
CREATE TABLE IF NOT EXISTS Executions(
|
|
49
|
+
id TEXT PRIMARY KEY,
|
|
50
|
+
runId TEXT,
|
|
51
|
+
graphId TEXT,
|
|
52
|
+
nodeType TEXT,
|
|
53
|
+
input TEXT,
|
|
54
|
+
output TEXT,
|
|
55
|
+
routed TEXT,
|
|
56
|
+
datetime TEXT,
|
|
57
|
+
success INTEGER
|
|
58
|
+
)
|
|
59
|
+
`);
|
|
60
|
+
this.initialized = true;
|
|
61
|
+
}
|
|
62
|
+
registerGraph(graphName) {
|
|
63
|
+
const existing = this.db
|
|
64
|
+
.prepare(`SELECT id FROM Graphs WHERE graphName = ? LIMIT 1`)
|
|
65
|
+
.get(graphName);
|
|
66
|
+
if (existing) {
|
|
67
|
+
return existing.id;
|
|
68
|
+
}
|
|
69
|
+
const graphId = crypto.randomUUID();
|
|
70
|
+
this.db
|
|
71
|
+
.prepare(`INSERT INTO Graphs(id, graphName) VALUES(?, ?)`)
|
|
72
|
+
.run(graphId, graphName);
|
|
73
|
+
return graphId;
|
|
74
|
+
}
|
|
75
|
+
logExecution(log) {
|
|
76
|
+
this.db
|
|
77
|
+
.prepare(`INSERT INTO Executions(id, runId, graphId, nodeType, input, output, routed, datetime, success)
|
|
78
|
+
VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?)`)
|
|
79
|
+
.run(log.id, log.runId, log.graphId, log.nodeType, serializeValue(log.input), serializeValue(log.output), log.routed, log.datetime, log.success ? 1 : 0);
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Get the underlying database instance for custom queries.
|
|
83
|
+
*/
|
|
84
|
+
getDatabase() {
|
|
85
|
+
return this.db;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Get all executions for a specific run.
|
|
89
|
+
*/
|
|
90
|
+
getExecutions(runId) {
|
|
91
|
+
return this.db
|
|
92
|
+
.prepare(`SELECT * FROM Executions WHERE runId = ? ORDER BY datetime`)
|
|
93
|
+
.all(runId);
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Get all runs for a specific graph.
|
|
97
|
+
*/
|
|
98
|
+
getRuns(graphName) {
|
|
99
|
+
const graphId = this.db
|
|
100
|
+
.prepare(`SELECT id FROM Graphs WHERE graphName = ? LIMIT 1`)
|
|
101
|
+
.get(graphName);
|
|
102
|
+
if (!graphId)
|
|
103
|
+
return [];
|
|
104
|
+
const runs = this.db
|
|
105
|
+
.prepare(`SELECT DISTINCT runId FROM Executions WHERE graphId = ?`)
|
|
106
|
+
.all(graphId.id);
|
|
107
|
+
return runs.map((r) => r.runId);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
//# sourceMappingURL=bun-sqlite.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bun-sqlite.js","sourceRoot":"","sources":["../../src/loggers/bun-sqlite.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAEtC,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAE7C,MAAM,OAAO,eAAe;IACnB,EAAE,CAAW;IACb,WAAW,GAAG,KAAK,CAAC;IAE5B;;;OAGG;IACH,YAAY,EAAa;QACxB,IAAI,CAAC,EAAE,GAAG,EAAE,IAAI,IAAI,QAAQ,CAAC,UAAU,CAAC,CAAC;QACzC,IAAI,CAAC,YAAY,EAAE,CAAC;IACrB,CAAC;IAEO,YAAY;QACnB,IAAI,IAAI,CAAC,WAAW;YAAE,OAAO;QAE7B,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC;;;;;GAKZ,CAAC,CAAC;QAEH,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC;;;;;;;;;;;;GAYZ,CAAC,CAAC;QAEH,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC;IACzB,CAAC;IAED,aAAa,CAAC,SAAiB;QAC9B,MAAM,QAAQ,GAAG,IAAI,CAAC,EAAE;aACtB,OAAO,CAAC,mDAAmD,CAAC;aAC5D,GAAG,CAAC,SAAS,CAA0B,CAAC;QAE1C,IAAI,QAAQ,EAAE,CAAC;YACd,OAAO,QAAQ,CAAC,EAAE,CAAC;QACpB,CAAC;QAED,MAAM,OAAO,GAAG,MAAM,CAAC,UAAU,EAAE,CAAC;QACpC,IAAI,CAAC,EAAE;aACL,OAAO,CAAC,gDAAgD,CAAC;aACzD,GAAG,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;QAE1B,OAAO,OAAO,CAAC;IAChB,CAAC;IAED,YAAY,CAAC,GAAiB;QAC7B,IAAI,CAAC,EAAE;aACL,OAAO,CACP;uCACmC,CACnC;aACA,GAAG,CACH,GAAG,CAAC,EAAE,EACN,GAAG,CAAC,KAAK,EACT,GAAG,CAAC,OAAO,EACX,GAAG,CAAC,QAAQ,EACZ,cAAc,CAAC,GAAG,CAAC,KAAK,CAAC,EACzB,cAAc,CAAC,GAAG,CAAC,MAAM,CAAC,EAC1B,GAAG,CAAC,MAAM,EACV,GAAG,CAAC,QAAQ,EACZ,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CACnB,CAAC;IACJ,CAAC;IAED;;OAEG;IACH,WAAW;QACV,OAAO,IAAI,CAAC,EAAE,CAAC;IAChB,CAAC;IAED;;OAEG;IACH,aAAa,CAAC,KAAa;QAC1B,OAAO,IAAI,CAAC,EAAE;aACZ,OAAO,CAAC,4DAA4D,CAAC;aACrE,GAAG,CAAC,KAAK,CAAmB,CAAC;IAChC,CAAC;IAED;;OAEG;IACH,OAAO,CAAC,SAAiB;QACxB,MAAM,OAAO,GAAG,IAAI,CAAC,EAAE;aACrB,OAAO,CAAC,mDAAmD,CAAC;aAC5D,GAAG,CAAC,SAAS,CAA0B,CAAC;QAE1C,IAAI,CAAC,OAAO;YAAE,OAAO,EAAE,CAAC;QAExB,MAAM,IAAI,GAAG,IAAI,CAAC,EAAE;aAClB,OAAO,CAAC,yDAAyD,CAAC;aAClE,GAAG,CAAC,OAAO,CAAC,EAAE,CAAwB,CAAC;QAEzC,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;IACjC,CAAC;CACD"}
|
package/dist/utils.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA,wBAAsB,KAAK,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,EAAE,UAAU,GAAE,MAAU,EAAE,OAAO,GAAE,MAAU,EAAE,KAAK,CAAC,EAAE,KAAK,GAAG,OAAO,CAAC,CAAC,CAAC,CAUjI;AAED,eAAO,MAAM,cAAc,GAAI,OAAO,GAAG,KAAG,MAAM,GAAG,IAepD,CAAC"}
|
package/dist/utils.js
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
export async function retry(func, maxAttempt = 3, attempt = 1, error) {
|
|
2
|
+
if (attempt > maxAttempt)
|
|
3
|
+
throw new Error(String(error));
|
|
4
|
+
try {
|
|
5
|
+
const res = await func();
|
|
6
|
+
return res;
|
|
7
|
+
}
|
|
8
|
+
catch (error) {
|
|
9
|
+
await new Promise((resolve) => setTimeout(resolve, 1000 * (attempt + 1) * (attempt + 1)));
|
|
10
|
+
return await retry(func, maxAttempt, attempt + 1, error);
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
export const serializeValue = (value) => {
|
|
14
|
+
if (value === null || value === undefined) {
|
|
15
|
+
return null;
|
|
16
|
+
}
|
|
17
|
+
if (value instanceof Error) {
|
|
18
|
+
return JSON.stringify({
|
|
19
|
+
name: value.name,
|
|
20
|
+
message: value.message,
|
|
21
|
+
stack: value.stack,
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
if (typeof value === 'object') {
|
|
25
|
+
return JSON.stringify(value);
|
|
26
|
+
}
|
|
27
|
+
return String(value);
|
|
28
|
+
};
|
|
29
|
+
//# sourceMappingURL=utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,KAAK,UAAU,KAAK,CAAI,IAA0B,EAAE,aAAqB,CAAC,EAAE,UAAkB,CAAC,EAAE,KAAa;IACpH,IAAI,OAAO,GAAG,UAAU;QAAE,MAAM,IAAI,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;IACzD,IAAI,CAAC;QACJ,MAAM,GAAG,GAAM,MAAM,IAAI,EAAE,CAAC;QAC5B,OAAO,GAAG,CAAC;IACZ,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QAChB,MAAM,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,IAAI,GAAG,CAAC,OAAO,GAAG,CAAC,CAAC,GAAG,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC,CACvF,CAAC;QACF,OAAO,MAAM,KAAK,CAAC,IAAI,EAAE,UAAU,EAAE,OAAO,GAAG,CAAC,EAAE,KAAc,CAAC,CAAC;IACnE,CAAC;AACF,CAAC;AAED,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,KAAU,EAAiB,EAAE;IAC3D,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QAC3C,OAAO,IAAI,CAAC;IACb,CAAC;IACD,IAAI,KAAK,YAAY,KAAK,EAAE,CAAC;QAC5B,OAAO,IAAI,CAAC,SAAS,CAAC;YACrB,IAAI,EAAE,KAAK,CAAC,IAAI;YAChB,OAAO,EAAE,KAAK,CAAC,OAAO;YACtB,KAAK,EAAE,KAAK,CAAC,KAAK;SAClB,CAAC,CAAC;IACJ,CAAC;IACD,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC/B,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;IAC9B,CAAC;IACD,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC;AACtB,CAAC,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "graph-mode",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "A graph-based workflow execution framework for TypeScript",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"module": "./dist/index.js",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
|
+
"import": "./dist/index.js"
|
|
13
|
+
},
|
|
14
|
+
"./bun": {
|
|
15
|
+
"types": "./dist/loggers/bun-sqlite.d.ts",
|
|
16
|
+
"import": "./dist/loggers/bun-sqlite.js"
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
"files": [
|
|
20
|
+
"dist",
|
|
21
|
+
"README.md",
|
|
22
|
+
"LICENSE"
|
|
23
|
+
],
|
|
24
|
+
"scripts": {
|
|
25
|
+
"build": "tsc",
|
|
26
|
+
"prepublishOnly": "npm run build"
|
|
27
|
+
},
|
|
28
|
+
"keywords": [
|
|
29
|
+
"graph",
|
|
30
|
+
"workflow",
|
|
31
|
+
"state-machine",
|
|
32
|
+
"dag",
|
|
33
|
+
"pipeline",
|
|
34
|
+
"orchestration",
|
|
35
|
+
"ai",
|
|
36
|
+
"agent",
|
|
37
|
+
"typescript"
|
|
38
|
+
],
|
|
39
|
+
"author": "",
|
|
40
|
+
"license": "MIT",
|
|
41
|
+
"repository": {
|
|
42
|
+
"type": "git",
|
|
43
|
+
"url": "https://github.com/jackmuva/graph-mode"
|
|
44
|
+
},
|
|
45
|
+
"engines": {
|
|
46
|
+
"node": ">=18"
|
|
47
|
+
},
|
|
48
|
+
"devDependencies": {
|
|
49
|
+
"@types/bun": "latest",
|
|
50
|
+
"typescript": "^5.0.0"
|
|
51
|
+
},
|
|
52
|
+
"peerDependencies": {
|
|
53
|
+
"typescript": "^5"
|
|
54
|
+
},
|
|
55
|
+
"peerDependenciesMeta": {
|
|
56
|
+
"typescript": {
|
|
57
|
+
"optional": true
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
"autho": "Jack Mu jackmu@umich.edu"
|
|
61
|
+
}
|