@suzuke/agend 0.0.1 → 1.0.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 (157) hide show
  1. package/README.md +78 -0
  2. package/README.zh-TW.md +79 -0
  3. package/dist/access-path.d.ts +7 -0
  4. package/dist/access-path.js +12 -0
  5. package/dist/access-path.js.map +1 -0
  6. package/dist/backend/claude-code.d.ts +13 -0
  7. package/dist/backend/claude-code.js +114 -0
  8. package/dist/backend/claude-code.js.map +1 -0
  9. package/dist/backend/codex.d.ts +10 -0
  10. package/dist/backend/codex.js +58 -0
  11. package/dist/backend/codex.js.map +1 -0
  12. package/dist/backend/factory.d.ts +2 -0
  13. package/dist/backend/factory.js +19 -0
  14. package/dist/backend/factory.js.map +1 -0
  15. package/dist/backend/gemini-cli.d.ts +10 -0
  16. package/dist/backend/gemini-cli.js +68 -0
  17. package/dist/backend/gemini-cli.js.map +1 -0
  18. package/dist/backend/index.d.ts +6 -0
  19. package/dist/backend/index.js +6 -0
  20. package/dist/backend/index.js.map +1 -0
  21. package/dist/backend/opencode.d.ts +10 -0
  22. package/dist/backend/opencode.js +63 -0
  23. package/dist/backend/opencode.js.map +1 -0
  24. package/dist/backend/types.d.ts +26 -0
  25. package/dist/backend/types.js +2 -0
  26. package/dist/backend/types.js.map +1 -0
  27. package/dist/channel/access-manager.d.ts +18 -0
  28. package/dist/channel/access-manager.js +149 -0
  29. package/dist/channel/access-manager.js.map +1 -0
  30. package/dist/channel/adapters/discord.d.ts +45 -0
  31. package/dist/channel/adapters/discord.js +366 -0
  32. package/dist/channel/adapters/discord.js.map +1 -0
  33. package/dist/channel/adapters/telegram.d.ts +58 -0
  34. package/dist/channel/adapters/telegram.js +569 -0
  35. package/dist/channel/adapters/telegram.js.map +1 -0
  36. package/dist/channel/attachment-handler.d.ts +15 -0
  37. package/dist/channel/attachment-handler.js +55 -0
  38. package/dist/channel/attachment-handler.js.map +1 -0
  39. package/dist/channel/factory.d.ts +12 -0
  40. package/dist/channel/factory.js +38 -0
  41. package/dist/channel/factory.js.map +1 -0
  42. package/dist/channel/ipc-bridge.d.ts +26 -0
  43. package/dist/channel/ipc-bridge.js +170 -0
  44. package/dist/channel/ipc-bridge.js.map +1 -0
  45. package/dist/channel/mcp-server.d.ts +10 -0
  46. package/dist/channel/mcp-server.js +196 -0
  47. package/dist/channel/mcp-server.js.map +1 -0
  48. package/dist/channel/mcp-tools.d.ts +909 -0
  49. package/dist/channel/mcp-tools.js +346 -0
  50. package/dist/channel/mcp-tools.js.map +1 -0
  51. package/dist/channel/message-bus.d.ts +17 -0
  52. package/dist/channel/message-bus.js +86 -0
  53. package/dist/channel/message-bus.js.map +1 -0
  54. package/dist/channel/message-queue.d.ts +39 -0
  55. package/dist/channel/message-queue.js +248 -0
  56. package/dist/channel/message-queue.js.map +1 -0
  57. package/dist/channel/tool-router.d.ts +6 -0
  58. package/dist/channel/tool-router.js +69 -0
  59. package/dist/channel/tool-router.js.map +1 -0
  60. package/dist/channel/tool-tracker.d.ts +13 -0
  61. package/dist/channel/tool-tracker.js +58 -0
  62. package/dist/channel/tool-tracker.js.map +1 -0
  63. package/dist/channel/types.d.ts +116 -0
  64. package/dist/channel/types.js +2 -0
  65. package/dist/channel/types.js.map +1 -0
  66. package/dist/cli.d.ts +2 -0
  67. package/dist/cli.js +782 -0
  68. package/dist/cli.js.map +1 -0
  69. package/dist/config.d.ts +8 -0
  70. package/dist/config.js +85 -0
  71. package/dist/config.js.map +1 -0
  72. package/dist/context-guardian.d.ts +29 -0
  73. package/dist/context-guardian.js +123 -0
  74. package/dist/context-guardian.js.map +1 -0
  75. package/dist/cost-guard.d.ts +21 -0
  76. package/dist/cost-guard.js +113 -0
  77. package/dist/cost-guard.js.map +1 -0
  78. package/dist/daemon-entry.d.ts +1 -0
  79. package/dist/daemon-entry.js +29 -0
  80. package/dist/daemon-entry.js.map +1 -0
  81. package/dist/daemon.d.ts +88 -0
  82. package/dist/daemon.js +821 -0
  83. package/dist/daemon.js.map +1 -0
  84. package/dist/daily-summary.d.ts +13 -0
  85. package/dist/daily-summary.js +55 -0
  86. package/dist/daily-summary.js.map +1 -0
  87. package/dist/event-log.d.ts +22 -0
  88. package/dist/event-log.js +66 -0
  89. package/dist/event-log.js.map +1 -0
  90. package/dist/export-import.d.ts +2 -0
  91. package/dist/export-import.js +110 -0
  92. package/dist/export-import.js.map +1 -0
  93. package/dist/fleet-context.d.ts +36 -0
  94. package/dist/fleet-context.js +4 -0
  95. package/dist/fleet-context.js.map +1 -0
  96. package/dist/fleet-manager.d.ts +115 -0
  97. package/dist/fleet-manager.js +1739 -0
  98. package/dist/fleet-manager.js.map +1 -0
  99. package/dist/fleet-system-prompt.d.ts +11 -0
  100. package/dist/fleet-system-prompt.js +60 -0
  101. package/dist/fleet-system-prompt.js.map +1 -0
  102. package/dist/hang-detector.d.ts +16 -0
  103. package/dist/hang-detector.js +53 -0
  104. package/dist/hang-detector.js.map +1 -0
  105. package/dist/index.d.ts +8 -0
  106. package/dist/index.js +6 -0
  107. package/dist/index.js.map +1 -0
  108. package/dist/logger.d.ts +3 -0
  109. package/dist/logger.js +63 -0
  110. package/dist/logger.js.map +1 -0
  111. package/dist/plugin/agend/.claude-plugin/plugin.json +5 -0
  112. package/dist/scheduler/db.d.ts +16 -0
  113. package/dist/scheduler/db.js +132 -0
  114. package/dist/scheduler/db.js.map +1 -0
  115. package/dist/scheduler/db.test.d.ts +1 -0
  116. package/dist/scheduler/db.test.js +92 -0
  117. package/dist/scheduler/db.test.js.map +1 -0
  118. package/dist/scheduler/index.d.ts +4 -0
  119. package/dist/scheduler/index.js +4 -0
  120. package/dist/scheduler/index.js.map +1 -0
  121. package/dist/scheduler/scheduler.d.ts +25 -0
  122. package/dist/scheduler/scheduler.js +119 -0
  123. package/dist/scheduler/scheduler.js.map +1 -0
  124. package/dist/scheduler/scheduler.test.d.ts +1 -0
  125. package/dist/scheduler/scheduler.test.js +119 -0
  126. package/dist/scheduler/scheduler.test.js.map +1 -0
  127. package/dist/scheduler/types.d.ts +47 -0
  128. package/dist/scheduler/types.js +7 -0
  129. package/dist/scheduler/types.js.map +1 -0
  130. package/dist/service-installer.d.ts +14 -0
  131. package/dist/service-installer.js +91 -0
  132. package/dist/service-installer.js.map +1 -0
  133. package/dist/setup-wizard.d.ts +14 -0
  134. package/dist/setup-wizard.js +517 -0
  135. package/dist/setup-wizard.js.map +1 -0
  136. package/dist/stt.d.ts +10 -0
  137. package/dist/stt.js +33 -0
  138. package/dist/stt.js.map +1 -0
  139. package/dist/tmux-manager.d.ts +22 -0
  140. package/dist/tmux-manager.js +132 -0
  141. package/dist/tmux-manager.js.map +1 -0
  142. package/dist/topic-commands.d.ts +22 -0
  143. package/dist/topic-commands.js +176 -0
  144. package/dist/topic-commands.js.map +1 -0
  145. package/dist/transcript-monitor.d.ts +21 -0
  146. package/dist/transcript-monitor.js +149 -0
  147. package/dist/transcript-monitor.js.map +1 -0
  148. package/dist/types.d.ts +153 -0
  149. package/dist/types.js +2 -0
  150. package/dist/types.js.map +1 -0
  151. package/dist/webhook-emitter.d.ts +15 -0
  152. package/dist/webhook-emitter.js +41 -0
  153. package/dist/webhook-emitter.js.map +1 -0
  154. package/package.json +58 -4
  155. package/templates/launchd.plist.ejs +29 -0
  156. package/templates/systemd.service.ejs +15 -0
  157. package/index.js +0 -1
