@openacp/cli 2026.326.4 → 2026.327.2

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 (132) hide show
  1. package/README.md +2 -2
  2. package/dist/{adapter-6ANPBSVU.js → adapter-LC2QSDAS.js} +4 -5
  3. package/dist/{adapter-PQGHVG4K.js → adapter-Y55NXX6I.js} +2 -2
  4. package/dist/{api-server-3PYLRBCN.js → api-server-7G3ZUZRM.js} +2 -2
  5. package/dist/{api-server-CHVSUDBX.js → api-server-CAYNPUF2.js} +2 -2
  6. package/dist/{chunk-UNJUWWQO.js → chunk-2YCW3QDV.js} +21 -14
  7. package/dist/chunk-2YCW3QDV.js.map +1 -0
  8. package/dist/{chunk-Y64XWMJ4.js → chunk-36YQ44D7.js} +2 -2
  9. package/dist/{chunk-UB2QB6DE.js → chunk-3ASUU6WW.js} +2 -2
  10. package/dist/{chunk-V5JT5TPD.js → chunk-4GMLGCF2.js} +2 -2
  11. package/dist/chunk-CDAUYTVP.js +41 -0
  12. package/dist/chunk-CDAUYTVP.js.map +1 -0
  13. package/dist/{chunk-Q6ZXJTZB.js → chunk-HUWOFP2H.js} +9 -17
  14. package/dist/chunk-HUWOFP2H.js.map +1 -0
  15. package/dist/{chunk-P4SNGQNI.js → chunk-KMMEFXIE.js} +2 -2
  16. package/dist/{chunk-RKB2ZK6S.js → chunk-LP45RCA4.js} +579 -153
  17. package/dist/chunk-LP45RCA4.js.map +1 -0
  18. package/dist/{chunk-L7YNNBI5.js → chunk-QAQDGPB4.js} +1 -75
  19. package/dist/chunk-QAQDGPB4.js.map +1 -0
  20. package/dist/{chunk-V2M243KZ.js → chunk-TRXBJEZ5.js} +55 -53
  21. package/dist/chunk-TRXBJEZ5.js.map +1 -0
  22. package/dist/{chunk-NBFIBGAT.js → chunk-UMT7RU77.js} +45 -118
  23. package/dist/chunk-UMT7RU77.js.map +1 -0
  24. package/dist/{chunk-FQEBWOZR.js → chunk-XIBG7LSL.js} +181 -128
  25. package/dist/chunk-XIBG7LSL.js.map +1 -0
  26. package/dist/cli.js +155 -49
  27. package/dist/cli.js.map +1 -1
  28. package/dist/{config-editor-HNEKXRLQ.js → config-editor-3IKBPZA7.js} +2 -2
  29. package/dist/{core-plugins-VEUNFTMB.js → core-plugins-ROU4GPLT.js} +8 -12
  30. package/dist/{dev-loader-RDC5E2CW.js → dev-loader-DRU3R7ZM.js} +7 -18
  31. package/dist/dev-loader-DRU3R7ZM.js.map +1 -0
  32. package/dist/{doctor-H72BZOPA.js → doctor-QZQAP46W.js} +2 -2
  33. package/dist/index.d.ts +128 -66
  34. package/dist/index.js +41 -20
  35. package/dist/index.js.map +1 -1
  36. package/dist/{integrate-5C6KSU6D.js → integrate-G6CVXTGT.js} +3 -4
  37. package/dist/integrate-G6CVXTGT.js.map +1 -0
  38. package/dist/{main-T5WVCCFN.js → main-UVTZ46WP.js} +39 -185
  39. package/dist/main-UVTZ46WP.js.map +1 -0
  40. package/dist/plugin-create-5HQRF2ID.js +967 -0
  41. package/dist/plugin-create-5HQRF2ID.js.map +1 -0
  42. package/dist/plugin-installer-GQ2P3Q3E.js +23 -0
  43. package/dist/plugin-installer-GQ2P3Q3E.js.map +1 -0
  44. package/dist/plugin-search-HQ4WQKOF.js +40 -0
  45. package/dist/plugin-search-HQ4WQKOF.js.map +1 -0
  46. package/dist/{post-upgrade-XLHZ6ZB7.js → post-upgrade-3ADZRMYJ.js} +2 -2
  47. package/dist/registry-client-AVGRE4CF.js +8 -0
  48. package/dist/{setup-BAI2F24H.js → setup-EYAFK2WI.js} +77 -50
  49. package/dist/setup-EYAFK2WI.js.map +1 -0
  50. package/dist/{slack-KH7E3VBS.js → slack-37ZWBDUI.js} +2 -2
  51. package/dist/{telegram-ZDC3JQF2.js → telegram-2ZCCCZIY.js} +2 -2
  52. package/dist/{tunnel-M47I7H4B.js → tunnel-45HA72MB.js} +2 -2
  53. package/dist/{tunnel-service-WADYHREX.js → tunnel-service-QJPUYEKU.js} +11 -3
  54. package/dist/tunnel-service-QJPUYEKU.js.map +1 -0
  55. package/package.json +2 -3
  56. package/dist/action-detect-QPA775HB.js +0 -16
  57. package/dist/adapter-77ZCVABT.js +0 -2394
  58. package/dist/adapter-77ZCVABT.js.map +0 -1
  59. package/dist/admin-GBPZFFAU.js +0 -23
  60. package/dist/agents-BWU4MRRD.js +0 -15
  61. package/dist/chunk-2CX4IEEC.js +0 -124
  62. package/dist/chunk-2CX4IEEC.js.map +0 -1
  63. package/dist/chunk-4KGLKKQK.js +0 -298
  64. package/dist/chunk-4KGLKKQK.js.map +0 -1
  65. package/dist/chunk-5ZOFBTOR.js +0 -553
  66. package/dist/chunk-5ZOFBTOR.js.map +0 -1
  67. package/dist/chunk-6RXVEXF3.js +0 -23
  68. package/dist/chunk-6RXVEXF3.js.map +0 -1
  69. package/dist/chunk-FQEBWOZR.js.map +0 -1
  70. package/dist/chunk-GJOY37U7.js +0 -265
  71. package/dist/chunk-GJOY37U7.js.map +0 -1
  72. package/dist/chunk-HVBNCPAY.js +0 -71
  73. package/dist/chunk-HVBNCPAY.js.map +0 -1
  74. package/dist/chunk-I3CGU5W7.js +0 -134
  75. package/dist/chunk-I3CGU5W7.js.map +0 -1
  76. package/dist/chunk-L7YNNBI5.js.map +0 -1
  77. package/dist/chunk-MTSDOSXS.js +0 -219
  78. package/dist/chunk-MTSDOSXS.js.map +0 -1
  79. package/dist/chunk-NAM4ERUW.js +0 -203
  80. package/dist/chunk-NAM4ERUW.js.map +0 -1
  81. package/dist/chunk-NBFIBGAT.js.map +0 -1
  82. package/dist/chunk-O5RG4YZY.js +0 -122
  83. package/dist/chunk-O5RG4YZY.js.map +0 -1
  84. package/dist/chunk-Q6ZXJTZB.js.map +0 -1
  85. package/dist/chunk-QSDZDHNS.js +0 -145
  86. package/dist/chunk-QSDZDHNS.js.map +0 -1
  87. package/dist/chunk-RKB2ZK6S.js.map +0 -1
  88. package/dist/chunk-UNJUWWQO.js.map +0 -1
  89. package/dist/chunk-V2M243KZ.js.map +0 -1
  90. package/dist/chunk-WAAD23KY.js +0 -222
  91. package/dist/chunk-WAAD23KY.js.map +0 -1
  92. package/dist/chunk-WVLDNYOJ.js +0 -150
  93. package/dist/chunk-WVLDNYOJ.js.map +0 -1
  94. package/dist/dev-loader-RDC5E2CW.js.map +0 -1
  95. package/dist/discord-NOJQ5PZO.js +0 -8
  96. package/dist/doctor-RF6BHMCC.js +0 -15
  97. package/dist/doctor-RF6BHMCC.js.map +0 -1
  98. package/dist/integrate-5C6KSU6D.js.map +0 -1
  99. package/dist/main-T5WVCCFN.js.map +0 -1
  100. package/dist/new-session-AVQCNXRG.js +0 -17
  101. package/dist/new-session-AVQCNXRG.js.map +0 -1
  102. package/dist/plugin-create-AQ3B22BZ.js +0 -334
  103. package/dist/plugin-create-AQ3B22BZ.js.map +0 -1
  104. package/dist/session-KZFA6Z26.js +0 -20
  105. package/dist/session-KZFA6Z26.js.map +0 -1
  106. package/dist/settings-MFYM7CZO.js +0 -14
  107. package/dist/settings-MFYM7CZO.js.map +0 -1
  108. package/dist/setup-BAI2F24H.js.map +0 -1
  109. package/dist/slack-KH7E3VBS.js.map +0 -1
  110. package/dist/telegram-ZDC3JQF2.js.map +0 -1
  111. package/dist/tunnel-M47I7H4B.js.map +0 -1
  112. package/dist/tunnel-service-WADYHREX.js.map +0 -1
  113. package/dist/usage-WYNK6ZC5.js +0 -10
  114. package/dist/usage-WYNK6ZC5.js.map +0 -1
  115. package/dist/validators-6CLEZUBD.js +0 -8
  116. package/dist/validators-6CLEZUBD.js.map +0 -1
  117. /package/dist/{action-detect-QPA775HB.js.map → adapter-LC2QSDAS.js.map} +0 -0
  118. /package/dist/{adapter-PQGHVG4K.js.map → adapter-Y55NXX6I.js.map} +0 -0
  119. /package/dist/{adapter-6ANPBSVU.js.map → api-server-7G3ZUZRM.js.map} +0 -0
  120. /package/dist/{admin-GBPZFFAU.js.map → api-server-CAYNPUF2.js.map} +0 -0
  121. /package/dist/{chunk-Y64XWMJ4.js.map → chunk-36YQ44D7.js.map} +0 -0
  122. /package/dist/{chunk-UB2QB6DE.js.map → chunk-3ASUU6WW.js.map} +0 -0
  123. /package/dist/{chunk-V5JT5TPD.js.map → chunk-4GMLGCF2.js.map} +0 -0
  124. /package/dist/{chunk-P4SNGQNI.js.map → chunk-KMMEFXIE.js.map} +0 -0
  125. /package/dist/{agents-BWU4MRRD.js.map → config-editor-3IKBPZA7.js.map} +0 -0
  126. /package/dist/{api-server-3PYLRBCN.js.map → core-plugins-ROU4GPLT.js.map} +0 -0
  127. /package/dist/{api-server-CHVSUDBX.js.map → doctor-QZQAP46W.js.map} +0 -0
  128. /package/dist/{post-upgrade-XLHZ6ZB7.js.map → post-upgrade-3ADZRMYJ.js.map} +0 -0
  129. /package/dist/{config-editor-HNEKXRLQ.js.map → registry-client-AVGRE4CF.js.map} +0 -0
  130. /package/dist/{core-plugins-VEUNFTMB.js.map → slack-37ZWBDUI.js.map} +0 -0
  131. /package/dist/{discord-NOJQ5PZO.js.map → telegram-2ZCCCZIY.js.map} +0 -0
  132. /package/dist/{doctor-H72BZOPA.js.map → tunnel-45HA72MB.js.map} +0 -0
