@librechat/agents 3.1.66-dev.0 → 3.1.67

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 (120) hide show
  1. package/dist/cjs/agents/AgentContext.cjs +24 -15
  2. package/dist/cjs/agents/AgentContext.cjs.map +1 -1
  3. package/dist/cjs/common/enum.cjs +0 -13
  4. package/dist/cjs/common/enum.cjs.map +1 -1
  5. package/dist/cjs/graphs/Graph.cjs +0 -3
  6. package/dist/cjs/graphs/Graph.cjs.map +1 -1
  7. package/dist/cjs/main.cjs +0 -40
  8. package/dist/cjs/main.cjs.map +1 -1
  9. package/dist/cjs/messages/format.cjs +12 -74
  10. package/dist/cjs/messages/format.cjs.map +1 -1
  11. package/dist/cjs/run.cjs +0 -111
  12. package/dist/cjs/run.cjs.map +1 -1
  13. package/dist/cjs/tools/ToolNode.cjs +140 -304
  14. package/dist/cjs/tools/ToolNode.cjs.map +1 -1
  15. package/dist/esm/agents/AgentContext.mjs +24 -15
  16. package/dist/esm/agents/AgentContext.mjs.map +1 -1
  17. package/dist/esm/common/enum.mjs +1 -12
  18. package/dist/esm/common/enum.mjs.map +1 -1
  19. package/dist/esm/graphs/Graph.mjs +0 -3
  20. package/dist/esm/graphs/Graph.mjs.map +1 -1
  21. package/dist/esm/main.mjs +1 -10
  22. package/dist/esm/main.mjs.map +1 -1
  23. package/dist/esm/messages/format.mjs +4 -66
  24. package/dist/esm/messages/format.mjs.map +1 -1
  25. package/dist/esm/run.mjs +0 -111
  26. package/dist/esm/run.mjs.map +1 -1
  27. package/dist/esm/tools/ToolNode.mjs +142 -306
  28. package/dist/esm/tools/ToolNode.mjs.map +1 -1
  29. package/dist/types/agents/AgentContext.d.ts +6 -0
  30. package/dist/types/common/enum.d.ts +1 -7
  31. package/dist/types/graphs/Graph.d.ts +0 -2
  32. package/dist/types/index.d.ts +0 -6
  33. package/dist/types/messages/format.d.ts +1 -2
  34. package/dist/types/run.d.ts +0 -1
  35. package/dist/types/tools/ToolNode.d.ts +2 -24
  36. package/dist/types/types/index.d.ts +0 -1
  37. package/dist/types/types/llm.d.ts +14 -2
  38. package/dist/types/types/run.d.ts +0 -20
  39. package/dist/types/types/tools.d.ts +1 -38
  40. package/package.json +1 -1
  41. package/src/agents/AgentContext.ts +28 -15
  42. package/src/agents/__tests__/AgentContext.test.ts +110 -0
  43. package/src/common/enum.ts +0 -12
  44. package/src/graphs/Graph.ts +0 -4
  45. package/src/index.ts +0 -8
  46. package/src/messages/format.ts +4 -74
  47. package/src/run.ts +0 -126
  48. package/src/tools/ToolNode.ts +169 -391
  49. package/src/tools/__tests__/ToolNode.session.test.ts +12 -12
  50. package/src/types/index.ts +0 -1
  51. package/src/types/llm.ts +16 -2
  52. package/src/types/run.ts +0 -20
  53. package/src/types/tools.ts +1 -41
  54. package/dist/cjs/hooks/HookRegistry.cjs +0 -162
  55. package/dist/cjs/hooks/HookRegistry.cjs.map +0 -1
  56. package/dist/cjs/hooks/executeHooks.cjs +0 -276
  57. package/dist/cjs/hooks/executeHooks.cjs.map +0 -1
  58. package/dist/cjs/hooks/matchers.cjs +0 -256
  59. package/dist/cjs/hooks/matchers.cjs.map +0 -1
  60. package/dist/cjs/hooks/types.cjs +0 -27
  61. package/dist/cjs/hooks/types.cjs.map +0 -1
  62. package/dist/cjs/tools/BashExecutor.cjs +0 -175
  63. package/dist/cjs/tools/BashExecutor.cjs.map +0 -1
  64. package/dist/cjs/tools/BashProgrammaticToolCalling.cjs +0 -296
  65. package/dist/cjs/tools/BashProgrammaticToolCalling.cjs.map +0 -1
  66. package/dist/cjs/tools/ReadFile.cjs +0 -43
  67. package/dist/cjs/tools/ReadFile.cjs.map +0 -1
  68. package/dist/cjs/tools/SkillTool.cjs +0 -50
  69. package/dist/cjs/tools/SkillTool.cjs.map +0 -1
  70. package/dist/cjs/tools/skillCatalog.cjs +0 -84
  71. package/dist/cjs/tools/skillCatalog.cjs.map +0 -1
  72. package/dist/esm/hooks/HookRegistry.mjs +0 -160
  73. package/dist/esm/hooks/HookRegistry.mjs.map +0 -1
  74. package/dist/esm/hooks/executeHooks.mjs +0 -273
  75. package/dist/esm/hooks/executeHooks.mjs.map +0 -1
  76. package/dist/esm/hooks/matchers.mjs +0 -251
  77. package/dist/esm/hooks/matchers.mjs.map +0 -1
  78. package/dist/esm/hooks/types.mjs +0 -25
  79. package/dist/esm/hooks/types.mjs.map +0 -1
  80. package/dist/esm/tools/BashExecutor.mjs +0 -169
  81. package/dist/esm/tools/BashExecutor.mjs.map +0 -1
  82. package/dist/esm/tools/BashProgrammaticToolCalling.mjs +0 -287
  83. package/dist/esm/tools/BashProgrammaticToolCalling.mjs.map +0 -1
  84. package/dist/esm/tools/ReadFile.mjs +0 -38
  85. package/dist/esm/tools/ReadFile.mjs.map +0 -1
  86. package/dist/esm/tools/SkillTool.mjs +0 -45
  87. package/dist/esm/tools/SkillTool.mjs.map +0 -1
  88. package/dist/esm/tools/skillCatalog.mjs +0 -82
  89. package/dist/esm/tools/skillCatalog.mjs.map +0 -1
  90. package/dist/types/hooks/HookRegistry.d.ts +0 -56
  91. package/dist/types/hooks/executeHooks.d.ts +0 -79
  92. package/dist/types/hooks/index.d.ts +0 -6
  93. package/dist/types/hooks/matchers.d.ts +0 -95
  94. package/dist/types/hooks/types.d.ts +0 -309
  95. package/dist/types/tools/BashExecutor.d.ts +0 -45
  96. package/dist/types/tools/BashProgrammaticToolCalling.d.ts +0 -72
  97. package/dist/types/tools/ReadFile.d.ts +0 -28
  98. package/dist/types/tools/SkillTool.d.ts +0 -40
  99. package/dist/types/tools/skillCatalog.d.ts +0 -19
  100. package/dist/types/types/skill.d.ts +0 -9
  101. package/src/hooks/HookRegistry.ts +0 -208
  102. package/src/hooks/__tests__/HookRegistry.test.ts +0 -190
  103. package/src/hooks/__tests__/executeHooks.test.ts +0 -1013
  104. package/src/hooks/__tests__/integration.test.ts +0 -337
  105. package/src/hooks/__tests__/matchers.test.ts +0 -238
  106. package/src/hooks/__tests__/toolHooks.test.ts +0 -669
  107. package/src/hooks/executeHooks.ts +0 -375
  108. package/src/hooks/index.ts +0 -55
  109. package/src/hooks/matchers.ts +0 -280
  110. package/src/hooks/types.ts +0 -388
  111. package/src/messages/formatAgentMessages.skills.test.ts +0 -334
  112. package/src/tools/BashExecutor.ts +0 -205
  113. package/src/tools/BashProgrammaticToolCalling.ts +0 -397
  114. package/src/tools/ReadFile.ts +0 -39
  115. package/src/tools/SkillTool.ts +0 -46
  116. package/src/tools/__tests__/ReadFile.test.ts +0 -44
  117. package/src/tools/__tests__/SkillTool.test.ts +0 -442
  118. package/src/tools/__tests__/skillCatalog.test.ts +0 -161
  119. package/src/tools/skillCatalog.ts +0 -126
  120. package/src/types/skill.ts +0 -11
