@picoflow/ezgraph 0.0.7 → 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 (54) hide show
  1. package/README.md +77 -0
  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-provider.adapter.js +1 -1
  15. package/dist/framework/persistence/session-manager.js +1 -1
  16. package/dist/framework/session-log.js +1 -1
  17. package/dist/framework/state-graph-ext.js +1 -1
  18. package/dist/framework/tool-response.js +1 -1
  19. package/dist/index.js +1 -1
  20. package/dist/testing/scripted-decisions.js +1 -0
  21. package/dist/testing/turn-harness.js +1 -1
  22. package/dist/testing.js +1 -1
  23. package/dist/types/npmlib/src/index.d.ts +9 -3
  24. package/dist/types/npmlib/src/testing.d.ts +1 -0
  25. package/dist/types/src/framework/base-graph.d.ts +23 -17
  26. package/dist/types/src/framework/conversation-node.d.ts +4 -4
  27. package/dist/types/src/framework/conversation-runner.d.ts +7 -7
  28. package/dist/types/src/framework/decision/decision-node.d.ts +17 -0
  29. package/dist/types/src/framework/decision/decision-provider.d.ts +14 -0
  30. package/dist/types/src/framework/decision/decision-runner.d.ts +18 -0
  31. package/dist/types/src/framework/decision/decision-types.d.ts +126 -0
  32. package/dist/types/src/framework/decision/decision-validation.d.ts +4 -0
  33. package/dist/types/src/framework/decision/typesafe-provider.d.ts +12 -0
  34. package/dist/types/src/framework/graph-engine.d.ts +4 -0
  35. package/dist/types/src/framework/graph-llm.config.d.ts +3 -3
  36. package/dist/types/src/framework/graph-node.d.ts +34 -22
  37. package/dist/types/src/framework/graph-registry.d.ts +8 -6
  38. package/dist/types/src/framework/graph-state-support.d.ts +1 -1
  39. package/dist/types/src/framework/graph-state.d.ts +6 -3
  40. package/dist/types/src/framework/langchain-provider.adapter.d.ts +2 -2
  41. package/dist/types/src/framework/llm-gateway.d.ts +4 -4
  42. package/dist/types/src/framework/model-stop-reason.d.ts +2 -2
  43. package/dist/types/src/framework/node-invocation.d.ts +2 -2
  44. package/dist/types/src/framework/node-outcome.d.ts +2 -2
  45. package/dist/types/src/framework/node-state.d.ts +1 -1
  46. package/dist/types/src/framework/openai-auth-provider.d.ts +1 -1
  47. package/dist/types/src/framework/persistence/session-manager.d.ts +3 -0
  48. package/dist/types/src/framework/session-log.d.ts +30 -0
  49. package/dist/types/src/framework/state-graph-ext.d.ts +3 -3
  50. package/dist/types/src/framework/token-usage.d.ts +2 -2
  51. package/dist/types/src/framework/tool-response.d.ts +7 -3
  52. package/dist/types/src/testing/scripted-decisions.d.ts +24 -0
  53. package/dist/types/src/testing/turn-harness.d.ts +2 -0
  54. package/package.json +11 -7
