@squadbase/vite-server 0.1.17-dev.24af54e → 0.1.17-dev.423ee34

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 (77) hide show
  1. package/dist/cli/index.js +4873 -1073
  2. package/dist/connectors/airtable-oauth.js +78 -11
  3. package/dist/connectors/airtable.js +74 -11
  4. package/dist/connectors/amplitude.js +38 -11
  5. package/dist/connectors/anthropic.js +4 -2
  6. package/dist/connectors/asana.js +67 -13
  7. package/dist/connectors/attio.js +60 -16
  8. package/dist/connectors/aws-billing.js +38 -11
  9. package/dist/connectors/azure-sql.js +64 -13
  10. package/dist/connectors/backlog-api-key.js +70 -18
  11. package/dist/connectors/clickup.js +80 -13
  12. package/dist/connectors/cosmosdb.js +42 -15
  13. package/dist/connectors/customerio.js +39 -12
  14. package/dist/connectors/dbt.js +716 -28
  15. package/dist/connectors/freshdesk.js +112 -11
  16. package/dist/connectors/freshsales.js +38 -11
  17. package/dist/connectors/freshservice.js +38 -11
  18. package/dist/connectors/gamma.js +47 -20
  19. package/dist/connectors/gemini.js +4 -2
  20. package/dist/connectors/github.js +42 -15
  21. package/dist/connectors/gmail-oauth.js +38 -13
  22. package/dist/connectors/gmail.js +34 -7
  23. package/dist/connectors/google-ads.js +38 -11
  24. package/dist/connectors/google-analytics-oauth.js +182 -28
  25. package/dist/connectors/google-analytics.js +653 -104
  26. package/dist/connectors/google-audit-log.js +34 -7
  27. package/dist/connectors/google-calendar-oauth.js +91 -18
  28. package/dist/connectors/google-calendar.js +91 -14
  29. package/dist/connectors/google-docs.js +38 -13
  30. package/dist/connectors/google-drive.js +60 -13
  31. package/dist/connectors/google-search-console-oauth.js +156 -20
  32. package/dist/connectors/google-sheets.js +36 -9
  33. package/dist/connectors/google-slides.js +38 -13
  34. package/dist/connectors/grafana.js +75 -13
  35. package/dist/connectors/hubspot-oauth.js +69 -12
  36. package/dist/connectors/hubspot.js +55 -12
  37. package/dist/connectors/influxdb.js +38 -11
  38. package/dist/connectors/intercom-oauth.js +100 -15
  39. package/dist/connectors/intercom.js +42 -15
  40. package/dist/connectors/jdbc.js +36 -9
  41. package/dist/connectors/jira-api-key.js +98 -14
  42. package/dist/connectors/kintone-api-token.js +96 -21
  43. package/dist/connectors/kintone.js +84 -14
  44. package/dist/connectors/linear.js +84 -15
  45. package/dist/connectors/linkedin-ads.js +71 -17
  46. package/dist/connectors/mailchimp-oauth.js +36 -9
  47. package/dist/connectors/mailchimp.js +36 -9
  48. package/dist/connectors/meta-ads-oauth.js +63 -17
  49. package/dist/connectors/meta-ads.js +65 -17
  50. package/dist/connectors/mixpanel.js +38 -11
  51. package/dist/connectors/monday.js +39 -12
  52. package/dist/connectors/mongodb.js +38 -11
  53. package/dist/connectors/notion-oauth.js +88 -14
  54. package/dist/connectors/notion.js +90 -14
  55. package/dist/connectors/openai.js +4 -2
  56. package/dist/connectors/oracle.js +78 -20
  57. package/dist/connectors/outlook-oauth.js +48 -23
  58. package/dist/connectors/powerbi-oauth.js +321 -49
  59. package/dist/connectors/salesforce.js +72 -12
  60. package/dist/connectors/semrush.js +374 -52
  61. package/dist/connectors/sentry.js +66 -13
  62. package/dist/connectors/shopify-oauth.js +71 -13
  63. package/dist/connectors/shopify.js +38 -11
  64. package/dist/connectors/sqlserver.js +64 -13
  65. package/dist/connectors/stripe-api-key.js +96 -18
  66. package/dist/connectors/stripe-oauth.js +98 -22
  67. package/dist/connectors/supabase.js +55 -11
  68. package/dist/connectors/tableau.js +262 -92
  69. package/dist/connectors/tiktok-ads.js +67 -19
  70. package/dist/connectors/wix-store.js +38 -11
  71. package/dist/connectors/zendesk-oauth.js +83 -15
  72. package/dist/connectors/zendesk.js +42 -15
  73. package/dist/index.d.ts +1 -0
  74. package/dist/index.js +4902 -1077
  75. package/dist/main.js +4891 -1071
  76. package/dist/vite-plugin.js +4871 -1071
  77. package/package.json +1 -1