@@ -664,6 +664,17 @@ export class AgentContext {
664
664
  this.indexTokenCountMap = { ...baseTokenMap };
665
665
  }
666
666
 
667
+ /** Active tool definitions for token accounting (excludes deferred-and-undiscovered entries). */
668
+ private getActiveToolDefinitions(): t.LCTool[] {
669
+ if (!this.toolDefinitions) {
670
+ return [];
671
+ }
672
+ return this.toolDefinitions.filter(
673
+ (def) =>
674
+ def.defer_loading !== true || this.discoveredToolNames.has(def.name)
675
+ );
676
+ }
677
+
667
678
  /**
668
679
  * Calculate tool tokens and add to instruction tokens
669
680
  * Note: System message tokens are calculated during systemRunnable creation
@@ -697,21 +708,19 @@ export class AgentContext {
697
708
  }
698
709
  }
699
710
 
700
- if (this.toolDefinitions && this.toolDefinitions.length > 0) {
701
- for (const def of this.toolDefinitions) {
702
- if (countedToolNames.has(def.name)) {
703
- continue;
704
- }
705
- const schema = {
706
- type: 'function',
707
- function: {
708
- name: def.name,
709
- description: def.description ?? '',
710
- parameters: def.parameters ?? {},
711
- },
712
- };
713
- toolTokens += tokenCounter(new SystemMessage(JSON.stringify(schema)));
711
+ for (const def of this.getActiveToolDefinitions()) {
712
+ if (countedToolNames.has(def.name)) {
713
+ continue;
714
714
  }
715
+ const schema = {
716
+ type: 'function',
717
+ function: {
718
+ name: def.name,
719
+ description: def.description ?? '',
720
+ parameters: def.parameters ?? {},
721
+ },
722
+ };
723
+ toolTokens += tokenCounter(new SystemMessage(JSON.stringify(schema)));
715
724
  }
716
725
 
717
726
  const isAnthropic =
@@ -860,11 +869,15 @@ export class AgentContext {
860
869
  /**
861
870
  * Returns a structured breakdown of how the context token budget is consumed.
862
871
  * Useful for diagnostics when context overflow or pruning issues occur.
872
+ *
873
+ * Note: `toolCount` reflects discoveries immediately, but `toolSchemaTokens`
874
+ * is a snapshot taken during `calculateInstructionTokens` and is not
875
+ * recomputed when `markToolsAsDiscovered` is called mid-run.
863
876
  */