@@ -1,20 +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 { 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
- export { GRAPH_NODE_LOCAL_STATE, type GraphNodeLocalState, type GraphNodeTarget, type GraphNodeUpdate, } 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";
15
16
  export type ToolDefinition<Input extends Record<string, unknown> = Record<string, unknown>> = Readonly<LlmGatewayTool<Input>>;
16
17
  export type ToolInput<Tool extends ToolDefinition<any>> = Tool extends ToolDefinition<infer Input> ? Input : never;
17
18
  export type GraphNodeResult<State extends GraphState> = GraphNodeUpdate<State> | Command<unknown, GraphNodeUpdate<State>, string>;
19
+ export type GraphNodeResponse<State extends GraphState> = GraphNodeResult<State> | ToolResponse;
18
20
  export type InvalidJsonResponseContext<State extends GraphState> = Readonly<{
19
21
  state: Readonly<State>;
20
22
  update: Readonly<GraphNodeUpdate<State>>;
@@ -45,7 +47,8 @@ export declare abstract class GraphNode<State extends GraphState, LocalState ext
45
47
  route(_state: State): string;
46
48
  protected handleTool(state: State, call: ToolCall, context: ToolContext): Promise<ToolResponse>;
47
49
  private rejectToolCall;
48
- abstract run(state: State): GraphNodeResult<State> | Promise<GraphNodeResult<State>>;
50
+ abstract run(state: State): GraphNodeResponse<State> | Promise<GraphNodeResponse<State>>;
51
+ protected usesChatModel(): boolean;
49
52
  protected onInvalidJsonResponse(context: InvalidJsonResponseContext<State>): GraphNodeUpdate<State> | Promise<GraphNodeUpdate<State>>;
50
53
  protected onEmptyModelResponse(context: EmptyModelResponseContext<State>): string | Promise<string>;
51
54
  readonly invoke: (state: State) => Promise<GraphNodeResult<State>>;
@@ -56,11 +59,12 @@ export declare abstract class GraphNode<State extends GraphState, LocalState ext
56
59
  protected runConversation(state: State, context: ToolContext): Promise<ConversationRunResult>;
57
60
  private runAgentLoop;
58
61
  protected historySpace(): string;
59
- protected history(state: Pick<State, 'histories'>): BaseMessage[];
60
- protected historyUpdate(messages: BaseMessage[]): Pick<State, 'histories'>;
62
+ protected history(state: Pick<State, "histories">): BaseMessage[];
63
+ protected historyUpdate(messages: BaseMessage[]): Pick<State, "histories">;
61
64
  protected respond(message: string): GraphNodeUpdate<State>;
62
65
  protected complete(message: string): GraphNodeUpdate<State>;
63
- 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>;
64
68
  protected getState(): Readonly<NodeStateValue<LocalState>>;
65
69
  protected saveState(patch: Partial<LocalState>): void;
66
70
  protected save(patch: Partial<LocalState>): GraphNodeUpdate<State>;
@@ -69,22 +73,30 @@ export declare abstract class GraphNode<State extends GraphState, LocalState ext
69
73
  private resolveJsonResponse;
70
74
  private toolHandlers;
71
75
  }
72
- 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"]> {
73
77
  private readonly defaultLlmConfig;
74
78
  private readonly historySpaces;
75
79
  private readonly initialHistorySpace;
76
80
  private readonly responseMode;
77
81
  readonly maxAgentRounds: number;
78
82
  readonly conversationPolicy: ConversationPolicy;
83
+ private readonly decisionOptions;
84
+ private readonly decisionErrorHandler?;
79
85
  private readonly tools;
80
- 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);
81
87
  llmCallOptions(): LlmCallOptions;
82
88
  expectsJsonResponse(): boolean;
83
89
  historySpace(currentNode?: string): string;
84
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>;
85
96
  registerTools(owner: string, definitions: readonly ToolDefinition[]): void;
86
97
  requireTool(name: string): ToolDefinition;
87
- input(state: Pick<State, 'histories' | 'currentNode'>): string;
98
+ input(state: Pick<State, "histories" | "currentNode">): string;
99
+ getConversation(space: string): DecisionConversation;
88
100
  respond(message: string): {
89
101
  response: string;
90
102
  inputConsumed: boolean;
@@ -102,7 +114,7 @@ export declare class GraphNodeRuntime<State extends GraphState> extends GraphSta
102
114
  appendHistory(space: string, messages: readonly BaseMessage[]): void;
103
115
  invocationHistory(space: string): BaseMessage[];
104
116
  stagedUpdate(): GraphNodeUpdate<State>;
105
- stageNodeEntries(nodes: State['nodes'] | undefined): void;
117
+ stageNodeEntries(nodes: State["nodes"] | undefined): void;
106
118
  saveNode(nodeName: string, values: NodeStateValue): GraphNodeUpdate<State>;
107
119
  saveNodeState<NodeClass extends GraphNodeTarget>(NodeClass: NodeClass, patch: Partial<GraphNodeLocalState<NodeClass>>): void;
108
120
  removeNode(nodeName: string, ...keys: string[]): Partial<State>;
@@ -1,21 +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>;
14
15
  stream?(input: any, options?: {
15
- streamMode?: 'values';
16
+ streamMode?: "values";
16
17
  }): Promise<AsyncIterable<State>>;
17
18
  };
18
19
  prepareInput(state: State | undefined, message: HumanMessage): Partial<State>;
20
+ attachDecisionProviderResolver?(resolve: (id: string) => DecisionProviderAdapter): void;
19
21
  restoreSessionDoc?(sessionDoc: SessionDocument<State>): Promise<SessionDocument<State> | null>;
