@agentforge/tools 0.18.5 → 0.18.7

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.js CHANGED
@@ -949,47 +949,33 @@ var webSearch = toolBuilder().name("web-search").description(
949
949
  };
950
950
  }
951
951
  }).build();
952
- function createGetConfiguredSlackClient(token, botName = "AgentForge Bot", botIcon = ":robot_face:") {
953
- let configuredClient = null;
954
- return function getConfiguredSlackClient() {
955
- if (!configuredClient) {
956
- const slackToken = token || process.env.SLACK_USER_TOKEN || process.env.SLACK_BOT_TOKEN;
957
- if (!slackToken) {
958
- throw new Error(
959
- "Slack token not configured. Please provide a token in config or set SLACK_USER_TOKEN or SLACK_BOT_TOKEN environment variable."
960
- );
952
+ function createLazySlackClient(resolveToken, config, missingTokenError) {
953
+ let client = null;
954
+ return () => {
955
+ const token = resolveToken();
956
+ if (!client) {
957
+ if (!token) {
958
+ throw new Error(missingTokenError);
961
959
  }
962
- configuredClient = new WebClient(slackToken);
960
+ client = new WebClient(token);
963
961
  }
964
- return {
965
- client: configuredClient,
966
- config: {
967
- token: token || process.env.SLACK_USER_TOKEN || process.env.SLACK_BOT_TOKEN || "",
968
- botName,
969
- botIcon
970
- }
971
- };
962
+ return { client, config: { token: token || "", ...config } };
972
963
  };
973
964
  }
974
- var defaultSlackClient = null;
965
+ function createGetConfiguredSlackClient(token, botName = "AgentForge Bot", botIcon = ":robot_face:") {
966
+ return createLazySlackClient(
967
+ () => token || process.env.SLACK_USER_TOKEN || process.env.SLACK_BOT_TOKEN,
968
+ { botName, botIcon },
969
+ "Slack token not configured. Please provide a token in config or set SLACK_USER_TOKEN or SLACK_BOT_TOKEN environment variable."
970
+ );
971
+ }
972
+ var getLazyDefaultSlackClient = createLazySlackClient(
973
+ () => process.env.SLACK_USER_TOKEN || process.env.SLACK_BOT_TOKEN,
974
+ { botName: "AgentForge Bot", botIcon: ":robot_face:" },
975
+ "Slack token not configured. Please set SLACK_USER_TOKEN or SLACK_BOT_TOKEN environment variable."
976
+ );
975
977
  function getDefaultSlackClient() {
976
- if (!defaultSlackClient) {
977
- const token = process.env.SLACK_USER_TOKEN || process.env.SLACK_BOT_TOKEN;
978
- if (!token) {
979
- throw new Error(
980
- "Slack token not configured. Please set SLACK_USER_TOKEN or SLACK_BOT_TOKEN environment variable."
981
- );
982
- }
983
- defaultSlackClient = new WebClient(token);
984
- }
985
- return {
986
- client: defaultSlackClient,
987
- config: {
988
- token: process.env.SLACK_USER_TOKEN || process.env.SLACK_BOT_TOKEN || "",
989
- botName: "AgentForge Bot",
990
- botIcon: ":robot_face:"
991
- }
992
- };
978
+ return getLazyDefaultSlackClient();
993
979
  }
994
980
  function createSendSlackMessageTool(getSlackClient, logger20) {
995
981
  return toolBuilder().name("send-slack-message").description("Send a message to a Slack channel for team communication and notifications").category(ToolCategory.WEB).tags(["slack", "messaging", "communication"]).usageNotes(
@@ -2876,6 +2862,61 @@ var OpenAIEmbeddingProvider = class {
2876
2862
  });
2877
2863
  }
2878
2864
  };
2865
+ async function generateHostedEmbedding(text, model, generateBatch) {
2866
+ const result = await generateBatch([text], model);
2867
+ return {
2868
+ embedding: result.embeddings[0],
2869
+ model: result.model,
2870
+ dimensions: result.dimensions,
2871
+ usage: result.usage
2872
+ };
2873
+ }
2874
+ function generateHostedBatchEmbeddings({
2875
+ texts,
2876
+ model,
2877
+ request: request2,
2878
+ formatError
2879
+ }) {
2880
+ return retryWithBackoff2(async () => {
2881
+ try {
2882
+ const { embeddings, usage } = await request2(texts, model);
2883
+ return {
2884
+ embeddings,
2885
+ model,
2886
+ dimensions: embeddings[0]?.length || 0,
2887
+ usage
2888
+ };
2889
+ } catch (error) {
2890
+ if (!axios5.isAxiosError(error)) throw error;
2891
+ const status = error.response?.status;
2892
+ const providerMessage = error.response?.data?.message || error.message;
2893
+ throw withProviderErrorMetadata(
2894
+ error,
2895
+ formatError({
2896
+ kind: classifyHttpError(status),
2897
+ status,
2898
+ providerMessage
2899
+ })
2900
+ );
2901
+ }
2902
+ });
2903
+ }
2904
+ function classifyHttpError(status) {
2905
+ if (status === 401) return "authentication";
2906
+ if (status === 429) return "rate-limit";
2907
+ if (status === 400) return "invalid-request";
2908
+ return "other";
2909
+ }
2910
+
2911
+ // src/data/neo4j/embeddings/providers/cohere.ts
2912
+ function formatCohereError({ kind, status, providerMessage }) {
2913
+ if (kind === "authentication") {
2914
+ return `Cohere API authentication failed. Please check your COHERE_API_KEY. ${providerMessage}`;
2915
+ }
2916
+ if (kind === "rate-limit") return `Cohere API rate limit exceeded. ${providerMessage}`;
2917
+ if (kind === "invalid-request") return `Cohere API request invalid: ${providerMessage}`;
2918
+ return `Cohere API error (${status}): ${providerMessage}`;
2919
+ }
2879
2920
  var CohereEmbeddingProvider = class {
2880
2921
  name = "cohere";
2881
2922
  defaultModel = "embed-english-v3.0";
@@ -2891,62 +2932,43 @@ var CohereEmbeddingProvider = class {
2891
2932
  return !!this.apiKey;
2892
2933
  }
2893
2934
  async generateEmbedding(text, model) {
2894
- const result = await this.generateBatchEmbeddings([text], model);
2895
- return {
2896
- embedding: result.embeddings[0],
2897
- model: result.model,
2898
- dimensions: result.dimensions,
2899
- usage: result.usage
2900
- };
2935
+ return generateHostedEmbedding(
2936
+ text,
2937
+ model,
2938
+ (texts, batchModel) => this.generateBatchEmbeddings(texts, batchModel)
2939
+ );
2901
2940
  }
2902
2941
  async generateBatchEmbeddings(texts, model) {
2903
2942
  const modelToUse = model || this.defaultModel;
2904
- return retryWithBackoff2(async () => {
2905
- try {
2943
+ return generateHostedBatchEmbeddings({
2944
+ texts,
2945
+ model: modelToUse,
2946
+ formatError: formatCohereError,
2947
+ request: async (requestTexts, requestModel) => {
2906
2948
  const response = await axios5.post(
2907
2949
  `${this.baseUrl}/embed`,
2908
2950
  {
2909
- texts,
2910
- model: modelToUse,
2951
+ texts: requestTexts,
2952
+ model: requestModel,
2911
2953
  input_type: "search_document",
2912
2954
  // For storing in vector DB
2913
2955
  embedding_types: ["float"]
2914
2956
  },
2915
2957
  {
2916
2958
  headers: {
2917
- "Authorization": `Bearer ${this.apiKey}`,
2959
+ Authorization: `Bearer ${this.apiKey}`,
2918
2960
  "Content-Type": "application/json"
2919
2961
  }
2920
2962
  }
2921
2963
  );
2922
2964
  const embeddings = response.data.embeddings.float;
2923
- const dimensions = embeddings[0]?.length || 0;
2924
2965
  return {
2925
2966
  embeddings,
2926
- model: modelToUse,
2927
- dimensions,
2928
2967
  usage: response.data.meta?.billed_units ? {
2929
2968
  promptTokens: response.data.meta.billed_units.input_tokens || 0,
2930
2969
  totalTokens: response.data.meta.billed_units.input_tokens || 0
2931
2970
  } : void 0
2932
2971
  };
2933
- } catch (error) {
2934
- if (axios5.isAxiosError(error)) {
2935
- const status = error.response?.status;
2936
- const providerMessage = error.response?.data?.message || error.message;
2937
- let message;
2938
- if (status === 401) {
2939
- message = `Cohere API authentication failed. Please check your COHERE_API_KEY. ${providerMessage}`;
2940
- } else if (status === 429) {
2941
- message = `Cohere API rate limit exceeded. ${providerMessage}`;
2942
- } else if (status === 400) {
2943
- message = `Cohere API request invalid: ${providerMessage}`;
2944
- } else {
2945
- message = `Cohere API error (${status}): ${providerMessage}`;
2946
- }
2947
- throw withProviderErrorMetadata(error, message);
2948
- }
2949
- throw error;
2950
2972
  }
2951
2973
  });
2952
2974
  }
@@ -2966,77 +2988,51 @@ var HuggingFaceEmbeddingProvider = class {
2966
2988
  return !!this.apiKey;
2967
2989
  }
2968
2990
  async generateEmbedding(text, model) {
2969
- const modelToUse = model || this.defaultModel;
2970
- return retryWithBackoff2(async () => {
2971
- try {
2972
- const response = await axios5.post(
2973
- `${this.baseUrl}/${modelToUse}`,
2974
- {
2975
- inputs: text,
2976
- options: {
2977
- wait_for_model: true
2978
- }
2979
- },
2980
- {
2981
- headers: {
2982
- "Authorization": `Bearer ${this.apiKey}`,
2983
- "Content-Type": "application/json"
2984
- }
2985
- }
2986
- );
2987
- const embedding = Array.isArray(response.data) ? response.data : response.data[0];
2988
- return {
2989
- embedding,
2990
- model: modelToUse,
2991
- dimensions: embedding.length
2992
- };
2993
- } catch (error) {
2994
- if (axios5.isAxiosError(error)) {
2995
- const status = error.response?.status;
2996
- const message = error.response?.data?.error || error.message;
2997
- let messageText;
2998
- if (status === 401) {
2999
- messageText = `HuggingFace API authentication failed. Please check your HUGGINGFACE_API_KEY. ${message}`;
3000
- } else if (status === 429) {
3001
- messageText = `HuggingFace API rate limit exceeded. ${message}`;
3002
- } else if (status === 400) {
3003
- messageText = `HuggingFace API request invalid: ${message}`;
3004
- } else if (status === 503) {
3005
- messageText = `HuggingFace model is loading. Please retry in a moment. ${message}`;
3006
- } else {
3007
- messageText = `HuggingFace API error (${status}): ${message}`;
3008
- }
3009
- throw withProviderErrorMetadata(error, messageText);
3010
- }
3011
- throw error;
3012
- }
3013
- });
2991
+ const { data, model: modelToUse } = await this.requestEmbeddings(
2992
+ text,
2993
+ model
2994
+ );
2995
+ const embedding = Array.isArray(data) ? data : data[0];
2996
+ return {
2997
+ embedding,
2998
+ model: modelToUse,
2999
+ dimensions: embedding.length
3000
+ };
3014
3001
  }
3015
3002
  async generateBatchEmbeddings(texts, model) {
3003
+ const { data: embeddings, model: modelToUse } = await this.requestEmbeddings(
3004
+ texts,
3005
+ model
3006
+ );
3007
+ const dimensions = embeddings[0]?.length || 0;
3008
+ return {
3009
+ embeddings,
3010
+ model: modelToUse,
3011
+ dimensions
3012
+ };
3013
+ }
3014
+ async requestEmbeddings(inputs, model) {
3016
3015
  const modelToUse = model || this.defaultModel;
3017
3016
  return retryWithBackoff2(async () => {
3018
3017
  try {
3019
3018
  const response = await axios5.post(
3020
3019
  `${this.baseUrl}/${modelToUse}`,
3021
3020
  {
3022
- inputs: texts,
3021
+ inputs,
3023
3022
  options: {
3024
3023
  wait_for_model: true
3025
3024
  }
3026
3025
  },
3027
3026
  {
3028
3027
  headers: {
3029
- "Authorization": `Bearer ${this.apiKey}`,
3028
+ Authorization: `Bearer ${this.apiKey}`,
3030
3029
  "Content-Type": "application/json"
3031
3030
  }
3032
3031
  }
3033
3032
  );
3034
- const embeddings = response.data;
3035
- const dimensions = embeddings[0]?.length || 0;
3036
3033
  return {
3037
- embeddings,
3038
- model: modelToUse,
3039
- dimensions
3034
+ data: response.data,
3035
+ model: modelToUse
3040
3036
  };
3041
3037
  } catch (error) {
3042
3038
  if (axios5.isAxiosError(error)) {
@@ -3061,6 +3057,14 @@ var HuggingFaceEmbeddingProvider = class {
3061
3057
  });
3062
3058
  }
3063
3059
  };
3060
+ function formatVoyageError({ kind, status, providerMessage }) {
3061
+ if (kind === "authentication") {
3062
+ return `Voyage AI API authentication failed. Please check your VOYAGE_API_KEY. ${providerMessage}`;
3063
+ }
3064
+ if (kind === "rate-limit") return `Voyage AI API rate limit exceeded. ${providerMessage}`;
3065
+ if (kind === "invalid-request") return `Voyage AI API request invalid: ${providerMessage}`;
3066
+ return `Voyage AI API error (${status}): ${providerMessage}`;
3067
+ }
3064
3068
  var VoyageEmbeddingProvider = class {
3065
3069
  name = "voyage";
3066
3070
  defaultModel = "voyage-2";
@@ -3076,61 +3080,44 @@ var VoyageEmbeddingProvider = class {
3076
3080
  return !!this.apiKey;
3077
3081
  }
3078
3082
  async generateEmbedding(text, model) {
3079
- const result = await this.generateBatchEmbeddings([text], model);
3080
- return {
3081
- embedding: result.embeddings[0],
3082
- model: result.model,
3083
- dimensions: result.dimensions,
3084
- usage: result.usage
3085
- };
3083
+ return generateHostedEmbedding(
3084
+ text,
3085
+ model,
3086
+ (texts, batchModel) => this.generateBatchEmbeddings(texts, batchModel)
3087
+ );
3086
3088
  }
3087
3089
  async generateBatchEmbeddings(texts, model) {
3088
3090
  const modelToUse = model || this.defaultModel;
3089
- return retryWithBackoff2(async () => {
3090
- try {
3091
+ return generateHostedBatchEmbeddings({
3092
+ texts,
3093
+ model: modelToUse,
3094
+ formatError: formatVoyageError,
3095
+ request: async (requestTexts, requestModel) => {
3091
3096
  const response = await axios5.post(
3092
3097
  `${this.baseUrl}/embeddings`,
3093
3098
  {
3094
- input: texts,
3095
- model: modelToUse,
3099
+ input: requestTexts,
3100
+ model: requestModel,
3096
3101
  input_type: "document"
3097
3102
  // For storing in vector DB
3098
3103
  },
3099
3104
  {
3100
3105
  headers: {
3101
- "Authorization": `Bearer ${this.apiKey}`,
3106
+ Authorization: `Bearer ${this.apiKey}`,
3102
3107
  "Content-Type": "application/json"
3103
3108
  }
3104
3109
  }
3105
3110
  );
3106
- const embeddings = response.data.data.map((item) => item.embedding);
3107
- const dimensions = embeddings[0]?.length || 0;
3111
+ const embeddings = response.data.data.map(
3112
+ (item) => item.embedding
3113
+ );
3108
3114
  return {
3109
3115
  embeddings,
3110
- model: modelToUse,
3111
- dimensions,
3112
3116
  usage: response.data.usage ? {
3113
3117
  promptTokens: response.data.usage.total_tokens || 0,
3114
3118
  totalTokens: response.data.usage.total_tokens || 0
3115
3119
  } : void 0
3116
3120
  };
3117
- } catch (error) {
3118
- if (axios5.isAxiosError(error)) {
3119
- const status = error.response?.status;
3120
- const message = error.response?.data?.message || error.message;
3121
- let messageText;
3122
- if (status === 401) {
3123
- messageText = `Voyage AI API authentication failed. Please check your VOYAGE_API_KEY. ${message}`;
3124
- } else if (status === 429) {
3125
- messageText = `Voyage AI API rate limit exceeded. ${message}`;
3126
- } else if (status === 400) {
3127
- messageText = `Voyage AI API request invalid: ${message}`;
3128
- } else {
3129
- messageText = `Voyage AI API error (${status}): ${message}`;
3130
- }
3131
- throw withProviderErrorMetadata(error, messageText);
3132
- }
3133
- throw error;
3134
3121
  }
3135
3122
  });
3136
3123
  }
@@ -7173,15 +7160,6 @@ function formatTableName(table) {
7173
7160
  return table.schema ? `${table.schema}.${table.name}` : table.name;
7174
7161
  }
7175
7162
 
7176
- // src/data/relational/schema/type-mapper-normalization.ts
7177
- function normaliseDbType(raw) {
7178
- let type = raw.toLowerCase().trim();
7179
- type = type.replace(/\[\]$/, "");
7180
- type = type.replace(/\([\d,\s]+\)/, "");
7181
- type = type.replace(/\s+unsigned$/, "");
7182
- return type.trim();
7183
- }
7184
-
7185
7163
  // src/data/relational/schema/type-mapper-vendor-maps.ts
7186
7164
  var POSTGRES_TYPE_MAP = {
7187
7165
  smallint: "number",
@@ -7357,6 +7335,13 @@ function getVendorTypeMap(vendor) {
7357
7335
  function usesStringPrecisionFallback(vendor, normalised) {
7358
7336
  return (normalised === "bigint" || normalised === "int8" || normalised === "bigserial") && (vendor === "postgresql" || vendor === "mysql");
7359
7337
  }
7338
+ function normaliseDbType(raw) {
7339
+ let type = raw.toLowerCase().trim();
7340
+ type = type.replace(/\[\]$/, "");
7341
+ type = type.replace(/\([\d,\s]+\)/, "");
7342
+ type = type.replace(/\s+unsigned$/, "");
7343
+ return type.trim();
7344
+ }
7360
7345
  var logger14 = createLogger("agentforge:tools:data:relational:schema-diff");
7361
7346
  function diffSchemas(before, after) {
7362
7347
  const tableDiffs = [];