toolpack-sdk 2.2.0 → 2.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -3,6 +3,263 @@ import { EventEmitter } from 'events';
3
3
  import { AuthInfo } from '@modelcontextprotocol/sdk/server/auth/types.js';
4
4
  export { AuthInfo } from '@modelcontextprotocol/sdk/server/auth/types.js';
5
5
 
6
+ interface PlanStep {
7
+ /** Unique step ID */
8
+ id: string;
9
+ /** Step number (1-indexed) */
10
+ number: number;
11
+ /** Human-readable description */
12
+ description: string;
13
+ /** Expected tools to be used (optional, for validation) */
14
+ expectedTools?: string[];
15
+ /** Dependencies on other step IDs (must complete first) */
16
+ dependsOn?: string[];
17
+ /** Step status */
18
+ status: 'pending' | 'in_progress' | 'completed' | 'failed' | 'skipped';
19
+ /** Result after completion */
20
+ result?: {
21
+ success: boolean;
22
+ output?: string;
23
+ error?: string;
24
+ toolsUsed?: string[];
25
+ duration?: number;
26
+ response?: CompletionResponse;
27
+ };
28
+ }
29
+ interface Plan {
30
+ /** Unique plan ID */
31
+ id: string;
32
+ /** Original user request */
33
+ request: string;
34
+ /** Plan summary/goal */
35
+ summary: string;
36
+ /** Ordered steps */
37
+ steps: PlanStep[];
38
+ /** Plan status */
39
+ status: 'draft' | 'approved' | 'in_progress' | 'completed' | 'failed' | 'cancelled';
40
+ /** Timestamps */
41
+ createdAt: Date;
42
+ startedAt?: Date;
43
+ completedAt?: Date;
44
+ /** Raw response from the planning phase */
45
+ planningResponse?: CompletionResponse;
46
+ /** Metrics */
47
+ metrics?: {
48
+ totalDuration: number;
49
+ stepsCompleted: number;
50
+ stepsFailed: number;
51
+ retriesUsed: number;
52
+ };
53
+ }
54
+
55
+ interface WorkflowConfig {
56
+ /**
57
+ * Workflow name for display purposes.
58
+ */
59
+ name?: string;
60
+ /**
61
+ * Planning phase configuration.
62
+ * If enabled, AI generates a plan before executing.
63
+ */
64
+ planning?: {
65
+ /** Enable planning phase. Default: false */
66
+ enabled: boolean;
67
+ /** Pause for user approval before executing plan. Default: false */
68
+ requireApproval?: boolean;
69
+ /** Custom system prompt for plan generation. */
70
+ planningPrompt?: string;
71
+ /** Maximum number of steps allowed in a plan. Default: 20 */
72
+ maxSteps?: number;
73
+ };
74
+ /**
75
+ * Progress reporting configuration.
76
+ */
77
+ progress?: {
78
+ /** Emit progress events. Default: true */
79
+ enabled: boolean;
80
+ /** Report estimated completion percentage. Default: true */
81
+ reportPercentage?: boolean;
82
+ };
83
+ /**
84
+ * Query complexity routing configuration.
85
+ * Routes simple queries to faster execution paths based on query classification.
86
+ */
87
+ complexityRouting?: {
88
+ /** Enable complexity-based routing. Default: false (opt-in) */
89
+ enabled: boolean;
90
+ /** Routing strategy for simple queries. Default: 'single-step' */
91
+ strategy: 'single-step' | 'bypass' | 'disabled';
92
+ /** Confidence threshold for routing analytical queries. Default: 0.6 */
93
+ confidenceThreshold?: number;
94
+ };
95
+ }
96
+ /**
97
+ * Default workflow config (direct execution, no planning).
98
+ */
99
+ declare const DEFAULT_WORKFLOW_CONFIG: WorkflowConfig;
100
+ interface WorkflowEvents {
101
+ /** Emitted when a plan is created (before approval if required) */
102
+ 'workflow:plan_created': (plan: Plan) => void;
103
+ /** Emitted when user approves/rejects a plan */
104
+ 'workflow:plan_decision': (plan: Plan, approved: boolean) => void;
105
+ /** Emitted when plan execution starts */
106
+ 'workflow:started': (plan: Plan) => void;
107
+ /** Emitted for progress updates */
108
+ 'workflow:progress': (progress: WorkflowProgress) => void;
109
+ /** Emitted when context window usage is high (approaching limit) */
110
+ 'workflow:context_warning': (event: ContextWindowWarningEvent) => void;
111
+ /** Emitted when context window would be exceeded */
112
+ 'workflow:context_exceeded': (event: ContextWindowExceededEvent) => void;
113
+ /** Emitted when messages are pruned to recover context */
114
+ 'workflow:context_pruned': (event: ContextPrunedEvent) => void;
115
+ /** Emitted when conversation is summarized for context recovery */
116
+ 'workflow:conversation_summarized': (event: ConversationSummarizedEvent) => void;
117
+ /** Emitted when workflow completes */
118
+ 'workflow:completed': (plan: Plan, result: WorkflowResult) => void;
119
+ /** Emitted when workflow fails */
120
+ 'workflow:failed': (plan: Plan, error: Error) => void;
121
+ }
122
+ interface ContextWindowWarningEvent {
123
+ currentTokens: number;
124
+ contextWindow: number;
125
+ percentage: number;
126
+ model: string;
127
+ conversationId?: string;
128
+ }
129
+ interface ContextWindowExceededEvent {
130
+ currentTokens: number;
131
+ contextWindow: number;
132
+ maxOutputTokens: number;
133
+ model: string;
134
+ strategy: 'prune' | 'summarize' | 'fail';
135
+ conversationId?: string;
136
+ }
137
+ interface ContextPrunedEvent {
138
+ removed: number;
139
+ tokensReclaimed: number;
140
+ newTotal: number;
141
+ conversationId?: string;
142
+ beforeCount: number;
143
+ afterCount: number;
144
+ }
145
+ interface ConversationSummarizedEvent {
146
+ summarized: number;
147
+ summaryTokens: number;
148
+ tokensSaved: number;
149
+ conversationId?: string;
150
+ }
151
+ interface WorkflowProgress {
152
+ planId: string;
153
+ currentStep: number;
154
+ totalSteps: number;
155
+ percentage: number;
156
+ currentStepDescription: string;
157
+ status: 'planning' | 'awaiting_approval' | 'executing' | 'completed' | 'failed';
158
+ }
159
+ interface WorkflowResult {
160
+ success: boolean;
161
+ plan: Plan;
162
+ output?: string;
163
+ error?: string;
164
+ response?: CompletionResponse;
165
+ metrics: {
166
+ totalDuration: number;
167
+ stepsCompleted: number;
168
+ stepsFailed: number;
169
+ retriesUsed: number;
170
+ };
171
+ }
172
+
173
+ /**
174
+ * Configuration for an AI agent mode.
175
+ * A mode shapes AI behavior by controlling which tools are available
176
+ * and injecting a persona-specific system prompt.
177
+ */
178
+ interface ModeConfig {
179
+ /** Unique identifier for the mode (e.g., "all", "ask", "code") */
180
+ name: string;
181
+ /** Human-readable display name (e.g., "All", "Ask", "Code") */
182
+ displayName: string;
183
+ /** Short description for UI tooltips */
184
+ description: string;
185
+ /**
186
+ * System prompt prepended to every request in this mode.
187
+ * Empty string means no system prompt injection (passthrough).
188
+ */
189
+ systemPrompt: string;
190
+ /**
191
+ * Base agent context configuration for this mode.
192
+ * Controls whether working directory and tool categories are injected into system prompt.
193
+ *
194
+ * - undefined: Use global default behavior (include everything)
195
+ * - false: Disable base context entirely
196
+ * - object: Fine-grained control over what is included
197
+ */
198
+ baseContext?: {
199
+ /** Include working directory in system prompt. Default: true */
200
+ includeWorkingDirectory?: boolean;
201
+ /** Include available tool categories. Default: true */
202
+ includeToolCategories?: boolean;
203
+ /** Custom base context string (overrides auto-generated). */
204
+ custom?: string;
205
+ } | false;
206
+ /** Workflow configuration controlling planning, steps, and progress. */
207
+ workflow?: WorkflowConfig;
208
+ /**
209
+ * Tool search configuration specific to this mode.
210
+ * Overrides or extends the global toolSearch config.
211
+ */
212
+ toolSearch?: {
213
+ /** Enable/disable tool search for this mode */
214
+ enabled?: boolean;
215
+ /** Tools to always include (never defer) for this mode */
216
+ alwaysLoadedTools?: string[];
217
+ /** Categories to always include for this mode */
218
+ alwaysLoadedCategories?: string[];
219
+ };
220
+ /**
221
+ * Tool categories allowed in this mode.
222
+ * Empty array means all categories are allowed (unless blocked).
223
+ */
224
+ allowedToolCategories: string[];
225
+ /**
226
+ * Tool categories explicitly blocked in this mode.
227
+ * Takes precedence over allowedToolCategories.
228
+ */
229
+ blockedToolCategories: string[];
230
+ /**
231
+ * Specific tool names allowed in this mode.
232
+ * Empty array means all tools are allowed (unless blocked).
233
+ */
234
+ allowedTools: string[];
235
+ /**
236
+ * Specific tool names explicitly blocked in this mode.
237
+ * Takes precedence over allowedTools.
238
+ */
239
+ blockedTools: string[];
240
+ /**
241
+ * If true, ALL tools are blocked regardless of other settings.
242
+ * Shorthand for "no tool calls at all".
243
+ */
244
+ blockAllTools: boolean;
245
+ /**
246
+ * Response format constraint for all requests in this mode.
247
+ * - 'json_object': instructs the model to return valid JSON as its text content.
248
+ * Useful for evaluator/parser agents whose final response must be machine-readable.
249
+ * Tool-call rounds are unaffected — the model still returns functionCall parts
250
+ * normally; the format only applies to text content.
251
+ * - 'text' (default): plain text, no constraint.
252
+ */
253
+ response_format?: 'text' | 'json_object';
254
+ }
255
+ /**
256
+ * A lightweight reference to a mode, used in tool-blocked hints.
257
+ */
258
+ interface ModeBlockedHint {
259
+ blockedToolNames: string[];
260
+ suggestedMode: string;
261
+ }
262
+
6
263
  /**
7
264
  * Core type definitions for the Tool Calling System.
8
265
  */
