@squadbase/vite-server 0.1.17-dev.a107052 → 0.1.17-dev.d4fff69

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 (80) hide show
  1. package/dist/cli/index.js +4284 -820
  2. package/dist/connectors/airtable-oauth.js +48 -8
  3. package/dist/connectors/airtable.js +44 -8
  4. package/dist/connectors/amplitude.js +8 -8
  5. package/dist/connectors/anthropic.js +2 -2
  6. package/dist/connectors/asana.js +37 -10
  7. package/dist/connectors/attio.js +30 -13
  8. package/dist/connectors/aws-billing.js +8 -8
  9. package/dist/connectors/azure-sql.js +47 -10
  10. package/dist/connectors/backlog-api-key.js +40 -15
  11. package/dist/connectors/clickup.js +50 -10
  12. package/dist/connectors/cosmosdb.js +12 -12
  13. package/dist/connectors/customerio.js +8 -8
  14. package/dist/connectors/dbt.js +686 -25
  15. package/dist/connectors/freshdesk.js +82 -8
  16. package/dist/connectors/freshsales.js +8 -8
  17. package/dist/connectors/freshservice.js +8 -8
  18. package/dist/connectors/gamma.js +15 -15
  19. package/dist/connectors/gemini.js +2 -2
  20. package/dist/connectors/github.js +12 -12
  21. package/dist/connectors/gmail-oauth.js +10 -10
  22. package/dist/connectors/gmail.js +4 -4
  23. package/dist/connectors/google-ads.js +8 -8
  24. package/dist/connectors/google-analytics-oauth.js +152 -25
  25. package/dist/connectors/google-analytics.js +475 -95
  26. package/dist/connectors/google-audit-log.js +4 -4
  27. package/dist/connectors/google-calendar-oauth.js +61 -15
  28. package/dist/connectors/google-calendar.js +61 -11
  29. package/dist/connectors/google-docs.js +10 -10
  30. package/dist/connectors/google-drive.js +32 -10
  31. package/dist/connectors/google-search-console-oauth.js +126 -17
  32. package/dist/connectors/google-sheets.js +6 -6
  33. package/dist/connectors/google-slides.js +10 -10
  34. package/dist/connectors/grafana.js +45 -10
  35. package/dist/connectors/hackernews.d.ts +5 -0
  36. package/dist/connectors/hackernews.js +890 -0
  37. package/dist/connectors/hubspot-oauth.js +41 -9
  38. package/dist/connectors/hubspot.js +25 -9
  39. package/dist/connectors/influxdb.js +8 -8
  40. package/dist/connectors/intercom-oauth.js +72 -12
  41. package/dist/connectors/intercom.js +12 -12
  42. package/dist/connectors/jdbc.js +37 -10
  43. package/dist/connectors/jira-api-key.js +68 -11
  44. package/dist/connectors/kintone-api-token.js +66 -18
  45. package/dist/connectors/kintone.js +54 -11
  46. package/dist/connectors/linear.js +54 -12
  47. package/dist/connectors/linkedin-ads.js +41 -14
  48. package/dist/connectors/mailchimp-oauth.js +6 -6
  49. package/dist/connectors/mailchimp.js +6 -6
  50. package/dist/connectors/meta-ads-oauth.js +33 -14
  51. package/dist/connectors/meta-ads.js +35 -14
  52. package/dist/connectors/mixpanel.js +8 -8
  53. package/dist/connectors/monday.js +9 -9
  54. package/dist/connectors/mongodb.js +8 -8
  55. package/dist/connectors/notion-oauth.js +60 -11
  56. package/dist/connectors/notion.js +60 -11
  57. package/dist/connectors/openai.js +2 -2
  58. package/dist/connectors/oracle.js +39 -11
  59. package/dist/connectors/outlook-oauth.js +21 -21
  60. package/dist/connectors/powerbi-oauth.js +13 -13
  61. package/dist/connectors/salesforce.js +42 -9
  62. package/dist/connectors/semrush.js +6 -6
  63. package/dist/connectors/sentry.js +36 -10
  64. package/dist/connectors/shopify-oauth.js +43 -10
  65. package/dist/connectors/shopify.js +8 -8
  66. package/dist/connectors/sqlserver.js +47 -10
  67. package/dist/connectors/stripe-api-key.js +66 -15
  68. package/dist/connectors/stripe-oauth.js +70 -19
  69. package/dist/connectors/supabase.js +31 -6
  70. package/dist/connectors/tableau.js +15 -15
  71. package/dist/connectors/tiktok-ads.js +37 -16
  72. package/dist/connectors/wix-store.js +8 -8
  73. package/dist/connectors/x.d.ts +5 -0
  74. package/dist/connectors/x.js +927 -0
  75. package/dist/connectors/zendesk-oauth.js +55 -12
  76. package/dist/connectors/zendesk.js +12 -12
  77. package/dist/index.js +4302 -818
  78. package/dist/main.js +4302 -818
  79. package/dist/vite-plugin.js +4282 -818
  80. package/package.json +9 -1