864
877
  getTokenBudgetBreakdown(messages?: BaseMessage[]): t.TokenBudgetBreakdown {
865
878
  const maxContextTokens = this.maxContextTokens ?? 0;
866
879
  const toolCount =
867
- (this.tools?.length ?? 0) + (this.toolDefinitions?.length ?? 0);
880
+ (this.tools?.length ?? 0) + this.getActiveToolDefinitions().length;
868
881
  const messageCount = messages?.length ?? 0;
869
882
 
870
883
  let messageTokens = 0;
@@ -375,6 +375,116 @@ describe('AgentContext', () => {
375
375
 
376
376
  expect(ctx.instructionTokens).toBeGreaterThan(initialTokens);
377
377
  });
378
+
379
+ it('excludes deferred-undiscovered toolDefinitions from toolSchemaTokens', async () => {
380
+ const activeDef: t.LCTool = {
381
+ name: 'active_tool',
382
+ description: 'Always loaded',
383
+ parameters: { type: 'object', properties: {} },
384
+ };
385
+ const deferredDef: t.LCTool = {
386
+ name: 'deferred_tool',
387
+ description: 'Loaded via tool search',
388
+ parameters: { type: 'object', properties: {} },
389
+ defer_loading: true,
390
+ };
391
+
392
+ const ctxBase = createBasicContext({
393
+ agentConfig: { toolDefinitions: [activeDef] },
394
+ tokenCounter: mockTokenCounter,
395
+ });
396
+ const ctxWithDeferred = createBasicContext({
397
+ agentConfig: { toolDefinitions: [activeDef, deferredDef] },
398
+ tokenCounter: mockTokenCounter,
399
+ });
400
+
401
+ await ctxBase.tokenCalculationPromise;
402
+ await ctxWithDeferred.tokenCalculationPromise;
403
+
404
+ expect(ctxWithDeferred.toolSchemaTokens).toBe(ctxBase.toolSchemaTokens);
405
+ });
406
+
407
+ it('includes deferred toolDefinitions once discovered via discoveredTools input', async () => {
408
+ const toolDefinitions: t.LCTool[] = [
409
+ {
410
+ name: 'deferred_tool',
411
+ description: 'Loaded via tool search',
412
+ parameters: { type: 'object', properties: {} },
413
+ defer_loading: true,
414
+ },
415
+ ];
416
+
417
+ const ctxUndiscovered = createBasicContext({
418
+ agentConfig: { toolDefinitions },
419
+ tokenCounter: mockTokenCounter,
420
+ });
421
+ const ctxDiscovered = createBasicContext({
422
+ agentConfig: { toolDefinitions, discoveredTools: ['deferred_tool'] },
423
+ tokenCounter: mockTokenCounter,
424
+ });
425
+
426
+ await ctxUndiscovered.tokenCalculationPromise;
427
+ await ctxDiscovered.tokenCalculationPromise;
428
+
429
+ expect(ctxUndiscovered.toolSchemaTokens).toBe(0);
430
+ expect(ctxDiscovered.toolSchemaTokens).toBeGreaterThan(0);
431
+ });
432
+
433
+ it('getTokenBudgetBreakdown toolCount excludes deferred-undiscovered toolDefinitions', () => {
434
+ const toolDefinitions: t.LCTool[] = [
435
+ {
436
+ name: 'active',
437
+ parameters: { type: 'object', properties: {} },
438
+ },
439
+ {
440
+ name: 'deferred',
441
+ defer_loading: true,
442
+ parameters: { type: 'object', properties: {} },
443
+ },
444
+ ];
445
+
446
+ const ctx = createBasicContext({ agentConfig: { toolDefinitions } });
447
+
448
+ expect(ctx.getTokenBudgetBreakdown().toolCount).toBe(1);
449
+ });
450
+
451
+ it('getTokenBudgetBreakdown toolCount reflects newly discovered deferred tools', () => {
452
+ const toolDefinitions: t.LCTool[] = [
453
+ {
454
+ name: 'deferred',
455
+ defer_loading: true,
456
+ parameters: { type: 'object', properties: {} },
457
+ },
458
+ ];
459
+
460
+ const ctx = createBasicContext({ agentConfig: { toolDefinitions } });
461
+
462
+ expect(ctx.getTokenBudgetBreakdown().toolCount).toBe(0);
463
+ ctx.markToolsAsDiscovered(['deferred']);
464
+ expect(ctx.getTokenBudgetBreakdown().toolCount).toBe(1);
465
+ });
466
+
467
+ it('toolSchemaTokens snapshot does not auto-update after markToolsAsDiscovered', async () => {
468
+ const toolDefinitions: t.LCTool[] = [
469
+ {
470
+ name: 'deferred',
471
+ description: 'Loaded via tool search',
472
+ parameters: { type: 'object', properties: {} },
473
+ defer_loading: true,
474
+ },
475
+ ];
476
+
477
+ const ctx = createBasicContext({
478
+ agentConfig: { toolDefinitions },
479
+ tokenCounter: mockTokenCounter,
480
+ });
481
+
482
+ await ctx.tokenCalculationPromise;
483
+ expect(ctx.toolSchemaTokens).toBe(0);
484
+
485
+ ctx.markToolsAsDiscovered(['deferred']);
486
+ expect(ctx.toolSchemaTokens).toBe(0);
487
+ });
378
488
  });