20
22
  }
21
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,6 +9,7 @@ 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;
@@ -18,6 +20,7 @@ export declare function createGraphStateAnnotation<CurrentNode extends string =
18
20
  config: import("@langchain/langgraph").BaseChannel<Record<string, unknown>, Record<string, unknown> | import("@langchain/langgraph").OverwriteValue<Record<string, unknown>>, unknown>;
19
21
  nodes: import("@langchain/langgraph").BaseChannel<Nodes, Nodes | import("@langchain/langgraph").OverwriteValue<Nodes>, unknown>;
20
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>;
21
24
  inputConsumed: import("@langchain/langgraph").BaseChannel<boolean, boolean | import("@langchain/langgraph").OverwriteValue<boolean>, unknown>;
22
25
  response: import("@langchain/langgraph").BaseChannel<string, string | import("@langchain/langgraph").OverwriteValue<string>, unknown>;
23
26
  completed: import("@langchain/langgraph").BaseChannel<boolean, boolean | import("@langchain/langgraph").OverwriteValue<boolean>, unknown>;
@@ -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;
@@ -1,7 +1,7 @@
1
- import type { ZodType } from 'zod';
2
- import type { AIMessage, BaseMessage } from '@langchain/core/messages';
3
- import type { GraphLlmConfig } from './graph-llm.config.js';
4
- import type { ModelResult } from './token-usage.js';
1
+ import type { ZodType } from "zod";
2
+ import type { AIMessage, BaseMessage } from "@langchain/core/messages";
3
+ import type { GraphLlmConfig } from "./graph-llm.config.js";
4
+ import type { ModelResult } from "./token-usage.js";
5
5
  export declare const LLM_GATEWAY_FACTORY: unique symbol;