@@ -224,7 +224,7 @@ var ConnectorPlugin = class _ConnectorPlugin {
224
224
  /**
225
225
  * Create tools for connections that belong to this connector.
226
226
  * Filters connections by connectorKey internally.
227
- * Returns tools keyed as `${connectorKey}_${toolName}`.
227
+ * Returns tools keyed as `connector_${connectorKey}_${toolName}`.
228
228
  */
229
229
  createTools(connections, config, opts) {
230
230
  const myConnections = connections.filter(
@@ -234,7 +234,7 @@ var ConnectorPlugin = class _ConnectorPlugin {
234
234
  for (const t of Object.values(this.tools)) {
235
235
  const tool = t.createTool(myConnections, config);
236
236
  const originalToModelOutput = tool.toModelOutput;
237
- result[`${this.connectorKey}_${t.name}`] = {
237
+ result[`connector_${this.connectorKey}_${t.name}`] = {
238
238
  ...tool,
239
239
  toModelOutput: async (options) => {
240
240
  if (!originalToModelOutput) {
@@ -364,12 +364,12 @@ var AUTH_TYPES = {
364
364
  // ../connectors/src/connectors/jira/setup.ts
365
365
  var jiraOnboarding = new ConnectorOnboarding({
366
366
  dataOverviewInstructions: {
367
- en: `1. Call jira-api-key_request with GET project to list all accessible projects
368
- 2. For key projects, call jira-api-key_request with POST search to search issues using JQL (e.g., body: { "jql": "project = PROJ order by created DESC", "maxResults": 5, "fields": ["summary", "status", "assignee", "priority", "created"] })
369
- 3. Call jira-api-key_request with GET issue/{issueKey} to inspect a sample issue's full details`,
370
- ja: `1. jira-api-key_request \u3067 GET project \u3092\u547C\u3073\u51FA\u3057\u3001\u30A2\u30AF\u30BB\u30B9\u53EF\u80FD\u306A\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u4E00\u89A7\u3092\u53D6\u5F97
371
- 2. \u4E3B\u8981\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u306B\u3064\u3044\u3066 jira-api-key_request \u3067 POST search \u3092\u4F7F\u7528\u3057\u3066JQL\u3067\u30A4\u30B7\u30E5\u30FC\u3092\u691C\u7D22\uFF08\u4F8B: body: { "jql": "project = PROJ order by created DESC", "maxResults": 5, "fields": ["summary", "status", "assignee", "priority", "created"] }\uFF09
372
- 3. jira-api-key_request \u3067 GET issue/{issueKey} \u3092\u547C\u3073\u51FA\u3057\u3001\u30B5\u30F3\u30D7\u30EB\u30A4\u30B7\u30E5\u30FC\u306E\u8A73\u7D30\u3092\u78BA\u8A8D`
367
+ en: `1. Call connector_jira-api-key_request with GET project to list all accessible projects
368
+ 2. For key projects, call connector_jira-api-key_request with POST search to search issues using JQL (e.g., body: { "jql": "project = PROJ order by created DESC", "maxResults": 5, "fields": ["summary", "status", "assignee", "priority", "created"] })
369
+ 3. Call connector_jira-api-key_request with GET issue/{issueKey} to inspect a sample issue's full details`,
370
+ ja: `1. connector_jira-api-key_request \u3067 GET project \u3092\u547C\u3073\u51FA\u3057\u3001\u30A2\u30AF\u30BB\u30B9\u53EF\u80FD\u306A\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u4E00\u89A7\u3092\u53D6\u5F97
371
+ 2. \u4E3B\u8981\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u306B\u3064\u3044\u3066 connector_jira-api-key_request \u3067 POST search \u3092\u4F7F\u7528\u3057\u3066JQL\u3067\u30A4\u30B7\u30E5\u30FC\u3092\u691C\u7D22\uFF08\u4F8B: body: { "jql": "project = PROJ order by created DESC", "maxResults": 5, "fields": ["summary", "status", "assignee", "priority", "created"] }\uFF09
372
+ 3. connector_jira-api-key_request \u3067 GET issue/{issueKey} \u3092\u547C\u3073\u51FA\u3057\u3001\u30B5\u30F3\u30D7\u30EB\u30A4\u30B7\u30E5\u30FC\u306E\u8A73\u7D30\u3092\u78BA\u8A8D`
373
373
  }
374
374
  });
375
375
 
@@ -431,6 +431,43 @@ async function getProject(params, keyOrId) {
431
431
  }
432
432
  return await res.json();
433
433
  }
434
+ async function fetchProjectIssueCount(params, projectKey) {
435
+ try {
436
+ const jql = encodeURIComponent(`project = ${projectKey}`);
437
+ const res = await apiFetch(
438
+ params,
439
+ `search?jql=${jql}&maxResults=0`
440
+ );
441
+ if (!res.ok) return null;
442
+ const data = await res.json();
443
+ return typeof data.total === "number" ? data.total : null;
444
+ } catch {
445
+ return null;
446
+ }
447
+ }
448
+ async function fetchStatusBreakdown(params, projectKey) {
449
+ try {
450
+ const jql = encodeURIComponent(
451
+ `project = ${projectKey} ORDER BY created DESC`
452
+ );
453
+ const res = await apiFetch(
454
+ params,
455
+ `search?jql=${jql}&maxResults=100&fields=status`
456
+ );
457
+ if (!res.ok) return null;
458
+ const data = await res.json();
459
+ const issues = data.issues ?? [];
460
+ if (issues.length === 0) return null;
461
+ const breakdown = {};
462
+ for (const issue of issues) {
463
+ const category = issue.fields?.status?.statusCategory?.name ?? "Unknown";
464
+ breakdown[category] = (breakdown[category] ?? 0) + 1;
465
+ }
466
+ return breakdown;
467
+ } catch {
468
+ return null;
469
+ }
470
+ }
434
471
  var jiraSetupFlow = {
435
472
  initialState: () => ({}),
436
473
  steps: [
@@ -471,17 +508,37 @@ var jiraSetupFlow = {
471
508
  const sections = ["## Jira", ""];
472
509
  for (const key of targetKeys) {
473
510
  const project = await getProject(rt.params, key);
474
- sections.push(`### Project: ${project.name} (${project.key})`, "");
511
+ const issueCount = await fetchProjectIssueCount(rt.params, key);
512
+ const countLabel = issueCount == null ? "" : ` - ${issueCount.toLocaleString()} issues`;
513
+ sections.push(
514
+ `### Project: ${project.name} (${project.key})${countLabel}`,
515
+ ""
516
+ );
475
517
  const lead = project.lead?.displayName ?? "-";
476
518
  const typeKey = project.projectTypeKey ?? "-";
477
519
  sections.push(`- Lead: ${lead}`);
478
520
  sections.push(`- Project type: ${typeKey}`);
521
+ if (issueCount != null) {
522
+ sections.push(`- Total issues: ${issueCount.toLocaleString()}`);
523
+ }
479
524
  const issueTypes = project.issueTypes ?? [];
480
525
  sections.push(`- Issue types (${issueTypes.length}):`);
481
526
  for (const it of issueTypes) {
482
527
  const suffix = it.subtask ? " (sub-task)" : "";
483
528
  sections.push(` - ${it.name}${suffix}`);
484
529
  }
530
+ const breakdown = await fetchStatusBreakdown(rt.params, key);
531
+ if (breakdown && Object.keys(breakdown).length > 0) {
532
+ sections.push("");
533
+ sections.push("**Status category breakdown (from recent 100 issues):**", "");
534
+ sections.push("| Status category | Count |");
535
+ sections.push("|-----------------|-------|");
536
+ for (const [category, count] of Object.entries(breakdown).sort(
537
+ (a, b) => b[1] - a[1]
538
+ )) {
539
+ sections.push(`| ${category} | ${count} |`);
540
+ }
541
+ }
485
542
  sections.push("");
486
543
  }
487
544
  return sections.join("\n");
@@ -580,7 +637,7 @@ var jiraConnector = new ConnectorPlugin({
580
637
  systemPrompt: {
581
638
  en: `### Tools
582
639
 
583
- - \`jira-api-key_request\`: The only way to call the Jira Cloud REST API (v3). Use it to list projects, search issues with JQL, get issue details, create/update issues, manage transitions, and add comments. Authentication (Basic Auth with email + API token) and instance URL are configured automatically.
640
+ - \`connector_jira-api-key_request\`: The only way to call the Jira Cloud REST API (v3). Use it to list projects, search issues with JQL, get issue details, create/update issues, manage transitions, and add comments. Authentication (Basic Auth with email + API token) and instance URL are configured automatically.
584
641
 
585
642
  ### Business Logic
586
643
 
@@ -650,7 +707,7 @@ await jira.request("/rest/api/3/issue", {
650
707
  - Text search: summary ~ "keyword"`,
651
708
  ja: `### \u30C4\u30FC\u30EB
652
709
 
653
- - \`jira-api-key_request\`: Jira Cloud REST API\uFF08v3\uFF09\u3092\u547C\u3073\u51FA\u3059\u552F\u4E00\u306E\u624B\u6BB5\u3067\u3059\u3002\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u4E00\u89A7\u306E\u53D6\u5F97\u3001JQL\u306B\u3088\u308B\u30A4\u30B7\u30E5\u30FC\u691C\u7D22\u3001\u30A4\u30B7\u30E5\u30FC\u8A73\u7D30\u306E\u53D6\u5F97\u3001\u30A4\u30B7\u30E5\u30FC\u306E\u4F5C\u6210\u30FB\u66F4\u65B0\u3001\u30C8\u30E9\u30F3\u30B8\u30B7\u30E7\u30F3\u7BA1\u7406\u3001\u30B3\u30E1\u30F3\u30C8\u8FFD\u52A0\u306B\u4F7F\u7528\u3057\u307E\u3059\u3002\u8A8D\u8A3C\uFF08Basic Auth: \u30E1\u30FC\u30EB + API\u30C8\u30FC\u30AF\u30F3\uFF09\u3068\u30A4\u30F3\u30B9\u30BF\u30F3\u30B9URL\u306F\u81EA\u52D5\u7684\u306B\u8A2D\u5B9A\u3055\u308C\u307E\u3059\u3002
710
+ - \`connector_jira-api-key_request\`: Jira Cloud REST API\uFF08v3\uFF09\u3092\u547C\u3073\u51FA\u3059\u552F\u4E00\u306E\u624B\u6BB5\u3067\u3059\u3002\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u4E00\u89A7\u306E\u53D6\u5F97\u3001JQL\u306B\u3088\u308B\u30A4\u30B7\u30E5\u30FC\u691C\u7D22\u3001\u30A4\u30B7\u30E5\u30FC\u8A73\u7D30\u306E\u53D6\u5F97\u3001\u30A4\u30B7\u30E5\u30FC\u306E\u4F5C\u6210\u30FB\u66F4\u65B0\u3001\u30C8\u30E9\u30F3\u30B8\u30B7\u30E7\u30F3\u7BA1\u7406\u3001\u30B3\u30E1\u30F3\u30C8\u8FFD\u52A0\u306B\u4F7F\u7528\u3057\u307E\u3059\u3002\u8A8D\u8A3C\uFF08Basic Auth: \u30E1\u30FC\u30EB + API\u30C8\u30FC\u30AF\u30F3\uFF09\u3068\u30A4\u30F3\u30B9\u30BF\u30F3\u30B9URL\u306F\u81EA\u52D5\u7684\u306B\u8A2D\u5B9A\u3055\u308C\u307E\u3059\u3002
654
711
 
655
712
  ### Business Logic
656
713
 
@@ -253,7 +253,7 @@ var ConnectorPlugin = class _ConnectorPlugin {
253
253
  /**
254
254
  * Create tools for connections that belong to this connector.
255
255
  * Filters connections by connectorKey internally.
256
- * Returns tools keyed as `${connectorKey}_${toolName}`.
256
+ * Returns tools keyed as `connector_${connectorKey}_${toolName}`.
257
257
  */
258
258
  createTools(connections, config, opts) {
259
259
  const myConnections = connections.filter(
@@ -263,7 +263,7 @@ var ConnectorPlugin = class _ConnectorPlugin {
263
263
  for (const t of Object.values(this.tools)) {
264
264
  const tool = t.createTool(myConnections, config);
265
265
  const originalToModelOutput = tool.toModelOutput;
266
- result[`${this.connectorKey}_${t.name}`] = {
266
+ result[`connector_${this.connectorKey}_${t.name}`] = {
267
267
  ...tool,
268
268
  toModelOutput: async (options) => {
269
269
  if (!originalToModelOutput) {
@@ -390,14 +390,14 @@ var kintoneApiTokenOnboarding = new ConnectorOnboarding({
390
390
  dataOverviewInstructions: {
391
391
  en: `Each connection is scoped to a single kintone app (configured via the "app-id" parameter). The request tool auto-injects the configured app id, so you do NOT need to specify "app=" in paths or "app" in bodies. apps.json is NOT available with API Token auth.
392
392
 
393
- 1. Call kintone-api-key_request with GET app.json to fetch the scoped app's metadata (name, description, creator)
394
- 2. Call kintone-api-key_request with GET app/form/fields.json to get field definitions
395
- 3. Call kintone-api-key_request with GET records.json with query=limit 5 to sample records`,
393
+ 1. Call connector_kintone-api-key_request with GET app.json to fetch the scoped app's metadata (name, description, creator)
394
+ 2. Call connector_kintone-api-key_request with GET app/form/fields.json to get field definitions
395
+ 3. Call connector_kintone-api-key_request with GET records.json with query=limit 5 to sample records`,
396
396
  ja: `\u5404\u63A5\u7D9A\u306F1\u3064\u306Ekintone\u30A2\u30D7\u30EA\u306B\u30B9\u30B3\u30FC\u30D7\u3055\u308C\u3066\u3044\u307E\u3059\uFF08"app-id" \u30D1\u30E9\u30E1\u30FC\u30BF\u3067\u8A2D\u5B9A\uFF09\u3002request \u30C4\u30FC\u30EB\u306F\u8A2D\u5B9A\u3055\u308C\u305F\u30A2\u30D7\u30EAID\u3092\u81EA\u52D5\u6CE8\u5165\u3059\u308B\u305F\u3081\u3001\u30D1\u30B9\u306B "app=" \u3084 body \u306B "app" \u3092\u6307\u5B9A\u3059\u308B\u5FC5\u8981\u306F\u3042\u308A\u307E\u305B\u3093\u3002API Token \u8A8D\u8A3C\u3067\u306F apps.json \u306F\u5229\u7528\u3067\u304D\u307E\u305B\u3093\u3002
397
397
 
398
- 1. kintone-api-key_request \u3067 GET app.json \u3092\u547C\u3073\u51FA\u3057\u3001\u30B9\u30B3\u30FC\u30D7\u5BFE\u8C61\u30A2\u30D7\u30EA\u306E\u30E1\u30BF\u60C5\u5831\uFF08\u30A2\u30D7\u30EA\u540D\u3001\u8AAC\u660E\u3001\u4F5C\u6210\u8005\uFF09\u3092\u53D6\u5F97
399
- 2. kintone-api-key_request \u3067 GET app/form/fields.json \u3092\u547C\u3073\u51FA\u3057\u3001\u30D5\u30A3\u30FC\u30EB\u30C9\u5B9A\u7FA9\u3092\u53D6\u5F97
400
- 3. kintone-api-key_request \u3067 GET records.json \u3092 query=limit 5 \u3067\u547C\u3073\u51FA\u3057\u3001\u30EC\u30B3\u30FC\u30C9\u3092\u30B5\u30F3\u30D7\u30EA\u30F3\u30B0`
398
+ 1. connector_kintone-api-key_request \u3067 GET app.json \u3092\u547C\u3073\u51FA\u3057\u3001\u30B9\u30B3\u30FC\u30D7\u5BFE\u8C61\u30A2\u30D7\u30EA\u306E\u30E1\u30BF\u60C5\u5831\uFF08\u30A2\u30D7\u30EA\u540D\u3001\u8AAC\u660E\u3001\u4F5C\u6210\u8005\uFF09\u3092\u53D6\u5F97
399
+ 2. connector_kintone-api-key_request \u3067 GET app/form/fields.json \u3092\u547C\u3073\u51FA\u3057\u3001\u30D5\u30A3\u30FC\u30EB\u30C9\u5B9A\u7FA9\u3092\u53D6\u5F97
400
+ 3. connector_kintone-api-key_request \u3067 GET records.json \u3092 query=limit 5 \u3067\u547C\u3073\u51FA\u3057\u3001\u30EC\u30B3\u30FC\u30C9\u3092\u30B5\u30F3\u30D7\u30EA\u30F3\u30B0`
401
401
  }
402
402
  });
403
403
 
@@ -421,6 +421,7 @@ async function apiFetch(params, path2, init) {
421
421
  }
422
422
 
423
423
  // ../connectors/src/connectors/kintone-api-token/setup-flow.ts
424
+ var SAMPLE_RECORD_LIMIT = 5;
424
425
  async function getAppMetadata(params, appId) {
425
426
  const res = await apiFetch(
426
427
  params,
@@ -447,15 +448,28 @@ async function getFormFields(params, appId) {
447
448
  }
448
449
  return await res.json();
449
450
  }
451
+ async function getSampleRecords(params, appId) {
452
+ const res = await apiFetch(
453
+ params,
454
+ `records.json?app=${encodeURIComponent(appId)}&query=${encodeURIComponent(`limit ${SAMPLE_RECORD_LIMIT}`)}&totalCount=true`
455
+ );
456
+ if (!res.ok) return { records: [], totalCount: null };
457
+ return await res.json();
458
+ }
459
+ function formatRecordValue(val) {
460
+ if (val == null) return "";
461
+ if (typeof val === "string") return val.length > 50 ? `${val.slice(0, 50)}\u2026` : val;
462
+ if (Array.isArray(val)) return `[${val.length} items]`;
463
+ if (typeof val === "object") return JSON.stringify(val).slice(0, 50);
464
+ return String(val);
465
+ }
450
466
  var kintoneApiTokenSetupFlow = {
451
467
  initialState: () => ({}),
452
468
  steps: [],
453
469
  async finalize(_state, rt) {
454
- const appId = rt.params[parameters.appId.slug];
470
+ const appId = rt.params["app-id"];
455
471
  if (!appId) {
456
- throw new Error(
457
- "kintone-api-token setup: missing app-id parameter on finalize"
458
- );
472
+ return "## kintone\n\n_App ID \u304C\u6307\u5B9A\u3055\u308C\u3066\u3044\u307E\u305B\u3093\u3002_\n";
459
473
  }
460
474
  const sections = ["## kintone", ""];
461
475
  const app = await getAppMetadata(rt.params, appId);
@@ -465,15 +479,39 @@ var kintoneApiTokenSetupFlow = {
465
479
  sections.push(app.description, "");
466
480
  }
467
481
  const fields = await getFormFields(rt.params, appId);
482
+ const fieldEntries = Object.entries(fields.properties ?? {});
483
+ sections.push("#### Fields", "");
468
484
  sections.push("| Field code | Label | Type | Required |");
469
485
  sections.push("|------------|-------|------|----------|");
470
- for (const [code, def] of Object.entries(fields.properties ?? {})) {
486
+ for (const [code, def] of fieldEntries) {
471
487
  const escapedLabel = (def.label ?? "").replace(/\|/g, "\\|");
472
488
  sections.push(
473
489
  `| ${code} | ${escapedLabel || "-"} | ${def.type} | ${def.required ? "yes" : "no"} |`
474
490
  );
475
491
  }
476
492
  sections.push("");
493
+ const sampleData = await getSampleRecords(rt.params, appId);
494
+ const totalCount = sampleData.totalCount ? Number(sampleData.totalCount) : null;
495
+ if (totalCount != null) {
496
+ sections.push(`#### Record count: ${totalCount.toLocaleString()}`, "");
497
+ }
498
+ const records = sampleData.records ?? [];
499
+ if (records.length > 0) {
500
+ const sampleFields = fieldEntries.slice(0, 8).map(([code]) => code);
501
+ if (sampleFields.length > 0) {
502
+ sections.push(`#### Sample records (${records.length})`, "");
503
+ sections.push(`| ${sampleFields.join(" | ")} |`);
504
+ sections.push(`| ${sampleFields.map(() => "---").join(" | ")} |`);
505
+ for (const record of records) {
506
+ const cells = sampleFields.map((code) => {
507
+ const cell = record[code];
508
+ return formatRecordValue(cell?.value).replace(/\|/g, "\\|");
509
+ });
510
+ sections.push(`| ${cells.join(" | ")} |`);
511
+ }
512
+ sections.push("");
513
+ }
514
+ }
477
515
  return sections.join("\n");
478
516
  }
479
517
  };
@@ -596,7 +634,7 @@ var kintoneApiTokenConnector = new ConnectorPlugin({
596
634
  systemPrompt: {
597
635
  en: `### Tools
598
636
 
599
- - \`kintone-api-key_request\`: The only way to call the kintone REST API. Use it to fetch app metadata/field definitions and read/write records. Authentication (API Token), base URL, and the connection's app id are configured automatically. Each connection is scoped to exactly one app (kintone API tokens are per-app).
637
+ - \`connector_kintone-api-key_request\`: The only way to call the kintone REST API. Use it to fetch app metadata/field definitions and read/write records. Authentication (API Token), base URL, and the connection's app id are configured automatically. Each connection is scoped to exactly one app (kintone API tokens are per-app).
600
638
 
601
639
  ### App scoping (important)
602
640
 
@@ -669,7 +707,7 @@ export default async function handler(c: Context) {
669
707
  - String: \`like "partial match"\``,
670
708
  ja: `### \u30C4\u30FC\u30EB
671
709
 
672
- - \`kintone-api-key_request\`: kintone REST API\u3092\u547C\u3073\u51FA\u3059\u552F\u4E00\u306E\u624B\u6BB5\u3067\u3059\u3002\u30A2\u30D7\u30EA\u306E\u30E1\u30BF\u60C5\u5831\u30FB\u30D5\u30A3\u30FC\u30EB\u30C9\u5B9A\u7FA9\u306E\u53D6\u5F97\u3001\u30EC\u30B3\u30FC\u30C9\u306E\u8AAD\u307F\u66F8\u304D\u306B\u4F7F\u7528\u3057\u307E\u3059\u3002\u8A8D\u8A3C\uFF08API\u30C8\u30FC\u30AF\u30F3\uFF09\u3001\u30D9\u30FC\u30B9URL\u3001\u304A\u3088\u3073\u63A5\u7D9A\u306E\u30A2\u30D7\u30EAID\u306F\u81EA\u52D5\u7684\u306B\u8A2D\u5B9A\u3055\u308C\u307E\u3059\u3002\u5404\u63A5\u7D9A\u306F\u3061\u3087\u3046\u30691\u3064\u306E\u30A2\u30D7\u30EA\u306B\u30B9\u30B3\u30FC\u30D7\u3055\u308C\u3066\u3044\u307E\u3059\uFF08kintone API\u30C8\u30FC\u30AF\u30F3\u306F\u30A2\u30D7\u30EA\u5358\u4F4D\u306E\u305F\u3081\uFF09\u3002
710
+ - \`connector_kintone-api-key_request\`: kintone REST API\u3092\u547C\u3073\u51FA\u3059\u552F\u4E00\u306E\u624B\u6BB5\u3067\u3059\u3002\u30A2\u30D7\u30EA\u306E\u30E1\u30BF\u60C5\u5831\u30FB\u30D5\u30A3\u30FC\u30EB\u30C9\u5B9A\u7FA9\u306E\u53D6\u5F97\u3001\u30EC\u30B3\u30FC\u30C9\u306E\u8AAD\u307F\u66F8\u304D\u306B\u4F7F\u7528\u3057\u307E\u3059\u3002\u8A8D\u8A3C\uFF08API\u30C8\u30FC\u30AF\u30F3\uFF09\u3001\u30D9\u30FC\u30B9URL\u3001\u304A\u3088\u3073\u63A5\u7D9A\u306E\u30A2\u30D7\u30EAID\u306F\u81EA\u52D5\u7684\u306B\u8A2D\u5B9A\u3055\u308C\u307E\u3059\u3002\u5404\u63A5\u7D9A\u306F\u3061\u3087\u3046\u30691\u3064\u306E\u30A2\u30D7\u30EA\u306B\u30B9\u30B3\u30FC\u30D7\u3055\u308C\u3066\u3044\u307E\u3059\uFF08kintone API\u30C8\u30FC\u30AF\u30F3\u306F\u30A2\u30D7\u30EA\u5358\u4F4D\u306E\u305F\u3081\uFF09\u3002
673
711
 
674
712
  ### \u30A2\u30D7\u30EA\u30B9\u30B3\u30FC\u30D7\uFF08\u91CD\u8981\uFF09
675
713
 
@@ -747,14 +785,15 @@ export default async function handler(c: Context) {
747
785
  const baseUrl = params[parameters.baseUrl.slug];
748
786
  const apiToken = params[parameters.apiToken.slug];
749
787
  const appId = params[parameters.appId.slug];
750
- if (!baseUrl || !apiToken || !appId) {
788
+ if (!baseUrl || !apiToken) {
751
789
  return {
752
790
  success: false,
753
- error: `Missing required parameters: ${parameters.baseUrl.slug}, ${parameters.apiToken.slug}, and ${parameters.appId.slug}`
791
+ error: `Missing required parameters: ${parameters.baseUrl.slug}, ${parameters.apiToken.slug}`
754
792
  };
755
793
  }
756
794
  try {
757
- const url = `${baseUrl.replace(/\/+$/, "")}/k/v1/app.json?id=${encodeURIComponent(appId)}`;
795
+ const path2 = appId ? `app.json?id=${encodeURIComponent(appId)}` : `app/form/fields.json?app=0`;
796
+ const url = `${baseUrl.replace(/\/+$/, "")}/k/v1/${path2}`;
758
797
  const res = await fetch(url, {
759
798
  method: "GET",
760
799
  headers: {
@@ -762,6 +801,15 @@ export default async function handler(c: Context) {
762
801
  Accept: "application/json"
763
802
  }
764
803
  });
804
+ if (!appId) {
805
+ if (res.status === 401 || res.status === 403) {
806
+ return {
807
+ success: false,
808
+ error: "kintone API failed: invalid API token"
809
+ };
810
+ }
811
+ return { success: true };
812
+ }
765
813
  if (!res.ok) {
766
814
  const data = await res.json().catch(() => null);
767
815
  const message = data?.message ?? `HTTP ${res.status} ${res.statusText}`;
@@ -262,7 +262,7 @@ var ConnectorPlugin = class _ConnectorPlugin {
262
262
  /**
263
263
  * Create tools for connections that belong to this connector.
264
264
  * Filters connections by connectorKey internally.
265
- * Returns tools keyed as `${connectorKey}_${toolName}`.
265
+ * Returns tools keyed as `connector_${connectorKey}_${toolName}`.
266
266
  */
267
267
  createTools(connections, config, opts) {
268
268
  const myConnections = connections.filter(
@@ -272,7 +272,7 @@ var ConnectorPlugin = class _ConnectorPlugin {
272
272
  for (const t of Object.values(this.tools)) {
273
273
  const tool = t.createTool(myConnections, config);
274
274
  const originalToModelOutput = tool.toModelOutput;
275
- result[`${this.connectorKey}_${t.name}`] = {
275
+ result[`connector_${this.connectorKey}_${t.name}`] = {
276
276
  ...tool,
277
277
  toModelOutput: async (options) => {
278
278
  if (!originalToModelOutput) {
@@ -402,12 +402,12 @@ var AUTH_TYPES = {
402
402
  // ../connectors/src/connectors/kintone/setup.ts
403
403
  var kintoneOnboarding = new ConnectorOnboarding({
404
404
  dataOverviewInstructions: {
405
- en: `1. Call kintone_request with GET apps.json to list available apps
406
- 2. For key apps, call kintone_request with GET app/form/fields.json?app={appId} to get field definitions
407
- 3. Call kintone_request with GET records.json?app={appId}&query=limit 5 to sample records`,
408
- ja: `1. kintone_request \u3067 GET apps.json \u3092\u547C\u3073\u51FA\u3057\u3001\u5229\u7528\u53EF\u80FD\u306A\u30A2\u30D7\u30EA\u4E00\u89A7\u3092\u53D6\u5F97
409
- 2. \u4E3B\u8981\u30A2\u30D7\u30EA\u306B\u3064\u3044\u3066 kintone_request \u3067 GET app/form/fields.json?app={appId} \u3092\u547C\u3073\u51FA\u3057\u3001\u30D5\u30A3\u30FC\u30EB\u30C9\u5B9A\u7FA9\u3092\u53D6\u5F97
410
- 3. kintone_request \u3067 GET records.json?app={appId}&query=limit 5 \u3092\u547C\u3073\u51FA\u3057\u3001\u30EC\u30B3\u30FC\u30C9\u3092\u30B5\u30F3\u30D7\u30EA\u30F3\u30B0`
405
+ en: `1. Call connector_kintone_request with GET apps.json to list available apps
406
+ 2. For key apps, call connector_kintone_request with GET app/form/fields.json?app={appId} to get field definitions
407
+ 3. Call connector_kintone_request with GET records.json?app={appId}&query=limit 5 to sample records`,
408
+ ja: `1. connector_kintone_request \u3067 GET apps.json \u3092\u547C\u3073\u51FA\u3057\u3001\u5229\u7528\u53EF\u80FD\u306A\u30A2\u30D7\u30EA\u4E00\u89A7\u3092\u53D6\u5F97
409
+ 2. \u4E3B\u8981\u30A2\u30D7\u30EA\u306B\u3064\u3044\u3066 connector_kintone_request \u3067 GET app/form/fields.json?app={appId} \u3092\u547C\u3073\u51FA\u3057\u3001\u30D5\u30A3\u30FC\u30EB\u30C9\u5B9A\u7FA9\u3092\u53D6\u5F97
410
+ 3. connector_kintone_request \u3067 GET records.json?app={appId}&query=limit 5 \u3092\u547C\u3073\u51FA\u3057\u3001\u30EC\u30B3\u30FC\u30C9\u3092\u30B5\u30F3\u30D7\u30EA\u30F3\u30B0`
411
411
  }
412
412
  });
413
413
 
@@ -435,6 +435,7 @@ async function apiFetch(params, path2, init) {
435
435
  // ../connectors/src/connectors/kintone/setup-flow.ts
436
436
  var ALL_APPS = "__ALL_APPS__";
437
437
  var KINTONE_SETUP_MAX_APPS = 20;
438
+ var SAMPLE_RECORD_LIMIT = 5;
438
439
  async function listApps(params) {
439
440
  const results = [];
440
441
  let offset = 0;
@@ -468,6 +469,25 @@ async function getFormFields(params, appId) {
468
469
  }
469
470
  return await res.json();
470
471
  }
472
+ async function getSampleRecords(params, appId) {
473
+ try {
474
+ const res = await apiFetch(
475
+ params,
476
+ `records.json?app=${encodeURIComponent(appId)}&query=${encodeURIComponent(`limit ${SAMPLE_RECORD_LIMIT}`)}&totalCount=true`
477
+ );
478
+ if (!res.ok) return { records: [], totalCount: null };
479
+ return await res.json();
480
+ } catch {
481
+ return { records: [], totalCount: null };
482
+ }
483
+ }
484
+ function formatRecordValue(val) {
485
+ if (val == null) return "";
486
+ if (typeof val === "string") return val.length > 50 ? `${val.slice(0, 50)}\u2026` : val;
487
+ if (Array.isArray(val)) return `[${val.length} items]`;
488
+ if (typeof val === "object") return JSON.stringify(val).slice(0, 50);
489
+ return String(val);
490
+ }
471
491
  var kintoneSetupFlow = {
472
492
  initialState: () => ({}),
473
493
  steps: [
@@ -513,15 +533,38 @@ var kintoneSetupFlow = {
513
533
  sections.push(app.description, "");
514
534
  }
515
535
  const fields = await getFormFields(rt.params, appId);
536
+ const fieldEntries = Object.entries(fields.properties ?? {});
516
537
  sections.push("| Field code | Label | Type | Required |");
517
538
  sections.push("|------------|-------|------|----------|");
518
- for (const [code, def] of Object.entries(fields.properties ?? {})) {
539
+ for (const [code, def] of fieldEntries) {
519
540
  const escapedLabel = (def.label ?? "").replace(/\|/g, "\\|");
520
541
  sections.push(
521
542
  `| ${code} | ${escapedLabel || "-"} | ${def.type} | ${def.required ? "yes" : "no"} |`
522
543
  );
523
544
  }
524
545
  sections.push("");
546
+ const sampleData = await getSampleRecords(rt.params, appId);
547
+ const totalCount = sampleData.totalCount ? Number(sampleData.totalCount) : null;
548
+ if (totalCount != null) {
549
+ sections.push(`#### Record count: ${totalCount.toLocaleString()}`, "");
550
+ }
551
+ const records = sampleData.records ?? [];
552
+ if (records.length > 0) {
553
+ const sampleFields = fieldEntries.slice(0, 8).map(([code]) => code);
554
+ if (sampleFields.length > 0) {
555
+ sections.push(`#### Sample records (${records.length})`, "");
556
+ sections.push(`| ${sampleFields.join(" | ")} |`);
557
+ sections.push(`| ${sampleFields.map(() => "---").join(" | ")} |`);
558
+ for (const record of records) {
559
+ const cells = sampleFields.map((code) => {
560
+ const cell = record[code];
561
+ return formatRecordValue(cell?.value).replace(/\|/g, "\\|");
562
+ });
563
+ sections.push(`| ${cells.join(" | ")} |`);
564
+ }
565
+ sections.push("");
566
+ }
567
+ }
525
568
  }
526
569
  return sections.join("\n");
527
570
  }
@@ -614,7 +657,7 @@ var kintoneConnector = new ConnectorPlugin({
614
657
  systemPrompt: {
615
658
  en: `### Tools
616
659
 
617
- - \`kintone_request\`: The only way to call the kintone REST API. Use it to list apps, fetch field definitions, and read/write records. The base URL (e.g., \`https://example.cybozu.com\`) is automatically resolved. See the kintone REST API Reference below for endpoints and the kintone query syntax.
660
+ - \`connector_kintone_request\`: The only way to call the kintone REST API. Use it to list apps, fetch field definitions, and read/write records. The base URL (e.g., \`https://example.cybozu.com\`) is automatically resolved. See the kintone REST API Reference below for endpoints and the kintone query syntax.
618
661
 
619
662
  ### Business Logic
620
663
 
@@ -681,7 +724,7 @@ export default async function handler(c: Context) {
681
724
  - String: \`like "partial match"\``,
682
725
  ja: `### \u30C4\u30FC\u30EB
683
726
 
684
- - \`kintone_request\`: kintone REST API\u3092\u547C\u3073\u51FA\u3059\u552F\u4E00\u306E\u624B\u6BB5\u3067\u3059\u3002\u30A2\u30D7\u30EA\u4E00\u89A7\u306E\u53D6\u5F97\u3001\u30D5\u30A3\u30FC\u30EB\u30C9\u5B9A\u7FA9\u306E\u53D6\u5F97\u3001\u30EC\u30B3\u30FC\u30C9\u306E\u8AAD\u307F\u66F8\u304D\u306B\u4F7F\u7528\u3057\u307E\u3059\u3002\u30D9\u30FC\u30B9URL\uFF08\u4F8B: \`https://example.cybozu.com\`\uFF09\u306F\u81EA\u52D5\u7684\u306B\u89E3\u6C7A\u3055\u308C\u307E\u3059\u3002\u30A8\u30F3\u30C9\u30DD\u30A4\u30F3\u30C8\u304A\u3088\u3073kintone\u30AF\u30A8\u30EA\u69CB\u6587\u306F\u4E0B\u90E8\u306E\u300Ckintone REST API \u30EA\u30D5\u30A1\u30EC\u30F3\u30B9\u300D\u3092\u53C2\u7167\u3057\u3066\u304F\u3060\u3055\u3044\u3002
727
+ - \`connector_kintone_request\`: kintone REST API\u3092\u547C\u3073\u51FA\u3059\u552F\u4E00\u306E\u624B\u6BB5\u3067\u3059\u3002\u30A2\u30D7\u30EA\u4E00\u89A7\u306E\u53D6\u5F97\u3001\u30D5\u30A3\u30FC\u30EB\u30C9\u5B9A\u7FA9\u306E\u53D6\u5F97\u3001\u30EC\u30B3\u30FC\u30C9\u306E\u8AAD\u307F\u66F8\u304D\u306B\u4F7F\u7528\u3057\u307E\u3059\u3002\u30D9\u30FC\u30B9URL\uFF08\u4F8B: \`https://example.cybozu.com\`\uFF09\u306F\u81EA\u52D5\u7684\u306B\u89E3\u6C7A\u3055\u308C\u307E\u3059\u3002\u30A8\u30F3\u30C9\u30DD\u30A4\u30F3\u30C8\u304A\u3088\u3073kintone\u30AF\u30A8\u30EA\u69CB\u6587\u306F\u4E0B\u90E8\u306E\u300Ckintone REST API \u30EA\u30D5\u30A1\u30EC\u30F3\u30B9\u300D\u3092\u53C2\u7167\u3057\u3066\u304F\u3060\u3055\u3044\u3002
685
728
 
686
729
  ### Business Logic
687
730
 
@@ -268,7 +268,7 @@ var ConnectorPlugin = class _ConnectorPlugin {
268
268
  /**
269
269
  * Create tools for connections that belong to this connector.
270
270
  * Filters connections by connectorKey internally.
271
- * Returns tools keyed as `${connectorKey}_${toolName}`.
271
+ * Returns tools keyed as `connector_${connectorKey}_${toolName}`.
272
272
  */
273
273
  createTools(connections, config, opts) {
274
274
  const myConnections = connections.filter(
@@ -278,7 +278,7 @@ var ConnectorPlugin = class _ConnectorPlugin {
278
278
  for (const t of Object.values(this.tools)) {
279
279
  const tool = t.createTool(myConnections, config);
280
280
  const originalToModelOutput = tool.toModelOutput;
281
- result[`${this.connectorKey}_${t.name}`] = {
281
+ result[`connector_${this.connectorKey}_${t.name}`] = {
282
282
  ...tool,
283
283
  toModelOutput: async (options) => {
284
284
  if (!originalToModelOutput) {
@@ -408,15 +408,15 @@ var AUTH_TYPES = {
408
408
  // ../connectors/src/connectors/linear/setup.ts
409
409
  var linearOnboarding = new ConnectorOnboarding({
410
410
  dataOverviewInstructions: {
411
- en: `1. Call linear_request with query \`{ teams { nodes { id name } } }\` to list all teams
412
- 2. Call linear_request with query \`{ workflowStates { nodes { id name type } } }\` to list workflow states
413
- 3. Call linear_request with query \`{ issues(first: 5, orderBy: updatedAt) { nodes { id identifier title state { name } assignee { name } priority } } }\` to sample recent issues
414
- 4. Call linear_request with query \`{ projects(first: 5) { nodes { id name state } } }\` to list projects
411
+ en: `1. Call connector_linear_request with query \`{ teams { nodes { id name } } }\` to list all teams
412
+ 2. Call connector_linear_request with query \`{ workflowStates { nodes { id name type } } }\` to list workflow states
413
+ 3. Call connector_linear_request with query \`{ issues(first: 5, orderBy: updatedAt) { nodes { id identifier title state { name } assignee { name } priority } } }\` to sample recent issues
414
+ 4. Call connector_linear_request with query \`{ projects(first: 5) { nodes { id name state } } }\` to list projects
415
415
  5. Explore other resources (cycles, labels, users) as needed`,
416
- ja: `1. linear_request \u3067\u30AF\u30A8\u30EA \`{ teams { nodes { id name } } }\` \u3092\u547C\u3073\u51FA\u3057\u3001\u30C1\u30FC\u30E0\u4E00\u89A7\u3092\u53D6\u5F97
417
- 2. linear_request \u3067\u30AF\u30A8\u30EA \`{ workflowStates { nodes { id name type } } }\` \u3092\u547C\u3073\u51FA\u3057\u3001\u30EF\u30FC\u30AF\u30D5\u30ED\u30FC\u72B6\u614B\u4E00\u89A7\u3092\u53D6\u5F97
418
- 3. linear_request \u3067\u30AF\u30A8\u30EA \`{ issues(first: 5, orderBy: updatedAt) { nodes { id identifier title state { name } assignee { name } priority } } }\` \u3092\u547C\u3073\u51FA\u3057\u3001\u6700\u8FD1\u306EIssue\u3092\u30B5\u30F3\u30D7\u30EA\u30F3\u30B0
419
- 4. linear_request \u3067\u30AF\u30A8\u30EA \`{ projects(first: 5) { nodes { id name state } } }\` \u3092\u547C\u3073\u51FA\u3057\u3001\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u4E00\u89A7\u3092\u53D6\u5F97
416
+ ja: `1. connector_linear_request \u3067\u30AF\u30A8\u30EA \`{ teams { nodes { id name } } }\` \u3092\u547C\u3073\u51FA\u3057\u3001\u30C1\u30FC\u30E0\u4E00\u89A7\u3092\u53D6\u5F97
417
+ 2. connector_linear_request \u3067\u30AF\u30A8\u30EA \`{ workflowStates { nodes { id name type } } }\` \u3092\u547C\u3073\u51FA\u3057\u3001\u30EF\u30FC\u30AF\u30D5\u30ED\u30FC\u72B6\u614B\u4E00\u89A7\u3092\u53D6\u5F97
418
+ 3. connector_linear_request \u3067\u30AF\u30A8\u30EA \`{ issues(first: 5, orderBy: updatedAt) { nodes { id identifier title state { name } assignee { name } priority } } }\` \u3092\u547C\u3073\u51FA\u3057\u3001\u6700\u8FD1\u306EIssue\u3092\u30B5\u30F3\u30D7\u30EA\u30F3\u30B0
419
+ 4. connector_linear_request \u3067\u30AF\u30A8\u30EA \`{ projects(first: 5) { nodes { id name state } } }\` \u3092\u547C\u3073\u51FA\u3057\u3001\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u4E00\u89A7\u3092\u53D6\u5F97
420
420
  5. \u5FC5\u8981\u306B\u5FDC\u3058\u3066\u4ED6\u306E\u30EA\u30BD\u30FC\u30B9\uFF08cycles\u3001labels\u3001users\uFF09\u3092\u63A2\u7D22`
421
421
  }
422
422
  });
@@ -473,6 +473,35 @@ async function getTeamDetail(params, teamId) {
473
473
  );
474
474
  return data.team ?? null;
475
475
  }
476
+ async function getIssueBreakdown(params, teamId) {
477
+ try {
478
+ const data = await gqlFetch(
479
+ params,
480
+ `query($id: String!) {
481
+ team(id: $id) {
482
+ issues(first: 250) { nodes { state { name type } } }
483
+ }
484
+ }`,
485
+ { id: teamId }
486
+ );
487
+ const nodes = data.team?.issues?.nodes ?? [];
488
+ const counts = /* @__PURE__ */ new Map();
489
+ for (const n of nodes) {
490
+ const key = `${n.state?.name ?? "Unknown"}|${n.state?.type ?? "unknown"}`;
491
+ const existing = counts.get(key);
492
+ if (existing) existing.count++;
493
+ else
494
+ counts.set(key, {
495
+ stateName: n.state?.name ?? "Unknown",
496
+ stateType: n.state?.type ?? "unknown",
497
+ count: 1
498
+ });
499
+ }
500
+ return { total: nodes.length, byState: Array.from(counts.values()) };
501
+ } catch {
502
+ return null;
503
+ }
504
+ }
476
505
  var linearSetupFlow = {
477
506
  initialState: () => ({}),
478
507
  steps: [
@@ -529,6 +558,19 @@ var linearSetupFlow = {
529
558
  sections.push(` - ${s.name} (${s.type})`);
530
559
  }
531
560
  sections.push("");
561
+ const breakdown = await getIssueBreakdown(rt.params, teamId);
562
+ if (breakdown && breakdown.byState.length > 0) {
563
+ sections.push(
564
+ `#### Issues (${breakdown.total}${breakdown.total === 250 ? "+" : ""})`,
565
+ ""
566
+ );
567
+ sections.push("| State | Type | Count |");
568
+ sections.push("|-------|------|-------|");
569
+ for (const b of breakdown.byState) {
570
+ sections.push(`| ${b.stateName} | ${b.stateType} | ${b.count} |`);
571
+ }
572
+ sections.push("");
573
+ }
532
574
  }
533
575
  return sections.join("\n");
534
576
  }
@@ -639,7 +681,7 @@ var linearConnector = new ConnectorPlugin({
639
681
  systemPrompt: {
640
682
  en: `### Tools
641
683
 
642
- - \`linear_request\`: The only way to call the Linear GraphQL API. Use it to query and mutate all Linear resources: issues, projects, teams, cycles, users, labels, workflow states, and comments. Authentication is configured automatically. Linear's API is GraphQL-only \u2014 send a query string and optional variables. Pagination uses Relay-style cursors with \`first\`/\`after\` and \`last\`/\`before\` arguments. Archived resources are hidden by default; pass \`includeArchived: true\` to include them.
684
+ - \`connector_linear_request\`: The only way to call the Linear GraphQL API. Use it to query and mutate all Linear resources: issues, projects, teams, cycles, users, labels, workflow states, and comments. Authentication is configured automatically. Linear's API is GraphQL-only \u2014 send a query string and optional variables. Pagination uses Relay-style cursors with \`first\`/\`after\` and \`last\`/\`before\` arguments. Archived resources are hidden by default; pass \`includeArchived: true\` to include them.
643
685
 
644
686
  ### Business Logic
645
687
 
@@ -700,7 +742,7 @@ export default async function handler(c: Context) {
700
742
  - \`mutation { commentCreate(input: { issueId: "...", body: "..." }) { success comment { id body } } }\` \u2014 add comment`,
701
743
  ja: `### \u30C4\u30FC\u30EB
702
744
 
703
- - \`linear_request\`: Linear GraphQL API\u3092\u547C\u3073\u51FA\u3059\u552F\u4E00\u306E\u624B\u6BB5\u3067\u3059\u3002Issue\u3001\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u3001\u30C1\u30FC\u30E0\u3001\u30B5\u30A4\u30AF\u30EB\u3001\u30E6\u30FC\u30B6\u30FC\u3001\u30E9\u30D9\u30EB\u3001\u30EF\u30FC\u30AF\u30D5\u30ED\u30FC\u72B6\u614B\u3001\u30B3\u30E1\u30F3\u30C8\u306A\u3069\u3059\u3079\u3066\u306ELinear\u30EA\u30BD\u30FC\u30B9\u306E\u30AF\u30A8\u30EA\u3068\u30DF\u30E5\u30FC\u30C6\u30FC\u30B7\u30E7\u30F3\u306B\u4F7F\u7528\u3057\u307E\u3059\u3002\u8A8D\u8A3C\u306F\u81EA\u52D5\u7684\u306B\u8A2D\u5B9A\u3055\u308C\u307E\u3059\u3002Linear\u306EAPI\u306FGraphQL\u306E\u307F\u3067\u3059\u3002\u30AF\u30A8\u30EA\u6587\u5B57\u5217\u3068\u30AA\u30D7\u30B7\u30E7\u30F3\u306E\u5909\u6570\u3092\u9001\u4FE1\u3057\u307E\u3059\u3002\u30DA\u30FC\u30B8\u30CD\u30FC\u30B7\u30E7\u30F3\u306FRelay\u5F62\u5F0F\u306E\u30AB\u30FC\u30BD\u30EB\u30D9\u30FC\u30B9\u3067\u3001\`first\`/\`after\`\u304A\u3088\u3073\`last\`/\`before\`\u5F15\u6570\u3092\u4F7F\u7528\u3057\u307E\u3059\u3002\u30A2\u30FC\u30AB\u30A4\u30D6\u3055\u308C\u305F\u30EA\u30BD\u30FC\u30B9\u306F\u30C7\u30D5\u30A9\u30EB\u30C8\u3067\u975E\u8868\u793A\u3067\u3059\u3002\`includeArchived: true\`\u3092\u6E21\u3059\u3068\u542B\u3081\u3089\u308C\u307E\u3059\u3002
745
+ - \`connector_linear_request\`: Linear GraphQL API\u3092\u547C\u3073\u51FA\u3059\u552F\u4E00\u306E\u624B\u6BB5\u3067\u3059\u3002Issue\u3001\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u3001\u30C1\u30FC\u30E0\u3001\u30B5\u30A4\u30AF\u30EB\u3001\u30E6\u30FC\u30B6\u30FC\u3001\u30E9\u30D9\u30EB\u3001\u30EF\u30FC\u30AF\u30D5\u30ED\u30FC\u72B6\u614B\u3001\u30B3\u30E1\u30F3\u30C8\u306A\u3069\u3059\u3079\u3066\u306ELinear\u30EA\u30BD\u30FC\u30B9\u306E\u30AF\u30A8\u30EA\u3068\u30DF\u30E5\u30FC\u30C6\u30FC\u30B7\u30E7\u30F3\u306B\u4F7F\u7528\u3057\u307E\u3059\u3002\u8A8D\u8A3C\u306F\u81EA\u52D5\u7684\u306B\u8A2D\u5B9A\u3055\u308C\u307E\u3059\u3002Linear\u306EAPI\u306FGraphQL\u306E\u307F\u3067\u3059\u3002\u30AF\u30A8\u30EA\u6587\u5B57\u5217\u3068\u30AA\u30D7\u30B7\u30E7\u30F3\u306E\u5909\u6570\u3092\u9001\u4FE1\u3057\u307E\u3059\u3002\u30DA\u30FC\u30B8\u30CD\u30FC\u30B7\u30E7\u30F3\u306FRelay\u5F62\u5F0F\u306E\u30AB\u30FC\u30BD\u30EB\u30D9\u30FC\u30B9\u3067\u3001\`first\`/\`after\`\u304A\u3088\u3073\`last\`/\`before\`\u5F15\u6570\u3092\u4F7F\u7528\u3057\u307E\u3059\u3002\u30A2\u30FC\u30AB\u30A4\u30D6\u3055\u308C\u305F\u30EA\u30BD\u30FC\u30B9\u306F\u30C7\u30D5\u30A9\u30EB\u30C8\u3067\u975E\u8868\u793A\u3067\u3059\u3002\`includeArchived: true\`\u3092\u6E21\u3059\u3068\u542B\u3081\u3089\u308C\u307E\u3059\u3002
704
746
 
705
747
  ### Business Logic
706
748