@picoflow/ezgraph 0.0.6 → 0.0.8

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 (60) hide show
  1. package/README.md +247 -86
  2. package/dist/framework/base-graph.js +1 -1
  3. package/dist/framework/conversation-node.js +1 -1
  4. package/dist/framework/conversation-runner.js +1 -1
  5. package/dist/framework/decision/decision-node.js +1 -0
  6. package/dist/framework/decision/decision-provider.js +1 -0
  7. package/dist/framework/decision/decision-runner.js +1 -0
  8. package/dist/framework/decision/decision-types.js +1 -0
  9. package/dist/framework/decision/decision-validation.js +1 -0
  10. package/dist/framework/decision/typesafe-provider.js +1 -0
  11. package/dist/framework/graph-engine.js +1 -1
  12. package/dist/framework/graph-node.js +1 -1
  13. package/dist/framework/graph-state.js +1 -1
  14. package/dist/framework/langchain-llm-gateway.js +1 -1
  15. package/dist/framework/langchain-provider.adapter.js +1 -1
  16. package/dist/framework/node-invocation.js +1 -0
  17. package/dist/framework/node-outcome.js +1 -1
  18. package/dist/framework/node-state.js +1 -1
  19. package/dist/framework/persistence/session-manager.js +1 -1
  20. package/dist/framework/session-log.js +1 -1
  21. package/dist/framework/state-graph-ext.js +1 -1
  22. package/dist/framework/tool-response.js +1 -0
  23. package/dist/index.js +1 -1
  24. package/dist/testing/scripted-decisions.js +1 -0
  25. package/dist/testing/turn-harness.js +1 -1
  26. package/dist/testing.js +1 -1
  27. package/dist/types/npmlib/src/index.d.ts +11 -5
  28. package/dist/types/npmlib/src/testing.d.ts +1 -0
  29. package/dist/types/src/framework/base-graph.d.ts +28 -14
  30. package/dist/types/src/framework/conversation-node.d.ts +9 -15
  31. package/dist/types/src/framework/conversation-runner.d.ts +9 -9
  32. package/dist/types/src/framework/decision/decision-node.d.ts +17 -0
  33. package/dist/types/src/framework/decision/decision-provider.d.ts +14 -0
  34. package/dist/types/src/framework/decision/decision-runner.d.ts +18 -0
  35. package/dist/types/src/framework/decision/decision-types.d.ts +126 -0
  36. package/dist/types/src/framework/decision/decision-validation.d.ts +4 -0
  37. package/dist/types/src/framework/decision/typesafe-provider.d.ts +12 -0
  38. package/dist/types/src/framework/graph-engine.d.ts +4 -0
  39. package/dist/types/src/framework/graph-llm.config.d.ts +3 -3
  40. package/dist/types/src/framework/graph-node.d.ts +51 -36
  41. package/dist/types/src/framework/graph-registry.d.ts +10 -5
  42. package/dist/types/src/framework/graph-state-support.d.ts +1 -1
  43. package/dist/types/src/framework/graph-state.d.ts +6 -5
  44. package/dist/types/src/framework/langchain-provider.adapter.d.ts +2 -2
  45. package/dist/types/src/framework/llm-gateway.d.ts +4 -4
  46. package/dist/types/src/framework/model-stop-reason.d.ts +2 -2
  47. package/dist/types/src/framework/node-invocation.d.ts +12 -0
  48. package/dist/types/src/framework/node-outcome.d.ts +3 -32
  49. package/dist/types/src/framework/node-state.d.ts +3 -2
  50. package/dist/types/src/framework/openai-auth-provider.d.ts +1 -1
  51. package/dist/types/src/framework/persistence/session-manager.d.ts +4 -0
  52. package/dist/types/src/framework/session-log.d.ts +30 -0
  53. package/dist/types/src/framework/state-graph-ext.d.ts +4 -10
  54. package/dist/types/src/framework/token-usage.d.ts +2 -2
  55. package/dist/types/src/framework/tool-response.d.ts +29 -0
  56. package/dist/types/src/testing/scripted-decisions.d.ts +24 -0
  57. package/dist/types/src/testing/turn-harness.d.ts +2 -0
  58. package/package.json +11 -7
  59. package/dist/framework/conversation-tool-result.js +0 -1
  60. package/dist/types/src/framework/conversation-tool-result.d.ts +0 -19
@@ -1,24 +1,29 @@
1
- import { type GraphLlmConfig } from './graph-llm.config.js';
2
- import { HumanMessage } from '@langchain/core/messages';
3
- import type { LlmGateway } from './llm-gateway.js';
4
- import { GraphNode, GraphNodeRuntime } from './graph-node.js';
5
- import type { GraphState } from './graph-state.js';
6
- import { StateGraphExt, type GraphNodeClass } from './state-graph-ext.js';
7
- import type { StateDefinitionInit } from '@langchain/langgraph';
8
- import type { SessionDocument } from './persistence/session-manager.js';
9
- import { type ConversationPolicy } from './conversation-runner.js';
1
+ import { type GraphLlmConfig } from "./graph-llm.config.js";
2
+ import { HumanMessage } from "@langchain/core/messages";
3
+ import type { LlmGateway } from "./llm-gateway.js";
4
+ import { GraphNode, GraphNodeRuntime, type GraphNodeResponse } from "./graph-node.js";
5
+ import type { GraphState } from "./graph-state.js";
6
+ import { StateGraphExt, type GraphNodeClass } from "./state-graph-ext.js";
7
+ import type { StateDefinitionInit } from "@langchain/langgraph";
8
+ import type { SessionDocument } from "./persistence/session-manager.js";
9
+ import { type ConversationPolicy } from "./conversation-runner.js";
10
+ import type { GraphNodeLocalState, GraphNodeTarget } from "./node-outcome.js";
11
+ import type { DecisionOptions, DecisionErrorContext, DecisionProviderAdapter } from "./decision/decision-types.js";
10
12
  export type HistorySpace = readonly [GraphNodeClass, string];
