jinn-cli 0.5.3 → 0.6.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 (163) hide show
  1. package/dist/bin/jimmy.js +0 -0
  2. package/dist/src/cli/status.d.ts.map +1 -1
  3. package/dist/src/cli/status.js +10 -1
  4. package/dist/src/cli/status.js.map +1 -1
  5. package/dist/src/connectors/discord/format.d.ts +3 -0
  6. package/dist/src/connectors/discord/format.d.ts.map +1 -0
  7. package/dist/src/connectors/discord/format.js +33 -0
  8. package/dist/src/connectors/discord/format.js.map +1 -0
  9. package/dist/src/connectors/discord/index.d.ts +41 -0
  10. package/dist/src/connectors/discord/index.d.ts.map +1 -0
  11. package/dist/src/connectors/discord/index.js +302 -0
  12. package/dist/src/connectors/discord/index.js.map +1 -0
  13. package/dist/src/connectors/discord/remote.d.ts +33 -0
  14. package/dist/src/connectors/discord/remote.d.ts.map +1 -0
  15. package/dist/src/connectors/discord/remote.js +89 -0
  16. package/dist/src/connectors/discord/remote.js.map +1 -0
  17. package/dist/src/connectors/discord/threads.d.ts +5 -0
  18. package/dist/src/connectors/discord/threads.d.ts.map +1 -0
  19. package/dist/src/connectors/discord/threads.js +22 -0
  20. package/dist/src/connectors/discord/threads.js.map +1 -0
  21. package/dist/src/connectors/whatsapp/format.d.ts +2 -0
  22. package/dist/src/connectors/whatsapp/format.d.ts.map +1 -0
  23. package/dist/src/connectors/whatsapp/format.js +22 -0
  24. package/dist/src/connectors/whatsapp/format.js.map +1 -0
  25. package/dist/src/connectors/whatsapp/index.d.ts +42 -0
  26. package/dist/src/connectors/whatsapp/index.d.ts.map +1 -0
  27. package/dist/src/connectors/whatsapp/index.js +279 -0
  28. package/dist/src/connectors/whatsapp/index.js.map +1 -0
  29. package/dist/src/engines/claude.d.ts +5 -0
  30. package/dist/src/engines/claude.d.ts.map +1 -1
  31. package/dist/src/engines/claude.js +192 -22
  32. package/dist/src/engines/claude.js.map +1 -1
  33. package/dist/src/gateway/api.d.ts +1 -0
  34. package/dist/src/gateway/api.d.ts.map +1 -1
  35. package/dist/src/gateway/api.js +705 -18
  36. package/dist/src/gateway/api.js.map +1 -1
  37. package/dist/src/gateway/lifecycle.d.ts.map +1 -1
  38. package/dist/src/gateway/lifecycle.js +32 -15
  39. package/dist/src/gateway/lifecycle.js.map +1 -1
  40. package/dist/src/gateway/project-tagger.d.ts +20 -0
  41. package/dist/src/gateway/project-tagger.d.ts.map +1 -0
  42. package/dist/src/gateway/project-tagger.js +55 -0
  43. package/dist/src/gateway/project-tagger.js.map +1 -0
  44. package/dist/src/gateway/project-tagger.test.d.ts +2 -0
  45. package/dist/src/gateway/project-tagger.test.d.ts.map +1 -0
  46. package/dist/src/gateway/project-tagger.test.js +110 -0
  47. package/dist/src/gateway/project-tagger.test.js.map +1 -0
  48. package/dist/src/gateway/projects.d.ts +15 -0
  49. package/dist/src/gateway/projects.d.ts.map +1 -0
  50. package/dist/src/gateway/projects.js +48 -0
  51. package/dist/src/gateway/projects.js.map +1 -0
  52. package/dist/src/gateway/projects.test.d.ts +2 -0
  53. package/dist/src/gateway/projects.test.d.ts.map +1 -0
  54. package/dist/src/gateway/projects.test.js +85 -0
  55. package/dist/src/gateway/projects.test.js.map +1 -0
  56. package/dist/src/gateway/server.d.ts.map +1 -1
  57. package/dist/src/gateway/server.js +90 -2
  58. package/dist/src/gateway/server.js.map +1 -1
  59. package/dist/src/gateway/tasks.d.ts +14 -0
  60. package/dist/src/gateway/tasks.d.ts.map +1 -0
  61. package/dist/src/gateway/tasks.js +51 -0
  62. package/dist/src/gateway/tasks.js.map +1 -0
  63. package/dist/src/gateway/tasks.test.d.ts +2 -0
  64. package/dist/src/gateway/tasks.test.d.ts.map +1 -0
  65. package/dist/src/gateway/tasks.test.js +131 -0
  66. package/dist/src/gateway/tasks.test.js.map +1 -0
  67. package/dist/src/sessions/callbacks.d.ts +29 -0
  68. package/dist/src/sessions/callbacks.d.ts.map +1 -0
  69. package/dist/src/sessions/callbacks.js +110 -0
  70. package/dist/src/sessions/callbacks.js.map +1 -0
  71. package/dist/src/sessions/context.js +4 -3
  72. package/dist/src/sessions/context.js.map +1 -1
  73. package/dist/src/sessions/engine-override.d.ts +3 -0
  74. package/dist/src/sessions/engine-override.d.ts.map +1 -0
  75. package/dist/src/sessions/engine-override.js +42 -0
  76. package/dist/src/sessions/engine-override.js.map +1 -0
  77. package/dist/src/sessions/manager.d.ts.map +1 -1
  78. package/dist/src/sessions/manager.js +385 -40
  79. package/dist/src/sessions/manager.js.map +1 -1
  80. package/dist/src/sessions/queue.d.ts +19 -2
  81. package/dist/src/sessions/queue.d.ts.map +1 -1
  82. package/dist/src/sessions/queue.js +44 -13
  83. package/dist/src/sessions/queue.js.map +1 -1
  84. package/dist/src/sessions/registry.d.ts +21 -1
  85. package/dist/src/sessions/registry.d.ts.map +1 -1
  86. package/dist/src/sessions/registry.js +62 -0
  87. package/dist/src/sessions/registry.js.map +1 -1
  88. package/dist/src/shared/rateLimit.d.ts +13 -0
  89. package/dist/src/shared/rateLimit.d.ts.map +1 -0
  90. package/dist/src/shared/rateLimit.js +30 -0
  91. package/dist/src/shared/rateLimit.js.map +1 -0
  92. package/dist/src/shared/types.d.ts +46 -3
  93. package/dist/src/shared/types.d.ts.map +1 -1
  94. package/dist/src/shared/usageAwareness.d.ts +10 -0
  95. package/dist/src/shared/usageAwareness.d.ts.map +1 -0
  96. package/dist/src/shared/usageAwareness.js +62 -0
  97. package/dist/src/shared/usageAwareness.js.map +1 -0
  98. package/dist/web/404.html +1 -1
  99. package/dist/web/_next/static/chunks/184-5a617386af9a1dd3.js +1 -0
  100. package/dist/web/_next/static/chunks/700-ad04a2a5b3c8880f.js +1 -0
  101. package/dist/web/_next/static/chunks/app/chat/page-36edb6fc1d1e880b.js +1 -0
  102. package/dist/web/_next/static/chunks/app/costs/{page-7940c2fe7e3dace1.js → page-6c5cd46a6b3cde21.js} +1 -1
  103. package/dist/web/_next/static/chunks/app/cron/{page-f81a986689712af7.js → page-210d9d333a7eed94.js} +1 -1
  104. package/dist/web/_next/static/chunks/app/kanban/page-c32370bcd6a7c841.js +1 -0
  105. package/dist/web/_next/static/chunks/app/layout-3ad6b73a0904c24b.js +1 -0
  106. package/dist/web/_next/static/chunks/app/logs/page-7322a6789e16dca4.js +1 -0
  107. package/dist/web/_next/static/chunks/app/org/{page-3d44d51e94edb85e.js → page-02263c5702e0fd3e.js} +1 -1
  108. package/dist/web/_next/static/chunks/app/{page-7ac43789d477a51f.js → page-b68dcf7b8802c704.js} +1 -1
  109. package/dist/web/_next/static/chunks/app/sessions/page-bf7ad2fac281c7d6.js +1 -0
  110. package/dist/web/_next/static/chunks/app/settings/page-d3b89563c42be2e5.js +1 -0
  111. package/dist/web/_next/static/chunks/app/skills/{page-26b727333df9db45.js → page-194f4e97f29ab581.js} +1 -1
  112. package/dist/web/_next/static/css/b809b6af2d241fc8.css +1 -0
  113. package/dist/web/chat.html +1 -1
  114. package/dist/web/chat.txt +4 -4
  115. package/dist/web/costs.html +2 -2
  116. package/dist/web/costs.txt +4 -4
  117. package/dist/web/cron.html +1 -1
  118. package/dist/web/cron.txt +4 -4
  119. package/dist/web/index.html +1 -1
  120. package/dist/web/index.txt +4 -4
  121. package/dist/web/kanban.html +1 -1
  122. package/dist/web/kanban.txt +4 -4
  123. package/dist/web/logs.html +2 -2
  124. package/dist/web/logs.txt +4 -4
  125. package/dist/web/org.html +1 -1
  126. package/dist/web/org.txt +4 -4
  127. package/dist/web/sessions.html +1 -1
  128. package/dist/web/sessions.txt +14 -17
  129. package/dist/web/settings.html +1 -1
  130. package/dist/web/settings.txt +4 -4
  131. package/dist/web/skills.html +1 -1
  132. package/dist/web/skills.txt +4 -4
  133. package/package.json +6 -1
  134. package/dist/web/_next/static/chunks/282-4e9c26e9a600c58e.js +0 -1
  135. package/dist/web/_next/static/chunks/700-a7cbf54fe1fbf4bc.js +0 -1
  136. package/dist/web/_next/static/chunks/app/chat/page-757fcd211d059cb7.js +0 -1
  137. package/dist/web/_next/static/chunks/app/kanban/page-6ab8586b063ca3ac.js +0 -1
  138. package/dist/web/_next/static/chunks/app/layout-c24e2d25774ff71a.js +0 -1
  139. package/dist/web/_next/static/chunks/app/logs/page-388b787cb847ca97.js +0 -1
  140. package/dist/web/_next/static/chunks/app/sessions/page-18757fcd067b7e9d.js +0 -1
  141. package/dist/web/_next/static/chunks/app/settings/page-f62176848534f90a.js +0 -1
  142. package/dist/web/_next/static/css/bd612b1ca9b40306.css +0 -1
  143. package/dist/web/app-build-manifest.json +0 -3
  144. package/dist/web/build-manifest.json +0 -17
  145. package/dist/web/react-loadable-manifest.json +0 -1
  146. package/dist/web/server/app-paths-manifest.json +0 -1
  147. package/dist/web/server/interception-route-rewrite-manifest.js +0 -1
  148. package/dist/web/server/middleware-build-manifest.js +0 -19
  149. package/dist/web/server/middleware-manifest.json +0 -6
  150. package/dist/web/server/middleware-react-loadable-manifest.js +0 -1
  151. package/dist/web/server/next-font-manifest.js +0 -1
  152. package/dist/web/server/next-font-manifest.json +0 -1
  153. package/dist/web/server/pages-manifest.json +0 -1
  154. package/dist/web/server/server-reference-manifest.js +0 -1
  155. package/dist/web/server/server-reference-manifest.json +0 -5
  156. package/dist/web/static/development/_buildManifest.js +0 -1
  157. package/dist/web/static/development/_ssgManifest.js +0 -1
  158. package/dist/web/types/cache-life.d.ts +0 -141
  159. package/dist/web/types/package.json +0 -1
  160. package/dist/web/types/routes.d.ts +0 -66
  161. package/dist/web/types/validator.ts +0 -142
  162. /package/dist/web/_next/static/{J4YFiPdzNcFHieP2FIPPe → QrKxazgwMrykF2yLwDvUM}/_buildManifest.js +0 -0
  163. /package/dist/web/_next/static/{J4YFiPdzNcFHieP2FIPPe → QrKxazgwMrykF2yLwDvUM}/_ssgManifest.js +0 -0