@@ -1,122 +0,0 @@
1
- import {
2
- log
3
- } from "./chunk-XMMAGAT4.js";
4
-
5
- // src/plugins/discord/forums.ts
6
- import { ChannelType } from "discord.js";
7
- async function ensureForums(guild, config, saveConfig) {
8
- let forumChannelId = config.forumChannelId;
9
- let notificationChannelId = config.notificationChannelId;
10
- let forumChannel = null;
11
- if (forumChannelId) {
12
- try {
13
- const ch = guild.channels.cache.get(forumChannelId) ?? await guild.channels.fetch(forumChannelId);
14
- if (ch && (ch.type === ChannelType.GuildForum || ch.type === ChannelType.GuildText)) {
15
- forumChannel = ch;
16
- log.info({ forumChannelId, type: ch.type }, "[forums] Reusing existing sessions channel");
17
- }
18
- } catch {
19
- log.warn({ forumChannelId }, "[forums] Saved sessions channel not found, recreating...");
20
- }
21
- }
22
- if (!forumChannel) {
23
- if (guild.features.includes("COMMUNITY")) {
24
- const channel = await guild.channels.create({
25
- name: "openacp-sessions",
26
- type: ChannelType.GuildForum
27
- });
28
- forumChannel = channel;
29
- log.info({ forumChannelId: channel.id }, "[forums] Created forum channel");
30
- } else {
31
- const channel = await guild.channels.create({
32
- name: "openacp-sessions",
33
- type: ChannelType.GuildText
34
- });
35
- forumChannel = channel;
36
- log.info({ forumChannelId: channel.id }, "[forums] Created text channel (Community mode not enabled, using threads fallback)");
37
- }
38
- await saveConfig({ channels: { discord: { forumChannelId: forumChannel.id } } });
39
- }
40
- let notificationChannel = null;
41
- if (notificationChannelId) {
42
- try {
43
- const ch = guild.channels.cache.get(notificationChannelId) ?? await guild.channels.fetch(notificationChannelId);
44
- if (ch && ch.type === ChannelType.GuildText) {
45
- notificationChannel = ch;
46
- log.info({ notificationChannelId }, "[forums] Reusing existing notification channel");
47
- }
48
- } catch {
49
- log.warn({ notificationChannelId }, "[forums] Saved notification channel not found, recreating...");
50
- }
51
- }
52
- if (!notificationChannel) {
53
- const channel = await guild.channels.create({
54
- name: "openacp-notifications",
55
- type: ChannelType.GuildText
56
- });
57
- notificationChannel = channel;
58
- await saveConfig({ channels: { discord: { notificationChannelId: channel.id } } });
59
- log.info({ notificationChannelId: channel.id }, "[forums] Created notification channel");
60
- }
61
- return { forumChannel, notificationChannel };
62
- }
63
- async function createSessionThread(forumChannel, name) {
64
- if (forumChannel.type === ChannelType.GuildForum) {
65
- const thread2 = await forumChannel.threads.create({
66
- name,
67
- message: { content: "\u23F3 Setting up..." }
68
- });
69
- return thread2;
70
- }
71
- const textChannel = forumChannel;
72
- const msg = await textChannel.send({ content: `\u{1F4C2} **${name}** \u2014 \u23F3 Setting up...` });
73
- const thread = await msg.startThread({ name });
74
- return thread;
75
- }
76
- async function renameSessionThread(guild, threadId, newName) {
77
- try {
78
- const channel = guild.channels.cache.get(threadId) ?? await guild.channels.fetch(threadId);
79
- if (channel && "setName" in channel) {
80
- await channel.setName(newName);
81
- }
82
- } catch {
83
- }
84
- }
85
- async function deleteSessionThread(guild, threadId) {
86
- try {
87
- const channel = guild.channels.cache.get(threadId) ?? await guild.channels.fetch(threadId);
88
- if (channel && channel.isThread()) {
89
- const thread = channel;
90
- if (!thread.archived) {
91
- await thread.setArchived(true);
92
- }
93
- if (!thread.locked) {
94
- await thread.setLocked(true);
95
- }
96
- }
97
- } catch {
98
- }
99
- }
100
- async function ensureUnarchived(thread) {
101
- if (thread.archived) {
102
- try {
103
- await thread.setArchived(false);
104
- } catch (err) {
105
- log.warn({ err, threadId: thread.id }, "[forums] Failed to unarchive thread");
106
- }
107
- }
108
- }
109
- function buildDeepLink(guildId, channelId, messageId) {
110
- const base = `https://discord.com/channels/${guildId}/${channelId}`;
111
- return messageId ? `${base}/${messageId}` : base;
112
- }
113
-
114
- export {
115
- ensureForums,
116
- createSessionThread,
117
- renameSessionThread,
118
- deleteSessionThread,
119
- ensureUnarchived,
120
- buildDeepLink
121
- };
122
- //# sourceMappingURL=chunk-O5RG4YZY.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/plugins/discord/forums.ts"],"sourcesContent":["import { ChannelType } from 'discord.js'\nimport type { ForumChannel, ThreadChannel, Guild, TextChannel } from 'discord.js'\nimport { log } from '../../core/utils/log.js'\n\n// ─── ensureForums ─────────────────────────────────────────────────────────────\n\n/**\n * Ensures both the forum channel and notification channel exist.\n * Creates them if their IDs are null, then persists the IDs via saveConfig.\n *\n * saveConfig uses nested object path: { channels: { discord: { forumChannelId: ... } } }\n */\nexport async function ensureForums(\n guild: Guild,\n config: {\n forumChannelId: string | null\n notificationChannelId: string | null\n },\n saveConfig: (updates: Record<string, unknown>) => Promise<void>,\n): Promise<{ forumChannel: ForumChannel | TextChannel; notificationChannel: TextChannel }> {\n let forumChannelId = config.forumChannelId\n let notificationChannelId = config.notificationChannelId\n\n // Ensure forum/sessions channel exists — fetch existing or create new\n let forumChannel: ForumChannel | TextChannel | null = null\n if (forumChannelId) {\n try {\n const ch = guild.channels.cache.get(forumChannelId)\n ?? await guild.channels.fetch(forumChannelId)\n if (ch && (ch.type === ChannelType.GuildForum || ch.type === ChannelType.GuildText)) {\n forumChannel = ch as ForumChannel | TextChannel\n log.info({ forumChannelId, type: ch.type }, '[forums] Reusing existing sessions channel')\n }\n } catch {\n log.warn({ forumChannelId }, '[forums] Saved sessions channel not found, recreating...')\n }\n }\n if (!forumChannel) {\n // Prefer Forum Channel (requires Community mode), fallback to Text Channel with threads\n if (guild.features.includes('COMMUNITY')) {\n const channel = await guild.channels.create({\n name: 'openacp-sessions',\n type: ChannelType.GuildForum,\n })\n forumChannel = channel as ForumChannel\n log.info({ forumChannelId: channel.id }, '[forums] Created forum channel')\n } else {\n const channel = await guild.channels.create({\n name: 'openacp-sessions',\n type: ChannelType.GuildText,\n })\n forumChannel = channel as TextChannel\n log.info({ forumChannelId: channel.id }, '[forums] Created text channel (Community mode not enabled, using threads fallback)')\n }\n await saveConfig({ channels: { discord: { forumChannelId: forumChannel.id } } })\n }\n\n // Ensure notification channel exists — fetch existing or create new\n let notificationChannel: TextChannel | null = null\n if (notificationChannelId) {\n try {\n const ch = guild.channels.cache.get(notificationChannelId)\n ?? await guild.channels.fetch(notificationChannelId)\n if (ch && ch.type === ChannelType.GuildText) {\n notificationChannel = ch as TextChannel\n log.info({ notificationChannelId }, '[forums] Reusing existing notification channel')\n }\n } catch {\n log.warn({ notificationChannelId }, '[forums] Saved notification channel not found, recreating...')\n }\n }\n if (!notificationChannel) {\n const channel = await guild.channels.create({\n name: 'openacp-notifications',\n type: ChannelType.GuildText,\n })\n notificationChannel = channel as TextChannel\n await saveConfig({ channels: { discord: { notificationChannelId: channel.id } } })\n log.info({ notificationChannelId: channel.id }, '[forums] Created notification channel')\n }\n\n return { forumChannel, notificationChannel }\n}\n\n// ─── createSessionThread ──────────────────────────────────────────────────────\n\n/**\n * Creates a new thread for a session.\n * - Forum Channel: creates a forum post (thread with initial message)\n * - Text Channel: creates a public thread\n */\nexport async function createSessionThread(\n forumChannel: ForumChannel | TextChannel,\n name: string,\n): Promise<ThreadChannel> {\n if (forumChannel.type === ChannelType.GuildForum) {\n // Forum channel: create a post (thread with initial message)\n const thread = await (forumChannel as ForumChannel).threads.create({\n name,\n message: { content: '⏳ Setting up...' },\n })\n return thread\n }\n\n // Text channel fallback: send a message first, then create a thread on it\n const textChannel = forumChannel as TextChannel\n const msg = await textChannel.send({ content: `📂 **${name}** — ⏳ Setting up...` })\n const thread = await msg.startThread({ name })\n return thread\n}\n\n// ─── renameSessionThread ──────────────────────────────────────────────────────\n\n/**\n * Fetches and renames a thread. Ignores all errors (thread may be deleted/archived).\n */\nexport async function renameSessionThread(\n guild: Guild,\n threadId: string,\n newName: string,\n): Promise<void> {\n try {\n const channel = guild.channels.cache.get(threadId)\n ?? await guild.channels.fetch(threadId)\n if (channel && 'setName' in channel) {\n await (channel as ThreadChannel).setName(newName)\n }\n } catch {\n // Ignore — thread may be deleted or archived\n }\n}\n\n// ─── deleteSessionThread ──────────────────────────────────────────────────────\n\n/**\n * Archives and locks a thread instead of permanently deleting it.\n * Unlike Telegram (which just closes a topic), Discord delete is permanent\n * and destroys all messages. Archiving preserves the conversation history.\n */\nexport async function deleteSessionThread(\n guild: Guild,\n threadId: string,\n): Promise<void> {\n try {\n const channel = guild.channels.cache.get(threadId)\n ?? await guild.channels.fetch(threadId)\n if (channel && channel.isThread()) {\n const thread = channel as ThreadChannel\n if (!thread.archived) {\n await thread.setArchived(true)\n }\n if (!thread.locked) {\n await thread.setLocked(true)\n }\n }\n } catch {\n // Ignore — thread may already be deleted or inaccessible\n }\n}\n\n// ─── ensureUnarchived ─────────────────────────────────────────────────────────\n\n/**\n * If the thread is archived, unarchives it.\n */\nexport async function ensureUnarchived(thread: ThreadChannel): Promise<void> {\n if (thread.archived) {\n try {\n await thread.setArchived(false)\n } catch (err) {\n log.warn({ err, threadId: thread.id }, '[forums] Failed to unarchive thread')\n }\n }\n}\n\n// ─── buildDeepLink ────────────────────────────────────────────────────────────\n\n/**\n * Builds a Discord deep link URL to a channel/thread, optionally to a specific message.\n */\nexport function buildDeepLink(\n guildId: string,\n channelId: string,\n messageId?: string,\n): string {\n const base = `https://discord.com/channels/${guildId}/${channelId}`\n return messageId ? `${base}/${messageId}` : base\n}\n"],"mappings":";;;;;AAAA,SAAS,mBAAmB;AAY5B,eAAsB,aACpB,OACA,QAIA,YACyF;AACzF,MAAI,iBAAiB,OAAO;AAC5B,MAAI,wBAAwB,OAAO;AAGnC,MAAI,eAAkD;AACtD,MAAI,gBAAgB;AAClB,QAAI;AACF,YAAM,KAAK,MAAM,SAAS,MAAM,IAAI,cAAc,KAC7C,MAAM,MAAM,SAAS,MAAM,cAAc;AAC9C,UAAI,OAAO,GAAG,SAAS,YAAY,cAAc,GAAG,SAAS,YAAY,YAAY;AACnF,uBAAe;AACf,YAAI,KAAK,EAAE,gBAAgB,MAAM,GAAG,KAAK,GAAG,4CAA4C;AAAA,MAC1F;AAAA,IACF,QAAQ;AACN,UAAI,KAAK,EAAE,eAAe,GAAG,0DAA0D;AAAA,IACzF;AAAA,EACF;AACA,MAAI,CAAC,cAAc;AAEjB,QAAI,MAAM,SAAS,SAAS,WAAW,GAAG;AACxC,YAAM,UAAU,MAAM,MAAM,SAAS,OAAO;AAAA,QAC1C,MAAM;AAAA,QACN,MAAM,YAAY;AAAA,MACpB,CAAC;AACD,qBAAe;AACf,UAAI,KAAK,EAAE,gBAAgB,QAAQ,GAAG,GAAG,gCAAgC;AAAA,IAC3E,OAAO;AACL,YAAM,UAAU,MAAM,MAAM,SAAS,OAAO;AAAA,QAC1C,MAAM;AAAA,QACN,MAAM,YAAY;AAAA,MACpB,CAAC;AACD,qBAAe;AACf,UAAI,KAAK,EAAE,gBAAgB,QAAQ,GAAG,GAAG,oFAAoF;AAAA,IAC/H;AACA,UAAM,WAAW,EAAE,UAAU,EAAE,SAAS,EAAE,gBAAgB,aAAa,GAAG,EAAE,EAAE,CAAC;AAAA,EACjF;AAGA,MAAI,sBAA0C;AAC9C,MAAI,uBAAuB;AACzB,QAAI;AACF,YAAM,KAAK,MAAM,SAAS,MAAM,IAAI,qBAAqB,KACpD,MAAM,MAAM,SAAS,MAAM,qBAAqB;AACrD,UAAI,MAAM,GAAG,SAAS,YAAY,WAAW;AAC3C,8BAAsB;AACtB,YAAI,KAAK,EAAE,sBAAsB,GAAG,gDAAgD;AAAA,MACtF;AAAA,IACF,QAAQ;AACN,UAAI,KAAK,EAAE,sBAAsB,GAAG,8DAA8D;AAAA,IACpG;AAAA,EACF;AACA,MAAI,CAAC,qBAAqB;AACxB,UAAM,UAAU,MAAM,MAAM,SAAS,OAAO;AAAA,MAC1C,MAAM;AAAA,MACN,MAAM,YAAY;AAAA,IACpB,CAAC;AACD,0BAAsB;AACtB,UAAM,WAAW,EAAE,UAAU,EAAE,SAAS,EAAE,uBAAuB,QAAQ,GAAG,EAAE,EAAE,CAAC;AACjF,QAAI,KAAK,EAAE,uBAAuB,QAAQ,GAAG,GAAG,uCAAuC;AAAA,EACzF;AAEA,SAAO,EAAE,cAAc,oBAAoB;AAC7C;AASA,eAAsB,oBACpB,cACA,MACwB;AACxB,MAAI,aAAa,SAAS,YAAY,YAAY;AAEhD,UAAMA,UAAS,MAAO,aAA8B,QAAQ,OAAO;AAAA,MACjE;AAAA,MACA,SAAS,EAAE,SAAS,uBAAkB;AAAA,IACxC,CAAC;AACD,WAAOA;AAAA,EACT;AAGA,QAAM,cAAc;AACpB,QAAM,MAAM,MAAM,YAAY,KAAK,EAAE,SAAS,eAAQ,IAAI,iCAAuB,CAAC;AAClF,QAAM,SAAS,MAAM,IAAI,YAAY,EAAE,KAAK,CAAC;AAC7C,SAAO;AACT;AAOA,eAAsB,oBACpB,OACA,UACA,SACe;AACf,MAAI;AACF,UAAM,UAAU,MAAM,SAAS,MAAM,IAAI,QAAQ,KAC5C,MAAM,MAAM,SAAS,MAAM,QAAQ;AACxC,QAAI,WAAW,aAAa,SAAS;AACnC,YAAO,QAA0B,QAAQ,OAAO;AAAA,IAClD;AAAA,EACF,QAAQ;AAAA,EAER;AACF;AASA,eAAsB,oBACpB,OACA,UACe;AACf,MAAI;AACF,UAAM,UAAU,MAAM,SAAS,MAAM,IAAI,QAAQ,KAC5C,MAAM,MAAM,SAAS,MAAM,QAAQ;AACxC,QAAI,WAAW,QAAQ,SAAS,GAAG;AACjC,YAAM,SAAS;AACf,UAAI,CAAC,OAAO,UAAU;AACpB,cAAM,OAAO,YAAY,IAAI;AAAA,MAC/B;AACA,UAAI,CAAC,OAAO,QAAQ;AAClB,cAAM,OAAO,UAAU,IAAI;AAAA,MAC7B;AAAA,IACF;AAAA,EACF,QAAQ;AAAA,EAER;AACF;AAOA,eAAsB,iBAAiB,QAAsC;AAC3E,MAAI,OAAO,UAAU;AACnB,QAAI;AACF,YAAM,OAAO,YAAY,KAAK;AAAA,IAChC,SAAS,KAAK;AACZ,UAAI,KAAK,EAAE,KAAK,UAAU,OAAO,GAAG,GAAG,qCAAqC;AAAA,IAC9E;AAAA,EACF;AACF;AAOO,SAAS,cACd,SACA,WACA,WACQ;AACR,QAAM,OAAO,gCAAgC,OAAO,IAAI,SAAS;AACjE,SAAO,YAAY,GAAG,IAAI,IAAI,SAAS,KAAK;AAC9C;","names":["thread"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/plugins/core-plugins.ts"],"sourcesContent":["/**\n * All built-in plugins: services, infrastructure, and adapters.\n * Booted by LifecycleManager in dependency order.\n * Adapter plugins depend on service plugins, so they boot last.\n */\nimport securityPlugin from './security/index.js'\nimport fileServicePlugin from './file-service/index.js'\nimport contextPlugin from './context/index.js'\nimport usagePlugin from './usage/index.js'\nimport speechPlugin from './speech/index.js'\nimport notificationsPlugin from './notifications/index.js'\nimport tunnelPlugin from './tunnel/index.js'\nimport apiServerPlugin from './api-server/index.js'\nimport telegramPlugin from './telegram/index.js'\nimport discordPlugin from './discord/index.js'\nimport slackPlugin from './slack/index.js'\n\nexport const corePlugins = [\n // Service plugins (no adapter dependencies)\n securityPlugin,\n fileServicePlugin,\n contextPlugin,\n usagePlugin,\n speechPlugin,\n notificationsPlugin,\n // Infrastructure plugins\n tunnelPlugin,\n apiServerPlugin,\n // Adapter plugins (depend on security, notifications, etc.)\n telegramPlugin,\n discordPlugin,\n slackPlugin,\n]\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAiBO,IAAM,cAAc;AAAA;AAAA,EAEzB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAEA;AAAA,EACA;AAAA;AAAA,EAEA;AAAA,EACA;AAAA,EACA;AACF;","names":[]}
@@ -1,145 +0,0 @@
1
- import {
2
- createSessionThread,
3
- deleteSessionThread
4
- } from "./chunk-O5RG4YZY.js";
5
- import {
6
- buildSessionControlKeyboard
7
- } from "./chunk-MTSDOSXS.js";
8
- import {
9
- log
10
- } from "./chunk-XMMAGAT4.js";
11
-
12
- // src/plugins/discord/commands/new-session.ts
13
- import {
14
- ActionRowBuilder,
15
- ButtonBuilder,
16
- ButtonStyle
17
- } from "discord.js";
18
- async function handleNew(interaction, adapter) {
19
- await interaction.deferReply({ ephemeral: true });
20
- const agentName = interaction.options.getString("agent") ?? void 0;
21
- const workspace = interaction.options.getString("workspace") ?? void 0;
22
- if (agentName) {
23
- await executeNewSession(interaction, adapter, agentName, workspace);
24
- return;
25
- }
26
- const installedEntries = adapter.core.agentCatalog.getInstalledEntries();
27
- const agentKeys = Object.keys(installedEntries);
28
- const config = adapter.core.configManager.get();
29
- if (agentKeys.length === 0) {
30
- await interaction.editReply("\u274C No agents installed. Use `/install` to install an agent first.");
31
- return;
32
- }
33
- if (agentKeys.length === 1) {
34
- await executeNewSession(interaction, adapter, config.defaultAgent, workspace);
35
- return;
36
- }
37
- const row = new ActionRowBuilder();
38
- for (const key of agentKeys) {
39
- const agent = installedEntries[key];
40
- const label = key === config.defaultAgent ? `${agent.name} (default)` : agent.name;
41
- row.addComponents(
42
- new ButtonBuilder().setCustomId(`m:new:agent:${key}`).setLabel(label).setStyle(ButtonStyle.Primary)
43
- );
44
- }
45
- await interaction.editReply({
46
- content: "\u{1F916} **Choose an agent:**",
47
- components: [row]
48
- });
49
- }
50
- async function handleNewChat(interaction, adapter) {
51
- await interaction.deferReply({ ephemeral: true });
52
- const channelId = interaction.channelId;
53
- const currentSession = adapter.core.sessionManager.getSessionByThread("discord", channelId);
54
- let agentName;
55
- let workspace;
56
- if (currentSession) {
57
- agentName = currentSession.agentName;
58
- workspace = currentSession.workingDirectory;
59
- } else {
60
- const record = adapter.core.sessionManager.getRecordByThread("discord", channelId);
61
- if (!record || record.status === "cancelled" || record.status === "error") {
62
- await interaction.editReply("No active session in this channel. Use `/new` to start one.");
63
- return;
64
- }
65
- agentName = record.agentName;
66
- workspace = record.workingDir;
67
- }
68
- await executeNewSession(interaction, adapter, agentName, workspace);
69
- }
70
- async function executeNewSession(interaction, adapter, agentName, workspace) {
71
- const config = adapter.core.configManager.get();
72
- const resolvedAgent = agentName || config.defaultAgent;
73
- log.info({ agentName: resolvedAgent, workspace }, "[discord-new-session] Creating session");
74
- const forumChannel = adapter.getForumChannel();
75
- if (!forumChannel) {
76
- const msg = "\u274C Forum channel not configured. Please run setup first.";
77
- if (interaction.deferred || interaction.replied) {
78
- await interaction.editReply(msg);
79
- } else {
80
- await interaction.reply({ content: msg, ephemeral: true });
81
- }
82
- return;
83
- }
84
- let thread;
85
- try {
86
- thread = await createSessionThread(forumChannel, `\u{1F504} ${resolvedAgent} \u2014 New Session`);
87
- const session = await adapter.core.handleNewSession("discord", resolvedAgent, workspace);
88
- session.threadId = thread.id;
89
- await adapter.core.sessionManager.patchRecord(session.id, {
90
- platform: { threadId: thread.id }
91
- });
92
- const controlRow = buildSessionControlKeyboard(session.id, false, false);
93
- await thread.send({
94
- content: `\u2705 **Session started**
95
- **Agent:** ${session.agentName}
96
- **Workspace:** \`${session.workingDirectory}\`
97
-
98
- This is your coding session \u2014 chat here to work with the agent.`,
99
- components: [controlRow]
100
- });
101
- const replyMsg = `\u2705 Session created \u2192 [Open thread](https://discord.com/channels/${adapter.getGuildId()}/${thread.id})`;
102
- if (interaction.deferred || interaction.replied) {
103
- await interaction.editReply(replyMsg);
104
- } else {
105
- await interaction.reply({ content: replyMsg, ephemeral: true });
106
- }
107
- session.warmup().catch((err) => log.error({ err }, "[discord-new-session] Warm-up error"));
108
- } catch (err) {
109
- log.error({ err }, "[discord-new-session] Session creation failed");
110
- if (thread) {
111
- try {
112
- await deleteSessionThread(adapter.getGuild(), thread.id);
113
- } catch {
114
- }
115
- }
116
- const errMsg = `\u274C ${err instanceof Error ? err.message : String(err)}`;
117
- try {
118
- if (interaction.deferred || interaction.replied) {
119
- await interaction.editReply(errMsg);
120
- } else {
121
- await interaction.reply({ content: errMsg, ephemeral: true });
122
- }
123
- } catch {
124
- }
125
- }
126
- }
127
- async function handleNewSessionButton(interaction, adapter) {
128
- const { customId } = interaction;
129
- if (customId.startsWith("m:new:agent:")) {
130
- const agentKey = customId.replace("m:new:agent:", "");
131
- try {
132
- await interaction.deferUpdate();
133
- } catch {
134
- }
135
- await executeNewSession(interaction, adapter, agentKey, void 0);
136
- }
137
- }
138
-
139
- export {
140
- handleNew,
141
- handleNewChat,
142
- executeNewSession,
143
- handleNewSessionButton
144
- };
145
- //# sourceMappingURL=chunk-QSDZDHNS.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/plugins/discord/commands/new-session.ts"],"sourcesContent":["import {\n ActionRowBuilder,\n ButtonBuilder,\n ButtonStyle,\n} from 'discord.js'\nimport type { ChatInputCommandInteraction, ButtonInteraction } from 'discord.js'\nimport { log } from '../../../core/utils/log.js'\nimport { buildSessionControlKeyboard } from './admin.js'\nimport { createSessionThread, deleteSessionThread } from '../forums.js'\nimport type { DiscordAdapter } from '../adapter.js'\n\nexport async function handleNew(\n interaction: ChatInputCommandInteraction,\n adapter: DiscordAdapter,\n): Promise<void> {\n await interaction.deferReply({ ephemeral: true })\n\n const agentName = interaction.options.getString('agent') ?? undefined\n const workspace = interaction.options.getString('workspace') ?? undefined\n\n if (agentName) {\n await executeNewSession(interaction, adapter, agentName, workspace)\n return\n }\n\n // No agent specified — show agent picker\n const installedEntries = adapter.core.agentCatalog.getInstalledEntries()\n const agentKeys = Object.keys(installedEntries)\n const config = adapter.core.configManager.get()\n\n if (agentKeys.length === 0) {\n await interaction.editReply('❌ No agents installed. Use `/install` to install an agent first.')\n return\n }\n\n if (agentKeys.length === 1) {\n await executeNewSession(interaction, adapter, config.defaultAgent, workspace)\n return\n }\n\n // Multiple agents — show picker buttons\n const row = new ActionRowBuilder<ButtonBuilder>()\n for (const key of agentKeys) {\n const agent = installedEntries[key]!\n const label = key === config.defaultAgent ? `${agent.name} (default)` : agent.name\n row.addComponents(\n new ButtonBuilder()\n .setCustomId(`m:new:agent:${key}`)\n .setLabel(label)\n .setStyle(ButtonStyle.Primary),\n )\n }\n\n await interaction.editReply({\n content: '🤖 **Choose an agent:**',\n components: [row],\n })\n}\n\nexport async function handleNewChat(\n interaction: ChatInputCommandInteraction,\n adapter: DiscordAdapter,\n): Promise<void> {\n await interaction.deferReply({ ephemeral: true })\n\n // Get current thread to inherit config from\n const channelId = interaction.channelId\n const currentSession = adapter.core.sessionManager.getSessionByThread('discord', channelId)\n\n let agentName: string | undefined\n let workspace: string | undefined\n\n if (currentSession) {\n agentName = currentSession.agentName\n workspace = currentSession.workingDirectory\n } else {\n const record = adapter.core.sessionManager.getRecordByThread('discord', channelId)\n if (!record || record.status === 'cancelled' || record.status === 'error') {\n await interaction.editReply('No active session in this channel. Use `/new` to start one.')\n return\n }\n agentName = record.agentName\n workspace = record.workingDir\n }\n\n await executeNewSession(interaction, adapter, agentName, workspace)\n}\n\nexport async function executeNewSession(\n interaction: ChatInputCommandInteraction | ButtonInteraction,\n adapter: DiscordAdapter,\n agentName?: string,\n workspace?: string,\n): Promise<void> {\n const config = adapter.core.configManager.get()\n const resolvedAgent = agentName || config.defaultAgent\n\n log.info({ agentName: resolvedAgent, workspace }, '[discord-new-session] Creating session')\n\n const forumChannel = adapter.getForumChannel()\n if (!forumChannel) {\n const msg = '❌ Forum channel not configured. Please run setup first.'\n if (interaction.deferred || interaction.replied) {\n await interaction.editReply(msg)\n } else {\n await (interaction as ChatInputCommandInteraction).reply({ content: msg, ephemeral: true })\n }\n return\n }\n\n let thread: import('discord.js').ThreadChannel | undefined\n\n try {\n // Create forum thread BEFORE creating session to avoid race condition\n thread = await createSessionThread(forumChannel, `🔄 ${resolvedAgent} — New Session`)\n\n // Create session via core\n const session = await adapter.core.handleNewSession('discord', resolvedAgent, workspace)\n session.threadId = thread.id\n\n // Patch platform record with Discord thread ID\n await adapter.core.sessionManager.patchRecord(session.id, {\n platform: { threadId: thread.id },\n })\n\n // Send welcome message in the new thread\n const controlRow = buildSessionControlKeyboard(session.id, false, false)\n await thread.send({\n content:\n `✅ **Session started**\\n` +\n `**Agent:** ${session.agentName}\\n` +\n `**Workspace:** \\`${session.workingDirectory}\\`\\n\\n` +\n `This is your coding session — chat here to work with the agent.`,\n components: [controlRow],\n })\n\n // Reply to the interaction with a link to the thread\n const replyMsg = `✅ Session created → [Open thread](https://discord.com/channels/${adapter.getGuildId()}/${thread.id})`\n if (interaction.deferred || interaction.replied) {\n await interaction.editReply(replyMsg)\n } else {\n await (interaction as ChatInputCommandInteraction).reply({ content: replyMsg, ephemeral: true })\n }\n\n // Warm up model cache in background\n session.warmup().catch((err: unknown) => log.error({ err }, '[discord-new-session] Warm-up error'))\n } catch (err) {\n log.error({ err }, '[discord-new-session] Session creation failed')\n\n // Clean up orphaned thread on failure (archive+lock instead of permanent delete)\n if (thread) {\n try { await deleteSessionThread(adapter.getGuild(), thread.id) } catch { /* ignore */ }\n }\n\n const errMsg = `❌ ${err instanceof Error ? err.message : String(err)}`\n try {\n if (interaction.deferred || interaction.replied) {\n await interaction.editReply(errMsg)\n } else {\n await (interaction as ChatInputCommandInteraction).reply({ content: errMsg, ephemeral: true })\n }\n } catch { /* ignore */ }\n }\n}\n\nexport async function handleNewSessionButton(\n interaction: ButtonInteraction,\n adapter: DiscordAdapter,\n): Promise<void> {\n const { customId } = interaction\n\n if (customId.startsWith('m:new:agent:')) {\n const agentKey = customId.replace('m:new:agent:', '')\n try { await interaction.deferUpdate() } catch { /* ignore */ }\n await executeNewSession(interaction, adapter, agentKey, undefined)\n }\n}\n"],"mappings":"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","names":[]}