@ai.ntellect/core 1.0.0 → 1.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/.mocharc.json +6 -0
- package/AGENTS.md +50 -0
- package/ARCHITECTURE.md +58 -0
- package/BENCHMARK.md +38 -0
- package/CHANGELOG.md +224 -0
- package/README.md +411 -142
- package/agent/agent-workflow.ts +569 -0
- package/agent/agent.ts +183 -0
- package/agent/base/executor.ts +103 -0
- package/agent/base/index.ts +87 -0
- package/agent/entity-resolver/confidence.ts +54 -0
- package/agent/entity-resolver/entity-index.ts +241 -0
- package/agent/entity-resolver/explore-strategy.ts +82 -0
- package/agent/entity-resolver/index.ts +22 -0
- package/agent/entity-resolver/resolver.ts +193 -0
- package/agent/entity-resolver/scorer.ts +211 -0
- package/agent/entity-resolver/types.ts +98 -0
- package/agent/generic-executor.ts +713 -0
- package/agent/handlers/cognitive-handler.ts +197 -0
- package/agent/handlers/index.ts +1 -0
- package/agent/handoff.ts +58 -0
- package/agent/llm-factory.ts +343 -0
- package/agent/orchestrator.ts +45 -0
- package/agent/prompt-builder.ts +78 -0
- package/agent/registry.ts +64 -0
- package/agent/tools/file-system.ts +471 -0
- package/agent/tools/index.ts +23 -0
- package/agent/tools/logger.ts +105 -0
- package/agent/tools/tool-resolver.ts +104 -0
- package/benchmark/cortexflow-workflow.ts +182 -0
- package/benchmark/langgraph-workflow.ts +201 -0
- package/benchmark/llm-client.ts +76 -0
- package/benchmark/run-benchmark.ts +222 -0
- package/cli-dev.ts +419 -0
- package/dist/agent/agent-workflow.d.ts +41 -0
- package/dist/agent/agent-workflow.d.ts.map +1 -0
- package/dist/agent/agent-workflow.js +560 -0
- package/dist/agent/agent-workflow.js.map +1 -0
- package/dist/agent/agent.d.ts +38 -0
- package/dist/agent/agent.d.ts.map +1 -0
- package/dist/agent/agent.js +149 -0
- package/dist/agent/agent.js.map +1 -0
- package/dist/agent/base/executor.d.ts +51 -0
- package/dist/agent/base/executor.d.ts.map +1 -0
- package/dist/agent/base/executor.js +69 -0
- package/dist/agent/base/executor.js.map +1 -0
- package/dist/agent/base/index.d.ts +30 -0
- package/dist/agent/base/index.d.ts.map +1 -0
- package/dist/agent/base/index.js +88 -0
- package/dist/agent/base/index.js.map +1 -0
- package/dist/agent/entity-resolver/confidence.d.ts +4 -0
- package/dist/agent/entity-resolver/confidence.d.ts.map +1 -0
- package/dist/agent/entity-resolver/confidence.js +47 -0
- package/dist/agent/entity-resolver/confidence.js.map +1 -0
- package/dist/agent/entity-resolver/entity-index.d.ts +40 -0
- package/dist/agent/entity-resolver/entity-index.d.ts.map +1 -0
- package/dist/agent/entity-resolver/entity-index.js +244 -0
- package/dist/agent/entity-resolver/entity-index.js.map +1 -0
- package/dist/agent/entity-resolver/explore-strategy.d.ts +13 -0
- package/dist/agent/entity-resolver/explore-strategy.d.ts.map +1 -0
- package/dist/agent/entity-resolver/explore-strategy.js +109 -0
- package/dist/agent/entity-resolver/explore-strategy.js.map +1 -0
- package/dist/agent/entity-resolver/index.d.ts +8 -0
- package/dist/agent/entity-resolver/index.d.ts.map +1 -0
- package/dist/agent/entity-resolver/index.js +16 -0
- package/dist/agent/entity-resolver/index.js.map +1 -0
- package/dist/agent/entity-resolver/resolver.d.ts +18 -0
- package/dist/agent/entity-resolver/resolver.d.ts.map +1 -0
- package/dist/agent/entity-resolver/resolver.js +158 -0
- package/dist/agent/entity-resolver/resolver.js.map +1 -0
- package/dist/agent/entity-resolver/scorer.d.ts +3 -0
- package/dist/agent/entity-resolver/scorer.d.ts.map +1 -0
- package/dist/agent/entity-resolver/scorer.js +182 -0
- package/dist/agent/entity-resolver/scorer.js.map +1 -0
- package/dist/agent/entity-resolver/types.d.ts +89 -0
- package/dist/agent/entity-resolver/types.d.ts.map +1 -0
- package/dist/agent/entity-resolver/types.js +3 -0
- package/dist/agent/entity-resolver/types.js.map +1 -0
- package/dist/agent/generic-executor.d.ts +68 -0
- package/dist/agent/generic-executor.d.ts.map +1 -0
- package/dist/agent/generic-executor.js +620 -0
- package/dist/agent/generic-executor.js.map +1 -0
- package/dist/agent/handlers/cognitive-handler.d.ts +44 -0
- package/dist/agent/handlers/cognitive-handler.d.ts.map +1 -0
- package/dist/agent/handlers/cognitive-handler.js +172 -0
- package/dist/agent/handlers/cognitive-handler.js.map +1 -0
- package/dist/agent/handlers/index.d.ts +2 -0
- package/dist/agent/handlers/index.d.ts.map +1 -0
- package/dist/agent/handlers/index.js +7 -0
- package/dist/agent/handlers/index.js.map +1 -0
- package/dist/agent/handoff.d.ts +12 -0
- package/dist/agent/handoff.d.ts.map +1 -0
- package/dist/agent/handoff.js +62 -0
- package/dist/agent/handoff.js.map +1 -0
- package/dist/agent/llm-factory.d.ts +19 -0
- package/dist/agent/llm-factory.d.ts.map +1 -0
- package/dist/agent/llm-factory.js +297 -0
- package/dist/agent/llm-factory.js.map +1 -0
- package/dist/agent/orchestrator.d.ts +18 -0
- package/dist/agent/orchestrator.d.ts.map +1 -0
- package/dist/agent/orchestrator.js +44 -0
- package/dist/agent/orchestrator.js.map +1 -0
- package/dist/agent/prompt-builder.d.ts +35 -0
- package/dist/agent/prompt-builder.d.ts.map +1 -0
- package/dist/agent/prompt-builder.js +76 -0
- package/dist/agent/prompt-builder.js.map +1 -0
- package/dist/agent/registry.d.ts +19 -0
- package/dist/agent/registry.d.ts.map +1 -0
- package/dist/agent/registry.js +48 -0
- package/dist/agent/registry.js.map +1 -0
- package/dist/agent/tools/file-system.d.ts +11 -0
- package/dist/agent/tools/file-system.d.ts.map +1 -0
- package/dist/agent/tools/file-system.js +528 -0
- package/dist/agent/tools/file-system.js.map +1 -0
- package/dist/agent/tools/index.d.ts +4 -0
- package/dist/agent/tools/index.d.ts.map +1 -0
- package/dist/agent/tools/index.js +20 -0
- package/dist/agent/tools/index.js.map +1 -0
- package/dist/agent/tools/logger.d.ts +33 -0
- package/dist/agent/tools/logger.d.ts.map +1 -0
- package/dist/agent/tools/logger.js +86 -0
- package/dist/agent/tools/logger.js.map +1 -0
- package/dist/agent/tools/tool-resolver.d.ts +7 -0
- package/dist/agent/tools/tool-resolver.d.ts.map +1 -0
- package/dist/agent/tools/tool-resolver.js +122 -0
- package/dist/agent/tools/tool-resolver.js.map +1 -0
- package/dist/execution/adapters/in-memory-checkpoint.d.ts +11 -0
- package/dist/execution/adapters/in-memory-checkpoint.d.ts.map +1 -0
- package/dist/execution/adapters/in-memory-checkpoint.js +54 -0
- package/dist/execution/adapters/in-memory-checkpoint.js.map +1 -0
- package/dist/execution/compiler.d.ts +8 -0
- package/dist/execution/compiler.d.ts.map +1 -0
- package/dist/execution/compiler.js +50 -0
- package/dist/execution/compiler.js.map +1 -0
- package/dist/execution/controller.d.ts +30 -0
- package/dist/execution/controller.d.ts.map +1 -0
- package/dist/execution/controller.js +80 -0
- package/dist/execution/controller.js.map +1 -0
- package/dist/execution/event-manager.d.ts +29 -0
- package/dist/execution/event-manager.d.ts.map +1 -0
- package/dist/execution/event-manager.js +264 -0
- package/dist/execution/event-manager.js.map +1 -0
- package/dist/execution/index.d.ts +221 -0
- package/dist/execution/index.d.ts.map +1 -0
- package/dist/execution/index.js +638 -0
- package/dist/execution/index.js.map +1 -0
- package/dist/execution/logger.d.ts +46 -0
- package/dist/execution/logger.d.ts.map +1 -0
- package/dist/execution/logger.js +69 -0
- package/dist/execution/logger.js.map +1 -0
- package/dist/execution/node.d.ts +65 -0
- package/dist/execution/node.d.ts.map +1 -0
- package/dist/execution/node.js +250 -0
- package/dist/execution/node.js.map +1 -0
- package/dist/execution/observer.d.ts +38 -0
- package/dist/execution/observer.d.ts.map +1 -0
- package/dist/execution/observer.js +111 -0
- package/dist/execution/observer.js.map +1 -0
- package/dist/execution/planner.d.ts +14 -0
- package/dist/execution/planner.d.ts.map +1 -0
- package/dist/execution/planner.js +43 -0
- package/dist/execution/planner.js.map +1 -0
- package/dist/execution/reducer.d.ts +19 -0
- package/dist/execution/reducer.d.ts.map +1 -0
- package/dist/execution/reducer.js +61 -0
- package/dist/execution/reducer.js.map +1 -0
- package/dist/execution/registry.d.ts +38 -0
- package/dist/execution/registry.d.ts.map +1 -0
- package/dist/execution/registry.js +63 -0
- package/dist/execution/registry.js.map +1 -0
- package/dist/execution/send-api.d.ts +24 -0
- package/dist/execution/send-api.d.ts.map +1 -0
- package/dist/execution/send-api.js +52 -0
- package/dist/execution/send-api.js.map +1 -0
- package/dist/execution/types.parallel.d.ts +61 -0
- package/dist/execution/types.parallel.d.ts.map +1 -0
- package/dist/execution/types.parallel.js +3 -0
- package/dist/execution/types.parallel.js.map +1 -0
- package/dist/execution/visualizer.d.ts +35 -0
- package/dist/execution/visualizer.d.ts.map +1 -0
- package/dist/execution/visualizer.js +131 -0
- package/dist/execution/visualizer.js.map +1 -0
- package/dist/index.d.ts +47 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +78 -0
- package/dist/index.js.map +1 -0
- package/dist/interfaces/index.d.ts +487 -0
- package/dist/interfaces/index.d.ts.map +1 -0
- package/dist/interfaces/index.js +75 -0
- package/dist/interfaces/index.js.map +1 -0
- package/dist/modules/agenda/adapters/node-cron/index.d.ts +17 -0
- package/dist/modules/agenda/adapters/node-cron/index.d.ts.map +1 -0
- package/dist/modules/agenda/adapters/node-cron/index.js +30 -0
- package/dist/modules/agenda/adapters/node-cron/index.js.map +1 -0
- package/dist/modules/agenda/index.d.ts +63 -0
- package/dist/modules/agenda/index.d.ts.map +1 -0
- package/dist/modules/agenda/index.js +141 -0
- package/dist/modules/agenda/index.js.map +1 -0
- package/dist/modules/cli/index.d.ts +13 -0
- package/dist/modules/cli/index.d.ts.map +1 -0
- package/dist/modules/cli/index.js +672 -0
- package/dist/modules/cli/index.js.map +1 -0
- package/dist/modules/embedding/adapters/ai/index.d.ts +29 -0
- package/dist/modules/embedding/adapters/ai/index.d.ts.map +1 -0
- package/dist/modules/embedding/adapters/ai/index.js +58 -0
- package/dist/modules/embedding/adapters/ai/index.js.map +1 -0
- package/dist/modules/embedding/index.d.ts +36 -0
- package/dist/modules/embedding/index.d.ts.map +1 -0
- package/dist/modules/embedding/index.js +60 -0
- package/dist/modules/embedding/index.js.map +1 -0
- package/dist/modules/nlp/engine.d.ts +126 -0
- package/dist/modules/nlp/engine.d.ts.map +1 -0
- package/dist/modules/nlp/engine.js +299 -0
- package/dist/modules/nlp/engine.js.map +1 -0
- package/dist/modules/nlp/index.d.ts +27 -0
- package/dist/modules/nlp/index.d.ts.map +1 -0
- package/dist/modules/nlp/index.js +56 -0
- package/dist/modules/nlp/index.js.map +1 -0
- package/dist/persistence/index.d.ts +12 -0
- package/dist/persistence/index.d.ts.map +1 -0
- package/dist/persistence/index.js +24 -0
- package/dist/persistence/index.js.map +1 -0
- package/dist/persistence/neo4j/driver.d.ts +26 -0
- package/dist/persistence/neo4j/driver.d.ts.map +1 -0
- package/dist/persistence/neo4j/driver.js +64 -0
- package/dist/persistence/neo4j/driver.js.map +1 -0
- package/dist/persistence/neo4j/entity-store.d.ts +15 -0
- package/dist/persistence/neo4j/entity-store.d.ts.map +1 -0
- package/dist/persistence/neo4j/entity-store.js +136 -0
- package/dist/persistence/neo4j/entity-store.js.map +1 -0
- package/dist/persistence/neo4j/execution-tracer.d.ts +19 -0
- package/dist/persistence/neo4j/execution-tracer.d.ts.map +1 -0
- package/dist/persistence/neo4j/execution-tracer.js +166 -0
- package/dist/persistence/neo4j/execution-tracer.js.map +1 -0
- package/dist/persistence/neo4j/memory-adapter.d.ts +35 -0
- package/dist/persistence/neo4j/memory-adapter.d.ts.map +1 -0
- package/dist/persistence/neo4j/memory-adapter.js +252 -0
- package/dist/persistence/neo4j/memory-adapter.js.map +1 -0
- package/dist/persistence/neo4j/petri-checkpoint-adapter.d.ts +22 -0
- package/dist/persistence/neo4j/petri-checkpoint-adapter.d.ts.map +1 -0
- package/dist/persistence/neo4j/petri-checkpoint-adapter.js +141 -0
- package/dist/persistence/neo4j/petri-checkpoint-adapter.js.map +1 -0
- package/dist/pipeline/agent-pipeline.d.ts +99 -0
- package/dist/pipeline/agent-pipeline.d.ts.map +1 -0
- package/dist/pipeline/agent-pipeline.js +356 -0
- package/dist/pipeline/agent-pipeline.js.map +1 -0
- package/dist/routing/checkpoint-adapter.d.ts +30 -0
- package/dist/routing/checkpoint-adapter.d.ts.map +1 -0
- package/dist/routing/checkpoint-adapter.js +83 -0
- package/dist/routing/checkpoint-adapter.js.map +1 -0
- package/dist/routing/documentation-generator.d.ts +47 -0
- package/dist/routing/documentation-generator.d.ts.map +1 -0
- package/dist/routing/documentation-generator.js +320 -0
- package/dist/routing/documentation-generator.js.map +1 -0
- package/dist/routing/index.d.ts +38 -0
- package/dist/routing/index.d.ts.map +1 -0
- package/dist/routing/index.js +375 -0
- package/dist/routing/index.js.map +1 -0
- package/dist/routing/intent-classifier.d.ts +206 -0
- package/dist/routing/intent-classifier.d.ts.map +1 -0
- package/dist/routing/intent-classifier.js +267 -0
- package/dist/routing/intent-classifier.js.map +1 -0
- package/dist/routing/matrix.d.ts +6 -0
- package/dist/routing/matrix.d.ts.map +1 -0
- package/dist/routing/matrix.js +131 -0
- package/dist/routing/matrix.js.map +1 -0
- package/dist/routing/orchestrator.d.ts +87 -0
- package/dist/routing/orchestrator.d.ts.map +1 -0
- package/dist/routing/orchestrator.js +425 -0
- package/dist/routing/orchestrator.js.map +1 -0
- package/dist/routing/postgres-checkpoint-adapter.d.ts +32 -0
- package/dist/routing/postgres-checkpoint-adapter.d.ts.map +1 -0
- package/dist/routing/postgres-checkpoint-adapter.js +167 -0
- package/dist/routing/postgres-checkpoint-adapter.js.map +1 -0
- package/dist/routing/redis-checkpoint-adapter.d.ts +34 -0
- package/dist/routing/redis-checkpoint-adapter.d.ts.map +1 -0
- package/dist/routing/redis-checkpoint-adapter.js +170 -0
- package/dist/routing/redis-checkpoint-adapter.js.map +1 -0
- package/dist/routing/types.d.ts +49 -0
- package/dist/routing/types.d.ts.map +1 -0
- package/dist/routing/types.js +3 -0
- package/dist/routing/types.js.map +1 -0
- package/dist/types/agent.d.ts +289 -0
- package/dist/types/agent.d.ts.map +1 -0
- package/dist/types/agent.js +78 -0
- package/dist/types/agent.js.map +1 -0
- package/dist/types/index.d.ts +343 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +3 -0
- package/dist/types/index.js.map +1 -0
- package/dist/utils/generate-action-schema.d.ts +4 -0
- package/dist/utils/generate-action-schema.d.ts.map +1 -0
- package/dist/utils/generate-action-schema.js +46 -0
- package/dist/utils/generate-action-schema.js.map +1 -0
- package/dist/utils/header-builder.d.ts +12 -0
- package/dist/utils/header-builder.d.ts.map +1 -0
- package/dist/utils/header-builder.js +35 -0
- package/dist/utils/header-builder.js.map +1 -0
- package/dist/utils/logger.d.ts +27 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +45 -0
- package/dist/utils/logger.js.map +1 -0
- package/docs/.gitbook/assets/image (1).png +0 -0
- package/docs/.gitbook/assets/image (2).png +0 -0
- package/docs/.gitbook/assets/image (3).png +0 -0
- package/docs/.gitbook/assets/image (4).png +0 -0
- package/docs/.gitbook/assets/image (5).png +0 -0
- package/docs/.gitbook/assets/image (6).png +0 -0
- package/docs/.gitbook/assets/image.png +0 -0
- package/docs/README.md +57 -0
- package/docs/SUMMARY.md +34 -0
- package/docs/cas-dusages.md +69 -0
- package/docs/cli/README.md +65 -0
- package/docs/concepts-cles.md +50 -0
- package/docs/core/architecture.md +87 -0
- package/docs/core/benchmark.md +59 -0
- package/docs/core/checkpoint.md +72 -0
- package/docs/core/documentation.md +55 -0
- package/docs/core/graphcontroller.md +63 -0
- package/docs/core/graphflow.md +137 -0
- package/docs/core/introduction.md +41 -0
- package/docs/core/les-evenements.md +95 -0
- package/docs/modules/agenda/README.md +63 -0
- package/docs/modules/agenda/interface-iagenda.md +170 -0
- package/docs/modules/agenda/les-adaptateurs/README.md +237 -0
- package/docs/modules/agenda/les-adaptateurs/nodecronadapter.md +91 -0
- package/docs/modules/introduction.md +55 -0
- package/docs/modules/les-adaptateurs.md +52 -0
- package/docs/modules/memoire/README.md +68 -0
- package/docs/modules/memoire/interface-imemory.md +183 -0
- package/docs/modules/memoire/les-adaptateurs/README.md +209 -0
- package/docs/modules/memoire/les-adaptateurs/inmemoryadapter.md +110 -0
- package/docs/modules/memoire/les-adaptateurs/meilisearchadapter.md +147 -0
- package/docs/modules/memoire/les-adaptateurs/redisadapter.md +212 -0
- package/docs/modules/nlp/README.md +44 -0
- package/docs/philosophie.md +51 -0
- package/docs/tutoriels/ajouter-des-conditions.md +150 -0
- package/docs/tutoriels/branching.md +194 -0
- package/docs/tutoriels/checkpoint-usage.md +99 -0
- package/docs/tutoriels/creer-agent-onchain.md +1041 -0
- package/docs/tutoriels/creer-un-agent.md +108 -0
- package/docs/tutoriels/creer-un-graphe-simple.md +92 -0
- package/docs/tutoriels/gerer-les-erreurs.md +124 -0
- package/docs/tutoriels/pour-commencer.md +73 -0
- package/docs/tutoriels/retry.md +166 -0
- package/execution/adapters/in-memory-checkpoint.ts +35 -0
- package/execution/compiler.ts +47 -0
- package/execution/controller.ts +84 -0
- package/execution/event-manager.ts +331 -0
- package/execution/index.ts +800 -0
- package/execution/logger.ts +70 -0
- package/execution/node.ts +315 -0
- package/execution/observer.ts +192 -0
- package/execution/planner.ts +40 -0
- package/execution/reducer.ts +73 -0
- package/execution/registry.ts +86 -0
- package/execution/send-api.ts +58 -0
- package/execution/types.parallel.ts +81 -0
- package/execution/visualizer.ts +158 -0
- package/index.ts +55 -465
- package/interfaces/index.ts +597 -0
- package/modules/agenda/adapters/node-cron/index.ts +25 -0
- package/modules/agenda/index.ts +146 -0
- package/modules/cli/index.ts +580 -0
- package/modules/embedding/adapters/ai/index.ts +42 -0
- package/modules/embedding/index.ts +45 -0
- package/modules/nlp/engine.ts +324 -0
- package/modules/nlp/index.ts +45 -0
- package/package.json +81 -9
- package/persistence/index.ts +27 -0
- package/persistence/neo4j/driver.ts +34 -0
- package/persistence/neo4j/entity-store.ts +141 -0
- package/persistence/neo4j/execution-tracer.ts +194 -0
- package/persistence/neo4j/memory-adapter.ts +281 -0
- package/persistence/neo4j/petri-checkpoint-adapter.ts +153 -0
- package/pipeline/agent-pipeline.ts +426 -0
- package/routing/checkpoint-adapter.ts +79 -0
- package/routing/documentation-generator.ts +358 -0
- package/routing/index.ts +459 -0
- package/routing/intent-classifier.ts +360 -0
- package/routing/matrix.ts +138 -0
- package/routing/orchestrator.ts +498 -0
- package/routing/patterns/data-extraction.json +79 -0
- package/routing/patterns/human-approval.json +64 -0
- package/routing/patterns/rag-search.json +68 -0
- package/routing/postgres-checkpoint-adapter.ts +172 -0
- package/routing/redis-checkpoint-adapter.ts +187 -0
- package/routing/types.ts +59 -0
- package/routing/web-server.ts +260 -0
- package/scripts/generate-petri-docs.ts +70 -0
- package/scripts/get-gmail-token.js +65 -0
- package/scripts/get-gmail-token.ts +65 -0
- package/test/agent/agent.test.ts +92 -0
- package/test/agent/clone.test.ts +143 -0
- package/test/agent/cognitive-handler.test.ts +78 -0
- package/test/agent/entity-store.test.ts +80 -0
- package/test/agent/generic-executor.test.ts +230 -0
- package/test/agent/handoff.test.ts +163 -0
- package/test/agent/llm-factory.test.ts +40 -0
- package/test/agent/orchestrator.test.ts +156 -0
- package/test/agent/registry.test.ts +97 -0
- package/test/agent/tools.test.ts +267 -0
- package/test/execution/checkpoint.test.ts +811 -0
- package/test/execution/controller.test.ts +236 -0
- package/test/execution/event-manager.test.ts +118 -0
- package/test/execution/index.test.ts +690 -0
- package/test/execution/node.test.ts +464 -0
- package/test/execution/observer.test.ts +393 -0
- package/test/execution/parallel.test.ts +135 -0
- package/test/execution/plan-llm-integration.test.ts +290 -0
- package/test/execution/plan-real-onchain.test.ts +226 -0
- package/test/execution/send-api.test.ts +121 -0
- package/test/modules/agenda/node-cron.test.ts +307 -0
- package/test/modules/cli/index.test.ts +125 -0
- package/test/persistence/neo4j-execution-tracer.test.ts +96 -0
- package/test/persistence/neo4j-memory-adapter.test.ts +107 -0
- package/test/persistence/neo4j-petri-checkpoint.test.ts +89 -0
- package/test/pipeline/agent-pipeline.test.ts +118 -0
- package/test/routing/checkpoint-persistence.test.ts +58 -0
- package/test/routing/documentation-generator.test.ts +76 -0
- package/test/routing/integration.test.ts +261 -0
- package/test/routing/intent-classifier.test.ts +102 -0
- package/test/routing/petri.test.ts +156 -0
- package/test/routing/real-llm.test.ts +260 -0
- package/test-petri-features.ts +218 -0
- package/test-pipeline-api.ts +163 -0
- package/tsconfig.json +30 -108
- package/types/agent.ts +296 -0
- package/types/index.ts +387 -0
- package/utils/generate-action-schema.ts +47 -0
- package/utils/header-builder.ts +40 -0
- package/utils/logger.ts +40 -0
- package/package copy.json +0 -21
- package/types.ts +0 -62
- package/utils/executor.ts +0 -42
|
@@ -0,0 +1,800 @@
|
|
|
1
|
+
import { EventEmitter } from "events";
|
|
2
|
+
import { BehaviorSubject, Subject } from "rxjs";
|
|
3
|
+
import { ZodSchema } from "zod";
|
|
4
|
+
import { GraphObservable, ICheckpointAdapter, IEventEmitter } from "../interfaces";
|
|
5
|
+
import { NLPNode } from "../modules/nlp";
|
|
6
|
+
import {
|
|
7
|
+
Checkpoint,
|
|
8
|
+
CheckpointConfig,
|
|
9
|
+
GraphConfig,
|
|
10
|
+
GraphContext,
|
|
11
|
+
GraphEvent,
|
|
12
|
+
GraphNodeConfig,
|
|
13
|
+
} from "../types";
|
|
14
|
+
import { GraphEventManager } from "./event-manager";
|
|
15
|
+
import { GraphLogger } from "./logger";
|
|
16
|
+
import { GraphNode, NodeExecutionHooks } from "./node";
|
|
17
|
+
import { GraphObserver } from "./observer";
|
|
18
|
+
import { GraphVisualizer } from "./visualizer";
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* @module GraphFlow
|
|
22
|
+
* @description A workflow engine that manages the execution of nodes in a graph-like structure.
|
|
23
|
+
*
|
|
24
|
+
* Key features:
|
|
25
|
+
* - Multiple branches support
|
|
26
|
+
* - Conditional branching (runs first matching condition, or all if none have conditions)
|
|
27
|
+
* - Event-driven nodes
|
|
28
|
+
* - Zod validation of context/inputs/outputs
|
|
29
|
+
* - Automatic retry on node failures
|
|
30
|
+
*
|
|
31
|
+
* @template T - Extends ZodSchema for type validation
|
|
32
|
+
*/
|
|
33
|
+
export class GraphFlow<T extends ZodSchema> {
|
|
34
|
+
private context: GraphContext<T>;
|
|
35
|
+
private _initialContext: GraphContext<T>;
|
|
36
|
+
public validator?: T;
|
|
37
|
+
private eventEmitter: IEventEmitter;
|
|
38
|
+
private globalErrorHandler?: (error: Error, context: GraphContext<T>) => void;
|
|
39
|
+
private graphEvents?: string[];
|
|
40
|
+
private entryNode?: string;
|
|
41
|
+
private verbose: boolean = false;
|
|
42
|
+
public nodes: Map<string, GraphNodeConfig<T, any>>;
|
|
43
|
+
public name: string;
|
|
44
|
+
|
|
45
|
+
private eventSubject: Subject<GraphEvent<T>> = new Subject();
|
|
46
|
+
private stateSubject: BehaviorSubject<GraphContext<T>>;
|
|
47
|
+
private destroySubject: Subject<void> = new Subject();
|
|
48
|
+
|
|
49
|
+
public observer: GraphObserver<T>;
|
|
50
|
+
private logger: GraphLogger;
|
|
51
|
+
private eventManager: GraphEventManager<T>;
|
|
52
|
+
private nodeExecutor: GraphNode<T>;
|
|
53
|
+
|
|
54
|
+
private nlpNodes: Map<string, NLPNode<T>> = new Map();
|
|
55
|
+
|
|
56
|
+
private _interrupted = false;
|
|
57
|
+
private _interruptCheckpoint: Checkpoint | null = null;
|
|
58
|
+
private _checkpointCounter = 0;
|
|
59
|
+
private _breakpoints: Set<string> = new Set();
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Creates a new instance of GraphFlow
|
|
63
|
+
* @param {GraphConfig<T>} config - Configuration object containing name, nodes, schema, context, and error handlers
|
|
64
|
+
* @param {Object} options - Optional options for the graph flow
|
|
65
|
+
*/
|
|
66
|
+
constructor(config: GraphConfig<T>, options: { verbose?: boolean } = {}) {
|
|
67
|
+
this.name = config.name;
|
|
68
|
+
this.nodes = new Map(
|
|
69
|
+
config.nodes.map((node: GraphNodeConfig<T, any>) => [node.name, node])
|
|
70
|
+
);
|
|
71
|
+
this.validator = config.schema;
|
|
72
|
+
this.context = config.schema.parse(config.context) as GraphContext<T>;
|
|
73
|
+
this._initialContext = structuredClone(this.context);
|
|
74
|
+
this.globalErrorHandler = config.onError;
|
|
75
|
+
this.eventEmitter =
|
|
76
|
+
config.eventEmitter || (new EventEmitter() as IEventEmitter);
|
|
77
|
+
this.graphEvents = config.events;
|
|
78
|
+
this.entryNode = config.entryNode;
|
|
79
|
+
this.verbose = options.verbose ?? false;
|
|
80
|
+
|
|
81
|
+
this.stateSubject = new BehaviorSubject<GraphContext<T>>(this.context);
|
|
82
|
+
|
|
83
|
+
this.logger = new GraphLogger(this.name, options.verbose);
|
|
84
|
+
this.eventManager = new GraphEventManager(
|
|
85
|
+
this.eventEmitter,
|
|
86
|
+
this.nodes,
|
|
87
|
+
this.name,
|
|
88
|
+
this.context,
|
|
89
|
+
config.events,
|
|
90
|
+
config.entryNode,
|
|
91
|
+
config.onError
|
|
92
|
+
);
|
|
93
|
+
this.nodeExecutor = new GraphNode(
|
|
94
|
+
this.nodes,
|
|
95
|
+
this.logger,
|
|
96
|
+
this.eventManager,
|
|
97
|
+
this.eventSubject,
|
|
98
|
+
this.stateSubject
|
|
99
|
+
);
|
|
100
|
+
|
|
101
|
+
this.setupEventStreams();
|
|
102
|
+
this.setupEventListeners();
|
|
103
|
+
this.setupGraphEventListeners();
|
|
104
|
+
|
|
105
|
+
this.observer = new GraphObserver(
|
|
106
|
+
this,
|
|
107
|
+
this.eventSubject,
|
|
108
|
+
this.stateSubject,
|
|
109
|
+
this.destroySubject,
|
|
110
|
+
this.eventManager
|
|
111
|
+
);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Sets up event listeners for node-based events
|
|
116
|
+
* @private
|
|
117
|
+
* @description Attaches all node-based event triggers while preserving external listeners
|
|
118
|
+
*/
|
|
119
|
+
private setupEventStreams(): void {
|
|
120
|
+
this.eventManager.on("nodeStarted", (data) => {
|
|
121
|
+
this.addLog(`Event: Node "${data.name}" started`);
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
this.eventManager.on("nodeCompleted", (data) => {
|
|
125
|
+
this.addLog(`Event: Node "${data.name}" completed`);
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
this.eventManager.on("nodeError", (data) => {
|
|
129
|
+
let errorMessage = "Unknown error";
|
|
130
|
+
if (data.error) {
|
|
131
|
+
errorMessage =
|
|
132
|
+
data.error instanceof Error
|
|
133
|
+
? data.error.message
|
|
134
|
+
: data.error.errors?.[0]?.message ||
|
|
135
|
+
data.error.message ||
|
|
136
|
+
"Unknown error";
|
|
137
|
+
}
|
|
138
|
+
this.addLog(`Event: Node "${data.name}" error: ${errorMessage}`);
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
this.eventManager.on("nodeStateChanged", (data) => {
|
|
142
|
+
this.addLog(`Event: Node "${data.name}" state changed`);
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Sets up event listeners for node-based events
|
|
148
|
+
* @private
|
|
149
|
+
* @description Attaches all node-based event triggers while preserving external listeners
|
|
150
|
+
*/
|
|
151
|
+
private setupEventListeners(): void {
|
|
152
|
+
this.eventManager.setupEventListeners();
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* Sets up event listeners for graph-based events
|
|
157
|
+
* @private
|
|
158
|
+
* @description Attaches all graph-based event triggers
|
|
159
|
+
*/
|
|
160
|
+
private setupGraphEventListeners(): void {
|
|
161
|
+
this.eventManager.setupGraphEventListeners();
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Executes a specific node in the graph
|
|
166
|
+
* @private
|
|
167
|
+
* @param {string} nodeName - Name of the node to execute
|
|
168
|
+
* @param {GraphContext<T>} context - Current execution context
|
|
169
|
+
* @param {boolean} triggeredByEvent - Whether the execution was triggered by an event
|
|
170
|
+
* @returns {Promise<void>}
|
|
171
|
+
*/
|
|
172
|
+
private async executeNode(
|
|
173
|
+
nodeName: string,
|
|
174
|
+
context: GraphContext<T>,
|
|
175
|
+
triggeredByEvent: boolean = false
|
|
176
|
+
): Promise<void> {
|
|
177
|
+
const node = this.nodes.get(nodeName);
|
|
178
|
+
if (!node) throw new Error(`Node "${nodeName}" not found`);
|
|
179
|
+
|
|
180
|
+
return this.nodeExecutor.executeNode(nodeName, context, triggeredByEvent);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
private addLog(message: string): void {
|
|
184
|
+
this.logger.addLog(message);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
public getLogs(): string[] {
|
|
188
|
+
return this.logger.getLogs();
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
public clearLogs(): void {
|
|
192
|
+
this.logger.clearLogs();
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* Get the observer instance for monitoring graph state and events
|
|
197
|
+
*/
|
|
198
|
+
public observe(
|
|
199
|
+
options: {
|
|
200
|
+
debounce?: number;
|
|
201
|
+
delay?: number;
|
|
202
|
+
stream?: boolean;
|
|
203
|
+
properties?: (string | number)[];
|
|
204
|
+
onStreamLetter?: (data: { letter: string; property: string }) => void;
|
|
205
|
+
onStreamComplete?: () => void;
|
|
206
|
+
} = {}
|
|
207
|
+
): GraphObservable<T> {
|
|
208
|
+
return this.observer.state(options) as GraphObservable<T>;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* Enable or disable verbose logging
|
|
213
|
+
* @param {boolean} enabled - Whether to enable verbose logging
|
|
214
|
+
*/
|
|
215
|
+
public setVerbose(enabled: boolean): void {
|
|
216
|
+
this.logger.setVerbose(enabled);
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* Get current verbose setting
|
|
221
|
+
* @returns {boolean} Current verbose setting
|
|
222
|
+
*/
|
|
223
|
+
public isVerbose(): boolean {
|
|
224
|
+
return this.logger.isVerbose();
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
* Executes the graph flow starting from a specific node
|
|
229
|
+
* @param {string} startNode - Name of the node to start execution from
|
|
230
|
+
* @param {Partial<GraphContext<T>>} context - Optional context to merge
|
|
231
|
+
* @returns {Promise<GraphContext<T>>} Final context after execution
|
|
232
|
+
*/
|
|
233
|
+
public async execute(
|
|
234
|
+
startNode: string,
|
|
235
|
+
context?: Partial<GraphContext<T>>
|
|
236
|
+
): Promise<GraphContext<T>> {
|
|
237
|
+
try {
|
|
238
|
+
if (context) {
|
|
239
|
+
const base = this._initialContext ? structuredClone(this._initialContext) : this.context;
|
|
240
|
+
const previousMessages = (this.context as any)?.messages;
|
|
241
|
+
const mergedContext = { ...base, ...context };
|
|
242
|
+
if (previousMessages && Array.isArray(previousMessages) && previousMessages.length > 0) {
|
|
243
|
+
(mergedContext as any).messages = previousMessages;
|
|
244
|
+
}
|
|
245
|
+
const validationResult = this.validator?.safeParse(mergedContext);
|
|
246
|
+
if (!validationResult?.success) {
|
|
247
|
+
const errors = validationResult?.error?.issues.map(
|
|
248
|
+
(err) => `${err.path.join(".")}: ${err.message}`
|
|
249
|
+
);
|
|
250
|
+
throw new Error(`Context validation failed: ${errors?.join(", ")}`);
|
|
251
|
+
}
|
|
252
|
+
this.context = validationResult.data as GraphContext<T>;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
this.eventEmitter.emit("graphStarted", { name: this.name });
|
|
256
|
+
|
|
257
|
+
const node = this.nodes.get(startNode);
|
|
258
|
+
if (!node) throw new Error(`Node "${startNode}" not found`);
|
|
259
|
+
|
|
260
|
+
await this.nodeExecutor.executeNode(startNode, this.context, false);
|
|
261
|
+
|
|
262
|
+
this.eventEmitter.emit("graphCompleted", {
|
|
263
|
+
name: this.name,
|
|
264
|
+
context: this.context,
|
|
265
|
+
});
|
|
266
|
+
|
|
267
|
+
return this.getContext();
|
|
268
|
+
} catch (error) {
|
|
269
|
+
this.eventEmitter.emit("graphError", { name: this.name, error });
|
|
270
|
+
this.globalErrorHandler?.(error as Error, this.context);
|
|
271
|
+
throw error;
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
/**
|
|
276
|
+
* Executes the graph flow with automatic checkpointing at each node
|
|
277
|
+
* @param startNode - Name of the node to start execution from
|
|
278
|
+
* @param adapter - Checkpoint persistence adapter
|
|
279
|
+
* @param config - Checkpoint configuration options
|
|
280
|
+
* @returns Execution result with final context and checkpoint ID
|
|
281
|
+
*/
|
|
282
|
+
public async executeWithCheckpoint(
|
|
283
|
+
startNode: string,
|
|
284
|
+
adapter: ICheckpointAdapter,
|
|
285
|
+
config: CheckpointConfig = {}
|
|
286
|
+
): Promise<{ context: GraphContext<T>; checkpointId: string }> {
|
|
287
|
+
const {
|
|
288
|
+
saveEveryNode = true,
|
|
289
|
+
saveOnComplete = true,
|
|
290
|
+
checkpointId = crypto.randomUUID(),
|
|
291
|
+
breakpoints = [],
|
|
292
|
+
runId,
|
|
293
|
+
initialContext,
|
|
294
|
+
} = config;
|
|
295
|
+
|
|
296
|
+
this._interrupted = false;
|
|
297
|
+
this._interruptCheckpoint = null;
|
|
298
|
+
this._checkpointCounter = 0;
|
|
299
|
+
this._breakpoints = new Set(breakpoints);
|
|
300
|
+
|
|
301
|
+
if (initialContext) {
|
|
302
|
+
const base = this._initialContext ? structuredClone(this._initialContext) : this.context;
|
|
303
|
+
const previousMessages = (this.context as any)?.messages;
|
|
304
|
+
const mergedContext = { ...base, ...initialContext };
|
|
305
|
+
if (previousMessages && Array.isArray(previousMessages) && previousMessages.length > 0) {
|
|
306
|
+
(mergedContext as any).messages = previousMessages;
|
|
307
|
+
}
|
|
308
|
+
const validationResult = this.validator?.safeParse(mergedContext);
|
|
309
|
+
if (!validationResult?.success) {
|
|
310
|
+
const errors = validationResult?.error?.issues.map(
|
|
311
|
+
(err) => `${err.path.join(".")}: ${err.message}`
|
|
312
|
+
);
|
|
313
|
+
throw new Error(`Context validation failed: ${errors?.join(", ")}`);
|
|
314
|
+
}
|
|
315
|
+
this.context = validationResult.data as GraphContext<T>;
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
if (this.context) {
|
|
319
|
+
const validationResult = this.validator?.safeParse(this.context);
|
|
320
|
+
if (!validationResult?.success) {
|
|
321
|
+
const errors = validationResult?.error?.issues.map(
|
|
322
|
+
(err) => `${err.path.join(".")}: ${err.message}`
|
|
323
|
+
);
|
|
324
|
+
throw new Error(`Context validation failed: ${errors?.join(", ")}`);
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
this.eventEmitter.emit("graphStarted", { name: this.name });
|
|
329
|
+
|
|
330
|
+
const runIdResolved = runId || crypto.randomUUID();
|
|
331
|
+
|
|
332
|
+
let hooks: NodeExecutionHooks<T> | undefined;
|
|
333
|
+
if (saveEveryNode) {
|
|
334
|
+
hooks = {
|
|
335
|
+
onBeforeExecute: async (nodeName, ctx) => {
|
|
336
|
+
const isBreakpoint = this._breakpoints.has(nodeName);
|
|
337
|
+
if (isBreakpoint) {
|
|
338
|
+
const cpId = `${checkpointId}-${++this._checkpointCounter}`;
|
|
339
|
+
const cp: Checkpoint<T> = {
|
|
340
|
+
id: cpId,
|
|
341
|
+
graphName: this.name,
|
|
342
|
+
runId: runIdResolved,
|
|
343
|
+
nodeName,
|
|
344
|
+
nextNodes: [nodeName],
|
|
345
|
+
context: structuredClone(ctx),
|
|
346
|
+
metadata: {
|
|
347
|
+
createdAt: Date.now(),
|
|
348
|
+
awaitingApproval: true,
|
|
349
|
+
},
|
|
350
|
+
};
|
|
351
|
+
this._interruptCheckpoint = cp;
|
|
352
|
+
await adapter.save(cp);
|
|
353
|
+
throw new CheckpointAwaitApprovalError(
|
|
354
|
+
`Awaiting approval at breakpoint "${nodeName}"`,
|
|
355
|
+
cpId
|
|
356
|
+
);
|
|
357
|
+
}
|
|
358
|
+
},
|
|
359
|
+
onBeforeExecuteNext: async (nodeName, ctx, nextNodes) => {
|
|
360
|
+
if (this._interrupted) {
|
|
361
|
+
const cpId = `${checkpointId}-${++this._checkpointCounter}`;
|
|
362
|
+
const cp: Checkpoint<T> = {
|
|
363
|
+
id: cpId,
|
|
364
|
+
graphName: this.name,
|
|
365
|
+
runId: runIdResolved,
|
|
366
|
+
nodeName,
|
|
367
|
+
nextNodes,
|
|
368
|
+
context: this.getContext(),
|
|
369
|
+
metadata: {
|
|
370
|
+
createdAt: Date.now(),
|
|
371
|
+
interrupted: true,
|
|
372
|
+
},
|
|
373
|
+
};
|
|
374
|
+
this._interruptCheckpoint = cp;
|
|
375
|
+
await adapter.save(cp);
|
|
376
|
+
throw new CheckpointInterruptError(
|
|
377
|
+
`Execution interrupted at node "${nodeName}"`,
|
|
378
|
+
cpId
|
|
379
|
+
);
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
const cpId = `${checkpointId}-${++this._checkpointCounter}`;
|
|
383
|
+
const cp: Checkpoint<T> = {
|
|
384
|
+
id: cpId,
|
|
385
|
+
graphName: this.name,
|
|
386
|
+
runId: runIdResolved,
|
|
387
|
+
nodeName,
|
|
388
|
+
nextNodes,
|
|
389
|
+
context: this.getContext(),
|
|
390
|
+
metadata: { createdAt: Date.now() },
|
|
391
|
+
};
|
|
392
|
+
await adapter.save(cp);
|
|
393
|
+
},
|
|
394
|
+
};
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
try {
|
|
398
|
+
const node = this.nodes.get(startNode);
|
|
399
|
+
if (!node) throw new Error(`Node "${startNode}" not found`);
|
|
400
|
+
|
|
401
|
+
await this.nodeExecutor.executeNode(
|
|
402
|
+
startNode,
|
|
403
|
+
this.context,
|
|
404
|
+
false,
|
|
405
|
+
hooks
|
|
406
|
+
);
|
|
407
|
+
|
|
408
|
+
if (saveOnComplete) {
|
|
409
|
+
const cpId = `${checkpointId}-${++this._checkpointCounter}`;
|
|
410
|
+
const cp: Checkpoint<T> = {
|
|
411
|
+
id: cpId,
|
|
412
|
+
graphName: this.name,
|
|
413
|
+
runId: runIdResolved,
|
|
414
|
+
nodeName: "__completed__",
|
|
415
|
+
nextNodes: [],
|
|
416
|
+
context: this.getContext(),
|
|
417
|
+
metadata: { createdAt: Date.now() },
|
|
418
|
+
};
|
|
419
|
+
await adapter.save(cp);
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
this.eventEmitter.emit("graphCompleted", {
|
|
423
|
+
name: this.name,
|
|
424
|
+
context: this.context,
|
|
425
|
+
});
|
|
426
|
+
|
|
427
|
+
return { context: this.getContext(), checkpointId };
|
|
428
|
+
} catch (error) {
|
|
429
|
+
if (
|
|
430
|
+
error instanceof CheckpointInterruptError ||
|
|
431
|
+
error instanceof CheckpointAwaitApprovalError
|
|
432
|
+
) {
|
|
433
|
+
this.eventEmitter.emit("graphError", { name: this.name, error });
|
|
434
|
+
throw error;
|
|
435
|
+
}
|
|
436
|
+
if (saveOnComplete) {
|
|
437
|
+
const cpId = `${checkpointId}-${++this._checkpointCounter}`;
|
|
438
|
+
const cp: Checkpoint<T> = {
|
|
439
|
+
id: cpId,
|
|
440
|
+
graphName: this.name,
|
|
441
|
+
runId: runIdResolved,
|
|
442
|
+
nodeName: "__error__",
|
|
443
|
+
nextNodes: [],
|
|
444
|
+
context: this.getContext(),
|
|
445
|
+
metadata: {
|
|
446
|
+
createdAt: Date.now(),
|
|
447
|
+
error: (error as Error).message,
|
|
448
|
+
},
|
|
449
|
+
};
|
|
450
|
+
await adapter.save(cp);
|
|
451
|
+
}
|
|
452
|
+
this.eventEmitter.emit("graphError", { name: this.name, error });
|
|
453
|
+
this.globalErrorHandler?.(error as Error, this.context);
|
|
454
|
+
throw error;
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
/**
|
|
459
|
+
* Resumes execution from a saved checkpoint
|
|
460
|
+
* @param checkpointId - ID of the checkpoint to resume from
|
|
461
|
+
* @param adapter - Checkpoint persistence adapter
|
|
462
|
+
* @returns Final context after execution
|
|
463
|
+
*/
|
|
464
|
+
public async resumeFromCheckpoint(
|
|
465
|
+
checkpointId: string,
|
|
466
|
+
adapter: ICheckpointAdapter,
|
|
467
|
+
contextModifications?: Partial<Record<string, any>>
|
|
468
|
+
): Promise<GraphContext<T>> {
|
|
469
|
+
const checkpoint = await adapter.load(checkpointId);
|
|
470
|
+
if (!checkpoint) {
|
|
471
|
+
throw new Error(`Checkpoint "${checkpointId}" not found`);
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
if (checkpoint.nodeName === "__completed__") {
|
|
475
|
+
return checkpoint.context as GraphContext<T>;
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
let resumeContext = checkpoint.context;
|
|
479
|
+
if (contextModifications) {
|
|
480
|
+
resumeContext = { ...checkpoint.context, ...contextModifications };
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
const validationResult = this.validator?.safeParse(resumeContext);
|
|
484
|
+
if (!validationResult?.success) {
|
|
485
|
+
const errors = validationResult?.error?.issues.map(
|
|
486
|
+
(err) => `${err.path.join(".")}: ${err.message}`
|
|
487
|
+
);
|
|
488
|
+
throw new Error(`Context validation failed: ${errors?.join(", ")}`);
|
|
489
|
+
}
|
|
490
|
+
this.context = validationResult.data as GraphContext<T>;
|
|
491
|
+
|
|
492
|
+
this.eventEmitter.emit("graphStarted", { name: this.name });
|
|
493
|
+
|
|
494
|
+
this._interrupted = false;
|
|
495
|
+
this._interruptCheckpoint = null;
|
|
496
|
+
this._checkpointCounter = 0;
|
|
497
|
+
|
|
498
|
+
const hooks: NodeExecutionHooks<T> = {
|
|
499
|
+
onBeforeExecuteNext: async (nodeName, ctx, nextNodes) => {
|
|
500
|
+
const cpId = `${checkpointId}-${++this._checkpointCounter}`;
|
|
501
|
+
if (this._interrupted) {
|
|
502
|
+
const cp: Checkpoint<T> = {
|
|
503
|
+
id: cpId,
|
|
504
|
+
graphName: this.name,
|
|
505
|
+
nodeName,
|
|
506
|
+
nextNodes,
|
|
507
|
+
context: this.getContext(),
|
|
508
|
+
metadata: { createdAt: Date.now(), interrupted: true },
|
|
509
|
+
};
|
|
510
|
+
this._interruptCheckpoint = cp;
|
|
511
|
+
await adapter.save(cp);
|
|
512
|
+
throw new CheckpointInterruptError(
|
|
513
|
+
`Execution interrupted at node "${nodeName}"`,
|
|
514
|
+
cpId
|
|
515
|
+
);
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
const cp: Checkpoint<T> = {
|
|
519
|
+
id: cpId,
|
|
520
|
+
graphName: this.name,
|
|
521
|
+
nodeName,
|
|
522
|
+
nextNodes,
|
|
523
|
+
context: this.getContext(),
|
|
524
|
+
metadata: { createdAt: Date.now() },
|
|
525
|
+
};
|
|
526
|
+
await adapter.save(cp);
|
|
527
|
+
},
|
|
528
|
+
};
|
|
529
|
+
|
|
530
|
+
try {
|
|
531
|
+
for (const nextNode of checkpoint.nextNodes) {
|
|
532
|
+
await this.nodeExecutor.executeNode(
|
|
533
|
+
nextNode,
|
|
534
|
+
this.context,
|
|
535
|
+
false,
|
|
536
|
+
hooks
|
|
537
|
+
);
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
const cpId = `${checkpointId}-${++this._checkpointCounter}`;
|
|
541
|
+
const cp: Checkpoint<T> = {
|
|
542
|
+
id: cpId,
|
|
543
|
+
graphName: this.name,
|
|
544
|
+
nodeName: "__completed__",
|
|
545
|
+
nextNodes: [],
|
|
546
|
+
context: this.getContext(),
|
|
547
|
+
metadata: { createdAt: Date.now() },
|
|
548
|
+
};
|
|
549
|
+
await adapter.save(cp);
|
|
550
|
+
|
|
551
|
+
this.eventEmitter.emit("graphCompleted", {
|
|
552
|
+
name: this.name,
|
|
553
|
+
context: this.context,
|
|
554
|
+
});
|
|
555
|
+
|
|
556
|
+
return this.getContext();
|
|
557
|
+
} catch (error) {
|
|
558
|
+
if (error instanceof CheckpointInterruptError) {
|
|
559
|
+
this.eventEmitter.emit("graphError", { name: this.name, error });
|
|
560
|
+
throw error;
|
|
561
|
+
}
|
|
562
|
+
const cpId = `${checkpointId}-${++this._checkpointCounter}`;
|
|
563
|
+
const cp: Checkpoint<T> = {
|
|
564
|
+
id: cpId,
|
|
565
|
+
graphName: this.name,
|
|
566
|
+
nodeName: "__error__",
|
|
567
|
+
nextNodes: [],
|
|
568
|
+
context: this.getContext(),
|
|
569
|
+
metadata: { createdAt: Date.now(), error: (error as Error).message },
|
|
570
|
+
};
|
|
571
|
+
await adapter.save(cp);
|
|
572
|
+
this.eventEmitter.emit("graphError", { name: this.name, error });
|
|
573
|
+
this.globalErrorHandler?.(error as Error, this.context);
|
|
574
|
+
throw error;
|
|
575
|
+
}
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
/**
|
|
579
|
+
* Interrupts the current execution and saves a checkpoint
|
|
580
|
+
*/
|
|
581
|
+
public interrupt(): void {
|
|
582
|
+
this._interrupted = true;
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
/**
|
|
586
|
+
* Lists all checkpoints for this graph
|
|
587
|
+
* @param adapter - Checkpoint persistence adapter
|
|
588
|
+
* @returns Array of checkpoints sorted by creation date (newest first)
|
|
589
|
+
*/
|
|
590
|
+
public async listCheckpoints(
|
|
591
|
+
adapter: ICheckpointAdapter
|
|
592
|
+
): Promise<Checkpoint<T>[]> {
|
|
593
|
+
return adapter.list(this.name);
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
/**
|
|
597
|
+
* Gets checkpoint history for a specific run
|
|
598
|
+
* @param runId - Run identifier
|
|
599
|
+
* @param adapter - Checkpoint persistence adapter
|
|
600
|
+
* @returns Checkpoints for the specified run, sorted newest first
|
|
601
|
+
*/
|
|
602
|
+
public async getCheckpointHistory(
|
|
603
|
+
runId: string,
|
|
604
|
+
adapter: ICheckpointAdapter
|
|
605
|
+
): Promise<Checkpoint<T>[]> {
|
|
606
|
+
const all = await adapter.list(this.name);
|
|
607
|
+
return all.filter((cp) => cp.runId === runId);
|
|
608
|
+
}
|
|
609
|
+
|
|
610
|
+
/**
|
|
611
|
+
* Emits an event to trigger event-based nodes
|
|
612
|
+
* @param {string} eventName - Name of the event to emit
|
|
613
|
+
* @param {Partial<GraphContext<T>>} data - Optional data to merge with context
|
|
614
|
+
* @returns {Promise<void>}
|
|
615
|
+
*/
|
|
616
|
+
public emit(
|
|
617
|
+
eventName: string,
|
|
618
|
+
data?: Partial<GraphContext<T>>
|
|
619
|
+
): Promise<void> {
|
|
620
|
+
const event: GraphEvent<T> = {
|
|
621
|
+
type: eventName,
|
|
622
|
+
payload: data,
|
|
623
|
+
timestamp: Date.now(),
|
|
624
|
+
};
|
|
625
|
+
this.eventSubject.next(event);
|
|
626
|
+
this.eventManager.emit(eventName, data);
|
|
627
|
+
return Promise.resolve();
|
|
628
|
+
}
|
|
629
|
+
|
|
630
|
+
/**
|
|
631
|
+
* Registers an event handler
|
|
632
|
+
* @param {string} eventName - Name of the event to listen for
|
|
633
|
+
* @param {Function} handler - Handler function to execute when event is emitted
|
|
634
|
+
*/
|
|
635
|
+
public on(eventName: string, handler: (...args: any[]) => void): void {
|
|
636
|
+
this.eventManager.on(eventName, handler);
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
/**
|
|
640
|
+
* Updates the graph definition with new configuration
|
|
641
|
+
* @param {GraphConfig<T>} definition - New graph definition
|
|
642
|
+
*/
|
|
643
|
+
public load(definition: GraphConfig<T>): void {
|
|
644
|
+
// Clear all existing nodes
|
|
645
|
+
this.nodes.clear();
|
|
646
|
+
|
|
647
|
+
// Wipe out old node-based event listeners
|
|
648
|
+
if (definition.nodes?.length) {
|
|
649
|
+
const allEvents = new Set<string>();
|
|
650
|
+
definition.nodes.forEach((n) =>
|
|
651
|
+
n.events?.forEach((evt) => allEvents.add(evt))
|
|
652
|
+
);
|
|
653
|
+
for (const evt of allEvents) {
|
|
654
|
+
this.eventEmitter.removeAllListeners(evt);
|
|
655
|
+
}
|
|
656
|
+
}
|
|
657
|
+
|
|
658
|
+
// Add in new nodes
|
|
659
|
+
definition.nodes.forEach((node) => this.nodes.set(node.name, node));
|
|
660
|
+
|
|
661
|
+
// Parse the new context
|
|
662
|
+
const validationResult = definition.schema.safeParse(definition.context);
|
|
663
|
+
if (!validationResult.success) {
|
|
664
|
+
const errors = validationResult.error.issues.map(
|
|
665
|
+
(err) => `${err.path.join(".")}: ${err.message}`
|
|
666
|
+
);
|
|
667
|
+
throw new Error(`Context validation failed: ${errors.join(", ")}`);
|
|
668
|
+
}
|
|
669
|
+
this.context = validationResult.data as GraphContext<T>;
|
|
670
|
+
this.validator = definition.schema;
|
|
671
|
+
|
|
672
|
+
// Store entry node and graph events
|
|
673
|
+
this.entryNode = definition.entryNode;
|
|
674
|
+
this.graphEvents = definition.events;
|
|
675
|
+
|
|
676
|
+
// Re-setup only node-based event triggers
|
|
677
|
+
for (const node of this.nodes.values()) {
|
|
678
|
+
if (node.events && node.events.length > 0) {
|
|
679
|
+
node.events.forEach((event) => {
|
|
680
|
+
this.eventEmitter.on(
|
|
681
|
+
event,
|
|
682
|
+
async (data?: Partial<GraphContext<T>>) => {
|
|
683
|
+
const freshContext = structuredClone(this.context);
|
|
684
|
+
if (data) Object.assign(freshContext, data);
|
|
685
|
+
await this.executeNode(node.name, freshContext, true);
|
|
686
|
+
}
|
|
687
|
+
);
|
|
688
|
+
});
|
|
689
|
+
}
|
|
690
|
+
}
|
|
691
|
+
|
|
692
|
+
// Re-setup graph event listeners
|
|
693
|
+
this.setupGraphEventListeners();
|
|
694
|
+
}
|
|
695
|
+
|
|
696
|
+
/**
|
|
697
|
+
* Gets a copy of the current context
|
|
698
|
+
* @returns {GraphContext<T>} A deep copy of the current context
|
|
699
|
+
*/
|
|
700
|
+
public getContext(): GraphContext<T> {
|
|
701
|
+
return structuredClone(this.context);
|
|
702
|
+
}
|
|
703
|
+
|
|
704
|
+
/**
|
|
705
|
+
* Logs a message with optional data
|
|
706
|
+
* @param {string} message - Message to log
|
|
707
|
+
* @param {any} data - Optional data to log
|
|
708
|
+
*/
|
|
709
|
+
public log(message: string, data?: any): void {
|
|
710
|
+
this.logger.log(message, data);
|
|
711
|
+
}
|
|
712
|
+
|
|
713
|
+
/**
|
|
714
|
+
* Adds a new node to the graph
|
|
715
|
+
* @param {GraphNodeConfig<T, any>} node - Node to add
|
|
716
|
+
* @throws {Error} If node with same name already exists
|
|
717
|
+
*/
|
|
718
|
+
public addNode(node: GraphNodeConfig<T, any>): void {
|
|
719
|
+
this.nodes.set(node.name, node);
|
|
720
|
+
this.eventManager.setupEventListeners();
|
|
721
|
+
}
|
|
722
|
+
|
|
723
|
+
/**
|
|
724
|
+
* Removes a node from the graph
|
|
725
|
+
* @param {string} nodeName - Name of the node to remove
|
|
726
|
+
*/
|
|
727
|
+
public removeNode(nodeName: string): void {
|
|
728
|
+
this.nodes.delete(nodeName);
|
|
729
|
+
this.eventManager.setupEventListeners();
|
|
730
|
+
}
|
|
731
|
+
|
|
732
|
+
/**
|
|
733
|
+
* Returns all nodes in the graph
|
|
734
|
+
* @returns {Node<T>[]} Array of all nodes
|
|
735
|
+
*/
|
|
736
|
+
public getNodes(): GraphNodeConfig<T, any>[] {
|
|
737
|
+
return Array.from(this.nodes.values());
|
|
738
|
+
}
|
|
739
|
+
|
|
740
|
+
/**
|
|
741
|
+
* Cleanup resources
|
|
742
|
+
*/
|
|
743
|
+
public destroy(): void {
|
|
744
|
+
this.destroySubject.next();
|
|
745
|
+
this.destroySubject.complete();
|
|
746
|
+
this.eventSubject.complete();
|
|
747
|
+
this.stateSubject.complete();
|
|
748
|
+
}
|
|
749
|
+
|
|
750
|
+
/**
|
|
751
|
+
* Creates a visualizer instance for the current graph
|
|
752
|
+
* @returns {GraphVisualizer<T>} A visualizer instance
|
|
753
|
+
*/
|
|
754
|
+
public createVisualizer(): GraphVisualizer<T> {
|
|
755
|
+
return new GraphVisualizer(this.nodes);
|
|
756
|
+
}
|
|
757
|
+
|
|
758
|
+
/**
|
|
759
|
+
* Gets the schema for the current graph
|
|
760
|
+
* @returns {T} The schema for the current graph
|
|
761
|
+
*/
|
|
762
|
+
public getSchema(): T {
|
|
763
|
+
return this.validator as T;
|
|
764
|
+
}
|
|
765
|
+
|
|
766
|
+
/**
|
|
767
|
+
* Processes natural language input using a specific NLP node
|
|
768
|
+
* @param {string} text - The input text to process
|
|
769
|
+
* @param {string} nodeName - The name of the NLP node to use
|
|
770
|
+
* @returns {Promise<GraphContext<T>>} The result of the NLP node execution
|
|
771
|
+
*/
|
|
772
|
+
public async processNaturalLanguage(text: string, nodeName: string) {
|
|
773
|
+
const node = this.nlpNodes.get(nodeName);
|
|
774
|
+
if (!node) {
|
|
775
|
+
throw new Error(`NLP node "${nodeName}" not found`);
|
|
776
|
+
}
|
|
777
|
+
|
|
778
|
+
return this.execute(nodeName, { input: text });
|
|
779
|
+
}
|
|
780
|
+
}
|
|
781
|
+
|
|
782
|
+
export class CheckpointInterruptError extends Error {
|
|
783
|
+
constructor(
|
|
784
|
+
message: string,
|
|
785
|
+
public readonly checkpointId: string
|
|
786
|
+
) {
|
|
787
|
+
super(message);
|
|
788
|
+
this.name = "CheckpointInterruptError";
|
|
789
|
+
}
|
|
790
|
+
}
|
|
791
|
+
|
|
792
|
+
export class CheckpointAwaitApprovalError extends Error {
|
|
793
|
+
constructor(
|
|
794
|
+
message: string,
|
|
795
|
+
public readonly checkpointId: string
|
|
796
|
+
) {
|
|
797
|
+
super(message);
|
|
798
|
+
this.name = "CheckpointAwaitApprovalError";
|
|
799
|
+
}
|
|
800
|
+
}
|