@flutchai/flutch-sdk 0.2.11 → 0.2.15

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 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
@@ -4477,11 +4477,17 @@ async function executeToolWithAttachments(params) {
4477
4477
  threshold = DEFAULT_ATTACHMENT_THRESHOLD,
4478
4478
  injectIntoArg = "data",
4479
4479
  sourceAttachmentId,
4480
- threadId
4480
+ threadId,
4481
+ toolSchema
4481
4482
  } = params;
4482
4483
  const argsWithInjection = { ...enrichedArgs };
4483
4484
  try {
4484
- if (shouldInjectData(argsWithInjection, attachments, injectIntoArg)) {
4485
+ if (shouldInjectData(
4486
+ argsWithInjection,
4487
+ attachments,
4488
+ injectIntoArg,
4489
+ toolSchema
4490
+ )) {
4485
4491
  const attachment = sourceAttachmentId ? attachments[sourceAttachmentId] : getLatestAttachment(attachments);
4486
4492
  if (attachment) {
4487
4493
  const attachmentKey = sourceAttachmentId || attachment.toolCallId;
@@ -4543,9 +4549,17 @@ async function executeToolWithAttachments(params) {
4543
4549
  });
4544
4550
  return { toolMessage };
4545
4551
  }
4546
- function shouldInjectData(args, attachments, dataArgName) {
4552
+ function shouldInjectData(args, attachments, dataArgName, toolSchema) {
4547
4553
  if (Object.keys(attachments).length === 0) return false;
4548
- return args[dataArgName] === void 0;
4554
+ if (args[dataArgName] !== void 0) return false;
4555
+ if (toolSchema) {
4556
+ const hasProperty = toolSchema.properties && dataArgName in toolSchema.properties;
4557
+ const isRequired = toolSchema.required?.includes(dataArgName);
4558
+ if (!hasProperty && !isRequired) {
4559
+ return false;
4560
+ }
4561
+ }
4562
+ return true;
4549
4563
  }
4550
4564
  var _internals = {
4551
4565
  shouldInjectData,
@@ -6452,12 +6466,19 @@ function hashToolsConfig(toolsConfig) {
6452
6466
  const sorted = toolsConfig.map((t) => `${t.toolName}:${t.enabled}:${JSON.stringify(t.config || {})}`).sort().join("|");
6453
6467
  return crypto.createHash("md5").update(sorted).digest("hex").slice(0, 16);
6454
6468
  }
6455
- function generateModelCacheKey(modelId, temperature, maxTokens, toolsConfig) {
6469
+ var DEFAULT_ROUTER_URL = "https://router.flutch.ai";
6470
+ function resolveRouterURL(baseURL) {
6471
+ return baseURL ?? process.env.FLUTCH_ROUTER_URL ?? DEFAULT_ROUTER_URL;
6472
+ }
6473
+ function generateModelCacheKey(modelId, temperature, maxTokens, toolsConfig, baseURL) {
6456
6474
  const parts = [
6457
6475
  modelId,
6458
6476
  temperature ?? "default",
6459
6477
  maxTokens ?? "default"
6460
6478
  ];
6479
+ if (baseURL) {
6480
+ parts.push(baseURL);
6481
+ }
6461
6482
  if (toolsConfig && toolsConfig.length > 0) {
6462
6483
  parts.push(hashToolsConfig(toolsConfig));
6463
6484
  }
@@ -6585,7 +6606,8 @@ var ModelInitializer = class _ModelInitializer {
6585
6606
  config.modelId,
6586
6607
  config.temperature,
6587
6608
  config.maxTokens,
6588
- config.toolsConfig
6609
+ config.toolsConfig,
6610
+ config.baseURL
6589
6611
  );
6590
6612
  }
6591
6613
  // Chat model creators
@@ -6594,7 +6616,8 @@ var ModelInitializer = class _ModelInitializer {
6594
6616
  modelName,
6595
6617
  defaultTemperature,
6596
6618
  defaultMaxTokens,
6597
- apiToken
6619
+ apiToken,
6620
+ baseURL
6598
6621
  }) => {
6599
6622
  const config = buildOpenAIModelConfig(
6600
6623
  modelName,
@@ -6602,18 +6625,21 @@ var ModelInitializer = class _ModelInitializer {
6602
6625
  defaultMaxTokens,
6603
6626
  apiToken || this.resolveApiKey("openai" /* OPENAI */) || ""
6604
6627
  );
6628
+ config.configuration = { baseURL: `${resolveRouterURL(baseURL)}/v1` };
6605
6629
  return new openai.ChatOpenAI(config);
6606
6630
  },
6607
6631
  ["anthropic" /* ANTHROPIC */]: ({
6608
6632
  modelName,
6609
6633
  defaultTemperature,
6610
6634
  defaultMaxTokens,
6611
- apiToken
6635
+ apiToken,
6636
+ baseURL
6612
6637
  }) => new anthropic.ChatAnthropic({
6613
6638
  modelName,
6614
6639
  temperature: defaultTemperature,
6615
6640
  maxTokens: defaultMaxTokens,
6616
- anthropicApiKey: apiToken || this.resolveApiKey("anthropic" /* ANTHROPIC */)
6641
+ anthropicApiKey: apiToken || this.resolveApiKey("anthropic" /* ANTHROPIC */),
6642
+ anthropicApiUrl: resolveRouterURL(baseURL)
6617
6643
  }),
6618
6644
  ["cohere" /* COHERE */]: ({
6619
6645
  modelName,
@@ -6629,12 +6655,17 @@ var ModelInitializer = class _ModelInitializer {
6629
6655
  modelName,
6630
6656
  defaultTemperature,
6631
6657
  defaultMaxTokens,
6632
- apiToken
6658
+ apiToken,
6659
+ baseURL
6633
6660
  }) => new mistralai.ChatMistralAI({
6634
6661
  model: modelName,
6635
6662
  temperature: defaultTemperature,
6636
6663
  maxTokens: defaultMaxTokens,
6637
- apiKey: apiToken || this.resolveApiKey("mistral" /* MISTRAL */)
6664
+ apiKey: apiToken || this.resolveApiKey("mistral" /* MISTRAL */),
6665
+ // Route through the same gateway as OpenAI/Anthropic.
6666
+ // Without serverURL, ChatMistralAI ignores FLUTCH_ROUTER_URL and calls
6667
+ // api.mistral.ai directly — inconsistent with other providers.
6668
+ serverURL: `${resolveRouterURL(baseURL)}/v1`
6638
6669
  }),
6639
6670
  ["voyageai" /* VOYAGEAI */]: () => {
6640
6671
  throw new Error("VoyageAI chat models not implemented");
@@ -6695,7 +6726,8 @@ var ModelInitializer = class _ModelInitializer {
6695
6726
  ),
6696
6727
  defaultMaxTokens: Number(
6697
6728
  config.maxTokens ?? modelConfig.defaultMaxTokens
6698
- )
6729
+ ),
6730
+ baseURL: config.baseURL ?? modelConfig.baseURL
6699
6731
  };
6700
6732
  this.logger.debug(`Creating new chat model instance: ${cacheKey}`);
6701
6733
  let model;