@within-7/minto 0.3.9 → 0.3.10

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 (141) hide show
  1. package/dist/commands/agents/AgentsCommand.js +459 -655
  2. package/dist/commands/agents/AgentsCommand.js.map +2 -2
  3. package/dist/commands/agents/types.js +1 -0
  4. package/dist/commands/agents/types.js.map +2 -2
  5. package/dist/commands/agents/utils/fileOperations.js +96 -36
  6. package/dist/commands/agents/utils/fileOperations.js.map +3 -3
  7. package/dist/commands/agents/utils/index.js +3 -1
  8. package/dist/commands/agents/utils/index.js.map +2 -2
  9. package/dist/commands/context.js +54 -23
  10. package/dist/commands/context.js.map +2 -2
  11. package/dist/commands/export.js +673 -93
  12. package/dist/commands/export.js.map +2 -2
  13. package/dist/commands/language.js +19 -46
  14. package/dist/commands/language.js.map +2 -2
  15. package/dist/commands/mcp-interactive.js +419 -217
  16. package/dist/commands/mcp-interactive.js.map +2 -2
  17. package/dist/commands/model.js +415 -66
  18. package/dist/commands/model.js.map +2 -2
  19. package/dist/commands/permissions.js +75 -49
  20. package/dist/commands/permissions.js.map +2 -2
  21. package/dist/commands/plugin.js +882 -185
  22. package/dist/commands/plugin.js.map +3 -3
  23. package/dist/commands/resume.js +1 -1
  24. package/dist/commands/resume.js.map +1 -1
  25. package/dist/commands/sandbox.js +168 -70
  26. package/dist/commands/sandbox.js.map +2 -2
  27. package/dist/commands/setup.js +593 -107
  28. package/dist/commands/setup.js.map +2 -2
  29. package/dist/commands/stats.js +188 -131
  30. package/dist/commands/stats.js.map +2 -2
  31. package/dist/commands/status.js +75 -13
  32. package/dist/commands/status.js.map +2 -2
  33. package/dist/commands/undo.js +138 -174
  34. package/dist/commands/undo.js.map +2 -2
  35. package/dist/commands.js.map +1 -1
  36. package/dist/components/Help.js +165 -32
  37. package/dist/components/Help.js.map +2 -2
  38. package/dist/components/InfoPanel/InfoPanel.js +123 -0
  39. package/dist/components/InfoPanel/InfoPanel.js.map +7 -0
  40. package/dist/components/InfoPanel/index.js +5 -0
  41. package/dist/components/InfoPanel/index.js.map +7 -0
  42. package/dist/components/InfoPanel/types.js +1 -0
  43. package/dist/components/InfoPanel/types.js.map +7 -0
  44. package/dist/components/ModelSelector/BrandTextInput.js +43 -0
  45. package/dist/components/ModelSelector/BrandTextInput.js.map +7 -0
  46. package/dist/components/ModelSelector/ModelSelector.js +419 -501
  47. package/dist/components/ModelSelector/ModelSelector.js.map +2 -2
  48. package/dist/components/ModelSelector/WizardContainer.js +45 -0
  49. package/dist/components/ModelSelector/WizardContainer.js.map +7 -0
  50. package/dist/components/ModelSelector/index.js +1 -3
  51. package/dist/components/ModelSelector/index.js.map +2 -2
  52. package/dist/components/PromptInput.js +5 -5
  53. package/dist/components/PromptInput.js.map +2 -2
  54. package/dist/components/SimpleSelector/SimpleSelector.js +154 -0
  55. package/dist/components/SimpleSelector/SimpleSelector.js.map +7 -0
  56. package/dist/components/SimpleSelector/index.js +5 -0
  57. package/dist/components/SimpleSelector/index.js.map +7 -0
  58. package/dist/components/SimpleSelector/types.js +1 -0
  59. package/dist/components/SimpleSelector/types.js.map +7 -0
  60. package/dist/components/StatusOverlayContent.js +21 -0
  61. package/dist/components/StatusOverlayContent.js.map +7 -0
  62. package/dist/components/TabbedListView/ScrollableList.js +31 -5
  63. package/dist/components/TabbedListView/ScrollableList.js.map +2 -2
  64. package/dist/components/TabbedListView/TabbedListView.js +122 -47
  65. package/dist/components/TabbedListView/TabbedListView.js.map +2 -2
  66. package/dist/core/backupHook.js +29 -0
  67. package/dist/core/backupHook.js.map +7 -0
  68. package/dist/core/config/defaults.js +8 -2
  69. package/dist/core/config/defaults.js.map +2 -2
  70. package/dist/core/config/schema.js +14 -2
  71. package/dist/core/config/schema.js.map +2 -2
  72. package/dist/core/costTracker.js +0 -16
  73. package/dist/core/costTracker.js.map +2 -2
  74. package/dist/cost-tracker.js +0 -16
  75. package/dist/cost-tracker.js.map +2 -2
  76. package/dist/entrypoints/bootstrap.js +3 -1
  77. package/dist/entrypoints/bootstrap.js.map +2 -2
  78. package/dist/entrypoints/cli.js +32 -0
  79. package/dist/entrypoints/cli.js.map +2 -2
  80. package/dist/i18n/locales/en.js +300 -1
  81. package/dist/i18n/locales/en.js.map +2 -2
  82. package/dist/i18n/locales/zh-CN.js +301 -2
  83. package/dist/i18n/locales/zh-CN.js.map +2 -2
  84. package/dist/i18n/types.js.map +1 -1
  85. package/dist/services/customCommands.js +30 -8
  86. package/dist/services/customCommands.js.map +2 -2
  87. package/dist/services/plugins/lspServers.js +1 -1
  88. package/dist/services/plugins/lspServers.js.map +2 -2
  89. package/dist/services/plugins/pluginRuntime.js +2 -1
  90. package/dist/services/plugins/pluginRuntime.js.map +2 -2
  91. package/dist/services/plugins/pluginValidation.js +10 -3
  92. package/dist/services/plugins/pluginValidation.js.map +2 -2
  93. package/dist/services/plugins/skillMarketplace.js +16 -8
  94. package/dist/services/plugins/skillMarketplace.js.map +2 -2
  95. package/dist/services/systemReminder.js +17 -6
  96. package/dist/services/systemReminder.js.map +2 -2
  97. package/dist/tools/FileEditTool/FileEditTool.js +7 -0
  98. package/dist/tools/FileEditTool/FileEditTool.js.map +2 -2
  99. package/dist/tools/FileWriteTool/FileWriteTool.js +7 -0
  100. package/dist/tools/FileWriteTool/FileWriteTool.js.map +2 -2
  101. package/dist/tools/MultiEditTool/MultiEditTool.js +7 -0
  102. package/dist/tools/MultiEditTool/MultiEditTool.js.map +2 -2
  103. package/dist/tools/NotebookEditTool/NotebookEditTool.js +2 -0
  104. package/dist/tools/NotebookEditTool/NotebookEditTool.js.map +2 -2
  105. package/dist/tools/TaskTool/TaskTool.js +9 -6
  106. package/dist/tools/TaskTool/TaskTool.js.map +2 -2
  107. package/dist/types/PermissionMode.js.map +1 -1
  108. package/dist/types/plugin.js +2 -4
  109. package/dist/types/plugin.js.map +2 -2
  110. package/dist/utils/agentHookExecutor.js +1 -4
  111. package/dist/utils/agentHookExecutor.js.map +2 -2
  112. package/dist/utils/agentLoader.js +67 -13
  113. package/dist/utils/agentLoader.js.map +2 -2
  114. package/dist/utils/agentMemory.js.map +2 -2
  115. package/dist/utils/claudeCodeSync.js +439 -0
  116. package/dist/utils/claudeCodeSync.js.map +7 -0
  117. package/dist/utils/config.js +1 -23
  118. package/dist/utils/config.js.map +2 -2
  119. package/dist/utils/execFileNoThrow.js +2 -1
  120. package/dist/utils/execFileNoThrow.js.map +2 -2
  121. package/dist/utils/marketplaceManager.js +80 -43
  122. package/dist/utils/marketplaceManager.js.map +2 -2
  123. package/dist/utils/messages.js +2 -2
  124. package/dist/utils/messages.js.map +2 -2
  125. package/dist/utils/pluginInstaller.js +34 -24
  126. package/dist/utils/pluginInstaller.js.map +2 -2
  127. package/dist/utils/pluginLoader.js +48 -25
  128. package/dist/utils/pluginLoader.js.map +2 -2
  129. package/dist/utils/repoFetcher.js +110 -0
  130. package/dist/utils/repoFetcher.js.map +7 -0
  131. package/dist/utils/skillLoader.js +18 -6
  132. package/dist/utils/skillLoader.js.map +2 -2
  133. package/dist/utils/stringSubstitution.js +4 -5
  134. package/dist/utils/stringSubstitution.js.map +2 -2
  135. package/dist/utils/teamConfig.js +153 -13
  136. package/dist/utils/teamConfig.js.map +2 -2
  137. package/dist/utils/terminal.js +1 -1
  138. package/dist/utils/terminal.js.map +2 -2
  139. package/dist/version.js +2 -2
  140. package/dist/version.js.map +1 -1
  141. package/package.json +6 -6
@@ -10,7 +10,7 @@ import {
10
10
  } from "fs";
11
11
  import { join, resolve, isAbsolute } from "path";
12
12
  import { homedir } from "os";
