@node-llm/core 1.16.2 → 1.17.1

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 (76) hide show
  1. package/dist/agent/Agent.d.ts +3 -0
  2. package/dist/agent/Agent.d.ts.map +1 -1
  3. package/dist/agent/Agent.js +3 -0
  4. package/dist/aliases.d.ts +592 -378
  5. package/dist/aliases.d.ts.map +1 -1
  6. package/dist/aliases.js +665 -451
  7. package/dist/chat/Chat.d.ts +17 -5
  8. package/dist/chat/Chat.d.ts.map +1 -1
  9. package/dist/chat/Chat.js +118 -79
  10. package/dist/chat/ChatOptions.d.ts +20 -0
  11. package/dist/chat/ChatOptions.d.ts.map +1 -1
  12. package/dist/chat/ChatStream.d.ts.map +1 -1
  13. package/dist/chat/ChatStream.js +69 -58
  14. package/dist/chat/ToolCallOutcome.d.ts +30 -0
  15. package/dist/chat/ToolCallOutcome.d.ts.map +1 -0
  16. package/dist/chat/ToolCallOutcome.js +43 -0
  17. package/dist/chat/ToolHandler.d.ts.map +1 -1
  18. package/dist/chat/ToolHandler.js +15 -1
  19. package/dist/config.d.ts +11 -0
  20. package/dist/config.d.ts.map +1 -1
  21. package/dist/config.js +9 -1
  22. package/dist/constants.d.ts +2 -0
  23. package/dist/constants.d.ts.map +1 -1
  24. package/dist/constants.js +4 -0
  25. package/dist/errors/index.d.ts +3 -1
  26. package/dist/errors/index.d.ts.map +1 -1
  27. package/dist/errors/index.js +4 -1
  28. package/dist/executor/Executor.d.ts +6 -0
  29. package/dist/executor/Executor.d.ts.map +1 -1
  30. package/dist/executor/Executor.js +19 -2
  31. package/dist/index.d.ts +1 -1
  32. package/dist/index.d.ts.map +1 -1
  33. package/dist/llm.d.ts +1 -1
  34. package/dist/llm.d.ts.map +1 -1
  35. package/dist/models/models.json +9478 -6064
  36. package/dist/providers/anthropic/Models.d.ts.map +1 -1
  37. package/dist/providers/anthropic/Models.js +4 -2
  38. package/dist/providers/bedrock/BedrockProvider.js +1 -1
  39. package/dist/providers/bedrock/Chat.js +1 -1
  40. package/dist/providers/bedrock/Embeddings.js +1 -1
  41. package/dist/providers/bedrock/Image.js +1 -1
  42. package/dist/providers/bedrock/Moderation.js +1 -1
  43. package/dist/providers/bedrock/Streaming.js +1 -1
  44. package/dist/providers/bedrock/config.d.ts +9 -1
  45. package/dist/providers/bedrock/config.d.ts.map +1 -1
  46. package/dist/providers/bedrock/config.js +4 -2
  47. package/dist/providers/bedrock/index.d.ts.map +1 -1
  48. package/dist/providers/bedrock/index.js +1 -0
  49. package/dist/providers/deepseek/Models.d.ts.map +1 -1
  50. package/dist/providers/deepseek/Models.js +4 -2
  51. package/dist/providers/gemini/Embeddings.d.ts.map +1 -1
  52. package/dist/providers/gemini/Embeddings.js +4 -2
  53. package/dist/providers/gemini/Image.d.ts.map +1 -1
  54. package/dist/providers/gemini/Image.js +4 -2
  55. package/dist/providers/gemini/Models.d.ts.map +1 -1
  56. package/dist/providers/gemini/Models.js +4 -2
  57. package/dist/providers/gemini/Transcription.d.ts.map +1 -1
  58. package/dist/providers/gemini/Transcription.js +4 -2
  59. package/dist/providers/mistral/Embedding.d.ts.map +1 -1
  60. package/dist/providers/mistral/Embedding.js +4 -2
  61. package/dist/providers/mistral/Models.d.ts.map +1 -1
  62. package/dist/providers/mistral/Models.js +4 -2
  63. package/dist/providers/openai/Models.d.ts.map +1 -1
  64. package/dist/providers/openai/Models.js +4 -2
  65. package/dist/providers/openrouter/Models.d.ts.map +1 -1
  66. package/dist/providers/openrouter/Models.js +4 -2
  67. package/dist/utils/Binary.d.ts.map +1 -1
  68. package/dist/utils/Binary.js +11 -0
  69. package/dist/utils/FileLoader.d.ts.map +1 -1
  70. package/dist/utils/FileLoader.js +21 -2
  71. package/dist/utils/handler-stacking.d.ts +31 -0
  72. package/dist/utils/handler-stacking.d.ts.map +1 -0
  73. package/dist/utils/handler-stacking.js +66 -0
  74. package/dist/utils/logger.d.ts.map +1 -1
  75. package/dist/utils/logger.js +8 -1
  76. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"Models.d.ts","sourceRoot":"","sources":["../../../src/providers/anthropic/Models.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAI3C,qBAAa,eAAe;IAExB,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,MAAM;gBADN,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM;IAG3B,OAAO,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC;IAqDrC,IAAI,CAAC,OAAO,EAAE,MAAM;CAGrB"}
