gut-cli 0.1.22 → 0.1.23

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.
@@ -1,5 +1,10 @@
1
1
  import { z } from 'zod';
2
2
 
3
+ type Language = 'en' | 'ja';
4
+ declare function getLanguage(): Language;
5
+ declare function setLanguage(lang: Language, local?: boolean): void;
6
+ declare function getLanguageInstruction(lang: Language): string;
7
+
3
8
  type Provider = 'gemini' | 'openai' | 'anthropic' | 'ollama';
4
9
  declare function saveApiKey(provider: Provider, apiKey: string): Promise<void>;
5
10
  declare function getApiKey(provider: Provider): Promise<string | null>;
@@ -9,11 +14,6 @@ declare function listProviders(): Promise<{
9
14
  hasKey: boolean;
10
15
  }[]>;
11
16
 
12
- type Language = 'en' | 'ja';
13
- declare function getLanguage(): Language;
14
- declare function setLanguage(lang: Language, local?: boolean): void;
15
- declare function getLanguageInstruction(lang: Language): string;
16
-
17
17
  interface AIOptions {
18
18
  provider: Provider;
19
19
  model?: string;
package/dist/lib/index.js CHANGED
@@ -1,14 +1,121 @@
1
1
  // src/lib/ai.ts
2
- import { generateText, generateObject } from "ai";
2
+ import { existsSync as existsSync2, readFileSync as readFileSync2 } from "fs";
3
+ import { homedir as homedir2 } from "os";
4
+ import { dirname, join as join2 } from "path";
5
+ import { fileURLToPath } from "url";
6
+ import { createAnthropic } from "@ai-sdk/anthropic";
3
7
  import { createGoogleGenerativeAI } from "@ai-sdk/google";
4
8
  import { createOpenAI } from "@ai-sdk/openai";
5
- import { createAnthropic } from "@ai-sdk/anthropic";
9
+ import { generateObject, generateText } from "ai";
6
10
  import { createOllama } from "ollama-ai-provider";
7
11
  import { z } from "zod";
8
- import { existsSync, readFileSync } from "fs";
9
- import { join, dirname } from "path";
12
+
13
+ // src/lib/config.ts
14
+ import { execSync } from "child_process";
15
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
10
16
  import { homedir } from "os";
11
- import { fileURLToPath } from "url";
17
+ import { join } from "path";
18
+ var DEFAULT_CONFIG = {
19
+ lang: "en"
20
+ };
21
+ var DEFAULT_MODELS = {
22
+ gemini: "gemini-2.5-flash",
23
+ openai: "gpt-4.1-mini",
24
+ anthropic: "claude-sonnet-4-5",
25
+ ollama: "llama3.3"
26
+ };
27
+ function getGlobalConfigPath() {
28
+ const configDir = join(homedir(), ".config", "gut");
29
+ return join(configDir, "config.json");
30
+ }
31
+ function getRepoRoot() {
32
+ try {
33
+ return execSync("git rev-parse --show-toplevel", { encoding: "utf-8" }).trim();
34
+ } catch {
35
+ return null;
36
+ }
37
+ }
38
+ function getLocalConfigPath() {
39
+ const repoRoot = getRepoRoot();
40
+ if (!repoRoot) return null;
41
+ return join(repoRoot, ".gut", "config.json");
42
+ }
43
+ function ensureGlobalConfigDir() {
44
+ const configDir = join(homedir(), ".config", "gut");
45
+ if (!existsSync(configDir)) {
46
+ mkdirSync(configDir, { recursive: true });
47
+ }
48
+ }
49
+ function ensureLocalConfigDir() {
50
+ const repoRoot = getRepoRoot();
51
+ if (!repoRoot) return;
52
+ const gutDir = join(repoRoot, ".gut");
53
+ if (!existsSync(gutDir)) {
54
+ mkdirSync(gutDir, { recursive: true });
55
+ }
56
+ }
57
+ function readConfigFile(path) {
58
+ if (!existsSync(path)) return {};
59
+ try {
60
+ return JSON.parse(readFileSync(path, "utf-8"));
61
+ } catch {
62
+ return {};
63
+ }
64
+ }
65
+ function getGlobalConfig() {
66
+ const globalPath = getGlobalConfigPath();
67
+ return { ...DEFAULT_CONFIG, ...readConfigFile(globalPath) };
68
+ }
69
+ function getLocalConfig() {
70
+ const localPath = getLocalConfigPath();
71
+ if (!localPath) return {};
72
+ return readConfigFile(localPath);
73
+ }
74
+ function getConfig() {
75
+ const globalConfig = getGlobalConfig();
76
+ const localConfig = getLocalConfig();
77
+ return { ...globalConfig, ...localConfig };
78
+ }
79
+ function setGlobalConfig(key, value) {
80
+ ensureGlobalConfigDir();
81
+ const config = getGlobalConfig();
82
+ config[key] = value;
83
+ writeFileSync(getGlobalConfigPath(), JSON.stringify(config, null, 2));
84
+ }
85
+ function setLocalConfig(key, value) {
86
+ const localPath = getLocalConfigPath();
87
+ if (!localPath) {
88
+ throw new Error("Not in a git repository");
89
+ }
90
+ ensureLocalConfigDir();
91
+ const config = getLocalConfig();
92
+ config[key] = value;
93
+ writeFileSync(localPath, JSON.stringify(config, null, 2));
94
+ }
95
+ function getLanguage() {
96
+ return getConfig().lang;
97
+ }
98
+ function setLanguage(lang, local = false) {
99
+ if (local) {
100
+ setLocalConfig("lang", lang);
101
+ } else {
102
+ setGlobalConfig("lang", lang);
103
+ }
104
+ }
105
+ function getLanguageInstruction(lang) {
106
+ switch (lang) {
107
+ case "ja":
108
+ return "\n\nIMPORTANT: Respond in Japanese (\u65E5\u672C\u8A9E\u3067\u56DE\u7B54\u3057\u3066\u304F\u3060\u3055\u3044).";
109
+ default:
110
+ return "";
111
+ }
112
+ }
113
+ function getConfiguredModel() {
114
+ return getConfig().model;
115
+ }
116
+ function getDefaultModel(provider) {
117
+ return DEFAULT_MODELS[provider] || DEFAULT_MODELS.gemini;
118
+ }
12
119
 
13
120
  // src/lib/credentials.ts
14
121
  import { createRequire } from "module";
@@ -86,36 +193,36 @@ var __dirname = dirname(__filename);
86
193
  function findGutRoot() {
87
194
  let current = __dirname;
88
195
  for (let i = 0; i < 5; i++) {
89
- const gutPath = join(current, ".gut");
90
- if (existsSync(gutPath)) {
196
+ const gutPath = join2(current, ".gut");
197
+ if (existsSync2(gutPath)) {
91
198
  return current;
92
199
  }
93
200
  current = dirname(current);
94
201
  }
95
- return join(__dirname, "..");
202
+ return join2(__dirname, "..");
96
203
  }
97
204
  var GUT_ROOT = findGutRoot();
98
205
  function loadTemplate(name) {
99
- const templatePath = join(GUT_ROOT, ".gut", `${name}.md`);
100
- if (existsSync(templatePath)) {
101
- return readFileSync(templatePath, "utf-8");
206
+ const templatePath = join2(GUT_ROOT, ".gut", `${name}.md`);
207
+ if (existsSync2(templatePath)) {
208
+ return readFileSync2(templatePath, "utf-8");
102
209
  }
103
210
  throw new Error(`Template not found: ${templatePath}`);
104
211
  }
105
212
  function getGlobalTemplatesDir() {
106
- return join(homedir(), ".config", "gut", "templates");
213
+ return join2(homedir2(), ".config", "gut", "templates");
107
214
  }
108
215
  function findGlobalTemplate(templateName) {
109
- const templatePath = join(getGlobalTemplatesDir(), `${templateName}.md`);
110
- if (existsSync(templatePath)) {
111
- return readFileSync(templatePath, "utf-8");
216
+ const templatePath = join2(getGlobalTemplatesDir(), `${templateName}.md`);
217
+ if (existsSync2(templatePath)) {
218
+ return readFileSync2(templatePath, "utf-8");
112
219
  }
113
220
  return null;
114
221
  }
115
222
  function findTemplate(repoRoot, templateName) {
116
- const projectTemplatePath = join(repoRoot, ".gut", `${templateName}.md`);
117
- if (existsSync(projectTemplatePath)) {
118
- return readFileSync(projectTemplatePath, "utf-8");
223
+ const projectTemplatePath = join2(repoRoot, ".gut", `${templateName}.md`);
224
+ if (existsSync2(projectTemplatePath)) {
225
+ return readFileSync2(projectTemplatePath, "utf-8");
119
226
  }
120
227
  const globalTemplate = findGlobalTemplate(templateName);
121
228
  if (globalTemplate) {
@@ -141,16 +248,12 @@ ${value}
141
248
  <output-format>
142
249
  ${outputFormat}
143
250
  </output-format>` : "";
144
- return contextXml + "<instructions>\n" + template + langInstruction + "\n</instructions>" + outputSection;
251
+ return `${contextXml}<instructions>
252
+ ${template}${langInstruction}
253
+ </instructions>${outputSection}`;
145
254
  }
146
- var DEFAULT_MODELS = {
147
- gemini: "gemini-2.0-flash",
148
- openai: "gpt-4o-mini",
149
- anthropic: "claude-sonnet-4-20250514",
150
- ollama: "llama3.2"
151
- };
152
255
  async function getModel(options) {
153
- const modelName = options.model || DEFAULT_MODELS[options.provider];
256
+ const modelName = options.model || getConfiguredModel() || getDefaultModel(options.provider);
154
257
  async function resolveApiKey() {
155
258
  if (options.apiKey) return options.apiKey;
156
259
  return getApiKey(options.provider);
@@ -189,9 +292,15 @@ async function getModel(options) {
189
292
  }
190
293
  async function generateCommitMessage(diff, options, template) {
191
294
  const model = await getModel(options);
192
- const prompt = buildPrompt(template, "commit", {
193
- diff: diff.slice(0, 8e3)
194
- }, options.language, "Respond with ONLY the commit message, nothing else.");
295
+ const prompt = buildPrompt(
296
+ template,
297
+ "commit",
298
+ {
299
+ diff: diff.slice(0, 8e3)
300
+ },
301
+ options.language,
302
+ "Respond with ONLY the commit message, nothing else."
303
+ );
195
304
  const result = await generateText({
196
305
  model,
197
306
  prompt,
@@ -201,18 +310,24 @@ async function generateCommitMessage(diff, options, template) {
201
310
  }
202
311
  async function generatePRDescription(context, options, template) {
203
312
  const model = await getModel(options);
204
- const prompt = buildPrompt(template, "pr", {
205
- baseBranch: context.baseBranch,
206
- currentBranch: context.currentBranch,
207
- commits: context.commits.map((c) => `- ${c}`).join("\n"),
208
- diff: context.diff.slice(0, 6e3)
209
- }, options.language, `Respond in JSON format:
313
+ const prompt = buildPrompt(
314
+ template,
315
+ "pr",
316
+ {
317
+ baseBranch: context.baseBranch,
318
+ currentBranch: context.currentBranch,
319
+ commits: context.commits.map((c) => `- ${c}`).join("\n"),
320
+ diff: context.diff.slice(0, 6e3)
321
+ },
322
+ options.language,
323
+ `Respond in JSON format:
210
324
  \`\`\`json
211
325
  {
212
326
  "title": "...",
213
327
  "body": "..."
214
328
  }
215
- \`\`\``);
329
+ \`\`\``
330
+ );
216
331
  const result = await generateText({
217
332
  model,
218
333
  prompt,
@@ -243,9 +358,14 @@ var CodeReviewSchema = z.object({
243
358
  });
244
359
  async function generateCodeReview(diff, options, template) {
245
360
  const model = await getModel(options);
246
- const prompt = buildPrompt(template, "review", {
247
- diff: diff.slice(0, 1e4)
248
- }, options.language);
361
+ const prompt = buildPrompt(
362
+ template,
363
+ "review",
364
+ {
365
+ diff: diff.slice(0, 1e4)
366
+ },
367
+ options.language
368
+ );
249
369
  const result = await generateObject({
250
370
  model,
251
371
  schema: CodeReviewSchema,
@@ -267,13 +387,18 @@ var ChangelogSchema = z.object({
267
387
  async function generateChangelog(context, options, template) {
268
388
  const model = await getModel(options);
269
389
  const commitList = context.commits.map((c) => `- ${c.hash.slice(0, 7)} ${c.message} (${c.author})`).join("\n");
270
- const prompt = buildPrompt(template, "changelog", {
271
- fromRef: context.fromRef,
272
- toRef: context.toRef,
273
- commits: commitList,
274
- diff: context.diff.slice(0, 8e3),
275
- todayDate: (/* @__PURE__ */ new Date()).toISOString().split("T")[0]
276
- }, options.language);
390
+ const prompt = buildPrompt(
391
+ template,
392
+ "changelog",
393
+ {
394
+ fromRef: context.fromRef,
395
+ toRef: context.toRef,
396
+ commits: commitList,
397
+ diff: context.diff.slice(0, 8e3),
398
+ todayDate: (/* @__PURE__ */ new Date()).toISOString().split("T")[0]
399
+ },
400
+ options.language
401
+ );
277
402
  const result = await generateObject({
278
403
  model,
279
404
  schema: ChangelogSchema,
@@ -301,10 +426,15 @@ var ExplanationSchema = z.object({
301
426
  async function generateExplanation(context, options, template) {
302
427
  const model = await getModel(options);
303
428
  if (context.type === "file-content") {
304
- const prompt2 = buildPrompt(template, "explain-file", {
305
- filePath: context.metadata.filePath || "",
306
- content: context.content?.slice(0, 15e3) || ""
307
- }, options.language);
429
+ const prompt2 = buildPrompt(
430
+ template,
431
+ "explain-file",
432
+ {
433
+ filePath: context.metadata.filePath || "",
434
+ content: context.content?.slice(0, 15e3) || ""
435
+ },
436
+ options.language
437
+ );
308
438
  const result2 = await generateObject({
309
439
  model,
310
440
  schema: ExplanationSchema,
@@ -338,11 +468,16 @@ Author: ${context.metadata.author}
338
468
  Date: ${context.metadata.date}`;
339
469
  targetType = "commit";
340
470
  }
341
- const prompt = buildPrompt(template, "explain", {
342
- targetType,
343
- contextInfo,
344
- diff: context.diff?.slice(0, 12e3) || ""
345
- }, options.language);
471
+ const prompt = buildPrompt(
472
+ template,
473
+ "explain",
474
+ {
475
+ targetType,
476
+ contextInfo,
477
+ diff: context.diff?.slice(0, 12e3) || ""
478
+ },
479
+ options.language
480
+ );
346
481
  const result = await generateObject({
347
482
  model,
348
483
  schema: ExplanationSchema,
@@ -361,12 +496,19 @@ var CommitSearchSchema = z.object({
361
496
  });
362
497
  async function searchCommits(query, commits, options, maxResults = 5, template) {
363
498
  const model = await getModel(options);
364
- const commitList = commits.map((c) => `${c.hash.slice(0, 7)} | ${c.author} | ${c.date.split("T")[0]} | ${c.message.split("\n")[0]}`).join("\n");
365
- const prompt = buildPrompt(template, "find", {
366
- query,
367
- commits: commitList,
368
- maxResults: String(maxResults)
369
- }, options.language);
499
+ const commitList = commits.map(
500
+ (c) => `${c.hash.slice(0, 7)} | ${c.author} | ${c.date.split("T")[0]} | ${c.message.split("\n")[0]}`
501
+ ).join("\n");
502
+ const prompt = buildPrompt(
503
+ template,
504
+ "find",
505
+ {
506
+ query,
507
+ commits: commitList,
508
+ maxResults: String(maxResults)
509
+ },
510
+ options.language
511
+ );
370
512
  const result = await generateObject({
371
513
  model,
372
514
  schema: CommitSearchSchema,
@@ -395,11 +537,17 @@ async function searchCommits(query, commits, options, maxResults = 5, template)
395
537
  }
396
538
  async function generateBranchName(description, options, context, template) {
397
539
  const model = await getModel(options);
398
- const prompt = buildPrompt(template, "branch", {
399
- description,
400
- type: context?.type,
401
- issue: context?.issue
402
- }, options.language, "Respond with ONLY the branch name, nothing else.");
540
+ const prompt = buildPrompt(
541
+ template,
542
+ "branch",
543
+ {
544
+ description,
545
+ type: context?.type,
546
+ issue: context?.issue
547
+ },
548
+ options.language,
549
+ "Respond with ONLY the branch name, nothing else."
550
+ );
403
551
  const result = await generateText({
404
552
  model,
405
553
  prompt,
@@ -409,9 +557,15 @@ async function generateBranchName(description, options, context, template) {
409
557
  }
410
558
  async function generateBranchNameFromDiff(diff, options, template) {
411
559
  const model = await getModel(options);
412
- const prompt = buildPrompt(template, "checkout", {
413
- diff: diff.slice(0, 8e3)
414
- }, options.language, "Respond with ONLY the branch name, nothing else.");
560
+ const prompt = buildPrompt(
561
+ template,
562
+ "checkout",
563
+ {
564
+ diff: diff.slice(0, 8e3)
565
+ },
566
+ options.language,
567
+ "Respond with ONLY the branch name, nothing else."
568
+ );
415
569
  const result = await generateText({
416
570
  model,
417
571
  prompt,
@@ -421,9 +575,15 @@ async function generateBranchNameFromDiff(diff, options, template) {
421
575
  }
422
576
  async function generateStashName(diff, options, template) {
423
577
  const model = await getModel(options);
424
- const prompt = buildPrompt(template, "stash", {
425
- diff: diff.slice(0, 4e3)
426
- }, options.language, "Respond with ONLY the stash name, nothing else.");
578
+ const prompt = buildPrompt(
579
+ template,
580
+ "stash",
581
+ {
582
+ diff: diff.slice(0, 4e3)
583
+ },
584
+ options.language,
585
+ "Respond with ONLY the stash name, nothing else."
586
+ );
427
587
  const result = await generateText({
428
588
  model,
429
589
  prompt,
@@ -453,13 +613,18 @@ async function generateWorkSummary(context, options, format = "custom", template
453
613
  const commitList = context.commits.map((c) => `- ${c.hash.slice(0, 7)} ${c.message.split("\n")[0]} (${c.date.split("T")[0]})`).join("\n");
454
614
  const formatHint = format === "daily" ? "This is a daily report. Focus on today's accomplishments." : format === "weekly" ? "This is a weekly report. Summarize the week's work at a higher level." : `This is a summary from ${context.since}${context.until ? ` to ${context.until}` : ""}.`;
455
615
  const period = `${context.since}${context.until ? ` to ${context.until}` : " to now"}`;
456
- const prompt = buildPrompt(template, "summary", {
457
- author: context.author,
458
- period,
459
- format: formatHint,
460
- commits: commitList,
461
- diff: context.diff?.slice(0, 6e3)
462
- }, options.language);
616
+ const prompt = buildPrompt(
617
+ template,
618
+ "summary",
619
+ {
620
+ author: context.author,
621
+ period,
622
+ format: formatHint,
623
+ commits: commitList,
624
+ diff: context.diff?.slice(0, 6e3)
625
+ },
626
+ options.language
627
+ );
463
628
  const result = await generateObject({
464
629
  model,
465
630
  schema: WorkSummarySchema,
@@ -475,12 +640,17 @@ async function generateWorkSummary(context, options, format = "custom", template
475
640
  }
476
641
  async function resolveConflict(conflictedContent, context, options, template) {
477
642
  const model = await getModel(options);
478
- const prompt = buildPrompt(template, "merge", {
479
- filename: context.filename,
480
- oursRef: context.oursRef,
481
- theirsRef: context.theirsRef,
482
- content: conflictedContent
483
- }, options.language);
643
+ const prompt = buildPrompt(
644
+ template,
645
+ "merge",
646
+ {
647
+ filename: context.filename,
648
+ oursRef: context.oursRef,
649
+ theirsRef: context.theirsRef,
650
+ content: conflictedContent
651
+ },
652
+ options.language
653
+ );
484
654
  const result = await generateObject({
485
655
  model,
486
656
  schema: ConflictResolutionSchema,
@@ -490,11 +660,17 @@ async function resolveConflict(conflictedContent, context, options, template) {
490
660
  }
491
661
  async function generateGitignore(context, options, template) {
492
662
  const model = await getModel(options);
493
- const prompt = buildPrompt(template, "gitignore", {
494
- files: context.files,
495
- configFiles: context.configFiles,
496
- existingGitignore: context.existingGitignore
497
- }, options.language, "Respond with ONLY the .gitignore content, nothing else. No explanations or markdown code blocks.");
663
+ const prompt = buildPrompt(
664
+ template,
665
+ "gitignore",
666
+ {
667
+ files: context.files,
668
+ configFiles: context.configFiles,
669
+ existingGitignore: context.existingGitignore
670
+ },
671
+ options.language,
672
+ "Respond with ONLY the .gitignore content, nothing else. No explanations or markdown code blocks."
673
+ );
498
674
  const result = await generateText({
499
675
  model,
500
676
  prompt,
@@ -502,102 +678,6 @@ async function generateGitignore(context, options, template) {
502
678
  });
503
679
  return result.text.trim();
504
680
  }
505
-
506
- // src/lib/config.ts
507
- import { homedir as homedir2 } from "os";
508
- import { join as join2 } from "path";
509
- import { existsSync as existsSync2, mkdirSync, readFileSync as readFileSync2, writeFileSync } from "fs";
510
- import { execSync } from "child_process";
511
- var DEFAULT_CONFIG = {
512
- lang: "en"
513
- };
514
- function getGlobalConfigPath() {
515
- const configDir = join2(homedir2(), ".config", "gut");
516
- return join2(configDir, "config.json");
517
- }
518
- function getRepoRoot() {
519
- try {
520
- return execSync("git rev-parse --show-toplevel", { encoding: "utf-8" }).trim();
521
- } catch {
522
- return null;
523
- }
524
- }
525
- function getLocalConfigPath() {
526
- const repoRoot = getRepoRoot();
527
- if (!repoRoot) return null;
528
- return join2(repoRoot, ".gut", "config.json");
529
- }
530
- function ensureGlobalConfigDir() {
531
- const configDir = join2(homedir2(), ".config", "gut");
532
- if (!existsSync2(configDir)) {
533
- mkdirSync(configDir, { recursive: true });
534
- }
535
- }
536
- function ensureLocalConfigDir() {
537
- const repoRoot = getRepoRoot();
538
- if (!repoRoot) return;
539
- const gutDir = join2(repoRoot, ".gut");
540
- if (!existsSync2(gutDir)) {
541
- mkdirSync(gutDir, { recursive: true });
542
- }
543
- }
544
- function readConfigFile(path) {
545
- if (!existsSync2(path)) return {};
546
- try {
547
- return JSON.parse(readFileSync2(path, "utf-8"));
548
- } catch {
549
- return {};
550
- }
551
- }
552
- function getGlobalConfig() {
553
- const globalPath = getGlobalConfigPath();
554
- return { ...DEFAULT_CONFIG, ...readConfigFile(globalPath) };
555
- }
556
- function getLocalConfig() {
557
- const localPath = getLocalConfigPath();
558
- if (!localPath) return {};
559
- return readConfigFile(localPath);
560
- }
561
- function getConfig() {
562
- const globalConfig = getGlobalConfig();
563
- const localConfig = getLocalConfig();
564
- return { ...globalConfig, ...localConfig };
565
- }
566
- function setGlobalConfig(key, value) {
567
- ensureGlobalConfigDir();
568
- const config = getGlobalConfig();
569
- config[key] = value;
570
- writeFileSync(getGlobalConfigPath(), JSON.stringify(config, null, 2));
571
- }
572
- function setLocalConfig(key, value) {
573
- const localPath = getLocalConfigPath();
574
- if (!localPath) {
575
- throw new Error("Not in a git repository");
576
- }
577
- ensureLocalConfigDir();
578
- const config = getLocalConfig();
579
- config[key] = value;
580
- writeFileSync(localPath, JSON.stringify(config, null, 2));
581
- }
582
- function getLanguage() {
583
- return getConfig().lang;
584
- }
585
- function setLanguage(lang, local = false) {
586
- if (local) {
587
- setLocalConfig("lang", lang);
588
- } else {
589
- setGlobalConfig("lang", lang);
590
- }
591
- }
592
- function getLanguageInstruction(lang) {
593
- switch (lang) {
594
- case "ja":
595
- return "\n\nIMPORTANT: Respond in Japanese (\u65E5\u672C\u8A9E\u3067\u56DE\u7B54\u3057\u3066\u304F\u3060\u3055\u3044).";
596
- case "en":
597
- default:
598
- return "";
599
- }
600
- }
601
681
  export {
602
682
  deleteApiKey,
603
683
  findTemplate,