mcp-rubber-duck 1.1.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 (184) hide show
  1. package/.dockerignore +19 -0
  2. package/.env.desktop.example +145 -0
  3. package/.env.example +45 -0
  4. package/.env.pi.example +106 -0
  5. package/.env.template +165 -0
  6. package/.eslintrc.json +40 -0
  7. package/.github/ISSUE_TEMPLATE/bug_report.md +65 -0
  8. package/.github/ISSUE_TEMPLATE/feature_request.md +58 -0
  9. package/.github/ISSUE_TEMPLATE/question.md +67 -0
  10. package/.github/pull_request_template.md +111 -0
  11. package/.github/workflows/docker-build.yml +138 -0
  12. package/.github/workflows/release.yml +182 -0
  13. package/.github/workflows/security.yml +141 -0
  14. package/.github/workflows/semantic-release.yml +89 -0
  15. package/.prettierrc +10 -0
  16. package/.releaserc.json +66 -0
  17. package/CHANGELOG.md +95 -0
  18. package/CONTRIBUTING.md +242 -0
  19. package/Dockerfile +62 -0
  20. package/LICENSE +21 -0
  21. package/README.md +803 -0
  22. package/audit-ci.json +8 -0
  23. package/config/claude_desktop.json +14 -0
  24. package/config/config.example.json +91 -0
  25. package/dist/config/config.d.ts +51 -0
  26. package/dist/config/config.d.ts.map +1 -0
  27. package/dist/config/config.js +301 -0
  28. package/dist/config/config.js.map +1 -0
  29. package/dist/config/types.d.ts +356 -0
  30. package/dist/config/types.d.ts.map +1 -0
  31. package/dist/config/types.js +41 -0
  32. package/dist/config/types.js.map +1 -0
  33. package/dist/index.d.ts +3 -0
  34. package/dist/index.d.ts.map +1 -0
  35. package/dist/index.js +109 -0
  36. package/dist/index.js.map +1 -0
  37. package/dist/providers/duck-provider-enhanced.d.ts +29 -0
  38. package/dist/providers/duck-provider-enhanced.d.ts.map +1 -0
  39. package/dist/providers/duck-provider-enhanced.js +230 -0
  40. package/dist/providers/duck-provider-enhanced.js.map +1 -0
  41. package/dist/providers/enhanced-manager.d.ts +54 -0
  42. package/dist/providers/enhanced-manager.d.ts.map +1 -0
  43. package/dist/providers/enhanced-manager.js +217 -0
  44. package/dist/providers/enhanced-manager.js.map +1 -0
  45. package/dist/providers/manager.d.ts +28 -0
  46. package/dist/providers/manager.d.ts.map +1 -0
  47. package/dist/providers/manager.js +204 -0
  48. package/dist/providers/manager.js.map +1 -0
  49. package/dist/providers/provider.d.ts +29 -0
  50. package/dist/providers/provider.d.ts.map +1 -0
  51. package/dist/providers/provider.js +179 -0
  52. package/dist/providers/provider.js.map +1 -0
  53. package/dist/providers/types.d.ts +69 -0
  54. package/dist/providers/types.d.ts.map +1 -0
  55. package/dist/providers/types.js +2 -0
  56. package/dist/providers/types.js.map +1 -0
  57. package/dist/server.d.ts +24 -0
  58. package/dist/server.d.ts.map +1 -0
  59. package/dist/server.js +501 -0
  60. package/dist/server.js.map +1 -0
  61. package/dist/services/approval.d.ts +44 -0
  62. package/dist/services/approval.d.ts.map +1 -0
  63. package/dist/services/approval.js +159 -0
  64. package/dist/services/approval.js.map +1 -0
  65. package/dist/services/cache.d.ts +21 -0
  66. package/dist/services/cache.d.ts.map +1 -0
  67. package/dist/services/cache.js +63 -0
  68. package/dist/services/cache.js.map +1 -0
  69. package/dist/services/conversation.d.ts +24 -0
  70. package/dist/services/conversation.d.ts.map +1 -0
  71. package/dist/services/conversation.js +108 -0
  72. package/dist/services/conversation.js.map +1 -0
  73. package/dist/services/function-bridge.d.ts +41 -0
  74. package/dist/services/function-bridge.d.ts.map +1 -0
  75. package/dist/services/function-bridge.js +259 -0
  76. package/dist/services/function-bridge.js.map +1 -0
  77. package/dist/services/health.d.ts +17 -0
  78. package/dist/services/health.d.ts.map +1 -0
  79. package/dist/services/health.js +77 -0
  80. package/dist/services/health.js.map +1 -0
  81. package/dist/services/mcp-client-manager.d.ts +49 -0
  82. package/dist/services/mcp-client-manager.d.ts.map +1 -0
  83. package/dist/services/mcp-client-manager.js +279 -0
  84. package/dist/services/mcp-client-manager.js.map +1 -0
  85. package/dist/tools/approve-mcp-request.d.ts +9 -0
  86. package/dist/tools/approve-mcp-request.d.ts.map +1 -0
  87. package/dist/tools/approve-mcp-request.js +111 -0
  88. package/dist/tools/approve-mcp-request.js.map +1 -0
  89. package/dist/tools/ask-duck.d.ts +9 -0
  90. package/dist/tools/ask-duck.d.ts.map +1 -0
  91. package/dist/tools/ask-duck.js +43 -0
  92. package/dist/tools/ask-duck.js.map +1 -0
  93. package/dist/tools/chat-duck.d.ts +9 -0
  94. package/dist/tools/chat-duck.d.ts.map +1 -0
  95. package/dist/tools/chat-duck.js +57 -0
  96. package/dist/tools/chat-duck.js.map +1 -0
  97. package/dist/tools/clear-conversations.d.ts +8 -0
  98. package/dist/tools/clear-conversations.d.ts.map +1 -0
  99. package/dist/tools/clear-conversations.js +17 -0
  100. package/dist/tools/clear-conversations.js.map +1 -0
  101. package/dist/tools/compare-ducks.d.ts +8 -0
  102. package/dist/tools/compare-ducks.d.ts.map +1 -0
  103. package/dist/tools/compare-ducks.js +49 -0
  104. package/dist/tools/compare-ducks.js.map +1 -0
  105. package/dist/tools/duck-council.d.ts +8 -0
  106. package/dist/tools/duck-council.d.ts.map +1 -0
  107. package/dist/tools/duck-council.js +69 -0
  108. package/dist/tools/duck-council.js.map +1 -0
  109. package/dist/tools/get-pending-approvals.d.ts +15 -0
  110. package/dist/tools/get-pending-approvals.d.ts.map +1 -0
  111. package/dist/tools/get-pending-approvals.js +74 -0
  112. package/dist/tools/get-pending-approvals.js.map +1 -0
  113. package/dist/tools/list-ducks.d.ts +9 -0
  114. package/dist/tools/list-ducks.d.ts.map +1 -0
  115. package/dist/tools/list-ducks.js +47 -0
  116. package/dist/tools/list-ducks.js.map +1 -0
  117. package/dist/tools/list-models.d.ts +8 -0
  118. package/dist/tools/list-models.d.ts.map +1 -0
  119. package/dist/tools/list-models.js +72 -0
  120. package/dist/tools/list-models.js.map +1 -0
  121. package/dist/tools/mcp-status.d.ts +17 -0
  122. package/dist/tools/mcp-status.d.ts.map +1 -0
  123. package/dist/tools/mcp-status.js +100 -0
  124. package/dist/tools/mcp-status.js.map +1 -0
  125. package/dist/utils/ascii-art.d.ts +19 -0
  126. package/dist/utils/ascii-art.d.ts.map +1 -0
  127. package/dist/utils/ascii-art.js +73 -0
  128. package/dist/utils/ascii-art.js.map +1 -0
  129. package/dist/utils/logger.d.ts +3 -0
  130. package/dist/utils/logger.d.ts.map +1 -0
  131. package/dist/utils/logger.js +86 -0
  132. package/dist/utils/logger.js.map +1 -0
  133. package/dist/utils/safe-logger.d.ts +23 -0
  134. package/dist/utils/safe-logger.d.ts.map +1 -0
  135. package/dist/utils/safe-logger.js +145 -0
  136. package/dist/utils/safe-logger.js.map +1 -0
  137. package/docker-compose.yml +161 -0
  138. package/jest.config.js +26 -0
  139. package/package.json +65 -0
  140. package/scripts/build-multiarch.sh +290 -0
  141. package/scripts/deploy-raspbian.sh +410 -0
  142. package/scripts/deploy.sh +322 -0
  143. package/scripts/gh-deploy.sh +343 -0
  144. package/scripts/setup-docker-raspbian.sh +530 -0
  145. package/server.json +8 -0
  146. package/src/config/config.ts +357 -0
  147. package/src/config/types.ts +89 -0
  148. package/src/index.ts +114 -0
  149. package/src/providers/duck-provider-enhanced.ts +294 -0
  150. package/src/providers/enhanced-manager.ts +290 -0
  151. package/src/providers/manager.ts +257 -0
  152. package/src/providers/provider.ts +207 -0
  153. package/src/providers/types.ts +78 -0
  154. package/src/server.ts +603 -0
  155. package/src/services/approval.ts +225 -0
  156. package/src/services/cache.ts +79 -0
  157. package/src/services/conversation.ts +146 -0
  158. package/src/services/function-bridge.ts +329 -0
  159. package/src/services/health.ts +107 -0
  160. package/src/services/mcp-client-manager.ts +362 -0
  161. package/src/tools/approve-mcp-request.ts +126 -0
  162. package/src/tools/ask-duck.ts +74 -0
  163. package/src/tools/chat-duck.ts +82 -0
  164. package/src/tools/clear-conversations.ts +24 -0
  165. package/src/tools/compare-ducks.ts +67 -0
  166. package/src/tools/duck-council.ts +88 -0
  167. package/src/tools/get-pending-approvals.ts +90 -0
  168. package/src/tools/list-ducks.ts +65 -0
  169. package/src/tools/list-models.ts +101 -0
  170. package/src/tools/mcp-status.ts +117 -0
  171. package/src/utils/ascii-art.ts +85 -0
  172. package/src/utils/logger.ts +116 -0
  173. package/src/utils/safe-logger.ts +165 -0
  174. package/systemd/mcp-rubber-duck-with-ollama.service +55 -0
  175. package/systemd/mcp-rubber-duck.service +58 -0
  176. package/test-functionality.js +147 -0
  177. package/test-mcp-interface.js +221 -0
  178. package/tests/ascii-art.test.ts +36 -0
  179. package/tests/config.test.ts +239 -0
  180. package/tests/conversation.test.ts +308 -0
  181. package/tests/mcp-bridge.test.ts +291 -0
  182. package/tests/providers.test.ts +269 -0
  183. package/tests/tools/clear-conversations.test.ts +163 -0
  184. package/tsconfig.json +26 -0
