@flutchai/flutch-sdk 0.2.14 → 0.2.16
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/README.md +37 -0
- package/dist/index.cjs +127 -33
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +57 -31
- package/dist/index.d.ts +57 -31
- package/dist/index.js +121 -34
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -522,6 +522,43 @@ Currently supports LangGraph.js. The architecture is designed to support other g
|
|
|
522
522
|
- **Multi-step Workflows**: Orchestrate complex AI pipelines
|
|
523
523
|
- **Interactive Assistants**: Create agents with callbacks and dynamic UIs
|
|
524
524
|
|
|
525
|
+
## Publishing
|
|
526
|
+
|
|
527
|
+
The package is automatically published to [npmjs.org](https://www.npmjs.com/package/@flutchai/flutch-sdk) on every merge to `main` via GitHub Actions.
|
|
528
|
+
|
|
529
|
+
### How it works
|
|
530
|
+
|
|
531
|
+
1. On merge to `main`, the [release workflow](.github/workflows/release.yml) runs
|
|
532
|
+
2. It reads the version from `package.json`
|
|
533
|
+
3. If a git tag `v{version}` does not exist yet — it creates the tag and publishes to npm
|
|
534
|
+
4. If the tag already exists — all publish steps are skipped (idempotent)
|
|
535
|
+
|
|
536
|
+
Publishing uses [npm OIDC Trusted Publishing](https://docs.npmjs.com/generating-provenance-statements) — no npm token secret is required. The GitHub Actions runner authenticates directly with npmjs.org via OpenID Connect.
|
|
537
|
+
|
|
538
|
+
### Rules
|
|
539
|
+
|
|
540
|
+
- **Bump the version before merging** — if `package.json` version matches an existing git tag, nothing will be published
|
|
541
|
+
- **Use semantic versioning** — `MAJOR.MINOR.PATCH` (e.g. `0.2.14`)
|
|
542
|
+
- `PATCH` — bug fixes, minor improvements
|
|
543
|
+
- `MINOR` — new backward-compatible features
|
|
544
|
+
- `MAJOR` — breaking changes
|
|
545
|
+
- **One version bump per PR** — keep version changes isolated from feature/fix changes when possible
|
|
546
|
+
|
|
547
|
+
### Releasing a new version
|
|
548
|
+
|
|
549
|
+
```bash
|
|
550
|
+
# 1. Create a branch
|
|
551
|
+
git checkout -b chore/bump-version-X.Y.Z
|
|
552
|
+
|
|
553
|
+
# 2. Update version in package.json
|
|
554
|
+
# "version": "X.Y.Z"
|
|
555
|
+
|
|
556
|
+
# 3. Push and open a PR
|
|
557
|
+
git push origin chore/bump-version-X.Y.Z
|
|
558
|
+
|
|
559
|
+
# 4. Merge the PR — publishing happens automatically
|
|
560
|
+
```
|
|
561
|
+
|
|
525
562
|
## Links
|
|
526
563
|
|
|
527
564
|
- [GitHub Repository](https://github.com/flutchai/node-sdk)
|
package/dist/index.cjs
CHANGED
|
@@ -25,6 +25,7 @@ var openai = require('@langchain/openai');
|
|
|
25
25
|
var aws = require('@langchain/aws');
|
|
26
26
|
var anthropic = require('@langchain/anthropic');
|
|
27
27
|
var cohere = require('@langchain/cohere');
|
|
28
|
+
var cohereAi = require('cohere-ai');
|
|
28
29
|
var document_compressors = require('@langchain/core/retrievers/document_compressors');
|
|
29
30
|
var mistralai = require('@langchain/mistralai');
|
|
30
31
|
|
|
@@ -6466,6 +6467,12 @@ function hashToolsConfig(toolsConfig) {
|
|
|
6466
6467
|
const sorted = toolsConfig.map((t) => `${t.toolName}:${t.enabled}:${JSON.stringify(t.config || {})}`).sort().join("|");
|
|
6467
6468
|
return crypto.createHash("md5").update(sorted).digest("hex").slice(0, 16);
|
|
6468
6469
|
}
|
|
6470
|
+
function normalizeToolConfigs(tools) {
|
|
6471
|
+
if (!tools || tools.length === 0) return void 0;
|
|
6472
|
+
return tools.map(
|
|
6473
|
+
(t) => typeof t === "string" ? { toolName: t, enabled: true } : { toolName: t.name, enabled: t.enabled !== false, config: t.config }
|
|
6474
|
+
);
|
|
6475
|
+
}
|
|
6469
6476
|
var DEFAULT_ROUTER_URL = "https://router.flutch.ai";
|
|
6470
6477
|
function resolveRouterURL(baseURL) {
|
|
6471
6478
|
return baseURL ?? process.env.FLUTCH_ROUTER_URL ?? DEFAULT_ROUTER_URL;
|
|
@@ -6508,13 +6515,14 @@ var VoyageAIRerank = class extends document_compressors.BaseDocumentCompressor {
|
|
|
6508
6515
|
model;
|
|
6509
6516
|
topN;
|
|
6510
6517
|
truncation;
|
|
6511
|
-
baseUrl
|
|
6518
|
+
baseUrl;
|
|
6512
6519
|
constructor(config) {
|
|
6513
6520
|
super();
|
|
6514
6521
|
this.apiKey = config.apiKey || process.env.VOYAGEAI_API_KEY || "";
|
|
6515
6522
|
this.model = config.model || "rerank-2";
|
|
6516
6523
|
this.topN = config.topN || 20;
|
|
6517
6524
|
this.truncation = config.truncation ?? true;
|
|
6525
|
+
this.baseUrl = config.baseUrl ? `${config.baseUrl}/v1/rerank` : "https://api.voyageai.com/v1/rerank";
|
|
6518
6526
|
if (!this.apiKey) {
|
|
6519
6527
|
throw new Error(
|
|
6520
6528
|
"VoyageAI API key is required. Set VOYAGEAI_API_KEY environment variable or pass apiKey in config."
|
|
@@ -6645,22 +6653,31 @@ var ModelInitializer = class _ModelInitializer {
|
|
|
6645
6653
|
modelName,
|
|
6646
6654
|
defaultTemperature,
|
|
6647
6655
|
defaultMaxTokens,
|
|
6648
|
-
apiToken
|
|
6656
|
+
apiToken,
|
|
6657
|
+
baseURL
|
|
6649
6658
|
}) => new cohere.ChatCohere({
|
|
6650
6659
|
model: modelName,
|
|
6651
6660
|
temperature: defaultTemperature,
|
|
6652
|
-
|
|
6661
|
+
client: new cohereAi.CohereClient({
|
|
6662
|
+
token: apiToken || this.resolveApiKey("cohere" /* COHERE */),
|
|
6663
|
+
baseUrl: resolveRouterURL(baseURL)
|
|
6664
|
+
})
|
|
6653
6665
|
}),
|
|
6654
6666
|
["mistral" /* MISTRAL */]: ({
|
|
6655
6667
|
modelName,
|
|
6656
6668
|
defaultTemperature,
|
|
6657
6669
|
defaultMaxTokens,
|
|
6658
|
-
apiToken
|
|
6670
|
+
apiToken,
|
|
6671
|
+
baseURL
|
|
6659
6672
|
}) => new mistralai.ChatMistralAI({
|
|
6660
6673
|
model: modelName,
|
|
6661
6674
|
temperature: defaultTemperature,
|
|
6662
6675
|
maxTokens: defaultMaxTokens,
|
|
6663
|
-
apiKey: apiToken || this.resolveApiKey("mistral" /* MISTRAL */)
|
|
6676
|
+
apiKey: apiToken || this.resolveApiKey("mistral" /* MISTRAL */),
|
|
6677
|
+
// Route through the same gateway as OpenAI/Anthropic.
|
|
6678
|
+
// Without serverURL, ChatMistralAI ignores FLUTCH_ROUTER_URL and calls
|
|
6679
|
+
// api.mistral.ai directly — inconsistent with other providers.
|
|
6680
|
+
serverURL: `${resolveRouterURL(baseURL)}/v1`
|
|
6664
6681
|
}),
|
|
6665
6682
|
["voyageai" /* VOYAGEAI */]: () => {
|
|
6666
6683
|
throw new Error("VoyageAI chat models not implemented");
|
|
@@ -6668,18 +6685,32 @@ var ModelInitializer = class _ModelInitializer {
|
|
|
6668
6685
|
};
|
|
6669
6686
|
// Rerank model creators
|
|
6670
6687
|
rerankModelCreators = {
|
|
6671
|
-
["cohere" /* COHERE */]: ({
|
|
6688
|
+
["cohere" /* COHERE */]: ({
|
|
6689
|
+
modelName,
|
|
6690
|
+
apiToken,
|
|
6691
|
+
maxDocuments,
|
|
6692
|
+
baseURL
|
|
6693
|
+
}) => {
|
|
6672
6694
|
return new cohere.CohereRerank({
|
|
6673
|
-
apiKey: apiToken || this.resolveApiKey("cohere" /* COHERE */),
|
|
6674
6695
|
model: modelName,
|
|
6675
|
-
topN: maxDocuments || 20
|
|
6696
|
+
topN: maxDocuments || 20,
|
|
6697
|
+
client: new cohereAi.CohereClient({
|
|
6698
|
+
token: apiToken || this.resolveApiKey("cohere" /* COHERE */),
|
|
6699
|
+
baseUrl: resolveRouterURL(baseURL)
|
|
6700
|
+
})
|
|
6676
6701
|
});
|
|
6677
6702
|
},
|
|
6678
|
-
["voyageai" /* VOYAGEAI */]: ({
|
|
6703
|
+
["voyageai" /* VOYAGEAI */]: ({
|
|
6704
|
+
modelName,
|
|
6705
|
+
apiToken,
|
|
6706
|
+
maxDocuments,
|
|
6707
|
+
baseURL
|
|
6708
|
+
}) => {
|
|
6679
6709
|
return new VoyageAIRerank({
|
|
6680
6710
|
apiKey: apiToken || this.resolveApiKey("voyageai" /* VOYAGEAI */),
|
|
6681
6711
|
model: modelName,
|
|
6682
|
-
topN: maxDocuments || 20
|
|
6712
|
+
topN: maxDocuments || 20,
|
|
6713
|
+
baseUrl: resolveRouterURL(baseURL)
|
|
6683
6714
|
});
|
|
6684
6715
|
},
|
|
6685
6716
|
// Other providers don't support rerank yet
|
|
@@ -6690,9 +6721,10 @@ var ModelInitializer = class _ModelInitializer {
|
|
|
6690
6721
|
};
|
|
6691
6722
|
// Embedding model creators
|
|
6692
6723
|
embeddingModelCreators = {
|
|
6693
|
-
["openai" /* OPENAI */]: ({ modelName, apiToken }) => new openai.OpenAIEmbeddings({
|
|
6724
|
+
["openai" /* OPENAI */]: ({ modelName, apiToken, baseURL }) => new openai.OpenAIEmbeddings({
|
|
6694
6725
|
model: modelName,
|
|
6695
|
-
apiKey: apiToken || this.resolveApiKey("openai" /* OPENAI */)
|
|
6726
|
+
apiKey: apiToken || this.resolveApiKey("openai" /* OPENAI */),
|
|
6727
|
+
configuration: { baseURL: `${resolveRouterURL(baseURL)}/v1` }
|
|
6696
6728
|
}),
|
|
6697
6729
|
// Other providers not yet implemented for embeddings
|
|
6698
6730
|
["anthropic" /* ANTHROPIC */]: void 0,
|
|
@@ -6701,7 +6733,82 @@ var ModelInitializer = class _ModelInitializer {
|
|
|
6701
6733
|
["aws" /* AWS */]: void 0,
|
|
6702
6734
|
["voyageai" /* VOYAGEAI */]: void 0
|
|
6703
6735
|
};
|
|
6704
|
-
|
|
6736
|
+
// ══════════════════════════════════════════════════════════════
|
|
6737
|
+
// initializeChatModel — overloaded: ModelConfig | ModelByIdConfig
|
|
6738
|
+
// ══════════════════════════════════════════════════════════════
|
|
6739
|
+
async initializeChatModel(config, customTools) {
|
|
6740
|
+
if ("provider" in config && "modelName" in config) {
|
|
6741
|
+
return this.initializeChatModelDirect(config, customTools);
|
|
6742
|
+
}
|
|
6743
|
+
return this.initializeChatModelByIdInternal(config);
|
|
6744
|
+
}
|
|
6745
|
+
/**
|
|
6746
|
+
* Direct initialization by provider + modelName (no DB lookup).
|
|
6747
|
+
*/
|
|
6748
|
+
async initializeChatModelDirect(config, customTools) {
|
|
6749
|
+
const toolsConfig = normalizeToolConfigs(config.tools);
|
|
6750
|
+
const modelIdentifier = `${config.provider}:${config.modelName}`;
|
|
6751
|
+
const cacheKey = generateModelCacheKey(
|
|
6752
|
+
modelIdentifier,
|
|
6753
|
+
config.temperature,
|
|
6754
|
+
config.maxTokens,
|
|
6755
|
+
toolsConfig,
|
|
6756
|
+
config.baseURL
|
|
6757
|
+
);
|
|
6758
|
+
const cached = this.modelInstanceCache.get(cacheKey);
|
|
6759
|
+
if (cached) {
|
|
6760
|
+
this.logger.debug(`Using cached chat model instance: ${cacheKey}`);
|
|
6761
|
+
return cached;
|
|
6762
|
+
}
|
|
6763
|
+
const provider = config.provider;
|
|
6764
|
+
if (!Object.values(ModelProvider).includes(provider)) {
|
|
6765
|
+
throw new Error(
|
|
6766
|
+
`Unknown provider "${provider}". Valid: ${Object.values(ModelProvider).join(", ")}`
|
|
6767
|
+
);
|
|
6768
|
+
}
|
|
6769
|
+
const apiToken = this.resolveApiKey(provider);
|
|
6770
|
+
const temperature = config.temperature ?? 0.7;
|
|
6771
|
+
const maxTokens = config.maxTokens ?? 4096;
|
|
6772
|
+
const modelConfig = {
|
|
6773
|
+
modelId: modelIdentifier,
|
|
6774
|
+
modelName: config.modelName,
|
|
6775
|
+
provider,
|
|
6776
|
+
modelType: "chat" /* CHAT */,
|
|
6777
|
+
defaultTemperature: Number(temperature),
|
|
6778
|
+
defaultMaxTokens: Number(maxTokens),
|
|
6779
|
+
apiToken,
|
|
6780
|
+
requiresApiKey: true,
|
|
6781
|
+
baseURL: config.baseURL
|
|
6782
|
+
};
|
|
6783
|
+
this.logger.debug(
|
|
6784
|
+
`Creating chat model: ${modelIdentifier} (apiKeyResolved=${!!apiToken})`
|
|
6785
|
+
);
|
|
6786
|
+
const creator = this.chatModelCreators[provider];
|
|
6787
|
+
if (!creator) {
|
|
6788
|
+
throw new Error(`Chat models not supported for provider: ${provider}`);
|
|
6789
|
+
}
|
|
6790
|
+
const model = creator(modelConfig);
|
|
6791
|
+
model.metadata = {
|
|
6792
|
+
...model.metadata,
|
|
6793
|
+
modelId: modelIdentifier
|
|
6794
|
+
};
|
|
6795
|
+
if (toolsConfig || customTools) {
|
|
6796
|
+
const boundModel = await this.bindToolsToModel(
|
|
6797
|
+
model,
|
|
6798
|
+
toolsConfig,
|
|
6799
|
+
customTools
|
|
6800
|
+
);
|
|
6801
|
+
this.modelInstanceCache.set(cacheKey, boundModel);
|
|
6802
|
+
return boundModel;
|
|
6803
|
+
}
|
|
6804
|
+
this.modelInstanceCache.set(cacheKey, model);
|
|
6805
|
+
return model;
|
|
6806
|
+
}
|
|
6807
|
+
/**
|
|
6808
|
+
* Legacy initialization by model ID (DB lookup via configFetcher).
|
|
6809
|
+
* @deprecated Pass ModelConfig with provider + modelName instead.
|
|
6810
|
+
*/
|
|
6811
|
+
async initializeChatModelByIdInternal(config) {
|
|
6705
6812
|
const cacheKey = this.generateModelCacheKey(config);
|
|
6706
6813
|
const cachedModel = this.modelInstanceCache.get(cacheKey);
|
|
6707
6814
|
if (cachedModel) {
|
|
@@ -6727,9 +6834,6 @@ var ModelInitializer = class _ModelInitializer {
|
|
|
6727
6834
|
this.logger.debug(`Creating new chat model instance: ${cacheKey}`);
|
|
6728
6835
|
let model;
|
|
6729
6836
|
if (finalConfig.useBedrock && finalConfig.bedrockModelId) {
|
|
6730
|
-
this.logger.debug(
|
|
6731
|
-
`Using Bedrock for model ${finalConfig.modelName}, bedrockModelId: ${finalConfig.bedrockModelId}`
|
|
6732
|
-
);
|
|
6733
6837
|
model = new aws.ChatBedrockConverse({
|
|
6734
6838
|
model: finalConfig.bedrockModelId,
|
|
6735
6839
|
region: this.resolveBedrockRegion(),
|
|
@@ -6750,29 +6854,12 @@ var ModelInitializer = class _ModelInitializer {
|
|
|
6750
6854
|
...model.metadata,
|
|
6751
6855
|
modelId: config.modelId
|
|
6752
6856
|
};
|
|
6753
|
-
this.logger.debug("\u{1F527} Model initialized with metadata", {
|
|
6754
|
-
modelId: config.modelId,
|
|
6755
|
-
metadataKeys: Object.keys(model.metadata || {}),
|
|
6756
|
-
hasModelId: !!model.metadata?.modelId
|
|
6757
|
-
});
|
|
6758
|
-
this.logger.debug(
|
|
6759
|
-
`[TOOLS CHECK] toolsConfig exists: ${!!config.toolsConfig}, customTools exists: ${!!config.customTools}`
|
|
6760
|
-
);
|
|
6761
|
-
if (config.toolsConfig) {
|
|
6762
|
-
this.logger.debug(
|
|
6763
|
-
`[TOOLS CHECK] toolsConfig length: ${config.toolsConfig.length}, content: ${JSON.stringify(config.toolsConfig)}`
|
|
6764
|
-
);
|
|
6765
|
-
}
|
|
6766
6857
|
if (config.toolsConfig || config.customTools) {
|
|
6767
|
-
this.logger.debug(
|
|
6768
|
-
`[TOOLS] Calling bindToolsToModel with toolsConfig: ${JSON.stringify(config.toolsConfig)}`
|
|
6769
|
-
);
|
|
6770
6858
|
const boundModel = await this.bindToolsToModel(
|
|
6771
6859
|
model,
|
|
6772
6860
|
config.toolsConfig,
|
|
6773
6861
|
config.customTools
|
|
6774
6862
|
);
|
|
6775
|
-
this.logger.debug(`[TOOLS] bindToolsToModel returned successfully`);
|
|
6776
6863
|
this.modelInstanceCache.set(cacheKey, boundModel);
|
|
6777
6864
|
return boundModel;
|
|
6778
6865
|
}
|
|
@@ -7607,6 +7694,7 @@ exports.CallbackRegistry = CallbackRegistry;
|
|
|
7607
7694
|
exports.CallbackStore = CallbackStore;
|
|
7608
7695
|
exports.ChatFeature = ChatFeature;
|
|
7609
7696
|
exports.DEFAULT_ATTACHMENT_THRESHOLD = DEFAULT_ATTACHMENT_THRESHOLD;
|
|
7697
|
+
exports.DEFAULT_ROUTER_URL = DEFAULT_ROUTER_URL;
|
|
7610
7698
|
exports.DEFAULT_TRACER_OPTIONS = DEFAULT_TRACER_OPTIONS;
|
|
7611
7699
|
exports.Endpoint = Endpoint;
|
|
7612
7700
|
exports.FileTokenStore = FileTokenStore;
|
|
@@ -7633,6 +7721,7 @@ exports.WithUIEndpoints = WithUIEndpoints;
|
|
|
7633
7721
|
exports._internals = _internals;
|
|
7634
7722
|
exports.bootstrap = bootstrap;
|
|
7635
7723
|
exports.buildOAuthAuthorizationUrl = buildOAuthAuthorizationUrl;
|
|
7724
|
+
exports.buildOpenAIModelConfig = buildOpenAIModelConfig;
|
|
7636
7725
|
exports.clearAttachmentDataStore = clearAttachmentDataStore;
|
|
7637
7726
|
exports.createEndpointDescriptors = createEndpointDescriptors;
|
|
7638
7727
|
exports.createGraphAttachment = createGraphAttachment;
|
|
@@ -7645,6 +7734,7 @@ exports.executeToolWithAttachments = executeToolWithAttachments;
|
|
|
7645
7734
|
exports.findCallbackMethod = findCallbackMethod;
|
|
7646
7735
|
exports.findEndpointMethod = findEndpointMethod;
|
|
7647
7736
|
exports.generateAttachmentSummary = generateAttachmentSummary;
|
|
7737
|
+
exports.generateModelCacheKey = generateModelCacheKey;
|
|
7648
7738
|
exports.getAttachmentData = getAttachmentData;
|
|
7649
7739
|
exports.getCallbackMetadata = getCallbackMetadata;
|
|
7650
7740
|
exports.getEndpointMetadata = getEndpointMetadata;
|
|
@@ -7654,10 +7744,14 @@ exports.getUIEndpointClassMetadata = getUIEndpointClassMetadata;
|
|
|
7654
7744
|
exports.getUIEndpointMethodsMetadata = getUIEndpointMethodsMetadata;
|
|
7655
7745
|
exports.hasCallbacks = hasCallbacks;
|
|
7656
7746
|
exports.hasUIEndpoints = hasUIEndpoints;
|
|
7747
|
+
exports.hashToolsConfig = hashToolsConfig;
|
|
7748
|
+
exports.isReasoningModel = isReasoningModel;
|
|
7657
7749
|
exports.loadOAuthProviders = loadOAuthProviders;
|
|
7750
|
+
exports.normalizeToolConfigs = normalizeToolConfigs;
|
|
7658
7751
|
exports.registerFinanceExampleCallback = registerFinanceExampleCallback;
|
|
7659
7752
|
exports.registerUIEndpointsFromClass = registerUIEndpointsFromClass;
|
|
7660
7753
|
exports.resolveOAuthProviderConfig = resolveOAuthProviderConfig;
|
|
7754
|
+
exports.resolveRouterURL = resolveRouterURL;
|
|
7661
7755
|
exports.sanitizeTraceData = sanitizeTraceData;
|
|
7662
7756
|
exports.storeAttachmentData = storeAttachmentData;
|
|
7663
7757
|
exports.traceApiCall = traceApiCall;
|