6
6
  export type LlmCallOptions = Readonly<{
7
7
  signal?: AbortSignal;
@@ -1,5 +1,5 @@
1
- import { AIMessage } from '@langchain/core/messages';
2
- export type ModelStopCategory = 'complete' | 'blocked' | 'truncated' | 'malformed_tool_call' | 'unspecified';
1
+ import { AIMessage } from "@langchain/core/messages";
2
+ export type ModelStopCategory = "complete" | "blocked" | "truncated" | "malformed_tool_call" | "unspecified";
3
3
  export type ModelStopReason = Readonly<{
4
4
  category: ModelStopCategory;
5
5
  provider?: string;
@@ -1,5 +1,5 @@
1
- import type { BaseMessage } from '@langchain/core/messages';
2
- import type { GraphState } from './graph-state.js';
1
+ import type { BaseMessage } from "@langchain/core/messages";
2
+ import type { GraphState } from "./graph-state.js";
3
3
  export declare function hasNodeInvocation(owner: object): boolean;
4
4
  export declare function withNodeInvocation<State extends GraphState, Result>(owner: object, nodeId: string, state: State, run: () => Promise<Result>): Promise<Result>;
5
5
  export declare function invocationNodeId(owner: object): string;
@@ -1,4 +1,4 @@
1
- import type { GraphState } from './graph-state.js';
1
+ import type { GraphState } from "./graph-state.js";
2
2
  export declare const GRAPH_NODE_LOCAL_STATE: unique symbol;
3
3
  export type GraphNodeTarget<LocalState extends object = object> = {
4
4
  readonly name: string;
@@ -7,6 +7,6 @@ export type GraphNodeTarget<LocalState extends object = object> = {
7
7
  readonly [GRAPH_NODE_LOCAL_STATE]: LocalState;
8
8
  };
9
9
  };
10
- export type GraphNodeLocalState<NodeClass extends GraphNodeTarget> = NodeClass['prototype'][typeof GRAPH_NODE_LOCAL_STATE];
10
+ export type GraphNodeLocalState<NodeClass extends GraphNodeTarget> = NodeClass["prototype"][typeof GRAPH_NODE_LOCAL_STATE];
11
11
  export type GraphNodeUpdate<State extends GraphState> = Partial<State>;
12
12
  export declare function combineGraphNodeUpdates<State extends GraphState>(current: GraphNodeUpdate<State>, addition: GraphNodeUpdate<State>): GraphNodeUpdate<State>;
@@ -1,4 +1,4 @@
1
- import type { GraphLlmModelMetadata } from './graph-llm.config.js';
1
+ import type { GraphLlmModelMetadata } from "./graph-llm.config.js";
2
2
  export type NodeStateValue<T extends object = Record<string, unknown>> = T & {
3
3
  model?: GraphLlmModelMetadata | undefined;
4
4
  };
@@ -1,4 +1,4 @@
1
- import type { GraphLlmConfig, ModelProviderInitialization } from './graph-llm.config.js';
1
+ import type { GraphLlmConfig, ModelProviderInitialization } from "./graph-llm.config.js";
2
2
  export declare const OPENAI_AUTH_PROVIDER = "openai-auth";
3
3
  export type OpenAIAuthCredentials = Readonly<{
4
4
  accessToken: string;
@@ -4,6 +4,7 @@ import { type GraphState } from '../graph-state.js';
4
4
  import { type GraphLlmConfig, type GraphLlmModelMetadata } from '../graph-llm.config.js';
5
5
  import { type SessionLogs } from '../session-log.js';
6
6
  import { type TokenUsage } from '../token-usage.js';
7
+ import { type DecisionUsage } from '../decision/decision-types.js';
7
8
  export declare const SESSION_DOCUMENT_VERSION = 16;
8
9
  export declare const SESSION_BUSY = "SESSION_BUSY";
9
10
  export declare const SESSION_CONFLICT = "SESSION_CONFLICT";
@@ -51,8 +52,10 @@ export type SessionDocument<State extends GraphState = GraphState> = {
51
52
  revision: number;
52
53
  status: SessionGraphStatus;
53
54
  tokens: TokenUsage;
55
+ decisionUsage?: DecisionUsage;
54
56
  errors: SessionLogs['errors'];
55
57
  warnings: SessionLogs['warnings'];
58
+ decisions?: SessionLogs['decisions'];
56
59
  graph: SessionGraphDocument<State>;
57
60
  turn?: SessionTurnLease;
58
61
  createdAt: string;
@@ -1,11 +1,41 @@
1
+ import type { DecisionFailure, DecisionUsage } from "./decision/decision-types.js";
1
2
  export type SessionLogEntry = Record<string, unknown> & {
2
3
  createdAt: string;
3
4
  };
4
5
  export type SessionLogs = {
5
6
  errors: SessionLogEntry[];
6
7
  warnings: SessionLogEntry[];
8
+ decisions: DecisionAuditEntry[];
9
+ };
10
+ export type DecisionAuditOutcome = "success" | "fallback" | "decision_handler_failed" | "fallback_handler_failed";
11
+ export type DecisionAuditEntry = SessionLogEntry & {
12
+ node: string;
13
+ provider: string;
14
+ configuredModel: string;
15
+ actualModel?: string;
16
+ outcome: DecisionAuditOutcome;
17
+ failure?: DecisionFailure;
18
+ attempts: number;
19
+ durationMs: number;
20
+ requestId?: string;
21
+ usage: DecisionUsage;
22
+ };
23
+ export type DecisionAuditInput = {
24
+ node: string;
25
+ provider: string;
26
+ configuredModel: string;
27
+ actualModel?: string;
28
+ outcome: DecisionAuditOutcome;
29
+ failure?: DecisionFailure;
30
+ attempts: number;
31
+ durationMs: number;
32
+ requestId?: string;
33
+ usage: DecisionUsage;
7
34
  };
8
35
  export declare function createSessionLogs(): SessionLogs;
36
+ export declare function drainSessionLogs(logs: SessionLogs): SessionLogs;
37
+ export declare function restoreSessionLogs(logs: SessionLogs, drained: SessionLogs): void;
9
38
  export declare function withSessionLogs<T>(logs: SessionLogs, callback: () => Promise<T>): Promise<T>;
10
39
  export declare function SessionLogError(tree: Record<string, unknown>, logs?: SessionLogs | undefined): void;
11
40
  export declare function SessionLogWarning(tree: Record<string, unknown>, logs?: SessionLogs | undefined): void;
41
+ export declare function SessionLogDecision(entry: DecisionAuditInput, logs?: SessionLogs | undefined): DecisionAuditEntry | undefined;
@@ -1,5 +1,5 @@
1
- import { type Command, END, type ExtractStateType, type ExtractUpdateType, START, type StateDefinitionInit } from '@langchain/langgraph';
2
- import { GRAPH_NODE_CLASS } from './graph-node.js';
1
+ import { type Command, END, type ExtractStateType, type ExtractUpdateType, START, type StateDefinitionInit } from "@langchain/langgraph";
2
+ import { GRAPH_NODE_CLASS } from "./graph-node.js";
3
3
  export type RegisteredNode<State, Update> = {
4
4
  readonly id: string;
5
5
  readonly invoke: (state: State) => Promise<Update | Command<unknown, Update & Record<string, unknown>, string>>;
@@ -21,7 +21,7 @@ export type CurrentNodeBranchOptions = Readonly<{
21
21
  }[];
22
22
  otherwise: GraphEndpoint;
23
23
  }>;
24
- type RouteOf<NodeClass extends GraphNodeClass> = NodeClass['prototype'] extends {
24
+ type RouteOf<NodeClass extends GraphNodeClass> = NodeClass["prototype"] extends {
25
25
  route(...args: never[]): infer Route;
26
26
  } ? Extract<Route, string> : never;
27
27
  type BranchDestinations<NodeClass extends GraphNodeClass, Destinations extends Readonly<Record<RouteOf<NodeClass>, GraphEndpoint>>> = Destinations & Record<Exclude<keyof Destinations, RouteOf<NodeClass>>, never>;
@@ -1,4 +1,4 @@
1
- import { ModelCatalog, type GraphLlmConfig, type GraphLlmParameters } from './graph-llm.config.js';
1
+ import { ModelCatalog, type GraphLlmConfig, type GraphLlmParameters } from "./graph-llm.config.js";
2
2
  export type TokenUsage = {
3
3
  input_tokens: number;
4
4
  output_tokens: number;
@@ -14,7 +14,7 @@ export type ModelResult<T> = {
14
14
  };
15
15
  export type ModelExecution = {
16
16
  model: string;
17
- family: ReturnType<typeof ModelCatalog.resolveModelDescriptor>['family'];
17
+ family: ReturnType<typeof ModelCatalog.resolveModelDescriptor>["family"];
18
18
  parameters: GraphLlmParameters;
19
19
  };
20
20
  export declare function modelExecution(config: GraphLlmConfig): ModelExecution;
@@ -1,6 +1,7 @@
1
- import type { BaseMessage } from '@langchain/core/messages';
2
- import type { GraphNodeLocalState, GraphNodeTarget } from './node-outcome.js';
3
- export type ToolResponseKind = 'go' | 'stay' | 'direct' | 'finish';
1
+ import type { BaseMessage } from "@langchain/core/messages";
2
+ import type { GraphNodeLocalState, GraphNodeTarget } from "./node-outcome.js";
3
+ import type { TokenUsage } from "./token-usage.js";
4
+ export type ToolResponseKind = "go" | "stay" | "direct" | "directTo" | "finish";
4
5
  export type ToolResponse = Readonly<{
5
6
  kind: ToolResponseKind;
6
7
  target?: GraphNodeTarget;
@@ -10,6 +11,7 @@ export type ToolResponse = Readonly<{
10
11
  messages?: readonly BaseMessage[];
11
12
  cleanup?: () => Promise<void>;
12
13
  response?: string;
14
+ usage?: TokenUsage;
13
15
  }>;
14
16
  export type ToolResponseBuilder<NodeClass extends GraphNodeTarget> = ToolResponse & {
15
17
  withState(state: Partial<GraphNodeLocalState<NodeClass>>): ToolResponseBuilder<NodeClass>;
@@ -17,9 +19,11 @@ export type ToolResponseBuilder<NodeClass extends GraphNodeTarget> = ToolRespons
17
19
  withMessages(messages: readonly BaseMessage[]): ToolResponseBuilder<NodeClass>;
18
20
  withCleanup(cleanup: () => Promise<void>): ToolResponseBuilder<NodeClass>;
19
21
  withToolFeedback(feedback: string): ToolResponseBuilder<NodeClass>;
22
+ withUsage(usage: TokenUsage): ToolResponseBuilder<NodeClass>;
20
23
  };
21
24
  export declare function go<NodeClass extends GraphNodeTarget>(target: NodeClass): ToolResponseBuilder<NodeClass>;
22
25
  export declare function stay(feedback?: string): ToolResponseBuilder<GraphNodeTarget>;
23
26
  export declare function direct(content: string | object): ToolResponseBuilder<GraphNodeTarget>;
27
+ export declare function directTo<NodeClass extends GraphNodeTarget>(target: NodeClass, content: string | object): ToolResponseBuilder<NodeClass>;
24
28
  export declare function finish(content: string | object): ToolResponseBuilder<GraphNodeTarget>;
25
29
  export declare function isToolResponse(value: unknown): value is ToolResponse;
@@ -0,0 +1,24 @@
1
+ import type { DecisionAnswer, DecisionCallOptions, DecisionProviderAdapter, DecisionRequest, DecisionResult, DecisionTokenUsage } from '../framework/decision/decision-types.js';
2
+ export type ScriptedDecisionCall = Readonly<{
3
+ request: DecisionRequest;
4
+ options: DecisionCallOptions;
5
+ }>;
6
+ export declare class ScriptedDecisions implements DecisionProviderAdapter {
7
+ readonly id: string;
8
+ private readonly turns;
9
+ private consumed;
10
+ readonly calls: ScriptedDecisionCall[];
11
+ constructor(id?: string);
12
+ answers(answers: Record<string, DecisionAnswer>, options?: Readonly<{
13
+ model?: string;
14
+ usage?: DecisionTokenUsage;
15
+ requestId?: string;
16
+ }>): this;
17
+ result(result: DecisionResult): this;
18
+ fail(error: Error | string): this;
19
+ get drained(): boolean;
20
+ get remaining(): number;
21
+ decide(request: DecisionRequest, options: DecisionCallOptions): Promise<DecisionResult>;
22
+ shouldRetry(error: Error): boolean;
23
+ }
24
+ export declare function scriptedDecisions(id?: string): ScriptedDecisions;
@@ -2,6 +2,7 @@ import { GraphEngine, type GraphConstructor, type RunResult } from '../framework
2
2
  import type { GraphState } from '../framework/graph-state.js';
3
3
  import type { LlmGateway } from '../framework/llm-gateway.js';
4
4
  import type { SessionLogs } from '../framework/session-log.js';
5
+ import type { DecisionProviderAdapter } from '../framework/decision/decision-types.js';
5
6
  import { SessionManager, type SessionDocument } from '../framework/persistence/session-manager.js';
6
7
  export type HarnessTurn<State extends GraphState> = Readonly<{
7
8
  status: number;
@@ -30,6 +31,7 @@ export type TurnHarness<State extends GraphState> = Readonly<{
30
31
  export declare function createTurnHarness<State extends GraphState = GraphState>(options: Readonly<{
31
32
  graph: GraphConstructor;
32
33
  gateway?: LlmGateway;
34
+ decisions?: DecisionProviderAdapter | readonly DecisionProviderAdapter[];
33
35
  sessionManager?: SessionManager;
34
36
  sessionId?: string;
35
37
  }>): TurnHarness<State>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@picoflow/ezgraph",
3
- "version": "0.0.7",
3
+ "version": "0.0.8",
4
4
  "description": "Provider-neutral graph primitives built on LangGraph and LangChain.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -37,18 +37,19 @@
37
37
  "@azure/identity": "4.13.1",
38
38
  "@google/genai": "2.14.0",
39
39
  "dotenv": "17.4.2",
40
- "@langchain/core": "1.2.3",
41
- "@langchain/langgraph": "1.4.8",
42
- "langchain": "1.5.4",
40
+ "@langchain/core": "1.2.12",
41
+ "@langchain/langgraph": "1.4.17",
42
+ "langchain": "1.5.12",
43
43
  "mongodb": "6.21.0",
44
44
  "openai": "7.1.0",
45
45
  "reflect-metadata": "0.2.2",
46
46
  "zod": "4.4.3"
47
47
  },
48
48
  "peerDependencies": {
49
- "@langchain/anthropic": ">=1.5.2",
50
- "@langchain/google": ">=0.2.1",
51
- "@langchain/openai": ">=1.5.5"
49
+ "@langchain/anthropic": ">=1.5.11",
50
+ "@langchain/google": ">=0.2.7",
51
+ "@langchain/openai": ">=1.5.13",
52
+ "@langchain/typesafe": ">=0.0.1"
52
53
  },
53
54
  "peerDependenciesMeta": {
54
55
  "@langchain/anthropic": {
@@ -59,6 +60,9 @@
59
60
  },
60
61
  "@langchain/openai": {
61
62
  "optional": true
63
+ },
64
+ "@langchain/typesafe": {
65
+ "optional": true
62
66
  }
63
67
  }
64
68
  }