@jaypie/llm 1.3.7 → 1.3.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.
@@ -227,9 +227,21 @@ declare class Toolkit {
227
227
  private readonly log;
228
228
  constructor(tools: LlmTool[], options?: ToolkitOptions);
229
229
  get tools(): Omit<LlmTool, "call">[];
230
- call({ name, arguments: args }: {
230
+ private parseArgs;
231
+ /**
232
+ * Resolve a tool's `message` (static string or function of args) without
233
+ * calling the tool. Returns undefined when the tool is missing or defines
234
+ * no message. Never throws; resolution errors log at warn.
235
+ */
236
+ resolveMessage({ name, arguments: args, }: {
237
+ name: string;
238
+ arguments: string;
239
+ }): Promise<string | undefined>;
240
+ call({ name, arguments: args, message: resolvedMessage, }: {
231
241
  name: string;
232
242
  arguments: string;
243
+ /** Pre-resolved tool message; skips re-resolving `tool.message` for logging */
244
+ message?: string;
233
245
  }): Promise<_jaypie_types.AnyValue>;
234
246
  extend(tools: LlmTool[], options?: {
235
247
  warn?: boolean;
@@ -415,6 +427,8 @@ declare enum LlmProgressEventType {
415
427
  interface LlmProgressToolCall {
416
428
  /** JSON string of arguments (tool_call events only) */
417
429
  arguments?: string;
430
+ /** Resolved `LlmTool.message`, when the tool defines one (tool_call events only) */
431
+ message?: string;
418
432
  /** Tool name */
419
433
  name: string;
420
434
  }
@@ -461,19 +475,23 @@ interface LlmOperateOptions {
461
475
  content: string | JsonObject;
462
476
  usage: LlmUsage;
463
477
  }) => unknown | Promise<unknown>;
464
- afterEachTool?: ({ result, toolName, args, }: {
478
+ afterEachTool?: ({ result, toolName, args, message, }: {
465
479
  result: unknown;
466
480
  toolName: string;
467
481
  args: string;
482
+ /** Resolved `LlmTool.message`, when the tool defines one */
483
+ message?: string;
468
484
  }) => unknown | Promise<unknown>;
469
485
  beforeEachModelRequest?: ({ input, options, providerRequest, }: {
470
486
  input: string | LlmHistory | LlmInputMessage;
471
487
  options?: LlmOperateOptions;
472
488
  providerRequest: any;
473
489
  }) => unknown | Promise<unknown>;
474
- beforeEachTool?: ({ toolName, args, }: {
490
+ beforeEachTool?: ({ toolName, args, message, }: {
475
491
  toolName: string;
476
492
  args: string;
493
+ /** Resolved `LlmTool.message`, when the tool defines one */
494
+ message?: string;
477
495
  }) => unknown | Promise<unknown>;
478
496
  onRetryableModelError?: ({ input, options, providerRequest, error, }: {
479
497
  input: string | LlmHistory | LlmInputMessage;
@@ -481,10 +499,12 @@ interface LlmOperateOptions {
481
499
  providerRequest: any;
482
500
  error: any;
483
501
  }) => unknown | Promise<unknown>;
484
- onToolError?: ({ error, toolName, args, }: {
502
+ onToolError?: ({ error, toolName, args, message, }: {
485
503
  error: Error;
486
504
  toolName: string;
487
505
  args: string;
506
+ /** Resolved `LlmTool.message`, when the tool defines one */
507
+ message?: string;
488
508
  }) => unknown | Promise<unknown>;
489
509
  onUnrecoverableModelError?: ({ input, options, providerRequest, error, }: {
490
510
  input: string | LlmHistory | LlmInputMessage;
@@ -15,16 +15,19 @@ export interface AfterModelResponseContext {
15
15
  }
16
16
  export interface BeforeToolContext {
17
17
  args: string;
18
+ message?: string;
18
19
  toolName: string;
19
20
  }
20
21
  export interface AfterToolContext {
21
22
  args: string;
23
+ message?: string;
22
24
  result: unknown;
23
25
  toolName: string;
24
26
  }
25
27
  export interface ToolErrorContext {
26
28
  args: string;
27
29
  error: Error;
30
+ message?: string;
28
31
  toolName: string;
29
32
  }
30
33
  export interface RetryableErrorContext {
@@ -14,9 +14,21 @@ export declare class Toolkit {
14
14
  private readonly log;
15
15
  constructor(tools: LlmTool[], options?: ToolkitOptions);
16
16
  get tools(): Omit<LlmTool, "call">[];
17
- call({ name, arguments: args }: {
17
+ private parseArgs;
18
+ /**
19
+ * Resolve a tool's `message` (static string or function of args) without
20
+ * calling the tool. Returns undefined when the tool is missing or defines
21
+ * no message. Never throws; resolution errors log at warn.
22
+ */
23
+ resolveMessage({ name, arguments: args, }: {
18
24
  name: string;
19
25
  arguments: string;
26
+ }): Promise<string | undefined>;
27
+ call({ name, arguments: args, message: resolvedMessage, }: {
28
+ name: string;
29
+ arguments: string;
30
+ /** Pre-resolved tool message; skips re-resolving `tool.message` for logging */
31
+ message?: string;
20
32
  }): Promise<import("@jaypie/types").AnyValue>;
21
33
  extend(tools: LlmTool[], options?: {
22
34
  warn?: boolean;
@@ -179,6 +179,8 @@ export declare enum LlmProgressEventType {
179
179
  export interface LlmProgressToolCall {
180
180
  /** JSON string of arguments (tool_call events only) */
181
181
  arguments?: string;
182
+ /** Resolved `LlmTool.message`, when the tool defines one (tool_call events only) */
183
+ message?: string;
182
184
  /** Tool name */
183
185
  name: string;
184
186
  }
@@ -225,19 +227,23 @@ export interface LlmOperateOptions {
225
227
  content: string | JsonObject;
226
228
  usage: LlmUsage;
227
229
  }) => unknown | Promise<unknown>;
228
- afterEachTool?: ({ result, toolName, args, }: {
230
+ afterEachTool?: ({ result, toolName, args, message, }: {
229
231
  result: unknown;
230
232
  toolName: string;
231
233
  args: string;
234
+ /** Resolved `LlmTool.message`, when the tool defines one */
235
+ message?: string;
232
236
  }) => unknown | Promise<unknown>;
233
237
  beforeEachModelRequest?: ({ input, options, providerRequest, }: {
234
238
  input: string | LlmHistory | LlmInputMessage;
235
239
  options?: LlmOperateOptions;
236
240
  providerRequest: any;
237
241
  }) => unknown | Promise<unknown>;
238
- beforeEachTool?: ({ toolName, args, }: {
242
+ beforeEachTool?: ({ toolName, args, message, }: {
239
243
  toolName: string;
240
244
  args: string;
245
+ /** Resolved `LlmTool.message`, when the tool defines one */
246
+ message?: string;
241
247
  }) => unknown | Promise<unknown>;
242
248
  onRetryableModelError?: ({ input, options, providerRequest, error, }: {
243
249
  input: string | LlmHistory | LlmInputMessage;
@@ -245,10 +251,12 @@ export interface LlmOperateOptions {
245
251
  providerRequest: any;
246
252
  error: any;
247
253
  }) => unknown | Promise<unknown>;
248
- onToolError?: ({ error, toolName, args, }: {
254
+ onToolError?: ({ error, toolName, args, message, }: {
249
255
  error: Error;
250
256
  toolName: string;
251
257
  args: string;
258
+ /** Resolved `LlmTool.message`, when the tool defines one */
259
+ message?: string;
252
260
  }) => unknown | Promise<unknown>;
253
261
  onUnrecoverableModelError?: ({ input, options, providerRequest, error, }: {
254
262
  input: string | LlmHistory | LlmInputMessage;
@@ -227,9 +227,21 @@ declare class Toolkit {
227
227
  private readonly log;
228
228
  constructor(tools: LlmTool[], options?: ToolkitOptions);
229
229
  get tools(): Omit<LlmTool, "call">[];
230
- call({ name, arguments: args }: {
230
+ private parseArgs;
231
+ /**
232
+ * Resolve a tool's `message` (static string or function of args) without
233
+ * calling the tool. Returns undefined when the tool is missing or defines
234
+ * no message. Never throws; resolution errors log at warn.
235
+ */
236
+ resolveMessage({ name, arguments: args, }: {
237
+ name: string;
238
+ arguments: string;
239
+ }): Promise<string | undefined>;
240
+ call({ name, arguments: args, message: resolvedMessage, }: {
231
241
  name: string;
232
242
  arguments: string;
243
+ /** Pre-resolved tool message; skips re-resolving `tool.message` for logging */
244
+ message?: string;
233
245
  }): Promise<_jaypie_types.AnyValue>;
234
246
  extend(tools: LlmTool[], options?: {
235
247
  warn?: boolean;
@@ -415,6 +427,8 @@ declare enum LlmProgressEventType {
415
427
  interface LlmProgressToolCall {
416
428
  /** JSON string of arguments (tool_call events only) */
417
429
  arguments?: string;
430
+ /** Resolved `LlmTool.message`, when the tool defines one (tool_call events only) */
431
+ message?: string;
418
432
  /** Tool name */
419
433
  name: string;
420
434
  }
@@ -461,19 +475,23 @@ interface LlmOperateOptions {
461
475
  content: string | JsonObject;
462
476
  usage: LlmUsage;
463
477
  }) => unknown | Promise<unknown>;
464
- afterEachTool?: ({ result, toolName, args, }: {
478
+ afterEachTool?: ({ result, toolName, args, message, }: {
465
479
  result: unknown;
466
480
  toolName: string;
467
481
  args: string;
482
+ /** Resolved `LlmTool.message`, when the tool defines one */
483
+ message?: string;
468
484
  }) => unknown | Promise<unknown>;
469
485
  beforeEachModelRequest?: ({ input, options, providerRequest, }: {
470
486
  input: string | LlmHistory | LlmInputMessage;
471
487
  options?: LlmOperateOptions;
472
488
  providerRequest: any;
473
489
  }) => unknown | Promise<unknown>;
474
- beforeEachTool?: ({ toolName, args, }: {
490
+ beforeEachTool?: ({ toolName, args, message, }: {
475
491
  toolName: string;
476
492
  args: string;
493
+ /** Resolved `LlmTool.message`, when the tool defines one */
494
+ message?: string;
477
495
  }) => unknown | Promise<unknown>;
478
496
  onRetryableModelError?: ({ input, options, providerRequest, error, }: {
479
497
  input: string | LlmHistory | LlmInputMessage;
@@ -481,10 +499,12 @@ interface LlmOperateOptions {
481
499
  providerRequest: any;
482
500
  error: any;
483
501
  }) => unknown | Promise<unknown>;
484
- onToolError?: ({ error, toolName, args, }: {
502
+ onToolError?: ({ error, toolName, args, message, }: {
485
503
  error: Error;
486
504
  toolName: string;
487
505
  args: string;
506
+ /** Resolved `LlmTool.message`, when the tool defines one */
507
+ message?: string;
488
508
  }) => unknown | Promise<unknown>;
489
509
  onUnrecoverableModelError?: ({ input, options, providerRequest, error, }: {
490
510
  input: string | LlmHistory | LlmInputMessage;
package/dist/esm/index.js CHANGED
@@ -5417,11 +5417,7 @@ class Toolkit {
5417
5417
  return toolCopy;
5418
5418
  });
5419
5419
  }
5420
- async call({ name, arguments: args }) {
5421
- const tool = this._tools.find((t) => t.name === name);
5422
- if (!tool) {
5423
- throw new Error(`Tool '${name}' not found`);
5424
- }
5420
+ parseArgs(args) {
5425
5421
  let parsedArgs;
5426
5422
  try {
5427
5423
  parsedArgs = JSON.parse(args);
@@ -5432,35 +5428,53 @@ class Toolkit {
5432
5428
  catch {
5433
5429
  parsedArgs = args;
5434
5430
  }
5431
+ return parsedArgs;
5432
+ }
5433
+ /**
5434
+ * Resolve a tool's `message` (static string or function of args) without
5435
+ * calling the tool. Returns undefined when the tool is missing or defines
5436
+ * no message. Never throws; resolution errors log at warn.
5437
+ */
5438
+ async resolveMessage({ name, arguments: args, }) {
5439
+ const tool = this._tools.find((t) => t.name === name);
5440
+ if (!tool || !tool.message) {
5441
+ return undefined;
5442
+ }
5443
+ try {
5444
+ if (typeof tool.message === "string") {
5445
+ return tool.message;
5446
+ }
5447
+ const parsedArgs = this.parseArgs(args);
5448
+ if (typeof tool.message === "function") {
5449
+ return await resolveValue(tool.message(parsedArgs, { name }));
5450
+ }
5451
+ log.warn("[Toolkit] Tool provided unknown message type");
5452
+ return String(tool.message);
5453
+ }
5454
+ catch (error) {
5455
+ log.warn("[Toolkit] Caught error resolving tool message");
5456
+ log.var({ error });
5457
+ return undefined;
5458
+ }
5459
+ }
5460
+ async call({ name, arguments: args, message: resolvedMessage, }) {
5461
+ const tool = this._tools.find((t) => t.name === name);
5462
+ if (!tool) {
5463
+ throw new Error(`Tool '${name}' not found`);
5464
+ }
5465
+ const parsedArgs = this.parseArgs(args);
5435
5466
  if (this.log !== false) {
5436
5467
  try {
5437
5468
  const context = {
5438
5469
  name,
5439
5470
  args: parsedArgs,
5440
5471
  };
5441
- let message;
5442
5472
  if (this.explain) {
5443
5473
  context.explanation = parsedArgs.__Explanation;
5444
5474
  }
5445
- if (tool.message) {
5446
- if (typeof tool.message === "string") {
5447
- log.trace("[Toolkit] Tool provided string message");
5448
- message = tool.message;
5449
- }
5450
- else if (typeof tool.message === "function") {
5451
- log.trace("[Toolkit] Tool provided function message");
5452
- log.trace("[Toolkit] Resolving message result");
5453
- message = await resolveValue(tool.message(parsedArgs, { name }));
5454
- }
5455
- else {
5456
- log.warn("[Toolkit] Tool provided unknown message type");
5457
- message = String(tool.message);
5458
- }
5459
- }
5460
- else {
5461
- log.trace("[Toolkit] Log tool call with default message");
5462
- message = `${tool.name}:${JSON.stringify(parsedArgs)}`;
5463
- }
5475
+ const message = resolvedMessage ??
5476
+ (await this.resolveMessage({ arguments: args, name })) ??
5477
+ `${tool.name}:${JSON.stringify(parsedArgs)}`;
5464
5478
  if (typeof this.log === "function") {
5465
5479
  log.trace("[Toolkit] Log tool call with custom logger");
5466
5480
  await resolveValue(this.log(message, context));
@@ -6875,10 +6889,19 @@ class OperateLoop {
6875
6889
  this.appendResponseItemsToRequest(currentProviderRequest, responseItems);
6876
6890
  // Process each tool call
6877
6891
  for (const toolCall of toolCalls) {
6892
+ // Resolved once per call; never throws (undefined when tool has no message)
6893
+ const toolMessage = await state.toolkit.resolveMessage({
6894
+ arguments: toolCall.arguments,
6895
+ name: toolCall.name,
6896
+ });
6878
6897
  try {
6879
6898
  await emitProgress({
6880
6899
  event: {
6881
- tool: { arguments: toolCall.arguments, name: toolCall.name },
6900
+ tool: {
6901
+ arguments: toolCall.arguments,
6902
+ message: toolMessage,
6903
+ name: toolCall.name,
6904
+ },
6882
6905
  turn: state.currentTurn,
6883
6906
  type: LlmProgressEventType.ToolCall,
6884
6907
  },
@@ -6887,6 +6910,7 @@ class OperateLoop {
6887
6910
  // Execute beforeEachTool hook
6888
6911
  await this.hookRunnerInstance.runBeforeTool(context.hooks, {
6889
6912
  args: toolCall.arguments,
6913
+ message: toolMessage,
6890
6914
  toolName: toolCall.name,
6891
6915
  });
6892
6916
  // Call the tool inside a child tool span (no-op when disabled)
@@ -6894,6 +6918,7 @@ class OperateLoop {
6894
6918
  const result = await withLlmObsSpan({ kind: "tool", name: toolCall.name }, async () => {
6895
6919
  const result = await state.toolkit.call({
6896
6920
  arguments: toolCall.arguments,
6921
+ message: toolMessage,
6897
6922
  name: toolCall.name,
6898
6923
  });
6899
6924
  annotateLlmObs({
@@ -6914,6 +6939,7 @@ class OperateLoop {
6914
6939
  // Execute afterEachTool hook
6915
6940
  await this.hookRunnerInstance.runAfterTool(context.hooks, {
6916
6941
  args: toolCall.arguments,
6942
+ message: toolMessage,
6917
6943
  result,
6918
6944
  toolName: toolCall.name,
6919
6945
  });
@@ -6947,6 +6973,7 @@ class OperateLoop {
6947
6973
  await this.hookRunnerInstance.runOnToolError(context.hooks, {
6948
6974
  args: toolCall.arguments,
6949
6975
  error: error,
6976
+ message: toolMessage,
6950
6977
  toolName: toolCall.name,
6951
6978
  });
6952
6979
  // Set error on response
@@ -7457,10 +7484,16 @@ class StreamLoop {
7457
7484
  async *processToolCalls(toolCalls, state, context) {
7458
7485
  const log = getLogger$6();
7459
7486
  for (const toolCall of toolCalls) {
7487
+ // Resolved once per call; never throws (undefined when tool has no message)
7488
+ const toolMessage = await state.toolkit.resolveMessage({
7489
+ arguments: toolCall.arguments,
7490
+ name: toolCall.name,
7491
+ });
7460
7492
  try {
7461
7493
  // Execute beforeEachTool hook
7462
7494
  await this.hookRunnerInstance.runBeforeTool(context.hooks, {
7463
7495
  args: toolCall.arguments,
7496
+ message: toolMessage,
7464
7497
  toolName: toolCall.name,
7465
7498
  });
7466
7499
  // Call the tool inside a child tool span (no-op when disabled)
@@ -7468,6 +7501,7 @@ class StreamLoop {
7468
7501
  const result = await withLlmObsSpan({ kind: "tool", name: toolCall.name }, async () => {
7469
7502
  const result = await state.toolkit.call({
7470
7503
  arguments: toolCall.arguments,
7504
+ message: toolMessage,
7471
7505
  name: toolCall.name,
7472
7506
  });
7473
7507
  annotateLlmObs({
@@ -7480,6 +7514,7 @@ class StreamLoop {
7480
7514
  // Execute afterEachTool hook
7481
7515
  await this.hookRunnerInstance.runAfterTool(context.hooks, {
7482
7516
  args: toolCall.arguments,
7517
+ message: toolMessage,
7483
7518
  result,
7484
7519
  toolName: toolCall.name,
7485
7520
  });
@@ -7507,6 +7542,7 @@ class StreamLoop {
7507
7542
  await this.hookRunnerInstance.runOnToolError(context.hooks, {
7508
7543
  args: toolCall.arguments,
7509
7544
  error: error,
7545
+ message: toolMessage,
7510
7546
  toolName: toolCall.name,
7511
7547
  });
7512
7548
  // Yield error chunk