@squadbase/vite-server 0.1.17-dev.a9ddcfa → 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.
- package/dist/cli/index.js +4299 -821
- package/dist/connectors/airtable-oauth.js +48 -8
- package/dist/connectors/airtable.js +44 -8
- package/dist/connectors/amplitude.js +8 -8
- package/dist/connectors/anthropic.js +2 -2
- package/dist/connectors/asana.js +37 -10
- package/dist/connectors/attio.js +30 -13
- package/dist/connectors/aws-billing.js +8 -8
- package/dist/connectors/azure-sql.js +47 -10
- package/dist/connectors/backlog-api-key.js +40 -15
- package/dist/connectors/clickup.js +50 -10
- package/dist/connectors/cosmosdb.js +12 -12
- package/dist/connectors/customerio.js +8 -8
- package/dist/connectors/dbt.js +686 -25
- package/dist/connectors/freshdesk.js +82 -8
- package/dist/connectors/freshsales.js +8 -8
- package/dist/connectors/freshservice.js +8 -8
- package/dist/connectors/gamma.js +15 -15
- package/dist/connectors/gemini.js +2 -2
- package/dist/connectors/github.js +12 -12
- package/dist/connectors/gmail-oauth.js +10 -10
- package/dist/connectors/gmail.js +4 -4
- package/dist/connectors/google-ads.js +8 -8
- package/dist/connectors/google-analytics-oauth.js +152 -25
- package/dist/connectors/google-analytics.js +490 -96
- package/dist/connectors/google-audit-log.js +4 -4
- package/dist/connectors/google-calendar-oauth.js +61 -15
- package/dist/connectors/google-calendar.js +61 -11
- package/dist/connectors/google-docs.js +10 -10
- package/dist/connectors/google-drive.js +32 -10
- package/dist/connectors/google-search-console-oauth.js +126 -17
- package/dist/connectors/google-sheets.js +6 -6
- package/dist/connectors/google-slides.js +10 -10
- package/dist/connectors/grafana.js +45 -10
- package/dist/connectors/hackernews.d.ts +5 -0
- package/dist/connectors/hackernews.js +890 -0
- package/dist/connectors/hubspot-oauth.js +41 -9
- package/dist/connectors/hubspot.js +25 -9
- package/dist/connectors/influxdb.js +8 -8
- package/dist/connectors/intercom-oauth.js +72 -12
- package/dist/connectors/intercom.js +12 -12
- package/dist/connectors/jdbc.js +37 -10
- package/dist/connectors/jira-api-key.js +68 -11
- package/dist/connectors/kintone-api-token.js +66 -18
- package/dist/connectors/kintone.js +54 -11
- package/dist/connectors/linear.js +54 -12
- package/dist/connectors/linkedin-ads.js +41 -14
- package/dist/connectors/mailchimp-oauth.js +6 -6
- package/dist/connectors/mailchimp.js +6 -6
- package/dist/connectors/meta-ads-oauth.js +33 -14
- package/dist/connectors/meta-ads.js +35 -14
- package/dist/connectors/mixpanel.js +8 -8
- package/dist/connectors/monday.js +9 -9
- package/dist/connectors/mongodb.js +8 -8
- package/dist/connectors/notion-oauth.js +60 -11
- package/dist/connectors/notion.js +60 -11
- package/dist/connectors/openai.js +2 -2
- package/dist/connectors/oracle.js +39 -11
- package/dist/connectors/outlook-oauth.js +21 -21
- package/dist/connectors/powerbi-oauth.js +13 -13
- package/dist/connectors/salesforce.js +42 -9
- package/dist/connectors/semrush.js +6 -6
- package/dist/connectors/sentry.js +36 -10
- package/dist/connectors/shopify-oauth.js +43 -10
- package/dist/connectors/shopify.js +8 -8
- package/dist/connectors/sqlserver.js +47 -10
- package/dist/connectors/stripe-api-key.js +66 -15
- package/dist/connectors/stripe-oauth.js +70 -19
- package/dist/connectors/supabase.js +31 -6
- package/dist/connectors/tableau.js +15 -15
- package/dist/connectors/tiktok-ads.js +37 -16
- package/dist/connectors/wix-store.js +8 -8
- package/dist/connectors/x.d.ts +5 -0
- package/dist/connectors/x.js +927 -0
- package/dist/connectors/zendesk-oauth.js +55 -12
- package/dist/connectors/zendesk.js +12 -12
- package/dist/index.js +4317 -819
- package/dist/main.js +4317 -819
- package/dist/vite-plugin.js +4297 -819
- 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
|
|
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[
|
|
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
|
|
368
|
-
2. For key projects, call
|
|
369
|
-
3. Call
|
|
370
|
-
ja: `1.
|
|
371
|
-
2. \u4E3B\u8981\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u306B\u3064\u3044\u3066
|
|
372
|
-
3.
|
|
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
|
-
|
|
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
|
-
- \`
|
|
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
|
-
- \`
|
|
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
|
|
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[
|
|
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
|
|
394
|
-
2. Call
|
|
395
|
-
3. Call
|
|
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.
|
|
399
|
-
2.
|
|
400
|
-
3.
|
|
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[
|
|
470
|
+
const appId = rt.params["app-id"];
|
|
455
471
|
if (!appId) {
|
|
456
|
-
|
|
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
|
|
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
|
-
- \`
|
|
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
|
-
- \`
|
|
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
|
|
788
|
+
if (!baseUrl || !apiToken) {
|
|
751
789
|
return {
|
|
752
790
|
success: false,
|
|
753
|
-
error: `Missing required parameters: ${parameters.baseUrl.slug}, ${parameters.apiToken.slug}
|
|
791
|
+
error: `Missing required parameters: ${parameters.baseUrl.slug}, ${parameters.apiToken.slug}`
|
|
754
792
|
};
|
|
755
793
|
}
|
|
756
794
|
try {
|
|
757
|
-
const
|
|
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
|
|
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[
|
|
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
|
|
406
|
-
2. For key apps, call
|
|
407
|
-
3. Call
|
|
408
|
-
ja: `1.
|
|
409
|
-
2. \u4E3B\u8981\u30A2\u30D7\u30EA\u306B\u3064\u3044\u3066
|
|
410
|
-
3.
|
|
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
|
|
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
|
-
- \`
|
|
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
|
-
- \`
|
|
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
|
|
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[
|
|
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
|
|
412
|
-
2. Call
|
|
413
|
-
3. Call
|
|
414
|
-
4. Call
|
|
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.
|
|
417
|
-
2.
|
|
418
|
-
3.
|
|
419
|
-
4.
|
|
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
|
-
- \`
|
|
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
|
-
- \`
|
|
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
|
|