379
489
 
380
490
  describe('reset()', () => {
@@ -182,20 +182,8 @@ export enum Constants {
182
182
  MCP_DELIMITER = '_mcp_',
183
183
  /** Anthropic server tool ID prefix (web_search, code_execution, etc.) */
184
184
  ANTHROPIC_SERVER_TOOL_PREFIX = 'srvtoolu_',
185
- SKILL_TOOL = 'skill',
186
- READ_FILE = 'read_file',
187
- BASH_TOOL = 'bash_tool',
188
- BASH_PROGRAMMATIC_TOOL_CALLING = 'run_tools_with_bash',
189
185
  }
190
186
 
191
- /** Tool names that use the code execution environment (shared session, file tracking). */
192
- export const CODE_EXECUTION_TOOLS: ReadonlySet<string> = new Set([
193
- Constants.EXECUTE_CODE,
194
- Constants.BASH_TOOL,
195
- Constants.PROGRAMMATIC_TOOL_CALLING,
196
- Constants.BASH_PROGRAMMATIC_TOOL_CALLING,
197
- ]);
198
-
199
187
  export enum TitleMethod {
200
188
  STRUCTURED = 'structured',
201
189
  FUNCTIONS = 'functions',
@@ -53,7 +53,6 @@ import { isThinkingEnabled } from '@/llm/request';
53
53
  import { initializeModel } from '@/llm/init';
54
54
  import { HandlerRegistry } from '@/events';
55
55
  import { ChatOpenAI } from '@/llm/openai';
56
- import type { HookRegistry } from '@/hooks';
57
56
 
58
57
  const { AGENT, TOOLS, SUMMARIZE } = GraphNodeKeys;
59
58
 
@@ -124,7 +123,6 @@ export abstract class Graph<
124
123
  /** Set of invoked tool call IDs from non-message run steps completed mid-run, if any */
125
124
  invokedToolIds?: Set<string>;
126
125
  handlerRegistry: HandlerRegistry | undefined;
127
- hookRegistry: HookRegistry | undefined;
128
126
  /**
129
127
  * Tool session contexts for automatic state persistence across tool invocations.
130
128
  * Keyed by tool name (e.g., Constants.EXECUTE_CODE).
@@ -149,7 +147,6 @@ export abstract class Graph<
149
147
  this.prelimMessageIdsByStepKey = new Map();
150
148
  this.invokedToolIds = undefined;
151
149
  this.handlerRegistry = undefined;
152
- this.hookRegistry = undefined;
153
150
  this.sessions.clear();
154
151
  }
155
152
  }
@@ -509,7 +506,6 @@ export class StandardGraph extends Graph<t.BaseGraphState, t.GraphNode> {
509
506
  agentId: agentContext?.agentId,
510
507
  toolCallStepIds: this.toolCallStepIds,
511
508
  toolRegistry: agentContext?.toolRegistry,
512
- hookRegistry: this.hookRegistry,
513
509
  directToolNames: directToolNames.size > 0 ? directToolNames : undefined,
514
510
  maxContextTokens: agentContext?.maxContextTokens,
515
511
  maxToolResultChars: agentContext?.maxToolResultChars,
package/src/index.ts CHANGED
@@ -14,12 +14,7 @@ export * from './summarization';
14
14
  /* Tools */
15
15
  export * from './tools/Calculator';
16
16
  export * from './tools/CodeExecutor';
17
- export * from './tools/BashExecutor';
18
17
  export * from './tools/ProgrammaticToolCalling';
19
- export * from './tools/BashProgrammaticToolCalling';
20
- export * from './tools/SkillTool';
21
- export * from './tools/ReadFile';
22
- export * from './tools/skillCatalog';
23
18
  export * from './tools/ToolSearch';
24
19
  export * from './tools/ToolNode';
25
20
  export * from './tools/schema';
@@ -30,9 +25,6 @@ export * from './tools/search';
30
25
  export * from './common';
31
26
  export * from './utils';
32
27
 
33
- /* Hooks */
34
- export * from './hooks';
35
-
36
28
  /* Types */
37
29
  export type * from './types';
38
30
 
@@ -797,39 +797,18 @@ function contentPartCharLength(part: MessageContentComplex): number {
797
797
  return len;
798
798
  }
799
799
 
800
- /** Extracts the skillName from a skill tool_call's args (string or object). */
801
- function extractSkillName(args: unknown): string | undefined {
802
- let parsed: Record<string, unknown> | undefined;
803
- if (typeof args === 'string') {
804
- try {
805
- parsed = JSON.parse(args) as Record<string, unknown>;
806
- } catch {
807
- /* malformed args — skip */
808
- }
809
- } else {
810
- parsed = args as Record<string, unknown> | undefined;
811
- }
812
- const name = parsed?.skillName;
813
- return typeof name === 'string' && name !== '' ? name : undefined;
814
- }
815
-
816
800
  /**
817
801
  * Formats an array of messages for LangChain, handling tool calls and creating ToolMessage instances.
818
802
  *
819
803
  * @param payload - The array of messages to format.
820
804
  * @param indexTokenCountMap - Optional map of message indices to token counts.
821
805
  * @param tools - Optional set of tool names that are allowed in the request.
822
- * @param skills - Optional map of skill name to body for reconstructing skill HumanMessages.
823
806
  * @returns - Object containing formatted messages and updated indexTokenCountMap if provided.
824
807
  */
825
808
  export const formatAgentMessages = (
826
809
  payload: TPayload,
827
810
  indexTokenCountMap?: Record<number, number | undefined>,
828
- tools?: Set<string>,
829
- /** Pre-resolved skill bodies keyed by skill name. When present, HumanMessages
830
- * are reconstructed after skill ToolMessages to restore skill instructions
831
- * that were only in LangGraph state during the original run. */
832
- skills?: Map<string, string>
811
+ tools?: Set<string>
833
812
  ): {
834
813
  messages: Array<HumanMessage | AIMessage | SystemMessage | ToolMessage>;
835
814
  indexTokenCountMap?: Record<number, number>;
@@ -923,7 +902,6 @@ export const formatAgentMessages = (
923
902
  * - Dynamically expand the set when tool_search results are encountered
924
903
  */
925
904
  let processedMessage = message;
926
- let pendingSkillNames: Set<string> | undefined;
927
905
  if (discoveredTools) {
928
906
  const content = message.content;
929
907
  if (content != null && Array.isArray(content)) {
@@ -972,17 +950,8 @@ export const formatAgentMessages = (
972
950
  }
973
951
 
974
952
  if (discoveredTools.has(toolName)) {
953
+ /** Valid tool - keep it */
975
954
  filteredContent.push(part);
976
- if (
977
- toolName === Constants.SKILL_TOOL &&
978
- skills?.size != null &&
979
- skills.size > 0
980
- ) {
981
- const skillName = extractSkillName(part.tool_call.args) ?? '';
982
- if (skillName) {
983
- (pendingSkillNames ??= new Set()).add(skillName);
984
- }
985
- }
986
955
  } else {
987
956
  /** Invalid tool - convert to string for context preservation */
988
957
  if (
@@ -1058,25 +1027,6 @@ export const formatAgentMessages = (
1058
1027
  }
1059
1028
  }
1060
1029
 
1061
- /** When tools filtering is off, still detect skill tool_calls for body reconstruction */
1062
- if (!discoveredTools && skills?.size != null && skills.size > 0) {
1063
- const content = processedMessage.content;
1064
- if (Array.isArray(content)) {
1065
- for (const part of content) {
1066
- if (
1067
- part.type !== ContentTypes.TOOL_CALL ||
1068
- part.tool_call?.name !== Constants.SKILL_TOOL
1069
- ) {
1070
- continue;
1071
- }
1072
- const skillName = extractSkillName(part.tool_call.args) ?? '';
1073
- if (skillName) {
1074
- (pendingSkillNames ??= new Set()).add(skillName);
1075
- }
1076
- }
1077
- }
1078
- }
1079
-
1080
1030
  const formattedMessages = formatAssistantMessage(processedMessage);
1081
1031
  if (sourceMessageId != null && sourceMessageId !== '') {
1082
1032
  for (const formattedMessage of formattedMessages) {
@@ -1085,29 +1035,9 @@ export const formatAgentMessages = (
1085
1035
  }
1086
1036
  messages.push(...formattedMessages);
1087
1037
 
1088
- // Capture index range BEFORE skill body injection so injected
1089
- // HumanMessages are excluded from the assistant's token distribution.
1038
+ // Update the index mapping for this assistant message
1039
+ // Store all indices that were created from this original message
1090
1040
  const endMessageIndex = messages.length;
1091
-
1092
- if (pendingSkillNames?.size != null && pendingSkillNames.size > 0) {
1093
- for (const skillName of pendingSkillNames) {
1094
- const body = skills?.get(skillName) ?? '';
1095
- if (body) {
1096
- messages.push(
1097
- new HumanMessage({
1098
- content: body,
1099
- additional_kwargs: {
1100
- role: 'user',
1101
- isMeta: true,
1102
- source: 'skill',
1103
- skillName,
1104
- },
1105
- })
1106
- );
1107
- }
1108
- }
1109
- }
1110
-
1111
1041
  const resultIndices = [];
1112
1042
  for (let j = startMessageIndex; j < endMessageIndex; j++) {
1113
1043
  resultIndices.push(j);
package/src/run.ts CHANGED
@@ -22,10 +22,8 @@ import { MultiAgentGraph } from '@/graphs/MultiAgentGraph';
22
22
  import { StandardGraph } from '@/graphs/Graph';
23
23
  import { initializeModel } from '@/llm/init';
24
24
  import { HandlerRegistry } from '@/events';
25
- import { executeHooks } from '@/hooks';
26
25
  import { isOpenAILike } from '@/utils/llm';
27
26
  import { isPresent } from '@/utils/misc';
28
- import type { HookRegistry } from '@/hooks';
29
27
 
30
28
  export const defaultOmitOptions = new Set([
31
29
  'stream',
@@ -44,7 +42,6 @@ export class Run<_T extends t.BaseGraphState> {
44
42
  id: string;
45
43
  private tokenCounter?: t.TokenCounter;
46
44
  private handlerRegistry?: HandlerRegistry;
47
- private hookRegistry?: HookRegistry;
48
45
  private indexTokenCountMap?: Record<string, number>;
49
46
  calibrationRatio: number = 1;
50
47
  graphRunnable?: t.CompiledStateWorkflow;
@@ -77,7 +74,6 @@ export class Run<_T extends t.BaseGraphState> {
77
74
  }
78
75
 
79
76
  this.handlerRegistry = handlerRegistry;
80
- this.hookRegistry = config.hooks;
81
77
 
82
78
  if (!config.graphConfig) {
83
79
  throw new Error('Graph config not provided');
@@ -99,12 +95,6 @@ export class Run<_T extends t.BaseGraphState> {
99
95
  }
100
96
  }
101
97
 
102
- if (config.initialSessions && this.Graph) {
103
- for (const [key, value] of config.initialSessions) {
104
- this.Graph.sessions.set(key, value);
105
- }
106
- }
107
-
108
98
  this.returnContent = config.returnContent ?? false;
109
99
  this.skipCleanup = config.skipCleanup ?? false;
110
100
  }
@@ -153,7 +143,6 @@ export class Run<_T extends t.BaseGraphState> {
153
143
  });
154
144
  /** Propagate compile options from graph config */
155
145
  standardGraph.compileOptions = config.compileOptions;
156
- standardGraph.hookRegistry = this.hookRegistry;
157
146
  this.Graph = standardGraph;
158
147
  return standardGraph.createWorkflow();
159
148
  }
@@ -176,7 +165,6 @@ export class Run<_T extends t.BaseGraphState> {
176
165
  multiAgentGraph.compileOptions = compileOptions;
177
166
  }
178
167
 
179
- multiAgentGraph.hookRegistry = this.hookRegistry;
180
168
  this.Graph = multiAgentGraph;
181
169
  return multiAgentGraph.createWorkflow();
182
170
  }
@@ -344,47 +332,6 @@ export class Run<_T extends t.BaseGraphState> {
344
332
  run_id: this.id,
345
333
  });
346
334
 
347
- const threadId = config.configurable.thread_id as string | undefined;
348
-
349
- if (this.hookRegistry != null) {
350
- await executeHooks({
351
- registry: this.hookRegistry,
352
- input: {
353
- hook_event_name: 'RunStart',
354
- runId: this.id,
355
- threadId,
356
- agentId: this.Graph.defaultAgentId,
357
- messages: inputs.messages,
358
- },
359
- sessionId: this.id,
360
- });
361
-
362
- const lastHuman = findLastMessageOfType(inputs.messages, 'human');
363
- if (lastHuman != null) {
364
- const promptResult = await executeHooks({
365
- registry: this.hookRegistry,
366
- input: {
367
- hook_event_name: 'UserPromptSubmit',
368
- runId: this.id,
369
- threadId,
370
- agentId: this.Graph.defaultAgentId,
371
- prompt: extractPromptText(lastHuman),
372
- // attachments: not yet wired — Phase 2 will extract
373
- // non-text content blocks (images, files) from messages
374
- },
375
- sessionId: this.id,
376
- });
377
- if (
378
- promptResult.decision === 'deny' ||
379
- promptResult.decision === 'ask'
380
- ) {
381
- this.hookRegistry.clearSession(this.id);
382
- config.callbacks = undefined;
383
- return undefined;
384
- }
385
- }
386
- }
387
-
388
335
  const stream = this.graphRunnable.streamEvents(inputs, config, {
389
336
  raiseError: true,
390
337
  /**
@@ -414,45 +361,7 @@ export class Run<_T extends t.BaseGraphState> {
414
361
  await handler.handle(eventName, data, metadata, this.Graph);
415
362
  }
416
363
  }
417
-
418
- if (this.hookRegistry?.hasHookFor('Stop', this.id) === true) {
419
- await executeHooks({
420
- registry: this.hookRegistry,
421
- input: {
422
- hook_event_name: 'Stop',
423
- runId: this.id,
424
- threadId,
425
- agentId: this.Graph.defaultAgentId,
426
- messages: this.Graph.getRunMessages() ?? inputs.messages,
427
- stopHookActive: false, // will be true when stop is triggered by a hook (Phase 2)
428
- },
429
- sessionId: this.id,
430
- }).catch(() => {
431
- /* Stop hook errors must not masquerade as stream failures */
432
- });
433
- }
434
- } catch (err) {
435
- if (this.hookRegistry?.hasHookFor('StopFailure', this.id) === true) {
436
- const runMessages = this.Graph.getRunMessages() ?? [];
437
- await executeHooks({
438
- registry: this.hookRegistry,
439
- input: {
440
- hook_event_name: 'StopFailure',
441
- runId: this.id,
442
- threadId,
443
- agentId: this.Graph.defaultAgentId,
444
- error: err instanceof Error ? err.message : String(err),
445
- lastAssistantMessage: findLastMessageOfType(runMessages, 'ai'),
446
- },
447
- sessionId: this.id,
448
- }).catch(() => {
449
- /* swallow hook errors — the original error must propagate */
450
- });
451
- }
452
- throw err;
453
364
  } finally {
454
- this.hookRegistry?.clearSession(this.id);
455
-
456
365
  /**
457
366
  * Break the reference chain that keeps heavy data alive via
458
367
  * LangGraph's internal `__pregel_scratchpad.currentTaskInput` →
@@ -648,38 +557,3 @@ export class Run<_T extends t.BaseGraphState> {
648
557
  }
649
558
  }
650
559
  }
651
-
652
- function findLastMessageOfType(
653
- messages: BaseMessage[],
654
- type: string
655
- ): BaseMessage | undefined {
656
- for (let i = messages.length - 1; i >= 0; i--) {
657
- if (messages[i].getType() === type) {
658
- return messages[i];
659
- }
660
- }
661
- return undefined;
662
- }
663
-
664
- function extractPromptText(message: BaseMessage): string {
665
- const content = message.content;
666
- if (typeof content === 'string') {
667
- return content;
668
- }
669
- if (!Array.isArray(content)) {
670
- return String(content);
671
- }
672
- const parts: string[] = [];
673
- for (const block of content) {
674
- if (
675
- typeof block === 'object' &&
676
- 'type' in block &&
677
- block.type === 'text' &&
678
- 'text' in block &&
679
- typeof block.text === 'string'
680
- ) {
681
- parts.push(block.text);
682
- }
683
- }
684
- return parts.join('\n');
685
- }