@@ -0,0 +1,49 @@
1
+ import { duckArt } from '../utils/ascii-art.js';
2
+ import { logger } from '../utils/logger.js';
3
+ export async function compareDucksTool(providerManager, _cache, args) {
4
+ const { prompt, providers, model } = args;
5
+ if (!prompt) {
6
+ throw new Error('Prompt is required');
7
+ }
8
+ // Get responses from multiple ducks
9
+ const responses = await providerManager.compareDucks(prompt, providers, { model });
10
+ // Build comparison response
11
+ let response = `${duckArt.panel}\n`;
12
+ response += `Asked: "${prompt}"\n\n`;
13
+ response += `═══════════════════════════════════════\n\n`;
14
+ for (const duckResponse of responses) {
15
+ response += `🦆 **${duckResponse.nickname}** (${duckResponse.provider})\n`;
16
+ response += `─────────────────────────────────────\n`;
17
+ if (duckResponse.content.startsWith('Error:')) {
18
+ response += `❌ ${duckResponse.content}\n`;
19
+ }
20
+ else {
21
+ response += `${duckResponse.content}\n`;
22
+ response += `\n📍 Model: ${duckResponse.model}`;
23
+ if (duckResponse.usage) {
24
+ response += ` | 📊 Tokens: ${duckResponse.usage.total_tokens}`;
25
+ }
26
+ if (duckResponse.latency > 0) {
27
+ response += ` | ⏱️ ${duckResponse.latency}ms`;
28
+ }
29
+ if (duckResponse.cached) {
30
+ response += ` | 💾 Cached`;
31
+ }
32
+ }
33
+ response += `\n\n`;
34
+ }
35
+ // Add summary
36
+ const successCount = responses.filter(r => !r.content.startsWith('Error:')).length;
37
+ response += `═══════════════════════════════════════\n`;
38
+ response += `✅ ${successCount}/${responses.length} ducks responded successfully`;
39
+ logger.info(`Compared ${responses.length} ducks, ${successCount} successful`);
40
+ return {
41
+ content: [
42
+ {
43
+ type: 'text',
44
+ text: response,
45
+ },
46
+ ],
47
+ };
48
+ }
49
+ //# sourceMappingURL=compare-ducks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compare-ducks.js","sourceRoot":"","sources":["../../src/tools/compare-ducks.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAChD,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAE5C,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,eAAgC,EAChC,MAAe,EACf,IAA6B;IAE7B,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,KAAK,EAAE,GAAG,IAIpC,CAAC;IAEF,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CAAC,oBAAoB,CAAC,CAAC;IACxC,CAAC;IAED,oCAAoC;IACpC,MAAM,SAAS,GAAG,MAAM,eAAe,CAAC,YAAY,CAAC,MAAM,EAAE,SAAS,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;IAEnF,4BAA4B;IAC5B,IAAI,QAAQ,GAAG,GAAG,OAAO,CAAC,KAAK,IAAI,CAAC;IACpC,QAAQ,IAAI,WAAW,MAAM,OAAO,CAAC;IACrC,QAAQ,IAAI,6CAA6C,CAAC;IAE1D,KAAK,MAAM,YAAY,IAAI,SAAS,EAAE,CAAC;QACrC,QAAQ,IAAI,QAAQ,YAAY,CAAC,QAAQ,OAAO,YAAY,CAAC,QAAQ,KAAK,CAAC;QAC3E,QAAQ,IAAI,yCAAyC,CAAC;QAEtD,IAAI,YAAY,CAAC,OAAO,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC9C,QAAQ,IAAI,KAAK,YAAY,CAAC,OAAO,IAAI,CAAC;QAC5C,CAAC;aAAM,CAAC;YACN,QAAQ,IAAI,GAAG,YAAY,CAAC,OAAO,IAAI,CAAC;YACxC,QAAQ,IAAI,eAAe,YAAY,CAAC,KAAK,EAAE,CAAC;YAEhD,IAAI,YAAY,CAAC,KAAK,EAAE,CAAC;gBACvB,QAAQ,IAAI,iBAAiB,YAAY,CAAC,KAAK,CAAC,YAAY,EAAE,CAAC;YACjE,CAAC;YACD,IAAI,YAAY,CAAC,OAAO,GAAG,CAAC,EAAE,CAAC;gBAC7B,QAAQ,IAAI,SAAS,YAAY,CAAC,OAAO,IAAI,CAAC;YAChD,CAAC;YACD,IAAI,YAAY,CAAC,MAAM,EAAE,CAAC;gBACxB,QAAQ,IAAI,cAAc,CAAC;YAC7B,CAAC;QACH,CAAC;QAED,QAAQ,IAAI,MAAM,CAAC;IACrB,CAAC;IAED,cAAc;IACd,MAAM,YAAY,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC;IACnF,QAAQ,IAAI,2CAA2C,CAAC;IACxD,QAAQ,IAAI,KAAK,YAAY,IAAI,SAAS,CAAC,MAAM,+BAA+B,CAAC;IAEjF,MAAM,CAAC,IAAI,CAAC,YAAY,SAAS,CAAC,MAAM,WAAW,YAAY,aAAa,CAAC,CAAC;IAE9E,OAAO;QACL,OAAO,EAAE;YACP;gBACE,IAAI,EAAE,MAAM;gBACZ,IAAI,EAAE,QAAQ;aACf;SACF;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,8 @@
1
+ import { ProviderManager } from '../providers/manager.js';
2
+ export declare function duckCouncilTool(providerManager: ProviderManager, args: Record<string, unknown>): Promise<{
3
+ content: {
4
+ type: string;
5
+ text: string;
6
+ }[];
7
+ }>;
8
+ //# sourceMappingURL=duck-council.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"duck-council.d.ts","sourceRoot":"","sources":["../../src/tools/duck-council.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAI1D,wBAAsB,eAAe,CACnC,eAAe,EAAE,eAAe,EAChC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;;;;;GAiF9B"}
@@ -0,0 +1,69 @@
1
+ import { duckArt, getRandomDuckMessage } from '../utils/ascii-art.js';
2
+ import { logger } from '../utils/logger.js';
3
+ export async function duckCouncilTool(providerManager, args) {
4
+ const { prompt, model } = args;
5
+ if (!prompt) {
6
+ throw new Error('Prompt is required for the duck council');
7
+ }
8
+ logger.info('Convening the duck council...');
9
+ // Get all available ducks
10
+ const allProviders = providerManager.getProviderNames();
11
+ if (allProviders.length === 0) {
12
+ throw new Error('No ducks available for the council!');
13
+ }
14
+ // Get responses from all ducks
15
+ const responses = await providerManager.duckCouncil(prompt, { model });
16
+ // Build council response with a panel discussion format
17
+ let response = `${duckArt.panel}\n\n`;
18
+ response += `🎙️ **Duck Council Topic:** "${prompt}"\n`;
19
+ response += `👥 **${allProviders.length} ducks in attendance**\n\n`;
20
+ response += `═══════════════════════════════════════\n\n`;
21
+ // Present each duck's perspective
22
+ for (let i = 0; i < responses.length; i++) {
23
+ const duckResponse = responses[i];
24
+ const duckNumber = i + 1;
25
+ response += `**Duck #${duckNumber}: ${duckResponse.nickname}**\n`;
26
+ response += `─────────────────────────────────────\n`;
27
+ if (duckResponse.content.startsWith('Error:')) {
28
+ response += `🦆💬 *[Duck had to leave early: ${duckResponse.content}]*\n`;
29
+ }
30
+ else {
31
+ response += `🦆💬 "${duckResponse.content}"\n`;
32
+ // Add metadata in a subtle way
33
+ response += `\n`;
34
+ response += `*[${duckResponse.model}`;
35
+ if (duckResponse.latency > 0) {
36
+ response += ` • ${duckResponse.latency}ms`;
37
+ }
38
+ if (duckResponse.usage) {
39
+ response += ` • ${duckResponse.usage.total_tokens} tokens`;
40
+ }
41
+ response += `]*\n`;
42
+ }
43
+ response += `\n`;
44
+ }
45
+ // Add council summary
46
+ const successCount = responses.filter(r => !r.content.startsWith('Error:')).length;
47
+ response += `═══════════════════════════════════════\n`;
48
+ response += `🏛️ **Council Summary**\n`;
49
+ response += `• ${successCount}/${responses.length} ducks provided their wisdom\n`;
50
+ if (successCount === responses.length) {
51
+ response += `• ${getRandomDuckMessage('success')}\n`;
52
+ }
53
+ else if (successCount > 0) {
54
+ response += `• Partial council - some ducks were unavailable\n`;
55
+ }
56
+ else {
57
+ response += `• ${getRandomDuckMessage('error')}\n`;
58
+ }
59
+ logger.info(`Duck council completed: ${successCount}/${responses.length} responses`);
60
+ return {
61
+ content: [
62
+ {
63
+ type: 'text',
64
+ text: response,
65
+ },
66
+ ],
67
+ };
68
+ }
69
+ //# sourceMappingURL=duck-council.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"duck-council.js","sourceRoot":"","sources":["../../src/tools/duck-council.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AACtE,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAE5C,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,eAAgC,EAChC,IAA6B;IAE7B,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,IAGzB,CAAC;IAEF,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CAAC,yCAAyC,CAAC,CAAC;IAC7D,CAAC;IAED,MAAM,CAAC,IAAI,CAAC,+BAA+B,CAAC,CAAC;IAE7C,0BAA0B;IAC1B,MAAM,YAAY,GAAG,eAAe,CAAC,gBAAgB,EAAE,CAAC;IAExD,IAAI,YAAY,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC9B,MAAM,IAAI,KAAK,CAAC,qCAAqC,CAAC,CAAC;IACzD,CAAC;IAED,+BAA+B;IAC/B,MAAM,SAAS,GAAG,MAAM,eAAe,CAAC,WAAW,CAAC,MAAM,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;IAEvE,wDAAwD;IACxD,IAAI,QAAQ,GAAG,GAAG,OAAO,CAAC,KAAK,MAAM,CAAC;IACtC,QAAQ,IAAI,gCAAgC,MAAM,KAAK,CAAC;IACxD,QAAQ,IAAI,QAAQ,YAAY,CAAC,MAAM,4BAA4B,CAAC;IACpE,QAAQ,IAAI,6CAA6C,CAAC;IAE1D,kCAAkC;IAClC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,SAAS,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAC1C,MAAM,YAAY,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC;QAClC,MAAM,UAAU,GAAG,CAAC,GAAG,CAAC,CAAC;QAEzB,QAAQ,IAAI,WAAW,UAAU,KAAK,YAAY,CAAC,QAAQ,MAAM,CAAC;QAClE,QAAQ,IAAI,yCAAyC,CAAC;QAEtD,IAAI,YAAY,CAAC,OAAO,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC9C,QAAQ,IAAI,mCAAmC,YAAY,CAAC,OAAO,MAAM,CAAC;QAC5E,CAAC;aAAM,CAAC;YACN,QAAQ,IAAI,SAAS,YAAY,CAAC,OAAO,KAAK,CAAC;YAE/C,+BAA+B;YAC/B,QAAQ,IAAI,IAAI,CAAC;YACjB,QAAQ,IAAI,KAAK,YAAY,CAAC,KAAK,EAAE,CAAC;YACtC,IAAI,YAAY,CAAC,OAAO,GAAG,CAAC,EAAE,CAAC;gBAC7B,QAAQ,IAAI,MAAM,YAAY,CAAC,OAAO,IAAI,CAAC;YAC7C,CAAC;YACD,IAAI,YAAY,CAAC,KAAK,EAAE,CAAC;gBACvB,QAAQ,IAAI,MAAM,YAAY,CAAC,KAAK,CAAC,YAAY,SAAS,CAAC;YAC7D,CAAC;YACD,QAAQ,IAAI,MAAM,CAAC;QACrB,CAAC;QAED,QAAQ,IAAI,IAAI,CAAC;IACnB,CAAC;IAED,sBAAsB;IACtB,MAAM,YAAY,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC;IACnF,QAAQ,IAAI,2CAA2C,CAAC;IACxD,QAAQ,IAAI,2BAA2B,CAAC;IACxC,QAAQ,IAAI,KAAK,YAAY,IAAI,SAAS,CAAC,MAAM,gCAAgC,CAAC;IAElF,IAAI,YAAY,KAAK,SAAS,CAAC,MAAM,EAAE,CAAC;QACtC,QAAQ,IAAI,KAAK,oBAAoB,CAAC,SAAS,CAAC,IAAI,CAAC;IACvD,CAAC;SAAM,IAAI,YAAY,GAAG,CAAC,EAAE,CAAC;QAC5B,QAAQ,IAAI,mDAAmD,CAAC;IAClE,CAAC;SAAM,CAAC;QACN,QAAQ,IAAI,KAAK,oBAAoB,CAAC,OAAO,CAAC,IAAI,CAAC;IACrD,CAAC;IAED,MAAM,CAAC,IAAI,CAAC,2BAA2B,YAAY,IAAI,SAAS,CAAC,MAAM,YAAY,CAAC,CAAC;IAErF,OAAO;QACL,OAAO,EAAE;YACP;gBACE,IAAI,EAAE,MAAM;gBACZ,IAAI,EAAE,QAAQ;aACf;SACF;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,15 @@
1
+ import { ApprovalService } from '../services/approval.js';
2
+ export declare function getPendingApprovalsTool(approvalService: ApprovalService, args: Record<string, unknown>): {
3
+ content: {
4
+ type: string;
5
+ text: string;
6
+ }[];
7
+ isError?: undefined;
8
+ } | {
9
+ content: {
10
+ type: string;
11
+ text: string;
12
+ }[];
13
+ isError: boolean;
14
+ };
15
+ //# sourceMappingURL=get-pending-approvals.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-pending-approvals.d.ts","sourceRoot":"","sources":["../../src/tools/get-pending-approvals.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAE1D,wBAAgB,uBAAuB,CACrC,eAAe,EAAE,eAAe,EAChC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;;;;;;;;;;;;EAqF9B"}
@@ -0,0 +1,74 @@
1
+ export function getPendingApprovalsTool(approvalService, args) {
2
+ const { duck } = args;
3
+ try {
4
+ let approvals = approvalService.getPendingApprovals();
5
+ // Filter by duck if specified
6
+ if (duck) {
7
+ approvals = approvals.filter(approval => approval.duckName === duck);
8
+ }
9
+ if (approvals.length === 0) {
10
+ return {
11
+ content: [
12
+ {
13
+ type: 'text',
14
+ text: '✅ No pending MCP tool approvals',
15
+ },
16
+ ],
17
+ };
18
+ }
19
+ // Format approvals for display
20
+ const formattedApprovals = approvals.map(approval => {
21
+ const timeAgo = Math.round((Date.now() - approval.timestamp) / 1000);
22
+ const expiresIn = Math.round((approval.expiresAt - Date.now()) / 1000);
23
+ return {
24
+ id: approval.id,
25
+ duck: approval.duckName,
26
+ server: approval.mcpServer,
27
+ tool: approval.toolName,
28
+ arguments: approval.arguments,
29
+ requestedAgo: `${timeAgo}s ago`,
30
+ expiresIn: expiresIn > 0 ? `${expiresIn}s` : 'expired',
31
+ };
32
+ });
33
+ // Create summary text
34
+ const summaryLines = [
35
+ `🔔 ${approvals.length} pending MCP approval${approvals.length === 1 ? '' : 's'}:`,
36
+ '',
37
+ ];
38
+ formattedApprovals.forEach((approval, index) => {
39
+ summaryLines.push(`${index + 1}. **${approval.duck}** wants to call \`${approval.server}:${approval.tool}\``);
40
+ summaryLines.push(` ID: \`${approval.id}\``);
41
+ // Show arguments if they exist and are reasonably sized
42
+ const argsStr = JSON.stringify(approval.arguments);
43
+ if (argsStr.length < 100) {
44
+ summaryLines.push(` Args: \`${argsStr}\``);
45
+ }
46
+ else {
47
+ summaryLines.push(` Args: [${Object.keys(approval.arguments).length} parameters]`);
48
+ }
49
+ summaryLines.push(` Requested: ${approval.requestedAgo}, Expires: ${approval.expiresIn}`);
50
+ summaryLines.push('');
51
+ });
52
+ summaryLines.push('💡 Use `approve_mcp_request` to approve or deny requests');
53
+ return {
54
+ content: [
55
+ {
56
+ type: 'text',
57
+ text: summaryLines.join('\n'),
58
+ },
59
+ ],
60
+ };
61
+ }
62
+ catch (error) {
63
+ return {
64
+ content: [
65
+ {
66
+ type: 'text',
67
+ text: `❌ Failed to get pending approvals: ${error instanceof Error ? error.message : String(error)}`,
68
+ },
69
+ ],
70
+ isError: true,
71
+ };
72
+ }
73
+ }
74
+ //# sourceMappingURL=get-pending-approvals.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-pending-approvals.js","sourceRoot":"","sources":["../../src/tools/get-pending-approvals.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ import { ProviderManager } from '../providers/manager.js';
2
+ import { HealthMonitor } from '../services/health.js';
3
+ export declare function listDucksTool(providerManager: ProviderManager, healthMonitor: HealthMonitor, args: Record<string, unknown>): Promise<{
4
+ content: {
5
+ type: string;
6
+ text: string;
7
+ }[];
8
+ }>;
9
+ //# sourceMappingURL=list-ducks.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list-ducks.d.ts","sourceRoot":"","sources":["../../src/tools/list-ducks.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC1D,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAItD,wBAAsB,aAAa,CACjC,eAAe,EAAE,eAAe,EAChC,aAAa,EAAE,aAAa,EAC5B,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;;;;;GAwD9B"}
@@ -0,0 +1,47 @@
1
+ import { duckArt } from '../utils/ascii-art.js';
2
+ import { logger } from '../utils/logger.js';
3
+ export async function listDucksTool(providerManager, healthMonitor, args) {
4
+ const { check_health = false } = args;
5
+ // Perform health check if requested
6
+ if (check_health) {
7
+ await healthMonitor.performHealthChecks();
8
+ }
9
+ // Get all providers with their info
10
+ const providers = providerManager.getAllProviders();
11
+ const healthStatus = healthMonitor.getHealthStatus();
12
+ // Build response
13
+ let response = `${duckArt.panel}\n\n`;
14
+ response += `Found ${providers.length} duck(s) in the pond:\n\n`;
15
+ for (const provider of providers) {
16
+ const health = healthStatus.get(provider.name);
17
+ const statusEmoji = health?.healthy ? '✅' : health === undefined ? '❓' : '❌';
18
+ response += `${statusEmoji} **${provider.info.nickname}** (${provider.name})\n`;
19
+ response += ` 📍 Model: ${provider.info.model}\n`;
20
+ response += ` 🔗 Endpoint: ${provider.info.baseURL}\n`;
21
+ response += ` 🔑 API Key: ${provider.info.hasApiKey ? 'Configured' : 'Not required'}\n`;
22
+ if (health) {
23
+ response += ` 💓 Health: ${health.healthy ? 'Healthy' : 'Unhealthy'}`;
24
+ if (health.latency) {
25
+ response += ` (${health.latency}ms)`;
26
+ }
27
+ if (health.error) {
28
+ response += `\n ⚠️ Error: ${health.error}`;
29
+ }
30
+ response += `\n 🕒 Last check: ${health.lastCheck.toLocaleTimeString()}\n`;
31
+ }
32
+ response += '\n';
33
+ }
34
+ // Add summary
35
+ const healthyCount = Array.from(healthStatus.values()).filter(h => h.healthy).length;
36
+ response += `\n📊 Summary: ${healthyCount}/${providers.length} ducks are healthy and ready!`;
37
+ logger.info(`Listed ${providers.length} ducks, ${healthyCount} healthy`);
38
+ return {
39
+ content: [
40
+ {
41
+ type: 'text',
42
+ text: response,
43
+ },
44
+ ],
45
+ };
46
+ }
47
+ //# sourceMappingURL=list-ducks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list-ducks.js","sourceRoot":"","sources":["../../src/tools/list-ducks.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAChD,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAE5C,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,eAAgC,EAChC,aAA4B,EAC5B,IAA6B;IAE7B,MAAM,EAAE,YAAY,GAAG,KAAK,EAAE,GAAG,IAEhC,CAAC;IAEF,oCAAoC;IACpC,IAAI,YAAY,EAAE,CAAC;QACjB,MAAM,aAAa,CAAC,mBAAmB,EAAE,CAAC;IAC5C,CAAC;IAED,oCAAoC;IACpC,MAAM,SAAS,GAAG,eAAe,CAAC,eAAe,EAAE,CAAC;IACpD,MAAM,YAAY,GAAG,aAAa,CAAC,eAAe,EAAE,CAAC;IAErD,iBAAiB;IACjB,IAAI,QAAQ,GAAG,GAAG,OAAO,CAAC,KAAK,MAAM,CAAC;IACtC,QAAQ,IAAI,SAAS,SAAS,CAAC,MAAM,2BAA2B,CAAC;IAEjE,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;QACjC,MAAM,MAAM,GAAG,YAAY,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QAC/C,MAAM,WAAW,GAAG,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC;QAE7E,QAAQ,IAAI,GAAG,WAAW,MAAM,QAAQ,CAAC,IAAI,CAAC,QAAQ,OAAO,QAAQ,CAAC,IAAI,KAAK,CAAC;QAChF,QAAQ,IAAI,gBAAgB,QAAQ,CAAC,IAAI,CAAC,KAAK,IAAI,CAAC;QACpD,QAAQ,IAAI,mBAAmB,QAAQ,CAAC,IAAI,CAAC,OAAO,IAAI,CAAC;QACzD,QAAQ,IAAI,kBAAkB,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,cAAc,IAAI,CAAC;QAE1F,IAAI,MAAM,EAAE,CAAC;YACX,QAAQ,IAAI,iBAAiB,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;YACxE,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;gBACnB,QAAQ,IAAI,KAAK,MAAM,CAAC,OAAO,KAAK,CAAC;YACvC,CAAC;YACD,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;gBACjB,QAAQ,IAAI,kBAAkB,MAAM,CAAC,KAAK,EAAE,CAAC;YAC/C,CAAC;YACD,QAAQ,IAAI,uBAAuB,MAAM,CAAC,SAAS,CAAC,kBAAkB,EAAE,IAAI,CAAC;QAC/E,CAAC;QAED,QAAQ,IAAI,IAAI,CAAC;IACnB,CAAC;IAED,cAAc;IACd,MAAM,YAAY,GAAG,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC;IACrF,QAAQ,IAAI,iBAAiB,YAAY,IAAI,SAAS,CAAC,MAAM,+BAA+B,CAAC;IAE7F,MAAM,CAAC,IAAI,CAAC,UAAU,SAAS,CAAC,MAAM,WAAW,YAAY,UAAU,CAAC,CAAC;IAEzE,OAAO;QACL,OAAO,EAAE;YACP;gBACE,IAAI,EAAE,MAAM;gBACZ,IAAI,EAAE,QAAQ;aACf;SACF;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,8 @@
1
+ import { ProviderManager } from '../providers/manager.js';
2
+ export declare function listModelsTool(providerManager: ProviderManager, args: Record<string, unknown>): Promise<{
3
+ content: {
4
+ type: string;
5
+ text: string;
6
+ }[];
7
+ }>;
8
+ //# sourceMappingURL=list-models.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list-models.d.ts","sourceRoot":"","sources":["../../src/tools/list-models.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAK1D,wBAAsB,cAAc,CAClC,eAAe,EAAE,eAAe,EAChC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;;;;;GA0D9B"}
@@ -0,0 +1,72 @@
1
+ import { duckArt } from '../utils/ascii-art.js';
2
+ import { logger } from '../utils/logger.js';
3
+ export async function listModelsTool(providerManager, args) {
4
+ const { provider, fetch_latest = false } = args;
5
+ try {
6
+ let response = `${duckArt.panel}\n📋 **Available Models**\n\n`;
7
+ if (provider) {
8
+ // List models for a specific provider
9
+ const providerInfo = providerManager.getAllProviders().find(p => p.name === provider);
10
+ if (!providerInfo) {
11
+ throw new Error(`Provider "${provider}" not found`);
12
+ }
13
+ const models = await providerManager.getAvailableModels(provider);
14
+ response += formatProviderModels(providerInfo.info.nickname, provider, models, providerInfo.info.model);
15
+ }
16
+ else {
17
+ // List models for all providers
18
+ const allProviders = providerManager.getAllProviders();
19
+ for (const providerInfo of allProviders) {
20
+ try {
21
+ const models = await providerManager.getAvailableModels(providerInfo.name);
22
+ response += formatProviderModels(providerInfo.info.nickname, providerInfo.name, models, providerInfo.info.model);
23
+ response += '\n';
24
+ }
25
+ catch (error) {
26
+ logger.warn(`Failed to get models for ${providerInfo.name}:`, error);
27
+ response += `\n🦆 **${providerInfo.info.nickname}** (${providerInfo.name})\n`;
28
+ response += ` ⚠️ Failed to fetch models\n\n`;
29
+ }
30
+ }
31
+ }
32
+ response += `\n─────────────────────────────────────\n`;
33
+ response += fetch_latest ? '🔄 Fetched from API' : '📋 Using cached/configured models';
34
+ logger.info(`Listed models for ${provider || 'all providers'}`);
35
+ return {
36
+ content: [
37
+ {
38
+ type: 'text',
39
+ text: response,
40
+ },
41
+ ],
42
+ };
43
+ }
44
+ catch (error) {
45
+ logger.error('Error listing models:', error);
46
+ throw error;
47
+ }
48
+ }
49
+ function formatProviderModels(nickname, providerName, models, defaultModel) {
50
+ let output = `\n🦆 **${nickname}** (${providerName})\n`;
51
+ if (models.length === 0) {
52
+ output += ` 📭 No models available\n`;
53
+ return output;
54
+ }
55
+ for (const model of models) {
56
+ const isDefault = model.id === defaultModel;
57
+ const defaultMarker = isDefault ? ' **(default)**' : '';
58
+ output += ` • ${model.id}${defaultMarker}`;
59
+ if (model.description) {
60
+ output += ` - ${model.description}`;
61
+ }
62
+ else if (model.owned_by) {
63
+ output += ` - by ${model.owned_by}`;
64
+ }
65
+ if (model.context_window) {
66
+ output += ` [${model.context_window} tokens]`;
67
+ }
68
+ output += '\n';
69
+ }
70
+ return output;
71
+ }
72
+ //# sourceMappingURL=list-models.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list-models.js","sourceRoot":"","sources":["../../src/tools/list-models.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ import { MCPClientManager } from '../services/mcp-client-manager.js';
2
+ import { ApprovalService } from '../services/approval.js';
3
+ import { FunctionBridge } from '../services/function-bridge.js';
4
+ export declare function mcpStatusTool(mcpManager: MCPClientManager, approvalService: ApprovalService, functionBridge: FunctionBridge, _args: Record<string, unknown>): Promise<{
5
+ content: {
6
+ type: string;
7
+ text: string;
8
+ }[];
9
+ isError?: undefined;
10
+ } | {
11
+ content: {
12
+ type: string;
13
+ text: string;
14
+ }[];
15
+ isError: boolean;
16
+ }>;
17
+ //# sourceMappingURL=mcp-status.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp-status.d.ts","sourceRoot":"","sources":["../../src/tools/mcp-status.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,mCAAmC,CAAC;AACrE,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC1D,OAAO,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;AAEhE,wBAAsB,aAAa,CACjC,UAAU,EAAE,gBAAgB,EAC5B,eAAe,EAAE,eAAe,EAChC,cAAc,EAAE,cAAc,EAC9B,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;;;;;;;;;;;;GA4G/B"}
@@ -0,0 +1,100 @@
1
+ export async function mcpStatusTool(mcpManager, approvalService, functionBridge, _args) {
2
+ try {
3
+ // Get MCP server status
4
+ const serverStatus = mcpManager.getStatus();
5
+ const connectedServers = mcpManager.getConnectedServers();
6
+ // Get available tools
7
+ const allTools = await mcpManager.listAllTools();
8
+ const toolsByServer = allTools.reduce((acc, tool) => {
9
+ if (!acc[tool.serverName]) {
10
+ acc[tool.serverName] = [];
11
+ }
12
+ acc[tool.serverName].push(tool);
13
+ return acc;
14
+ }, {});
15
+ // Get approval statistics
16
+ const approvalStats = approvalService.getStats();
17
+ // Get function bridge statistics
18
+ const bridgeStats = functionBridge.getStats();
19
+ // Build status report
20
+ const statusLines = [
21
+ '🦆 **MCP Bridge Status**',
22
+ '',
23
+ '📊 **Overview:**',
24
+ `- Connected Servers: ${connectedServers.length}`,
25
+ `- Available Tools: ${allTools.length}`,
26
+ `- Trusted Tools: ${bridgeStats.trustedToolCount}`,
27
+ '',
28
+ ];
29
+ // Server details
30
+ if (Object.keys(serverStatus).length > 0) {
31
+ statusLines.push('🖥️ **MCP Servers:**');
32
+ for (const [serverName, status] of Object.entries(serverStatus)) {
33
+ const toolCount = toolsByServer[serverName]?.length || 0;
34
+ const statusIcon = status.status === 'connected' ? '🟢' :
35
+ status.status === 'connecting' ? '🟡' : '🔴';
36
+ statusLines.push(`${statusIcon} **${serverName}** (${status.type})`);
37
+ statusLines.push(` Status: ${status.status}`);
38
+ if (toolCount > 0) {
39
+ statusLines.push(` Tools: ${toolCount}`);
40
+ // Show first few tools as examples
41
+ const tools = toolsByServer[serverName];
42
+ if (tools && tools.length <= 3) {
43
+ statusLines.push(` Available: ${tools.map(t => t.name).join(', ')}`);
44
+ }
45
+ else if (tools && tools.length > 3) {
46
+ statusLines.push(` Available: ${tools.slice(0, 3).map(t => t.name).join(', ')} +${tools.length - 3} more`);
47
+ }
48
+ }
49
+ statusLines.push('');
50
+ }
51
+ }
52
+ else {
53
+ statusLines.push('🖥️ **No MCP servers configured**');
54
+ statusLines.push('');
55
+ }
56
+ // Approval statistics
57
+ statusLines.push('📋 **Approval Statistics:**');
58
+ statusLines.push(`- Total Requests: ${approvalStats.total}`);
59
+ statusLines.push(`- Pending: ${approvalStats.pending}`);
60
+ statusLines.push(`- Approved: ${approvalStats.approved}`);
61
+ statusLines.push(`- Denied: ${approvalStats.denied}`);
62
+ statusLines.push(`- Expired: ${approvalStats.expired}`);
63
+ // Show pending approvals if any
64
+ if (approvalStats.pending > 0) {
65
+ const pendingApprovals = approvalService.getPendingApprovals();
66
+ statusLines.push('');
67
+ statusLines.push('⏳ **Pending Approvals:**');
68
+ pendingApprovals.forEach(approval => {
69
+ const timeAgo = Math.round((Date.now() - approval.timestamp) / 1000);
70
+ statusLines.push(`- ${approval.duckName} → ${approval.mcpServer}:${approval.toolName} (${timeAgo}s ago)`);
71
+ });
72
+ }
73
+ // Configuration hints
74
+ statusLines.push('');
75
+ statusLines.push('💡 **Commands:**');
76
+ statusLines.push('- `get_pending_approvals` - View pending approval requests');
77
+ statusLines.push('- `approve_mcp_request` - Approve or deny requests');
78
+ statusLines.push('- `ask_duck` - Chat with ducks (MCP functions auto-enabled)');
79
+ return {
80
+ content: [
81
+ {
82
+ type: 'text',
83
+ text: statusLines.join('\n'),
84
+ },
85
+ ],
86
+ };
87
+ }
88
+ catch (error) {
89
+ return {
90
+ content: [
91
+ {
92
+ type: 'text',
93
+ text: `❌ Failed to get MCP status: ${error instanceof Error ? error.message : String(error)}`,
94
+ },
95
+ ],
96
+ isError: true,
97
+ };
98
+ }
99
+ }
100
+ //# sourceMappingURL=mcp-status.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp-status.js","sourceRoot":"","sources":["../../src/tools/mcp-status.ts"],"names":[],"mappings":"AAIA,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,UAA4B,EAC5B,eAAgC,EAChC,cAA8B,EAC9B,KAA8B;IAE9B,IAAI,CAAC;QACH,wBAAwB;QACxB,MAAM,YAAY,GAAG,UAAU,CAAC,SAAS,EAAE,CAAC;QAC5C,MAAM,gBAAgB,GAAG,UAAU,CAAC,mBAAmB,EAAE,CAAC;QAE1D,sBAAsB;QACtB,MAAM,QAAQ,GAAG,MAAM,UAAU,CAAC,YAAY,EAAE,CAAC;QACjD,MAAM,aAAa,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE;YAClD,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC;gBAC1B,GAAG,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,EAAE,CAAC;YAC5B,CAAC;YACD,GAAG,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAChC,OAAO,GAAG,CAAC;QACb,CAAC,EAAE,EAA+D,CAAC,CAAC;QAEpE,0BAA0B;QAC1B,MAAM,aAAa,GAAG,eAAe,CAAC,QAAQ,EAAE,CAAC;QAEjD,iCAAiC;QACjC,MAAM,WAAW,GAAG,cAAc,CAAC,QAAQ,EAAE,CAAC;QAE9C,sBAAsB;QACtB,MAAM,WAAW,GAAG;YAClB,0BAA0B;YAC1B,EAAE;YACF,kBAAkB;YAClB,wBAAwB,gBAAgB,CAAC,MAAM,EAAE;YACjD,sBAAsB,QAAQ,CAAC,MAAM,EAAE;YACvC,oBAAoB,WAAW,CAAC,gBAAgB,EAAE;YAClD,EAAE;SACH,CAAC;QAEF,iBAAiB;QACjB,IAAI,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACzC,WAAW,CAAC,IAAI,CAAC,sBAAsB,CAAC,CAAC;YACzC,KAAK,MAAM,CAAC,UAAU,EAAE,MAAM,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,YAAY,CAAC,EAAE,CAAC;gBAChE,MAAM,SAAS,GAAG,aAAa,CAAC,UAAU,CAAC,EAAE,MAAM,IAAI,CAAC,CAAC;gBACzD,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,KAAK,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;oBACvC,MAAM,CAAC,MAAM,KAAK,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;gBAE/D,WAAW,CAAC,IAAI,CAAC,GAAG,UAAU,MAAM,UAAU,OAAO,MAAM,CAAC,IAAI,GAAG,CAAC,CAAC;gBACrE,WAAW,CAAC,IAAI,CAAC,cAAc,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC;gBAChD,IAAI,SAAS,GAAG,CAAC,EAAE,CAAC;oBAClB,WAAW,CAAC,IAAI,CAAC,aAAa,SAAS,EAAE,CAAC,CAAC;oBAE3C,mCAAmC;oBACnC,MAAM,KAAK,GAAG,aAAa,CAAC,UAAU,CAAC,CAAC;oBACxC,IAAI,KAAK,IAAI,KAAK,CAAC,MAAM,IAAI,CAAC,EAAE,CAAC;wBAC/B,WAAW,CAAC,IAAI,CAAC,iBAAiB,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;oBACzE,CAAC;yBAAM,IAAI,KAAK,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;wBACrC,WAAW,CAAC,IAAI,CAAC,iBAAiB,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,KAAK,CAAC,MAAM,GAAG,CAAC,OAAO,CAAC,CAAC;oBAC/G,CAAC;gBACH,CAAC;gBACD,WAAW,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YACvB,CAAC;QACH,CAAC;aAAM,CAAC;YACN,WAAW,CAAC,IAAI,CAAC,mCAAmC,CAAC,CAAC;YACtD,WAAW,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACvB,CAAC;QAED,sBAAsB;QACtB,WAAW,CAAC,IAAI,CAAC,6BAA6B,CAAC,CAAC;QAChD,WAAW,CAAC,IAAI,CAAC,qBAAqB,aAAa,CAAC,KAAK,EAAE,CAAC,CAAC;QAC7D,WAAW,CAAC,IAAI,CAAC,cAAc,aAAa,CAAC,OAAO,EAAE,CAAC,CAAC;QACxD,WAAW,CAAC,IAAI,CAAC,eAAe,aAAa,CAAC,QAAQ,EAAE,CAAC,CAAC;QAC1D,WAAW,CAAC,IAAI,CAAC,aAAa,aAAa,CAAC,MAAM,EAAE,CAAC,CAAC;QACtD,WAAW,CAAC,IAAI,CAAC,cAAc,aAAa,CAAC,OAAO,EAAE,CAAC,CAAC;QAExD,gCAAgC;QAChC,IAAI,aAAa,CAAC,OAAO,GAAG,CAAC,EAAE,CAAC;YAC9B,MAAM,gBAAgB,GAAG,eAAe,CAAC,mBAAmB,EAAE,CAAC;YAC/D,WAAW,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YACrB,WAAW,CAAC,IAAI,CAAC,0BAA0B,CAAC,CAAC;YAC7C,gBAAgB,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE;gBAClC,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,QAAQ,CAAC,SAAS,CAAC,GAAG,IAAI,CAAC,CAAC;gBACrE,WAAW,CAAC,IAAI,CAAC,KAAK,QAAQ,CAAC,QAAQ,MAAM,QAAQ,CAAC,SAAS,IAAI,QAAQ,CAAC,QAAQ,KAAK,OAAO,QAAQ,CAAC,CAAC;YAC5G,CAAC,CAAC,CAAC;QACL,CAAC;QAED,sBAAsB;QACtB,WAAW,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACrB,WAAW,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC;QACrC,WAAW,CAAC,IAAI,CAAC,4DAA4D,CAAC,CAAC;QAC/E,WAAW,CAAC,IAAI,CAAC,oDAAoD,CAAC,CAAC;QACvE,WAAW,CAAC,IAAI,CAAC,6DAA6D,CAAC,CAAC;QAEhF,OAAO;YACL,OAAO,EAAE;gBACP;oBACE,IAAI,EAAE,MAAM;oBACZ,IAAI,EAAE,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC;iBAC7B;aACF;SACF,CAAC;IAEJ,CAAC;IAAC,OAAO,KAAc,EAAE,CAAC;QACxB,OAAO;YACL,OAAO,EAAE;gBACP;oBACE,IAAI,EAAE,MAAM;oBACZ,IAAI,EAAE,+BAA+B,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE;iBAC9F;aACF;YACD,OAAO,EAAE,IAAI;SACd,CAAC;IACJ,CAAC;AACH,CAAC"}
@@ -0,0 +1,19 @@
1
+ export declare const duckArt: {
2
+ normal: string;
3
+ happy: string;
4
+ thinking: string;
5
+ error: string;
6
+ sleeping: string;
7
+ panel: string;
8
+ welcome: string;
9
+ };
10
+ export declare const duckMessages: {
11
+ startup: string[];
12
+ error: string[];
13
+ success: string[];
14
+ thinking: string[];
15
+ failover: string[];
16
+ };
17
+ export declare function getRandomDuckMessage(type: keyof typeof duckMessages): string;
18
+ export declare function formatDuckResponse(provider: string, message: string, model?: string): string;
19
+ //# sourceMappingURL=ascii-art.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ascii-art.d.ts","sourceRoot":"","sources":["../../src/utils/ascii-art.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,OAAO;;;;;;;;CAwCnB,CAAC;AAEF,eAAO,MAAM,YAAY;;;;;;CA8BxB,CAAC;AAEF,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,OAAO,YAAY,GAAG,MAAM,CAG5E;AAED,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAK5F"}
@@ -0,0 +1,73 @@
1
+ export const duckArt = {
2
+ normal: `
3
+ __
4
+ <(o )___
5
+ ( ._> /
6
+ \`---'`,
7
+ happy: `
8
+ __
9
+ <(^v^)___
10
+ ( ._> /
11
+ \`---'`,
12
+ thinking: `
13
+ __ ?
14
+ <(o )___
15
+ ( ._> /
16
+ \`---'`,
17
+ error: `
18
+ __ !
19
+ <(x_x)___
20
+ ( ._> /
21
+ \`---'`,
22
+ sleeping: `
23
+ __ zzz
24
+ <(- -)___
25
+ ( ._> /
26
+ \`---'`,
27
+ panel: `
28
+ 🦆 Duck Council in Session 🦆
29
+ =============================`,
30
+ welcome: `
31
+ ╔══════════════════════════════════════╗
32
+ ║ Welcome to MCP Rubber Duck! 🦆 ║
33
+ ║ Your AI debugging companions ║
34
+ ╚══════════════════════════════════════╝`,
35
+ };
36
+ export const duckMessages = {
37
+ startup: [
38
+ 'Quack! Rubber ducks reporting for duty!',
39
+ 'Ducks assembled and ready to debug!',
40
+ 'The duck pond is open for business!',
41
+ ],
42
+ error: [
43
+ 'Quack! The duck has flown away!',
44
+ 'Oh no! This duck got confused!',
45
+ 'The duck needs a moment to think...',
46
+ ],
47
+ success: [
48
+ 'Quack quack! Problem solved!',
49
+ 'The duck has spoken wisely!',
50
+ 'Another successful rubber duck session!',
51
+ ],
52
+ thinking: [
53
+ 'The duck is pondering...',
54
+ 'Hmm, let the duck think about this...',
55
+ 'Duck brain processing...',
56
+ ],
57
+ failover: [
58
+ 'Primary duck is resting, calling backup duck!',
59
+ 'Switching to a fresh duck!',
60
+ 'Backup duck swimming in!',
61
+ ],
62
+ };
63
+ export function getRandomDuckMessage(type) {
64
+ const messages = duckMessages[type];
65
+ return messages[Math.floor(Math.random() * messages.length)];
66
+ }
67
+ export function formatDuckResponse(provider, message, model) {
68
+ if (model) {
69
+ return `🦆 [${provider} | ${model}]: ${message}`;
70
+ }
71
+ return `🦆 [${provider}]: ${message}`;
72
+ }
73
+ //# sourceMappingURL=ascii-art.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ascii-art.js","sourceRoot":"","sources":["../../src/utils/ascii-art.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,OAAO,GAAG;IACrB,MAAM,EAAE;;;;YAIE;IAEV,KAAK,EAAE;;;;YAIG;IAEV,QAAQ,EAAE;;;;YAIA;IAEV,KAAK,EAAE;;;;YAIG;IAEV,QAAQ,EAAE;;;;YAIA;IAEV,KAAK,EAAE;;gCAEuB;IAE9B,OAAO,EAAE;;;;yCAI8B;CACxC,CAAC;AAEF,MAAM,CAAC,MAAM,YAAY,GAAG;IAC1B,OAAO,EAAE;QACP,yCAAyC;QACzC,qCAAqC;QACrC,qCAAqC;KACtC;IAED,KAAK,EAAE;QACL,iCAAiC;QACjC,gCAAgC;QAChC,qCAAqC;KACtC;IAED,OAAO,EAAE;QACP,8BAA8B;QAC9B,6BAA6B;QAC7B,yCAAyC;KAC1C;IAED,QAAQ,EAAE;QACR,0BAA0B;QAC1B,uCAAuC;QACvC,0BAA0B;KAC3B;IAED,QAAQ,EAAE;QACR,+CAA+C;QAC/C,4BAA4B;QAC5B,0BAA0B;KAC3B;CACF,CAAC;AAEF,MAAM,UAAU,oBAAoB,CAAC,IAA+B;IAClE,MAAM,QAAQ,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;IACpC,OAAO,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC;AAC/D,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,QAAgB,EAAE,OAAe,EAAE,KAAc;IAClF,IAAI,KAAK,EAAE,CAAC;QACV,OAAO,OAAO,QAAQ,MAAM,KAAK,MAAM,OAAO,EAAE,CAAC;IACnD,CAAC;IACD,OAAO,OAAO,QAAQ,MAAM,OAAO,EAAE,CAAC;AACxC,CAAC"}