1
+ {"version":3,"file":"Models.d.ts","sourceRoot":"","sources":["../../../src/providers/anthropic/Models.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAM3C,qBAAa,eAAe;IAExB,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,MAAM;gBADN,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM;IAG3B,OAAO,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC;IAyDrC,IAAI,CAAC,OAAO,EAAE,MAAM;CAGrB"}
@@ -1,3 +1,5 @@
1
+ import { config } from "../../config.js";
2
+ import { fetchWithTimeout } from "../../utils/fetch.js";
1
3
  import { Capabilities } from "./Capabilities.js";
2
4
  import { ModelRegistry } from "../../models/ModelRegistry.js";
3
5
  export class AnthropicModels {
@@ -9,14 +11,14 @@ export class AnthropicModels {
9
11
  }
10
12
  async execute() {
11
13
  try {
12
- const response = await fetch(`${this.baseUrl}/models`, {
14
+ const response = await fetchWithTimeout(`${this.baseUrl}/models`, {
13
15
  method: "GET",
14
16
  headers: {
15
17
  "x-api-key": this.apiKey,
16
18
  "anthropic-version": "2023-06-01",
17
19
  "content-type": "application/json"
18
20
  }
19
- });
21
+ }, config.requestTimeout);
20
22
  if (response.ok) {
21
23
  const { data } = (await response.json());
22
24
  return data.map((m) => {
@@ -65,7 +65,7 @@ export class BedrockProvider extends BaseProvider {
65
65
  this.moderationHandler = new BedrockModeration(config);
66
66
  }
67
67
  apiBase() {
68
- return getBedrockEndpoint(this.config.region);
68
+ return getBedrockEndpoint(this.config.region, this.config.apiBase);
69
69
  }
70
70
  headers() {
71
71
  // Headers are built dynamically based on auth mode
@@ -20,7 +20,7 @@ export class BedrockChat {
20
20
  constructor(config) {
21
21
  this.config = config;
22
22
  this.authMode = validateBedrockConfig(config);
23
- this.baseUrl = getBedrockEndpoint(config.region);
23
+ this.baseUrl = getBedrockEndpoint(config.region, config.apiBase);
24
24
  }
25
25
  /**
26
26
  * Execute a chat request against Bedrock Converse API.
@@ -17,7 +17,7 @@ export class BedrockEmbeddings {
17
17
  constructor(config) {
18
18
  this.config = config;
19
19
  this.authMode = validateBedrockConfig(config);
20
- this.baseUrl = getBedrockEndpoint(config.region);
20
+ this.baseUrl = getBedrockEndpoint(config.region, config.apiBase);
21
21
  }
22
22
  /**
23
23
  * Execute an embedding request against Bedrock InvokeModel API.
@@ -12,7 +12,7 @@ export class BedrockImage {
12
12
  baseUrl;
13
13
  constructor(config) {
14
14
  this.config = config;
15
- this.baseUrl = getBedrockEndpoint(config.region);
15
+ this.baseUrl = getBedrockEndpoint(config.region, config.apiBase);
16
16
  }
17
17
  /**
18
18
  * Execute an image generation request.
@@ -15,7 +15,7 @@ export class BedrockModeration {
15
15
  constructor(config) {
16
16
  this.config = config;
17
17
  this.authMode = validateBedrockConfig(config);
18
- this.baseUrl = getBedrockEndpoint(config.region);
18
+ this.baseUrl = getBedrockEndpoint(config.region, config.apiBase);
19
19
  }
20
20
  /**
21
21
  * Execute a moderation request against Bedrock Guardrails.
@@ -18,7 +18,7 @@ export class BedrockStreaming {
18
18
  constructor(config) {
19
19
  this.config = config;
20
20
  this.authMode = validateBedrockConfig(config);
21
- this.baseUrl = getBedrockEndpoint(config.region);
21
+ this.baseUrl = getBedrockEndpoint(config.region, config.apiBase);
22
22
  }
23
23
  async *execute(request, controller) {
24
24
  const internalController = new AbortController();
@@ -37,6 +37,12 @@ export interface BedrockConfig {
37
37
  * Default: 120000 (2 minutes)
38
38
  */
39
39
  requestTimeout?: number;
40
+ /**
41
+ * Custom Bedrock Runtime endpoint override (e.g. for routing traffic
42
+ * through a proxy or private gateway). Defaults to the standard
43
+ * `https://bedrock-runtime.{region}.amazonaws.com` endpoint when unset.
44
+ */
45
+ apiBase?: string;
40
46
  /**
41
47
  * Default Bedrock Guardrail identifier (ID or ARN).
42
48
  */
@@ -52,6 +58,8 @@ export interface BedrockConfig {
52
58
  export declare function validateBedrockConfig(config: BedrockConfig): "apiKey" | "sigv4";
53
59
  /**
54
60
  * Build the Bedrock Runtime endpoint URL for a given region.
61
+ * Pass `apiBase` to route through a custom endpoint (e.g. a proxy/gateway)
62
+ * instead of the standard AWS Bedrock Runtime URL.
55
63
  */
56
- export declare function getBedrockEndpoint(region: string): string;
64
+ export declare function getBedrockEndpoint(region: string, apiBase?: string): string;
57
65
  //# sourceMappingURL=config.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../../src/providers/bedrock/config.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,MAAM,WAAW,aAAa;IAC5B;;;OAGG;IACH,MAAM,EAAE,MAAM,CAAC;IAKf;;;;OAIG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAKhB;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB;;;OAGG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IAEzB;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IAKtB;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IAExB;;OAEG;IACH,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAE7B;;OAEG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,aAAa,GAAG,QAAQ,GAAG,OAAO,CAuB/E;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAEzD"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../../src/providers/bedrock/config.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,MAAM,WAAW,aAAa;IAC5B;;;OAGG;IACH,MAAM,EAAE,MAAM,CAAC;IAKf;;;;OAIG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAKhB;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB;;;OAGG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IAEzB;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IAKtB;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IAExB;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB;;OAEG;IACH,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAE7B;;OAEG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,aAAa,GAAG,QAAQ,GAAG,OAAO,CAuB/E;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAE3E"}
@@ -27,7 +27,9 @@ export function validateBedrockConfig(config) {
27
27
  }
28
28
  /**
29
29
  * Build the Bedrock Runtime endpoint URL for a given region.
30
+ * Pass `apiBase` to route through a custom endpoint (e.g. a proxy/gateway)
31
+ * instead of the standard AWS Bedrock Runtime URL.
30
32
  */
31
- export function getBedrockEndpoint(region) {
32
- return `https://bedrock-runtime.${region}.amazonaws.com`;
33
+ export function getBedrockEndpoint(region, apiBase) {
34
+ return apiBase || `https://bedrock-runtime.${region}.amazonaws.com`;
33
35
  }
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/providers/bedrock/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAOH,wBAAgB,uBAAuB,SAuBtC;AAED,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACtE,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AACxC,cAAc,YAAY,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/providers/bedrock/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAOH,wBAAgB,uBAAuB,SAwBtC;AAED,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACtE,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AACxC,cAAc,YAAY,CAAC"}
@@ -19,6 +19,7 @@ export function registerBedrockProvider() {
19
19
  accessKeyId: cfg.bedrockAccessKeyId,
20
20
  secretAccessKey: cfg.bedrockSecretAccessKey,
21
21
  sessionToken: cfg.bedrockSessionToken,
22
+ apiBase: cfg.bedrockApiBase,
22
23
  guardrailIdentifier: cfg.bedrockGuardrailIdentifier,
23
24
  guardrailVersion: cfg.bedrockGuardrailVersion
24
25
  };
@@ -1 +1 @@
1
- {"version":3,"file":"Models.d.ts","sourceRoot":"","sources":["../../../src/providers/deepseek/Models.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAe3C,qBAAa,cAAc;IAEvB,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,MAAM;gBADN,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM;IAG3B,OAAO,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC;CA+DtC"}
1
+ {"version":3,"file":"Models.d.ts","sourceRoot":"","sources":["../../../src/providers/deepseek/Models.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAiB3C,qBAAa,cAAc;IAEvB,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,MAAM;gBADN,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM;IAG3B,OAAO,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC;CAmEtC"}
@@ -1,3 +1,5 @@
1
+ import { config } from "../../config.js";
2
+ import { fetchWithTimeout } from "../../utils/fetch.js";
1
3
  import { Capabilities } from "./Capabilities.js";
2
4
  import { ModelRegistry } from "../../models/ModelRegistry.js";
3
5
  export class DeepSeekModels {
@@ -8,12 +10,12 @@ export class DeepSeekModels {
8
10
  this.apiKey = apiKey;
9
11
  }
10
12
  async execute() {
11
- const response = await fetch(`${this.baseUrl}/models`, {
13
+ const response = await fetchWithTimeout(`${this.baseUrl}/models`, {
12
14
  method: "GET",
13
15
  headers: {
14
16
  Authorization: `Bearer ${this.apiKey}`
15
17
  }
16
- });
18
+ }, config.requestTimeout);
17
19
  if (!response.ok) {
18
20
  // Fallback to local registry
19
21
  const localModels = ModelRegistry.all()
@@ -1 +1 @@
1
- {"version":3,"file":"Embeddings.d.ts","sourceRoot":"","sources":["../../../src/providers/gemini/Embeddings.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAKrE,qBAAa,gBAAgB;IAEzB,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,MAAM;gBADN,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM;IAG3B,OAAO,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,iBAAiB,CAAC;CA2CrE"}
1
+ {"version":3,"file":"Embeddings.d.ts","sourceRoot":"","sources":["../../../src/providers/gemini/Embeddings.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAOrE,qBAAa,gBAAgB;IAEzB,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,MAAM;gBADN,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM;IAG3B,OAAO,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,iBAAiB,CAAC;CA+CrE"}
@@ -1,3 +1,5 @@
1
+ import { config } from "../../config.js";
2
+ import { fetchWithTimeout } from "../../utils/fetch.js";
1
3
  import { handleGeminiError } from "./Errors.js";
2
4
  import { logger } from "../../utils/logger.js";
3
5
  export class GeminiEmbeddings {
@@ -26,11 +28,11 @@ export class GeminiEmbeddings {
26
28
  })
27
29
  };
28
30
  logger.logRequest("Gemini", "POST", url, payload);
29
- const response = await fetch(url, {
31
+ const response = await fetchWithTimeout(url, {
30
32
  method: "POST",
31
33
  headers: { "Content-Type": "application/json" },
32
34
  body: JSON.stringify(payload)
33
- });
35
+ }, config.requestTimeout);
34
36
  if (!response.ok) {
35
37
  await handleGeminiError(response, modelId);
36
38
  }
@@ -1 +1 @@
1
- {"version":3,"file":"Image.d.ts","sourceRoot":"","sources":["../../../src/providers/gemini/Image.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAK7D,qBAAa,WAAW;IAEpB,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,MAAM;gBADN,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM;IAG3B,OAAO,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,aAAa,CAAC;CAiE7D"}
1
+ {"version":3,"file":"Image.d.ts","sourceRoot":"","sources":["../../../src/providers/gemini/Image.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAO7D,qBAAa,WAAW;IAEpB,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,MAAM;gBADN,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM;IAG3B,OAAO,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,aAAa,CAAC;CAqE7D"}
@@ -1,3 +1,5 @@
1
+ import { config } from "../../config.js";
2
+ import { fetchWithTimeout } from "../../utils/fetch.js";
1
3
  import { handleGeminiError } from "./Errors.js";
2
4
  import { logger } from "../../utils/logger.js";
3
5
  import { BinaryUtils } from "../../utils/Binary.js";
@@ -36,13 +38,13 @@ export class GeminiImage {
36
38
  }
37
39
  };
38
40
  logger.logRequest("Gemini", "POST", url, body);
39
- const response = await fetch(url, {
41
+ const response = await fetchWithTimeout(url, {
40
42
  method: "POST",
41
43
  headers: {
42
44
  "Content-Type": "application/json"
43
45
  },
44
46
  body: JSON.stringify(body)
45
- });
47
+ }, config.requestTimeout);
46
48
  if (!response.ok) {
47
49
  await handleGeminiError(response, modelId);
48
50
  }
@@ -1 +1 @@
1
- {"version":3,"file":"Models.d.ts","sourceRoot":"","sources":["../../../src/providers/gemini/Models.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAK3C,qBAAa,YAAY;IAErB,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,MAAM;gBADN,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM;IAG3B,OAAO,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC;IAmDrC,IAAI,CAAC,OAAO,EAAE,MAAM;CAGrB"}
1
+ {"version":3,"file":"Models.d.ts","sourceRoot":"","sources":["../../../src/providers/gemini/Models.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAO3C,qBAAa,YAAY;IAErB,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,MAAM;gBADN,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM;IAG3B,OAAO,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC;IAuDrC,IAAI,CAAC,OAAO,EAAE,MAAM;CAGrB"}
@@ -1,3 +1,5 @@
1
+ import { config } from "../../config.js";
2
+ import { fetchWithTimeout } from "../../utils/fetch.js";
1
3
  import { Capabilities } from "./Capabilities.js";
2
4
  import { ModelRegistry } from "../../models/ModelRegistry.js";
3
5
  export class GeminiModels {
@@ -9,12 +11,12 @@ export class GeminiModels {
9
11
  }
10
12
  async execute() {
11
13
  try {
12
- const response = await fetch(`${this.baseUrl}/models?key=${this.apiKey}`, {
14
+ const response = await fetchWithTimeout(`${this.baseUrl}/models?key=${this.apiKey}`, {
13
15
  method: "GET",
14
16
  headers: {
15
17
  "Content-Type": "application/json"
16
18
  }
17
- });
19
+ }, config.requestTimeout);
18
20
  if (response.ok) {
19
21
  const { models } = (await response.json());
20
22
  return models.map((m) => {
@@ -1 +1 @@
1
- {"version":3,"file":"Transcription.d.ts","sourceRoot":"","sources":["../../../src/providers/gemini/Transcription.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;AAM7E,qBAAa,mBAAmB;IAK5B,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,MAAM;IALzB,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,cAAc,CACuC;gBAG1D,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM;IAG3B,OAAO,CAAC,OAAO,EAAE,oBAAoB,GAAG,OAAO,CAAC,qBAAqB,CAAC;CA8D7E"}
1
+ {"version":3,"file":"Transcription.d.ts","sourceRoot":"","sources":["../../../src/providers/gemini/Transcription.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;AAQ7E,qBAAa,mBAAmB;IAK5B,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,MAAM;IALzB,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,cAAc,CACuC;gBAG1D,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM;IAG3B,OAAO,CAAC,OAAO,EAAE,oBAAoB,GAAG,OAAO,CAAC,qBAAqB,CAAC;CAkE7E"}
@@ -1,3 +1,5 @@
1
+ import { config } from "../../config.js";
2
+ import { fetchWithTimeout } from "../../utils/fetch.js";
1
3
  import { handleGeminiError } from "./Errors.js";
2
4
  import { BinaryUtils } from "../../utils/Binary.js";
3
5
  import { logger } from "../../utils/logger.js";
@@ -44,13 +46,13 @@ export class GeminiTranscription {
44
46
  }
45
47
  };
46
48
  logger.logRequest("Gemini", "POST", url, payload);
47
- const response = await fetch(url, {
49
+ const response = await fetchWithTimeout(url, {
48
50
  method: "POST",
49
51
  headers: {
50
52
  "Content-Type": "application/json"
51
53
  },
52
54
  body: JSON.stringify(payload)
53
- });
55
+ }, config.requestTimeout);
54
56
  if (!response.ok) {
55
57
  await handleGeminiError(response, model);
56
58
  }
@@ -1 +1 @@
1
- {"version":3,"file":"Embedding.d.ts","sourceRoot":"","sources":["../../../src/providers/mistral/Embedding.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAoBrE,qBAAa,gBAAgB;IAEzB,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,MAAM;gBADN,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM;IAG3B,OAAO,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,iBAAiB,CAAC;CAwCrE"}
1
+ {"version":3,"file":"Embedding.d.ts","sourceRoot":"","sources":["../../../src/providers/mistral/Embedding.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAsBrE,qBAAa,gBAAgB;IAEzB,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,MAAM;gBADN,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM;IAG3B,OAAO,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,iBAAiB,CAAC;CA4CrE"}
@@ -1,3 +1,5 @@
1
+ import { config } from "../../config.js";
2
+ import { fetchWithTimeout } from "../../utils/fetch.js";
1
3
  import { logger } from "../../utils/logger.js";
2
4
  import { handleMistralError } from "./Errors.js";
3
5
  import { MistralCapabilities } from "./Capabilities.js";
@@ -20,7 +22,7 @@ export class MistralEmbedding {
20
22
  };
21
23
  const url = `${this.baseUrl}/embeddings`;
22
24
  logger.logRequest("Mistral Embeddings", "POST", url, body);
23
- const response = await fetch(url, {
25
+ const response = await fetchWithTimeout(url, {
24
26
  method: "POST",
25
27
  headers: {
26
28
  Authorization: `Bearer ${this.apiKey}`,
@@ -28,7 +30,7 @@ export class MistralEmbedding {
28
30
  Accept: "application/json"
29
31
  },
30
32
  body: JSON.stringify(body)
31
- });
33
+ }, config.requestTimeout);
32
34
  if (!response.ok) {
33
35
  await handleMistralError(response, model);
34
36
  }
@@ -1 +1 @@
1
- {"version":3,"file":"Models.d.ts","sourceRoot":"","sources":["../../../src/providers/mistral/Models.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAgB3C,qBAAa,aAAa;IAEtB,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,MAAM;gBADN,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM;IAG3B,OAAO,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC;CAmEtC"}
1
+ {"version":3,"file":"Models.d.ts","sourceRoot":"","sources":["../../../src/providers/mistral/Models.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAkB3C,qBAAa,aAAa;IAEtB,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,MAAM;gBADN,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM;IAG3B,OAAO,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC;CAuEtC"}
@@ -1,3 +1,5 @@
1
+ import { config } from "../../config.js";
2
+ import { fetchWithTimeout } from "../../utils/fetch.js";
1
3
  import { MistralCapabilities } from "./Capabilities.js";
2
4
  import { ModelRegistry } from "../../models/ModelRegistry.js";
3
5
  export class MistralModels {
@@ -8,13 +10,13 @@ export class MistralModels {
8
10
  this.apiKey = apiKey;
9
11
  }
10
12
  async execute() {
11
- const response = await fetch(`${this.baseUrl}/models`, {
13
+ const response = await fetchWithTimeout(`${this.baseUrl}/models`, {
12
14
  method: "GET",
13
15
  headers: {
14
16
  Authorization: `Bearer ${this.apiKey}`,
15
17
  Accept: "application/json"
16
18
  }
17
- });
19
+ }, config.requestTimeout);
18
20
  if (!response.ok) {
19
21
  // Fallback to local registry
20
22
  const localModels = ModelRegistry.all()
@@ -1 +1 @@
1
- {"version":3,"file":"Models.d.ts","sourceRoot":"","sources":["../../../src/providers/openai/Models.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAK3C,qBAAa,YAAY;IAErB,SAAS,CAAC,QAAQ,CAAC,OAAO,EAAE,MAAM;IAClC,SAAS,CAAC,QAAQ,CAAC,MAAM,EAAE,MAAM;gBADd,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM;IAGnC,SAAS,CAAC,eAAe,IAAI,MAAM;IAInC,SAAS,CAAC,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM;IAMpD,SAAS,CAAC,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAQ1D,SAAS,CAAC,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAQ5D,SAAS,CAAC,aAAa,CAAC,OAAO,EAAE,MAAM;;;;IAKvC,SAAS,CAAC,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE;IAKpD,SAAS,CAAC,UAAU,CAAC,OAAO,EAAE,MAAM;IAK9B,OAAO,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC;IA0DrC,IAAI,CAAC,OAAO,EAAE,MAAM;CAGrB"}
1
+ {"version":3,"file":"Models.d.ts","sourceRoot":"","sources":["../../../src/providers/openai/Models.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAO3C,qBAAa,YAAY;IAErB,SAAS,CAAC,QAAQ,CAAC,OAAO,EAAE,MAAM;IAClC,SAAS,CAAC,QAAQ,CAAC,MAAM,EAAE,MAAM;gBADd,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM;IAGnC,SAAS,CAAC,eAAe,IAAI,MAAM;IAInC,SAAS,CAAC,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM;IAMpD,SAAS,CAAC,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAQ1D,SAAS,CAAC,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAQ5D,SAAS,CAAC,aAAa,CAAC,OAAO,EAAE,MAAM;;;;IAKvC,SAAS,CAAC,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE;IAKpD,SAAS,CAAC,UAAU,CAAC,OAAO,EAAE,MAAM;IAK9B,OAAO,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC;IA8DrC,IAAI,CAAC,OAAO,EAAE,MAAM;CAGrB"}
@@ -1,3 +1,5 @@
1
+ import { config } from "../../config.js";
2
+ import { fetchWithTimeout } from "../../utils/fetch.js";
1
3
  import { Capabilities } from "./Capabilities.js";
2
4
  import { ModelRegistry } from "../../models/ModelRegistry.js";
3
5
  import { buildUrl } from "./utils.js";
@@ -42,13 +44,13 @@ export class OpenAIModels {
42
44
  async execute() {
43
45
  const provider = this.getProviderName();
44
46
  try {
45
- const response = await fetch(buildUrl(this.baseUrl, "/models"), {
47
+ const response = await fetchWithTimeout(buildUrl(this.baseUrl, "/models"), {
46
48
  method: "GET",
47
49
  headers: {
48
50
  Authorization: `Bearer ${this.apiKey}`,
49
51
  "Content-Type": "application/json"
50
52
  }
51
- });
53
+ }, config.requestTimeout);
52
54
  if (response.ok) {
53
55
  const { data } = (await response.json());
54
56
  return data.map((m) => {
@@ -1 +1 @@
1
- {"version":3,"file":"Models.d.ts","sourceRoot":"","sources":["../../../src/providers/openrouter/Models.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAwB3C,qBAAa,gBAAgB;IAEzB,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,MAAM;gBADN,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM;IAG3B,OAAO,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC;IAiBrC,OAAO,CAAC,UAAU;IA0BlB,OAAO,CAAC,iBAAiB;IA8BzB,OAAO,CAAC,YAAY;CAgCrB"}
1
+ {"version":3,"file":"Models.d.ts","sourceRoot":"","sources":["../../../src/providers/openrouter/Models.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AA0B3C,qBAAa,gBAAgB;IAEzB,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,MAAM;gBADN,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM;IAG3B,OAAO,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC;IAqBrC,OAAO,CAAC,UAAU;IA0BlB,OAAO,CAAC,iBAAiB;IA8BzB,OAAO,CAAC,YAAY;CAgCrB"}
@@ -1,3 +1,5 @@
1
+ import { config } from "../../config.js";
2
+ import { fetchWithTimeout } from "../../utils/fetch.js";
1
3
  export class OpenRouterModels {
2
4
  baseUrl;
3
5
  apiKey;
@@ -6,12 +8,12 @@ export class OpenRouterModels {
6
8
  this.apiKey = apiKey;
7
9
  }
8
10
  async execute() {
9
- const response = await fetch(`${this.baseUrl}/models`, {
11
+ const response = await fetchWithTimeout(`${this.baseUrl}/models`, {
10
12
  headers: {
11
13
  Authorization: `Bearer ${this.apiKey}`,
12
14
  "Content-Type": "application/json"
13
15
  }
14
- });
16
+ }, config.requestTimeout);
15
17
  if (!response.ok) {
16
18
  throw new Error(`OpenRouter API error: ${response.status}`);
17
19
  }
@@ -1 +1 @@
1
- {"version":3,"file":"Binary.d.ts","sourceRoot":"","sources":["../../src/utils/Binary.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,qBAAa,WAAW;IACtB;;OAEG;WACU,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC;IA0C9D;;OAEG;IACH,MAAM,CAAC,YAAY,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI;IAI7C;;OAEG;IACH,MAAM,CAAC,cAAc,CAAC,MAAM,EAAE,UAAU,GAAG,MAAM;IAIjD,OAAO,CAAC,MAAM,CAAC,aAAa;CA0B7B"}
1
+ {"version":3,"file":"Binary.d.ts","sourceRoot":"","sources":["../../src/utils/Binary.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,qBAAa,WAAW;IACtB;;OAEG;WACU,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC;IAmD9D;;OAEG;IACH,MAAM,CAAC,YAAY,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI;IAI7C;;OAEG;IACH,MAAM,CAAC,cAAc,CAAC,MAAM,EAAE,UAAU,GAAG,MAAM;IAIjD,OAAO,CAAC,MAAM,CAAC,aAAa;CA0B7B"}
@@ -1,6 +1,8 @@
1
1
  import fs from "fs";
2
2
  import path from "path";
3
3
  import { logger } from "./logger.js";
4
+ /** Max size (bytes) for a remotely-fetched binary, buffered fully into memory. */
5
+ const MAX_REMOTE_BYTES = 50 * 1024 * 1024;
4
6
  export class BinaryUtils {
5
7
  /**
6
8
  * Converts a URL (data:, http:, or local path) to a base64 string and mime type.
@@ -20,7 +22,16 @@ export class BinaryUtils {
20
22
  const response = await fetch(url);
21
23
  if (!response.ok)
22
24
  return null;
25
+ const declared = Number(response.headers.get("content-length"));
26
+ if (Number.isFinite(declared) && declared > MAX_REMOTE_BYTES) {
27
+ logger.error(`Remote file exceeds ${MAX_REMOTE_BYTES}-byte limit: ${url}`);
28
+ return null;
29
+ }
23
30
  const buffer = await response.arrayBuffer();
31
+ if (buffer.byteLength > MAX_REMOTE_BYTES) {
32
+ logger.error(`Remote file exceeds ${MAX_REMOTE_BYTES}-byte limit: ${url}`);
33
+ return null;
34
+ }
24
35
  const base64 = Buffer.from(buffer).toString("base64");
25
36
  const mimeType = response.headers.get("content-type") || this.guessMimeType(url);
26
37
  return {
@@ -1 +1 @@
1
- {"version":3,"file":"FileLoader.d.ts","sourceRoot":"","sources":["../../src/utils/FileLoader.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAgEjD,qBAAa,UAAU;WACR,IAAI,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;CAmF1D"}
1
+ {"version":3,"file":"FileLoader.d.ts","sourceRoot":"","sources":["../../src/utils/FileLoader.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAyFjD,qBAAa,UAAU;WACR,IAAI,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;CAmF1D"}
@@ -1,5 +1,23 @@
1
1
  import { promises as fs } from "fs";
2
2
  import * as path from "path";
3
+ /**
4
+ * Maximum size (bytes) for a remotely-fetched attachment. Caps memory use and
5
+ * limits the blast radius if an untrusted URL is ever passed here (the fetched
6
+ * body is buffered fully into memory as base64). 50 MB comfortably covers
7
+ * images, audio, and PDFs sent to providers.
8
+ */
9
+ const MAX_REMOTE_BYTES = 50 * 1024 * 1024;
10
+ async function readCapped(response, source) {
11
+ const declared = Number(response.headers.get("content-length"));
12
+ if (Number.isFinite(declared) && declared > MAX_REMOTE_BYTES) {
13
+ throw new Error(`Remote file ${source} is ${declared} bytes, exceeding the ${MAX_REMOTE_BYTES}-byte limit.`);
14
+ }
15
+ const buffer = await response.arrayBuffer();
16
+ if (buffer.byteLength > MAX_REMOTE_BYTES) {
17
+ throw new Error(`Remote file ${source} is ${buffer.byteLength} bytes, exceeding the ${MAX_REMOTE_BYTES}-byte limit.`);
18
+ }
19
+ return buffer;
20
+ }
3
21
  const MIME_TYPES = {
4
22
  ".jpg": "image/jpeg",
5
23
  ".jpeg": "image/jpeg",
@@ -50,7 +68,8 @@ const TEXT_EXTENSIONS = new Set([
50
68
  ".xml",
51
69
  ".yml",
52
70
  ".yaml",
53
- ".env",
71
+ // ".env" intentionally excluded: silently inlining a dotenv file would leak
72
+ // secrets into the prompt sent to the provider.
54
73
  ".csv",
55
74
  ".go",
56
75
  ".java",
@@ -67,7 +86,7 @@ export class FileLoader {
67
86
  const response = await fetch(filePath);
68
87
  if (!response.ok)
69
88
  throw new Error(`Failed to fetch file: ${response.statusText}`);
70
- const buffer = await response.arrayBuffer();
89
+ const buffer = await readCapped(response, filePath);
71
90
  const contentTypeFull = response.headers.get("content-type") || "image/jpeg";
72
91
  const contentType = (contentTypeFull.split(";")[0] ?? "image/jpeg").trim();
73
92
  const base64 = Buffer.from(buffer).toString("base64");
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Combines a single "constructor-provided" handler with a list of handlers
3
+ * appended later (e.g. via fluent on*() calls), preserving registration order.
4
+ */
5
+ export declare function collectHandlers<T>(single: T | undefined, list: T[] | undefined): T[];
6
+ /**
7
+ * Runs every handler with the given args, awaiting each in order. Use for
8
+ * pure observers (onNewMessage, onEndMessage, onToolCallStart, onToolCallEnd)
9
+ * where every registered handler should fire and none of them return a value.
10
+ */
11
+ export declare function runAllHandlers<Args extends unknown[]>(handlers: Array<(...args: Args) => unknown>, ...args: Args): Promise<void>;
12
+ /**
13
+ * Runs every handler in order and returns the first defined (non-void)
14
+ * result, but still calls the remaining handlers so every one of them gets a
15
+ * chance to observe/react (mirrors the middleware-runner directive pattern).
16
+ * Use for onToolCallError, where the first STOP/RETRY/CONTINUE wins.
17
+ */
18
+ export declare function runDirectiveHandlers<Args extends unknown[], R>(handlers: Array<(...args: Args) => R | void | Promise<R | void>>, ...args: Args): Promise<R | undefined>;
19
+ /**
20
+ * Runs every handler in order, AND-ing boolean results together. Used for
21
+ * onConfirmToolCall: every registered handler must approve for the call to
22
+ * proceed. Short-circuits once a handler declines.
23
+ */
24
+ export declare function runConfirmHandlers<Args extends unknown[]>(handlers: Array<(...args: Args) => Promise<boolean> | boolean>, ...args: Args): Promise<boolean>;
25
+ /**
26
+ * Runs every handler in order, feeding each handler's (possibly transformed)
27
+ * output into the next as its input. Used for onBeforeRequest/onAfterResponse,
28
+ * where each handler may rewrite the value for downstream handlers.
29
+ */
30
+ export declare function runChainHandlers<T>(handlers: Array<(value: T) => Promise<T | void> | T | void>, initial: T): Promise<T>;
31
+ //# sourceMappingURL=handler-stacking.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"handler-stacking.d.ts","sourceRoot":"","sources":["../../src/utils/handler-stacking.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,wBAAgB,eAAe,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,GAAG,SAAS,EAAE,IAAI,EAAE,CAAC,EAAE,GAAG,SAAS,GAAG,CAAC,EAAE,CAKpF;AAED;;;;GAIG;AACH,wBAAsB,cAAc,CAAC,IAAI,SAAS,OAAO,EAAE,EACzD,QAAQ,EAAE,KAAK,CAAC,CAAC,GAAG,IAAI,EAAE,IAAI,KAAK,OAAO,CAAC,EAC3C,GAAG,IAAI,EAAE,IAAI,GACZ,OAAO,CAAC,IAAI,CAAC,CAIf;AAED;;;;;GAKG;AACH,wBAAsB,oBAAoB,CAAC,IAAI,SAAS,OAAO,EAAE,EAAE,CAAC,EAClE,QAAQ,EAAE,KAAK,CAAC,CAAC,GAAG,IAAI,EAAE,IAAI,KAAK,CAAC,GAAG,IAAI,GAAG,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,EAChE,GAAG,IAAI,EAAE,IAAI,GACZ,OAAO,CAAC,CAAC,GAAG,SAAS,CAAC,CASxB;AAED;;;;GAIG;AACH,wBAAsB,kBAAkB,CAAC,IAAI,SAAS,OAAO,EAAE,EAC7D,QAAQ,EAAE,KAAK,CAAC,CAAC,GAAG,IAAI,EAAE,IAAI,KAAK,OAAO,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC,EAC9D,GAAG,IAAI,EAAE,IAAI,GACZ,OAAO,CAAC,OAAO,CAAC,CAMlB;AAED;;;;GAIG;AACH,wBAAsB,gBAAgB,CAAC,CAAC,EACtC,QAAQ,EAAE,KAAK,CAAC,CAAC,KAAK,EAAE,CAAC,KAAK,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,EAC3D,OAAO,EAAE,CAAC,GACT,OAAO,CAAC,CAAC,CAAC,CASZ"}
@@ -0,0 +1,66 @@
1
+ /**
2
+ * Combines a single "constructor-provided" handler with a list of handlers
3
+ * appended later (e.g. via fluent on*() calls), preserving registration order.
4
+ */
5
+ export function collectHandlers(single, list) {
6
+ const handlers = [];
7
+ if (single)
8
+ handlers.push(single);
9
+ if (list)
10
+ handlers.push(...list);
11
+ return handlers;
12
+ }
13
+ /**
14
+ * Runs every handler with the given args, awaiting each in order. Use for
15
+ * pure observers (onNewMessage, onEndMessage, onToolCallStart, onToolCallEnd)
16
+ * where every registered handler should fire and none of them return a value.
17
+ */
18
+ export async function runAllHandlers(handlers, ...args) {
19
+ for (const handler of handlers) {
20
+ await handler(...args);
21
+ }
22
+ }
23
+ /**
24
+ * Runs every handler in order and returns the first defined (non-void)
25
+ * result, but still calls the remaining handlers so every one of them gets a
26
+ * chance to observe/react (mirrors the middleware-runner directive pattern).
27
+ * Use for onToolCallError, where the first STOP/RETRY/CONTINUE wins.
28
+ */
29
+ export async function runDirectiveHandlers(handlers, ...args) {
30
+ let result;
31
+ for (const handler of handlers) {
32
+ const value = await handler(...args);
33
+ if (value !== undefined && result === undefined) {
34
+ result = value;
35
+ }
36
+ }
37
+ return result;
38
+ }
39
+ /**
40
+ * Runs every handler in order, AND-ing boolean results together. Used for
41
+ * onConfirmToolCall: every registered handler must approve for the call to
42
+ * proceed. Short-circuits once a handler declines.
43
+ */
44
+ export async function runConfirmHandlers(handlers, ...args) {
45
+ for (const handler of handlers) {
46
+ const approved = await handler(...args);
47
+ if (approved === false)
48
+ return false;
49
+ }
50
+ return true;
51
+ }
52
+ /**
53
+ * Runs every handler in order, feeding each handler's (possibly transformed)
54
+ * output into the next as its input. Used for onBeforeRequest/onAfterResponse,
55
+ * where each handler may rewrite the value for downstream handlers.
56
+ */
57
+ export async function runChainHandlers(handlers, initial) {
58
+ let value = initial;
59
+ for (const handler of handlers) {
60
+ const result = await handler(value);
61
+ if (result !== undefined) {
62
+ value = result;
63
+ }
64
+ }
65
+ return value;
66
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/utils/logger.ts"],"names":[],"mappings":"AAEA,cAAM,MAAM;IACV,OAAO,CAAC,cAAc;IAItB,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,IAAI;IAO5C;;OAEG;IACH,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,IAAI;IAS/E;;OAEG;IACH,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,IAAI;IASvF,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAI3B,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,KAAK,GAAG,IAAI;IAI3C,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;CAG5B;AAED,eAAO,MAAM,MAAM,QAAe,CAAC"}
1
+ {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/utils/logger.ts"],"names":[],"mappings":"AAUA,cAAM,MAAM;IACV,OAAO,CAAC,cAAc;IAItB,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,IAAI;IAO5C;;OAEG;IACH,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,IAAI;IAS/E;;OAEG;IACH,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,IAAI;IASvF,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAI3B,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,KAAK,GAAG,IAAI;IAI3C,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;CAG5B;AAED,eAAO,MAAM,MAAM,QAAe,CAAC"}
@@ -1,4 +1,11 @@
1
1
  import { config } from "../config.js";
2
+ /**
3
+ * Masks credentials passed as URL query parameters (e.g. Gemini's `?key=...`)
4
+ * so they never reach stdout or a log aggregator when debug logging is on.
5
+ */
6
+ function redactUrl(url) {
7
+ return url.replace(/([?&](?:key|api_key|apikey|access_token|token)=)[^&#]+/gi, "$1[REDACTED]");
8
+ }
2
9
  class Logger {
3
10
  isDebugEnabled() {
4
11
  return config.debug === true;
@@ -14,7 +21,7 @@ class Logger {
14
21
  */
15
22
  logRequest(provider, method, url, body) {
16
23
  if (this.isDebugEnabled()) {
17
- console.log(`[NodeLLM] [${provider}] Request: ${method} ${url}`);
24
+ console.log(`[NodeLLM] [${provider}] Request: ${method} ${redactUrl(url)}`);
18
25
  if (body) {
19
26
  console.log(JSON.stringify(body, null, 2));
20
27
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@node-llm/core",
3
- "version": "1.16.2",
3
+ "version": "1.17.1",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",