package/dist/bin/jimmy.js CHANGED
File without changes
@@ -1 +1 @@
1
- {"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../../src/cli/status.ts"],"names":[],"mappings":"AAKA,wBAAsB,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC,CAwD/C"}
1
+ {"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../../src/cli/status.ts"],"names":[],"mappings":"AAKA,wBAAsB,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC,CAgE/C"}
@@ -39,7 +39,16 @@ export async function runStatus() {
39
39
  const data = await res.json();
40
40
  console.log(` Port: ${config.gateway.port}`);
41
41
  if (data.sessions !== undefined) {
42
- console.log(` Active sessions: ${data.sessions}`);
42
+ if (typeof data.sessions === "object" && data.sessions && !Array.isArray(data.sessions)) {
43
+ const s = data.sessions;
44
+ const total = s.total ?? 0;
45
+ const active = s.active ?? 0;
46
+ const running = s.running ?? 0;
47
+ console.log(` Active sessions: ${active} (running: ${running}, total: ${total})`);
48
+ }
49
+ else {
50
+ console.log(` Active sessions: ${data.sessions}`);
51
+ }
43
52
  }
44
53
  if (data.uptime !== undefined) {
45
54
  console.log(` Server uptime: ${data.uptime}s`);
@@ -1 +1 @@
1
- {"version":3,"file":"status.js","sourceRoot":"","sources":["../../../src/cli/status.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"status.js","sourceRoot":"","sources":["../../../src/cli/status.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AACpD,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACjD,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAAE,MAAM,SAAS,CAAC;AAEzB,MAAM,CAAC,KAAK,UAAU,SAAS;IAC7B,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;QAC9B,OAAO,CAAC,GAAG,CAAC,kDAAkD,CAAC,CAAC;QAChE,OAAO;IACT,CAAC;IAED,MAAM,MAAM,GAAG,SAAS,EAAE,CAAC;IAE3B,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;QACpB,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC;QAChC,IAAI,MAAM,CAAC,GAAG,EAAE,CAAC;YACf,OAAO,CAAC,GAAG,CAAC,+BAA+B,MAAM,CAAC,GAAG,0BAA0B,CAAC,CAAC;QACnF,CAAC;QACD,OAAO;IACT,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC;IAChC,OAAO,CAAC,GAAG,CAAC,UAAU,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC;IAEpC,wCAAwC;IACxC,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;QACnC,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,OAAO,CAAC;QAC3C,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,GAAG,IAAI,CAAC,CAAC;QAC9C,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,GAAG,IAAI,CAAC,CAAC;QAC3C,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;QACpD,MAAM,OAAO,GAAG,SAAS,GAAG,EAAE,CAAC;QAC/B,OAAO,CAAC,GAAG,CAAC,aAAa,KAAK,KAAK,OAAO,KAAK,OAAO,GAAG,CAAC,CAAC;IAC7D,CAAC;IAAC,MAAM,CAAC;QACP,SAAS;IACX,CAAC;IAED,yCAAyC;IACzC,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;QAC5B,MAAM,GAAG,GAAG,UAAU,MAAM,CAAC,OAAO,CAAC,IAAI,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,aAAa,CAAC;QAC9E,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE,EAAE,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACpE,IAAI,GAAG,CAAC,EAAE,EAAE,CAAC;YACX,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;YAC9B,OAAO,CAAC,GAAG,CAAC,WAAW,MAAM,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;YAC9C,IAAI,IAAI,CAAC,QAAQ,KAAK,SAAS,EAAE,CAAC;gBAChC,IAAI,OAAO,IAAI,CAAC,QAAQ,KAAK,QAAQ,IAAI,IAAI,CAAC,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;oBACxF,MAAM,CAAC,GAAG,IAAI,CAAC,QAAiE,CAAC;oBACjF,MAAM,KAAK,GAAG,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC;oBAC3B,MAAM,MAAM,GAAG,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC;oBAC7B,MAAM,OAAO,GAAG,CAAC,CAAC,OAAO,IAAI,CAAC,CAAC;oBAC/B,OAAO,CAAC,GAAG,CAAC,sBAAsB,MAAM,cAAc,OAAO,YAAY,KAAK,GAAG,CAAC,CAAC;gBACrF,CAAC;qBAAM,CAAC;oBACN,OAAO,CAAC,GAAG,CAAC,sBAAsB,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC;gBACrD,CAAC;YACH,CAAC;YACD,IAAI,IAAI,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;gBAC9B,OAAO,CAAC,GAAG,CAAC,oBAAoB,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC;YAClD,CAAC;QACH,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,8CAA8C;QAC9C,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;YAC5B,OAAO,CAAC,GAAG,CAAC,WAAW,MAAM,CAAC,OAAO,CAAC,IAAI,2BAA2B,CAAC,CAAC;QACzE,CAAC;QAAC,MAAM,CAAC;YACP,YAAY;QACd,CAAC;IACH,CAAC;AACH,CAAC"}
@@ -0,0 +1,3 @@
1
+ export declare function formatResponse(text: string): string[];
2
+ export declare function downloadAttachment(url: string, destDir: string, filename: string): Promise<string>;
3
+ //# sourceMappingURL=format.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"format.d.ts","sourceRoot":"","sources":["../../../../src/connectors/discord/format.ts"],"names":[],"mappings":"AAEA,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAgBrD;AAED,wBAAsB,kBAAkB,CACtC,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,MAAM,CAAC,CASjB"}
@@ -0,0 +1,33 @@
1
+ const DISCORD_MAX_LENGTH = 2000;
2
+ export function formatResponse(text) {
3
+ if (text.length <= DISCORD_MAX_LENGTH)
4
+ return [text];
5
+ const chunks = [];
6
+ let remaining = text;
7
+ while (remaining.length > 0) {
8
+ if (remaining.length <= DISCORD_MAX_LENGTH) {
9
+ chunks.push(remaining);
10
+ break;
11
+ }
12
+ let cutAt = remaining.lastIndexOf("\n", DISCORD_MAX_LENGTH);
13
+ if (cutAt <= 0)
14
+ cutAt = remaining.lastIndexOf(" ", DISCORD_MAX_LENGTH);
15
+ if (cutAt <= 0)
16
+ cutAt = DISCORD_MAX_LENGTH;
17
+ chunks.push(remaining.slice(0, cutAt));
18
+ remaining = remaining.slice(cutAt).trimStart();
19
+ }
20
+ return chunks;
21
+ }
22
+ export async function downloadAttachment(url, destDir, filename) {
23
+ const { default: fs } = await import("node:fs");
24
+ const { default: path } = await import("node:path");
25
+ const destPath = path.join(destDir, filename);
26
+ const res = await fetch(url);
27
+ if (!res.ok)
28
+ throw new Error(`Failed to download attachment: ${res.status}`);
29
+ const buffer = Buffer.from(await res.arrayBuffer());
30
+ fs.writeFileSync(destPath, buffer);
31
+ return destPath;
32
+ }
33
+ //# sourceMappingURL=format.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"format.js","sourceRoot":"","sources":["../../../../src/connectors/discord/format.ts"],"names":[],"mappings":"AAAA,MAAM,kBAAkB,GAAG,IAAI,CAAC;AAEhC,MAAM,UAAU,cAAc,CAAC,IAAY;IACzC,IAAI,IAAI,CAAC,MAAM,IAAI,kBAAkB;QAAE,OAAO,CAAC,IAAI,CAAC,CAAC;IACrD,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,IAAI,SAAS,GAAG,IAAI,CAAC;IACrB,OAAO,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC5B,IAAI,SAAS,CAAC,MAAM,IAAI,kBAAkB,EAAE,CAAC;YAC3C,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;YACvB,MAAM;QACR,CAAC;QACD,IAAI,KAAK,GAAG,SAAS,CAAC,WAAW,CAAC,IAAI,EAAE,kBAAkB,CAAC,CAAC;QAC5D,IAAI,KAAK,IAAI,CAAC;YAAE,KAAK,GAAG,SAAS,CAAC,WAAW,CAAC,GAAG,EAAE,kBAAkB,CAAC,CAAC;QACvE,IAAI,KAAK,IAAI,CAAC;YAAE,KAAK,GAAG,kBAAkB,CAAC;QAC3C,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC;QACvC,SAAS,GAAG,SAAS,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,SAAS,EAAE,CAAC;IACjD,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,GAAW,EACX,OAAe,EACf,QAAgB;IAEhB,MAAM,EAAE,OAAO,EAAE,EAAE,EAAE,GAAG,MAAM,MAAM,CAAC,SAAS,CAAC,CAAC;IAChD,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,GAAG,MAAM,MAAM,CAAC,WAAW,CAAC,CAAC;IACpD,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;IAC9C,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,CAAC;IAC7B,IAAI,CAAC,GAAG,CAAC,EAAE;QAAE,MAAM,IAAI,KAAK,CAAC,kCAAkC,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC;IAC7E,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,WAAW,EAAE,CAAC,CAAC;IACpD,EAAE,CAAC,aAAa,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;IACnC,OAAO,QAAQ,CAAC;AAClB,CAAC"}
@@ -0,0 +1,41 @@
1
+ import type { Connector, ConnectorCapabilities, ConnectorHealth, IncomingMessage, Target } from "../../shared/types.js";
2
+ export interface DiscordConnectorConfig {
3
+ botToken?: string;
4
+ allowFrom?: string | string[];
5
+ ignoreOldMessagesOnBoot?: boolean;
6
+ guildId?: string;
7
+ /** Only respond to messages in this channel (right-click channel → Copy Channel ID) */
8
+ channelId?: string;
9
+ /** Route messages from specific channels to remote Jinn instances */
10
+ channelRouting?: Record<string, string>;
11
+ /** If set, this instance proxies all Discord operations through the primary instance at this URL */
12
+ proxyVia?: string;
13
+ }
14
+ export declare class DiscordConnector implements Connector {
15
+ name: string;
16
+ private client;
17
+ private config;
18
+ private handler;
19
+ private bootTimeMs;
20
+ private allowedUserIds;
21
+ private status;
22
+ private lastError;
23
+ private typingIntervals;
24
+ constructor(config: DiscordConnectorConfig);
25
+ onMessage(handler: (msg: IncomingMessage) => void): void;
26
+ start(): Promise<void>;
27
+ stop(): Promise<void>;
28
+ getCapabilities(): ConnectorCapabilities;
29
+ getHealth(): ConnectorHealth;
30
+ reconstructTarget(replyContext: Record<string, unknown> | null | undefined): Target;
31
+ sendMessage(target: Target, text: string): Promise<string | undefined>;
32
+ replyMessage(target: Target, text: string): Promise<string | undefined>;
33
+ editMessage(target: Target, text: string): Promise<void>;
34
+ addReaction(target: Target, emoji: string): Promise<void>;
35
+ removeReaction(target: Target, emoji: string): Promise<void>;
36
+ setTypingStatus(channelId: string, _threadTs: string | undefined, status: string): Promise<void>;
37
+ private handleMessage;
38
+ /** Forward a message to a remote Jinn instance via HTTP */
39
+ private proxyToRemote;
40
+ }
41
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/connectors/discord/index.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EACV,SAAS,EACT,qBAAqB,EACrB,eAAe,EACf,eAAe,EACf,MAAM,EACP,MAAM,uBAAuB,CAAC;AAM/B,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IAC9B,uBAAuB,CAAC,EAAE,OAAO,CAAC;IAClC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,uFAAuF;IACvF,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,qEAAqE;IACrE,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACxC,oGAAoG;IACpG,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,qBAAa,gBAAiB,YAAW,SAAS;IAChD,IAAI,SAAa;IACjB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,MAAM,CAAyB;IACvC,OAAO,CAAC,OAAO,CAAiD;IAChE,OAAO,CAAC,UAAU,CAAc;IAChC,OAAO,CAAC,cAAc,CAAc;IACpC,OAAO,CAAC,MAAM,CAA4D;IAC1E,OAAO,CAAC,SAAS,CAAuB;IACxC,OAAO,CAAC,eAAe,CAAqD;gBAEhE,MAAM,EAAE,sBAAsB;IA6B1C,SAAS,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,eAAe,KAAK,IAAI,GAAG,IAAI;IAIlD,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAuBtB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAM3B,eAAe,IAAI,qBAAqB;IASxC,SAAS,IAAI,eAAe;IAQ5B,iBAAiB,CAAC,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM;IAS7E,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC;IAgBtE,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC;IAgBvE,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAYxD,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAYzD,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAY5D,eAAe,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,SAAS,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;YAwBxF,aAAa;IA2E3B,2DAA2D;YAC7C,aAAa;CAwC5B"}
@@ -0,0 +1,302 @@
1
+ import { Client, GatewayIntentBits, Partials, } from "discord.js";
2
+ import { logger } from "../../shared/logger.js";
3
+ import { TMP_DIR } from "../../shared/paths.js";
4
+ import { formatResponse, downloadAttachment } from "./format.js";
5
+ import { deriveSessionKey, buildReplyContext, isOldMessage } from "./threads.js";
6
+ export class DiscordConnector {
7
+ name = "discord";
8
+ client;
9
+ config;
10
+ handler = null;
11
+ bootTimeMs = Date.now();
12
+ allowedUserIds;
13
+ status = "starting";
14
+ lastError = null;
15
+ typingIntervals = new Map();
16
+ constructor(config) {
17
+ this.config = config;
18
+ // Normalize Discord IDs to strings (YAML may parse large snowflake IDs as numbers)
19
+ if (this.config.guildId)
20
+ this.config.guildId = String(this.config.guildId);
21
+ if (this.config.channelId)
22
+ this.config.channelId = String(this.config.channelId);
23
+ if (this.config.channelRouting) {
24
+ this.config.channelRouting = Object.fromEntries(Object.entries(this.config.channelRouting).map(([k, v]) => [String(k), v]));
25
+ }
26
+ this.allowedUserIds = new Set(Array.isArray(config.allowFrom)
27
+ ? config.allowFrom
28
+ : config.allowFrom
29
+ ? [config.allowFrom]
30
+ : []);
31
+ this.client = new Client({
32
+ intents: [
33
+ GatewayIntentBits.Guilds,
34
+ GatewayIntentBits.GuildMessages,
35
+ GatewayIntentBits.MessageContent,
36
+ GatewayIntentBits.DirectMessages,
37
+ GatewayIntentBits.GuildMessageReactions,
38
+ ],
39
+ partials: [Partials.Channel, Partials.Message],
40
+ });
41
+ }
42
+ onMessage(handler) {
43
+ this.handler = handler;
44
+ }
45
+ async start() {
46
+ this.client.on("ready", () => {
47
+ logger.info(`Discord connector ready as ${this.client.user?.tag}`);
48
+ this.status = "running";
49
+ });
50
+ this.client.on("messageCreate", async (message) => {
51
+ try {
52
+ await this.handleMessage(message);
53
+ }
54
+ catch (err) {
55
+ logger.error(`Discord message handler error: ${err instanceof Error ? err.message : err}`);
56
+ }
57
+ });
58
+ this.client.on("error", (err) => {
59
+ this.lastError = err.message;
60
+ this.status = "error";
61
+ logger.error(`Discord client error: ${err.message}`);
62
+ });
63
+ await this.client.login(this.config.botToken);
64
+ }
65
+ async stop() {
66
+ this.status = "stopped";
67
+ await this.client.destroy();
68
+ logger.info("Discord connector stopped");
69
+ }
70
+ getCapabilities() {
71
+ return {
72
+ threading: true,
73
+ messageEdits: true,
74
+ reactions: true,
75
+ attachments: true,
76
+ };
77
+ }
78
+ getHealth() {
79
+ return {
80
+ status: this.status === "running" ? "running" : this.status === "error" ? "error" : "stopped",
81
+ detail: this.lastError ?? undefined,
82
+ capabilities: this.getCapabilities(),
83
+ };
84
+ }
85
+ reconstructTarget(replyContext) {
86
+ const ctx = (replyContext ?? {});
87
+ return {
88
+ channel: ctx.channel ?? "",
89
+ thread: ctx.thread ?? undefined,
90
+ messageTs: ctx.messageTs ?? undefined,
91
+ };
92
+ }
93
+ async sendMessage(target, text) {
94
+ try {
95
+ const channel = await this.client.channels.fetch(target.channel);
96
+ if (!channel || !channel.isTextBased())
97
+ return;
98
+ const chunks = formatResponse(text);
99
+ let lastId;
100
+ for (const chunk of chunks) {
101
+ const sent = await channel.send(chunk);
102
+ lastId = sent.id;
103
+ }
104
+ return lastId;
105
+ }
106
+ catch (err) {
107
+ logger.error(`Discord sendMessage error: ${err instanceof Error ? err.message : err}`);
108
+ }
109
+ }
110
+ async replyMessage(target, text) {
111
+ try {
112
+ const channel = await this.client.channels.fetch(target.thread ?? target.channel);
113
+ if (!channel || !channel.isTextBased())
114
+ return;
115
+ const chunks = formatResponse(text);
116
+ let lastId;
117
+ for (const chunk of chunks) {
118
+ const sent = await channel.send(chunk);
119
+ lastId = sent.id;
120
+ }
121
+ return lastId;
122
+ }
123
+ catch (err) {
124
+ logger.error(`Discord replyMessage error: ${err instanceof Error ? err.message : err}`);
125
+ }
126
+ }
127
+ async editMessage(target, text) {
128
+ try {
129
+ if (!target.messageTs)
130
+ return;
131
+ const channel = await this.client.channels.fetch(target.channel);
132
+ if (!channel || !channel.isTextBased())
133
+ return;
134
+ const msg = await channel.messages.fetch(target.messageTs);
135
+ await msg.edit(text.slice(0, 2000));
136
+ }
137
+ catch (err) {
138
+ logger.error(`Discord editMessage error: ${err instanceof Error ? err.message : err}`);
139
+ }
140
+ }
141
+ async addReaction(target, emoji) {
142
+ try {
143
+ if (!target.messageTs)
144
+ return;
145
+ const channel = await this.client.channels.fetch(target.thread ?? target.channel);
146
+ if (!channel || !channel.isTextBased())
147
+ return;
148
+ const msg = await channel.messages.fetch(target.messageTs);
149
+ await msg.react(emoji);
150
+ }
151
+ catch {
152
+ // non-fatal
153
+ }
154
+ }
155
+ async removeReaction(target, emoji) {
156
+ try {
157
+ if (!target.messageTs)
158
+ return;
159
+ const channel = await this.client.channels.fetch(target.thread ?? target.channel);
160
+ if (!channel || !channel.isTextBased())
161
+ return;
162
+ const msg = await channel.messages.fetch(target.messageTs);
163
+ await msg.reactions.cache.get(emoji)?.users.remove(this.client.user?.id);
164
+ }
165
+ catch {
166
+ // non-fatal
167
+ }
168
+ }
169
+ async setTypingStatus(channelId, _threadTs, status) {
170
+ const existing = this.typingIntervals.get(channelId);
171
+ if (existing) {
172
+ clearInterval(existing);
173
+ this.typingIntervals.delete(channelId);
174
+ }
175
+ if (!status)
176
+ return;
177
+ try {
178
+ const channel = await this.client.channels.fetch(channelId);
179
+ if (channel && channel.isTextBased()) {
180
+ await channel.sendTyping();
181
+ // Discord typing expires after 10s — refresh every 8s
182
+ const interval = setInterval(async () => {
183
+ try {
184
+ await channel.sendTyping();
185
+ }
186
+ catch { /* non-fatal */ }
187
+ }, 8_000);
188
+ this.typingIntervals.set(channelId, interval);
189
+ }
190
+ }
191
+ catch {
192
+ // non-fatal
193
+ }
194
+ }
195
+ async handleMessage(message) {
196
+ // Ignore bots (including self)
197
+ if (message.author.bot)
198
+ return;
199
+ logger.debug(`Discord message from ${message.author.username} in channel ${message.channel.id}`);
200
+ // Ignore old messages on boot
201
+ if (this.config.ignoreOldMessagesOnBoot !== false &&
202
+ isOldMessage(message.createdTimestamp, this.bootTimeMs))
203
+ return;
204
+ // Guild restriction
205
+ if (this.config.guildId && message.guild?.id !== this.config.guildId)
206
+ return;
207
+ // Channel routing — proxy messages to remote instances
208
+ const routeTarget = this.config.channelRouting?.[message.channel.id];
209
+ if (routeTarget) {
210
+ logger.debug(`Routing Discord message from channel ${message.channel.id} to ${routeTarget}`);
211
+ await this.proxyToRemote(routeTarget, message);
212
+ return;
213
+ }
214
+ // Channel restriction — only respond in a specific channel (+ DMs always allowed)
215
+ if (this.config.channelId && message.channel.id !== this.config.channelId && !message.channel.isDMBased())
216
+ return;
217
+ // User allowlist
218
+ if (this.allowedUserIds.size > 0 && !this.allowedUserIds.has(message.author.id))
219
+ return;
220
+ if (!this.handler)
221
+ return;
222
+ const sessionKey = deriveSessionKey(message);
223
+ const replyContext = buildReplyContext(message);
224
+ // Download attachments
225
+ const attachments = await Promise.all(Array.from(message.attachments.values()).map(async (att) => {
226
+ try {
227
+ const localPath = await downloadAttachment(att.url, TMP_DIR, att.name);
228
+ return { name: att.name, localPath, mimeType: att.contentType ?? "application/octet-stream" };
229
+ }
230
+ catch {
231
+ return null;
232
+ }
233
+ })).then((results) => results.filter(Boolean));
234
+ const incomingMessage = {
235
+ connector: "discord",
236
+ source: "discord",
237
+ sessionKey,
238
+ channel: message.channel.id,
239
+ thread: message.channel.isThread() ? message.channel.id : undefined,
240
+ user: message.author.username,
241
+ userId: message.author.id,
242
+ text: message.content,
243
+ attachments: attachments.map((a) => ({
244
+ name: a.name,
245
+ url: "",
246
+ mimeType: a.mimeType,
247
+ localPath: a.localPath,
248
+ })),
249
+ replyContext,
250
+ messageId: message.id,
251
+ raw: message,
252
+ transportMeta: {
253
+ channelName: message.channel.isTextBased() && "name" in message.channel
254
+ ? message.channel.name
255
+ : "dm",
256
+ guildId: message.guild?.id ?? null,
257
+ isDM: message.channel.isDMBased(),
258
+ },
259
+ };
260
+ this.handler(incomingMessage);
261
+ }
262
+ /** Forward a message to a remote Jinn instance via HTTP */
263
+ async proxyToRemote(remoteUrl, message) {
264
+ try {
265
+ const attachments = Array.from(message.attachments.values()).map((att) => ({
266
+ name: att.name,
267
+ url: att.url,
268
+ mimeType: att.contentType ?? "application/octet-stream",
269
+ }));
270
+ const payload = {
271
+ sessionKey: deriveSessionKey(message),
272
+ channel: message.channel.id,
273
+ thread: message.channel.isThread() ? message.channel.id : undefined,
274
+ user: message.author.username,
275
+ userId: message.author.id,
276
+ text: message.content,
277
+ messageId: message.id,
278
+ attachments,
279
+ replyContext: buildReplyContext(message),
280
+ transportMeta: {
281
+ channelName: message.channel.isTextBased() && "name" in message.channel
282
+ ? message.channel.name
283
+ : "dm",
284
+ guildId: message.guild?.id ?? null,
285
+ isDM: message.channel.isDMBased(),
286
+ },
287
+ };
288
+ const res = await fetch(`${remoteUrl.replace(/\/+$/, "")}/api/connectors/discord/incoming`, {
289
+ method: "POST",
290
+ headers: { "Content-Type": "application/json" },
291
+ body: JSON.stringify(payload),
292
+ });
293
+ if (!res.ok) {
294
+ logger.error(`Failed to proxy Discord message to ${remoteUrl}: ${res.status} ${res.statusText}`);
295
+ }
296
+ }
297
+ catch (err) {
298
+ logger.error(`Discord proxy error to ${remoteUrl}: ${err instanceof Error ? err.message : err}`);
299
+ }
300
+ }
301
+ }
302
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/connectors/discord/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,33 @@
1
+ import type { Connector, ConnectorCapabilities, ConnectorHealth, IncomingMessage, Target } from "../../shared/types.js";
2
+ export interface RemoteDiscordConfig {
3
+ /** URL of the primary Jinn instance that holds the Discord WebSocket connection */
4
+ proxyVia: string;
5
+ channelId?: string;
6
+ }
7
+ /**
8
+ * A Discord connector that doesn't hold its own WebSocket connection.
9
+ * Instead, it receives messages from the primary Jinn instance via HTTP
10
+ * and proxies all send/react operations back through the primary.
11
+ */
12
+ export declare class RemoteDiscordConnector implements Connector {
13
+ name: string;
14
+ private handler;
15
+ private baseUrl;
16
+ constructor(config: RemoteDiscordConfig);
17
+ onMessage(handler: (msg: IncomingMessage) => void): void;
18
+ /** Called by the /api/connectors/discord/incoming endpoint to deliver proxied messages */
19
+ deliverMessage(msg: IncomingMessage): void;
20
+ start(): Promise<void>;
21
+ stop(): Promise<void>;
22
+ getCapabilities(): ConnectorCapabilities;
23
+ getHealth(): ConnectorHealth;
24
+ reconstructTarget(replyContext: Record<string, unknown> | null | undefined): Target;
25
+ sendMessage(target: Target, text: string): Promise<string | undefined>;
26
+ replyMessage(target: Target, text: string): Promise<string | undefined>;
27
+ editMessage(target: Target, text: string): Promise<void>;
28
+ addReaction(target: Target, emoji: string): Promise<void>;
29
+ removeReaction(target: Target, emoji: string): Promise<void>;
30
+ setTypingStatus(channelId: string, threadTs: string | undefined, status: string): Promise<void>;
31
+ private proxyAction;
32
+ }
33
+ //# sourceMappingURL=remote.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"remote.d.ts","sourceRoot":"","sources":["../../../../src/connectors/discord/remote.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,SAAS,EACT,qBAAqB,EACrB,eAAe,EACf,eAAe,EACf,MAAM,EACP,MAAM,uBAAuB,CAAC;AAG/B,MAAM,WAAW,mBAAmB;IAClC,mFAAmF;IACnF,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;GAIG;AACH,qBAAa,sBAAuB,YAAW,SAAS;IACtD,IAAI,SAAa;IACjB,OAAO,CAAC,OAAO,CAAiD;IAChE,OAAO,CAAC,OAAO,CAAS;gBAEZ,MAAM,EAAE,mBAAmB;IAIvC,SAAS,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,eAAe,KAAK,IAAI,GAAG,IAAI;IAIxD,0FAA0F;IAC1F,cAAc,CAAC,GAAG,EAAE,eAAe,GAAG,IAAI;IAMpC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAItB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAI3B,eAAe,IAAI,qBAAqB;IASxC,SAAS,IAAI,eAAe;IAO5B,iBAAiB,CAAC,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM;IAS7E,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC;IAItE,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC;IAIvE,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIxD,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIzD,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAI5D,eAAe,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,SAAS,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;YAIvF,WAAW;CAkB1B"}
@@ -0,0 +1,89 @@
1
+ import { logger } from "../../shared/logger.js";
2
+ /**
3
+ * A Discord connector that doesn't hold its own WebSocket connection.
4
+ * Instead, it receives messages from the primary Jinn instance via HTTP
5
+ * and proxies all send/react operations back through the primary.
6
+ */
7
+ export class RemoteDiscordConnector {
8
+ name = "discord";
9
+ handler = null;
10
+ baseUrl;
11
+ constructor(config) {
12
+ this.baseUrl = config.proxyVia.replace(/\/+$/, "");
13
+ }
14
+ onMessage(handler) {
15
+ this.handler = handler;
16
+ }
17
+ /** Called by the /api/connectors/discord/incoming endpoint to deliver proxied messages */
18
+ deliverMessage(msg) {
19
+ if (this.handler) {
20
+ this.handler(msg);
21
+ }
22
+ }
23
+ async start() {
24
+ logger.info(`Remote Discord connector started (proxying via ${this.baseUrl})`);
25
+ }
26
+ async stop() {
27
+ logger.info("Remote Discord connector stopped");
28
+ }
29
+ getCapabilities() {
30
+ return {
31
+ threading: true,
32
+ messageEdits: true,
33
+ reactions: true,
34
+ attachments: true,
35
+ };
36
+ }
37
+ getHealth() {
38
+ return {
39
+ status: "running",
40
+ capabilities: this.getCapabilities(),
41
+ };
42
+ }
43
+ reconstructTarget(replyContext) {
44
+ const ctx = (replyContext ?? {});
45
+ return {
46
+ channel: ctx.channel ?? "",
47
+ thread: ctx.thread ?? undefined,
48
+ messageTs: ctx.messageTs ?? undefined,
49
+ };
50
+ }
51
+ async sendMessage(target, text) {
52
+ return this.proxyAction("sendMessage", { target, text });
53
+ }
54
+ async replyMessage(target, text) {
55
+ return this.proxyAction("replyMessage", { target, text });
56
+ }
57
+ async editMessage(target, text) {
58
+ await this.proxyAction("editMessage", { target, text });
59
+ }
60
+ async addReaction(target, emoji) {
61
+ await this.proxyAction("addReaction", { target, emoji });
62
+ }
63
+ async removeReaction(target, emoji) {
64
+ await this.proxyAction("removeReaction", { target, emoji });
65
+ }
66
+ async setTypingStatus(channelId, threadTs, status) {
67
+ await this.proxyAction("setTypingStatus", { channelId, threadTs, status });
68
+ }
69
+ async proxyAction(action, params) {
70
+ try {
71
+ const res = await fetch(`${this.baseUrl}/api/connectors/discord/proxy`, {
72
+ method: "POST",
73
+ headers: { "Content-Type": "application/json" },
74
+ body: JSON.stringify({ action, ...params }),
75
+ });
76
+ if (!res.ok) {
77
+ logger.error(`Remote Discord proxy ${action} failed: ${res.status}`);
78
+ return undefined;
79
+ }
80
+ const data = (await res.json());
81
+ return data.messageId;
82
+ }
83
+ catch (err) {
84
+ logger.error(`Remote Discord proxy ${action} error: ${err instanceof Error ? err.message : err}`);
85
+ return undefined;
86
+ }
87
+ }
88
+ }
89
+ //# sourceMappingURL=remote.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"remote.js","sourceRoot":"","sources":["../../../../src/connectors/discord/remote.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ import type { Message } from "discord.js";
2
+ export declare function deriveSessionKey(message: Message): string;
3
+ export declare function buildReplyContext(message: Message): Record<string, string | null>;
4
+ export declare function isOldMessage(createdTimestamp: number, bootTimeMs: number): boolean;
5
+ //# sourceMappingURL=threads.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"threads.d.ts","sourceRoot":"","sources":["../../../../src/connectors/discord/threads.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAE1C,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,CAQzD;AAED,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC,CAQjF;AAED,wBAAgB,YAAY,CAAC,gBAAgB,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAElF"}
@@ -0,0 +1,22 @@
1
+ export function deriveSessionKey(message) {
2
+ if (message.channel.isDMBased()) {
3
+ return `discord:dm:${message.author.id}`;
4
+ }
5
+ if (message.channel.isThread()) {
6
+ return `discord:thread:${message.channel.id}`;
7
+ }
8
+ return `discord:${message.channel.id}`;
9
+ }
10
+ export function buildReplyContext(message) {
11
+ const threadId = message.channel.isThread() ? message.channel.id : null;
12
+ return {
13
+ channel: message.channel.id,
14
+ thread: threadId,
15
+ messageTs: message.id,
16
+ guildId: message.guild?.id ?? null,
17
+ };
18
+ }
19
+ export function isOldMessage(createdTimestamp, bootTimeMs) {
20
+ return createdTimestamp < bootTimeMs;
21
+ }
22
+ //# sourceMappingURL=threads.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"threads.js","sourceRoot":"","sources":["../../../../src/connectors/discord/threads.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,gBAAgB,CAAC,OAAgB;IAC/C,IAAI,OAAO,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC;QAChC,OAAO,cAAc,OAAO,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC;IAC3C,CAAC;IACD,IAAI,OAAO,CAAC,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC;QAC/B,OAAO,kBAAkB,OAAO,CAAC,OAAO,CAAC,EAAE,EAAE,CAAC;IAChD,CAAC;IACD,OAAO,WAAW,OAAO,CAAC,OAAO,CAAC,EAAE,EAAE,CAAC;AACzC,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,OAAgB;IAChD,MAAM,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;IACxE,OAAO;QACL,OAAO,EAAE,OAAO,CAAC,OAAO,CAAC,EAAE;QAC3B,MAAM,EAAE,QAAQ;QAChB,SAAS,EAAE,OAAO,CAAC,EAAE;QACrB,OAAO,EAAE,OAAO,CAAC,KAAK,EAAE,EAAE,IAAI,IAAI;KACnC,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,gBAAwB,EAAE,UAAkB;IACvE,OAAO,gBAAgB,GAAG,UAAU,CAAC;AACvC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare function formatResponse(text: string): string[];
2
+ //# sourceMappingURL=format.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"format.d.ts","sourceRoot":"","sources":["../../../../src/connectors/whatsapp/format.ts"],"names":[],"mappings":"AAEA,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAarD"}