@@ -0,0 +1,18 @@
1
+ import type { AccessConfig } from "../types.js";
2
+ export declare class AccessManager {
3
+ private config;
4
+ private statePath;
5
+ private state;
6
+ private failedAttempts;
7
+ constructor(config: AccessConfig, statePath: string);
8
+ private persist;
9
+ private pruneExpired;
10
+ isAllowed(userId: number): boolean;
11
+ hasPairingQuota(userId: number): boolean;
12
+ generateCode(userId: number): string;
13
+ confirmCode(code: string, callerUserId?: string): boolean;
14
+ setMode(mode: "pairing" | "locked"): void;
15
+ getMode(): "pairing" | "locked";
16
+ getAllowedUsers(): number[];
17
+ removeUser(userId: number): boolean;
18
+ }
@@ -0,0 +1,149 @@
1
+ import { readFileSync, writeFileSync, existsSync } from "node:fs";
2
+ import { randomBytes } from "node:crypto";
3
+ export class AccessManager {
4
+ config;
5
+ statePath;
6
+ state;
7
+ failedAttempts = new Map();
8
+ constructor(config, statePath) {
9
+ this.config = config;
10
+ this.statePath = statePath;
11
+ // Load persisted state or start fresh
12
+ if (existsSync(statePath)) {
13
+ try {
14
+ const raw = readFileSync(statePath, "utf8");
15
+ const saved = JSON.parse(raw);
16
+ this.state = {
17
+ mode: saved.mode,
18
+ allowed_users: saved.allowed_users ?? [],
19
+ pending_codes: saved.pending_codes ?? [],
20
+ };
21
+ }
22
+ catch {
23
+ this.state = { allowed_users: [], pending_codes: [] };
24
+ }
25
+ }
26
+ else {
27
+ this.state = { allowed_users: [], pending_codes: [] };
28
+ }
29
+ // Merge config's allowed_users with saved ones (deduplicated)
30
+ const merged = new Set([...this.state.allowed_users, ...config.allowed_users]);
31
+ this.state.allowed_users = Array.from(merged);
32
+ // If saved state has no mode, use config mode
33
+ if (this.state.mode === undefined) {
34
+ this.state.mode = config.mode;
35
+ }
36
+ // Prune expired codes on load
37
+ this.pruneExpired();
38
+ }
39
+ persist() {
40
+ writeFileSync(this.statePath, JSON.stringify(this.state, null, 2), "utf8");
41
+ }
42
+ pruneExpired() {
43
+ const now = Date.now();
44
+ const expiryMs = this.config.code_expiry_minutes * 60 * 1000;
45
+ const before = this.state.pending_codes.length;
46
+ this.state.pending_codes = this.state.pending_codes.filter((p) => now - p.createdAt < expiryMs);
47
+ if (this.state.pending_codes.length !== before) {
48
+ this.persist();
49
+ }
50
+ }
51
+ isAllowed(userId) {
52
+ return this.state.allowed_users.includes(userId);
53
+ }
54
+ hasPairingQuota(userId) {
55
+ const userCodes = this.state.pending_codes.filter((p) => p.userId === userId);
56
+ return userCodes.length < 2;
57
+ }
58
+ generateCode(userId) {
59
+ this.pruneExpired();
60
+ if (this.state.mode === "locked") {
61
+ throw new Error("Cannot generate pairing code in locked mode");
62
+ }
63
+ if (!this.hasPairingQuota(userId)) {
64
+ throw new Error(`User ${userId} has reached max pairing code attempts (2)`);
65
+ }
66
+ // Count distinct users with pending codes
67
+ const usersWithPending = new Set(this.state.pending_codes.map((p) => p.userId));
68
+ // If this user is new and we're already at max, throw
69
+ if (!usersWithPending.has(userId) && usersWithPending.size >= this.config.max_pending_codes) {
70
+ throw new Error(`Max pending codes reached for ${this.config.max_pending_codes} unique users`);
71
+ }
72
+ const code = randomBytes(4).toString("hex").toUpperCase();
73
+ this.state.pending_codes.push({
74
+ code,
75
+ userId,
76
+ createdAt: Date.now(),
77
+ attempts: 0,
78
+ });
79
+ this.persist();
80
+ return code;
81
+ }
82
+ confirmCode(code, callerUserId) {
83
+ this.pruneExpired();
84
+ // Rate limit: check per-userId failures (10 failures in 60 seconds)
85
+ if (callerUserId) {
86
+ const record = this.failedAttempts.get(callerUserId);
87
+ if (record) {
88
+ const elapsed = Date.now() - record.lastAttempt;
89
+ if (elapsed > 60_000) {
90
+ // Reset window
91
+ this.failedAttempts.delete(callerUserId);
92
+ }
93
+ else if (record.count >= 10) {
94
+ return false;
95
+ }
96
+ }
97
+ }
98
+ const entry = this.state.pending_codes.find((p) => p.code === code);
99
+ if (!entry) {
100
+ // Increment attempts on all pending codes that were checked
101
+ for (const pending of this.state.pending_codes) {
102
+ pending.attempts++;
103
+ }
104
+ // Auto-invalidate codes that have been tried too many times
105
+ this.state.pending_codes = this.state.pending_codes.filter((p) => p.attempts < 5);
106
+ // Track per-userId failures
107
+ if (callerUserId) {
108
+ const record = this.failedAttempts.get(callerUserId);
109
+ if (record) {
110
+ record.count++;
111
+ record.lastAttempt = Date.now();
112
+ }
113
+ else {
114
+ this.failedAttempts.set(callerUserId, { count: 1, lastAttempt: Date.now() });
115
+ }
116
+ }
117
+ this.persist();
118
+ return false;
119
+ }
120
+ // Add user to allowlist if not already there
121
+ if (!this.state.allowed_users.includes(entry.userId)) {
122
+ this.state.allowed_users.push(entry.userId);
123
+ }
124
+ // Remove all pending codes for that user
125
+ this.state.pending_codes = this.state.pending_codes.filter((p) => p.userId !== entry.userId);
126
+ this.persist();
127
+ return true;
128
+ }
129
+ setMode(mode) {
130
+ this.state.mode = mode;
131
+ this.persist();
132
+ }
133
+ getMode() {
134
+ return this.state.mode ?? this.config.mode;
135
+ }
136
+ getAllowedUsers() {
137
+ return [...this.state.allowed_users];
138
+ }
139
+ removeUser(userId) {
140
+ const idx = this.state.allowed_users.indexOf(userId);
141
+ if (idx === -1) {
142
+ return false;
143
+ }
144
+ this.state.allowed_users.splice(idx, 1);
145
+ this.persist();
146
+ return true;
147
+ }
148
+ }
149
+ //# sourceMappingURL=access-manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"access-manager.js","sourceRoot":"","sources":["../../src/channel/access-manager.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,45 @@
1
+ import { EventEmitter } from "node:events";
2
+ import type { ChannelAdapter, ApprovalHandle, SendOpts, SentMessage, PermissionPrompt, Choice, AlertData } from "../types.js";
3
+ import type { AccessManager } from "../access-manager.js";
4
+ export interface DiscordAdapterOptions {
5
+ id: string;
6
+ botToken: string;
7
+ accessManager: AccessManager;
8
+ inboxDir: string;
9
+ guildId: string;
10
+ categoryName?: string;
11
+ generalChannelId?: string;
12
+ }
13
+ export declare class DiscordAdapter extends EventEmitter implements ChannelAdapter {
14
+ readonly type = "discord";
15
+ readonly topology: "channels";
16
+ readonly id: string;
17
+ private client;
18
+ private botToken;
19
+ private accessManager;
20
+ private inboxDir;
21
+ private guildId;
22
+ private categoryName;
23
+ private generalChannelId?;
24
+ private queue;
25
+ private lastChatId;
26
+ constructor(opts: DiscordAdapterOptions);
27
+ private _fetchTextChannel;
28
+ private _registerHandlers;
29
+ start(): Promise<void>;
30
+ stop(): Promise<void>;
31
+ sendText(chatId: string, text: string, opts?: SendOpts): Promise<SentMessage>;
32
+ sendFile(chatId: string, filePath: string, opts?: SendOpts): Promise<SentMessage>;
33
+ editMessage(chatId: string, messageId: string, text: string): Promise<void>;
34
+ react(chatId: string, messageId: string, emoji: string): Promise<void>;
35
+ sendApproval(prompt: PermissionPrompt, callback: (decision: "approve" | "approve_always" | "deny") => void, signal?: AbortSignal, threadId?: string): Promise<ApprovalHandle>;
36
+ getChatId(): string | null;
37
+ setChatId(chatId: string): void;
38
+ downloadAttachment(fileId: string): Promise<string>;
39
+ promptUser(chatId: string, text: string, choices: Choice[], opts?: SendOpts): Promise<string>;
40
+ notifyAlert(chatId: string, alert: AlertData, opts?: SendOpts): Promise<SentMessage>;
41
+ createTopic(name: string): Promise<number>;
42
+ topicExists(topicId: number): Promise<boolean>;
43
+ handlePairing(chatId: string, userId: string): Promise<string>;
44
+ confirmPairing(code: string): Promise<boolean>;
45
+ }
@@ -0,0 +1,366 @@
1
+ import { EventEmitter } from "node:events";
2
+ import { randomBytes } from "node:crypto";
3
+ import { mkdirSync } from "node:fs";
4
+ import { Client, GatewayIntentBits, ActionRowBuilder, ButtonBuilder, ButtonStyle, ChannelType, } from "discord.js";
5
+ import { MessageQueue } from "../message-queue.js";
6
+ const DISCORD_MAX_LENGTH = 2000;
7
+ export class DiscordAdapter extends EventEmitter {
8
+ type = "discord";
9
+ topology = "channels";
10
+ id;
11
+ client;
12
+ botToken;
13
+ accessManager;
14
+ inboxDir;
15
+ guildId;
16
+ categoryName;
17
+ generalChannelId;
18
+ queue;
19
+ lastChatId = null;
20
+ constructor(opts) {
21
+ super();
22
+ this.id = opts.id;
23
+ this.botToken = opts.botToken;
24
+ this.accessManager = opts.accessManager;
25
+ this.inboxDir = opts.inboxDir;
26
+ this.guildId = opts.guildId;
27
+ this.categoryName = opts.categoryName ?? "AgEnD Agents";
28
+ this.generalChannelId = opts.generalChannelId;
29
+ mkdirSync(this.inboxDir, { recursive: true });
30
+ this.client = new Client({
31
+ intents: [
32
+ GatewayIntentBits.Guilds,
33
+ GatewayIntentBits.GuildMessages,
34
+ GatewayIntentBits.MessageContent,
35
+ ],
36
+ });
37
+ this.queue = new MessageQueue({
38
+ send: async (chatId, threadId, text) => {
39
+ const channel = await this._fetchTextChannel(threadId ?? chatId);
40
+ const msg = await channel.send(text);
41
+ return { messageId: msg.id };
42
+ },
43
+ edit: async (chatId, messageId, text) => {
44
+ const channel = await this._fetchTextChannel(chatId);
45
+ const msg = await channel.messages.fetch(messageId);
46
+ await msg.edit(text);
47
+ },
48
+ sendFile: async (chatId, threadId, filePath) => {
49
+ const channel = await this._fetchTextChannel(threadId ?? chatId);
50
+ const msg = await channel.send({ files: [filePath] });
51
+ return { messageId: msg.id };
52
+ },
53
+ });
54
+ this._registerHandlers();
55
+ }
56
+ async _fetchTextChannel(channelId) {
57
+ const channel = await this.client.channels.fetch(channelId);
58
+ if (!channel?.isTextBased()) {
59
+ throw new Error(`Channel ${channelId} is not a text channel`);
60
+ }
61
+ return channel;
62
+ }
63
+ _registerHandlers() {
64
+ this.client.on("messageCreate", async (msg) => {
65
+ if (msg.author.bot)
66
+ return;
67
+ if (msg.guildId !== this.guildId)
68
+ return;
69
+ const userId = msg.author.id;
70
+ // Access control — Discord snowflake IDs are strings, parseInt for AccessManager
71
+ if (!this.accessManager.isAllowed(Number(userId))) {
72
+ return;
73
+ }
74
+ const chatId = this.guildId;
75
+ const threadId = msg.channelId;
76
+ const messageId = msg.id;
77
+ const username = msg.author.username;
78
+ const text = msg.content;
79
+ // Collect attachments
80
+ const attachments = msg.attachments.map((att) => ({
81
+ kind: "document",
82
+ fileId: att.id,
83
+ mime: att.contentType ?? undefined,
84
+ size: att.size,
85
+ filename: att.name ?? undefined,
86
+ }));
87
+ this.emit("message", {
88
+ source: "discord",
89
+ adapterId: this.id,
90
+ chatId,
91
+ threadId,
92
+ messageId,
93
+ userId,
94
+ username,
95
+ text,
96
+ timestamp: msg.createdAt,
97
+ attachments: attachments.length > 0 ? attachments : undefined,
98
+ replyTo: msg.reference?.messageId ?? undefined,
99
+ });
100
+ });
101
+ // Handle button interactions
102
+ this.client.on("interactionCreate", async (interaction) => {
103
+ if (!interaction.isButton())
104
+ return;
105
+ await interaction.deferUpdate();
106
+ this.emit("callback_query", {
107
+ callbackData: interaction.customId,
108
+ chatId: this.guildId,
109
+ threadId: interaction.channelId,
110
+ messageId: interaction.message.id,
111
+ });
112
+ });
113
+ // Handle channel deletion (equivalent to topic_closed)
114
+ this.client.on("channelDelete", (channel) => {
115
+ if (!("guildId" in channel))
116
+ return;
117
+ if (channel.guildId !== this.guildId)
118
+ return;
119
+ this.emit("topic_closed", {
120
+ chatId: this.guildId,
121
+ threadId: channel.id,
122
+ });
123
+ });
124
+ }
125
+ // ── Lifecycle ──────────────────────────────────────────────────────────
126
+ async start() {
127
+ this.queue.start();
128
+ this.client.once("ready", () => {
129
+ this.emit("started", this.client.user?.username ?? "discord-bot");
130
+ });
131
+ await this.client.login(this.botToken);
132
+ }
133
+ async stop() {
134
+ this.queue.stop();
135
+ this.client.destroy();
136
+ }
137
+ // ── Text / file sending ────────────────────────────────────────────────
138
+ async sendText(chatId, text, opts) {
139
+ const channelId = opts?.threadId ?? chatId;
140
+ const channel = await this._fetchTextChannel(channelId);
141
+ const chunkLimit = opts?.chunkLimit ?? DISCORD_MAX_LENGTH;
142
+ const chunks = splitText(text, chunkLimit);
143
+ if (chunks.length === 0)
144
+ throw new Error("Empty text");
145
+ const first = await channel.send(chunks[0]);
146
+ // Enqueue remaining chunks
147
+ for (let i = 1; i < chunks.length; i++) {
148
+ this.queue.enqueue(chatId, opts?.threadId, { type: "content", text: chunks[i] });
149
+ }
150
+ return {
151
+ messageId: first.id,
152
+ chatId,
153
+ threadId: opts?.threadId,
154
+ };
155
+ }
156
+ async sendFile(chatId, filePath, opts) {
157
+ const channelId = opts?.threadId ?? chatId;
158
+ const channel = await this._fetchTextChannel(channelId);
159
+ const msg = await channel.send({ files: [filePath] });
160
+ return { messageId: msg.id, chatId, threadId: opts?.threadId };
161
+ }
162
+ async editMessage(chatId, messageId, text) {
163
+ // chatId is guild ID in channels topology, but messageId is in a channel.
164
+ // We need to find the message. Try all text channels in the guild.
165
+ // Optimization: caller usually provides the channel via sendText return value.
166
+ try {
167
+ // Try the general channel first, then search
168
+ const guild = await this.client.guilds.fetch(this.guildId);
169
+ const channels = guild.channels.cache.filter((c) => c.type === ChannelType.GuildText);
170
+ for (const [, ch] of channels) {
171
+ try {
172
+ const textCh = ch;
173
+ const msg = await textCh.messages.fetch(messageId);
174
+ await msg.edit(text.slice(0, DISCORD_MAX_LENGTH));
175
+ return;
176
+ }
177
+ catch {
178
+ continue;
179
+ }
180
+ }
181
+ throw new Error(`Message ${messageId} not found in any channel`);
182
+ }
183
+ catch (err) {
184
+ // Fallback: send a new message if edit fails
185
+ if (this.generalChannelId) {
186
+ const channel = await this._fetchTextChannel(this.generalChannelId);
187
+ await channel.send(text.slice(0, DISCORD_MAX_LENGTH));
188
+ }
189
+ }
190
+ }
191
+ async react(chatId, messageId, emoji) {
192
+ try {
193
+ const guild = await this.client.guilds.fetch(this.guildId);
194
+ const channels = guild.channels.cache.filter((c) => c.type === ChannelType.GuildText);
195
+ for (const [, ch] of channels) {
196
+ try {
197
+ const textCh = ch;
198
+ const msg = await textCh.messages.fetch(messageId);
199
+ await msg.react(emoji);
200
+ return;
201
+ }
202
+ catch {
203
+ continue;
204
+ }
205
+ }
206
+ }
207
+ catch {
208
+ // No-op per degradation strategy
209
+ }
210
+ }
211
+ // ── Approval ───────────────────────────────────────────────────────────
212
+ async sendApproval(prompt, callback, signal, threadId) {
213
+ const nonce = randomBytes(5).toString("hex");
214
+ const approveData = `approval:approve:${nonce}`;
215
+ const alwaysData = `approval:approve_always:${nonce}`;
216
+ const denyData = `approval:deny:${nonce}`;
217
+ const row = new ActionRowBuilder().addComponents(new ButtonBuilder()
218
+ .setCustomId(approveData)
219
+ .setLabel("Allow")
220
+ .setStyle(ButtonStyle.Success), new ButtonBuilder()
221
+ .setCustomId(alwaysData)
222
+ .setLabel("Always")
223
+ .setStyle(ButtonStyle.Success), new ButtonBuilder()
224
+ .setCustomId(denyData)
225
+ .setLabel("Deny")
226
+ .setStyle(ButtonStyle.Danger));
227
+ let text = `⚠️ **Permission Request**\nTool: \`${prompt.tool_name}\``;
228
+ if (prompt.input_preview) {
229
+ const preview = prompt.input_preview.length > 200
230
+ ? prompt.input_preview.slice(0, 200) + "…"
231
+ : prompt.input_preview;
232
+ text += `\n\`\`\`\n${preview}\n\`\`\``;
233
+ }
234
+ else if (prompt.description) {
235
+ text += `\n${prompt.description}`;
236
+ }
237
+ const cleanup = () => {
238
+ this.off("callback_query", handler);
239
+ };
240
+ const handler = (query) => {
241
+ if (!query.callbackData)
242
+ return;
243
+ const isApprove = query.callbackData === approveData;
244
+ const isAlways = query.callbackData === alwaysData;
245
+ const isDeny = query.callbackData === denyData;
246
+ if (!isApprove && !isAlways && !isDeny)
247
+ return;
248
+ cleanup();
249
+ // Update the message to show the decision
250
+ if (query.threadId && query.messageId) {
251
+ this._fetchTextChannel(query.threadId).then((ch) => {
252
+ ch.messages.fetch(query.messageId).then((msg) => {
253
+ const label = isDeny ? "❌ Denied" : isAlways ? "✅ Always Allowed" : "✅ Allowed";
254
+ msg.edit({
255
+ content: `${label}\nTool: \`${prompt.tool_name}\``,
256
+ components: [],
257
+ }).catch(() => { });
258
+ }).catch(() => { });
259
+ }).catch(() => { });
260
+ }
261
+ callback(isDeny ? "deny" : isAlways ? "approve_always" : "approve");
262
+ };
263
+ this.on("callback_query", handler);
264
+ if (signal) {
265
+ signal.addEventListener("abort", () => cleanup());
266
+ }
267
+ const channelId = threadId ?? this.generalChannelId;
268
+ if (channelId) {
269
+ const channel = await this._fetchTextChannel(channelId);
270
+ await channel.send({ content: text, components: [row] });
271
+ }
272
+ else {
273
+ this.emit("approval_request", { prompt: text, components: [row], nonce });
274
+ }
275
+ return { cancel: cleanup };
276
+ }
277
+ // ── Chat ID management ──────────────────────────────────────────────────
278
+ getChatId() { return this.lastChatId; }
279
+ setChatId(chatId) { this.lastChatId = chatId; }
280
+ // ── File download ──────────────────────────────────────────────────────
281
+ async downloadAttachment(fileId) {
282
+ // Discord attachment fileId is the attachment ID. We need to find the URL.
283
+ // Since Discord attachments include URLs directly, we'll search for the message
284
+ // containing this attachment. For MVP, we store the URL in the attachment metadata.
285
+ // Here we try to download via the Discord CDN URL pattern.
286
+ // In practice, the inbound message handler should store the URL.
287
+ throw new Error("downloadAttachment not yet implemented for Discord — use attachment URL directly");
288
+ }
289
+ // ── Intent-oriented methods ──────────────────────────────────────────
290
+ async promptUser(chatId, text, choices, opts) {
291
+ const channelId = opts?.threadId ?? chatId;
292
+ const channel = await this._fetchTextChannel(channelId);
293
+ const row = new ActionRowBuilder();
294
+ for (const choice of choices) {
295
+ row.addComponents(new ButtonBuilder()
296
+ .setCustomId(choice.id)
297
+ .setLabel(choice.label.slice(0, 80)) // Discord button label max 80 chars
298
+ .setStyle(ButtonStyle.Primary));
299
+ }
300
+ const msg = await channel.send({ content: text, components: [row] });
301
+ return msg.id;
302
+ }
303
+ async notifyAlert(chatId, alert, opts) {
304
+ if (alert.choices && alert.choices.length > 0) {
305
+ const channelId = opts?.threadId ?? chatId;
306
+ const channel = await this._fetchTextChannel(channelId);
307
+ const row = new ActionRowBuilder();
308
+ for (const choice of alert.choices) {
309
+ row.addComponents(new ButtonBuilder()
310
+ .setCustomId(choice.id)
311
+ .setLabel(choice.label.slice(0, 80))
312
+ .setStyle(ButtonStyle.Secondary));
313
+ }
314
+ const msg = await channel.send({ content: alert.message, components: [row] });
315
+ return { messageId: msg.id, chatId, threadId: opts?.threadId };
316
+ }
317
+ return this.sendText(chatId, alert.message, opts);
318
+ }
319
+ // ── Topology: create channel ────────────────────────────────────────────
320
+ async createTopic(name) {
321
+ const guild = await this.client.guilds.fetch(this.guildId);
322
+ // Find or create the category
323
+ let category = guild.channels.cache.find((c) => c.type === ChannelType.GuildCategory && c.name === this.categoryName);
324
+ if (!category) {
325
+ category = await guild.channels.create({
326
+ name: this.categoryName,
327
+ type: ChannelType.GuildCategory,
328
+ });
329
+ }
330
+ const channelOpts = {
331
+ name,
332
+ type: ChannelType.GuildText,
333
+ parent: category.id,
334
+ };
335
+ const channel = await guild.channels.create(channelOpts);
336
+ return parseInt(channel.id);
337
+ }
338
+ async topicExists(topicId) {
339
+ try {
340
+ const channel = await this.client.channels.fetch(String(topicId));
341
+ return channel != null;
342
+ }
343
+ catch {
344
+ return false;
345
+ }
346
+ }
347
+ // ── Pairing ────────────────────────────────────────────────────────────
348
+ async handlePairing(chatId, userId) {
349
+ const code = this.accessManager.generateCode(Number(userId));
350
+ return code;
351
+ }
352
+ async confirmPairing(code) {
353
+ return this.accessManager.confirmCode(code);
354
+ }
355
+ }
356
+ // ── Helpers ──────────────────────────────────────────────────────────────
357
+ function splitText(text, limit) {
358
+ const chunks = [];
359
+ let offset = 0;
360
+ while (offset < text.length) {
361
+ chunks.push(text.slice(offset, offset + limit));
362
+ offset += limit;
363
+ }
364
+ return chunks;
365
+ }
366
+ //# sourceMappingURL=discord.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"discord.js","sourceRoot":"","sources":["../../../src/channel/adapters/discord.ts"],"names":[],"mappings":"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"}