volute 0.26.0 → 0.27.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.
- package/README.md +13 -13
- package/dist/{activity-events-ZMBAKLUF.js → activity-events-BBIEA2F4.js} +2 -3
- package/dist/api.d.ts +363 -168
- package/dist/{archive-4ZQYK5MN.js → archive-UA4BDFXQ.js} +2 -2
- package/dist/{auth-4TV573WE.js → auth-D3OT2ARB.js} +3 -3
- package/dist/bridge-FQHZL3MC.js +206 -0
- package/dist/chat-MHJ3L6JQ.js +58 -0
- package/dist/{chunk-PHU4DEAJ.js → chunk-2WPW7OT6.js} +3 -3
- package/dist/{chunk-5Y3PBKW6.js → chunk-2YP2TVDT.js} +138 -56
- package/dist/{chunk-USNBKHYG.js → chunk-4WXYUOAK.js} +4 -6
- package/dist/{chunk-YJA7P64S.js → chunk-AW7PFDVN.js} +5 -5
- package/dist/{chunk-OZFKBXD6.js → chunk-EHYDTZTF.js} +6 -6
- package/dist/{chunk-LX22GRG7.js → chunk-GIE6CSN5.js} +11 -8
- package/dist/{chunk-WBHMQ5OZ.js → chunk-H7OZRFJB.js} +192 -12
- package/dist/{chunk-ON3FF5JA.js → chunk-HDN7MNGD.js} +3 -3
- package/dist/chunk-IAYBDWVG.js +477 -0
- package/dist/{chunk-TZKJLDQN.js → chunk-IKRVFPWU.js} +14 -9
- package/dist/{chunk-WGOGUMPO.js → chunk-JGFVMROS.js} +13 -6
- package/dist/{chunk-3TV4GLFO.js → chunk-JKOWNZ4P.js} +3 -3
- package/dist/{chunk-NWI2425I.js → chunk-K5NAC55T.js} +1 -1
- package/dist/{chunk-HFCBO2GL.js → chunk-KDGS53OS.js} +4 -4
- package/dist/chunk-KTLFDYPT.js +61 -0
- package/dist/{chunk-V63B7DX3.js → chunk-LAC664WU.js} +7 -4
- package/dist/{chunk-3CFRE2VC.js → chunk-OQZH4PBB.js} +337 -1061
- package/dist/{chunk-2VO7453N.js → chunk-PHSAT7YL.js} +30 -54
- package/dist/{chunk-XOXLRRR2.js → chunk-RKQEHRBB.js} +4 -3
- package/dist/chunk-T6HKBWXZ.js +23 -0
- package/dist/{chunk-UTL75LP6.js → chunk-USUXRNVD.js} +22 -22
- package/dist/{chunk-J2CO4WEV.js → chunk-VIVMW2H2.js} +4 -4
- package/dist/{chunk-KTJGZ7M7.js → chunk-XBLSAVJF.js} +1 -1
- package/dist/cli.js +31 -36
- package/dist/{cloud-sync-NI2K3C7G.js → cloud-sync-T7M3ESC3.js} +15 -14
- package/dist/connectors/discord-bridge.js +158 -0
- package/dist/connectors/slack-bridge.js +119 -0
- package/dist/connectors/telegram-bridge.js +133 -0
- package/dist/conversations-M2K4253F.js +55 -0
- package/dist/create-D7J73A6H.js +45 -0
- package/dist/{create-4YBRTTJS.js → create-QWV73WXD.js} +1 -1
- package/dist/{daemon-client-Z7FAJ6JW.js → daemon-client-I42FK2BF.js} +2 -2
- package/dist/{daemon-restart-BJZ3O4U4.js → daemon-restart-M2QTYMEG.js} +7 -7
- package/dist/daemon.js +1758 -1024
- package/dist/db-IC4J52XQ.js +8 -0
- package/dist/{delete-27OYNK25.js → delete-4JYGD4VN.js} +1 -1
- package/dist/down-LVBXEULC.js +14 -0
- package/dist/{env-M336ONDP.js → env-YJMUMFIY.js} +2 -2
- package/dist/{export-HP4G5DQC.js → export-BOJQWBMA.js} +4 -4
- package/dist/{file-HUDKTRAS.js → file-CR36YUPD.js} +4 -4
- package/dist/{history-B64GTFTD.js → history-XKRTAFS2.js} +5 -5
- package/dist/{import-XIB7UV4S.js → import-SRTQXBGH.js} +4 -4
- package/dist/join-J4QU42DL.js +66 -0
- package/dist/list-R73GENNL.js +40 -0
- package/dist/{log-PBFNILJ4.js → log-ABYNVYJ3.js} +4 -4
- package/dist/{login-B5E7N7MY.js → login-3QZNR2DF.js} +4 -4
- package/dist/{login-6U7U6BNG.js → login-XX37I52P.js} +2 -2
- package/dist/{logout-XSJRYS3U.js → logout-T53VKCPU.js} +4 -4
- package/dist/{logout-UKD5LA37.js → logout-W4KOOBIT.js} +2 -2
- package/dist/{logs-3CART7O7.js → logs-U35JR2KE.js} +5 -5
- package/dist/{merge-VK2HSKMA.js → merge-LNSMSAOF.js} +4 -4
- package/dist/message-delivery-LDXLGERA.js +25 -0
- package/dist/migrate-registry-to-db-XC7T5B7P.js +110 -0
- package/dist/{mind-HZ3QSDDJ.js → mind-DI33C74K.js} +25 -25
- package/dist/{mind-activity-tracker-4G6FURY2.js → mind-activity-tracker-EN6XNXPF.js} +3 -4
- package/dist/mind-manager-M6EMUW5I.js +18 -0
- package/dist/{mind-sleep-DTV7L44D.js → mind-sleep-BTSWQNAC.js} +4 -4
- package/dist/{mind-wake-PFN4FN3T.js → mind-wake-SBAKIDVP.js} +4 -4
- package/dist/{notes-37FW2UR2.js → notes-XCER3I7M.js} +11 -21
- package/dist/{package-VZWLXPHV.js → package-7WY6VKU3.js} +1 -1
- package/dist/{pages-DIIT5HMQ.js → pages-6EBS6CBR.js} +2 -2
- package/dist/{publish-HQV7YREB.js → publish-66UB2ZFY.js} +5 -5
- package/dist/{pull-2MB4SK3C.js → pull-XCHJTM5M.js} +4 -4
- package/dist/read-36UFXN3G.js +46 -0
- package/dist/{register-EFND67FQ.js → register-6B2CXTYM.js} +2 -2
- package/dist/{registry-D2BSQ2X5.js → registry-NDNOOYG4.js} +15 -9
- package/dist/{restart-CCK7D6TV.js → restart-6ESL3NBO.js} +5 -5
- package/dist/{sandbox-EHGFF52K.js → sandbox-TGBX22DS.js} +3 -3
- package/dist/{schedule-6F7ELB2M.js → schedule-QTJMFATP.js} +5 -5
- package/dist/{seed-E5OQGWX3.js → seed-SSUCYYDF.js} +2 -2
- package/dist/{send-IH6XZKPC.js → send-ZNCJDSRP.js} +25 -19
- package/dist/{service-LLBV3R7M.js → service-6LIN3F3K.js} +4 -4
- package/dist/{setup-F6TWFYGQ.js → setup-JG4QAEBV.js} +12 -12
- package/dist/{setup-YGAAIKKZ.js → setup-JHL5ZEST.js} +2 -2
- package/dist/{shared-UMO4S7CC.js → shared-ML5I4Q2A.js} +4 -4
- package/dist/{skill-42LGFBQC.js → skill-AUAQTSP5.js} +5 -5
- package/dist/skills/dreaming/references/INSTALL.md +2 -2
- package/dist/skills/orientation/SKILL.md +3 -3
- package/dist/skills/volute-mind/SKILL.md +32 -30
- package/dist/sleep-manager-MWYHM5HV.js +29 -0
- package/dist/split-TKJ5OT3P.js +63 -0
- package/dist/{sprout-QL74KR2X.js → sprout-IJVVKSJ2.js} +6 -7
- package/dist/{start-O5JQASRC.js → start-EUJSS5R4.js} +2 -2
- package/dist/{status-FZBEBM7Q.js → status-77YEPHMW.js} +5 -5
- package/dist/{status-WXD4HXRL.js → status-7GA4SM4Y.js} +4 -4
- package/dist/{status-LV34BG6G.js → status-THLOBLWG.js} +2 -2
- package/dist/{stop-2SOG5NYF.js → stop-3XAITBBF.js} +5 -5
- package/dist/{tailscale-AJ4VL5XK.js → tailscale-NY5MUMY3.js} +1 -1
- package/dist/up-NKSMXBWR.js +17 -0
- package/dist/{update-5VUDAI3D.js → update-PTSH22AZ.js} +9 -9
- package/dist/{update-check-F5Z3ALXX.js → update-check-64FWC4Y2.js} +2 -2
- package/dist/{upgrade-QCCO33BK.js → upgrade-HA47CS4C.js} +12 -5
- package/dist/variant-7TGZHOU3.js +41 -0
- package/dist/{version-notify-USFZBWMG.js → version-notify-5Z4MNR6M.js} +26 -30
- package/dist/web-assets/assets/index-CI5wgghI.css +1 -0
- package/dist/web-assets/assets/index-is5CvJWH.js +75 -0
- package/dist/web-assets/favicon.png +0 -0
- package/dist/web-assets/index.html +2 -2
- package/drizzle/0017_minds.sql +16 -0
- package/drizzle/meta/_journal.json +7 -0
- package/package.json +1 -1
- package/templates/_base/.init/.config/prompts.json +2 -2
- package/templates/_base/home/VOLUTE.md +5 -5
- package/templates/_base/src/lib/startup.ts +2 -2
- package/dist/channel-ZVZV42UD.js +0 -260
- package/dist/chunk-B2CPS4QU.js +0 -283
- package/dist/chunk-SIAG3QMM.js +0 -42
- package/dist/chunk-WSLPZF72.js +0 -173
- package/dist/connector-G722WXAU.js +0 -147
- package/dist/connectors/discord.js +0 -177
- package/dist/connectors/slack.js +0 -181
- package/dist/connectors/telegram.js +0 -187
- package/dist/down-7UKFMJJZ.js +0 -14
- package/dist/message-delivery-MS5JYPZX.js +0 -25
- package/dist/mind-manager-VVK67AY3.js +0 -19
- package/dist/sleep-manager-EE4NRN2Q.js +0 -29
- package/dist/up-SDMCSVI3.js +0 -17
- package/dist/variant-WWLDY6D5.js +0 -207
- package/dist/web-assets/assets/index-CUQ31ieL.js +0 -69
- package/dist/web-assets/assets/index-CW8NSl1o.css +0 -1
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
loadBridgeEnv,
|
|
4
|
+
onShutdown,
|
|
5
|
+
sendToBridge
|
|
6
|
+
} from "../chunk-KTLFDYPT.js";
|
|
7
|
+
import {
|
|
8
|
+
slugify
|
|
9
|
+
} from "../chunk-T6HKBWXZ.js";
|
|
10
|
+
import "../chunk-K3NQKI34.js";
|
|
11
|
+
|
|
12
|
+
// src/connectors/discord-bridge.ts
|
|
13
|
+
import { Client, Events, GatewayIntentBits, Partials } from "discord.js";
|
|
14
|
+
var env = loadBridgeEnv();
|
|
15
|
+
var token = process.env.DISCORD_TOKEN;
|
|
16
|
+
if (!token) {
|
|
17
|
+
console.error("Missing required env var: DISCORD_TOKEN");
|
|
18
|
+
process.exit(1);
|
|
19
|
+
}
|
|
20
|
+
var TYPING_INTERVAL_MS = 8e3;
|
|
21
|
+
var client = new Client({
|
|
22
|
+
intents: [
|
|
23
|
+
GatewayIntentBits.Guilds,
|
|
24
|
+
GatewayIntentBits.GuildMessages,
|
|
25
|
+
GatewayIntentBits.MessageContent,
|
|
26
|
+
GatewayIntentBits.DirectMessages,
|
|
27
|
+
GatewayIntentBits.GuildMessageTyping,
|
|
28
|
+
GatewayIntentBits.DirectMessageTyping
|
|
29
|
+
],
|
|
30
|
+
partials: [Partials.Channel]
|
|
31
|
+
});
|
|
32
|
+
onShutdown(() => {
|
|
33
|
+
client.destroy();
|
|
34
|
+
});
|
|
35
|
+
client.once(Events.ClientReady, (c) => {
|
|
36
|
+
console.log(`Discord bridge connected as ${c.user.tag}`);
|
|
37
|
+
});
|
|
38
|
+
client.on(Events.MessageCreate, async (message) => {
|
|
39
|
+
if (message.author.bot) return;
|
|
40
|
+
const isDM = !message.guild;
|
|
41
|
+
const content = [];
|
|
42
|
+
let text = message.content;
|
|
43
|
+
if (!isDM && message.mentions.has(client.user)) {
|
|
44
|
+
text = text.replace(new RegExp(`<@!?${client.user.id}>`, "g"), "").trim();
|
|
45
|
+
}
|
|
46
|
+
if (text) content.push({ type: "text", text });
|
|
47
|
+
for (const attachment of message.attachments.values()) {
|
|
48
|
+
if (!attachment.contentType?.startsWith("image/")) continue;
|
|
49
|
+
try {
|
|
50
|
+
const res = await fetch(attachment.url);
|
|
51
|
+
const buffer = Buffer.from(await res.arrayBuffer());
|
|
52
|
+
content.push({
|
|
53
|
+
type: "image",
|
|
54
|
+
media_type: attachment.contentType,
|
|
55
|
+
data: buffer.toString("base64")
|
|
56
|
+
});
|
|
57
|
+
} catch (err) {
|
|
58
|
+
console.error(`Failed to download attachment: ${err}`);
|
|
59
|
+
content.push({ type: "text", text: "[Image attachment could not be loaded]" });
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
if (content.length === 0) return;
|
|
63
|
+
const displayName = message.author.displayName || message.author.username;
|
|
64
|
+
const platformUserId = message.author.username;
|
|
65
|
+
const channelName = !isDM && "name" in message.channel ? message.channel.name : void 0;
|
|
66
|
+
const externalChannel = isDM ? `@${slugify(message.author.username)}` : channelName && message.guild ? `${slugify(message.guild.name)}/${slugify(channelName)}` : message.channelId;
|
|
67
|
+
if (isDM) {
|
|
68
|
+
const channel = message.channel;
|
|
69
|
+
if ("sendTyping" in channel) {
|
|
70
|
+
const typingInterval = setInterval(() => {
|
|
71
|
+
channel.sendTyping().catch(() => {
|
|
72
|
+
});
|
|
73
|
+
}, TYPING_INTERVAL_MS);
|
|
74
|
+
channel.sendTyping().catch(() => {
|
|
75
|
+
});
|
|
76
|
+
try {
|
|
77
|
+
const result = await sendToBridge(env, {
|
|
78
|
+
content,
|
|
79
|
+
platformUserId,
|
|
80
|
+
displayName,
|
|
81
|
+
externalChannel,
|
|
82
|
+
isDM: true
|
|
83
|
+
});
|
|
84
|
+
if (!result.ok) {
|
|
85
|
+
message.reply(result.error ?? "Failed to process message").catch((err) => {
|
|
86
|
+
console.error(`Failed to send error reply: ${err}`);
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
} finally {
|
|
90
|
+
clearInterval(typingInterval);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
} else {
|
|
94
|
+
const isMentioned = message.mentions.has(client.user);
|
|
95
|
+
if (isMentioned) {
|
|
96
|
+
const channel = message.channel;
|
|
97
|
+
if ("sendTyping" in channel) {
|
|
98
|
+
const typingInterval = setInterval(() => {
|
|
99
|
+
channel.sendTyping().catch(() => {
|
|
100
|
+
});
|
|
101
|
+
}, TYPING_INTERVAL_MS);
|
|
102
|
+
channel.sendTyping().catch(() => {
|
|
103
|
+
});
|
|
104
|
+
try {
|
|
105
|
+
const result = await sendToBridge(env, {
|
|
106
|
+
content,
|
|
107
|
+
platformUserId,
|
|
108
|
+
displayName,
|
|
109
|
+
externalChannel,
|
|
110
|
+
isDM: false
|
|
111
|
+
});
|
|
112
|
+
if (!result.ok) {
|
|
113
|
+
message.reply(result.error ?? "Failed to process message").catch((err) => {
|
|
114
|
+
console.error(`Failed to send error reply: ${err}`);
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
} finally {
|
|
118
|
+
clearInterval(typingInterval);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
} else {
|
|
122
|
+
const result = await sendToBridge(env, {
|
|
123
|
+
content,
|
|
124
|
+
platformUserId,
|
|
125
|
+
displayName,
|
|
126
|
+
externalChannel,
|
|
127
|
+
isDM: false
|
|
128
|
+
});
|
|
129
|
+
if (!result.ok) {
|
|
130
|
+
message.reply(result.error ?? "Failed to process message").catch((err) => {
|
|
131
|
+
console.error(`Failed to send error reply: ${err}`);
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
});
|
|
137
|
+
async function loginWithRetry() {
|
|
138
|
+
try {
|
|
139
|
+
await client.login(token);
|
|
140
|
+
} catch (err) {
|
|
141
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
142
|
+
const match = msg.match(/resets at (.+)/);
|
|
143
|
+
if (match) {
|
|
144
|
+
const resetAt = new Date(match[1]);
|
|
145
|
+
const waitMs = resetAt.getTime() - Date.now();
|
|
146
|
+
if (waitMs > 0) {
|
|
147
|
+
console.error(`Session limit hit, waiting until ${resetAt.toISOString()}...`);
|
|
148
|
+
await new Promise((r) => setTimeout(r, waitMs + 5e3));
|
|
149
|
+
return loginWithRetry();
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
throw err;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
loginWithRetry().catch((err) => {
|
|
156
|
+
console.error("Failed to connect to Discord:", err);
|
|
157
|
+
process.exit(1);
|
|
158
|
+
});
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
loadBridgeEnv,
|
|
4
|
+
onShutdown,
|
|
5
|
+
sendToBridge
|
|
6
|
+
} from "../chunk-KTLFDYPT.js";
|
|
7
|
+
import {
|
|
8
|
+
slugify
|
|
9
|
+
} from "../chunk-T6HKBWXZ.js";
|
|
10
|
+
import "../chunk-K3NQKI34.js";
|
|
11
|
+
|
|
12
|
+
// src/connectors/slack-bridge.ts
|
|
13
|
+
import { App } from "@slack/bolt";
|
|
14
|
+
var env = loadBridgeEnv();
|
|
15
|
+
var botToken = process.env.SLACK_BOT_TOKEN;
|
|
16
|
+
var appToken = process.env.SLACK_APP_TOKEN;
|
|
17
|
+
if (!botToken || !appToken) {
|
|
18
|
+
console.error("Missing required env vars: SLACK_BOT_TOKEN, SLACK_APP_TOKEN");
|
|
19
|
+
process.exit(1);
|
|
20
|
+
}
|
|
21
|
+
var app = new App({
|
|
22
|
+
token: botToken,
|
|
23
|
+
socketMode: true,
|
|
24
|
+
appToken
|
|
25
|
+
});
|
|
26
|
+
var botUserId;
|
|
27
|
+
var serverName;
|
|
28
|
+
app.message(async ({ message }) => {
|
|
29
|
+
if (message.subtype) return;
|
|
30
|
+
if (!("user" in message) || !("text" in message)) return;
|
|
31
|
+
if ("bot_id" in message && message.bot_id) return;
|
|
32
|
+
const isDM = message.channel_type === "im" || message.channel_type === "mpim";
|
|
33
|
+
let text = message.text ?? "";
|
|
34
|
+
if (!isDM && botUserId && text.includes(`<@${botUserId}>`)) {
|
|
35
|
+
text = text.replace(new RegExp(`<@${botUserId}>`, "g"), "").trim();
|
|
36
|
+
}
|
|
37
|
+
const content = [];
|
|
38
|
+
if (text) content.push({ type: "text", text });
|
|
39
|
+
if ("files" in message && message.files) {
|
|
40
|
+
for (const file of message.files) {
|
|
41
|
+
if (!file.mimetype?.startsWith("image/") || !file.url_private) continue;
|
|
42
|
+
try {
|
|
43
|
+
const res = await fetch(file.url_private, {
|
|
44
|
+
headers: { Authorization: `Bearer ${botToken}` }
|
|
45
|
+
});
|
|
46
|
+
if (!res.ok) {
|
|
47
|
+
console.warn(`Failed to download Slack file: HTTP ${res.status}`);
|
|
48
|
+
content.push({ type: "text", text: "[Image attachment could not be loaded]" });
|
|
49
|
+
continue;
|
|
50
|
+
}
|
|
51
|
+
const buffer = Buffer.from(await res.arrayBuffer());
|
|
52
|
+
content.push({
|
|
53
|
+
type: "image",
|
|
54
|
+
media_type: file.mimetype,
|
|
55
|
+
data: buffer.toString("base64")
|
|
56
|
+
});
|
|
57
|
+
} catch (err) {
|
|
58
|
+
console.error(`Failed to download attachment: ${err}`);
|
|
59
|
+
content.push({ type: "text", text: "[Image attachment could not be loaded]" });
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
if (content.length === 0) return;
|
|
64
|
+
let displayName = message.user;
|
|
65
|
+
let senderUsername = message.user;
|
|
66
|
+
try {
|
|
67
|
+
const userInfo = await app.client.users.info({
|
|
68
|
+
user: message.user
|
|
69
|
+
});
|
|
70
|
+
displayName = userInfo.user?.profile?.display_name || userInfo.user?.profile?.real_name || message.user;
|
|
71
|
+
senderUsername = userInfo.user?.name ?? message.user;
|
|
72
|
+
} catch (err) {
|
|
73
|
+
console.warn(`Failed to get user info: ${err}`);
|
|
74
|
+
}
|
|
75
|
+
let channelName;
|
|
76
|
+
if (!isDM) {
|
|
77
|
+
try {
|
|
78
|
+
const info = await app.client.conversations.info({
|
|
79
|
+
channel: message.channel
|
|
80
|
+
});
|
|
81
|
+
channelName = info.channel?.name;
|
|
82
|
+
} catch (err) {
|
|
83
|
+
console.warn(`Failed to get channel info: ${err}`);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
const externalChannel = isDM ? `@${slugify(senderUsername)}` : channelName && serverName ? `${slugify(serverName)}/${slugify(channelName)}` : message.channel;
|
|
87
|
+
const result = await sendToBridge(env, {
|
|
88
|
+
content,
|
|
89
|
+
platformUserId: senderUsername,
|
|
90
|
+
displayName,
|
|
91
|
+
externalChannel,
|
|
92
|
+
isDM
|
|
93
|
+
});
|
|
94
|
+
if (!result.ok) {
|
|
95
|
+
app.client.chat.postMessage({
|
|
96
|
+
channel: message.channel,
|
|
97
|
+
text: result.error ?? "Failed to process message"
|
|
98
|
+
}).catch((err) => {
|
|
99
|
+
console.warn(`[slack-bridge] failed to send error reply: ${err}`);
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
});
|
|
103
|
+
async function start() {
|
|
104
|
+
await app.start();
|
|
105
|
+
const auth = await app.client.auth.test();
|
|
106
|
+
if (!auth.user_id) {
|
|
107
|
+
throw new Error("auth.test succeeded but returned no user_id");
|
|
108
|
+
}
|
|
109
|
+
botUserId = auth.user_id;
|
|
110
|
+
serverName = auth.team;
|
|
111
|
+
console.log(`Slack bridge connected as ${botUserId}${serverName ? ` in ${serverName}` : ""}`);
|
|
112
|
+
}
|
|
113
|
+
onShutdown(async () => {
|
|
114
|
+
await app.stop();
|
|
115
|
+
});
|
|
116
|
+
start().catch((err) => {
|
|
117
|
+
console.error("Failed to start Slack bridge:", err);
|
|
118
|
+
process.exit(1);
|
|
119
|
+
});
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
loadBridgeEnv,
|
|
4
|
+
onShutdown,
|
|
5
|
+
sendToBridge
|
|
6
|
+
} from "../chunk-KTLFDYPT.js";
|
|
7
|
+
import {
|
|
8
|
+
slugify
|
|
9
|
+
} from "../chunk-T6HKBWXZ.js";
|
|
10
|
+
import "../chunk-K3NQKI34.js";
|
|
11
|
+
|
|
12
|
+
// src/connectors/telegram-bridge.ts
|
|
13
|
+
import { Telegraf } from "telegraf";
|
|
14
|
+
import { message } from "telegraf/filters";
|
|
15
|
+
var env = loadBridgeEnv();
|
|
16
|
+
var botToken = process.env.TELEGRAM_BOT_TOKEN;
|
|
17
|
+
if (!botToken) {
|
|
18
|
+
console.error("Missing required env var: TELEGRAM_BOT_TOKEN");
|
|
19
|
+
process.exit(1);
|
|
20
|
+
}
|
|
21
|
+
var TYPING_INTERVAL_MS = 5e3;
|
|
22
|
+
var bot = new Telegraf(botToken);
|
|
23
|
+
bot.on(message("text"), async (ctx) => {
|
|
24
|
+
if (ctx.message.from.is_bot) return;
|
|
25
|
+
const isDM = ctx.chat.type === "private";
|
|
26
|
+
const botUsername = ctx.botInfo.username;
|
|
27
|
+
let text = ctx.message.text;
|
|
28
|
+
if (!isDM && botUsername) {
|
|
29
|
+
const isMentioned = ctx.message.entities?.some(
|
|
30
|
+
(e) => e.type === "mention" && ctx.message.text.substring(e.offset, e.offset + e.length) === `@${botUsername}`
|
|
31
|
+
);
|
|
32
|
+
if (isMentioned) {
|
|
33
|
+
text = text.replace(new RegExp(`@${botUsername}`, "g"), "").trim();
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
const content = [];
|
|
37
|
+
if (text) content.push({ type: "text", text });
|
|
38
|
+
if (content.length === 0) return;
|
|
39
|
+
const displayName = ctx.message.from.first_name + (ctx.message.from.last_name ? ` ${ctx.message.from.last_name}` : "");
|
|
40
|
+
const platformUserId = ctx.message.from.username ?? String(ctx.message.from.id);
|
|
41
|
+
const chatTitle = "title" in ctx.chat ? ctx.chat.title : void 0;
|
|
42
|
+
const externalChannel = isDM ? `@${slugify(platformUserId)}` : chatTitle ? slugify(chatTitle) : String(ctx.chat.id);
|
|
43
|
+
if (isDM) {
|
|
44
|
+
const typingInterval = setInterval(() => {
|
|
45
|
+
bot.telegram.sendChatAction(ctx.chat.id, "typing").catch(() => {
|
|
46
|
+
});
|
|
47
|
+
}, TYPING_INTERVAL_MS);
|
|
48
|
+
bot.telegram.sendChatAction(ctx.chat.id, "typing").catch(() => {
|
|
49
|
+
});
|
|
50
|
+
try {
|
|
51
|
+
const result = await sendToBridge(env, {
|
|
52
|
+
content,
|
|
53
|
+
platformUserId,
|
|
54
|
+
displayName,
|
|
55
|
+
externalChannel,
|
|
56
|
+
isDM: true
|
|
57
|
+
});
|
|
58
|
+
if (!result.ok) {
|
|
59
|
+
ctx.reply(result.error ?? "Failed to process message").catch((err) => {
|
|
60
|
+
console.error(`Failed to send error reply: ${err}`);
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
} finally {
|
|
64
|
+
clearInterval(typingInterval);
|
|
65
|
+
}
|
|
66
|
+
} else {
|
|
67
|
+
const result = await sendToBridge(env, {
|
|
68
|
+
content,
|
|
69
|
+
platformUserId,
|
|
70
|
+
displayName,
|
|
71
|
+
externalChannel,
|
|
72
|
+
isDM: false
|
|
73
|
+
});
|
|
74
|
+
if (!result.ok) {
|
|
75
|
+
ctx.reply(result.error ?? "Failed to process message").catch((err) => {
|
|
76
|
+
console.error(`Failed to send error reply: ${err}`);
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
});
|
|
81
|
+
bot.on(message("photo"), async (ctx) => {
|
|
82
|
+
if (ctx.message.from.is_bot) return;
|
|
83
|
+
const isDM = ctx.chat.type === "private";
|
|
84
|
+
const content = [];
|
|
85
|
+
const caption = ctx.message.caption;
|
|
86
|
+
if (caption) content.push({ type: "text", text: caption });
|
|
87
|
+
const photos = ctx.message.photo;
|
|
88
|
+
const largest = photos[photos.length - 1];
|
|
89
|
+
try {
|
|
90
|
+
const fileUrl = await ctx.telegram.getFileLink(largest.file_id);
|
|
91
|
+
const res = await fetch(fileUrl.href);
|
|
92
|
+
if (res.ok) {
|
|
93
|
+
const buffer = Buffer.from(await res.arrayBuffer());
|
|
94
|
+
content.push({
|
|
95
|
+
type: "image",
|
|
96
|
+
media_type: "image/jpeg",
|
|
97
|
+
data: buffer.toString("base64")
|
|
98
|
+
});
|
|
99
|
+
} else {
|
|
100
|
+
console.warn(`Failed to download Telegram photo: HTTP ${res.status}`);
|
|
101
|
+
content.push({ type: "text", text: "[Image attachment could not be loaded]" });
|
|
102
|
+
}
|
|
103
|
+
} catch (err) {
|
|
104
|
+
console.error(`Failed to download photo: ${err}`);
|
|
105
|
+
content.push({ type: "text", text: "[Image attachment could not be loaded]" });
|
|
106
|
+
}
|
|
107
|
+
if (content.length === 0) return;
|
|
108
|
+
const displayName = ctx.message.from.first_name + (ctx.message.from.last_name ? ` ${ctx.message.from.last_name}` : "");
|
|
109
|
+
const platformUserId = ctx.message.from.username ?? String(ctx.message.from.id);
|
|
110
|
+
const chatTitle = "title" in ctx.chat ? ctx.chat.title : void 0;
|
|
111
|
+
const externalChannel = isDM ? `@${slugify(platformUserId)}` : chatTitle ? slugify(chatTitle) : String(ctx.chat.id);
|
|
112
|
+
const result = await sendToBridge(env, {
|
|
113
|
+
content,
|
|
114
|
+
platformUserId,
|
|
115
|
+
displayName,
|
|
116
|
+
externalChannel,
|
|
117
|
+
isDM
|
|
118
|
+
});
|
|
119
|
+
if (!result.ok) {
|
|
120
|
+
ctx.reply(result.error ?? "Failed to process message").catch((err) => {
|
|
121
|
+
console.error(`Failed to send error reply: ${err}`);
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
});
|
|
125
|
+
bot.launch().then(() => {
|
|
126
|
+
console.log(`Telegram bridge connected as @${bot.botInfo?.username}`);
|
|
127
|
+
}).catch((err) => {
|
|
128
|
+
console.error("Failed to start Telegram bridge:", err);
|
|
129
|
+
process.exit(1);
|
|
130
|
+
});
|
|
131
|
+
onShutdown(() => {
|
|
132
|
+
bot.stop("SIGTERM");
|
|
133
|
+
});
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
addMessage,
|
|
4
|
+
addParticipant,
|
|
5
|
+
createChannel,
|
|
6
|
+
createConversation,
|
|
7
|
+
deleteConversation,
|
|
8
|
+
deleteConversationForUser,
|
|
9
|
+
findDMConversation,
|
|
10
|
+
getChannelByName,
|
|
11
|
+
getConversation,
|
|
12
|
+
getMessages,
|
|
13
|
+
getMessagesPaginated,
|
|
14
|
+
getOrCreateConversation,
|
|
15
|
+
getParticipants,
|
|
16
|
+
getUnreadCounts,
|
|
17
|
+
isParticipant,
|
|
18
|
+
isParticipantOrOwner,
|
|
19
|
+
joinChannel,
|
|
20
|
+
leaveChannel,
|
|
21
|
+
listChannels,
|
|
22
|
+
listConversationsForUser,
|
|
23
|
+
listConversationsWithParticipants,
|
|
24
|
+
markConversationRead,
|
|
25
|
+
removeParticipant
|
|
26
|
+
} from "./chunk-IAYBDWVG.js";
|
|
27
|
+
import "./chunk-VIVMW2H2.js";
|
|
28
|
+
import "./chunk-YUIHSKR6.js";
|
|
29
|
+
import "./chunk-H7OZRFJB.js";
|
|
30
|
+
import "./chunk-K3NQKI34.js";
|
|
31
|
+
export {
|
|
32
|
+
addMessage,
|
|
33
|
+
addParticipant,
|
|
34
|
+
createChannel,
|
|
35
|
+
createConversation,
|
|
36
|
+
deleteConversation,
|
|
37
|
+
deleteConversationForUser,
|
|
38
|
+
findDMConversation,
|
|
39
|
+
getChannelByName,
|
|
40
|
+
getConversation,
|
|
41
|
+
getMessages,
|
|
42
|
+
getMessagesPaginated,
|
|
43
|
+
getOrCreateConversation,
|
|
44
|
+
getParticipants,
|
|
45
|
+
getUnreadCounts,
|
|
46
|
+
isParticipant,
|
|
47
|
+
isParticipantOrOwner,
|
|
48
|
+
joinChannel,
|
|
49
|
+
leaveChannel,
|
|
50
|
+
listChannels,
|
|
51
|
+
listConversationsForUser,
|
|
52
|
+
listConversationsWithParticipants,
|
|
53
|
+
markConversationRead,
|
|
54
|
+
removeParticipant
|
|
55
|
+
};
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
resolveMindName
|
|
4
|
+
} from "./chunk-NAOW2CLO.js";
|
|
5
|
+
import {
|
|
6
|
+
daemonFetch
|
|
7
|
+
} from "./chunk-JGFVMROS.js";
|
|
8
|
+
import {
|
|
9
|
+
parseArgs
|
|
10
|
+
} from "./chunk-D424ZQGI.js";
|
|
11
|
+
import "./chunk-H7OZRFJB.js";
|
|
12
|
+
import "./chunk-K3NQKI34.js";
|
|
13
|
+
|
|
14
|
+
// src/commands/chat/create.ts
|
|
15
|
+
async function run(args) {
|
|
16
|
+
const { flags } = parseArgs(args, {
|
|
17
|
+
mind: { type: "string" },
|
|
18
|
+
participants: { type: "string" },
|
|
19
|
+
name: { type: "string" }
|
|
20
|
+
});
|
|
21
|
+
if (!flags.participants) {
|
|
22
|
+
console.error('Usage: volute chat create --participants u1,u2 [--name "..."] [--mind <name>]');
|
|
23
|
+
process.exit(1);
|
|
24
|
+
}
|
|
25
|
+
const mindName = resolveMindName(flags);
|
|
26
|
+
const participants = flags.participants.split(",").map((p) => p.trim());
|
|
27
|
+
const res = await daemonFetch(`/api/minds/${encodeURIComponent(mindName)}/conversations`, {
|
|
28
|
+
method: "POST",
|
|
29
|
+
headers: { "Content-Type": "application/json" },
|
|
30
|
+
body: JSON.stringify({
|
|
31
|
+
participantNames: participants,
|
|
32
|
+
title: flags.name
|
|
33
|
+
})
|
|
34
|
+
});
|
|
35
|
+
if (!res.ok) {
|
|
36
|
+
const data = await res.json().catch(() => ({}));
|
|
37
|
+
console.error(data.error ?? `Failed to create conversation: ${res.status}`);
|
|
38
|
+
process.exit(1);
|
|
39
|
+
}
|
|
40
|
+
const conv = await res.json();
|
|
41
|
+
console.log(`Created conversation: ${conv.id}`);
|
|
42
|
+
}
|
|
43
|
+
export {
|
|
44
|
+
run
|
|
45
|
+
};
|
|
@@ -17,7 +17,7 @@ async function run(args) {
|
|
|
17
17
|
process.exit(1);
|
|
18
18
|
}
|
|
19
19
|
const skills = flags.skills === "none" ? [] : flags.skills ? flags.skills.split(",") : void 0;
|
|
20
|
-
const { daemonFetch } = await import("./daemon-client-
|
|
20
|
+
const { daemonFetch } = await import("./daemon-client-I42FK2BF.js");
|
|
21
21
|
const { getClient, urlOf } = await import("./api-client-YPKOZP2O.js");
|
|
22
22
|
const client = getClient();
|
|
23
23
|
const res = await daemonFetch(urlOf(client.api.minds.$url()), {
|
|
@@ -1,22 +1,22 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
run
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-GIE6CSN5.js";
|
|
5
5
|
import {
|
|
6
6
|
stopDaemon
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-EHYDTZTF.js";
|
|
8
8
|
import {
|
|
9
9
|
getServiceMode,
|
|
10
10
|
modeLabel,
|
|
11
11
|
pollHealth,
|
|
12
12
|
readDaemonConfig,
|
|
13
13
|
restartService
|
|
14
|
-
} from "./chunk-
|
|
15
|
-
import "./chunk-
|
|
16
|
-
import "./chunk-
|
|
14
|
+
} from "./chunk-LAC664WU.js";
|
|
15
|
+
import "./chunk-AW7PFDVN.js";
|
|
16
|
+
import "./chunk-RKQEHRBB.js";
|
|
17
|
+
import "./chunk-IKRVFPWU.js";
|
|
17
18
|
import "./chunk-D424ZQGI.js";
|
|
18
|
-
import "./chunk-
|
|
19
|
-
import "./chunk-B2CPS4QU.js";
|
|
19
|
+
import "./chunk-H7OZRFJB.js";
|
|
20
20
|
import "./chunk-K3NQKI34.js";
|
|
21
21
|
|
|
22
22
|
// src/commands/daemon-restart.ts
|