@@ -190,7 +190,7 @@ var ConnectorPlugin = class _ConnectorPlugin {
190
190
  /**
191
191
  * Create tools for connections that belong to this connector.
192
192
  * Filters connections by connectorKey internally.
193
- * Returns tools keyed as `${connectorKey}_${toolName}`.
193
+ * Returns tools keyed as `connector_${connectorKey}_${toolName}`.
194
194
  */
195
195
  createTools(connections, config, opts) {
196
196
  const myConnections = connections.filter(
@@ -200,7 +200,7 @@ var ConnectorPlugin = class _ConnectorPlugin {
200
200
  for (const t of Object.values(this.tools)) {
201
201
  const tool = t.createTool(myConnections, config);
202
202
  const originalToModelOutput = tool.toModelOutput;
203
- result[`${this.connectorKey}_${t.name}`] = {
203
+ result[`connector_${this.connectorKey}_${t.name}`] = {
204
204
  ...tool,
205
205
  toModelOutput: async (options) => {
206
206
  if (!originalToModelOutput) {
@@ -256,19 +256,34 @@ async function runSetupFlow(flow, params, ctx, config) {
256
256
  };
257
257
  let state = flow.initialState();
258
258
  let answerIdx = 0;
259
+ const pendingParameterUpdates = [];
259
260
  for (const step of flow.steps) {
260
261
  const ans = ctx.answers[answerIdx];
261
262
  if (ans && ans.questionSlug === step.slug) {
262
263
  state = step.applyAnswer(state, ans.answer);
264
+ if (step.toParameterUpdates) {
265
+ pendingParameterUpdates.push(...step.toParameterUpdates(state));
266
+ }
263
267
  answerIdx += 1;
264
268
  continue;
265
269
  }
270
+ const resolvedAllowFreeText = step.allowFreeText !== void 0 ? step.allowFreeText : true;
266
271
  if (step.type === "text") {
272
+ if (step.fetchOptions) {
273
+ const options2 = await step.fetchOptions(state, runtime);
274
+ if (options2.length === 0) {
275
+ continue;
276
+ }
277
+ }
267
278
  return {
268
279
  type: "nextQuestion",
269
280
  questionSlug: step.slug,
270
281
  question: step.question[ctx.language],
271
- questionType: "text"
282
+ questionType: "text",
283
+ allowFreeText: resolvedAllowFreeText,
284
+ ...pendingParameterUpdates.length > 0 && {
285
+ parameterUpdates: pendingParameterUpdates
286
+ }
272
287
  };
273
288
  }
274
289
  const options = step.fetchOptions ? await step.fetchOptions(state, runtime) : [];
@@ -280,11 +295,21 @@ async function runSetupFlow(flow, params, ctx, config) {
280
295
  questionSlug: step.slug,
281
296
  question: step.question[ctx.language],
282
297
  questionType: step.type,
283
- options
298
+ options,
299
+ allowFreeText: resolvedAllowFreeText,
300
+ ...pendingParameterUpdates.length > 0 && {
301
+ parameterUpdates: pendingParameterUpdates
302
+ }
284
303
  };
285
304
  }
286
305
  const dataInvestigationResult = await flow.finalize(state, runtime);
287
- return { type: "fulfilled", dataInvestigationResult };
306
+ return {
307
+ type: "fulfilled",
308
+ dataInvestigationResult,
309
+ ...pendingParameterUpdates.length > 0 && {
310
+ parameterUpdates: pendingParameterUpdates
311
+ }
312
+ };
288
313
  }
289
314
  async function resolveSetupSelection(params) {
290
315
  const { selected, allSentinel, fetchAll, limit } = params;
@@ -466,14 +491,14 @@ var powerbiOauthOnboarding = new ConnectorOnboarding({
466
491
  - Write only 1 sentence between tool calls, then immediately call the next tool`
467
492
  },
468
493
  dataOverviewInstructions: {
469
- en: `1. Call powerbi-oauth_request with GET /groups to list accessible workspaces
470
- 2. For a target workspace, call powerbi-oauth_request with GET /groups/{groupId}/datasets to list datasets
471
- 3. Call powerbi-oauth_request with GET /groups/{groupId}/reports to list reports
472
- 4. For each interesting dataset call powerbi-oauth_request with GET /groups/{groupId}/datasets/{datasetId}/tables to inspect tables`,
473
- ja: `1. powerbi-oauth_request \u3067 GET /groups \u3092\u547C\u3073\u51FA\u3057\u3001\u30A2\u30AF\u30BB\u30B9\u53EF\u80FD\u306A\u30EF\u30FC\u30AF\u30B9\u30DA\u30FC\u30B9\u4E00\u89A7\u3092\u53D6\u5F97
474
- 2. \u5BFE\u8C61\u30EF\u30FC\u30AF\u30B9\u30DA\u30FC\u30B9\u306B\u5BFE\u3057\u3066 powerbi-oauth_request \u3067 GET /groups/{groupId}/datasets \u3092\u547C\u3073\u51FA\u3057\u3001\u30C7\u30FC\u30BF\u30BB\u30C3\u30C8\u4E00\u89A7\u3092\u53D6\u5F97
475
- 3. powerbi-oauth_request \u3067 GET /groups/{groupId}/reports \u3092\u547C\u3073\u51FA\u3057\u3001\u30EC\u30DD\u30FC\u30C8\u4E00\u89A7\u3092\u53D6\u5F97
476
- 4. \u8208\u5473\u306E\u3042\u308B\u30C7\u30FC\u30BF\u30BB\u30C3\u30C8\u306B\u3064\u3044\u3066 powerbi-oauth_request \u3067 GET /groups/{groupId}/datasets/{datasetId}/tables \u3092\u547C\u3073\u51FA\u3057\u3001\u30C6\u30FC\u30D6\u30EB\u69CB\u9020\u3092\u78BA\u8A8D`
494
+ en: `1. Call connector_powerbi-oauth_request with GET /groups to list accessible workspaces
495
+ 2. For a target workspace, call connector_powerbi-oauth_request with GET /groups/{groupId}/datasets to list datasets
496
+ 3. Call connector_powerbi-oauth_request with GET /groups/{groupId}/reports to list reports
497
+ 4. For each interesting dataset call connector_powerbi-oauth_request with GET /groups/{groupId}/datasets/{datasetId}/tables to inspect tables`,
498
+ ja: `1. connector_powerbi-oauth_request \u3067 GET /groups \u3092\u547C\u3073\u51FA\u3057\u3001\u30A2\u30AF\u30BB\u30B9\u53EF\u80FD\u306A\u30EF\u30FC\u30AF\u30B9\u30DA\u30FC\u30B9\u4E00\u89A7\u3092\u53D6\u5F97
499
+ 2. \u5BFE\u8C61\u30EF\u30FC\u30AF\u30B9\u30DA\u30FC\u30B9\u306B\u5BFE\u3057\u3066 connector_powerbi-oauth_request \u3067 GET /groups/{groupId}/datasets \u3092\u547C\u3073\u51FA\u3057\u3001\u30C7\u30FC\u30BF\u30BB\u30C3\u30C8\u4E00\u89A7\u3092\u53D6\u5F97
500
+ 3. connector_powerbi-oauth_request \u3067 GET /groups/{groupId}/reports \u3092\u547C\u3073\u51FA\u3057\u3001\u30EC\u30DD\u30FC\u30C8\u4E00\u89A7\u3092\u53D6\u5F97
501
+ 4. \u8208\u5473\u306E\u3042\u308B\u30C7\u30FC\u30BF\u30BB\u30C3\u30C8\u306B\u3064\u3044\u3066 connector_powerbi-oauth_request \u3067 GET /groups/{groupId}/datasets/{datasetId}/tables \u3092\u547C\u3073\u51FA\u3057\u3001\u30C6\u30FC\u30D6\u30EB\u69CB\u9020\u3092\u78BA\u8A8D`
477
502
  }
478
503
  });
479
504
 
@@ -489,6 +514,10 @@ function apiFetch(proxyFetch, path2, init) {
489
514
 
490
515
  // ../connectors/src/connectors/powerbi-oauth/setup-flow.ts
491
516
  var ALL_WORKSPACES = "__ALL_WORKSPACES__";
517
+ var MY_WORKSPACE = "__MY_WORKSPACE__";
518
+ var ALL_DATASETS = "__ALL_DATASETS__";
519
+ var ALL_REPORTS = "__ALL_REPORTS__";
520
+ var ALL_DASHBOARDS = "__ALL_DASHBOARDS__";
492
521
  var POWERBI_SETUP_MAX_WORKSPACES = 10;
493
522
  var RESOURCE_DISPLAY_LIMIT = 25;
494
523
  var RESOURCE_DATASETS = "datasets";
@@ -504,14 +533,12 @@ async function listGroups(proxyFetch) {
504
533
  return data.value ?? [];
505
534
  }
506
535
  async function listResource(proxyFetch, groupId, resource) {
507
- const res = await apiFetch(
508
- proxyFetch,
509
- `/groups/${encodeURIComponent(groupId)}/${resource}`
510
- );
536
+ const path2 = groupId === MY_WORKSPACE ? `/${resource}` : `/groups/${encodeURIComponent(groupId)}/${resource}`;
537
+ const res = await apiFetch(proxyFetch, path2);
511
538
  if (!res.ok) {
512
539
  const body = await res.text().catch(() => res.statusText);
513
540
  throw new Error(
514
- `powerbi: list ${resource} for group ${groupId} failed (${res.status}): ${body}`
541
+ `powerbi: list ${resource} for ${groupId === MY_WORKSPACE ? "My workspace" : `group ${groupId}`} failed (${res.status}): ${body}`
515
542
  );
516
543
  }
517
544
  const data = await res.json();
@@ -520,6 +547,99 @@ async function listResource(proxyFetch, groupId, resource) {
520
547
  function resourceLabel(r) {
521
548
  return r.name ?? r.displayName ?? r.id ?? "(unknown)";
522
549
  }
550
+ var INTERNAL_TABLE_PREFIXES = [
551
+ "DateTableTemplate_",
552
+ "LocalDateTable_"
553
+ ];
554
+ function isInternalColumn(name) {
555
+ return /^RowNumber-[0-9A-Fa-f-]+$/.test(name);
556
+ }
557
+ async function fetchDatasetSchema(proxyFetch, wsId, datasetId) {
558
+ const pathPrefix = wsId === MY_WORKSPACE ? "" : `/groups/${encodeURIComponent(wsId)}`;
559
+ const daxQuery = 'EVALUATE SELECTCOLUMNS(COLUMNSTATISTICS(), "T", [Table Name], "C", [Column Name])';
560
+ const res = await apiFetch(
561
+ proxyFetch,
562
+ `${pathPrefix}/datasets/${encodeURIComponent(datasetId)}/executeQueries`,
563
+ {
564
+ method: "POST",
565
+ headers: { "Content-Type": "application/json" },
566
+ body: JSON.stringify({
567
+ queries: [{ query: daxQuery }],
568
+ serializerSettings: { includeNulls: true }
569
+ })
570
+ }
571
+ );
572
+ if (!res.ok) return /* @__PURE__ */ new Map();
573
+ const data = await res.json();
574
+ const rows = data.results?.[0]?.tables?.[0]?.rows ?? [];
575
+ const schema = /* @__PURE__ */ new Map();
576
+ for (const row of rows) {
577
+ const table = row["[T]"] ?? "";
578
+ const column = row["[C]"] ?? "";
579
+ if (!table || !column) continue;
580
+ if (INTERNAL_TABLE_PREFIXES.some((p) => table.startsWith(p))) continue;
581
+ if (isInternalColumn(column)) continue;
582
+ if (!schema.has(table)) schema.set(table, []);
583
+ schema.get(table).push(column);
584
+ }
585
+ return schema;
586
+ }
587
+ function workspaceName(wsId, groupById, language) {
588
+ if (wsId === MY_WORKSPACE) {
589
+ return language === "ja" ? "\u30DE\u30A4 \u30EF\u30FC\u30AF\u30B9\u30DA\u30FC\u30B9" : "My workspace";
590
+ }
591
+ return groupById.get(wsId)?.name ?? wsId;
592
+ }
593
+ async function resolveWorkspaceIds(selected, proxyFetch) {
594
+ return resolveSetupSelection({
595
+ selected,
596
+ allSentinel: ALL_WORKSPACES,
597
+ fetchAll: async () => {
598
+ const groups = await listGroups(proxyFetch);
599
+ return [MY_WORKSPACE, ...groups.map((g) => g.id).filter(Boolean)];
600
+ },
601
+ limit: POWERBI_SETUP_MAX_WORKSPACES
602
+ });
603
+ }
604
+ function compoundKey(wsId, objectId) {
605
+ return `${wsId}:${objectId}`;
606
+ }
607
+ function parseCompoundKey(key) {
608
+ const idx = key.indexOf(":");
609
+ if (idx < 0) return { wsId: "", objectId: key };
610
+ return { wsId: key.slice(0, idx), objectId: key.slice(idx + 1) };
611
+ }
612
+ async function fetchObjectOptions(state, resource, allSentinel, allLabelJa, allLabelEn, rt) {
613
+ if (!state.workspaces?.length || !state.resources?.includes(resource))
614
+ return [];
615
+ const wsIds = await resolveWorkspaceIds(
616
+ state.workspaces,
617
+ rt.config.proxyFetch
618
+ );
619
+ const allGroups = await listGroups(rt.config.proxyFetch);
620
+ const groupById = new Map(allGroups.map((g) => [g.id, g]));
621
+ const multiWorkspace = wsIds.length > 1;
622
+ const options = [];
623
+ for (const wsId of wsIds) {
624
+ const wsLabel = workspaceName(wsId, groupById, rt.language);
625
+ const items = await listResource(rt.config.proxyFetch, wsId, resource);
626
+ for (const item of items) {
627
+ if (!item.id) continue;
628
+ options.push({
629
+ value: compoundKey(wsId, item.id),
630
+ label: multiWorkspace ? `${wsLabel} / ${resourceLabel(item)}` : resourceLabel(item)
631
+ });
632
+ }
633
+ }
634
+ if (options.length === 0) return [];
635
+ return [
636
+ {
637
+ value: allSentinel,
638
+ label: rt.language === "ja" ? allLabelJa : allLabelEn
639
+ },
640
+ ...options
641
+ ];
642
+ }
523
643
  var powerbiOauthSetupFlow = {
524
644
  initialState: () => ({}),
525
645
  steps: [
@@ -538,6 +658,10 @@ var powerbiOauthSetupFlow = {
538
658
  value: ALL_WORKSPACES,
539
659
  label: rt.language === "ja" ? "\u3059\u3079\u3066\u306E\u30EF\u30FC\u30AF\u30B9\u30DA\u30FC\u30B9" : "All workspaces"
540
660
  },
661
+ {
662
+ value: MY_WORKSPACE,
663
+ label: rt.language === "ja" ? "\u30DE\u30A4 \u30EF\u30FC\u30AF\u30B9\u30DA\u30FC\u30B9" : "My workspace"
664
+ },
541
665
  ...options
542
666
  ];
543
667
  },
@@ -552,16 +676,82 @@ var powerbiOauthSetupFlow = {
552
676
  },
553
677
  async fetchOptions(state, rt) {
554
678
  if (!state.workspaces?.length) return [];
555
- const datasetsLabel = rt.language === "ja" ? "\u30C7\u30FC\u30BF\u30BB\u30C3\u30C8" : "Datasets";
556
- const reportsLabel = rt.language === "ja" ? "\u30EC\u30DD\u30FC\u30C8" : "Reports";
557
- const dashboardsLabel = rt.language === "ja" ? "\u30C0\u30C3\u30B7\u30E5\u30DC\u30FC\u30C9" : "Dashboards";
558
679
  return [
559
- { value: RESOURCE_DATASETS, label: datasetsLabel },
560
- { value: RESOURCE_REPORTS, label: reportsLabel },
561
- { value: RESOURCE_DASHBOARDS, label: dashboardsLabel }
680
+ {
681
+ value: RESOURCE_DATASETS,
682
+ label: rt.language === "ja" ? "\u30C7\u30FC\u30BF\u30BB\u30C3\u30C8" : "Datasets"
683
+ },
684
+ {
685
+ value: RESOURCE_REPORTS,
686
+ label: rt.language === "ja" ? "\u30EC\u30DD\u30FC\u30C8" : "Reports"
687
+ },
688
+ {
689
+ value: RESOURCE_DASHBOARDS,
690
+ label: rt.language === "ja" ? "\u30C0\u30C3\u30B7\u30E5\u30DC\u30FC\u30C9" : "Dashboards"
691
+ }
562
692
  ];
563
693
  },
564
694
  applyAnswer: (state, answer) => ({ ...state, resources: answer })
695
+ },
696
+ {
697
+ slug: "datasets",
698
+ type: "multiSelect",
699
+ question: {
700
+ ja: "\u4F7F\u7528\u3059\u308B\u30C7\u30FC\u30BF\u30BB\u30C3\u30C8\u3092\u9078\u3093\u3067\u304F\u3060\u3055\u3044\uFF08\u8907\u6570\u9078\u629E\u53EF\uFF09",
701
+ en: "Select the datasets you want to use (multi-select allowed)"
702
+ },
703
+ async fetchOptions(state, rt) {
704
+ return fetchObjectOptions(
705
+ state,
706
+ RESOURCE_DATASETS,
707
+ ALL_DATASETS,
708
+ "\u3059\u3079\u3066\u306E\u30C7\u30FC\u30BF\u30BB\u30C3\u30C8",
709
+ "All datasets",
710
+ rt
711
+ );
712
+ },
713
+ applyAnswer: (state, answer) => ({ ...state, selectedDatasets: answer })
714
+ },
715
+ {
716
+ slug: "reports",
717
+ type: "multiSelect",
718
+ question: {
719
+ ja: "\u4F7F\u7528\u3059\u308B\u30EC\u30DD\u30FC\u30C8\u3092\u9078\u3093\u3067\u304F\u3060\u3055\u3044\uFF08\u8907\u6570\u9078\u629E\u53EF\uFF09",
720
+ en: "Select the reports you want to use (multi-select allowed)"
721
+ },
722
+ async fetchOptions(state, rt) {
723
+ return fetchObjectOptions(
724
+ state,
725
+ RESOURCE_REPORTS,
726
+ ALL_REPORTS,
727
+ "\u3059\u3079\u3066\u306E\u30EC\u30DD\u30FC\u30C8",
728
+ "All reports",
729
+ rt
730
+ );
731
+ },
732
+ applyAnswer: (state, answer) => ({ ...state, selectedReports: answer })
733
+ },
734
+ {
735
+ slug: "dashboards",
736
+ type: "multiSelect",
737
+ question: {
738
+ ja: "\u4F7F\u7528\u3059\u308B\u30C0\u30C3\u30B7\u30E5\u30DC\u30FC\u30C9\u3092\u9078\u3093\u3067\u304F\u3060\u3055\u3044\uFF08\u8907\u6570\u9078\u629E\u53EF\uFF09",
739
+ en: "Select the dashboards you want to use (multi-select allowed)"
740
+ },
741
+ async fetchOptions(state, rt) {
742
+ return fetchObjectOptions(
743
+ state,
744
+ RESOURCE_DASHBOARDS,
745
+ ALL_DASHBOARDS,
746
+ "\u3059\u3079\u3066\u306E\u30C0\u30C3\u30B7\u30E5\u30DC\u30FC\u30C9",
747
+ "All dashboards",
748
+ rt
749
+ );
750
+ },
751
+ applyAnswer: (state, answer) => ({
752
+ ...state,
753
+ selectedDashboards: answer
754
+ })
565
755
  }
566
756
  ],
567
757
  async finalize(state, rt) {
@@ -570,37 +760,119 @@ var powerbiOauthSetupFlow = {
570
760
  }
571
761
  const allGroups = await listGroups(rt.config.proxyFetch);
572
762
  const groupById = new Map(allGroups.map((g) => [g.id, g]));
573
- const targetIds = await resolveSetupSelection({
574
- selected: state.workspaces,
575
- allSentinel: ALL_WORKSPACES,
576
- fetchAll: async () => allGroups.map((g) => g.id).filter((id) => id),
577
- limit: POWERBI_SETUP_MAX_WORKSPACES
578
- });
763
+ const wsIds = await resolveWorkspaceIds(
764
+ state.workspaces,
765
+ rt.config.proxyFetch
766
+ );
579
767
  const selectedResources = new Set(state.resources);
768
+ async function resolveObjects(selected, allSentinel, resource) {
769
+ const byWorkspace = /* @__PURE__ */ new Map();
770
+ if (!selected || !selectedResources.has(resource)) return byWorkspace;
771
+ if (selected.includes(allSentinel)) {
772
+ for (const wsId of wsIds) {
773
+ const items = await listResource(
774
+ rt.config.proxyFetch,
775
+ wsId,
776
+ resource
777
+ );
778
+ const ids = items.map((i) => i.id).filter((id) => !!id);
779
+ if (ids.length > 0) byWorkspace.set(wsId, new Set(ids));
780
+ }
781
+ } else {
782
+ for (const key of selected) {
783
+ if (key === allSentinel) continue;
784
+ const { wsId, objectId } = parseCompoundKey(key);
785
+ if (!byWorkspace.has(wsId)) byWorkspace.set(wsId, /* @__PURE__ */ new Set());
786
+ byWorkspace.get(wsId).add(objectId);
787
+ }
788
+ }
789
+ return byWorkspace;
790
+ }
791
+ const datasetsByWs = await resolveObjects(
792
+ state.selectedDatasets,
793
+ ALL_DATASETS,
794
+ RESOURCE_DATASETS
795
+ );
796
+ const reportsByWs = await resolveObjects(
797
+ state.selectedReports,
798
+ ALL_REPORTS,
799
+ RESOURCE_REPORTS
800
+ );
801
+ const dashboardsByWs = await resolveObjects(
802
+ state.selectedDashboards,
803
+ ALL_DASHBOARDS,
804
+ RESOURCE_DASHBOARDS
805
+ );
806
+ const allWsIds = /* @__PURE__ */ new Set([
807
+ ...datasetsByWs.keys(),
808
+ ...reportsByWs.keys(),
809
+ ...dashboardsByWs.keys()
810
+ ]);
580
811
  const sections = ["## Power BI", ""];
581
- if (!targetIds.length) {
582
- sections.push("_No workspaces selected._", "");
812
+ if (allWsIds.size === 0) {
813
+ sections.push("_No resources selected._", "");
583
814
  return sections.join("\n");
584
815
  }
585
- for (const id of targetIds) {
586
- const group = groupById.get(id);
587
- const name = group?.name ?? id;
588
- sections.push(`### Workspace: ${name}`, "", `- id: \`${id}\``);
589
- for (const resource of [
590
- RESOURCE_DATASETS,
591
- RESOURCE_REPORTS,
592
- RESOURCE_DASHBOARDS
816
+ for (const wsId of wsIds) {
817
+ if (!allWsIds.has(wsId)) continue;
818
+ const name = workspaceName(wsId, groupById, rt.language);
819
+ sections.push(`### Workspace: ${name}`, "");
820
+ if (wsId !== MY_WORKSPACE) {
821
+ sections.push(`- id: \`${wsId}\``);
822
+ }
823
+ const datasetIds = datasetsByWs.get(wsId);
824
+ if (datasetIds?.size) {
825
+ const items = await listResource(
826
+ rt.config.proxyFetch,
827
+ wsId,
828
+ RESOURCE_DATASETS
829
+ );
830
+ const filtered = items.filter(
831
+ (item) => item.id && datasetIds.has(item.id)
832
+ );
833
+ for (const item of filtered.slice(0, RESOURCE_DISPLAY_LIMIT)) {
834
+ sections.push(`#### Dataset: ${resourceLabel(item)}`, "");
835
+ const schema = await fetchDatasetSchema(
836
+ rt.config.proxyFetch,
837
+ wsId,
838
+ item.id
839
+ );
840
+ if (schema.size > 0) {
841
+ for (const [table, columns] of schema) {
842
+ sections.push(`##### Table: ${table}`, "");
843
+ sections.push("| Column |");
844
+ sections.push("|--------|");
845
+ for (const col of columns) {
846
+ sections.push(`| ${col} |`);
847
+ }
848
+ sections.push("");
849
+ }
850
+ } else {
851
+ sections.push("_Schema not available._", "");
852
+ }
853
+ }
854
+ }
855
+ for (const [resource, selectedByWs, heading] of [
856
+ [RESOURCE_REPORTS, reportsByWs, "Reports"],
857
+ [RESOURCE_DASHBOARDS, dashboardsByWs, "Dashboards"]
593
858
  ]) {
594
- if (!selectedResources.has(resource)) continue;
595
- const items = await listResource(rt.config.proxyFetch, id, resource);
596
- const heading = resource === RESOURCE_DATASETS ? "Datasets" : resource === RESOURCE_REPORTS ? "Reports" : "Dashboards";
597
- sections.push(`- ${heading} (${items.length}):`);
598
- for (const item of items.slice(0, RESOURCE_DISPLAY_LIMIT)) {
859
+ const selectedIds = selectedByWs.get(wsId);
860
+ if (!selectedIds?.size) continue;
861
+ const items = await listResource(
862
+ rt.config.proxyFetch,
863
+ wsId,
864
+ resource
865
+ );
866
+ const filtered = items.filter(
867
+ (item) => item.id && selectedIds.has(item.id)
868
+ );
869
+ sections.push(`- ${heading} (${filtered.length}):`);
870
+ for (const item of filtered.slice(0, RESOURCE_DISPLAY_LIMIT)) {
599
871
  sections.push(` - ${resourceLabel(item)}`);
600
872
  }
601
- if (items.length > RESOURCE_DISPLAY_LIMIT) {
873
+ if (filtered.length > RESOURCE_DISPLAY_LIMIT) {
602
874
  sections.push(
603
- ` - \u2026and ${items.length - RESOURCE_DISPLAY_LIMIT} more`
875
+ ` - \u2026and ${filtered.length - RESOURCE_DISPLAY_LIMIT} more`
604
876
  );
605
877
  }
606
878
  }
@@ -634,7 +906,7 @@ var powerbiOauthConnector = new ConnectorPlugin({
634
906
  systemPrompt: {
635
907
  en: `### Tools
636
908
 
637
- - \`powerbi-oauth_request\`: The only way to call the Power BI REST API v1.0. Use it to list workspaces (\`/groups\`), datasets, reports, and to run DAX via the \`executeQueries\` endpoint. Authentication is configured automatically via OAuth (Microsoft Entra ID).
909
+ - \`connector_powerbi-oauth_request\`: The only way to call the Power BI REST API v1.0. Use it to list workspaces (\`/groups\`), datasets, reports, and to run DAX via the \`executeQueries\` endpoint. Authentication is configured automatically via OAuth (Microsoft Entra ID).
638
910
 
639
911
  ### Business Logic
640
912
 
@@ -690,7 +962,7 @@ export default async function handler(c: Context) {
690
962
  - Each \`executeQueries\` call accepts one query in the \`queries\` array (per current Power BI API limits)`,
691
963
  ja: `### \u30C4\u30FC\u30EB
692
964
 
693
- - \`powerbi-oauth_request\`: Power BI REST API v1.0 \u3092\u547C\u3073\u51FA\u3059\u552F\u4E00\u306E\u624B\u6BB5\u3067\u3059\u3002\u30EF\u30FC\u30AF\u30B9\u30DA\u30FC\u30B9 (\`/groups\`)\u3001\u30C7\u30FC\u30BF\u30BB\u30C3\u30C8\u3001\u30EC\u30DD\u30FC\u30C8\u306E\u4E00\u89A7\u53D6\u5F97\u3084\u3001\`executeQueries\` \u30A8\u30F3\u30C9\u30DD\u30A4\u30F3\u30C8\u306B\u3088\u308B DAX \u306E\u5B9F\u884C\u306B\u4F7F\u7528\u3057\u307E\u3059\u3002OAuth (Microsoft Entra ID) \u7D4C\u7531\u3067\u8A8D\u8A3C\u306F\u81EA\u52D5\u8A2D\u5B9A\u3055\u308C\u307E\u3059\u3002
965
+ - \`connector_powerbi-oauth_request\`: Power BI REST API v1.0 \u3092\u547C\u3073\u51FA\u3059\u552F\u4E00\u306E\u624B\u6BB5\u3067\u3059\u3002\u30EF\u30FC\u30AF\u30B9\u30DA\u30FC\u30B9 (\`/groups\`)\u3001\u30C7\u30FC\u30BF\u30BB\u30C3\u30C8\u3001\u30EC\u30DD\u30FC\u30C8\u306E\u4E00\u89A7\u53D6\u5F97\u3084\u3001\`executeQueries\` \u30A8\u30F3\u30C9\u30DD\u30A4\u30F3\u30C8\u306B\u3088\u308B DAX \u306E\u5B9F\u884C\u306B\u4F7F\u7528\u3057\u307E\u3059\u3002OAuth (Microsoft Entra ID) \u7D4C\u7531\u3067\u8A8D\u8A3C\u306F\u81EA\u52D5\u8A2D\u5B9A\u3055\u308C\u307E\u3059\u3002
694
966
 
695
967
  ### Business Logic
696
968
 
@@ -16,6 +16,7 @@ var init_parameter_definition = __esm({
16
16
  type;
17
17
  secret;
18
18
  required;
19
+ isDeprecated;
19
20
  constructor(config) {
20
21
  this.slug = config.slug;
21
22
  this.name = config.name;
@@ -24,6 +25,7 @@ var init_parameter_definition = __esm({
24
25
  this.type = config.type;
25
26
  this.secret = config.secret;
26
27
  this.required = config.required;
28
+ this.isDeprecated = config.isDeprecated ?? false;
27
29
  }
28
30
  /**
29
31
  * Get the parameter value from a ConnectorConnectionObject.
@@ -331,7 +333,7 @@ var ConnectorPlugin = class _ConnectorPlugin {
331
333
  /**
332
334
  * Create tools for connections that belong to this connector.
333
335
  * Filters connections by connectorKey internally.
334
- * Returns tools keyed as `${connectorKey}_${toolName}`.
336
+ * Returns tools keyed as `connector_${connectorKey}_${toolName}`.
335
337
  */
336
338
  createTools(connections, config, opts) {
337
339
  const myConnections = connections.filter(
@@ -341,7 +343,7 @@ var ConnectorPlugin = class _ConnectorPlugin {
341
343
  for (const t of Object.values(this.tools)) {
342
344
  const tool = t.createTool(myConnections, config);
343
345
  const originalToModelOutput = tool.toModelOutput;
344
- result[`${this.connectorKey}_${t.name}`] = {
346
+ result[`connector_${this.connectorKey}_${t.name}`] = {
345
347
  ...tool,
346
348
  toModelOutput: async (options) => {
347
349
  if (!originalToModelOutput) {
@@ -397,19 +399,34 @@ async function runSetupFlow(flow, params, ctx, config) {
397
399
  };
398
400
  let state = flow.initialState();
399
401
  let answerIdx = 0;
402
+ const pendingParameterUpdates = [];
400
403
  for (const step of flow.steps) {
401
404
  const ans = ctx.answers[answerIdx];
402
405
  if (ans && ans.questionSlug === step.slug) {
403
406
  state = step.applyAnswer(state, ans.answer);
407
+ if (step.toParameterUpdates) {
408
+ pendingParameterUpdates.push(...step.toParameterUpdates(state));
409
+ }
404
410
  answerIdx += 1;
405
411
  continue;
406
412
  }
413
+ const resolvedAllowFreeText = step.allowFreeText !== void 0 ? step.allowFreeText : true;
407
414
  if (step.type === "text") {
415
+ if (step.fetchOptions) {
416
+ const options2 = await step.fetchOptions(state, runtime);
417
+ if (options2.length === 0) {
418
+ continue;
419
+ }
420
+ }
408
421
  return {
409
422
  type: "nextQuestion",
410
423
  questionSlug: step.slug,
411
424
  question: step.question[ctx.language],
412
- questionType: "text"
425
+ questionType: "text",
426
+ allowFreeText: resolvedAllowFreeText,
427
+ ...pendingParameterUpdates.length > 0 && {
428
+ parameterUpdates: pendingParameterUpdates
429
+ }
413
430
  };
414
431
  }
415
432
  const options = step.fetchOptions ? await step.fetchOptions(state, runtime) : [];
@@ -421,11 +438,21 @@ async function runSetupFlow(flow, params, ctx, config) {
421
438
  questionSlug: step.slug,
422
439
  question: step.question[ctx.language],
423
440
  questionType: step.type,
424
- options
441
+ options,
442
+ allowFreeText: resolvedAllowFreeText,
443
+ ...pendingParameterUpdates.length > 0 && {
444
+ parameterUpdates: pendingParameterUpdates
445
+ }
425
446
  };
426
447
  }
427
448
  const dataInvestigationResult = await flow.finalize(state, runtime);
428
- return { type: "fulfilled", dataInvestigationResult };
449
+ return {
450
+ type: "fulfilled",
451
+ dataInvestigationResult,
452
+ ...pendingParameterUpdates.length > 0 && {
453
+ parameterUpdates: pendingParameterUpdates
454
+ }
455
+ };
429
456
  }
430
457
  async function resolveSetupSelection(params) {
431
458
  const { selected, allSentinel, fetchAll, limit } = params;
@@ -446,11 +473,11 @@ var AUTH_TYPES = {
446
473
  // ../connectors/src/connectors/salesforce/setup.ts
447
474
  var salesforceOnboarding = new ConnectorOnboarding({
448
475
  dataOverviewInstructions: {
449
- en: `1. Call salesforce_request with GET /services/data/v60.0/sobjects/ to list available sObjects (standard + custom)
450
- 2. Call salesforce_request with GET /services/data/v60.0/sobjects/Account/describe to inspect Account fields; repeat for Contact, Opportunity, Lead as needed
476
+ en: `1. Call connector_salesforce_request with GET /services/data/v60.0/sobjects/ to list available sObjects (standard + custom)
477
+ 2. Call connector_salesforce_request with GET /services/data/v60.0/sobjects/Account/describe to inspect Account fields; repeat for Contact, Opportunity, Lead as needed
451
478
  3. Run a sample SOQL query: GET /services/data/v60.0/query?q=SELECT+Id,Name,Industry+FROM+Account+LIMIT+5 to verify access and explore data`,
452
- ja: `1. salesforce_request \u3067 GET /services/data/v60.0/sobjects/ \u3092\u547C\u3073\u51FA\u3057\u3001\u5229\u7528\u53EF\u80FD\u306A sObject\uFF08\u6A19\u6E96 + \u30AB\u30B9\u30BF\u30E0\uFF09\u3092\u4E00\u89A7\u53D6\u5F97
453
- 2. salesforce_request \u3067 GET /services/data/v60.0/sobjects/Account/describe \u3092\u547C\u3073\u51FA\u3057 Account \u306E\u30D5\u30A3\u30FC\u30EB\u30C9\u3092\u78BA\u8A8D\u3002Contact / Opportunity / Lead \u306A\u3069\u5FC5\u8981\u306A sObject \u306B\u5BFE\u3057\u3066\u540C\u69D8\u306B\u5B9F\u884C
479
+ ja: `1. connector_salesforce_request \u3067 GET /services/data/v60.0/sobjects/ \u3092\u547C\u3073\u51FA\u3057\u3001\u5229\u7528\u53EF\u80FD\u306A sObject\uFF08\u6A19\u6E96 + \u30AB\u30B9\u30BF\u30E0\uFF09\u3092\u4E00\u89A7\u53D6\u5F97
480
+ 2. connector_salesforce_request \u3067 GET /services/data/v60.0/sobjects/Account/describe \u3092\u547C\u3073\u51FA\u3057 Account \u306E\u30D5\u30A3\u30FC\u30EB\u30C9\u3092\u78BA\u8A8D\u3002Contact / Opportunity / Lead \u306A\u3069\u5FC5\u8981\u306A sObject \u306B\u5BFE\u3057\u3066\u540C\u69D8\u306B\u5B9F\u884C
454
481
  3. \u30B5\u30F3\u30D7\u30EB SOQL \u3092\u5B9F\u884C: GET /services/data/v60.0/query?q=SELECT+Id,Name,Industry+FROM+Account+LIMIT+5 \u3067\u30A2\u30AF\u30BB\u30B9\u53EF\u5426\u3068\u30C7\u30FC\u30BF\u69CB\u9020\u3092\u78BA\u8A8D`
455
482
  }
456
483
  });
@@ -540,6 +567,20 @@ async function describeSObject(params, name) {
540
567
  const data = await res.json();
541
568
  return data.fields ?? [];
542
569
  }
570
+ async function fetchSObjectCount(params, objectName) {
571
+ try {
572
+ const query = encodeURIComponent(`SELECT COUNT() FROM ${objectName}`);
573
+ const res = await apiFetch(
574
+ params,
575
+ `/services/data/${SALESFORCE_API_VERSION}/query?q=${query}`
576
+ );
577
+ if (!res.ok) return null;
578
+ const data = await res.json();
579
+ return typeof data.totalSize === "number" ? data.totalSize : null;
580
+ } catch {
581
+ return null;
582
+ }
583
+ }
543
584
  var salesforceSetupFlow = {
544
585
  initialState: () => ({}),
545
586
  steps: [
@@ -574,8 +615,27 @@ var salesforceSetupFlow = {
574
615
  limit: SALESFORCE_SETUP_MAX_OBJECTS
575
616
  });
576
617
  const sections = ["## Salesforce", ""];
618
+ const countByObject = /* @__PURE__ */ new Map();
619
+ for (const objectName of targetObjects) {
620
+ countByObject.set(
621
+ objectName,
622
+ await fetchSObjectCount(rt.params, objectName)
623
+ );
624
+ }
625
+ sections.push("### Record counts", "");
626
+ sections.push("| sObject | Record count |");
627
+ sections.push("|---------|-------------|");
628
+ for (const objectName of targetObjects) {
629
+ const count = countByObject.get(objectName);
630
+ sections.push(
631
+ `| ${objectName} | ${count == null ? "-" : count.toLocaleString()} |`
632
+ );
633
+ }
634
+ sections.push("");
577
635
  for (const objectName of targetObjects) {
578
- sections.push(`### sObject: ${objectName}`, "");
636
+ const count = countByObject.get(objectName);
637
+ const countLabel = count == null ? "" : ` (${count.toLocaleString()} records)`;
638
+ sections.push(`### sObject: ${objectName}${countLabel}`, "");
579
639
  const fields = await describeSObject(rt.params, objectName);
580
640
  const limited = fields.slice(0, SALESFORCE_SETUP_MAX_FIELDS);
581
641
  sections.push("| Field | Type | Label | Custom |");
@@ -745,7 +805,7 @@ var salesforceConnector = new ConnectorPlugin({
745
805
  systemPrompt: {
746
806
  en: `### Tools
747
807
 
748
- - \`salesforce_request\`: The only way to call the Salesforce REST API. Use it to run SOQL queries, describe sObjects, and read/create/update/delete standard (Account, Contact, Opportunity, Lead, Case) and custom objects. Authentication (OAuth 2.0 Client Credentials Flow against the External Client App / Connected App) is configured automatically \u2014 an access token is resolved on each request against the configured org instance URL. Prefer SOQL via \`GET /services/data/v60.0/query?q=...\` over paginating \`/sobjects/{Type}\` endpoints for filtered or joined reads.
808
+ - \`connector_salesforce_request\`: The only way to call the Salesforce REST API. Use it to run SOQL queries, describe sObjects, and read/create/update/delete standard (Account, Contact, Opportunity, Lead, Case) and custom objects. Authentication (OAuth 2.0 Client Credentials Flow against the External Client App / Connected App) is configured automatically \u2014 an access token is resolved on each request against the configured org instance URL. Prefer SOQL via \`GET /services/data/v60.0/query?q=...\` over paginating \`/sobjects/{Type}\` endpoints for filtered or joined reads.
749
809
 
750
810
  ### Business Logic
751
811
 
@@ -816,7 +876,7 @@ export default async function handler(c: Context) {
816
876
  - Parent-to-child subquery: \`SELECT Id, Name, (SELECT Id, Email FROM Contacts) FROM Account\``,
817
877
  ja: `### \u30C4\u30FC\u30EB
818
878
 
819
- - \`salesforce_request\`: Salesforce REST API \u3092\u547C\u3073\u51FA\u3059\u552F\u4E00\u306E\u624B\u6BB5\u3067\u3059\u3002SOQL \u30AF\u30A8\u30EA\u306E\u5B9F\u884C\u3001sObject \u306E describe\u3001\u6A19\u6E96\u30AA\u30D6\u30B8\u30A7\u30AF\u30C8\uFF08Account, Contact, Opportunity, Lead, Case\uFF09\u3084\u30AB\u30B9\u30BF\u30E0\u30AA\u30D6\u30B8\u30A7\u30AF\u30C8\u306E\u8AAD\u307F\u66F8\u304D\u306B\u4F7F\u7528\u3057\u307E\u3059\u3002\u8A8D\u8A3C\uFF08External Client App / Connected App + OAuth 2.0 Client Credentials Flow\uFF09\u306F\u81EA\u52D5\u3067\u884C\u308F\u308C\u3001\u8A2D\u5B9A\u3055\u308C\u305F\u7D44\u7E54\u306E instance URL \u306B\u5BFE\u3057\u3066\u30EA\u30AF\u30A8\u30B9\u30C8\u3054\u3068\u306B\u30A2\u30AF\u30BB\u30B9\u30C8\u30FC\u30AF\u30F3\u304C\u89E3\u6C7A\u3055\u308C\u307E\u3059\u3002\u30D5\u30A3\u30EB\u30BF\u3084\u7D50\u5408\u306E\u3042\u308B\u8AAD\u307F\u53D6\u308A\u3067\u306F \`/sobjects/{Type}\` \u3092\u30DA\u30FC\u30B8\u30F3\u30B0\u3059\u308B\u306E\u3067\u306F\u306A\u304F\u3001\`GET /services/data/v60.0/query?q=...\` \u306E SOQL \u3092\u512A\u5148\u3057\u3066\u304F\u3060\u3055\u3044\u3002
879
+ - \`connector_salesforce_request\`: Salesforce REST API \u3092\u547C\u3073\u51FA\u3059\u552F\u4E00\u306E\u624B\u6BB5\u3067\u3059\u3002SOQL \u30AF\u30A8\u30EA\u306E\u5B9F\u884C\u3001sObject \u306E describe\u3001\u6A19\u6E96\u30AA\u30D6\u30B8\u30A7\u30AF\u30C8\uFF08Account, Contact, Opportunity, Lead, Case\uFF09\u3084\u30AB\u30B9\u30BF\u30E0\u30AA\u30D6\u30B8\u30A7\u30AF\u30C8\u306E\u8AAD\u307F\u66F8\u304D\u306B\u4F7F\u7528\u3057\u307E\u3059\u3002\u8A8D\u8A3C\uFF08External Client App / Connected App + OAuth 2.0 Client Credentials Flow\uFF09\u306F\u81EA\u52D5\u3067\u884C\u308F\u308C\u3001\u8A2D\u5B9A\u3055\u308C\u305F\u7D44\u7E54\u306E instance URL \u306B\u5BFE\u3057\u3066\u30EA\u30AF\u30A8\u30B9\u30C8\u3054\u3068\u306B\u30A2\u30AF\u30BB\u30B9\u30C8\u30FC\u30AF\u30F3\u304C\u89E3\u6C7A\u3055\u308C\u307E\u3059\u3002\u30D5\u30A3\u30EB\u30BF\u3084\u7D50\u5408\u306E\u3042\u308B\u8AAD\u307F\u53D6\u308A\u3067\u306F \`/sobjects/{Type}\` \u3092\u30DA\u30FC\u30B8\u30F3\u30B0\u3059\u308B\u306E\u3067\u306F\u306A\u304F\u3001\`GET /services/data/v60.0/query?q=...\` \u306E SOQL \u3092\u512A\u5148\u3057\u3066\u304F\u3060\u3055\u3044\u3002
820
880
 
821
881
  ### Business Logic
822
882