13
- import { execFileNoThrow } from "./execFileNoThrow.js";
13
+ import { fetchRepo } from "./repoFetcher.js";
14
14
  import {
15
15
  MarketplaceManifestSchema,
16
16
  MarketplaceError,
@@ -45,38 +45,13 @@ function saveRegistry(marketplaces) {
45
45
  const registryPath = getRegistryPath();
46
46
  writeFileSync(registryPath, JSON.stringify(marketplaces, null, 2), "utf-8");
47
47
  }
48
- async function cloneGitRepo(url, ref) {
49
- const tempDir = join(getMarketplaceDir(), "temp", Date.now().toString());
50
- mkdirSync(tempDir, { recursive: true });
51
- try {
52
- const args = ["clone", "--depth", "1"];
53
- if (ref) {
54
- args.push("--branch", ref);
55
- }
56
- args.push(url, tempDir);
57
- const result = await execFileNoThrow("git", args);
58
- if (result.code !== 0) {
59
- throw new Error(`Git clone failed: ${result.stderr || result.stdout}`);
60
- }
61
- return tempDir;
62
- } catch (error) {
63
- try {
64
- rmSync(tempDir, { recursive: true, force: true });
65
- } catch (cleanupError) {
66
- }
67
- throw new MarketplaceError(
68
- `Failed to clone repository: ${error instanceof Error ? error.message : String(error)}`,
69
- MarketplaceErrorCode.GIT_ERROR,
70
- void 0,
71
- error
72
- );
73
- }
74
- }
75
48
  function loadManifestFromDirectory(dir) {
76
- const manifestPath = join(dir, ".minto-plugin", "marketplace.json");
77
- if (!existsSync(manifestPath)) {
49
+ const mintoPath = join(dir, ".minto-plugin", "marketplace.json");
50
+ const claudePath = join(dir, ".claude-plugin", "marketplace.json");
51
+ const manifestPath = existsSync(mintoPath) ? mintoPath : existsSync(claudePath) ? claudePath : null;
52
+ if (!manifestPath) {
78
53
  throw new MarketplaceError(
79
- `Marketplace manifest not found at ${manifestPath}`,
54
+ `Marketplace manifest not found (checked .minto-plugin/ and .claude-plugin/ in ${dir})`,
80
55
  MarketplaceErrorCode.MANIFEST_NOT_FOUND
81
56
  );
82
57
  }
@@ -94,10 +69,18 @@ function loadManifestFromDirectory(dir) {
94
69
  }
95
70
  }
96
71
  async function fetchGitHubMarketplace(repo, ref) {
97
- const url = `https://github.com/${repo}.git`;
98
- const tempDir = await cloneGitRepo(url, ref);
72
+ const tempDir = join(getMarketplaceDir(), "temp", Date.now().toString());
73
+ mkdirSync(tempDir, { recursive: true });
99
74
  try {
75
+ await fetchRepo({ type: "github", repo, ref }, tempDir);
100
76
  return loadManifestFromDirectory(tempDir);
77
+ } catch (error) {
78
+ throw new MarketplaceError(
79
+ `Failed to fetch repository: ${error instanceof Error ? error.message : String(error)}`,
80
+ MarketplaceErrorCode.GIT_ERROR,
81
+ void 0,
82
+ error
83
+ );
101
84
  } finally {
102
85
  try {
103
86
  rmSync(tempDir, { recursive: true, force: true });
@@ -106,9 +89,18 @@ async function fetchGitHubMarketplace(repo, ref) {
106
89
  }
107
90
  }
108
91
  async function fetchUrlMarketplace(url, ref) {
109
- const tempDir = await cloneGitRepo(url, ref);
92
+ const tempDir = join(getMarketplaceDir(), "temp", Date.now().toString());
93
+ mkdirSync(tempDir, { recursive: true });
110
94
  try {
95
+ await fetchRepo({ type: "url", url, ref }, tempDir);
111
96
  return loadManifestFromDirectory(tempDir);
97
+ } catch (error) {
98
+ throw new MarketplaceError(
99
+ `Failed to fetch repository: ${error instanceof Error ? error.message : String(error)}`,
100
+ MarketplaceErrorCode.GIT_ERROR,
101
+ void 0,
102
+ error
103
+ );
112
104
  } finally {
113
105
  try {
114
106
  rmSync(tempDir, { recursive: true, force: true });
@@ -120,6 +112,24 @@ function loadLocalMarketplace(path) {
120
112
  const resolvedPath = path.startsWith("/") ? path : join(getCwd(), path);
121
113
  return loadManifestFromDirectory(resolvedPath);
122
114
  }
115
+ function isMarketplaceRegistered(name) {
116
+ return loadRegistry().some((m) => m.name === name);
117
+ }
118
+ function registerMarketplaceFromDirectory(name, source, localDir) {
119
+ const registry = loadRegistry();
120
+ if (registry.some((m) => m.name === name)) return null;
121
+ const manifest = loadManifestFromDirectory(localDir);
122
+ const registered = {
123
+ name: manifest.name,
124
+ source,
125
+ manifest,
126
+ lastUpdated: /* @__PURE__ */ new Date(),
127
+ enabled: true
128
+ };
129
+ registry.push(registered);
130
+ saveRegistry(registry);
131
+ return registered;
132
+ }
123
133
  function parseMarketplaceSource(input) {
124
134
  if (/^[\w-]+\/[\w-]+$/.test(input)) {
125
135
  return { type: "github", repo: input };
@@ -243,7 +253,9 @@ function loadMarketplaceSettings() {
243
253
  const home = homedir();
244
254
  const settingsPaths = [
245
255
  { path: join(cwd, ".minto", "settings.json"), label: "project" },
246
- { path: join(home, ".minto", "settings.json"), label: "user" }
256
+ { path: join(cwd, ".claude", "settings.json"), label: "project/.claude" },
257
+ { path: join(home, ".minto", "settings.json"), label: "user" },
258
+ { path: join(home, ".claude", "settings.json"), label: "user/.claude" }
247
259
  ];
248
260
  for (const { path, label } of settingsPaths) {
249
261
  if (existsSync(path)) {
@@ -312,14 +324,28 @@ async function autoRegisterMarketplaces() {
312
324
  async function getMarketplaceRepoPath(marketplace) {
313
325
  switch (marketplace.source.type) {
314
326
  case "github": {
315
- const url = `https://github.com/${marketplace.source.repo}.git`;
316
- const tempDir = await cloneGitRepo(url, marketplace.source.ref);
327
+ const tempDir = join(getMarketplaceDir(), "temp", Date.now().toString());
328
+ mkdirSync(tempDir, { recursive: true });
329
+ await fetchRepo(
330
+ {
331
+ type: "github",
332
+ repo: marketplace.source.repo,
333
+ ref: marketplace.source.ref
334
+ },
335
+ tempDir
336
+ );
317
337
  return { path: tempDir, cleanup: true };
318
338
  }
319
339
  case "url": {
320
- const tempDir = await cloneGitRepo(
321
- marketplace.source.url,
322
- marketplace.source.ref
340
+ const tempDir = join(getMarketplaceDir(), "temp", Date.now().toString());
341
+ mkdirSync(tempDir, { recursive: true });
342
+ await fetchRepo(
343
+ {
344
+ type: "url",
345
+ url: marketplace.source.url,
346
+ ref: marketplace.source.ref
347
+ },
348
+ tempDir
323
349
  );
324
350
  return { path: tempDir, cleanup: true };
325
351
  }
@@ -426,16 +452,25 @@ async function installPluginFromMarketplace(pluginName, marketplaceName, targetD
426
452
  }
427
453
  copyDirectory(pluginSourcePath, installDir);
428
454
  } else if (plugin.source.source === "github") {
429
- const url = `https://github.com/${plugin.source.repo}.git`;
430
- const tempDir = await cloneGitRepo(url, plugin.source.ref);
455
+ const tempDir = join(getMarketplaceDir(), "temp", Date.now().toString());
456
+ mkdirSync(tempDir, { recursive: true });
431
457
  try {
458
+ await fetchRepo(
459
+ { type: "github", repo: plugin.source.repo, ref: plugin.source.ref },
460
+ tempDir
461
+ );
432
462
  copyDirectory(tempDir, installDir);
433
463
  } finally {
434
464
  rmSync(tempDir, { recursive: true, force: true });
435
465
  }
436
466
  } else if (plugin.source.source === "url") {
437
- const tempDir = await cloneGitRepo(plugin.source.url, plugin.source.ref);
467
+ const tempDir = join(getMarketplaceDir(), "temp", Date.now().toString());
468
+ mkdirSync(tempDir, { recursive: true });
438
469
  try {
470
+ await fetchRepo(
471
+ { type: "url", url: plugin.source.url, ref: plugin.source.ref },
472
+ tempDir
473
+ );
439
474
  copyDirectory(tempDir, installDir);
440
475
  } finally {
441
476
  rmSync(tempDir, { recursive: true, force: true });
@@ -499,9 +534,11 @@ export {
499
534
  findPlugin,
500
535
  getMarketplace,
501
536
  installPluginFromMarketplace,
537
+ isMarketplaceRegistered,
502
538
  listMarketplaces,
503
539
  loadMarketplaceSettings,
504
540
  parseMarketplaceSource,
541
+ registerMarketplaceFromDirectory,
505
542
  removeMarketplace,
506
543
  updateMarketplace
507
544
  };
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/utils/marketplaceManager.ts"],
4
- "sourcesContent": ["/**\n * Marketplace Manager\n *\n * Manages plugin marketplaces including registration, updates, and plugin installation\n * from git-based marketplace sources.\n */\n\nimport {\n existsSync,\n readFileSync,\n writeFileSync,\n mkdirSync,\n rmSync,\n cpSync,\n symlinkSync,\n lstatSync,\n} from 'fs'\nimport { join, resolve, isAbsolute } from 'path'\nimport { homedir } from 'os'\nimport { execFileNoThrow } from './execFileNoThrow'\nimport {\n MarketplaceManifest,\n MarketplaceManifestSchema,\n MarketplaceSource,\n RegisteredMarketplace,\n MarketplaceSettings,\n MarketplaceError,\n MarketplaceErrorCode,\n MarketplacePlugin,\n} from '../types/marketplace'\nimport { getCwd } from './state'\n\n/**\n * Get marketplace storage directory\n */\nfunction getMarketplaceDir(): string {\n const home = homedir()\n const dir = join(home, '.minto', 'marketplaces')\n\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true })\n }\n\n return dir\n}\n\n/**\n * Get marketplace registry file path\n */\nfunction getRegistryPath(): string {\n return join(getMarketplaceDir(), 'registry.json')\n}\n\n/**\n * Load marketplace registry\n */\nfunction loadRegistry(): RegisteredMarketplace[] {\n const registryPath = getRegistryPath()\n\n if (!existsSync(registryPath)) {\n return []\n }\n\n try {\n const content = readFileSync(registryPath, 'utf-8')\n return JSON.parse(content)\n } catch (error) {\n console.error('Error loading marketplace registry:', error)\n return []\n }\n}\n\n/**\n * Save marketplace registry\n */\nfunction saveRegistry(marketplaces: RegisteredMarketplace[]): void {\n const registryPath = getRegistryPath()\n writeFileSync(registryPath, JSON.stringify(marketplaces, null, 2), 'utf-8')\n}\n\n/**\n * Clone git repository to temporary location using safe execFile\n */\nasync function cloneGitRepo(url: string, ref?: string): Promise<string> {\n const tempDir = join(getMarketplaceDir(), 'temp', Date.now().toString())\n mkdirSync(tempDir, { recursive: true })\n\n try {\n // Build git clone arguments safely\n const args = ['clone', '--depth', '1']\n\n if (ref) {\n args.push('--branch', ref)\n }\n\n args.push(url, tempDir)\n\n // Clone repository using safe execFile\n const result = await execFileNoThrow('git', args)\n\n if (result.code !== 0) {\n throw new Error(`Git clone failed: ${result.stderr || result.stdout}`)\n }\n\n return tempDir\n } catch (error) {\n // Clean up on error\n try {\n rmSync(tempDir, { recursive: true, force: true })\n } catch (cleanupError) {\n // Ignore cleanup errors\n }\n\n throw new MarketplaceError(\n `Failed to clone repository: ${error instanceof Error ? error.message : String(error)}`,\n MarketplaceErrorCode.GIT_ERROR,\n undefined,\n error,\n )\n }\n}\n\n/**\n * Load marketplace manifest from directory\n */\nfunction loadManifestFromDirectory(dir: string): MarketplaceManifest {\n const manifestPath = join(dir, '.minto-plugin', 'marketplace.json')\n\n if (!existsSync(manifestPath)) {\n throw new MarketplaceError(\n `Marketplace manifest not found at ${manifestPath}`,\n MarketplaceErrorCode.MANIFEST_NOT_FOUND,\n )\n }\n\n try {\n const content = readFileSync(manifestPath, 'utf-8')\n const data = JSON.parse(content)\n\n // Validate with Zod schema\n return MarketplaceManifestSchema.parse(data)\n } catch (error) {\n throw new MarketplaceError(\n `Invalid marketplace manifest: ${error instanceof Error ? error.message : String(error)}`,\n MarketplaceErrorCode.MANIFEST_INVALID,\n undefined,\n error,\n )\n }\n}\n\n/**\n * Fetch marketplace manifest from GitHub\n */\nasync function fetchGitHubMarketplace(\n repo: string,\n ref?: string,\n): Promise<MarketplaceManifest> {\n const url = `https://github.com/${repo}.git`\n const tempDir = await cloneGitRepo(url, ref)\n\n try {\n return loadManifestFromDirectory(tempDir)\n } finally {\n // Clean up temp directory\n try {\n rmSync(tempDir, { recursive: true, force: true })\n } catch (e) {\n // Ignore cleanup errors\n }\n }\n}\n\n/**\n * Fetch marketplace manifest from git URL\n */\nasync function fetchUrlMarketplace(\n url: string,\n ref?: string,\n): Promise<MarketplaceManifest> {\n const tempDir = await cloneGitRepo(url, ref)\n\n try {\n return loadManifestFromDirectory(tempDir)\n } finally {\n // Clean up temp directory\n try {\n rmSync(tempDir, { recursive: true, force: true })\n } catch (e) {\n // Ignore cleanup errors\n }\n }\n}\n\n/**\n * Load marketplace manifest from local path\n */\nfunction loadLocalMarketplace(path: string): MarketplaceManifest {\n const resolvedPath = path.startsWith('/') ? path : join(getCwd(), path)\n return loadManifestFromDirectory(resolvedPath)\n}\n\n/**\n * Parse marketplace source from string input\n */\nexport function parseMarketplaceSource(input: string): MarketplaceSource {\n // GitHub shorthand: owner/repo\n if (/^[\\w-]+\\/[\\w-]+$/.test(input)) {\n return { type: 'github', repo: input }\n }\n\n // GitHub URL\n if (input.includes('github.com')) {\n const match = input.match(/github\\.com[/:]([\\w-]+\\/[\\w-]+)/)\n if (match) {\n return { type: 'github', repo: match[1] }\n }\n }\n\n // Git URL\n if (\n input.startsWith('http://') ||\n input.startsWith('https://') ||\n input.endsWith('.git')\n ) {\n return { type: 'url', url: input }\n }\n\n // Local path\n return { type: 'local', path: input }\n}\n\n/**\n * Add/register a marketplace\n */\nexport async function addMarketplace(\n input: string,\n): Promise<RegisteredMarketplace> {\n const source = parseMarketplaceSource(input)\n\n // Fetch manifest based on source type\n let manifest: MarketplaceManifest\n\n switch (source.type) {\n case 'github':\n manifest = await fetchGitHubMarketplace(source.repo, source.ref)\n break\n case 'url':\n manifest = await fetchUrlMarketplace(source.url, source.ref)\n break\n case 'local':\n manifest = loadLocalMarketplace(source.path)\n break\n }\n\n // Check if already registered\n const registry = loadRegistry()\n if (registry.some(m => m.name === manifest.name)) {\n throw new MarketplaceError(\n `Marketplace \"${manifest.name}\" is already registered`,\n MarketplaceErrorCode.ALREADY_REGISTERED,\n manifest.name,\n )\n }\n\n // Create registered marketplace\n const registered: RegisteredMarketplace = {\n name: manifest.name,\n source,\n manifest,\n lastUpdated: new Date(),\n enabled: true,\n }\n\n // Save to registry\n registry.push(registered)\n saveRegistry(registry)\n\n return registered\n}\n\n/**\n * Remove a marketplace\n */\nexport function removeMarketplace(name: string): void {\n const registry = loadRegistry()\n const filtered = registry.filter(m => m.name !== name)\n\n if (filtered.length === registry.length) {\n throw new MarketplaceError(\n `Marketplace \"${name}\" is not registered`,\n MarketplaceErrorCode.NOT_REGISTERED,\n name,\n )\n }\n\n saveRegistry(filtered)\n}\n\n/**\n * Update a marketplace (re-fetch manifest)\n */\nexport async function updateMarketplace(\n name: string,\n): Promise<RegisteredMarketplace> {\n const registry = loadRegistry()\n const marketplace = registry.find(m => m.name === name)\n\n if (!marketplace) {\n throw new MarketplaceError(\n `Marketplace \"${name}\" is not registered`,\n MarketplaceErrorCode.NOT_REGISTERED,\n name,\n )\n }\n\n // Re-fetch manifest\n let manifest: MarketplaceManifest\n\n switch (marketplace.source.type) {\n case 'github':\n manifest = await fetchGitHubMarketplace(\n marketplace.source.repo,\n marketplace.source.ref,\n )\n break\n case 'url':\n manifest = await fetchUrlMarketplace(\n marketplace.source.url,\n marketplace.source.ref,\n )\n break\n case 'local':\n manifest = loadLocalMarketplace(marketplace.source.path)\n break\n }\n\n // Update in registry\n marketplace.manifest = manifest\n marketplace.lastUpdated = new Date()\n\n saveRegistry(registry)\n\n return marketplace\n}\n\n/**\n * List all registered marketplaces\n */\nexport function listMarketplaces(): RegisteredMarketplace[] {\n return loadRegistry()\n}\n\n/**\n * Get a specific marketplace\n */\nexport function getMarketplace(\n name: string,\n): RegisteredMarketplace | undefined {\n const registry = loadRegistry()\n return registry.find(m => m.name === name)\n}\n\n/**\n * Find plugin in marketplaces\n */\nexport function findPlugin(\n pluginName: string,\n marketplaceName?: string,\n):\n | {\n marketplace: RegisteredMarketplace\n plugin: MarketplacePlugin\n }\n | undefined {\n const registry = loadRegistry()\n\n // Search in specific marketplace\n if (marketplaceName) {\n const marketplace = registry.find(m => m.name === marketplaceName)\n if (!marketplace) return undefined\n\n const plugin = marketplace.manifest.plugins.find(p => p.name === pluginName)\n if (!plugin) return undefined\n\n return { marketplace, plugin }\n }\n\n // Search in all marketplaces\n for (const marketplace of registry) {\n if (!marketplace.enabled) continue\n\n const plugin = marketplace.manifest.plugins.find(p => p.name === pluginName)\n if (plugin) {\n return { marketplace, plugin }\n }\n }\n\n return undefined\n}\n\n/**\n * Load marketplace settings with hierarchical priority\n * Priority (highest to lowest):\n * 1. Project .minto/settings.json\n * 2. User ~/.minto/settings.json\n */\nexport function loadMarketplaceSettings(): MarketplaceSettings {\n const cwd = getCwd()\n const home = homedir()\n\n // Define search paths in priority order\n const settingsPaths = [\n { path: join(cwd, '.minto', 'settings.json'), label: 'project' },\n { path: join(home, '.minto', 'settings.json'), label: 'user' },\n ]\n\n // Try loading from each path in priority order\n for (const { path, label } of settingsPaths) {\n if (existsSync(path)) {\n try {\n const content = readFileSync(path, 'utf-8')\n const settings = JSON.parse(content)\n // Optional: log which settings file was used for debugging\n // console.log(`Loaded marketplace settings from ${label}: ${path}`)\n return settings\n } catch (error) {\n console.error(\n `Error loading marketplace settings from ${label} (${path}):`,\n error,\n )\n // Continue to next path on error\n }\n }\n }\n\n // No settings found\n return {}\n}\n\n/**\n * Auto-register marketplaces from settings\n */\nexport async function autoRegisterMarketplaces(): Promise<void> {\n const settings = loadMarketplaceSettings()\n\n if (!settings.extraKnownMarketplaces) return\n\n const registry = loadRegistry()\n\n for (const [name, config] of Object.entries(\n settings.extraKnownMarketplaces,\n )) {\n // Skip if already registered\n if (registry.some(m => m.name === name)) continue\n\n try {\n let source: MarketplaceSource\n\n if (config.source.source === 'github' && config.source.repo) {\n source = {\n type: 'github',\n repo: config.source.repo,\n ref: config.source.ref,\n }\n } else if (config.source.source === 'url' && config.source.url) {\n source = { type: 'url', url: config.source.url, ref: config.source.ref }\n } else if (config.source.source === 'local' && config.source.path) {\n source = { type: 'local', path: config.source.path }\n } else {\n continue\n }\n\n // Fetch and register\n let manifest: MarketplaceManifest\n\n switch (source.type) {\n case 'github':\n manifest = await fetchGitHubMarketplace(source.repo, source.ref)\n break\n case 'url':\n manifest = await fetchUrlMarketplace(source.url, source.ref)\n break\n case 'local':\n manifest = loadLocalMarketplace(source.path)\n break\n }\n\n registry.push({\n name: manifest.name,\n source,\n manifest,\n lastUpdated: new Date(),\n enabled: true,\n })\n } catch (error) {\n console.error(`Error auto-registering marketplace ${name}:`, error)\n }\n }\n\n saveRegistry(registry)\n}\n\n/**\n * Get marketplace repository directory path\n * For cloned marketplaces, returns the temp directory path\n * For local marketplaces, returns the local path\n */\nasync function getMarketplaceRepoPath(\n marketplace: RegisteredMarketplace,\n): Promise<{ path: string; cleanup: boolean }> {\n switch (marketplace.source.type) {\n case 'github': {\n const url = `https://github.com/${marketplace.source.repo}.git`\n const tempDir = await cloneGitRepo(url, marketplace.source.ref)\n return { path: tempDir, cleanup: true }\n }\n case 'url': {\n const tempDir = await cloneGitRepo(\n marketplace.source.url,\n marketplace.source.ref,\n )\n return { path: tempDir, cleanup: true }\n }\n case 'local': {\n const resolvedPath = isAbsolute(marketplace.source.path)\n ? marketplace.source.path\n : resolve(getCwd(), marketplace.source.path)\n\n if (!existsSync(resolvedPath)) {\n throw new MarketplaceError(\n `Local marketplace path does not exist: ${resolvedPath}`,\n MarketplaceErrorCode.MANIFEST_NOT_FOUND,\n )\n }\n\n return { path: resolvedPath, cleanup: false }\n }\n }\n}\n\n/**\n * Copy directory contents recursively\n */\nfunction copyDirectory(sourcePath: string, destPath: string): void {\n try {\n // Create destination directory if it doesn't exist\n if (!existsSync(destPath)) {\n mkdirSync(destPath, { recursive: true })\n }\n\n // Copy recursively, excluding .git directories\n cpSync(sourcePath, destPath, {\n recursive: true,\n filter: src => {\n // Skip .git directories to avoid copying version control history\n return !src.includes('/.git/') && !src.endsWith('/.git')\n },\n })\n } catch (error) {\n throw new MarketplaceError(\n `Failed to copy directory from ${sourcePath} to ${destPath}: ${error instanceof Error ? error.message : String(error)}`,\n MarketplaceErrorCode.GIT_ERROR,\n undefined,\n error,\n )\n }\n}\n\n/**\n * Create symlink to directory\n */\nfunction symlinkDirectory(sourcePath: string, destPath: string): void {\n try {\n // Remove destination if it exists\n if (existsSync(destPath)) {\n // Check if it's already a symlink pointing to the right place\n try {\n const stats = lstatSync(destPath)\n if (stats.isSymbolicLink()) {\n // Already a symlink, remove it\n rmSync(destPath, { force: true })\n } else {\n throw new MarketplaceError(\n `Destination path already exists and is not a symlink: ${destPath}`,\n MarketplaceErrorCode.GIT_ERROR,\n )\n }\n } catch (error) {\n throw new MarketplaceError(\n `Failed to check existing path: ${error instanceof Error ? error.message : String(error)}`,\n MarketplaceErrorCode.GIT_ERROR,\n undefined,\n error,\n )\n }\n } else {\n // Create parent directory\n const parentDir = join(destPath, '..')\n if (!existsSync(parentDir)) {\n mkdirSync(parentDir, { recursive: true })\n }\n }\n\n // Create symlink\n symlinkSync(sourcePath, destPath, 'dir')\n } catch (error) {\n throw new MarketplaceError(\n `Failed to create symlink from ${sourcePath} to ${destPath}: ${error instanceof Error ? error.message : String(error)}`,\n MarketplaceErrorCode.GIT_ERROR,\n undefined,\n error,\n )\n }\n}\n\n/**\n * Install plugin from marketplace\n */\nexport async function installPluginFromMarketplace(\n pluginName: string,\n marketplaceName?: string,\n targetDir?: string,\n options?: { dev?: boolean },\n): Promise<string> {\n const found = findPlugin(pluginName, marketplaceName)\n\n if (!found) {\n throw new MarketplaceError(\n marketplaceName\n ? `Plugin \"${pluginName}\" not found in marketplace \"${marketplaceName}\"`\n : `Plugin \"${pluginName}\" not found in any marketplace`,\n MarketplaceErrorCode.PLUGIN_NOT_FOUND,\n )\n }\n\n const { marketplace, plugin } = found\n\n // Determine installation directory\n const installDir =\n targetDir || join(getCwd(), '.minto', 'plugins', plugin.name)\n\n // Create installation directory\n if (!existsSync(installDir)) {\n mkdirSync(installDir, { recursive: true })\n }\n\n let cleanupMarketplaceRepo = false\n let marketplaceRepoPath: string | undefined\n\n try {\n // Install plugin based on source type\n if (typeof plugin.source === 'string') {\n // Relative path - resolve from marketplace source\n const repoInfo = await getMarketplaceRepoPath(marketplace)\n marketplaceRepoPath = repoInfo.path\n cleanupMarketplaceRepo = repoInfo.cleanup\n\n // Determine base path for relative plugin sources\n const pluginRoot = marketplace.manifest.metadata?.pluginRoot || ''\n const pluginSourcePath = join(\n marketplaceRepoPath,\n pluginRoot,\n plugin.source,\n )\n\n if (!existsSync(pluginSourcePath)) {\n throw new MarketplaceError(\n `Plugin source path does not exist: ${pluginSourcePath} (relative path: ${plugin.source})`,\n MarketplaceErrorCode.PLUGIN_NOT_FOUND,\n )\n }\n\n // Copy plugin files to installation directory\n copyDirectory(pluginSourcePath, installDir)\n } else if (plugin.source.source === 'github') {\n // GitHub repository - clone directly\n const url = `https://github.com/${plugin.source.repo}.git`\n const tempDir = await cloneGitRepo(url, plugin.source.ref)\n\n try {\n copyDirectory(tempDir, installDir)\n } finally {\n // Clean up temp directory\n rmSync(tempDir, { recursive: true, force: true })\n }\n } else if (plugin.source.source === 'url') {\n // Git URL - clone directly\n const tempDir = await cloneGitRepo(plugin.source.url, plugin.source.ref)\n\n try {\n copyDirectory(tempDir, installDir)\n } finally {\n // Clean up temp directory\n rmSync(tempDir, { recursive: true, force: true })\n }\n } else if (plugin.source.source === 'local') {\n // Local path - resolve and copy or symlink\n const pluginSourcePath = isAbsolute(plugin.source.path)\n ? plugin.source.path\n : resolve(getCwd(), plugin.source.path)\n\n if (!existsSync(pluginSourcePath)) {\n throw new MarketplaceError(\n `Local plugin path does not exist: ${pluginSourcePath}`,\n MarketplaceErrorCode.PLUGIN_NOT_FOUND,\n )\n }\n\n // In dev mode, create symlink for easier development\n // In production mode, copy files for isolation\n if (options?.dev) {\n symlinkDirectory(pluginSourcePath, installDir)\n } else {\n copyDirectory(pluginSourcePath, installDir)\n }\n }\n\n // Create marketplace metadata file to track source\n const metadataPath = join(installDir, '.marketplace-meta.json')\n const metadata = {\n marketplace: marketplace.name,\n plugin: plugin.name,\n installedAt: new Date().toISOString(),\n source: plugin.source,\n }\n writeFileSync(metadataPath, JSON.stringify(metadata, null, 2), 'utf-8')\n\n // Create plugin.json if it doesn't exist (required for plugin discovery)\n const pluginManifestPath = join(installDir, 'plugin.json')\n if (!existsSync(pluginManifestPath)) {\n const pluginManifest = {\n name: plugin.name,\n displayName: plugin.name, // Use name as displayName for marketplace plugins\n version: plugin.version || '1.0.0',\n description: plugin.description || '',\n author: plugin.author,\n license: plugin.license,\n homepage: plugin.homepage,\n repository: plugin.repository,\n keywords: plugin.keywords || [],\n category: plugin.category,\n }\n writeFileSync(\n pluginManifestPath,\n JSON.stringify(pluginManifest, null, 2),\n 'utf-8',\n )\n }\n\n return installDir\n } finally {\n // Clean up marketplace repo if it was cloned\n if (cleanupMarketplaceRepo && marketplaceRepoPath) {\n try {\n rmSync(marketplaceRepoPath, { recursive: true, force: true })\n } catch (error) {\n // Ignore cleanup errors\n }\n }\n }\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["/**\n * Marketplace Manager\n *\n * Manages plugin marketplaces including registration, updates, and plugin installation\n * from git-based marketplace sources.\n */\n\nimport {\n existsSync,\n readFileSync,\n writeFileSync,\n mkdirSync,\n rmSync,\n cpSync,\n symlinkSync,\n lstatSync,\n} from 'fs'\nimport { join, resolve, isAbsolute } from 'path'\nimport { homedir } from 'os'\nimport { fetchRepo } from './repoFetcher'\nimport {\n MarketplaceManifest,\n MarketplaceManifestSchema,\n MarketplaceSource,\n RegisteredMarketplace,\n MarketplaceSettings,\n MarketplaceError,\n MarketplaceErrorCode,\n MarketplacePlugin,\n} from '../types/marketplace'\nimport { getCwd } from './state'\n\n/**\n * Get marketplace storage directory\n */\nfunction getMarketplaceDir(): string {\n const home = homedir()\n const dir = join(home, '.minto', 'marketplaces')\n\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true })\n }\n\n return dir\n}\n\n/**\n * Get marketplace registry file path\n */\nfunction getRegistryPath(): string {\n return join(getMarketplaceDir(), 'registry.json')\n}\n\n/**\n * Load marketplace registry\n */\nfunction loadRegistry(): RegisteredMarketplace[] {\n const registryPath = getRegistryPath()\n\n if (!existsSync(registryPath)) {\n return []\n }\n\n try {\n const content = readFileSync(registryPath, 'utf-8')\n return JSON.parse(content)\n } catch (error) {\n console.error('Error loading marketplace registry:', error)\n return []\n }\n}\n\n/**\n * Save marketplace registry\n */\nfunction saveRegistry(marketplaces: RegisteredMarketplace[]): void {\n const registryPath = getRegistryPath()\n writeFileSync(registryPath, JSON.stringify(marketplaces, null, 2), 'utf-8')\n}\n\n/**\n * Load marketplace manifest from directory\n */\nfunction loadManifestFromDirectory(dir: string): MarketplaceManifest {\n // Support both .minto-plugin (current) and .claude-plugin (legacy) directory names\n const mintoPath = join(dir, '.minto-plugin', 'marketplace.json')\n const claudePath = join(dir, '.claude-plugin', 'marketplace.json')\n const manifestPath = existsSync(mintoPath)\n ? mintoPath\n : existsSync(claudePath)\n ? claudePath\n : null\n\n if (!manifestPath) {\n throw new MarketplaceError(\n `Marketplace manifest not found (checked .minto-plugin/ and .claude-plugin/ in ${dir})`,\n MarketplaceErrorCode.MANIFEST_NOT_FOUND,\n )\n }\n\n try {\n const content = readFileSync(manifestPath, 'utf-8')\n const data = JSON.parse(content)\n\n // Validate with Zod schema\n return MarketplaceManifestSchema.parse(data)\n } catch (error) {\n throw new MarketplaceError(\n `Invalid marketplace manifest: ${error instanceof Error ? error.message : String(error)}`,\n MarketplaceErrorCode.MANIFEST_INVALID,\n undefined,\n error,\n )\n }\n}\n\n/**\n * Fetch marketplace manifest from GitHub\n */\nasync function fetchGitHubMarketplace(\n repo: string,\n ref?: string,\n): Promise<MarketplaceManifest> {\n const tempDir = join(getMarketplaceDir(), 'temp', Date.now().toString())\n mkdirSync(tempDir, { recursive: true })\n\n try {\n await fetchRepo({ type: 'github', repo, ref }, tempDir)\n return loadManifestFromDirectory(tempDir)\n } catch (error) {\n throw new MarketplaceError(\n `Failed to fetch repository: ${error instanceof Error ? error.message : String(error)}`,\n MarketplaceErrorCode.GIT_ERROR,\n undefined,\n error,\n )\n } finally {\n try {\n rmSync(tempDir, { recursive: true, force: true })\n } catch (e) {\n // Ignore cleanup errors\n }\n }\n}\n\n/**\n * Fetch marketplace manifest from git URL\n */\nasync function fetchUrlMarketplace(\n url: string,\n ref?: string,\n): Promise<MarketplaceManifest> {\n const tempDir = join(getMarketplaceDir(), 'temp', Date.now().toString())\n mkdirSync(tempDir, { recursive: true })\n\n try {\n await fetchRepo({ type: 'url', url, ref }, tempDir)\n return loadManifestFromDirectory(tempDir)\n } catch (error) {\n throw new MarketplaceError(\n `Failed to fetch repository: ${error instanceof Error ? error.message : String(error)}`,\n MarketplaceErrorCode.GIT_ERROR,\n undefined,\n error,\n )\n } finally {\n try {\n rmSync(tempDir, { recursive: true, force: true })\n } catch (e) {\n // Ignore cleanup errors\n }\n }\n}\n\n/**\n * Load marketplace manifest from local path\n */\nfunction loadLocalMarketplace(path: string): MarketplaceManifest {\n const resolvedPath = path.startsWith('/') ? path : join(getCwd(), path)\n return loadManifestFromDirectory(resolvedPath)\n}\n\n/**\n * Check if a marketplace is already registered by name\n */\nexport function isMarketplaceRegistered(name: string): boolean {\n return loadRegistry().some(m => m.name === name)\n}\n\n/**\n * Register a marketplace from a local directory containing a marketplace manifest.\n * Returns the registered marketplace, or null if already registered.\n */\nexport function registerMarketplaceFromDirectory(\n name: string,\n source: MarketplaceSource,\n localDir: string,\n): RegisteredMarketplace | null {\n const registry = loadRegistry()\n if (registry.some(m => m.name === name)) return null // already registered\n\n const manifest = loadManifestFromDirectory(localDir)\n const registered: RegisteredMarketplace = {\n name: manifest.name,\n source,\n manifest,\n lastUpdated: new Date(),\n enabled: true,\n }\n\n registry.push(registered)\n saveRegistry(registry)\n return registered\n}\n\n/**\n * Parse marketplace source from string input\n */\nexport function parseMarketplaceSource(input: string): MarketplaceSource {\n // GitHub shorthand: owner/repo\n if (/^[\\w-]+\\/[\\w-]+$/.test(input)) {\n return { type: 'github', repo: input }\n }\n\n // GitHub URL\n if (input.includes('github.com')) {\n const match = input.match(/github\\.com[/:]([\\w-]+\\/[\\w-]+)/)\n if (match) {\n return { type: 'github', repo: match[1] }\n }\n }\n\n // Git URL\n if (\n input.startsWith('http://') ||\n input.startsWith('https://') ||\n input.endsWith('.git')\n ) {\n return { type: 'url', url: input }\n }\n\n // Local path\n return { type: 'local', path: input }\n}\n\n/**\n * Add/register a marketplace\n */\nexport async function addMarketplace(\n input: string,\n): Promise<RegisteredMarketplace> {\n const source = parseMarketplaceSource(input)\n\n // Fetch manifest based on source type\n let manifest: MarketplaceManifest\n\n switch (source.type) {\n case 'github':\n manifest = await fetchGitHubMarketplace(source.repo, source.ref)\n break\n case 'url':\n manifest = await fetchUrlMarketplace(source.url, source.ref)\n break\n case 'local':\n manifest = loadLocalMarketplace(source.path)\n break\n }\n\n // Check if already registered\n const registry = loadRegistry()\n if (registry.some(m => m.name === manifest.name)) {\n throw new MarketplaceError(\n `Marketplace \"${manifest.name}\" is already registered`,\n MarketplaceErrorCode.ALREADY_REGISTERED,\n manifest.name,\n )\n }\n\n // Create registered marketplace\n const registered: RegisteredMarketplace = {\n name: manifest.name,\n source,\n manifest,\n lastUpdated: new Date(),\n enabled: true,\n }\n\n // Save to registry\n registry.push(registered)\n saveRegistry(registry)\n\n return registered\n}\n\n/**\n * Remove a marketplace\n */\nexport function removeMarketplace(name: string): void {\n const registry = loadRegistry()\n const filtered = registry.filter(m => m.name !== name)\n\n if (filtered.length === registry.length) {\n throw new MarketplaceError(\n `Marketplace \"${name}\" is not registered`,\n MarketplaceErrorCode.NOT_REGISTERED,\n name,\n )\n }\n\n saveRegistry(filtered)\n}\n\n/**\n * Update a marketplace (re-fetch manifest)\n */\nexport async function updateMarketplace(\n name: string,\n): Promise<RegisteredMarketplace> {\n const registry = loadRegistry()\n const marketplace = registry.find(m => m.name === name)\n\n if (!marketplace) {\n throw new MarketplaceError(\n `Marketplace \"${name}\" is not registered`,\n MarketplaceErrorCode.NOT_REGISTERED,\n name,\n )\n }\n\n // Re-fetch manifest\n let manifest: MarketplaceManifest\n\n switch (marketplace.source.type) {\n case 'github':\n manifest = await fetchGitHubMarketplace(\n marketplace.source.repo,\n marketplace.source.ref,\n )\n break\n case 'url':\n manifest = await fetchUrlMarketplace(\n marketplace.source.url,\n marketplace.source.ref,\n )\n break\n case 'local':\n manifest = loadLocalMarketplace(marketplace.source.path)\n break\n }\n\n // Update in registry\n marketplace.manifest = manifest\n marketplace.lastUpdated = new Date()\n\n saveRegistry(registry)\n\n return marketplace\n}\n\n/**\n * List all registered marketplaces\n */\nexport function listMarketplaces(): RegisteredMarketplace[] {\n return loadRegistry()\n}\n\n/**\n * Get a specific marketplace\n */\nexport function getMarketplace(\n name: string,\n): RegisteredMarketplace | undefined {\n const registry = loadRegistry()\n return registry.find(m => m.name === name)\n}\n\n/**\n * Find plugin in marketplaces\n */\nexport function findPlugin(\n pluginName: string,\n marketplaceName?: string,\n):\n | {\n marketplace: RegisteredMarketplace\n plugin: MarketplacePlugin\n }\n | undefined {\n const registry = loadRegistry()\n\n // Search in specific marketplace\n if (marketplaceName) {\n const marketplace = registry.find(m => m.name === marketplaceName)\n if (!marketplace) return undefined\n\n const plugin = marketplace.manifest.plugins.find(p => p.name === pluginName)\n if (!plugin) return undefined\n\n return { marketplace, plugin }\n }\n\n // Search in all marketplaces\n for (const marketplace of registry) {\n if (!marketplace.enabled) continue\n\n const plugin = marketplace.manifest.plugins.find(p => p.name === pluginName)\n if (plugin) {\n return { marketplace, plugin }\n }\n }\n\n return undefined\n}\n\n/**\n * Load marketplace settings with hierarchical priority\n * Priority (highest to lowest):\n * 1. Project .minto/settings.json\n * 2. Project .claude/settings.json (legacy)\n * 3. User ~/.minto/settings.json\n * 4. User ~/.claude/settings.json (legacy)\n */\nexport function loadMarketplaceSettings(): MarketplaceSettings {\n const cwd = getCwd()\n const home = homedir()\n\n // Define search paths in priority order (.minto > .claude at each level)\n const settingsPaths = [\n { path: join(cwd, '.minto', 'settings.json'), label: 'project' },\n { path: join(cwd, '.claude', 'settings.json'), label: 'project/.claude' },\n { path: join(home, '.minto', 'settings.json'), label: 'user' },\n { path: join(home, '.claude', 'settings.json'), label: 'user/.claude' },\n ]\n\n // Try loading from each path in priority order\n for (const { path, label } of settingsPaths) {\n if (existsSync(path)) {\n try {\n const content = readFileSync(path, 'utf-8')\n const settings = JSON.parse(content)\n // Optional: log which settings file was used for debugging\n // console.log(`Loaded marketplace settings from ${label}: ${path}`)\n return settings\n } catch (error) {\n console.error(\n `Error loading marketplace settings from ${label} (${path}):`,\n error,\n )\n // Continue to next path on error\n }\n }\n }\n\n // No settings found\n return {}\n}\n\n/**\n * Auto-register marketplaces from settings\n */\nexport async function autoRegisterMarketplaces(): Promise<void> {\n const settings = loadMarketplaceSettings()\n\n if (!settings.extraKnownMarketplaces) return\n\n const registry = loadRegistry()\n\n for (const [name, config] of Object.entries(\n settings.extraKnownMarketplaces,\n )) {\n // Skip if already registered\n if (registry.some(m => m.name === name)) continue\n\n try {\n let source: MarketplaceSource\n\n if (config.source.source === 'github' && config.source.repo) {\n source = {\n type: 'github',\n repo: config.source.repo,\n ref: config.source.ref,\n }\n } else if (config.source.source === 'url' && config.source.url) {\n source = { type: 'url', url: config.source.url, ref: config.source.ref }\n } else if (config.source.source === 'local' && config.source.path) {\n source = { type: 'local', path: config.source.path }\n } else {\n continue\n }\n\n // Fetch and register\n let manifest: MarketplaceManifest\n\n switch (source.type) {\n case 'github':\n manifest = await fetchGitHubMarketplace(source.repo, source.ref)\n break\n case 'url':\n manifest = await fetchUrlMarketplace(source.url, source.ref)\n break\n case 'local':\n manifest = loadLocalMarketplace(source.path)\n break\n }\n\n registry.push({\n name: manifest.name,\n source,\n manifest,\n lastUpdated: new Date(),\n enabled: true,\n })\n } catch (error) {\n console.error(`Error auto-registering marketplace ${name}:`, error)\n }\n }\n\n saveRegistry(registry)\n}\n\n/**\n * Get marketplace repository directory path\n * For cloned marketplaces, returns the temp directory path\n * For local marketplaces, returns the local path\n */\nasync function getMarketplaceRepoPath(\n marketplace: RegisteredMarketplace,\n): Promise<{ path: string; cleanup: boolean }> {\n switch (marketplace.source.type) {\n case 'github': {\n const tempDir = join(getMarketplaceDir(), 'temp', Date.now().toString())\n mkdirSync(tempDir, { recursive: true })\n await fetchRepo(\n {\n type: 'github',\n repo: marketplace.source.repo,\n ref: marketplace.source.ref,\n },\n tempDir,\n )\n return { path: tempDir, cleanup: true }\n }\n case 'url': {\n const tempDir = join(getMarketplaceDir(), 'temp', Date.now().toString())\n mkdirSync(tempDir, { recursive: true })\n await fetchRepo(\n {\n type: 'url',\n url: marketplace.source.url,\n ref: marketplace.source.ref,\n },\n tempDir,\n )\n return { path: tempDir, cleanup: true }\n }\n case 'local': {\n const resolvedPath = isAbsolute(marketplace.source.path)\n ? marketplace.source.path\n : resolve(getCwd(), marketplace.source.path)\n\n if (!existsSync(resolvedPath)) {\n throw new MarketplaceError(\n `Local marketplace path does not exist: ${resolvedPath}`,\n MarketplaceErrorCode.MANIFEST_NOT_FOUND,\n )\n }\n\n return { path: resolvedPath, cleanup: false }\n }\n }\n}\n\n/**\n * Copy directory contents recursively\n */\nfunction copyDirectory(sourcePath: string, destPath: string): void {\n try {\n // Create destination directory if it doesn't exist\n if (!existsSync(destPath)) {\n mkdirSync(destPath, { recursive: true })\n }\n\n // Copy recursively, excluding .git directories\n cpSync(sourcePath, destPath, {\n recursive: true,\n filter: src => {\n // Skip .git directories to avoid copying version control history\n return !src.includes('/.git/') && !src.endsWith('/.git')\n },\n })\n } catch (error) {\n throw new MarketplaceError(\n `Failed to copy directory from ${sourcePath} to ${destPath}: ${error instanceof Error ? error.message : String(error)}`,\n MarketplaceErrorCode.GIT_ERROR,\n undefined,\n error,\n )\n }\n}\n\n/**\n * Create symlink to directory\n */\nfunction symlinkDirectory(sourcePath: string, destPath: string): void {\n try {\n // Remove destination if it exists\n if (existsSync(destPath)) {\n // Check if it's already a symlink pointing to the right place\n try {\n const stats = lstatSync(destPath)\n if (stats.isSymbolicLink()) {\n // Already a symlink, remove it\n rmSync(destPath, { force: true })\n } else {\n throw new MarketplaceError(\n `Destination path already exists and is not a symlink: ${destPath}`,\n MarketplaceErrorCode.GIT_ERROR,\n )\n }\n } catch (error) {\n throw new MarketplaceError(\n `Failed to check existing path: ${error instanceof Error ? error.message : String(error)}`,\n MarketplaceErrorCode.GIT_ERROR,\n undefined,\n error,\n )\n }\n } else {\n // Create parent directory\n const parentDir = join(destPath, '..')\n if (!existsSync(parentDir)) {\n mkdirSync(parentDir, { recursive: true })\n }\n }\n\n // Create symlink\n symlinkSync(sourcePath, destPath, 'dir')\n } catch (error) {\n throw new MarketplaceError(\n `Failed to create symlink from ${sourcePath} to ${destPath}: ${error instanceof Error ? error.message : String(error)}`,\n MarketplaceErrorCode.GIT_ERROR,\n undefined,\n error,\n )\n }\n}\n\n/**\n * Install plugin from marketplace\n */\nexport async function installPluginFromMarketplace(\n pluginName: string,\n marketplaceName?: string,\n targetDir?: string,\n options?: { dev?: boolean },\n): Promise<string> {\n const found = findPlugin(pluginName, marketplaceName)\n\n if (!found) {\n throw new MarketplaceError(\n marketplaceName\n ? `Plugin \"${pluginName}\" not found in marketplace \"${marketplaceName}\"`\n : `Plugin \"${pluginName}\" not found in any marketplace`,\n MarketplaceErrorCode.PLUGIN_NOT_FOUND,\n )\n }\n\n const { marketplace, plugin } = found\n\n // Determine installation directory\n const installDir =\n targetDir || join(getCwd(), '.minto', 'plugins', plugin.name)\n\n // Create installation directory\n if (!existsSync(installDir)) {\n mkdirSync(installDir, { recursive: true })\n }\n\n let cleanupMarketplaceRepo = false\n let marketplaceRepoPath: string | undefined\n\n try {\n // Install plugin based on source type\n if (typeof plugin.source === 'string') {\n // Relative path - resolve from marketplace source\n const repoInfo = await getMarketplaceRepoPath(marketplace)\n marketplaceRepoPath = repoInfo.path\n cleanupMarketplaceRepo = repoInfo.cleanup\n\n // Determine base path for relative plugin sources\n const pluginRoot = marketplace.manifest.metadata?.pluginRoot || ''\n const pluginSourcePath = join(\n marketplaceRepoPath,\n pluginRoot,\n plugin.source,\n )\n\n if (!existsSync(pluginSourcePath)) {\n throw new MarketplaceError(\n `Plugin source path does not exist: ${pluginSourcePath} (relative path: ${plugin.source})`,\n MarketplaceErrorCode.PLUGIN_NOT_FOUND,\n )\n }\n\n // Copy plugin files to installation directory\n copyDirectory(pluginSourcePath, installDir)\n } else if (plugin.source.source === 'github') {\n // GitHub repository - fetch via tarball/clone\n const tempDir = join(getMarketplaceDir(), 'temp', Date.now().toString())\n mkdirSync(tempDir, { recursive: true })\n\n try {\n await fetchRepo(\n { type: 'github', repo: plugin.source.repo, ref: plugin.source.ref },\n tempDir,\n )\n copyDirectory(tempDir, installDir)\n } finally {\n rmSync(tempDir, { recursive: true, force: true })\n }\n } else if (plugin.source.source === 'url') {\n // URL - fetch via tarball/clone\n const tempDir = join(getMarketplaceDir(), 'temp', Date.now().toString())\n mkdirSync(tempDir, { recursive: true })\n\n try {\n await fetchRepo(\n { type: 'url', url: plugin.source.url, ref: plugin.source.ref },\n tempDir,\n )\n copyDirectory(tempDir, installDir)\n } finally {\n rmSync(tempDir, { recursive: true, force: true })\n }\n } else if (plugin.source.source === 'local') {\n // Local path - resolve and copy or symlink\n const pluginSourcePath = isAbsolute(plugin.source.path)\n ? plugin.source.path\n : resolve(getCwd(), plugin.source.path)\n\n if (!existsSync(pluginSourcePath)) {\n throw new MarketplaceError(\n `Local plugin path does not exist: ${pluginSourcePath}`,\n MarketplaceErrorCode.PLUGIN_NOT_FOUND,\n )\n }\n\n // In dev mode, create symlink for easier development\n // In production mode, copy files for isolation\n if (options?.dev) {\n symlinkDirectory(pluginSourcePath, installDir)\n } else {\n copyDirectory(pluginSourcePath, installDir)\n }\n }\n\n // Create marketplace metadata file to track source\n const metadataPath = join(installDir, '.marketplace-meta.json')\n const metadata = {\n marketplace: marketplace.name,\n plugin: plugin.name,\n installedAt: new Date().toISOString(),\n source: plugin.source,\n }\n writeFileSync(metadataPath, JSON.stringify(metadata, null, 2), 'utf-8')\n\n // Create plugin.json if it doesn't exist (required for plugin discovery)\n const pluginManifestPath = join(installDir, 'plugin.json')\n if (!existsSync(pluginManifestPath)) {\n const pluginManifest = {\n name: plugin.name,\n displayName: plugin.name, // Use name as displayName for marketplace plugins\n version: plugin.version || '1.0.0',\n description: plugin.description || '',\n author: plugin.author,\n license: plugin.license,\n homepage: plugin.homepage,\n repository: plugin.repository,\n keywords: plugin.keywords || [],\n category: plugin.category,\n }\n writeFileSync(\n pluginManifestPath,\n JSON.stringify(pluginManifest, null, 2),\n 'utf-8',\n )\n }\n\n return installDir\n } finally {\n // Clean up marketplace repo if it was cloned\n if (cleanupMarketplaceRepo && marketplaceRepoPath) {\n try {\n rmSync(marketplaceRepoPath, { recursive: true, force: true })\n } catch (error) {\n // Ignore cleanup errors\n }\n }\n }\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -297,10 +297,10 @@ async function getMessagesForSlashCommand(commandName, args, setToolJSX, context
297
297
  context,
298
298
  args
299
299
  ).then((jsx) => {
300
+ if (jsx == null) return;
300
301
  setToolJSX({
301
302
  jsx,
302
- // Use command's showBelowPrompt property if defined, otherwise default to hiding
303
- shouldHidePromptInput: !command.showBelowPrompt
303
+ shouldHidePromptInput: command.hidePromptInput ?? false
304
304
  });
305
305
  });
306
306
  });
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/utils/messages.tsx"],
4
- "sourcesContent": ["import { createHash, randomUUID, UUID } from 'crypto'\nimport { Box } from 'ink'\nimport {\n AssistantMessage,\n Message,\n ProgressMessage,\n StreamingProgressContent,\n UserMessage,\n} from '@query'\nimport { getCommand, hasCommand } from '@commands'\nimport { MalformedCommandError } from './errors'\nimport { logError } from './log'\nimport { resolve } from 'path'\nimport { last } from 'lodash-es'\nimport { memoizeWithLimit } from './async'\nimport type { SetToolJSXFn, Tool, ToolUseContext } from '@tool'\nimport { lastX } from '@utils/generators'\nimport { NO_CONTENT_MESSAGE } from '@services/claude'\nimport {\n ImageBlockParam,\n TextBlockParam,\n ToolResultBlockParam,\n ToolUseBlockParam,\n Message as APIMessage,\n ContentBlockParam,\n ContentBlock,\n} from '@anthropic-ai/sdk/resources/index.mjs'\nimport { setCwd } from './state'\nimport { getCwd } from './state'\nimport chalk from 'chalk'\nimport * as React from 'react'\nimport { UserBashInputMessage } from '@components/messages/UserBashInputMessage'\nimport { Spinner } from '@components/Spinner'\nimport { StreamingBashOutput } from '@components/StreamingBashOutput'\nimport { BashTool } from '@tools/BashTool/BashTool'\nimport { ToolUseBlock } from '@anthropic-ai/sdk/resources/index.mjs'\n\n// NOTE: Dynamic content processing for custom commands has been moved to\n// src/services/customCommands.ts for better organization and reusability.\n// The functions executeBashCommands and resolveFileReferences are no longer\n// duplicated here but are imported when needed for custom command processing.\n\nexport const INTERRUPT_MESSAGE = '[Request interrupted by user]'\nexport const INTERRUPT_MESSAGE_FOR_TOOL_USE =\n '[Request interrupted by user for tool use]'\nexport const CANCEL_MESSAGE =\n \"The user doesn't want to take this action right now. STOP what you are doing and wait for the user to tell you how to proceed.\"\nexport const REJECT_MESSAGE =\n \"The user doesn't want to proceed with this tool use. The tool use was rejected (eg. if it was a file edit, the new_string was NOT written to the file). STOP what you are doing and wait for the user to tell you how to proceed.\"\nexport const NO_RESPONSE_REQUESTED = 'No response requested.'\n\nexport const SYNTHETIC_ASSISTANT_MESSAGES = new Set([\n INTERRUPT_MESSAGE,\n INTERRUPT_MESSAGE_FOR_TOOL_USE,\n CANCEL_MESSAGE,\n REJECT_MESSAGE,\n NO_RESPONSE_REQUESTED,\n])\n\nfunction baseCreateAssistantMessage(\n content: ContentBlock[],\n extra?: Partial<AssistantMessage>,\n): AssistantMessage {\n return {\n type: 'assistant',\n costUSD: 0,\n durationMs: 0,\n uuid: randomUUID(),\n message: {\n id: randomUUID(),\n model: '<synthetic>',\n role: 'assistant',\n stop_reason: 'stop_sequence',\n stop_sequence: '',\n type: 'message',\n usage: {\n input_tokens: 0,\n output_tokens: 0,\n cache_creation_input_tokens: 0,\n cache_read_input_tokens: 0,\n },\n content,\n },\n ...extra,\n }\n}\n\nexport function createAssistantMessage(content: string): AssistantMessage {\n return baseCreateAssistantMessage([\n {\n type: 'text' as const,\n text: content === '' ? NO_CONTENT_MESSAGE : content,\n citations: [],\n },\n ])\n}\n\nexport function createAssistantAPIErrorMessage(\n content: string,\n): AssistantMessage {\n return baseCreateAssistantMessage(\n [\n {\n type: 'text' as const,\n text: content === '' ? NO_CONTENT_MESSAGE : content,\n citations: [],\n },\n ],\n { isApiErrorMessage: true },\n )\n}\n\nexport type FullToolUseResult = {\n data: unknown // Matches tool's `Output` type\n resultForAssistant: ToolResultBlockParam['content']\n /**\n * New messages to add to the conversation from tool execution\n * Used by SlashCommandTool to inject skill-generated messages\n */\n newMessages?: unknown[]\n /**\n * Context modifier for modifying tool execution context\n * Used by SlashCommandTool to apply allowed tools and model switching\n */\n contextModifier?: {\n modifyContext: (ctx: any) => any\n }\n}\n\nexport function createUserMessage(\n content: string | ContentBlockParam[],\n toolUseResult?: FullToolUseResult,\n): UserMessage {\n const m: UserMessage = {\n type: 'user',\n message: {\n role: 'user',\n content,\n },\n uuid: randomUUID(),\n toolUseResult,\n }\n return m\n}\n\nexport function createProgressMessage(\n toolUseID: string,\n siblingToolUseIDs: Set<string>,\n content: AssistantMessage | StreamingProgressContent,\n normalizedMessages: NormalizedMessage[],\n tools: Tool[],\n): ProgressMessage {\n return {\n type: 'progress',\n content,\n normalizedMessages,\n siblingToolUseIDs,\n tools,\n toolUseID,\n uuid: randomUUID(),\n }\n}\n\nexport function createToolResultStopMessage(\n toolUseID: string,\n): ToolResultBlockParam {\n return {\n type: 'tool_result',\n content: CANCEL_MESSAGE,\n is_error: true,\n tool_use_id: toolUseID,\n }\n}\n\nexport async function processUserInput(\n input: string,\n mode: 'bash' | 'prompt' | 'koding',\n setToolJSX: SetToolJSXFn,\n context: ToolUseContext & {\n setForkConvoWithMessagesOnTheNextRender: (\n forkConvoWithMessages: Message[],\n ) => void\n unmount?: () => void\n options?: {\n isKodingRequest?: boolean\n kodingContext?: string\n }\n },\n pastedImage: string | null,\n): Promise<Message[]> {\n // Bash commands\n if (mode === 'bash') {\n const userMessage = createUserMessage(`<bash-input>${input}</bash-input>`)\n\n // Special case: cd\n if (input.startsWith('cd ')) {\n const oldCwd = getCwd()\n const newCwd = resolve(oldCwd, input.slice(3))\n try {\n await setCwd(newCwd)\n return [\n userMessage,\n createAssistantMessage(\n `<bash-stdout>Changed directory to ${chalk.bold(`${newCwd}/`)}</bash-stdout>`,\n ),\n ]\n } catch (e) {\n logError(e)\n return [\n userMessage,\n createAssistantMessage(\n `<bash-stderr>cwd error: ${e instanceof Error ? e.message : String(e)}</bash-stderr>`,\n ),\n ]\n }\n }\n\n // All other bash commands - run in background with streaming output\n const validationResult = await BashTool.validateInput({\n command: input,\n })\n if (!validationResult.result) {\n return [userMessage, createAssistantMessage(validationResult.message)]\n }\n\n // Start command in background to enable streaming\n const { BackgroundShellManager } = await import(\n '@utils/BackgroundShellManager'\n )\n const shellId = BackgroundShellManager.getInstance().create(\n input,\n context.readFileTimestamps ? getCwd() : process.cwd(),\n )\n\n let movedToBackground = false\n let completed = false\n let completionData: {\n stdout: string\n stderr: string\n exitCode: number\n } | null = null\n\n // Show streaming output with Ctrl+B option\n setToolJSX({\n jsx: (\n <StreamingBashOutput\n shellId={shellId}\n command={input}\n onMoveToBackground={() => {\n movedToBackground = true\n setToolJSX(null)\n }}\n onComplete={(stdout, stderr, exitCode) => {\n completed = true\n completionData = { stdout, stderr, exitCode }\n setToolJSX(null)\n }}\n />\n ),\n shouldHidePromptInput: false,\n })\n\n // Wait for either completion or move to background\n await new Promise<void>(resolve => {\n const checkInterval = setInterval(() => {\n if (movedToBackground || completed) {\n clearInterval(checkInterval)\n resolve()\n }\n }, 100)\n })\n\n if (movedToBackground) {\n // Task moved to background - return message about it\n return [\n userMessage,\n createAssistantMessage(\n `<bash-stdout>Command moved to background (shell ID: ${shellId})\\nUse Shift+B to view background tasks</bash-stdout>`,\n ),\n ]\n } else if (completed && completionData) {\n // Task completed normally\n return [\n userMessage,\n createAssistantMessage(\n `<bash-stdout>${completionData.stdout}</bash-stdout><bash-stderr>${completionData.stderr}</bash-stderr>`,\n ),\n ]\n } else {\n // Should not reach here\n return [\n userMessage,\n createAssistantMessage(\n `<bash-stderr>Unexpected error in bash execution</bash-stderr>`,\n ),\n ]\n }\n }\n // Koding mode - special wrapper for display\n else if (mode === 'koding') {\n const userMessage = createUserMessage(\n `<koding-input>${input}</koding-input>`,\n )\n // Add the Koding flag to the message\n userMessage.options = {\n ...userMessage.options,\n isKodingRequest: true,\n }\n\n // Rest of koding processing is handled separately to capture assistant response\n return [userMessage]\n }\n\n // Slash commands\n if (input.startsWith('/')) {\n const words = input.slice(1).split(' ')\n let commandName = words[0]\n if (words.length > 1 && words[1] === '(MCP)') {\n commandName = commandName + ' (MCP)'\n }\n if (!commandName) {\n return [\n createAssistantMessage('Commands are in the form `/command [args]`'),\n ]\n }\n\n // Check if it's a real command before processing\n if (!hasCommand(commandName, context.options.commands)) {\n // If not a real command, treat it as a regular user input\n return [createUserMessage(input)]\n }\n\n const args = input.slice(commandName.length + 2)\n const newMessages = await getMessagesForSlashCommand(\n commandName,\n args,\n setToolJSX,\n context,\n )\n\n // Local JSX commands\n if (newMessages.length === 0) {\n return []\n }\n\n // For invalid commands, preserve both the user message and error\n if (\n newMessages.length === 2 &&\n newMessages[0]!.type === 'user' &&\n newMessages[1]!.type === 'assistant' &&\n typeof newMessages[1]!.message.content === 'string' &&\n newMessages[1]!.message.content.startsWith('Unknown command:')\n ) {\n return newMessages\n }\n\n // User-Assistant pair (eg. local commands)\n if (newMessages.length === 2) {\n return newMessages\n }\n\n // A valid command\n\n return newMessages\n }\n\n // Regular user prompt\n\n // Check if this is a Koding request that needs special handling\n const isKodingRequest = context.options?.isKodingRequest === true\n const kodingContextInfo = context.options?.kodingContext\n\n // Create base message\n let userMessage: UserMessage\n\n if (pastedImage) {\n userMessage = createUserMessage([\n {\n type: 'image',\n source: {\n type: 'base64',\n media_type: 'image/png',\n data: pastedImage,\n },\n },\n {\n type: 'text',\n text:\n isKodingRequest && kodingContextInfo\n ? `${kodingContextInfo}\\n\\n${input}`\n : input,\n },\n ])\n } else {\n let processedInput =\n isKodingRequest && kodingContextInfo\n ? `${kodingContextInfo}\\n\\n${input}`\n : input\n\n // Process dynamic content for custom commands with ! and @ prefixes\n // This uses the same processing functions as custom commands to maintain consistency\n if (input.includes('!`') || input.includes('@')) {\n try {\n // Import functions from customCommands service to avoid code duplication\n const { executeBashCommands } = await import('@services/customCommands')\n\n // Execute bash commands if present\n if (input.includes('!`')) {\n // Note: This function is not exported from customCommands.ts, so we need to expose it\n // For now, we'll keep the local implementation until we refactor the service\n processedInput = await executeBashCommands(processedInput)\n }\n\n // Process mentions for system reminder integration\n // Note: We don't call resolveFileReferences here anymore -\n // @file mentions should trigger Read tool usage via reminders, not embed content\n if (input.includes('@')) {\n const { processMentions } = await import('@services/mentionProcessor')\n await processMentions(input)\n }\n } catch (error) {\n console.warn('Dynamic content processing failed:', error)\n // Continue with original input if processing fails\n }\n }\n\n userMessage = createUserMessage(processedInput)\n }\n\n // Add the Koding flag to the message if needed\n if (isKodingRequest) {\n userMessage.options = {\n ...userMessage.options,\n isKodingRequest: true,\n }\n }\n\n return [userMessage]\n}\n\nasync function getMessagesForSlashCommand(\n commandName: string,\n args: string,\n setToolJSX: SetToolJSXFn,\n context: ToolUseContext & {\n setForkConvoWithMessagesOnTheNextRender: (\n forkConvoWithMessages: Message[],\n ) => void\n unmount?: () => void\n },\n): Promise<Message[]> {\n try {\n const command = getCommand(commandName, context.options.commands)\n switch (command.type) {\n case 'local-jsx': {\n return new Promise(resolve => {\n command\n .call(\n r => {\n setToolJSX(null)\n resolve([\n createUserMessage(`<command-name>${command.userFacingName()}</command-name>\n <command-message>${command.userFacingName()}</command-message>\n <command-args>${args}</command-args>`),\n r\n ? createAssistantMessage(r)\n : createAssistantMessage(NO_RESPONSE_REQUESTED),\n ])\n },\n context,\n args,\n )\n .then(jsx => {\n setToolJSX({\n jsx,\n // Use command's showBelowPrompt property if defined, otherwise default to hiding\n shouldHidePromptInput: !(command as any).showBelowPrompt,\n })\n })\n })\n }\n case 'local': {\n const userMessage =\n createUserMessage(`<command-name>${command.userFacingName()}</command-name>\n <command-message>${command.userFacingName()}</command-message>\n <command-args>${args}</command-args>`)\n\n try {\n // Use the context's abortController for local commands\n const result = await command.call(args, {\n ...context,\n options: {\n commands: context.options.commands || [],\n tools: context.options.tools || [],\n slowAndCapableModel:\n context.options.slowAndCapableModel || 'main',\n },\n })\n\n return [\n userMessage,\n createAssistantMessage(\n `<local-command-stdout>${result}</local-command-stdout>`,\n ),\n ]\n } catch (e) {\n logError(e)\n return [\n userMessage,\n createAssistantMessage(\n `<local-command-stderr>${String(e)}</local-command-stderr>`,\n ),\n ]\n }\n }\n case 'prompt': {\n // For custom commands, process them naturally instead of wrapping in command-contents\n const prompt = await command.getPromptForCommand(args)\n return prompt.map(msg => {\n // Create a normal user message from the custom command content\n const userMessage = createUserMessage(\n typeof msg.content === 'string'\n ? msg.content\n : msg.content\n .map(block => (block.type === 'text' ? block.text : ''))\n .join('\\n'),\n )\n\n // Add metadata for tracking but don't wrap in special tags\n userMessage.options = {\n ...userMessage.options,\n isCustomCommand: true,\n commandName: command.userFacingName(),\n commandArgs: args,\n }\n\n return userMessage\n })\n }\n }\n } catch (e) {\n if (e instanceof MalformedCommandError) {\n return [createAssistantMessage(e.message)]\n }\n throw e\n }\n}\n\nexport function extractTagFromMessage(\n message: Message,\n tagName: string,\n): string | null {\n if (message.type === 'progress') {\n return null\n }\n if (typeof message.message.content !== 'string') {\n return null\n }\n return extractTag(message.message.content, tagName)\n}\n\nexport function extractTag(html: string, tagName: string): string | null {\n if (!html.trim() || !tagName.trim()) {\n return null\n }\n\n // Escape special characters in the tag name\n const escapedTag = tagName.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')\n\n // Create regex pattern that handles:\n // 1. Self-closing tags\n // 2. Tags with attributes\n // 3. Nested tags of the same type\n // 4. Multiline content\n const pattern = new RegExp(\n `<${escapedTag}(?:\\\\s+[^>]*)?>` + // Opening tag with optional attributes\n '([\\\\s\\\\S]*?)' + // Content (non-greedy match)\n `<\\\\/${escapedTag}>`, // Closing tag\n 'gi',\n )\n\n let match\n let depth = 0\n let lastIndex = 0\n const openingTag = new RegExp(`<${escapedTag}(?:\\\\s+[^>]*?)?>`, 'gi')\n const closingTag = new RegExp(`<\\\\/${escapedTag}>`, 'gi')\n\n while ((match = pattern.exec(html)) !== null) {\n // Check for nested tags\n const content = match[1]\n const beforeMatch = html.slice(lastIndex, match.index)\n\n // Reset depth counter\n depth = 0\n\n // Count opening tags before this match\n openingTag.lastIndex = 0\n while (openingTag.exec(beforeMatch) !== null) {\n depth++\n }\n\n // Count closing tags before this match\n closingTag.lastIndex = 0\n while (closingTag.exec(beforeMatch) !== null) {\n depth--\n }\n\n // Only include content if we're at the correct nesting level\n if (depth === 0 && content) {\n return content\n }\n\n lastIndex = match.index + match[0].length\n }\n\n return null\n}\n\nexport function isNotEmptyMessage(message: Message): boolean {\n if (message.type === 'progress') {\n return true\n }\n\n if (typeof message.message.content === 'string') {\n return message.message.content.trim().length > 0\n }\n\n if (message.message.content.length === 0) {\n return false\n }\n\n // Skip multi-block messages for now\n if (message.message.content.length > 1) {\n return true\n }\n\n if (message.message.content[0]!.type !== 'text') {\n return true\n }\n\n return (\n message.message.content[0]!.text.trim().length > 0 &&\n message.message.content[0]!.text !== NO_CONTENT_MESSAGE &&\n message.message.content[0]!.text !== INTERRUPT_MESSAGE_FOR_TOOL_USE\n )\n}\n\n// TODO: replace this with plain UserMessage if/when PR #405 lands\ntype NormalizedUserMessage = {\n message: {\n content: [\n | TextBlockParam\n | ImageBlockParam\n | ToolUseBlockParam\n | ToolResultBlockParam,\n ]\n role: 'user'\n }\n type: 'user'\n uuid: UUID\n}\n\nexport type NormalizedMessage =\n | NormalizedUserMessage\n | AssistantMessage\n | ProgressMessage\n\n/**\n * Generate a deterministic UUID based on input string\n * This ensures the same content always produces the same UUID,\n * preventing duplicate entries in Ink's <Static> component\n */\nfunction deterministicUUID(seed: string): UUID {\n const hash = createHash('sha256').update(seed).digest('hex')\n // Format as UUID v4 (xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx)\n return `${hash.slice(0, 8)}-${hash.slice(8, 12)}-4${hash.slice(13, 16)}-${((parseInt(hash.slice(16, 17), 16) & 0x3) | 0x8).toString(16)}${hash.slice(17, 20)}-${hash.slice(20, 32)}` as UUID\n}\n\n// Split messages, so each content block gets its own message\nexport function normalizeMessages(messages: Message[]): NormalizedMessage[] {\n return messages.flatMap((message, messageIndex) => {\n if (message.type === 'progress') {\n return [message] as NormalizedMessage[]\n }\n if (typeof message.message.content === 'string') {\n return [message] as NormalizedMessage[]\n }\n return message.message.content.map((_, contentIndex) => {\n switch (message.type) {\n case 'assistant':\n // Generate deterministic UUID based on message uuid + content index\n // This ensures the same content block always gets the same UUID,\n // preventing duplicate entries when Ink's <Static> re-renders\n const baseUuid =\n (message as AssistantMessage).uuid || `msg-${messageIndex}`\n const contentId =\n _.type === 'tool_use' ? _.id || contentIndex : contentIndex\n const stableUuid = deterministicUUID(`${baseUuid}-${contentId}`)\n\n return {\n type: 'assistant',\n uuid: stableUuid,\n // Preserve original UUID for identifying parallel tool calls from same message\n originalUuid: (message as AssistantMessage).uuid,\n message: {\n ...message.message,\n content: [_],\n },\n costUSD:\n (message as AssistantMessage).costUSD /\n message.message.content.length,\n durationMs: (message as AssistantMessage).durationMs,\n } as NormalizedMessage\n case 'user':\n // It seems like the line below was a no-op before, but I'm not sure.\n // To check, we could throw an error if any of the following are true:\n // - message `role` does isn't `user` -- this possibility is allowed by MCP tools,\n // though isn't supposed to happen in practice (we should fix this)\n // - message `content` is not an array -- this one is more concerning because it's\n // not allowed by the `NormalizedUserMessage` type, but if it's happening that was\n // probably a bug before.\n // Maybe I'm missing something? -(ab)\n // return createUserMessage([_]) as NormalizedMessage\n return message as NormalizedUserMessage\n }\n })\n })\n}\n\ntype ToolUseRequestMessage = AssistantMessage & {\n message: { content: ToolUseBlock[] }\n}\n\nfunction isToolUseRequestMessage(\n message: Message,\n): message is ToolUseRequestMessage {\n return (\n message.type === 'assistant' &&\n 'costUSD' in message &&\n // Note: stop_reason === 'tool_use' is unreliable -- it's not always set correctly\n message.message.content.some(_ => _.type === 'tool_use')\n )\n}\n\n// Re-order, to move result messages to be after their tool use messages\nexport function reorderMessages(\n messages: NormalizedMessage[],\n): NormalizedMessage[] {\n const ms: NormalizedMessage[] = []\n const toolUseMessages: ToolUseRequestMessage[] = []\n\n for (const message of messages) {\n // track tool use messages we've seen\n if (isToolUseRequestMessage(message)) {\n toolUseMessages.push(message)\n }\n\n // if it's a tool progress message...\n if (message.type === 'progress') {\n // replace any existing progress messages with this one\n const existingProgressMessage = ms.find(\n _ => _.type === 'progress' && _.toolUseID === message.toolUseID,\n )\n if (existingProgressMessage) {\n ms[ms.indexOf(existingProgressMessage)] = message\n continue\n }\n // otherwise, insert it after its tool use\n const toolUseMessage = toolUseMessages.find(\n _ => _.message.content[0]?.id === message.toolUseID,\n )\n if (toolUseMessage) {\n ms.splice(ms.indexOf(toolUseMessage) + 1, 0, message)\n continue\n }\n }\n\n // if it's a tool result, insert it after its tool use and progress messages\n if (\n message.type === 'user' &&\n Array.isArray(message.message.content) &&\n message.message.content[0]?.type === 'tool_result'\n ) {\n const toolUseID = (message.message.content[0] as ToolResultBlockParam)\n ?.tool_use_id\n\n // First check for progress messages\n const lastProgressMessage = ms.find(\n _ => _.type === 'progress' && _.toolUseID === toolUseID,\n )\n if (lastProgressMessage) {\n ms.splice(ms.indexOf(lastProgressMessage) + 1, 0, message)\n continue\n }\n\n // If no progress messages, check for tool use messages\n const toolUseMessage = toolUseMessages.find(\n _ => _.message.content[0]?.id === toolUseID,\n )\n if (toolUseMessage) {\n ms.splice(ms.indexOf(toolUseMessage) + 1, 0, message)\n continue\n }\n }\n\n // otherwise, just add it to the list\n else {\n ms.push(message)\n }\n }\n\n return ms\n}\n\n// Use memoizeWithLimit to prevent unbounded cache growth during long conversations\n// Each unique normalizedMessages array would create a new cache entry with lodash memoize\nconst getToolResultIDs = memoizeWithLimit(\n (normalizedMessages: NormalizedMessage[]): { [toolUseID: string]: boolean } =>\n Object.fromEntries(\n normalizedMessages.flatMap(_ =>\n _.type === 'user' && _.message.content[0]?.type === 'tool_result'\n ? [\n [\n _.message.content[0]!.tool_use_id,\n _.message.content[0]!.is_error ?? false,\n ],\n ]\n : ([] as [string, boolean][]),\n ),\n ),\n { max: 50, ttl: 30000 }, // Keep last 50 results for 30 seconds\n)\n\nexport function getUnresolvedToolUseIDs(\n normalizedMessages: NormalizedMessage[],\n): Set<string> {\n const toolResults = getToolResultIDs(normalizedMessages)\n return new Set(\n normalizedMessages\n .filter(\n (\n _,\n ): _ is AssistantMessage & {\n message: { content: [ToolUseBlockParam] }\n } =>\n _.type === 'assistant' &&\n Array.isArray(_.message.content) &&\n _.message.content[0]?.type === 'tool_use' &&\n !(_.message.content[0]?.id in toolResults),\n )\n .map(_ => _.message.content[0].id),\n )\n}\n\n/**\n * Tool uses are in flight if either:\n * 1. They have a corresponding progress message and no result message\n * 2. They are the first unresoved tool use\n *\n * TODO: Find a way to harden this logic to make it more explicit\n */\nexport function getInProgressToolUseIDs(\n normalizedMessages: NormalizedMessage[],\n): Set<string> {\n const unresolvedToolUseIDs = getUnresolvedToolUseIDs(normalizedMessages)\n const toolUseIDsThatHaveProgressMessages = new Set(\n normalizedMessages.filter(_ => _.type === 'progress').map(_ => _.toolUseID),\n )\n return new Set(\n (\n normalizedMessages.filter(_ => {\n if (_.type !== 'assistant') {\n return false\n }\n if (_.message.content[0]?.type !== 'tool_use') {\n return false\n }\n const toolUseID = _.message.content[0].id\n if (toolUseID === unresolvedToolUseIDs.values().next().value) {\n return true\n }\n\n if (\n toolUseIDsThatHaveProgressMessages.has(toolUseID) &&\n unresolvedToolUseIDs.has(toolUseID)\n ) {\n return true\n }\n\n return false\n }) as AssistantMessage[]\n ).map(_ => (_.message.content[0]! as ToolUseBlockParam).id),\n )\n}\n\nexport function getErroredToolUseMessages(\n normalizedMessages: NormalizedMessage[],\n): AssistantMessage[] {\n const toolResults = getToolResultIDs(normalizedMessages)\n return normalizedMessages.filter(\n _ =>\n _.type === 'assistant' &&\n Array.isArray(_.message.content) &&\n _.message.content[0]?.type === 'tool_use' &&\n _.message.content[0]?.id in toolResults &&\n toolResults[_.message.content[0]?.id],\n ) as AssistantMessage[]\n}\n\nexport function normalizeMessagesForAPI(\n messages: Message[],\n): (UserMessage | AssistantMessage)[] {\n const result: (UserMessage | AssistantMessage)[] = []\n messages\n .filter(_ => _.type !== 'progress')\n .forEach(message => {\n switch (message.type) {\n case 'user': {\n // If the current message is not a tool result, add it to the result\n if (\n !Array.isArray(message.message.content) ||\n message.message.content[0]?.type !== 'tool_result'\n ) {\n result.push(message)\n return\n }\n\n // If the last message is not a tool result, add it to the result\n const lastMessage = last(result)\n if (\n !lastMessage ||\n lastMessage?.type === 'assistant' ||\n !Array.isArray(lastMessage.message.content) ||\n lastMessage.message.content[0]?.type !== 'tool_result'\n ) {\n result.push(message)\n return\n }\n\n // Otherwise, merge the current message with the last message\n result[result.indexOf(lastMessage)] = {\n ...lastMessage,\n message: {\n ...lastMessage.message,\n content: [\n ...lastMessage.message.content,\n ...message.message.content,\n ],\n },\n }\n return\n }\n case 'assistant':\n result.push(message)\n return\n }\n })\n return result\n}\n\n// Sometimes the API returns empty messages (eg. \"\\n\\n\"). We need to filter these out,\n// otherwise they will give an API error when we send them to the API next time we call query().\nexport function normalizeContentFromAPI(\n content: APIMessage['content'],\n): APIMessage['content'] {\n const filteredContent = content.filter(\n _ => _.type !== 'text' || _.text.trim().length > 0,\n )\n\n if (filteredContent.length === 0) {\n return [{ type: 'text', text: NO_CONTENT_MESSAGE, citations: [] }]\n }\n\n return filteredContent\n}\n\nexport function isEmptyMessageText(text: string): boolean {\n return (\n stripSystemMessages(text).trim() === '' ||\n text.trim() === NO_CONTENT_MESSAGE\n )\n}\nconst STRIPPED_TAGS = [\n 'commit_analysis',\n 'context',\n 'function_analysis',\n 'pr_analysis',\n]\n\nexport function stripSystemMessages(content: string): string {\n const regex = new RegExp(`<(${STRIPPED_TAGS.join('|')})>.*?</\\\\1>\\n?`, 'gs')\n return content.replace(regex, '').trim()\n}\n\nexport function getToolUseID(message: NormalizedMessage): string | null {\n switch (message.type) {\n case 'assistant':\n if (message.message.content[0]?.type !== 'tool_use') {\n return null\n }\n return message.message.content[0].id\n case 'user':\n if (message.message.content[0]?.type !== 'tool_result') {\n return null\n }\n return message.message.content[0].tool_use_id\n case 'progress':\n return message.toolUseID\n }\n}\n\nexport function getLastAssistantMessageId(\n messages: Message[],\n): string | undefined {\n // Iterate from the end of the array to find the last assistant message\n for (let i = messages.length - 1; i >= 0; i--) {\n const message = messages[i]\n if (message && message.type === 'assistant') {\n return message.message.id\n }\n }\n return undefined\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { createHash, randomUUID, UUID } from 'crypto'\nimport { Box } from 'ink'\nimport {\n AssistantMessage,\n Message,\n ProgressMessage,\n StreamingProgressContent,\n UserMessage,\n} from '@query'\nimport { getCommand, hasCommand } from '@commands'\nimport { MalformedCommandError } from './errors'\nimport { logError } from './log'\nimport { resolve } from 'path'\nimport { last } from 'lodash-es'\nimport { memoizeWithLimit } from './async'\nimport type { SetToolJSXFn, Tool, ToolUseContext } from '@tool'\nimport { lastX } from '@utils/generators'\nimport { NO_CONTENT_MESSAGE } from '@services/claude'\nimport {\n ImageBlockParam,\n TextBlockParam,\n ToolResultBlockParam,\n ToolUseBlockParam,\n Message as APIMessage,\n ContentBlockParam,\n ContentBlock,\n} from '@anthropic-ai/sdk/resources/index.mjs'\nimport { setCwd } from './state'\nimport { getCwd } from './state'\nimport chalk from 'chalk'\nimport * as React from 'react'\nimport { UserBashInputMessage } from '@components/messages/UserBashInputMessage'\nimport { Spinner } from '@components/Spinner'\nimport { StreamingBashOutput } from '@components/StreamingBashOutput'\nimport { BashTool } from '@tools/BashTool/BashTool'\nimport { ToolUseBlock } from '@anthropic-ai/sdk/resources/index.mjs'\n\n// NOTE: Dynamic content processing for custom commands has been moved to\n// src/services/customCommands.ts for better organization and reusability.\n// The functions executeBashCommands and resolveFileReferences are no longer\n// duplicated here but are imported when needed for custom command processing.\n\nexport const INTERRUPT_MESSAGE = '[Request interrupted by user]'\nexport const INTERRUPT_MESSAGE_FOR_TOOL_USE =\n '[Request interrupted by user for tool use]'\nexport const CANCEL_MESSAGE =\n \"The user doesn't want to take this action right now. STOP what you are doing and wait for the user to tell you how to proceed.\"\nexport const REJECT_MESSAGE =\n \"The user doesn't want to proceed with this tool use. The tool use was rejected (eg. if it was a file edit, the new_string was NOT written to the file). STOP what you are doing and wait for the user to tell you how to proceed.\"\nexport const NO_RESPONSE_REQUESTED = 'No response requested.'\n\nexport const SYNTHETIC_ASSISTANT_MESSAGES = new Set([\n INTERRUPT_MESSAGE,\n INTERRUPT_MESSAGE_FOR_TOOL_USE,\n CANCEL_MESSAGE,\n REJECT_MESSAGE,\n NO_RESPONSE_REQUESTED,\n])\n\nfunction baseCreateAssistantMessage(\n content: ContentBlock[],\n extra?: Partial<AssistantMessage>,\n): AssistantMessage {\n return {\n type: 'assistant',\n costUSD: 0,\n durationMs: 0,\n uuid: randomUUID(),\n message: {\n id: randomUUID(),\n model: '<synthetic>',\n role: 'assistant',\n stop_reason: 'stop_sequence',\n stop_sequence: '',\n type: 'message',\n usage: {\n input_tokens: 0,\n output_tokens: 0,\n cache_creation_input_tokens: 0,\n cache_read_input_tokens: 0,\n },\n content,\n },\n ...extra,\n }\n}\n\nexport function createAssistantMessage(content: string): AssistantMessage {\n return baseCreateAssistantMessage([\n {\n type: 'text' as const,\n text: content === '' ? NO_CONTENT_MESSAGE : content,\n citations: [],\n },\n ])\n}\n\nexport function createAssistantAPIErrorMessage(\n content: string,\n): AssistantMessage {\n return baseCreateAssistantMessage(\n [\n {\n type: 'text' as const,\n text: content === '' ? NO_CONTENT_MESSAGE : content,\n citations: [],\n },\n ],\n { isApiErrorMessage: true },\n )\n}\n\nexport type FullToolUseResult = {\n data: unknown // Matches tool's `Output` type\n resultForAssistant: ToolResultBlockParam['content']\n /**\n * New messages to add to the conversation from tool execution\n * Used by SlashCommandTool to inject skill-generated messages\n */\n newMessages?: unknown[]\n /**\n * Context modifier for modifying tool execution context\n * Used by SlashCommandTool to apply allowed tools and model switching\n */\n contextModifier?: {\n modifyContext: (ctx: any) => any\n }\n}\n\nexport function createUserMessage(\n content: string | ContentBlockParam[],\n toolUseResult?: FullToolUseResult,\n): UserMessage {\n const m: UserMessage = {\n type: 'user',\n message: {\n role: 'user',\n content,\n },\n uuid: randomUUID(),\n toolUseResult,\n }\n return m\n}\n\nexport function createProgressMessage(\n toolUseID: string,\n siblingToolUseIDs: Set<string>,\n content: AssistantMessage | StreamingProgressContent,\n normalizedMessages: NormalizedMessage[],\n tools: Tool[],\n): ProgressMessage {\n return {\n type: 'progress',\n content,\n normalizedMessages,\n siblingToolUseIDs,\n tools,\n toolUseID,\n uuid: randomUUID(),\n }\n}\n\nexport function createToolResultStopMessage(\n toolUseID: string,\n): ToolResultBlockParam {\n return {\n type: 'tool_result',\n content: CANCEL_MESSAGE,\n is_error: true,\n tool_use_id: toolUseID,\n }\n}\n\nexport async function processUserInput(\n input: string,\n mode: 'bash' | 'prompt' | 'koding',\n setToolJSX: SetToolJSXFn,\n context: ToolUseContext & {\n setForkConvoWithMessagesOnTheNextRender: (\n forkConvoWithMessages: Message[],\n ) => void\n unmount?: () => void\n options?: {\n isKodingRequest?: boolean\n kodingContext?: string\n }\n },\n pastedImage: string | null,\n): Promise<Message[]> {\n // Bash commands\n if (mode === 'bash') {\n const userMessage = createUserMessage(`<bash-input>${input}</bash-input>`)\n\n // Special case: cd\n if (input.startsWith('cd ')) {\n const oldCwd = getCwd()\n const newCwd = resolve(oldCwd, input.slice(3))\n try {\n await setCwd(newCwd)\n return [\n userMessage,\n createAssistantMessage(\n `<bash-stdout>Changed directory to ${chalk.bold(`${newCwd}/`)}</bash-stdout>`,\n ),\n ]\n } catch (e) {\n logError(e)\n return [\n userMessage,\n createAssistantMessage(\n `<bash-stderr>cwd error: ${e instanceof Error ? e.message : String(e)}</bash-stderr>`,\n ),\n ]\n }\n }\n\n // All other bash commands - run in background with streaming output\n const validationResult = await BashTool.validateInput({\n command: input,\n })\n if (!validationResult.result) {\n return [userMessage, createAssistantMessage(validationResult.message)]\n }\n\n // Start command in background to enable streaming\n const { BackgroundShellManager } = await import(\n '@utils/BackgroundShellManager'\n )\n const shellId = BackgroundShellManager.getInstance().create(\n input,\n context.readFileTimestamps ? getCwd() : process.cwd(),\n )\n\n let movedToBackground = false\n let completed = false\n let completionData: {\n stdout: string\n stderr: string\n exitCode: number\n } | null = null\n\n // Show streaming output with Ctrl+B option\n setToolJSX({\n jsx: (\n <StreamingBashOutput\n shellId={shellId}\n command={input}\n onMoveToBackground={() => {\n movedToBackground = true\n setToolJSX(null)\n }}\n onComplete={(stdout, stderr, exitCode) => {\n completed = true\n completionData = { stdout, stderr, exitCode }\n setToolJSX(null)\n }}\n />\n ),\n shouldHidePromptInput: false,\n })\n\n // Wait for either completion or move to background\n await new Promise<void>(resolve => {\n const checkInterval = setInterval(() => {\n if (movedToBackground || completed) {\n clearInterval(checkInterval)\n resolve()\n }\n }, 100)\n })\n\n if (movedToBackground) {\n // Task moved to background - return message about it\n return [\n userMessage,\n createAssistantMessage(\n `<bash-stdout>Command moved to background (shell ID: ${shellId})\\nUse Shift+B to view background tasks</bash-stdout>`,\n ),\n ]\n } else if (completed && completionData) {\n // Task completed normally\n return [\n userMessage,\n createAssistantMessage(\n `<bash-stdout>${completionData.stdout}</bash-stdout><bash-stderr>${completionData.stderr}</bash-stderr>`,\n ),\n ]\n } else {\n // Should not reach here\n return [\n userMessage,\n createAssistantMessage(\n `<bash-stderr>Unexpected error in bash execution</bash-stderr>`,\n ),\n ]\n }\n }\n // Koding mode - special wrapper for display\n else if (mode === 'koding') {\n const userMessage = createUserMessage(\n `<koding-input>${input}</koding-input>`,\n )\n // Add the Koding flag to the message\n userMessage.options = {\n ...userMessage.options,\n isKodingRequest: true,\n }\n\n // Rest of koding processing is handled separately to capture assistant response\n return [userMessage]\n }\n\n // Slash commands\n if (input.startsWith('/')) {\n const words = input.slice(1).split(' ')\n let commandName = words[0]\n if (words.length > 1 && words[1] === '(MCP)') {\n commandName = commandName + ' (MCP)'\n }\n if (!commandName) {\n return [\n createAssistantMessage('Commands are in the form `/command [args]`'),\n ]\n }\n\n // Check if it's a real command before processing\n if (!hasCommand(commandName, context.options.commands)) {\n // If not a real command, treat it as a regular user input\n return [createUserMessage(input)]\n }\n\n const args = input.slice(commandName.length + 2)\n const newMessages = await getMessagesForSlashCommand(\n commandName,\n args,\n setToolJSX,\n context,\n )\n\n // Local JSX commands\n if (newMessages.length === 0) {\n return []\n }\n\n // For invalid commands, preserve both the user message and error\n if (\n newMessages.length === 2 &&\n newMessages[0]!.type === 'user' &&\n newMessages[1]!.type === 'assistant' &&\n typeof newMessages[1]!.message.content === 'string' &&\n newMessages[1]!.message.content.startsWith('Unknown command:')\n ) {\n return newMessages\n }\n\n // User-Assistant pair (eg. local commands)\n if (newMessages.length === 2) {\n return newMessages\n }\n\n // A valid command\n\n return newMessages\n }\n\n // Regular user prompt\n\n // Check if this is a Koding request that needs special handling\n const isKodingRequest = context.options?.isKodingRequest === true\n const kodingContextInfo = context.options?.kodingContext\n\n // Create base message\n let userMessage: UserMessage\n\n if (pastedImage) {\n userMessage = createUserMessage([\n {\n type: 'image',\n source: {\n type: 'base64',\n media_type: 'image/png',\n data: pastedImage,\n },\n },\n {\n type: 'text',\n text:\n isKodingRequest && kodingContextInfo\n ? `${kodingContextInfo}\\n\\n${input}`\n : input,\n },\n ])\n } else {\n let processedInput =\n isKodingRequest && kodingContextInfo\n ? `${kodingContextInfo}\\n\\n${input}`\n : input\n\n // Process dynamic content for custom commands with ! and @ prefixes\n // This uses the same processing functions as custom commands to maintain consistency\n if (input.includes('!`') || input.includes('@')) {\n try {\n // Import functions from customCommands service to avoid code duplication\n const { executeBashCommands } = await import('@services/customCommands')\n\n // Execute bash commands if present\n if (input.includes('!`')) {\n // Note: This function is not exported from customCommands.ts, so we need to expose it\n // For now, we'll keep the local implementation until we refactor the service\n processedInput = await executeBashCommands(processedInput)\n }\n\n // Process mentions for system reminder integration\n // Note: We don't call resolveFileReferences here anymore -\n // @file mentions should trigger Read tool usage via reminders, not embed content\n if (input.includes('@')) {\n const { processMentions } = await import('@services/mentionProcessor')\n await processMentions(input)\n }\n } catch (error) {\n console.warn('Dynamic content processing failed:', error)\n // Continue with original input if processing fails\n }\n }\n\n userMessage = createUserMessage(processedInput)\n }\n\n // Add the Koding flag to the message if needed\n if (isKodingRequest) {\n userMessage.options = {\n ...userMessage.options,\n isKodingRequest: true,\n }\n }\n\n return [userMessage]\n}\n\nasync function getMessagesForSlashCommand(\n commandName: string,\n args: string,\n setToolJSX: SetToolJSXFn,\n context: ToolUseContext & {\n setForkConvoWithMessagesOnTheNextRender: (\n forkConvoWithMessages: Message[],\n ) => void\n unmount?: () => void\n },\n): Promise<Message[]> {\n try {\n const command = getCommand(commandName, context.options.commands)\n switch (command.type) {\n case 'local-jsx': {\n return new Promise(resolve => {\n command\n .call(\n r => {\n setToolJSX(null)\n resolve([\n createUserMessage(`<command-name>${command.userFacingName()}</command-name>\n <command-message>${command.userFacingName()}</command-message>\n <command-args>${args}</command-args>`),\n r\n ? createAssistantMessage(r)\n : createAssistantMessage(NO_RESPONSE_REQUESTED),\n ])\n },\n context,\n args,\n )\n .then(jsx => {\n // If call returned null/undefined (e.g. onDone already called synchronously),\n // don't override toolJSX \u2014 it was already cleared by onDone\n if (jsx == null) return\n setToolJSX({\n jsx,\n shouldHidePromptInput: command.hidePromptInput ?? false,\n })\n })\n })\n }\n case 'local': {\n const userMessage =\n createUserMessage(`<command-name>${command.userFacingName()}</command-name>\n <command-message>${command.userFacingName()}</command-message>\n <command-args>${args}</command-args>`)\n\n try {\n // Use the context's abortController for local commands\n const result = await command.call(args, {\n ...context,\n options: {\n commands: context.options.commands || [],\n tools: context.options.tools || [],\n slowAndCapableModel:\n context.options.slowAndCapableModel || 'main',\n },\n })\n\n return [\n userMessage,\n createAssistantMessage(\n `<local-command-stdout>${result}</local-command-stdout>`,\n ),\n ]\n } catch (e) {\n logError(e)\n return [\n userMessage,\n createAssistantMessage(\n `<local-command-stderr>${String(e)}</local-command-stderr>`,\n ),\n ]\n }\n }\n case 'prompt': {\n // For custom commands, process them naturally instead of wrapping in command-contents\n const prompt = await command.getPromptForCommand(args)\n return prompt.map(msg => {\n // Create a normal user message from the custom command content\n const userMessage = createUserMessage(\n typeof msg.content === 'string'\n ? msg.content\n : msg.content\n .map(block => (block.type === 'text' ? block.text : ''))\n .join('\\n'),\n )\n\n // Add metadata for tracking but don't wrap in special tags\n userMessage.options = {\n ...userMessage.options,\n isCustomCommand: true,\n commandName: command.userFacingName(),\n commandArgs: args,\n }\n\n return userMessage\n })\n }\n }\n } catch (e) {\n if (e instanceof MalformedCommandError) {\n return [createAssistantMessage(e.message)]\n }\n throw e\n }\n}\n\nexport function extractTagFromMessage(\n message: Message,\n tagName: string,\n): string | null {\n if (message.type === 'progress') {\n return null\n }\n if (typeof message.message.content !== 'string') {\n return null\n }\n return extractTag(message.message.content, tagName)\n}\n\nexport function extractTag(html: string, tagName: string): string | null {\n if (!html.trim() || !tagName.trim()) {\n return null\n }\n\n // Escape special characters in the tag name\n const escapedTag = tagName.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')\n\n // Create regex pattern that handles:\n // 1. Self-closing tags\n // 2. Tags with attributes\n // 3. Nested tags of the same type\n // 4. Multiline content\n const pattern = new RegExp(\n `<${escapedTag}(?:\\\\s+[^>]*)?>` + // Opening tag with optional attributes\n '([\\\\s\\\\S]*?)' + // Content (non-greedy match)\n `<\\\\/${escapedTag}>`, // Closing tag\n 'gi',\n )\n\n let match\n let depth = 0\n let lastIndex = 0\n const openingTag = new RegExp(`<${escapedTag}(?:\\\\s+[^>]*?)?>`, 'gi')\n const closingTag = new RegExp(`<\\\\/${escapedTag}>`, 'gi')\n\n while ((match = pattern.exec(html)) !== null) {\n // Check for nested tags\n const content = match[1]\n const beforeMatch = html.slice(lastIndex, match.index)\n\n // Reset depth counter\n depth = 0\n\n // Count opening tags before this match\n openingTag.lastIndex = 0\n while (openingTag.exec(beforeMatch) !== null) {\n depth++\n }\n\n // Count closing tags before this match\n closingTag.lastIndex = 0\n while (closingTag.exec(beforeMatch) !== null) {\n depth--\n }\n\n // Only include content if we're at the correct nesting level\n if (depth === 0 && content) {\n return content\n }\n\n lastIndex = match.index + match[0].length\n }\n\n return null\n}\n\nexport function isNotEmptyMessage(message: Message): boolean {\n if (message.type === 'progress') {\n return true\n }\n\n if (typeof message.message.content === 'string') {\n return message.message.content.trim().length > 0\n }\n\n if (message.message.content.length === 0) {\n return false\n }\n\n // Skip multi-block messages for now\n if (message.message.content.length > 1) {\n return true\n }\n\n if (message.message.content[0]!.type !== 'text') {\n return true\n }\n\n return (\n message.message.content[0]!.text.trim().length > 0 &&\n message.message.content[0]!.text !== NO_CONTENT_MESSAGE &&\n message.message.content[0]!.text !== INTERRUPT_MESSAGE_FOR_TOOL_USE\n )\n}\n\n// TODO: replace this with plain UserMessage if/when PR #405 lands\ntype NormalizedUserMessage = {\n message: {\n content: [\n | TextBlockParam\n | ImageBlockParam\n | ToolUseBlockParam\n | ToolResultBlockParam,\n ]\n role: 'user'\n }\n type: 'user'\n uuid: UUID\n}\n\nexport type NormalizedMessage =\n | NormalizedUserMessage\n | AssistantMessage\n | ProgressMessage\n\n/**\n * Generate a deterministic UUID based on input string\n * This ensures the same content always produces the same UUID,\n * preventing duplicate entries in Ink's <Static> component\n */\nfunction deterministicUUID(seed: string): UUID {\n const hash = createHash('sha256').update(seed).digest('hex')\n // Format as UUID v4 (xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx)\n return `${hash.slice(0, 8)}-${hash.slice(8, 12)}-4${hash.slice(13, 16)}-${((parseInt(hash.slice(16, 17), 16) & 0x3) | 0x8).toString(16)}${hash.slice(17, 20)}-${hash.slice(20, 32)}` as UUID\n}\n\n// Split messages, so each content block gets its own message\nexport function normalizeMessages(messages: Message[]): NormalizedMessage[] {\n return messages.flatMap((message, messageIndex) => {\n if (message.type === 'progress') {\n return [message] as NormalizedMessage[]\n }\n if (typeof message.message.content === 'string') {\n return [message] as NormalizedMessage[]\n }\n return message.message.content.map((_, contentIndex) => {\n switch (message.type) {\n case 'assistant':\n // Generate deterministic UUID based on message uuid + content index\n // This ensures the same content block always gets the same UUID,\n // preventing duplicate entries when Ink's <Static> re-renders\n const baseUuid =\n (message as AssistantMessage).uuid || `msg-${messageIndex}`\n const contentId =\n _.type === 'tool_use' ? _.id || contentIndex : contentIndex\n const stableUuid = deterministicUUID(`${baseUuid}-${contentId}`)\n\n return {\n type: 'assistant',\n uuid: stableUuid,\n // Preserve original UUID for identifying parallel tool calls from same message\n originalUuid: (message as AssistantMessage).uuid,\n message: {\n ...message.message,\n content: [_],\n },\n costUSD:\n (message as AssistantMessage).costUSD /\n message.message.content.length,\n durationMs: (message as AssistantMessage).durationMs,\n } as NormalizedMessage\n case 'user':\n // It seems like the line below was a no-op before, but I'm not sure.\n // To check, we could throw an error if any of the following are true:\n // - message `role` does isn't `user` -- this possibility is allowed by MCP tools,\n // though isn't supposed to happen in practice (we should fix this)\n // - message `content` is not an array -- this one is more concerning because it's\n // not allowed by the `NormalizedUserMessage` type, but if it's happening that was\n // probably a bug before.\n // Maybe I'm missing something? -(ab)\n // return createUserMessage([_]) as NormalizedMessage\n return message as NormalizedUserMessage\n }\n })\n })\n}\n\ntype ToolUseRequestMessage = AssistantMessage & {\n message: { content: ToolUseBlock[] }\n}\n\nfunction isToolUseRequestMessage(\n message: Message,\n): message is ToolUseRequestMessage {\n return (\n message.type === 'assistant' &&\n 'costUSD' in message &&\n // Note: stop_reason === 'tool_use' is unreliable -- it's not always set correctly\n message.message.content.some(_ => _.type === 'tool_use')\n )\n}\n\n// Re-order, to move result messages to be after their tool use messages\nexport function reorderMessages(\n messages: NormalizedMessage[],\n): NormalizedMessage[] {\n const ms: NormalizedMessage[] = []\n const toolUseMessages: ToolUseRequestMessage[] = []\n\n for (const message of messages) {\n // track tool use messages we've seen\n if (isToolUseRequestMessage(message)) {\n toolUseMessages.push(message)\n }\n\n // if it's a tool progress message...\n if (message.type === 'progress') {\n // replace any existing progress messages with this one\n const existingProgressMessage = ms.find(\n _ => _.type === 'progress' && _.toolUseID === message.toolUseID,\n )\n if (existingProgressMessage) {\n ms[ms.indexOf(existingProgressMessage)] = message\n continue\n }\n // otherwise, insert it after its tool use\n const toolUseMessage = toolUseMessages.find(\n _ => _.message.content[0]?.id === message.toolUseID,\n )\n if (toolUseMessage) {\n ms.splice(ms.indexOf(toolUseMessage) + 1, 0, message)\n continue\n }\n }\n\n // if it's a tool result, insert it after its tool use and progress messages\n if (\n message.type === 'user' &&\n Array.isArray(message.message.content) &&\n message.message.content[0]?.type === 'tool_result'\n ) {\n const toolUseID = (message.message.content[0] as ToolResultBlockParam)\n ?.tool_use_id\n\n // First check for progress messages\n const lastProgressMessage = ms.find(\n _ => _.type === 'progress' && _.toolUseID === toolUseID,\n )\n if (lastProgressMessage) {\n ms.splice(ms.indexOf(lastProgressMessage) + 1, 0, message)\n continue\n }\n\n // If no progress messages, check for tool use messages\n const toolUseMessage = toolUseMessages.find(\n _ => _.message.content[0]?.id === toolUseID,\n )\n if (toolUseMessage) {\n ms.splice(ms.indexOf(toolUseMessage) + 1, 0, message)\n continue\n }\n }\n\n // otherwise, just add it to the list\n else {\n ms.push(message)\n }\n }\n\n return ms\n}\n\n// Use memoizeWithLimit to prevent unbounded cache growth during long conversations\n// Each unique normalizedMessages array would create a new cache entry with lodash memoize\nconst getToolResultIDs = memoizeWithLimit(\n (normalizedMessages: NormalizedMessage[]): { [toolUseID: string]: boolean } =>\n Object.fromEntries(\n normalizedMessages.flatMap(_ =>\n _.type === 'user' && _.message.content[0]?.type === 'tool_result'\n ? [\n [\n _.message.content[0]!.tool_use_id,\n _.message.content[0]!.is_error ?? false,\n ],\n ]\n : ([] as [string, boolean][]),\n ),\n ),\n { max: 50, ttl: 30000 }, // Keep last 50 results for 30 seconds\n)\n\nexport function getUnresolvedToolUseIDs(\n normalizedMessages: NormalizedMessage[],\n): Set<string> {\n const toolResults = getToolResultIDs(normalizedMessages)\n return new Set(\n normalizedMessages\n .filter(\n (\n _,\n ): _ is AssistantMessage & {\n message: { content: [ToolUseBlockParam] }\n } =>\n _.type === 'assistant' &&\n Array.isArray(_.message.content) &&\n _.message.content[0]?.type === 'tool_use' &&\n !(_.message.content[0]?.id in toolResults),\n )\n .map(_ => _.message.content[0].id),\n )\n}\n\n/**\n * Tool uses are in flight if either:\n * 1. They have a corresponding progress message and no result message\n * 2. They are the first unresoved tool use\n *\n * TODO: Find a way to harden this logic to make it more explicit\n */\nexport function getInProgressToolUseIDs(\n normalizedMessages: NormalizedMessage[],\n): Set<string> {\n const unresolvedToolUseIDs = getUnresolvedToolUseIDs(normalizedMessages)\n const toolUseIDsThatHaveProgressMessages = new Set(\n normalizedMessages.filter(_ => _.type === 'progress').map(_ => _.toolUseID),\n )\n return new Set(\n (\n normalizedMessages.filter(_ => {\n if (_.type !== 'assistant') {\n return false\n }\n if (_.message.content[0]?.type !== 'tool_use') {\n return false\n }\n const toolUseID = _.message.content[0].id\n if (toolUseID === unresolvedToolUseIDs.values().next().value) {\n return true\n }\n\n if (\n toolUseIDsThatHaveProgressMessages.has(toolUseID) &&\n unresolvedToolUseIDs.has(toolUseID)\n ) {\n return true\n }\n\n return false\n }) as AssistantMessage[]\n ).map(_ => (_.message.content[0]! as ToolUseBlockParam).id),\n )\n}\n\nexport function getErroredToolUseMessages(\n normalizedMessages: NormalizedMessage[],\n): AssistantMessage[] {\n const toolResults = getToolResultIDs(normalizedMessages)\n return normalizedMessages.filter(\n _ =>\n _.type === 'assistant' &&\n Array.isArray(_.message.content) &&\n _.message.content[0]?.type === 'tool_use' &&\n _.message.content[0]?.id in toolResults &&\n toolResults[_.message.content[0]?.id],\n ) as AssistantMessage[]\n}\n\nexport function normalizeMessagesForAPI(\n messages: Message[],\n): (UserMessage | AssistantMessage)[] {\n const result: (UserMessage | AssistantMessage)[] = []\n messages\n .filter(_ => _.type !== 'progress')\n .forEach(message => {\n switch (message.type) {\n case 'user': {\n // If the current message is not a tool result, add it to the result\n if (\n !Array.isArray(message.message.content) ||\n message.message.content[0]?.type !== 'tool_result'\n ) {\n result.push(message)\n return\n }\n\n // If the last message is not a tool result, add it to the result\n const lastMessage = last(result)\n if (\n !lastMessage ||\n lastMessage?.type === 'assistant' ||\n !Array.isArray(lastMessage.message.content) ||\n lastMessage.message.content[0]?.type !== 'tool_result'\n ) {\n result.push(message)\n return\n }\n\n // Otherwise, merge the current message with the last message\n result[result.indexOf(lastMessage)] = {\n ...lastMessage,\n message: {\n ...lastMessage.message,\n content: [\n ...lastMessage.message.content,\n ...message.message.content,\n ],\n },\n }\n return\n }\n case 'assistant':\n result.push(message)\n return\n }\n })\n return result\n}\n\n// Sometimes the API returns empty messages (eg. \"\\n\\n\"). We need to filter these out,\n// otherwise they will give an API error when we send them to the API next time we call query().\nexport function normalizeContentFromAPI(\n content: APIMessage['content'],\n): APIMessage['content'] {\n const filteredContent = content.filter(\n _ => _.type !== 'text' || _.text.trim().length > 0,\n )\n\n if (filteredContent.length === 0) {\n return [{ type: 'text', text: NO_CONTENT_MESSAGE, citations: [] }]\n }\n\n return filteredContent\n}\n\nexport function isEmptyMessageText(text: string): boolean {\n return (\n stripSystemMessages(text).trim() === '' ||\n text.trim() === NO_CONTENT_MESSAGE\n )\n}\nconst STRIPPED_TAGS = [\n 'commit_analysis',\n 'context',\n 'function_analysis',\n 'pr_analysis',\n]\n\nexport function stripSystemMessages(content: string): string {\n const regex = new RegExp(`<(${STRIPPED_TAGS.join('|')})>.*?</\\\\1>\\n?`, 'gs')\n return content.replace(regex, '').trim()\n}\n\nexport function getToolUseID(message: NormalizedMessage): string | null {\n switch (message.type) {\n case 'assistant':\n if (message.message.content[0]?.type !== 'tool_use') {\n return null\n }\n return message.message.content[0].id\n case 'user':\n if (message.message.content[0]?.type !== 'tool_result') {\n return null\n }\n return message.message.content[0].tool_use_id\n case 'progress':\n return message.toolUseID\n }\n}\n\nexport function getLastAssistantMessageId(\n messages: Message[],\n): string | undefined {\n // Iterate from the end of the array to find the last assistant message\n for (let i = messages.length - 1; i >= 0; i--) {\n const message = messages[i]\n if (message && message.type === 'assistant') {\n return message.message.id\n }\n }\n return undefined\n}\n"],
5
+ "mappings": "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",
6
6
  "names": ["userMessage", "resolve"]
7
7
  }