@kirosnn/mosaic 0.0.91 → 0.73.0

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 (99) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +2 -6
  3. package/package.json +55 -48
  4. package/src/agent/Agent.ts +353 -131
  5. package/src/agent/context.ts +4 -4
  6. package/src/agent/prompts/systemPrompt.ts +209 -70
  7. package/src/agent/prompts/toolsPrompt.ts +285 -138
  8. package/src/agent/provider/anthropic.ts +109 -105
  9. package/src/agent/provider/google.ts +111 -107
  10. package/src/agent/provider/mistral.ts +95 -95
  11. package/src/agent/provider/ollama.ts +73 -17
  12. package/src/agent/provider/openai.ts +146 -102
  13. package/src/agent/provider/rateLimit.ts +178 -0
  14. package/src/agent/provider/reasoning.ts +29 -0
  15. package/src/agent/provider/xai.ts +108 -104
  16. package/src/agent/tools/definitions.ts +15 -1
  17. package/src/agent/tools/executor.ts +717 -98
  18. package/src/agent/tools/exploreExecutor.ts +20 -22
  19. package/src/agent/tools/fetch.ts +58 -0
  20. package/src/agent/tools/glob.ts +20 -4
  21. package/src/agent/tools/grep.ts +64 -9
  22. package/src/agent/tools/plan.ts +27 -0
  23. package/src/agent/tools/question.ts +7 -1
  24. package/src/agent/tools/read.ts +2 -0
  25. package/src/agent/types.ts +15 -14
  26. package/src/components/App.tsx +50 -8
  27. package/src/components/CustomInput.tsx +461 -77
  28. package/src/components/Main.tsx +1459 -1112
  29. package/src/components/Setup.tsx +1 -1
  30. package/src/components/ShortcutsModal.tsx +11 -8
  31. package/src/components/Welcome.tsx +1 -1
  32. package/src/components/main/ApprovalPanel.tsx +4 -3
  33. package/src/components/main/ChatPage.tsx +858 -516
  34. package/src/components/main/HomePage.tsx +58 -39
  35. package/src/components/main/QuestionPanel.tsx +52 -7
  36. package/src/components/main/ThinkingIndicator.tsx +13 -2
  37. package/src/components/main/types.ts +11 -10
  38. package/src/index.tsx +53 -25
  39. package/src/mcp/approvalPolicy.ts +148 -0
  40. package/src/mcp/cli/add.ts +185 -0
  41. package/src/mcp/cli/doctor.ts +77 -0
  42. package/src/mcp/cli/index.ts +85 -0
  43. package/src/mcp/cli/list.ts +50 -0
  44. package/src/mcp/cli/logs.ts +24 -0
  45. package/src/mcp/cli/manage.ts +99 -0
  46. package/src/mcp/cli/show.ts +53 -0
  47. package/src/mcp/cli/tools.ts +77 -0
  48. package/src/mcp/config.ts +223 -0
  49. package/src/mcp/index.ts +80 -0
  50. package/src/mcp/processManager.ts +299 -0
  51. package/src/mcp/rateLimiter.ts +50 -0
  52. package/src/mcp/registry.ts +151 -0
  53. package/src/mcp/schemaConverter.ts +100 -0
  54. package/src/mcp/servers/navigation.ts +854 -0
  55. package/src/mcp/toolCatalog.ts +169 -0
  56. package/src/mcp/types.ts +95 -0
  57. package/src/utils/approvalBridge.ts +45 -12
  58. package/src/utils/approvalModeBridge.ts +17 -0
  59. package/src/utils/commands/approvals.ts +48 -0
  60. package/src/utils/commands/compact.ts +30 -0
  61. package/src/utils/commands/echo.ts +1 -1
  62. package/src/utils/commands/image.ts +109 -0
  63. package/src/utils/commands/index.ts +9 -7
  64. package/src/utils/commands/new.ts +15 -0
  65. package/src/utils/commands/types.ts +3 -0
  66. package/src/utils/config.ts +3 -1
  67. package/src/utils/diffRendering.tsx +13 -16
  68. package/src/utils/exploreBridge.ts +10 -0
  69. package/src/utils/history.ts +82 -40
  70. package/src/utils/imageBridge.ts +28 -0
  71. package/src/utils/images.ts +31 -0
  72. package/src/utils/markdown.tsx +163 -99
  73. package/src/utils/models.ts +31 -16
  74. package/src/utils/notificationBridge.ts +23 -0
  75. package/src/utils/questionBridge.ts +36 -1
  76. package/src/utils/tokenEstimator.ts +32 -0
  77. package/src/utils/toolFormatting.ts +428 -48
  78. package/src/web/app.tsx +65 -5
  79. package/src/web/assets/css/ChatPage.css +102 -30
  80. package/src/web/assets/css/MessageItem.css +26 -29
  81. package/src/web/assets/css/ThinkingIndicator.css +44 -6
  82. package/src/web/assets/css/ToolMessage.css +36 -14
  83. package/src/web/components/ChatPage.tsx +228 -105
  84. package/src/web/components/HomePage.tsx +3 -3
  85. package/src/web/components/MessageItem.tsx +80 -81
  86. package/src/web/components/QuestionPanel.tsx +72 -12
  87. package/src/web/components/Setup.tsx +1 -1
  88. package/src/web/components/Sidebar.tsx +1 -3
  89. package/src/web/components/ThinkingIndicator.tsx +41 -21
  90. package/src/web/router.ts +1 -1
  91. package/src/web/server.tsx +894 -662
  92. package/src/web/storage.ts +23 -1
  93. package/src/web/types.ts +7 -6
  94. package/src/utils/commands/redo.ts +0 -74
  95. package/src/utils/commands/sessions.ts +0 -129
  96. package/src/utils/commands/undo.ts +0 -75
  97. package/src/utils/undoRedo.ts +0 -429
  98. package/src/utils/undoRedoBridge.ts +0 -45
  99. package/src/utils/undoRedoDb.ts +0 -338