11
13
  export type GraphSchemaMigration<State extends GraphState = GraphState> = Readonly<{
12
14
  from: number;
13
15
  migrate(sessionDoc: SessionDocument<State>): SessionDocument<State> | Promise<SessionDocument<State>>;
14
16
  }>;
15
- export type GraphDefinition<NodeId extends string = string, State extends GraphState = GraphState> = Readonly<{
17
+ export type GraphDefinition<NodeId extends string = string, State extends GraphState = GraphState & {
18
+ decisionUsage: NonNullable<GraphState["decisionUsage"]>;
19
+ }> = Readonly<{
16
20
  llmConfig: GraphLlmConfig;
21
+ decisionConfig?: DecisionOptions;
17
22
  endNode: NodeId;
18
23
  schemaVersion?: number;
19
24
  migrations?: readonly GraphSchemaMigration<State>[];
20
25
  requiresUserMessage?: boolean;
21
- responseMode?: 'chat' | 'json';
26
+ responseMode?: "chat" | "json";
22
27
  historySpaces?: readonly HistorySpace[];
23
28
  initialHistorySpace?: string;
24
29
  maxAgentRounds?: number;
@@ -42,7 +47,7 @@ export declare abstract class BaseGraph<State extends GraphState> {
42
47
  readonly schemaVersion: number;
43
48
  readonly llmConfig: GraphLlmConfig;
44
49
  readonly requiresUserMessage: boolean;
45
- readonly responseMode: 'chat' | 'json';
50
+ readonly responseMode: "chat" | "json";
46
51
  readonly maxAgentRounds: number;
47
52
  readonly conversationPolicy: ConversationPolicy;
48
53
  private compiledGraph?;
@@ -50,16 +55,25 @@ export declare abstract class BaseGraph<State extends GraphState> {
50
55
  private readonly nodeMap;
51
56
  private readonly endNode;
52
57
  private readonly migrations;
53
- protected constructor(llmGateway: LlmGateway, definition: GraphDefinition<State['currentNode'], State>);
58
+ protected constructor(llmGateway: LlmGateway, definition: GraphDefinition<State["currentNode"], State>);
59
+ protected onDecisionError(_context: DecisionErrorContext<State>): GraphNodeResponse<State> | null | Promise<GraphNodeResponse<State> | null>;
60
+ attachDecisionProviderResolver(resolve: (id: string) => DecisionProviderAdapter): void;
54
61
  get graph(): {
55
62
  invoke(input: unknown): Promise<State>;
63
+ stream(input: unknown, options?: {
64
+ streamMode?: "values";
65
+ }): Promise<AsyncIterable<State>>;
56
66
  };
57
67
  prepareInput(state: State | undefined, message: HumanMessage): Partial<State>;
68
+ saveNodeState<NodeClass extends GraphNodeTarget>(NodeClass: NodeClass, patch: Partial<GraphNodeLocalState<NodeClass>>): void;
58
69
  restoreSessionDoc(sessionDoc: SessionDocument<State>): Promise<SessionDocument<State> | null>;
59
70
  protected onRestoreSessionDoc(sessionDoc: SessionDocument<State>): Promise<SessionDocument<State> | null>;
60
- protected idleMs(sessionDoc: Pick<SessionDocument, 'modifiedAt'>): number;
71
+ protected idleMs(sessionDoc: Pick<SessionDocument, "modifiedAt">): number;
61
72
  protected abstract buildGraph(): {
62
73
  invoke(input: unknown): Promise<State>;
74
+ stream(input: unknown, options?: {
75
+ streamMode?: "values";
76
+ }): Promise<AsyncIterable<State>>;
63
77
  };
64
78
  protected createStateGraph<StateDefinition extends StateDefinitionInit>(state: StateDefinition): StateGraphExt<StateDefinition>;
65
79
  private createNode;
@@ -1,18 +1,12 @@
1
- import type { ConversationRunResult, ConversationToolResult } from './conversation-runner.js';
2
- import { GraphNode, type GraphNodeUpdate, type NodeOutcomeBuilder } from './graph-node.js';
3
- import type { GraphState } from './graph-state.js';
4
- export type ConversationNodeRunResult = ConversationRunResult & {
5
- quitRequested: boolean;
6
- };
7
- export declare abstract class ConversationNode<State extends GraphState, LocalState extends object = Record<string, never>, Context extends object = Record<string, never>> extends GraphNode<State, LocalState, Context> {
8
- private readonly quitRequests;
9
- readonly supportsAutomaticOutcomeRouting = true;
10
- protected abstract createContext(state: State): Context;
11
- protected abstract nextStep(state: State, context: Context, conversation: ConversationNodeRunResult): GraphNodeUpdate<State> | Promise<GraphNodeUpdate<State>>;
1
+ import type { ConversationRunResult } from "./conversation-runner.js";
2
+ import { GraphNode, type GraphNodeResult } from "./graph-node.js";
3
+ import type { GraphState } from "./graph-state.js";
4
+ import { type ToolResponse } from "./tool-response.js";
5
+ export type ConversationNodeRunResult = ConversationRunResult;
6
+ export declare abstract class ConversationNode<State extends GraphState> extends GraphNode<State> {
12
7
  protected endChat(input: {
13
8
  message?: string;
14
- }, context: Context): Promise<ConversationToolResult>;
15
- protected quit(conversation: ConversationRunResult): NodeOutcomeBuilder<State, LocalState>;
16
- run(state: State): Promise<GraphNodeUpdate<State>>;
17
- protected runConversation(state: State, context: Context): Promise<ConversationNodeRunResult>;
9
+ }): Promise<ToolResponse>;
10
+ run(state: State): Promise<GraphNodeResult<State>>;
11
+ private resolveToolResponse;
18
12
  }
@@ -1,16 +1,16 @@
1
- import { type BaseMessage } from '@langchain/core/messages';
2
- import type { ToolCall } from '@langchain/core/messages/tool';
3
- import type { GraphLlmConfig } from './graph-llm.config.js';
4
- import type { LlmCallOptions, LlmGateway, LlmGatewayTool } from './llm-gateway.js';
5
- import { type TokenUsage } from './token-usage.js';
6
- import type { ConversationToolResult } from './conversation-tool-result.js';
7
- import { type ModelStopReason } from './model-stop-reason.js';
8
- export type { ConversationToolResult } from './conversation-tool-result.js';
1
+ import { type BaseMessage } from "@langchain/core/messages";
2
+ import type { ToolCall } from "@langchain/core/messages/tool";
3
+ import type { GraphLlmConfig } from "./graph-llm.config.js";
4
+ import type { LlmCallOptions, LlmGateway, LlmGatewayTool } from "./llm-gateway.js";
5
+ import { type TokenUsage } from "./token-usage.js";
6
+ import { type ToolResponse } from "./tool-response.js";
7
+ import { type ModelStopReason } from "./model-stop-reason.js";
9
8
  export type ConversationRunResult = {
10
9
  messages: BaseMessage[];
11
10
  usage: TokenUsage;
12
11
  response?: string;
13
12
  stoppedAfterTool: boolean;
13
+ toolResponse?: ToolResponse;
14
14
  stopReason?: ModelStopReason;
15
15
  };
16
16
  export declare class EmptyModelResponseError extends Error {
@@ -40,7 +40,7 @@ export declare class ConversationRunner {
40
40
  history: readonly BaseMessage[];
41
41
  tools: readonly LlmGatewayTool[];
42
42
  llmConfig: GraphLlmConfig;
43
- executeTool: (call: ToolCall) => Promise<ConversationToolResult>;
43
+ executeTool: (call: ToolCall) => Promise<ToolResponse>;
44
44
  maxAgentRounds?: number;
45
45
  emptyHistorySeed?: string | null;
46
46
  emptyResponseRecovery?: EmptyResponseRecovery | null;
@@ -0,0 +1,17 @@
1
+ import type { ConversationRunResult } from "../conversation-runner.js";
2
+ import { GraphNode, type GraphNodeResponse, type GraphNodeResult } from "../graph-node.js";
3
+ import type { GraphState } from "../graph-state.js";
4
+ import { type DecisionAnswers, type DecisionContext, type DecisionEvidence, type DecisionErrorContext, type DecisionOptions, type DecisionQuestionMap } from "./decision-types.js";
5
+ export declare abstract class DecisionNode<State extends GraphState, Questions extends DecisionQuestionMap = DecisionQuestionMap, LocalState extends object = Record<string, unknown>> extends GraphNode<State, LocalState> {
6
+ abstract defineQuestions(state: State): Questions;
7
+ getPrompt(_state: State): string;
8
+ protected getDecisionEvidence(_state: State): DecisionEvidence;
9
+ getDecisionConfig(): DecisionOptions;
10
+ abstract onDecision(answers: DecisionAnswers<Questions>, context: DecisionContext, state: State): GraphNodeResponse<State> | Promise<GraphNodeResponse<State>>;
11
+ protected onDecisionError(_context: DecisionErrorContext<State>): GraphNodeResponse<State> | null | Promise<GraphNodeResponse<State> | null>;
12
+ run(state: State): Promise<GraphNodeResult<State>>;
13
+ validateTools(): void;
14
+ private assertNoChatConfiguration;
15
+ protected usesChatModel(): boolean;
16
+ protected runConversation(_state: State, _context: Record<string, unknown>): Promise<ConversationRunResult>;
17
+ }
@@ -0,0 +1,14 @@
1
+ import { type DecisionProviderAdapter } from "./decision-types.js";
2
+ import { type TypeSafeProviderOptions } from "./typesafe-provider.js";
3
+ export type BuiltinDecisionProviderConfigs = Readonly<{
4
+ typesafe?: TypeSafeProviderOptions | undefined;
5
+ }>;
6
+ export declare class DecisionProvider {
7
+ private constructor();
8
+ static create(configs: BuiltinDecisionProviderConfigs): readonly DecisionProviderAdapter[];
9
+ }
10
+ export declare class DecisionProviderRegistry {
11
+ private readonly providers;
12
+ constructor(adapters?: readonly DecisionProviderAdapter[]);
13
+ resolve(id: string): DecisionProviderAdapter;
14
+ }
@@ -0,0 +1,18 @@
1
+ import type { GraphState } from "../graph-state.js";
2
+ import type { GraphNodeResult } from "../graph-node.js";
3
+ import { type DecisionAnswers, type DecisionContext, type DecisionConversation, type DecisionErrorContext, type DecisionProviderAdapter, type DecisionQuestionMap, type DecisionState, type ResolvedDecisionOptions } from "./decision-types.js";
4
+ export type DecisionRunOptions<State extends GraphState, Questions extends DecisionQuestionMap> = Readonly<{
5
+ nodeId: string;
6
+ state: State;
7
+ conversation: DecisionConversation;
8
+ providerState: DecisionState;
9
+ questions: Questions;
10
+ provider: DecisionProviderAdapter;
11
+ options: ResolvedDecisionOptions;
12
+ callerSignal?: AbortSignal | undefined;
13
+ onDecision(answers: DecisionAnswers<Questions>, context: DecisionContext, state: State): GraphNodeResult<State> | Promise<GraphNodeResult<State>>;
14
+ onError(context: DecisionErrorContext<State>): GraphNodeResult<State> | Promise<GraphNodeResult<State>>;
15
+ }>;
16
+ export declare class DecisionRunner {
17
+ static run<State extends GraphState, Questions extends DecisionQuestionMap>(run: DecisionRunOptions<State, Questions>): Promise<GraphNodeResult<State>>;
18
+ }
@@ -0,0 +1,126 @@
1
+ import type { GraphState } from "../graph-state.js";
2
+ export type JsonPrimitive = string | number | boolean | null;
3
+ export type JsonValue = JsonPrimitive | readonly JsonValue[] | {
4
+ readonly [key: string]: JsonValue;
5
+ };
6
+ export type JsonObject = Readonly<Record<string, JsonValue>>;
7
+ export type DecisionState = string | JsonObject | readonly JsonValue[];
8
+ export type DecisionConversation = Readonly<{
9
+ request: string;
10
+ priorRequests: readonly string[];
11
+ }>;
12
+ export type DecisionEvidence = JsonObject;
13
+ export type Choice = Readonly<{
14
+ type: "choice";
15
+ criteria: Readonly<Record<string, JsonValue>>;
16
+ instructions?: DecisionState;
17
+ }>;
18
+ export type Score = Readonly<{
19
+ type: "score";
20
+ criteria: readonly JsonValue[];
21
+ instructions?: DecisionState;
22
+ }>;
23
+ export type Noul = Readonly<{
24
+ type: "noul";
25
+ instructions?: DecisionState;
26
+ criteria?: Readonly<{
27
+ true?: JsonValue;
28
+ false?: JsonValue;
29
+ }>;
30
+ }>;
31
+ export type DecisionQuestion = Choice | Score | Noul;
32
+ export type DecisionQuestionMap = Readonly<Record<string, DecisionQuestion>>;
33
+ export type ChoiceAnswer<Label extends string = string> = {
34
+ type: "choice";
35
+ choice: Label;
36
+ probabilities: Record<Label, number>;
37
+ confidence: number;
38
+ };
39
+ export type ScoreAnswer = {
40
+ type: "score";
41
+ score: number;
42
+ legend: Record<string, JsonValue>;
43
+ probabilities: Record<string, number>;
44
+ confidence: number;
45
+ };
46
+ export type NoulAnswer = {
47
+ type: "noul";
48
+ noul: number;
49
+ };
50
+ export type DecisionAnswer = ChoiceAnswer | ScoreAnswer | NoulAnswer;
51
+ type AnswerFor<Question extends DecisionQuestion> = Question extends Choice ? ChoiceAnswer<Extract<keyof Question["criteria"], string>> : Question extends Score ? ScoreAnswer : NoulAnswer;
52
+ export type DecisionAnswers<Questions extends DecisionQuestionMap> = {
53
+ -readonly [Key in keyof Questions]: AnswerFor<Questions[Key]>;
54
+ };
55
+ export type DecisionTokenUsage = Readonly<{
56
+ inputTokens?: number;
57
+ outputTokens?: number;
58
+ }>;
59
+ export type DecisionUsage = {
60
+ calls: number;
61
+ inputTokens: number;
62
+ outputTokens: number;
63
+ totalTokens: number;
64
+ };
65
+ export declare function emptyDecisionUsage(): DecisionUsage;
66
+ export declare function normalizeDecisionUsage(usage?: Partial<DecisionUsage>): DecisionUsage;
67
+ export declare function addDecisionUsage(current: DecisionUsage | undefined, addition: DecisionUsage | undefined): DecisionUsage;
68
+ export declare function decisionUsage(usage?: DecisionTokenUsage): DecisionUsage;
69
+ export type DecisionOptions = Readonly<{
70
+ provider?: string;
71
+ model?: string;
72
+ timeoutMs?: number;
73
+ maxRetries?: number;
74
+ }>;
75
+ export type ResolvedDecisionOptions = Required<DecisionOptions>;
76
+ export declare const DEFAULT_DECISION_OPTIONS: ResolvedDecisionOptions;
77
+ export declare function resolveDecisionOptions(defaults?: DecisionOptions, overrides?: DecisionOptions): ResolvedDecisionOptions;
78
+ export type DecisionRequest = Readonly<{
79
+ model: string;
80
+ state: DecisionState;
81
+ questions: DecisionQuestionMap;
82
+ }>;
83
+ export type DecisionCallOptions = Readonly<{
84
+ signal: AbortSignal;
85
+ timeoutMs: number;
86
+ }>;
87
+ export type DecisionResult = Readonly<{
88
+ model: string;
89
+ answers: Record<string, DecisionAnswer>;
90
+ usage?: DecisionTokenUsage;
91
+ requestId?: string;
92
+ }>;
93
+ export type DecisionProviderAdapter = Readonly<{
94
+ id: string;
95
+ decide(input: DecisionRequest, options: DecisionCallOptions): Promise<DecisionResult>;
96
+ shouldRetry?(error: Error): boolean;
97
+ }>;
98
+ export type DecisionMetadata = Readonly<{
99
+ provider: string;
100
+ model: string;
101
+ durationMs: number;
102
+ attempts: number;
103
+ usage: DecisionTokenUsage;
104
+ requestId?: string;
105
+ }>;
106
+ export type DecisionContext = DecisionMetadata & DecisionConversation;
107
+ export type DecisionFailure = "configuration" | "provider" | "timeout" | "validation";
108
+ export type DecisionErrorContext<State extends GraphState = GraphState> = Readonly<{
109
+ nodeId: string;
110
+ provider: string;
111
+ model: string;
112
+ failure: DecisionFailure;
113
+ attempts: number;
114
+ error: Error;
115
+ state: Readonly<State>;
116
+ }>;
117
+ export declare class DecisionValidationError extends Error {
118
+ constructor(message: string);
119
+ }
120
+ export declare class DecisionConfigurationError extends Error {
121
+ constructor(message: string);
122
+ }
123
+ export declare class DecisionTimeoutError extends Error {
124
+ constructor(message?: string);
125
+ }
126
+ export {};
@@ -0,0 +1,4 @@
1
+ import { type DecisionQuestionMap, type DecisionResult } from "./decision-types.js";
2
+ export declare function assertJsonCompatible(value: unknown, label: string): void;
3
+ export declare function validateDecisionQuestions(questions: DecisionQuestionMap): void;
4
+ export declare function validateDecisionResult(result: DecisionResult, questions: DecisionQuestionMap): void;
@@ -0,0 +1,12 @@
1
+ import { type DecisionCallOptions, type DecisionProviderAdapter, type DecisionRequest, type DecisionResult } from "./decision-types.js";
2
+ export type TypeSafeProviderOptions = Readonly<{
3
+ apiKey?: string | undefined;
4
+ fetch?: typeof fetch | undefined;
5
+ }>;
6
+ export declare class TypeSafeClassifierAdapter implements DecisionProviderAdapter {
7
+ private readonly options;
8
+ readonly id = "typesafe";
9
+ constructor(options?: TypeSafeProviderOptions);
10
+ decide(input: DecisionRequest, options: DecisionCallOptions): Promise<DecisionResult>;
11
+ shouldRetry(error: Error): boolean;
12
+ }
@@ -5,6 +5,7 @@ import type { GraphState } from "./graph-state.js";
5
5
  import type { RegisteredGraph } from "./graph-registry.js";
6
6
  import type { RegisteredModelProviderAdapter } from "./model-provider.js";
7
7
  import { SessionManager, type SessionDocument } from "./persistence/session-manager.js";
8
+ import type { DecisionProviderAdapter } from "./decision/decision-types.js";
8
9
  export type GraphConstructor = {
9
10
  new (llmGateway: LlmGateway): RegisteredGraph;
10
11
  getGraphDefinition(): GraphDefinition;
@@ -14,12 +15,14 @@ export type GraphEngineOptions = Readonly<{
14
15
  llmGatewayFactory?: LlmGatewayFactory;
15
16
  graphs?: readonly GraphConstructor[];
16
17
  providers?: readonly RegisteredModelProviderAdapter[];
18
+ decisionProviders?: readonly DecisionProviderAdapter[];
17
19
  }>;
18
20
  export type GraphEngineCreateOptions = Readonly<{
19
21
  configManager?: ConfigManager;
20
22
  llmGatewayFactory?: LlmGatewayFactory;
21
23
  graphs?: readonly GraphConstructor[];
22
24
  providers?: readonly RegisteredModelProviderAdapter[];
25
+ decisionProviders?: readonly DecisionProviderAdapter[];
23
26
  }>;
24
27
  export type RunResult = {
25
28
  status: number;
@@ -38,6 +41,7 @@ export declare class GraphEngine {
38
41
  private readonly registry;
39
42
  private readonly sessions;
40
43
  private readonly llmGatewayFactory;
44
+ private readonly decisionProviders;
41
45
  private readonly inflightSessions;
42
46
  constructor(options?: GraphEngineOptions);
43
47
  static create(options?: GraphEngineCreateOptions): Promise<GraphEngine>;
@@ -1,6 +1,6 @@
1
- import type { ModelProfile } from '@langchain/core/language_models/profile';
2
- import { type GraphLlmConfig, type GraphLlmFamily, type GraphLlmParameters } from './model-catalog.js';
3
- export { BUILT_IN_MODEL_CATALOG, GRAPH_LLM_CAPABILITIES, GRAPH_LLM_FAMILIES, GRAPH_LLM_PROVIDERS, ModelCatalog, ModelProviderRegistry, type AnthropicChatParameters, type AnthropicThinkingParameters, type BasicChatParameters, type BuiltInGraphLlmConfig, type BuiltInModelId, type BuiltInModelParameters, type CommonModelParameters, type GoogleChatParameters, type GraphLlmCapability, type GraphLlmConfig, type GraphLlmFamily, type GraphLlmParameters, type GraphLlmProvider, type GraphLlmRequiredCapabilities, type ModelCatalogDocument, type ModelParameterProfile, type ModelProviderAdapter, type ModelProviderInitialization, type OpenAIAuthReasoningParameters, type OpenAIChatParameters, type OpenAIReasoningParameters, type ResolvedModelDescriptor, type RuntimeGraphLlmConfig, } from './model-catalog.js';
1
+ import type { ModelProfile } from "@langchain/core/language_models/profile";
2
+ import { type GraphLlmConfig, type GraphLlmFamily, type GraphLlmParameters } from "./model-catalog.js";
3
+ export { BUILT_IN_MODEL_CATALOG, GRAPH_LLM_CAPABILITIES, GRAPH_LLM_FAMILIES, GRAPH_LLM_PROVIDERS, ModelCatalog, ModelProviderRegistry, type AnthropicChatParameters, type AnthropicThinkingParameters, type BasicChatParameters, type BuiltInGraphLlmConfig, type BuiltInModelId, type BuiltInModelParameters, type CommonModelParameters, type GoogleChatParameters, type GraphLlmCapability, type GraphLlmConfig, type GraphLlmFamily, type GraphLlmParameters, type GraphLlmProvider, type GraphLlmRequiredCapabilities, type ModelCatalogDocument, type ModelParameterProfile, type ModelProviderAdapter, type ModelProviderInitialization, type OpenAIAuthReasoningParameters, type OpenAIChatParameters, type OpenAIReasoningParameters, type ResolvedModelDescriptor, type RuntimeGraphLlmConfig, } from "./model-catalog.js";
4
4
  export type GraphLlmConfigOverride = GraphLlmConfig | Readonly<{
5
5
  model?: never;
6
6
  params?: Readonly<Record<string, unknown | null>>;
@@ -1,18 +1,22 @@
1
- import type { GraphState } from './graph-state.js';
2
- import type { LlmCallOptions, LlmGateway, LlmGatewayTool } from './llm-gateway.js';
3
- import 'reflect-metadata';
4
- import { type BaseMessage } from '@langchain/core/messages';
5
- import type { ToolCall } from '@langchain/core/messages/tool';
6
- import { type GraphLlmConfig, type GraphLlmConfigOverride } from './graph-llm.config.js';
7
- import type { NodeStateValue } from './node-state.js';
8
- import { GraphStateSupport } from './graph-state-support.js';
9
- import { type ConversationPolicy, type ConversationRunResult, type ConversationToolResult } from './conversation-runner.js';
10
- import type { ModelStopReason } from './model-stop-reason.js';
11
- import { type ConversationToolResultBuilder } from './conversation-tool-result.js';
12
- import { GRAPH_NODE_LOCAL_STATE, type GraphNodeTarget, type GraphNodeUpdate, type NodeOutcomeBuilder } from './node-outcome.js';
13
- export { GRAPH_NODE_LOCAL_STATE, type GraphNodeLocalState, type GraphNodeTarget, type GraphNodeUpdate, type NodeOutcomeBuilder, type OutcomeRouteTarget, } from './node-outcome.js';
1
+ import type { GraphState } from "./graph-state.js";
2
+ import type { LlmCallOptions, LlmGateway, LlmGatewayTool } from "./llm-gateway.js";
3
+ import "reflect-metadata";
4
+ import { type BaseMessage } from "@langchain/core/messages";
5
+ import type { ToolCall } from "@langchain/core/messages/tool";
6
+ import { Command } from "@langchain/langgraph";
7
+ import { type GraphLlmConfig, type GraphLlmConfigOverride } from "./graph-llm.config.js";
8
+ import type { NodeStateValue } from "./node-state.js";
9
+ import { GraphStateSupport } from "./graph-state-support.js";
10
+ import { type ConversationPolicy, type ConversationRunResult } from "./conversation-runner.js";
11
+ import type { ModelStopReason } from "./model-stop-reason.js";
12
+ import { GRAPH_NODE_LOCAL_STATE, type GraphNodeLocalState, type GraphNodeTarget, type GraphNodeUpdate } from "./node-outcome.js";
13
+ import { type ToolResponse } from "./tool-response.js";
14
+ import { type DecisionConversation, type DecisionErrorContext, type DecisionOptions, type DecisionProviderAdapter, type ResolvedDecisionOptions } from "./decision/decision-types.js";
15
+ export { GRAPH_NODE_LOCAL_STATE, type GraphNodeLocalState, type GraphNodeTarget, type GraphNodeUpdate, } from "./node-outcome.js";
14
16
  export type ToolDefinition<Input extends Record<string, unknown> = Record<string, unknown>> = Readonly<LlmGatewayTool<Input>>;
15
17
  export type ToolInput<Tool extends ToolDefinition<any>> = Tool extends ToolDefinition<infer Input> ? Input : never;
18
+ export type GraphNodeResult<State extends GraphState> = GraphNodeUpdate<State> | Command<unknown, GraphNodeUpdate<State>, string>;
19
+ export type GraphNodeResponse<State extends GraphState> = GraphNodeResult<State> | ToolResponse;
16
20
  export type InvalidJsonResponseContext<State extends GraphState> = Readonly<{
17
21
  state: Readonly<State>;
18
22
  update: Readonly<GraphNodeUpdate<State>>;
@@ -26,69 +30,73 @@ export type EmptyModelResponseContext<State extends GraphState> = Readonly<{
26
30
  }>;
27
31
  export declare const GRAPH_NODE_CLASS: unique symbol;
28
32
  export declare function Tool(toolName: string): MethodDecorator;
29
- export declare abstract class GraphNode<State extends GraphState, LocalState extends object = Record<string, never>, ToolContext extends object = Record<string, never>> {
33
+ export declare abstract class GraphNode<State extends GraphState, LocalState extends object = Record<string, unknown>, ToolContext extends object = Record<string, unknown>> {
30
34
  protected readonly llmGateway: LlmGateway;
31
35
  private readonly runtime;
32
36
  static readonly [GRAPH_NODE_CLASS] = true;
33
37
  static id(): string;
34
38
  static readonly name: string;
35
39
  readonly [GRAPH_NODE_LOCAL_STATE]: LocalState;
36
- readonly supportsAutomaticOutcomeRouting: boolean;
37
40
  readonly name: string;
38
41
  readonly id: string;
39
42
  constructor(llmGateway: LlmGateway, runtime: GraphNodeRuntime<State>);
43
+ protected get graph(): GraphNodeRuntime<State>;
40
44
  abstract getPrompt(state: State): string;
41
45
  defineTool(): readonly ToolDefinition[];
42
46
  getLlmConfig(): GraphLlmConfigOverride;
43
47
  route(_state: State): string;
44
- protected handleTool(state: State, call: ToolCall, context: ToolContext): Promise<ConversationToolResult>;
48
+ protected handleTool(state: State, call: ToolCall, context: ToolContext): Promise<ToolResponse>;
45
49
  private rejectToolCall;
46
- abstract run(state: State): GraphNodeUpdate<State> | Promise<GraphNodeUpdate<State>>;
50
+ abstract run(state: State): GraphNodeResponse<State> | Promise<GraphNodeResponse<State>>;
51
+ protected usesChatModel(): boolean;
47
52
  protected onInvalidJsonResponse(context: InvalidJsonResponseContext<State>): GraphNodeUpdate<State> | Promise<GraphNodeUpdate<State>>;
48
53
  protected onEmptyModelResponse(context: EmptyModelResponseContext<State>): string | Promise<string>;
49
- readonly invoke: (state: State) => Promise<GraphNodeUpdate<State>>;
54
+ readonly invoke: (state: State) => Promise<GraphNodeResult<State>>;
50
55
  obtainTools(): readonly ToolDefinition[];
51
56
  validateTools(): void;
52
57
  protected llmConfig(): GraphLlmConfig;
53
58
  protected llmCallOptions(): LlmCallOptions;
54
59
  protected runConversation(state: State, context: ToolContext): Promise<ConversationRunResult>;
55
60
  private runAgentLoop;
56
- protected toolResult(output: unknown): ConversationToolResultBuilder<ToolContext>;
57
61
  protected historySpace(): string;
58
- protected history(state: Pick<State, 'histories'>): BaseMessage[];
59
- protected historyUpdate(messages: BaseMessage[]): Pick<State, 'histories'>;
62
+ protected history(state: Pick<State, "histories">): BaseMessage[];
63
+ protected historyUpdate(messages: BaseMessage[]): Pick<State, "histories">;
60
64
  protected respond(message: string): GraphNodeUpdate<State>;
61
65
  protected complete(message: string): GraphNodeUpdate<State>;
62
- protected stay(conversation: ConversationRunResult, response?: string | undefined): NodeOutcomeBuilder<State, LocalState>;
63
- protected resumeAt<NodeClass extends GraphNodeTarget>(NodeClass: NodeClass, conversation: ConversationRunResult): NodeOutcomeBuilder<State, LocalState>;
64
- protected advance<NodeClass extends GraphNodeTarget>(NodeClass: NodeClass, conversation: ConversationRunResult): NodeOutcomeBuilder<State, LocalState, true>;
65
- protected transition<NodeClass extends GraphNodeTarget>(NodeClass: NodeClass, conversation: ConversationRunResult, canForwardInput: false): NodeOutcomeBuilder<State, LocalState>;
66
- protected transition<NodeClass extends GraphNodeTarget>(NodeClass: NodeClass, conversation: ConversationRunResult, canForwardInput: true): NodeOutcomeBuilder<State, LocalState, true>;
67
- protected finish(response: string, conversation: ConversationRunResult): NodeOutcomeBuilder<State, LocalState>;
68
- protected state(state: Pick<State, 'nodes'>): NodeStateValue<LocalState>;
66
+ protected resolveNodeResponse(result: GraphNodeResponse<State>): GraphNodeResult<State>;
67
+ protected state(state: Pick<State, "nodes">): NodeStateValue<LocalState>;
68
+ protected getState(): Readonly<NodeStateValue<LocalState>>;
69
+ protected saveState(patch: Partial<LocalState>): void;
69
70
  protected save(patch: Partial<LocalState>): GraphNodeUpdate<State>;
70
71
  protected remove(...keys: (keyof LocalState & string)[]): GraphNodeUpdate<State>;
71
- private outcomeBuilder;
72
72
  private toolHandler;
73
73
  private resolveJsonResponse;
74
74
  private toolHandlers;
75
75
  }
76
- export declare class GraphNodeRuntime<State extends GraphState> extends GraphStateSupport<State['currentNode'], State['nodes']> {
76
+ export declare class GraphNodeRuntime<State extends GraphState> extends GraphStateSupport<State["currentNode"], State["nodes"]> {
77
77
  private readonly defaultLlmConfig;
78
78
  private readonly historySpaces;
79
79
  private readonly initialHistorySpace;
80
80
  private readonly responseMode;
81
81
  readonly maxAgentRounds: number;
82
82
  readonly conversationPolicy: ConversationPolicy;
83
+ private readonly decisionOptions;
84
+ private readonly decisionErrorHandler?;
83
85
  private readonly tools;
84
- constructor(endNode: State['currentNode'], defaultLlmConfig: GraphLlmConfig, historySpaces?: Readonly<Record<string, string>>, initialHistorySpace?: string, responseMode?: 'chat' | 'json', maxAgentRounds?: number, conversationPolicy?: ConversationPolicy);
86
+ constructor(endNode: State["currentNode"], defaultLlmConfig: GraphLlmConfig, historySpaces?: Readonly<Record<string, string>>, initialHistorySpace?: string, responseMode?: "chat" | "json", maxAgentRounds?: number, conversationPolicy?: ConversationPolicy, decisionOptions?: DecisionOptions, decisionErrorHandler?: ((context: DecisionErrorContext<State>) => GraphNodeResponse<State> | null | Promise<GraphNodeResponse<State> | null>) | undefined);
85
87
  llmCallOptions(): LlmCallOptions;
86
88
  expectsJsonResponse(): boolean;
87
89
  historySpace(currentNode?: string): string;
88
90
  resolveLlmConfig(override?: GraphLlmConfigOverride): GraphLlmConfig;
91
+ resolveDecisionOptions(override?: DecisionOptions): ResolvedDecisionOptions;
92
+ private decisionProviderResolver?;
93
+ attachDecisionProviderResolver(resolve: (id: string) => DecisionProviderAdapter): void;
94
+ resolveDecisionProvider(id: string): DecisionProviderAdapter;
95
+ handleDecisionError(context: DecisionErrorContext<State>): Promise<GraphNodeResponse<State> | null>;
89
96
  registerTools(owner: string, definitions: readonly ToolDefinition[]): void;
90
97
  requireTool(name: string): ToolDefinition;
91
- input(state: Pick<State, 'histories' | 'currentNode'>): string;
98
+ input(state: Pick<State, "histories" | "currentNode">): string;
99
+ getConversation(space: string): DecisionConversation;
92
100
  respond(message: string): {
93
101
  response: string;
94
102
  inputConsumed: boolean;
@@ -99,8 +107,15 @@ export declare class GraphNodeRuntime<State extends GraphState> extends GraphSta
99
107
  response: string;
100
108
  inputConsumed: boolean;
101
109
  };
102
- saveNode(nodeName: string, values: NodeStateValue): {
103
- nodes: State["nodes"];
104
- };
105
- removeNode(nodeName: string, ...keys: string[]): NonNullable<State["nodes"][keyof State["nodes"]]>;
110
+ withInvocation<Result>(nodeId: string, state: State, run: () => Promise<Result>): Promise<Result>;
111
+ nodeState(nodeName: string): Record<string, unknown>;
112
+ hasInvocation(): boolean;
113
+ graphState(): State;
114
+ appendHistory(space: string, messages: readonly BaseMessage[]): void;
115
+ invocationHistory(space: string): BaseMessage[];
116
+ stagedUpdate(): GraphNodeUpdate<State>;
117
+ stageNodeEntries(nodes: State["nodes"] | undefined): void;
118
+ saveNode(nodeName: string, values: NodeStateValue): GraphNodeUpdate<State>;
119
+ saveNodeState<NodeClass extends GraphNodeTarget>(NodeClass: NodeClass, patch: Partial<GraphNodeLocalState<NodeClass>>): void;
120
+ removeNode(nodeName: string, ...keys: string[]): Partial<State>;
106
121
  }
@@ -1,18 +1,23 @@
1
- import type { GraphState } from './graph-state.js';
2
- import type { GraphLlmConfig } from './graph-llm.config.js';
3
- import type { HumanMessage } from '@langchain/core/messages';
4
- import type { SessionDocument } from './persistence/session-manager.js';
1
+ import type { GraphState } from "./graph-state.js";
2
+ import type { GraphLlmConfig } from "./graph-llm.config.js";
3
+ import type { HumanMessage } from "@langchain/core/messages";
4
+ import type { SessionDocument } from "./persistence/session-manager.js";
5
+ import type { DecisionProviderAdapter } from "./decision/decision-types.js";
5
6
  export interface RegisteredGraph<State extends GraphState = GraphState> {
6
7
  readonly id?: string;
7
8
  readonly name: string;
8
9
  readonly schemaVersion?: number;
9
10
  readonly llmConfig: GraphLlmConfig;
10
11
  readonly requiresUserMessage?: boolean;
11
- readonly responseMode?: 'chat' | 'json';
12
+ readonly responseMode?: "chat" | "json";
12
13
  readonly graph: {
13
14
  invoke(input: any): Promise<State>;
15
+ stream?(input: any, options?: {
16
+ streamMode?: "values";
17
+ }): Promise<AsyncIterable<State>>;
14
18
  };
15
19
  prepareInput(state: State | undefined, message: HumanMessage): Partial<State>;
20
+ attachDecisionProviderResolver?(resolve: (id: string) => DecisionProviderAdapter): void;
16
21
  restoreSessionDoc?(sessionDoc: SessionDocument<State>): Promise<SessionDocument<State> | null>;
17
22
  }
18
23
  export declare class GraphRegistry {
@@ -1,4 +1,4 @@
1
- import { type BaseMessage } from '@langchain/core/messages';
1
+ import { type BaseMessage } from "@langchain/core/messages";
2
2
  type MessageState = {
3
3
  messages: BaseMessage[];
4
4
  };
@@ -1,6 +1,7 @@
1
- import type { BaseMessage } from '@langchain/core/messages';
2
- import { type GraphNodeStates } from './node-state.js';
3
- import { type TokenUsage } from './token-usage.js';
1
+ import type { BaseMessage } from "@langchain/core/messages";
2
+ import { type GraphNodeStates } from "./node-state.js";
3
+ import { type TokenUsage } from "./token-usage.js";
4
+ import { type DecisionUsage } from "./decision/decision-types.js";
4
5
  export declare const GRAPH_END_NODE: "end";
5
6
  export type GraphState<CurrentNode extends string = string, Nodes extends object = GraphNodeStates> = {
6
7
  histories: Record<string, BaseMessage[]>;
@@ -8,10 +9,10 @@ export type GraphState<CurrentNode extends string = string, Nodes extends object
8
9
  config: Record<string, unknown>;
9
10
  nodes: Nodes;
10
11
  tokens: TokenUsage;
12
+ decisionUsage?: DecisionUsage;
11
13
  inputConsumed: boolean;
12
14
  response: string;
13
15
  completed: boolean;
14
- outcomeRoute: string | undefined;
15
16
  };
16
17
  export declare function createGraphStateAnnotation<CurrentNode extends string = string, Nodes extends object = GraphNodeStates>(defaultCurrentNode: string, createInitialNodes?: () => Nodes): import("@langchain/langgraph").AnnotationRoot<{
17
18
  histories: import("@langchain/langgraph").BaseChannel<Record<string, BaseMessage<import("@langchain/core/messages").MessageStructure<import("@langchain/core/messages").MessageToolSet>, import("@langchain/core/messages").MessageType>[]>, Record<string, BaseMessage<import("@langchain/core/messages").MessageStructure<import("@langchain/core/messages").MessageToolSet>, import("@langchain/core/messages").MessageType>[]> | import("@langchain/langgraph").OverwriteValue<Record<string, BaseMessage<import("@langchain/core/messages").MessageStructure<import("@langchain/core/messages").MessageToolSet>, import("@langchain/core/messages").MessageType>[]>>, unknown>;
@@ -19,8 +20,8 @@ export declare function createGraphStateAnnotation<CurrentNode extends string =
19
20
  config: import("@langchain/langgraph").BaseChannel<Record<string, unknown>, Record<string, unknown> | import("@langchain/langgraph").OverwriteValue<Record<string, unknown>>, unknown>;
20
21
  nodes: import("@langchain/langgraph").BaseChannel<Nodes, Nodes | import("@langchain/langgraph").OverwriteValue<Nodes>, unknown>;
21
22
  tokens: import("@langchain/langgraph").BaseChannel<TokenUsage, TokenUsage | import("@langchain/langgraph").OverwriteValue<TokenUsage>, unknown>;
23
+ decisionUsage: import("@langchain/langgraph").BaseChannel<DecisionUsage, DecisionUsage | import("@langchain/langgraph").OverwriteValue<DecisionUsage>, unknown>;
22
24
  inputConsumed: import("@langchain/langgraph").BaseChannel<boolean, boolean | import("@langchain/langgraph").OverwriteValue<boolean>, unknown>;
23
25
  response: import("@langchain/langgraph").BaseChannel<string, string | import("@langchain/langgraph").OverwriteValue<string>, unknown>;
24
26
  completed: import("@langchain/langgraph").BaseChannel<boolean, boolean | import("@langchain/langgraph").OverwriteValue<boolean>, unknown>;
25
- outcomeRoute: import("@langchain/langgraph").BaseChannel<string | undefined, string | import("@langchain/langgraph").OverwriteValue<string | undefined> | undefined, unknown>;
26
27
  }>;
@@ -1,4 +1,4 @@
1
- import type { GraphLlmConfig, ModelProviderInitialization } from './graph-llm.config.js';
2
- import { type RegisteredModelProviderAdapter } from './model-provider.js';
1
+ import type { GraphLlmConfig, ModelProviderInitialization } from "./graph-llm.config.js";
2
+ import { type RegisteredModelProviderAdapter } from "./model-provider.js";
3
3
  export type LangChainModelInitialization = ModelProviderInitialization;
4
4
  export declare function langChainModelInitialization(config: GraphLlmConfig, providers?: readonly RegisteredModelProviderAdapter[]): LangChainModelInitialization;