@@ -319,6 +576,18 @@ interface CompletionRequest<T = unknown> {
319
576
  * Useful for agents that should only ever make one tool call (e.g. routers).
320
577
  */
321
578
  maxToolRounds?: number;
579
+ /**
580
+ * Per-request mode override. Snapshotted for the entire duration of the
581
+ * request — concurrent `setMode()` calls (e.g. from another agent sharing
582
+ * this Toolpack instance during awaited delegation) cannot affect an
583
+ * in-flight request's system prompt, tool filtering, or response format.
584
+ *
585
+ * - `ModeConfig` — use this mode for the request
586
+ * - `string` — mode name, resolved from Toolpack's mode registry
587
+ * - `null` — explicitly run without a mode
588
+ * - omitted — snapshot the instance's active mode at request start
589
+ */
590
+ mode?: ModeConfig | string | null;
322
591
  }
323
592
  interface Usage {
324
593
  prompt_tokens: number;
@@ -731,358 +1000,101 @@ declare class ToolRegistry {
731
1000
  private projects;
732
1001
  private config;
733
1002
  /**
734
- * Register a tool (built-in or custom).
735
- */
736
- register(tool: ToolDefinition): void;
737
- /**
738
- * Register a custom tool provided by the consumer.
739
- * Identical to register() but semantically distinct for clarity.
740
- */
741
- registerCustom(tool: ToolDefinition): void;
742
- /**
743
- * Get a tool by name.
744
- */
745
- get(name: string): ToolDefinition | undefined;
746
- /**
747
- * Check if a tool exists.
748
- */
749
- has(name: string): boolean;
750
- /**
751
- * Get all registered tool names.
752
- */
753
- getNames(): string[];
754
- /**
755
- * Get all tools in a specific category.
756
- */
757
- getByCategory(category: string): ToolDefinition[];
758
- /**
759
- * Get all enabled tools based on config.
760
- * If enabledTools and enabledToolCategories are both empty, returns all registered tools.
761
- * Otherwise, returns only tools from enabledTools[] + enabledToolCategories[].
762
- */
763
- getEnabled(): ToolDefinition[];
764
- /**
765
- * Get tool schemas suitable for sending to AI providers.
766
- * If toolNames is provided, only return schemas for those tools.
767
- * Otherwise, return schemas for all enabled tools.
768
- */
769
- getSchemas(toolNames?: string[]): ToolSchema[];
770
- /**
771
- * Get all tools matching a list of names.
772
- */
773
- getByNames(names: string[]): ToolDefinition[];
774
- /**
775
- * Get all tools matching a list of categories.
776
- */
777
- getByCategories(categories: string[]): ToolDefinition[];
778
- /**
779
- * Get all registered categories (derived from tools).
780
- */
781
- getCategories(): string[];
782
- /**
783
- * Get all registered tools.
784
- * Used by BM25SearchEngine for indexing.
785
- */
786
- getAll(): ToolDefinition[];
787
- /**
788
- * Update the config (called by config loader).
789
- */
790
- setConfig(config: ToolsConfig): void;
791
- /**
792
- * Get the current config.
793
- */
794
- getConfig(): ToolsConfig;
795
- /**
796
- * Get the total number of registered tools.
797
- */
798
- get size(): number;
799
- /**
800
- * Validate that a tool project's declared dependencies are resolvable.
801
- * Returns an array of missing package names (empty = all good).
802
- */
803
- validateDependencies(project: ToolProject): Promise<string[]>;
804
- /**
805
- * Load a single tool project into the registry.
806
- * Validates dependencies before loading — throws if any are missing.
807
- */
808
- loadProject(project: ToolProject): Promise<void>;
809
- /**
810
- * Load multiple tool projects.
811
- */
812
- loadProjects(projects: ToolProject[]): Promise<void>;
813
- /**
814
- * Get a loaded project by name.
815
- */
816
- getProject(name: string): ToolProject | undefined;
817
- /**
818
- * Get all loaded projects.
819
- */
820
- getProjects(): ToolProject[];
821
- /**
822
- * Get all loaded project names.
823
- */
824
- getProjectNames(): string[];
825
- /**
826
- * Load all built-in tool projects.
827
- */
828
- loadBuiltIn(): Promise<void>;
829
- }
830
-
831
- interface PlanStep {
832
- /** Unique step ID */
833
- id: string;
834
- /** Step number (1-indexed) */
835
- number: number;
836
- /** Human-readable description */
837
- description: string;
838
- /** Expected tools to be used (optional, for validation) */
839
- expectedTools?: string[];
840
- /** Dependencies on other step IDs (must complete first) */
841
- dependsOn?: string[];
842
- /** Step status */
843
- status: 'pending' | 'in_progress' | 'completed' | 'failed' | 'skipped';
844
- /** Result after completion */
845
- result?: {
846
- success: boolean;
847
- output?: string;
848
- error?: string;
849
- toolsUsed?: string[];
850
- duration?: number;
851
- response?: CompletionResponse;
852
- };
853
- }
854
- interface Plan {
855
- /** Unique plan ID */
856
- id: string;
857
- /** Original user request */
858
- request: string;
859
- /** Plan summary/goal */
860
- summary: string;
861
- /** Ordered steps */
862
- steps: PlanStep[];
863
- /** Plan status */
864
- status: 'draft' | 'approved' | 'in_progress' | 'completed' | 'failed' | 'cancelled';
865
- /** Timestamps */
866
- createdAt: Date;
867
- startedAt?: Date;
868
- completedAt?: Date;
869
- /** Raw response from the planning phase */
870
- planningResponse?: CompletionResponse;
871
- /** Metrics */
872
- metrics?: {
873
- totalDuration: number;
874
- stepsCompleted: number;
875
- stepsFailed: number;
876
- retriesUsed: number;
877
- };
878
- }
879
-
880
- interface WorkflowConfig {
881
- /**
882
- * Workflow name for display purposes.
1003
+ * Register a tool (built-in or custom).
883
1004
  */
884
- name?: string;
1005
+ register(tool: ToolDefinition): void;
885
1006
  /**
886
- * Planning phase configuration.
887
- * If enabled, AI generates a plan before executing.
1007
+ * Register a custom tool provided by the consumer.
1008
+ * Identical to register() but semantically distinct for clarity.
888
1009
  */
889
- planning?: {
890
- /** Enable planning phase. Default: false */
891
- enabled: boolean;
892
- /** Pause for user approval before executing plan. Default: false */
893
- requireApproval?: boolean;
894
- /** Custom system prompt for plan generation. */
895
- planningPrompt?: string;
896
- /** Maximum number of steps allowed in a plan. Default: 20 */
897
- maxSteps?: number;
898
- };
1010
+ registerCustom(tool: ToolDefinition): void;
899
1011
  /**
900
- * Progress reporting configuration.
1012
+ * Get a tool by name.
901
1013
  */
902
- progress?: {
903
- /** Emit progress events. Default: true */
904
- enabled: boolean;
905
- /** Report estimated completion percentage. Default: true */
906
- reportPercentage?: boolean;
907
- };
1014
+ get(name: string): ToolDefinition | undefined;
908
1015
  /**
909
- * Query complexity routing configuration.
910
- * Routes simple queries to faster execution paths based on query classification.
1016
+ * Check if a tool exists.
911
1017
  */
912
- complexityRouting?: {
913
- /** Enable complexity-based routing. Default: false (opt-in) */
914
- enabled: boolean;
915
- /** Routing strategy for simple queries. Default: 'single-step' */
916
- strategy: 'single-step' | 'bypass' | 'disabled';
917
- /** Confidence threshold for routing analytical queries. Default: 0.6 */
918
- confidenceThreshold?: number;
919
- };
920
- }
921
- /**
922
- * Default workflow config (direct execution, no planning).
923
- */
924
- declare const DEFAULT_WORKFLOW_CONFIG: WorkflowConfig;
925
- interface WorkflowEvents {
926
- /** Emitted when a plan is created (before approval if required) */
927
- 'workflow:plan_created': (plan: Plan) => void;
928
- /** Emitted when user approves/rejects a plan */
929
- 'workflow:plan_decision': (plan: Plan, approved: boolean) => void;
930
- /** Emitted when plan execution starts */
931
- 'workflow:started': (plan: Plan) => void;
932
- /** Emitted for progress updates */
933
- 'workflow:progress': (progress: WorkflowProgress) => void;
934
- /** Emitted when context window usage is high (approaching limit) */
935
- 'workflow:context_warning': (event: ContextWindowWarningEvent) => void;
936
- /** Emitted when context window would be exceeded */
937
- 'workflow:context_exceeded': (event: ContextWindowExceededEvent) => void;
938
- /** Emitted when messages are pruned to recover context */
939
- 'workflow:context_pruned': (event: ContextPrunedEvent) => void;
940
- /** Emitted when conversation is summarized for context recovery */
941
- 'workflow:conversation_summarized': (event: ConversationSummarizedEvent) => void;
942
- /** Emitted when workflow completes */
943
- 'workflow:completed': (plan: Plan, result: WorkflowResult) => void;
944
- /** Emitted when workflow fails */
945
- 'workflow:failed': (plan: Plan, error: Error) => void;
946
- }
947
- interface ContextWindowWarningEvent {
948
- currentTokens: number;
949
- contextWindow: number;
950
- percentage: number;
951
- model: string;
952
- conversationId?: string;
953
- }
954
- interface ContextWindowExceededEvent {
955
- currentTokens: number;
956
- contextWindow: number;
957
- maxOutputTokens: number;
958
- model: string;
959
- strategy: 'prune' | 'summarize' | 'fail';
960
- conversationId?: string;
961
- }
962
- interface ContextPrunedEvent {
963
- removed: number;
964
- tokensReclaimed: number;
965
- newTotal: number;
966
- conversationId?: string;
967
- beforeCount: number;
968
- afterCount: number;
969
- }
970
- interface ConversationSummarizedEvent {
971
- summarized: number;
972
- summaryTokens: number;
973
- tokensSaved: number;
974
- conversationId?: string;
975
- }
976
- interface WorkflowProgress {
977
- planId: string;
978
- currentStep: number;
979
- totalSteps: number;
980
- percentage: number;
981
- currentStepDescription: string;
982
- status: 'planning' | 'awaiting_approval' | 'executing' | 'completed' | 'failed';
983
- }
984
- interface WorkflowResult {
985
- success: boolean;
986
- plan: Plan;
987
- output?: string;
988
- error?: string;
989
- response?: CompletionResponse;
990
- metrics: {
991
- totalDuration: number;
992
- stepsCompleted: number;
993
- stepsFailed: number;
994
- retriesUsed: number;
995
- };
996
- }
997
-
998
- /**
999
- * Configuration for an AI agent mode.
1000
- * A mode shapes AI behavior by controlling which tools are available
1001
- * and injecting a persona-specific system prompt.
1002
- */
1003
- interface ModeConfig {
1004
- /** Unique identifier for the mode (e.g., "all", "ask", "code") */
1005
- name: string;
1006
- /** Human-readable display name (e.g., "All", "Ask", "Code") */
1007
- displayName: string;
1008
- /** Short description for UI tooltips */
1009
- description: string;
1018
+ has(name: string): boolean;
1010
1019
  /**
1011
- * System prompt prepended to every request in this mode.
1012
- * Empty string means no system prompt injection (passthrough).
1020
+ * Get all registered tool names.
1013
1021
  */
1014
- systemPrompt: string;
1022
+ getNames(): string[];
1015
1023
  /**
1016
- * Base agent context configuration for this mode.
1017
- * Controls whether working directory and tool categories are injected into system prompt.
1018
- *
1019
- * - undefined: Use global default behavior (include everything)
1020
- * - false: Disable base context entirely
1021
- * - object: Fine-grained control over what is included
1024
+ * Get all tools in a specific category.
1022
1025
  */
1023
- baseContext?: {
1024
- /** Include working directory in system prompt. Default: true */
1025
- includeWorkingDirectory?: boolean;
1026
- /** Include available tool categories. Default: true */
1027
- includeToolCategories?: boolean;
1028
- /** Custom base context string (overrides auto-generated). */
1029
- custom?: string;
1030
- } | false;
1031
- /** Workflow configuration controlling planning, steps, and progress. */
1032
- workflow?: WorkflowConfig;
1026
+ getByCategory(category: string): ToolDefinition[];
1033
1027
  /**
1034
- * Tool search configuration specific to this mode.
1035
- * Overrides or extends the global toolSearch config.
1028
+ * Get all enabled tools based on config.
1029
+ * If enabledTools and enabledToolCategories are both empty, returns all registered tools.
1030
+ * Otherwise, returns only tools from enabledTools[] + enabledToolCategories[].
1036
1031
  */
1037
- toolSearch?: {
1038
- /** Enable/disable tool search for this mode */
1039
- enabled?: boolean;
1040
- /** Tools to always include (never defer) for this mode */
1041
- alwaysLoadedTools?: string[];
1042
- /** Categories to always include for this mode */
1043
- alwaysLoadedCategories?: string[];
1044
- };
1032
+ getEnabled(): ToolDefinition[];
1045
1033
  /**
1046
- * Tool categories allowed in this mode.
1047
- * Empty array means all categories are allowed (unless blocked).
1034
+ * Get tool schemas suitable for sending to AI providers.
1035
+ * If toolNames is provided, only return schemas for those tools.
1036
+ * Otherwise, return schemas for all enabled tools.
1048
1037
  */
1049
- allowedToolCategories: string[];
1038
+ getSchemas(toolNames?: string[]): ToolSchema[];
1050
1039
  /**
1051
- * Tool categories explicitly blocked in this mode.
1052
- * Takes precedence over allowedToolCategories.
1040
+ * Get all tools matching a list of names.
1053
1041
  */
1054
- blockedToolCategories: string[];
1042
+ getByNames(names: string[]): ToolDefinition[];
1055
1043
  /**
1056
- * Specific tool names allowed in this mode.
1057
- * Empty array means all tools are allowed (unless blocked).
1044
+ * Get all tools matching a list of categories.
1058
1045
  */
1059
- allowedTools: string[];
1046
+ getByCategories(categories: string[]): ToolDefinition[];
1060
1047
  /**
1061
- * Specific tool names explicitly blocked in this mode.
1062
- * Takes precedence over allowedTools.
1048
+ * Get all registered categories (derived from tools).
1063
1049
  */
1064
- blockedTools: string[];
1050
+ getCategories(): string[];
1065
1051
  /**
1066
- * If true, ALL tools are blocked regardless of other settings.
1067
- * Shorthand for "no tool calls at all".
1052
+ * Get all registered tools.
1053
+ * Used by BM25SearchEngine for indexing.
1068
1054
  */
1069
- blockAllTools: boolean;
1055
+ getAll(): ToolDefinition[];
1070
1056
  /**
1071
- * Response format constraint for all requests in this mode.
1072
- * - 'json_object': instructs the model to return valid JSON as its text content.
1073
- * Useful for evaluator/parser agents whose final response must be machine-readable.
1074
- * Tool-call rounds are unaffected — the model still returns functionCall parts
1075
- * normally; the format only applies to text content.
1076
- * - 'text' (default): plain text, no constraint.
1057
+ * Update the config (called by config loader).
1077
1058
  */
1078
- response_format?: 'text' | 'json_object';
1079
- }
1080
- /**
1081
- * A lightweight reference to a mode, used in tool-blocked hints.
1082
- */
1083
- interface ModeBlockedHint {
1084
- blockedToolNames: string[];
1085
- suggestedMode: string;
1059
+ setConfig(config: ToolsConfig): void;
1060
+ /**
1061
+ * Get the current config.
1062
+ */
1063
+ getConfig(): ToolsConfig;
1064
+ /**
1065
+ * Get the total number of registered tools.
1066
+ */
1067
+ get size(): number;
1068
+ /**
1069
+ * Validate that a tool project's declared dependencies are resolvable.
1070
+ * Returns an array of missing package names (empty = all good).
1071
+ */
1072
+ validateDependencies(project: ToolProject): Promise<string[]>;
1073
+ /**
1074
+ * Load a single tool project into the registry.
1075
+ * Validates dependencies before loading — throws if any are missing.
1076
+ */
1077
+ loadProject(project: ToolProject): Promise<void>;
1078
+ /**
1079
+ * Load multiple tool projects.
1080
+ */
1081
+ loadProjects(projects: ToolProject[]): Promise<void>;
1082
+ /**
1083
+ * Get a loaded project by name.
1084
+ */
1085
+ getProject(name: string): ToolProject | undefined;
1086
+ /**
1087
+ * Get all loaded projects.
1088
+ */
1089
+ getProjects(): ToolProject[];
1090
+ /**
1091
+ * Get all loaded project names.
1092
+ */
1093
+ getProjectNames(): string[];
1094
+ /**
1095
+ * Load all built-in tool projects.
1096
+ */
1097
+ loadBuiltIn(): Promise<void>;
1086
1098
  }
1087
1099
 
1088
1100
  type ConfirmationLevel = 'high' | 'medium';
@@ -1342,6 +1354,11 @@ declare class AIClient extends EventEmitter {
1342
1354
  * Enrich a request with tools based on the router config.
1343
1355
  * Applies mode-based tool filtering when an active mode is set.
1344
1356
  */
1357
+ /**
1358
+ * @param mode Mode snapshot taken at request start. Passed explicitly (not
1359
+ * read from `this.activeMode`) so that per-round re-enrichment inside the
1360
+ * tool loop is immune to concurrent `setMode()` calls on this instance.
1361
+ */
1345
1362
  private enrichRequestWithTools;
1346
1363
  private buildRequestToolMap;
1347
1364
  private requestToolToSchema;
@@ -1350,13 +1367,24 @@ declare class AIClient extends EventEmitter {
1350
1367
  private mergeToolCallRequests;
1351
1368
  private injectRequestToolGuidance;
1352
1369
  private stripRequestTools;
1370
+ /**
1371
+ * Resolve the mode snapshot for a request.
1372
+ *
1373
+ * - `request.mode` omitted → snapshot the instance's activeMode now
1374
+ * - `request.mode === null` → explicitly no mode
1375
+ * - `request.mode` is a ModeConfig → use it directly
1376
+ * - `request.mode` is a string → mode names are resolved by Toolpack (which
1377
+ * owns the mode registry) before reaching the client; if an unresolved
1378
+ * name gets here, warn and fall back to the activeMode snapshot
1379
+ */
1380
+ private resolveRequestMode;
1353
1381
  /**
1354
1382
  * Filter tool schemas based on mode permissions.
1355
1383
  * blockedTools/blockedToolCategories always take precedence.
1356
1384
  */
1357
1385
  private filterSchemasByMode;
1358
1386
  /**
1359
- * Inject the active mode's system prompt into the request messages.
1387
+ * Inject the given mode's system prompt into the request messages.
1360
1388
  * For the "All" mode (empty systemPrompt), this is a no-op.
1361
1389
  */
1362
1390
  private injectModeSystemPrompt;
@@ -1390,7 +1418,7 @@ declare class AIClient extends EventEmitter {
1390
1418
  /**
1391
1419
  * Execute tool.search using BM25 engine.
1392
1420
  */
1393
- executeToolSearch(args: Record<string, any>): string;
1421
+ executeToolSearch(args: Record<string, any>, mode?: ModeConfig | null): string;
1394
1422
  private wrapError;
1395
1423
  /**
1396
1424
  * Truncate a tool result to fit within the remaining round budget.
@@ -3040,6 +3068,13 @@ declare class Toolpack extends EventEmitter {
3040
3068
  */
3041
3069
  private static createProvider;
3042
3070
  generate(request: CompletionRequest | string, providerName?: string): Promise<CompletionResponse>;
3071
+ /**
3072
+ * Resolve a string `mode` on the request to its registered ModeConfig.
3073
+ * The AIClient cannot resolve names (the mode registry lives here), so
3074
+ * names must be resolved before the request reaches the client.
3075
+ * Throws for unknown names — same contract as setMode().
3076
+ */
3077
+ private resolveRequestModeName;
3043
3078
  private _buildInterceptorChain;
3044
3079
  stream(request: CompletionRequest, providerName?: string): AsyncGenerator<CompletionChunk>;
3045
3080
  embed(request: EmbeddingRequest, providerName?: string): Promise<EmbeddingResponse>;