@@ -1,139 +1,286 @@
1
1
  export const TOOLS_PROMPT = `
2
- AVAILABLE TOOLS:
3
-
4
- You have access to the following tools to interact with the workspace:
5
-
6
- FILE READING:
7
- 1. read: Read the complete contents of a file
8
- - Use this to examine existing code, configuration, or documentation
9
- - Parameters: path (string)
10
-
11
- FILE WRITING & EDITING:
12
- 2. write: Write or overwrite a file (with advanced features)
13
- - Creates parent directories automatically if they don't exist
14
- - Can append to existing files instead of overwriting
15
- - Parameters: path (string), content (string, optional), append (boolean, optional)
16
- - Note: content can be omitted or empty to create an empty file
17
-
18
- 3. edit: Edit a specific part of a file without rewriting everything
19
- - More efficient for targeted changes - replace specific text content
20
- - Parameters: path (string), old_content (string), new_content (string), occurrence (number, optional)
21
-
22
- FILE & DIRECTORY OPERATIONS:
23
- 4. list: List files and directories with filtering
24
- - Supports recursive listing through subdirectories
25
- - Can filter by glob patterns (e.g., "*.ts")
26
- - Can include or exclude hidden files
27
- - Parameters: path (string), recursive (boolean, optional), filter (string, optional), include_hidden (boolean, optional)
28
-
29
- SEARCH & DISCOVERY:
30
- 5. glob: Fast file pattern matching
31
- - Find files matching a glob pattern
32
- - REQUIRED: pattern (string) - Glob pattern to match files (e.g., "*.ts", "**/*.tsx", "src/**/*.js")
33
- - OPTIONAL: path (string) - Directory to search in (default: workspace root)
34
-
35
- Examples:
36
- - Find all TypeScript files: glob(pattern="**/*.ts")
37
- - Find React components: glob(pattern="**/*.tsx")
38
- - Search in specific directory: glob(pattern="*.js", path="src")
39
-
40
- 6. grep: Search for text content within files
41
- - Search for text within files matching a glob pattern
42
- - REQUIRED: pattern (string) - Glob pattern to match files (e.g., "*.ts", "**/*.tsx")
43
- - REQUIRED: query (string) - Text content to search for
44
- - OPTIONAL: path (string) - Directory to search in (default: workspace root)
45
- - OPTIONAL: case_sensitive (boolean) - Case-sensitive search (default: false)
46
- - OPTIONAL: max_results (number) - Maximum results (default: 100)
47
-
48
- Examples:
49
- - Find interface in TypeScript files: grep(pattern="**/*.ts", query="interface User")
50
- - Search in specific directory: grep(pattern="*.js", query="console.log", path="src")
51
- - Case-sensitive search: grep(pattern="**/*.ts", query="UserModel", case_sensitive=true)
52
-
53
- AUTONOMOUS EXPLORATION:
54
- 7. explore: Launch an autonomous exploration agent
55
- - Explores the codebase iteratively to gather information
56
- - The agent uses read, glob, grep, and list tools autonomously
57
- - Continues until it has enough information or reaches its limit
58
- - Use for open-ended exploration tasks
59
- - Parameters: purpose (string) - The goal of the exploration
60
-
61
- Examples:
62
- - Understand project structure:
63
- explore(purpose="Understand the project structure and main entry points")
64
- - Find implementations:
65
- explore(purpose="Find all React components that handle user authentication")
66
- - Investigate code patterns:
67
- explore(purpose="Find how errors are handled throughout the codebase")
68
-
69
- COMMAND EXECUTION:
70
- 8. bash: Execute a shell command
71
- - Use this to run build tools, tests, git commands, or other CLI tools
72
- - Parameters: command (string)
73
- - CRITICAL: You MUST add --timeout <ms> at the END of commands that might hang:
74
- * Dev servers: ALWAYS add --timeout 5000
75
- Example: bash(command="npm run dev --timeout 5000")
76
- * Build commands: ALWAYS add --timeout 120000
77
- Example: bash(command="npm run build --timeout 120000")
78
- * Test runners: ALWAYS add --timeout 60000
79
- Example: bash(command="pytest tests/ --timeout 60000")
80
- * Package installs: ALWAYS add --timeout 120000
81
- Example: bash(command="npm install --timeout 120000")
82
- * Interactive CLIs: ALWAYS add --timeout 5000 or avoid entirely
83
- Example: bash(command="npx create-react-app myapp --timeout 5000")
84
- - Quick commands (ls, cat, git status, echo): No --timeout needed (default: 30s)
85
-
86
- USER INTERACTION:
87
- 9. question: Ask the user a question with predefined options
88
- - CRITICAL: This is the ONLY way to ask the user questions. NEVER ask questions in plain text.
89
- - MANDATORY usage scenarios:
90
- * When you need user to pick between choices
91
- * When you need user's confirmation or approval
92
- * When you need clarification on ambiguous requests
93
- * When you're unsure how to proceed
94
- * When a tool operation is rejected and you need to know why
95
- * When multiple approaches are possible and user input is needed
96
- - The UI will show the prompt and options and return the selected option
97
- - Parameters:
98
- - prompt (string) - The question to ask in the user's language
99
- - options (array of objects) - At least 2 options required:
100
- - label (string) - The option text shown to user
101
- - value (string | null) - Optional value returned (use null if not needed)
102
- - Returns: { id, index, label, value }
103
- - Example: question(prompt="Which approach do you prefer?", options=[{label:"Approach A", value:"a"}, {label:"Approach B", value:"b"}])
104
-
105
- TOOL USAGE GUIDELINES:
106
-
107
- - Use explore for open-ended exploration tasks (autonomous agent)
108
- - Use glob to find files by pattern (fast file discovery)
109
- - Use grep to search for text content within files
110
- - Use edit for small changes to avoid rewriting entire files
111
- - Always use read before modifying files to understand the current state
112
- - When writing files, preserve existing code structure and style
113
- - Use list with recursive:true to explore deep directory structures
114
- - All file paths are relative to the workspace root: {{WORKSPACE}}
115
-
116
- ERRORS:
117
- - Some tools return an object like {"error": "..."} when something went wrong. Treat this as a TOOL ERROR (not an API error).
118
- - When a tool returns an error, continue the task using that information (e.g., adjust path, create missing parent directory, retry with correct tool).
119
-
120
- WORKFLOW BEST PRACTICES:
121
-
122
- 1. Discover: Use explore for open-ended exploration, or glob/grep for targeted searches
123
- 2. Understand: Use read to examine files
124
- 3. Plan: Think through modifications before acting
125
- 4. Execute: Use edit for small changes, write for new/complete rewrites
126
- 5. Verify: Use bash to run tests and verify changes
127
- 6. Communicate: Explain your actions to the user in their language
128
-
129
- CRITICAL REMINDERS:
130
- - NEVER ask questions in plain text - ALWAYS use the question tool
131
- - When write/edit/bash operations are rejected by the user, IMMEDIATELY use the question tool to understand why and what to do instead
132
- - The question tool is NOT optional - it's MANDATORY for any user interaction requiring a response
133
- - If you catch yourself about to ask something in text, STOP and use the question tool instead
134
-
135
- Remember: The user can see your tool usage, so be transparent about what you're doing and why.`;
136
-
137
- export function getToolsPrompt(): string {
138
- return TOOLS_PROMPT;
139
- }
2
+ # Available Tools
3
+
4
+ ## File Operations
5
+
6
+ ### read
7
+ Read file contents. ALWAYS read before modifying.
8
+ - path (string, required): File path relative to workspace
9
+ - start_line (number, optional): Start reading from this line (1-based)
10
+ - end_line (number, optional): End reading at this line (1-based)
11
+
12
+ ### write
13
+ Create or overwrite a file. Creates parent directories automatically.
14
+ - path (string, required): File path
15
+ - content (string, optional): File content (empty to create empty file)
16
+ - append (boolean, optional): Append instead of overwrite
17
+
18
+ ### edit
19
+ Replace specific text in a file. Preferred for targeted changes.
20
+ - path (string, required): File path
21
+ - old_content (string, required): Exact text to replace
22
+ - new_content (string, required): Replacement text
23
+ - occurrence (number, optional): Which occurrence (default: 1)
24
+
25
+ ### list
26
+ List directory contents.
27
+ - path (string, required): Directory path
28
+ - recursive (boolean, optional): Include subdirectories
29
+ - filter (string, optional): Glob pattern filter
30
+ - include_hidden (boolean, optional): Include hidden files
31
+
32
+ ## Search & Discovery
33
+
34
+ ### explore (RECOMMENDED for understanding context)
35
+ Autonomous exploration agent that intelligently searches the codebase.
36
+ - purpose (string, required): What to find/understand
37
+
38
+ USE EXPLORE WHEN:
39
+ - Starting work on an unfamiliar codebase
40
+ - Understanding how something works
41
+ - Finding related code, patterns, or architecture
42
+ - You're unsure where to make changes
43
+
44
+ Examples:
45
+ - explore(purpose="Find API endpoints and understand routing")
46
+ - explore(purpose="Understand the authentication flow")
47
+ - explore(purpose="Find UserService and all its usages")
48
+
49
+ The explore tool is INTELLIGENT - it autonomously reads files, follows imports, and builds understanding. This is MORE EFFICIENT than manual glob/grep/read cycles.
50
+
51
+ ### glob
52
+ Find files by name pattern. Fast file discovery.
53
+ - pattern (string, required): Glob pattern with **/ for recursive search
54
+ - path (string, optional): Directory to search
55
+
56
+ IMPORTANT: Use "**/" prefix for recursive search:
57
+ - "**/*.ts" - All TypeScript files (recursive)
58
+ - "*.ts" - Only in current directory (NOT recursive)
59
+
60
+ ### grep
61
+ Search for text within files.
62
+ - query (string, required): Text to search for
63
+ - file_type (string, optional): language or extension (ts, tsx, js, txt, .env)
64
+ - pattern (string, optional): Glob pattern for files
65
+ - regex (boolean, optional): Treat query as regex
66
+ - context (number, optional): Lines around matches
67
+ - output_mode (string, optional): "matches", "files", or "count"
68
+
69
+ RECOMMENDED: Use file_type for best results:
70
+ - grep(query="handleClick", file_type="tsx")
71
+ - grep(query="interface User", file_type="ts")
72
+
73
+ TOOL SELECTION:
74
+ | Need to understand how X works | explore |
75
+ | Find specific file by name | glob |
76
+ | Find specific text in code | grep |
77
+
78
+ ## Planning
79
+
80
+ ### plan
81
+ Track progress on multi-step tasks.
82
+ - explanation (string, optional): Context about the plan
83
+ - plan (array, required): Steps with statuses
84
+ - step (string): Action description
85
+ - status: "pending" | "in_progress" | "completed"
86
+
87
+ Use plan for any task that is not a single obvious step. Default to planning when unsure.
88
+ Use plan when there are 2+ actions, file changes, or unclear success criteria.
89
+ Plan rules:
90
+ - Keep plans short (3-6 steps) and outcome-focused
91
+ - Exactly one step can be "in_progress" at a time
92
+ - Mark a step "completed" before starting the next
93
+ - Keep unstarted steps "pending"
94
+ Always update the plan after each step.
95
+ Never output a plan as plain text, JSON, or tags. Use the plan tool call only.
96
+ Never mark multiple future steps as completed in a single update. Show progress incrementally as each step is done.
97
+
98
+ ## Web Access
99
+
100
+ ### fetch
101
+ Retrieve web content as markdown.
102
+ - url (string, required): URL to fetch
103
+ - max_length (number, optional): Max chars (default: 10000)
104
+ - start_index (number, optional): For pagination
105
+ - raw (boolean, optional): Return raw HTML
106
+ - timeout (number, optional): Timeout in ms (default: 30000)
107
+
108
+ ## Command Execution
109
+
110
+ ### bash
111
+ Execute shell commands. Adapt to OS ({{OS}}).
112
+ - command (string, required): Command to execute
113
+
114
+ Timeouts (add --timeout <ms> to long commands):
115
+ - Dev servers: 5000
116
+ - Builds: 120000
117
+ - Tests: 60000
118
+ - Package installs: 120000
119
+
120
+ ## User Interaction
121
+
122
+ ### question
123
+ Ask user with predefined options. ONLY way to ask questions.
124
+ - prompt (string, required): Question in user's language
125
+ - options (array, required): At least 2 options
126
+ - label (string): Display text
127
+ - value (string|null): Return value
128
+ - group (string, optional): Group header for consecutive options with the same group
129
+ - timeout (number, optional): Seconds before the question auto-rejects
130
+ - validation (object, optional): Regex validation for custom text input
131
+ - pattern (string): Regex pattern the custom text must match
132
+ - message (string, optional): Error message shown on validation failure
133
+
134
+ CRITICAL: Never ask questions in plain text. Always use this tool.
135
+
136
+ # Tool Selection Guide
137
+
138
+ | Task | Tool | Example |
139
+ |------|------|---------|
140
+ | Understand codebase/architecture | explore | explore(purpose="How does auth work?") |
141
+ | Find files by name | glob | glob(pattern="**/*.config.ts") |
142
+ | Find specific text | grep | grep(query="handleSubmit", file_type="tsx") |
143
+ | Read file contents | read | read(path="src/auth.ts") |
144
+ | Small targeted edit | edit | edit(path="...", old_content="...", new_content="...") |
145
+ | New file or full rewrite | write | write(path="...", content="...") |
146
+ | Run commands/tests | bash | bash(command="npm test") |
147
+ | Track multi-step work | plan | plan(plan=[...]) |
148
+ | Need user input | question | question(prompt="...", options=[...]) |
149
+
150
+ PREFER EXPLORE for understanding context before making changes.
151
+ PREFER grep with file_type for targeted text searches.
152
+
153
+ # Continuation - CRITICAL
154
+
155
+ NEVER stop after using a tool. ALWAYS continue to the next step in the SAME response.
156
+
157
+ Pattern: text → tool → text → tool → text → tool → ... → completion
158
+
159
+ CORRECT:
160
+ "Searching for config files." → [glob] → "Found 3 files. Reading the main one." → [read] → "I see the issue. Fixing now." → [edit] → "Done."
161
+
162
+ WRONG:
163
+ "Searching for config files." → [glob] → "Found 3 files. I'll read them next." → [STOP]
164
+
165
+ After EVERY tool result, you must either:
166
+ 1. Continue with the next action (use another tool), OR
167
+ 2. Complete the task with a summary, OR
168
+ 3. Ask the user via question tool if genuinely blocked
169
+
170
+ FORBIDDEN:
171
+ - Stopping mid-task after announcing what you'll do next
172
+ - Ending with "I'll do X next" without actually doing X
173
+ - Waiting for implicit user approval to continue
174
+
175
+ # Communication with Tools
176
+
177
+ BEFORE using tools:
178
+ - Brief explanation of what you're doing
179
+ - Then IMMEDIATELY use the tool in the same response
180
+
181
+ AFTER tool results:
182
+ - Brief comment on result if needed
183
+ - Then IMMEDIATELY continue to next action
184
+
185
+ AFTER tool errors:
186
+ - Explain what went wrong
187
+ - Then IMMEDIATELY retry with different approach
188
+
189
+ # File Modification - MANDATORY RULE
190
+
191
+ You MUST read a file BEFORE modifying it. This is NOT optional.
192
+
193
+ Correct workflow:
194
+ 1. "Let me examine the current implementation." → read(path="src/auth.ts")
195
+ 2. "I see the issue. I'll fix the validation logic." → edit(path="src/auth.ts", ...)
196
+
197
+ WRONG (will fail):
198
+ - Using edit or write on a file you haven't read in this conversation
199
+ - Assuming you know what's in a file without reading it
200
+
201
+ # Error Recovery
202
+
203
+ When a tool returns {"error": "..."}:
204
+ 1. Tell the user what went wrong
205
+ 2. Explain your retry strategy
206
+ 3. Try with adjusted parameters
207
+ 4. After 2-3 failures, explain the blocker and ask for help
208
+
209
+ # Question Tool - When to Use
210
+
211
+ USE question tool:
212
+ - Multiple valid approaches need user preference
213
+ - Destructive action needs confirmation
214
+ - Requirements are genuinely ambiguous
215
+ - A tool was rejected and you need to understand why
216
+
217
+ DO NOT use question tool:
218
+ - You can figure out the answer by exploring
219
+ - The path forward is reasonably clear
220
+ - It's a standard implementation decision
221
+
222
+ NEVER ask questions in plain text. The question tool is MANDATORY.
223
+
224
+ # Workflow Summary
225
+
226
+ 1. PLAN: Use plan unless the task is trivial (single obvious action)
227
+ 2. COMMUNICATE: Say what you're about to do
228
+ 3. READ: Always read files before modifying
229
+ 4. ACT: Use the appropriate tool
230
+ 5. VERIFY: Run tests/builds to confirm
231
+ 6. REPORT: Summarize what was done`;
232
+
233
+ export function getToolsPrompt(mcpToolInfos?: Array<{ serverId: string; name: string; description: string; inputSchema: Record<string, unknown>; canonicalId: string; safeId: string }>): string {
234
+ if (!mcpToolInfos || mcpToolInfos.length === 0) {
235
+ return TOOLS_PROMPT;
236
+ }
237
+
238
+ const mcpSection = buildMcpToolsSection(mcpToolInfos);
239
+ return TOOLS_PROMPT + '\n\n' + mcpSection;
240
+ }
241
+
242
+ function buildMcpToolsSection(tools: Array<{ serverId: string; name: string; description: string; inputSchema: Record<string, unknown>; canonicalId: string; safeId: string }>): string {
243
+ const lines: string[] = [];
244
+ lines.push('## External Tools (MCP)');
245
+ lines.push('');
246
+ lines.push('These tools are provided by external MCP servers. Call them by their tool name.');
247
+ lines.push('They may require approval before execution.');
248
+ lines.push('');
249
+
250
+ const byServer = new Map<string, typeof tools>();
251
+ for (const t of tools) {
252
+ const list = byServer.get(t.serverId) || [];
253
+ list.push(t);
254
+ byServer.set(t.serverId, list);
255
+ }
256
+
257
+ for (const [serverId, serverTools] of byServer) {
258
+ lines.push(`### Server: ${serverId}`);
259
+ lines.push('');
260
+ for (const t of serverTools) {
261
+ lines.push(`#### ${t.safeId}`);
262
+ if (t.description) {
263
+ lines.push(t.description);
264
+ }
265
+ const schema = t.inputSchema;
266
+ if (schema && typeof schema === 'object' && schema.properties) {
267
+ const props = schema.properties as Record<string, Record<string, unknown>>;
268
+ const required = (schema.required || []) as string[];
269
+ const paramLines: string[] = [];
270
+ for (const [key, propSchema] of Object.entries(props)) {
271
+ const type = propSchema.type || 'unknown';
272
+ const desc = propSchema.description || '';
273
+ const req = required.includes(key) ? 'required' : 'optional';
274
+ paramLines.push(`- ${key} (${type}, ${req})${desc ? ': ' + desc : ''}`);
275
+ }
276
+ if (paramLines.length > 0) {
277
+ lines.push('Parameters:');
278
+ lines.push(...paramLines);
279
+ }
280
+ }
281
+ lines.push('');
282
+ }
283
+ }
284
+
285
+ return lines.join('\n');
286
+ }