@openacp/cli 2026.330.3 → 2026.331.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.
- package/README.md +19 -1
- package/dist/cli.d.ts +11 -0
- package/dist/cli.js +25134 -278
- package/dist/cli.js.map +1 -1
- package/dist/data/registry-snapshot.json +1 -1
- package/dist/index.d.ts +259 -30
- package/dist/index.js +17632 -404
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/dist/adapter-AWSI4GML.js +0 -13
- package/dist/adapter-AWSI4GML.js.map +0 -1
- package/dist/agent-catalog-SZQQERV7.js +0 -10
- package/dist/agent-catalog-SZQQERV7.js.map +0 -1
- package/dist/agent-dependencies-ED2ZTUHG.js +0 -23
- package/dist/agent-dependencies-ED2ZTUHG.js.map +0 -1
- package/dist/agent-registry-YOGP656W.js +0 -8
- package/dist/agent-registry-YOGP656W.js.map +0 -1
- package/dist/agent-store-5UHZH2XI.js +0 -8
- package/dist/agent-store-5UHZH2XI.js.map +0 -1
- package/dist/api-client-XTLRRFPX.js +0 -13
- package/dist/api-client-XTLRRFPX.js.map +0 -1
- package/dist/api-server-5VNYFWJE.js +0 -7
- package/dist/api-server-5VNYFWJE.js.map +0 -1
- package/dist/api-server-JLBDKCU4.js +0 -10
- package/dist/api-server-JLBDKCU4.js.map +0 -1
- package/dist/autostart-CUPZMKKC.js +0 -22
- package/dist/autostart-CUPZMKKC.js.map +0 -1
- package/dist/chunk-237WYH6H.js +0 -235
- package/dist/chunk-237WYH6H.js.map +0 -1
- package/dist/chunk-2HEFALTZ.js +0 -44
- package/dist/chunk-2HEFALTZ.js.map +0 -1
- package/dist/chunk-2KT6TROD.js +0 -129
- package/dist/chunk-2KT6TROD.js.map +0 -1
- package/dist/chunk-2R5XM3ES.js +0 -154
- package/dist/chunk-2R5XM3ES.js.map +0 -1
- package/dist/chunk-3EWTPOF7.js +0 -51
- package/dist/chunk-3EWTPOF7.js.map +0 -1
- package/dist/chunk-3NAFXVQM.js +0 -67
- package/dist/chunk-3NAFXVQM.js.map +0 -1
- package/dist/chunk-4WXALZA3.js +0 -45
- package/dist/chunk-4WXALZA3.js.map +0 -1
- package/dist/chunk-566W6INH.js +0 -83
- package/dist/chunk-566W6INH.js.map +0 -1
- package/dist/chunk-5HKQCYOI.js +0 -145
- package/dist/chunk-5HKQCYOI.js.map +0 -1
- package/dist/chunk-5OCGO27U.js +0 -125
- package/dist/chunk-5OCGO27U.js.map +0 -1
- package/dist/chunk-5WGVYX3C.js +0 -55
- package/dist/chunk-5WGVYX3C.js.map +0 -1
- package/dist/chunk-7ZCQF6QM.js +0 -27
- package/dist/chunk-7ZCQF6QM.js.map +0 -1
- package/dist/chunk-AFKX424Q.js +0 -92
- package/dist/chunk-AFKX424Q.js.map +0 -1
- package/dist/chunk-APS6UEFU.js +0 -259
- package/dist/chunk-APS6UEFU.js.map +0 -1
- package/dist/chunk-BTJHGSLM.js +0 -1116
- package/dist/chunk-BTJHGSLM.js.map +0 -1
- package/dist/chunk-CDAUYTVP.js +0 -41
- package/dist/chunk-CDAUYTVP.js.map +0 -1
- package/dist/chunk-FCTC7KDT.js +0 -101
- package/dist/chunk-FCTC7KDT.js.map +0 -1
- package/dist/chunk-FNRSWA2K.js +0 -1
- package/dist/chunk-FNRSWA2K.js.map +0 -1
- package/dist/chunk-GEOXPGCO.js +0 -650
- package/dist/chunk-GEOXPGCO.js.map +0 -1
- package/dist/chunk-IZ5UEZF7.js +0 -138
- package/dist/chunk-IZ5UEZF7.js.map +0 -1
- package/dist/chunk-KDU3ZEWT.js +0 -97
- package/dist/chunk-KDU3ZEWT.js.map +0 -1
- package/dist/chunk-LGFWH3AE.js +0 -26
- package/dist/chunk-LGFWH3AE.js.map +0 -1
- package/dist/chunk-MITTQMGZ.js +0 -543
- package/dist/chunk-MITTQMGZ.js.map +0 -1
- package/dist/chunk-MLF4W5R6.js +0 -101
- package/dist/chunk-MLF4W5R6.js.map +0 -1
- package/dist/chunk-MPGEHTGE.js +0 -679
- package/dist/chunk-MPGEHTGE.js.map +0 -1
- package/dist/chunk-OYSAN7UX.js +0 -15
- package/dist/chunk-OYSAN7UX.js.map +0 -1
- package/dist/chunk-PA6MNBG4.js +0 -190
- package/dist/chunk-PA6MNBG4.js.map +0 -1
- package/dist/chunk-QWVHCTCA.js +0 -172
- package/dist/chunk-QWVHCTCA.js.map +0 -1
- package/dist/chunk-R6KZYF7D.js +0 -231
- package/dist/chunk-R6KZYF7D.js.map +0 -1
- package/dist/chunk-S64CB6J3.js +0 -98
- package/dist/chunk-S64CB6J3.js.map +0 -1
- package/dist/chunk-TMVTSWVH.js +0 -228
- package/dist/chunk-TMVTSWVH.js.map +0 -1
- package/dist/chunk-UCIZM5SW.js +0 -3917
- package/dist/chunk-UCIZM5SW.js.map +0 -1
- package/dist/chunk-UWH7KIAA.js +0 -701
- package/dist/chunk-UWH7KIAA.js.map +0 -1
- package/dist/chunk-V2YZWYXT.js +0 -484
- package/dist/chunk-V2YZWYXT.js.map +0 -1
- package/dist/chunk-W26AUH5B.js +0 -61
- package/dist/chunk-W26AUH5B.js.map +0 -1
- package/dist/chunk-W4LK6WJP.js +0 -446
- package/dist/chunk-W4LK6WJP.js.map +0 -1
- package/dist/chunk-WQCJTU2C.js +0 -84
- package/dist/chunk-WQCJTU2C.js.map +0 -1
- package/dist/chunk-XBZIHNKV.js +0 -6410
- package/dist/chunk-XBZIHNKV.js.map +0 -1
- package/dist/chunk-ZSLHHQPQ.js +0 -282
- package/dist/chunk-ZSLHHQPQ.js.map +0 -1
- package/dist/config-KN6NKKPF.js +0 -20
- package/dist/config-KN6NKKPF.js.map +0 -1
- package/dist/config-editor-76RVZS4B.js +0 -10
- package/dist/config-editor-76RVZS4B.js.map +0 -1
- package/dist/config-registry-ZXAIJNYB.js +0 -17
- package/dist/config-registry-ZXAIJNYB.js.map +0 -1
- package/dist/context-NXXW62NJ.js +0 -9
- package/dist/context-NXXW62NJ.js.map +0 -1
- package/dist/core-plugins-BPZY7SEB.js +0 -22
- package/dist/core-plugins-BPZY7SEB.js.map +0 -1
- package/dist/daemon-XFEMMJSZ.js +0 -29
- package/dist/daemon-XFEMMJSZ.js.map +0 -1
- package/dist/dev-loader-7P3HZCIA.js +0 -37
- package/dist/dev-loader-7P3HZCIA.js.map +0 -1
- package/dist/doctor-AV6AUO22.js +0 -9
- package/dist/doctor-AV6AUO22.js.map +0 -1
- package/dist/file-service-HHB3JQIO.js +0 -8
- package/dist/file-service-HHB3JQIO.js.map +0 -1
- package/dist/install-cloudflared-JRJ4BSOM.js +0 -32
- package/dist/install-cloudflared-JRJ4BSOM.js.map +0 -1
- package/dist/install-context-EHYV5WRY.js +0 -77
- package/dist/install-context-EHYV5WRY.js.map +0 -1
- package/dist/install-jq-ISTGT263.js +0 -31
- package/dist/install-jq-ISTGT263.js.map +0 -1
- package/dist/integrate-JIEZYDOR.js +0 -371
- package/dist/integrate-JIEZYDOR.js.map +0 -1
- package/dist/log-YZ243M5G.js +0 -25
- package/dist/log-YZ243M5G.js.map +0 -1
- package/dist/main-VEJCG5PY.js +0 -654
- package/dist/main-VEJCG5PY.js.map +0 -1
- package/dist/menu-ALFN37IR.js +0 -15
- package/dist/menu-ALFN37IR.js.map +0 -1
- package/dist/notifications-MO23S7S3.js +0 -8
- package/dist/notifications-MO23S7S3.js.map +0 -1
- package/dist/plugin-create-EHL76ZZG.js +0 -966
- package/dist/plugin-create-EHL76ZZG.js.map +0 -1
- package/dist/plugin-installer-VSTYZSXC.js +0 -9
- package/dist/plugin-installer-VSTYZSXC.js.map +0 -1
- package/dist/plugin-registry-6J3YSFHF.js +0 -7
- package/dist/plugin-registry-6J3YSFHF.js.map +0 -1
- package/dist/plugin-search-MGKAL5JM.js +0 -39
- package/dist/plugin-search-MGKAL5JM.js.map +0 -1
- package/dist/post-upgrade-Y26S2ZQ7.js +0 -79
- package/dist/post-upgrade-Y26S2ZQ7.js.map +0 -1
- package/dist/read-text-file-DJBTITIB.js +0 -7
- package/dist/read-text-file-DJBTITIB.js.map +0 -1
- package/dist/registry-client-GTBWLXYU.js +0 -7
- package/dist/registry-client-GTBWLXYU.js.map +0 -1
- package/dist/security-2BA265LN.js +0 -8
- package/dist/security-2BA265LN.js.map +0 -1
- package/dist/settings-manager-B4UN2LAC.js +0 -7
- package/dist/settings-manager-B4UN2LAC.js.map +0 -1
- package/dist/setup-DISPNDEK.js +0 -802
- package/dist/setup-DISPNDEK.js.map +0 -1
- package/dist/speech-SG62JYIF.js +0 -9
- package/dist/speech-SG62JYIF.js.map +0 -1
- package/dist/suggest-RST5VOHB.js +0 -36
- package/dist/suggest-RST5VOHB.js.map +0 -1
- package/dist/telegram-L3YM6SQJ.js +0 -7
- package/dist/telegram-L3YM6SQJ.js.map +0 -1
- package/dist/tunnel-HWJ27WDH.js +0 -7
- package/dist/tunnel-HWJ27WDH.js.map +0 -1
- package/dist/tunnel-service-ZMO4THKE.js +0 -1261
- package/dist/tunnel-service-ZMO4THKE.js.map +0 -1
- package/dist/validators-GITLOFXC.js +0 -11
- package/dist/validators-GITLOFXC.js.map +0 -1
- package/dist/version-AXXV6IV2.js +0 -15
- package/dist/version-AXXV6IV2.js.map +0 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openacp/cli",
|
|
3
|
-
"version": "2026.
|
|
3
|
+
"version": "2026.331.2",
|
|
4
4
|
"description": "Self-hosted bridge for AI coding agents via ACP protocol",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
"@clack/prompts": "^1.1.0",
|
|
27
27
|
"@hono/node-server": "^1.19.11",
|
|
28
28
|
"@inquirer/prompts": "^8.3.2",
|
|
29
|
-
"@
|
|
29
|
+
"@agentclientprotocol/claude-agent-acp": "^0.24.2",
|
|
30
30
|
"diff": "^8.0.3",
|
|
31
31
|
"fastest-levenshtein": "^1.0.16",
|
|
32
32
|
"grammy": "^1.41.1",
|
package/dist/adapter-AWSI4GML.js
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
TelegramAdapter
|
|
3
|
-
} from "./chunk-XBZIHNKV.js";
|
|
4
|
-
import "./chunk-AFKX424Q.js";
|
|
5
|
-
import "./chunk-GEOXPGCO.js";
|
|
6
|
-
import "./chunk-APS6UEFU.js";
|
|
7
|
-
import "./chunk-5HKQCYOI.js";
|
|
8
|
-
import "./chunk-W4LK6WJP.js";
|
|
9
|
-
import "./chunk-R6KZYF7D.js";
|
|
10
|
-
export {
|
|
11
|
-
TelegramAdapter
|
|
12
|
-
};
|
|
13
|
-
//# sourceMappingURL=adapter-AWSI4GML.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
REGISTRY_AGENT_ALIASES,
|
|
3
|
-
checkDependencies,
|
|
4
|
-
checkRuntimeAvailable,
|
|
5
|
-
commandExists,
|
|
6
|
-
getAgentAlias,
|
|
7
|
-
getAgentCapabilities,
|
|
8
|
-
getAgentDependencies,
|
|
9
|
-
getAgentSetup,
|
|
10
|
-
listAgentsWithIntegration
|
|
11
|
-
} from "./chunk-ZSLHHQPQ.js";
|
|
12
|
-
export {
|
|
13
|
-
REGISTRY_AGENT_ALIASES,
|
|
14
|
-
checkDependencies,
|
|
15
|
-
checkRuntimeAvailable,
|
|
16
|
-
commandExists,
|
|
17
|
-
getAgentAlias,
|
|
18
|
-
getAgentCapabilities,
|
|
19
|
-
getAgentDependencies,
|
|
20
|
-
getAgentSetup,
|
|
21
|
-
listAgentsWithIntegration
|
|
22
|
-
};
|
|
23
|
-
//# sourceMappingURL=agent-dependencies-ED2ZTUHG.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
escapeSystemdValue,
|
|
3
|
-
escapeXml,
|
|
4
|
-
generateLaunchdPlist,
|
|
5
|
-
generateSystemdUnit,
|
|
6
|
-
installAutoStart,
|
|
7
|
-
isAutoStartInstalled,
|
|
8
|
-
isAutoStartSupported,
|
|
9
|
-
uninstallAutoStart
|
|
10
|
-
} from "./chunk-2R5XM3ES.js";
|
|
11
|
-
import "./chunk-R6KZYF7D.js";
|
|
12
|
-
export {
|
|
13
|
-
escapeSystemdValue,
|
|
14
|
-
escapeXml,
|
|
15
|
-
generateLaunchdPlist,
|
|
16
|
-
generateSystemdUnit,
|
|
17
|
-
installAutoStart,
|
|
18
|
-
isAutoStartInstalled,
|
|
19
|
-
isAutoStartSupported,
|
|
20
|
-
uninstallAutoStart
|
|
21
|
-
};
|
|
22
|
-
//# sourceMappingURL=autostart-CUPZMKKC.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
package/dist/chunk-237WYH6H.js
DELETED
|
@@ -1,235 +0,0 @@
|
|
|
1
|
-
// src/plugins/telegram/index.ts
|
|
2
|
-
function createTelegramPlugin() {
|
|
3
|
-
let adapter = null;
|
|
4
|
-
return {
|
|
5
|
-
name: "@openacp/telegram",
|
|
6
|
-
version: "1.0.0",
|
|
7
|
-
description: "Telegram adapter with forum topics",
|
|
8
|
-
essential: true,
|
|
9
|
-
pluginDependencies: {
|
|
10
|
-
"@openacp/security": "^1.0.0",
|
|
11
|
-
"@openacp/notifications": "^1.0.0"
|
|
12
|
-
},
|
|
13
|
-
optionalPluginDependencies: {
|
|
14
|
-
"@openacp/speech": "^1.0.0"
|
|
15
|
-
},
|
|
16
|
-
permissions: ["services:register", "kernel:access", "events:read"],
|
|
17
|
-
async install(ctx) {
|
|
18
|
-
const { terminal, settings, legacyConfig } = ctx;
|
|
19
|
-
if (legacyConfig) {
|
|
20
|
-
const tg = legacyConfig.channels;
|
|
21
|
-
const telegramCfg = tg?.telegram;
|
|
22
|
-
if (telegramCfg?.botToken) {
|
|
23
|
-
await settings.setAll({
|
|
24
|
-
botToken: telegramCfg.botToken,
|
|
25
|
-
chatId: telegramCfg.chatId,
|
|
26
|
-
notificationTopicId: telegramCfg.notificationTopicId ?? null,
|
|
27
|
-
assistantTopicId: telegramCfg.assistantTopicId ?? null
|
|
28
|
-
});
|
|
29
|
-
terminal.log.success("Telegram settings migrated from legacy config");
|
|
30
|
-
return;
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
const { validateBotToken, validateChatId, validateBotAdmin } = await import("./validators-GITLOFXC.js");
|
|
34
|
-
let botToken = "";
|
|
35
|
-
while (true) {
|
|
36
|
-
botToken = await terminal.text({
|
|
37
|
-
message: "Telegram bot token (from @BotFather):",
|
|
38
|
-
validate: (val) => {
|
|
39
|
-
if (!val.trim()) return "Token cannot be empty";
|
|
40
|
-
return void 0;
|
|
41
|
-
}
|
|
42
|
-
});
|
|
43
|
-
botToken = botToken.trim();
|
|
44
|
-
const spin = terminal.spinner();
|
|
45
|
-
spin.start("Validating token...");
|
|
46
|
-
const result = await validateBotToken(botToken);
|
|
47
|
-
if (result.ok) {
|
|
48
|
-
spin.stop(`Connected to @${result.botUsername}`);
|
|
49
|
-
break;
|
|
50
|
-
}
|
|
51
|
-
spin.fail(result.error);
|
|
52
|
-
const action = await terminal.select({
|
|
53
|
-
message: "What to do?",
|
|
54
|
-
options: [
|
|
55
|
-
{ label: "Re-enter token", value: "retry" },
|
|
56
|
-
{ label: "Use as-is (skip validation)", value: "skip" }
|
|
57
|
-
]
|
|
58
|
-
});
|
|
59
|
-
if (action === "skip") break;
|
|
60
|
-
}
|
|
61
|
-
terminal.log.info("Send a message in your Telegram supergroup to detect the chat ID,");
|
|
62
|
-
terminal.log.info("or enter the chat ID manually.");
|
|
63
|
-
const chatIdMethod = await terminal.select({
|
|
64
|
-
message: "How to get the chat ID?",
|
|
65
|
-
options: [
|
|
66
|
-
{ value: "manual", label: "Enter chat ID manually" },
|
|
67
|
-
{ value: "detect", label: "Auto-detect from group message" }
|
|
68
|
-
]
|
|
69
|
-
});
|
|
70
|
-
let chatId;
|
|
71
|
-
if (chatIdMethod === "manual") {
|
|
72
|
-
const val = await terminal.text({
|
|
73
|
-
message: "Supergroup chat ID (e.g. -1001234567890):",
|
|
74
|
-
validate: (v) => {
|
|
75
|
-
const n = Number(v.trim());
|
|
76
|
-
if (isNaN(n) || !Number.isInteger(n)) return "Chat ID must be an integer";
|
|
77
|
-
return void 0;
|
|
78
|
-
}
|
|
79
|
-
});
|
|
80
|
-
chatId = Number(val.trim());
|
|
81
|
-
} else {
|
|
82
|
-
terminal.log.step('Listening for messages... Send "hi" in the group.');
|
|
83
|
-
chatId = await detectChatIdViaPolling(botToken, terminal);
|
|
84
|
-
}
|
|
85
|
-
const chatResult = await validateChatId(botToken, chatId);
|
|
86
|
-
if (chatResult.ok) {
|
|
87
|
-
terminal.log.success(`Group: ${chatResult.title}${chatResult.isForum ? " (Topics enabled)" : ""}`);
|
|
88
|
-
} else {
|
|
89
|
-
terminal.log.warning(chatResult.error);
|
|
90
|
-
}
|
|
91
|
-
const adminResult = await validateBotAdmin(botToken, chatId);
|
|
92
|
-
if (adminResult.ok) {
|
|
93
|
-
terminal.log.success("Bot has admin privileges");
|
|
94
|
-
} else {
|
|
95
|
-
terminal.log.warning(adminResult.error);
|
|
96
|
-
}
|
|
97
|
-
await settings.setAll({
|
|
98
|
-
botToken,
|
|
99
|
-
chatId,
|
|
100
|
-
notificationTopicId: null,
|
|
101
|
-
assistantTopicId: null
|
|
102
|
-
});
|
|
103
|
-
terminal.log.success("Telegram settings saved");
|
|
104
|
-
},
|
|
105
|
-
async configure(ctx) {
|
|
106
|
-
const { terminal, settings } = ctx;
|
|
107
|
-
const current = await settings.getAll();
|
|
108
|
-
const choice = await terminal.select({
|
|
109
|
-
message: "What to configure?",
|
|
110
|
-
options: [
|
|
111
|
-
{ value: "token", label: "Change bot token" },
|
|
112
|
-
{ value: "chatId", label: "Change chat ID" },
|
|
113
|
-
{ value: "done", label: "Done" }
|
|
114
|
-
]
|
|
115
|
-
});
|
|
116
|
-
if (choice === "token") {
|
|
117
|
-
const token = await terminal.text({
|
|
118
|
-
message: "New bot token:",
|
|
119
|
-
validate: (v) => !v.trim() ? "Token cannot be empty" : void 0
|
|
120
|
-
});
|
|
121
|
-
await settings.set("botToken", token.trim());
|
|
122
|
-
terminal.log.success("Bot token updated");
|
|
123
|
-
} else if (choice === "chatId") {
|
|
124
|
-
const val = await terminal.text({
|
|
125
|
-
message: "New chat ID:",
|
|
126
|
-
defaultValue: String(current.chatId ?? ""),
|
|
127
|
-
validate: (v) => {
|
|
128
|
-
const n = Number(v.trim());
|
|
129
|
-
if (isNaN(n) || !Number.isInteger(n)) return "Chat ID must be an integer";
|
|
130
|
-
return void 0;
|
|
131
|
-
}
|
|
132
|
-
});
|
|
133
|
-
await settings.set("chatId", Number(val.trim()));
|
|
134
|
-
terminal.log.success("Chat ID updated");
|
|
135
|
-
}
|
|
136
|
-
},
|
|
137
|
-
async uninstall(ctx, opts) {
|
|
138
|
-
if (opts.purge) {
|
|
139
|
-
await ctx.settings.clear();
|
|
140
|
-
ctx.terminal.log.success("Telegram settings cleared");
|
|
141
|
-
}
|
|
142
|
-
},
|
|
143
|
-
async setup(ctx) {
|
|
144
|
-
const config = ctx.pluginConfig;
|
|
145
|
-
if (!config.botToken || !config.chatId) {
|
|
146
|
-
ctx.log.info("Telegram disabled (missing botToken or chatId)");
|
|
147
|
-
return;
|
|
148
|
-
}
|
|
149
|
-
const core = ctx.core;
|
|
150
|
-
const settingsManager = core.lifecycleManager?.settingsManager;
|
|
151
|
-
if ((config.notificationTopicId == null || config.assistantTopicId == null) && settingsManager) {
|
|
152
|
-
const mainCfg = core.configManager.get();
|
|
153
|
-
const legacy = mainCfg?.channels?.telegram;
|
|
154
|
-
const migrated = {};
|
|
155
|
-
if (legacy?.notificationTopicId != null && config.notificationTopicId == null) {
|
|
156
|
-
config.notificationTopicId = legacy.notificationTopicId;
|
|
157
|
-
migrated.notificationTopicId = legacy.notificationTopicId;
|
|
158
|
-
}
|
|
159
|
-
if (legacy?.assistantTopicId != null && config.assistantTopicId == null) {
|
|
160
|
-
config.assistantTopicId = legacy.assistantTopicId;
|
|
161
|
-
migrated.assistantTopicId = legacy.assistantTopicId;
|
|
162
|
-
}
|
|
163
|
-
if (Object.keys(migrated).length > 0) {
|
|
164
|
-
await settingsManager.updatePluginSettings(ctx.pluginName, migrated);
|
|
165
|
-
ctx.log.info("Migrated topic IDs from main config to plugin settings");
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
const { TelegramAdapter } = await import("./adapter-AWSI4GML.js");
|
|
169
|
-
adapter = new TelegramAdapter(core, {
|
|
170
|
-
...config,
|
|
171
|
-
enabled: true,
|
|
172
|
-
maxMessageLength: 4096
|
|
173
|
-
}, async (updates) => {
|
|
174
|
-
if (settingsManager) {
|
|
175
|
-
await settingsManager.updatePluginSettings(ctx.pluginName, updates);
|
|
176
|
-
}
|
|
177
|
-
});
|
|
178
|
-
ctx.registerService("adapter:telegram", adapter);
|
|
179
|
-
ctx.log.info("Telegram adapter registered");
|
|
180
|
-
},
|
|
181
|
-
async teardown() {
|
|
182
|
-
if (adapter) {
|
|
183
|
-
await adapter.stop();
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
};
|
|
187
|
-
}
|
|
188
|
-
async function detectChatIdViaPolling(token, terminal) {
|
|
189
|
-
let lastUpdateId = 0;
|
|
190
|
-
try {
|
|
191
|
-
const clearRes = await fetch(`https://api.telegram.org/bot${token}/getUpdates?offset=-1`);
|
|
192
|
-
const clearData = await clearRes.json();
|
|
193
|
-
if (clearData.ok && clearData.result?.length) {
|
|
194
|
-
lastUpdateId = clearData.result[clearData.result.length - 1].update_id;
|
|
195
|
-
}
|
|
196
|
-
} catch {
|
|
197
|
-
}
|
|
198
|
-
const MAX_ATTEMPTS = 120;
|
|
199
|
-
const POLL_INTERVAL = 2e3;
|
|
200
|
-
for (let i = 0; i < MAX_ATTEMPTS; i++) {
|
|
201
|
-
try {
|
|
202
|
-
const offset = lastUpdateId ? lastUpdateId + 1 : 0;
|
|
203
|
-
const res = await fetch(`https://api.telegram.org/bot${token}/getUpdates?offset=${offset}&timeout=2`);
|
|
204
|
-
const data = await res.json();
|
|
205
|
-
if (data.ok && data.result?.length) {
|
|
206
|
-
for (const update of data.result) {
|
|
207
|
-
lastUpdateId = update.update_id;
|
|
208
|
-
const chat = update.message?.chat ?? update.my_chat_member?.chat;
|
|
209
|
-
if (chat && (chat.type === "supergroup" || chat.type === "group")) {
|
|
210
|
-
terminal.log.success(`Group detected: ${chat.title ?? chat.id} (${chat.id})`);
|
|
211
|
-
return chat.id;
|
|
212
|
-
}
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
} catch {
|
|
216
|
-
}
|
|
217
|
-
await new Promise((r) => setTimeout(r, POLL_INTERVAL));
|
|
218
|
-
}
|
|
219
|
-
terminal.log.warning("Timed out waiting for messages. Enter chat ID manually.");
|
|
220
|
-
const val = await terminal.text({
|
|
221
|
-
message: "Supergroup chat ID (e.g. -1001234567890):",
|
|
222
|
-
validate: (v) => {
|
|
223
|
-
const n = Number(v.trim());
|
|
224
|
-
if (isNaN(n) || !Number.isInteger(n)) return "Chat ID must be an integer";
|
|
225
|
-
return void 0;
|
|
226
|
-
}
|
|
227
|
-
});
|
|
228
|
-
return Number(val.trim());
|
|
229
|
-
}
|
|
230
|
-
var telegram_default = createTelegramPlugin();
|
|
231
|
-
|
|
232
|
-
export {
|
|
233
|
-
telegram_default
|
|
234
|
-
};
|
|
235
|
-
//# sourceMappingURL=chunk-237WYH6H.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/plugins/telegram/index.ts"],"sourcesContent":["import type { OpenACPPlugin, InstallContext } from '../../core/plugin/types.js'\nimport type { OpenACPCore } from '../../core/core.js'\nimport type { TelegramChannelConfig } from './types.js'\n\nfunction createTelegramPlugin(): OpenACPPlugin {\n let adapter: { stop(): Promise<void> } | null = null\n\n return {\n name: '@openacp/telegram',\n version: '1.0.0',\n description: 'Telegram adapter with forum topics',\n essential: true,\n pluginDependencies: {\n '@openacp/security': '^1.0.0',\n '@openacp/notifications': '^1.0.0',\n },\n optionalPluginDependencies: {\n '@openacp/speech': '^1.0.0',\n },\n permissions: ['services:register', 'kernel:access', 'events:read'],\n\n async install(ctx: InstallContext) {\n const { terminal, settings, legacyConfig } = ctx\n\n // Migrate from legacy config if present\n if (legacyConfig) {\n const tg = legacyConfig.channels as Record<string, unknown> | undefined\n const telegramCfg = tg?.telegram as Record<string, unknown> | undefined\n if (telegramCfg?.botToken) {\n await settings.setAll({\n botToken: telegramCfg.botToken,\n chatId: telegramCfg.chatId,\n notificationTopicId: telegramCfg.notificationTopicId ?? null,\n assistantTopicId: telegramCfg.assistantTopicId ?? null,\n })\n terminal.log.success('Telegram settings migrated from legacy config')\n return\n }\n }\n\n // Interactive setup via terminal\n const { validateBotToken, validateChatId, validateBotAdmin } = await import('./validators.js')\n\n let botToken = ''\n while (true) {\n botToken = await terminal.text({\n message: 'Telegram bot token (from @BotFather):',\n validate: (val) => {\n if (!val.trim()) return 'Token cannot be empty'\n return undefined\n },\n })\n botToken = botToken.trim()\n\n const spin = terminal.spinner()\n spin.start('Validating token...')\n const result = await validateBotToken(botToken)\n if (result.ok) {\n spin.stop(`Connected to @${result.botUsername}`)\n break\n }\n spin.fail(result.error)\n const action = await terminal.select({\n message: 'What to do?',\n options: [\n { label: 'Re-enter token', value: 'retry' },\n { label: 'Use as-is (skip validation)', value: 'skip' },\n ],\n })\n if (action === 'skip') break\n }\n\n // Chat ID detection\n terminal.log.info('Send a message in your Telegram supergroup to detect the chat ID,')\n terminal.log.info('or enter the chat ID manually.')\n\n const chatIdMethod = await terminal.select({\n message: 'How to get the chat ID?',\n options: [\n { value: 'manual', label: 'Enter chat ID manually' },\n { value: 'detect', label: 'Auto-detect from group message' },\n ],\n })\n\n let chatId: number\n if (chatIdMethod === 'manual') {\n const val = await terminal.text({\n message: 'Supergroup chat ID (e.g. -1001234567890):',\n validate: (v) => {\n const n = Number(v.trim())\n if (isNaN(n) || !Number.isInteger(n)) return 'Chat ID must be an integer'\n return undefined\n },\n })\n chatId = Number(val.trim())\n } else {\n // Simple polling-based detection\n terminal.log.step('Listening for messages... Send \"hi\" in the group.')\n chatId = await detectChatIdViaPolling(botToken, terminal)\n }\n\n // Validate chat ID\n const chatResult = await validateChatId(botToken, chatId)\n if (chatResult.ok) {\n terminal.log.success(`Group: ${chatResult.title}${chatResult.isForum ? ' (Topics enabled)' : ''}`)\n } else {\n terminal.log.warning(chatResult.error)\n }\n\n // Validate admin\n const adminResult = await validateBotAdmin(botToken, chatId)\n if (adminResult.ok) {\n terminal.log.success('Bot has admin privileges')\n } else {\n terminal.log.warning(adminResult.error)\n }\n\n await settings.setAll({\n botToken,\n chatId,\n notificationTopicId: null,\n assistantTopicId: null,\n })\n terminal.log.success('Telegram settings saved')\n },\n\n async configure(ctx: InstallContext) {\n const { terminal, settings } = ctx\n const current = await settings.getAll()\n\n const choice = await terminal.select({\n message: 'What to configure?',\n options: [\n { value: 'token', label: 'Change bot token' },\n { value: 'chatId', label: 'Change chat ID' },\n { value: 'done', label: 'Done' },\n ],\n })\n\n if (choice === 'token') {\n const token = await terminal.text({\n message: 'New bot token:',\n validate: (v) => (!v.trim() ? 'Token cannot be empty' : undefined),\n })\n await settings.set('botToken', token.trim())\n terminal.log.success('Bot token updated')\n } else if (choice === 'chatId') {\n const val = await terminal.text({\n message: 'New chat ID:',\n defaultValue: String(current.chatId ?? ''),\n validate: (v) => {\n const n = Number(v.trim())\n if (isNaN(n) || !Number.isInteger(n)) return 'Chat ID must be an integer'\n return undefined\n },\n })\n await settings.set('chatId', Number(val.trim()))\n terminal.log.success('Chat ID updated')\n }\n },\n\n async uninstall(ctx: InstallContext, opts: { purge: boolean }) {\n if (opts.purge) {\n await ctx.settings.clear()\n ctx.terminal.log.success('Telegram settings cleared')\n }\n },\n\n async setup(ctx) {\n const config = ctx.pluginConfig as Record<string, unknown>\n if (!config.botToken || !config.chatId) {\n ctx.log.info('Telegram disabled (missing botToken or chatId)')\n return\n }\n\n const core = ctx.core as OpenACPCore\n const settingsManager = core.lifecycleManager?.settingsManager\n\n // If topic IDs are null in plugin settings but present in main config, migrate them.\n // This handles users who ran a version where ensureTopics saved to main config instead of plugin settings.\n if ((config.notificationTopicId == null || config.assistantTopicId == null) && settingsManager) {\n const mainCfg = core.configManager.get()\n const legacy = (mainCfg as any)?.channels?.telegram as Record<string, unknown> | undefined\n const migrated: Record<string, unknown> = {}\n if (legacy?.notificationTopicId != null && config.notificationTopicId == null) {\n config.notificationTopicId = legacy.notificationTopicId\n migrated.notificationTopicId = legacy.notificationTopicId\n }\n if (legacy?.assistantTopicId != null && config.assistantTopicId == null) {\n config.assistantTopicId = legacy.assistantTopicId\n migrated.assistantTopicId = legacy.assistantTopicId\n }\n if (Object.keys(migrated).length > 0) {\n await settingsManager.updatePluginSettings(ctx.pluginName, migrated)\n ctx.log.info('Migrated topic IDs from main config to plugin settings')\n }\n }\n\n const { TelegramAdapter } = await import('./adapter.js')\n // config is a Record<string, unknown> from pluginConfig; at runtime it\n // contains all TelegramChannelConfig fields populated from the migrated config.\n adapter = new TelegramAdapter(core, {\n ...config,\n enabled: true,\n maxMessageLength: 4096,\n } as unknown as TelegramChannelConfig, async (updates) => {\n // Save topic IDs to plugin settings so they persist across restarts\n if (settingsManager) {\n await settingsManager.updatePluginSettings(ctx.pluginName, updates)\n }\n })\n\n ctx.registerService('adapter:telegram', adapter)\n ctx.log.info('Telegram adapter registered')\n },\n\n async teardown() {\n if (adapter) {\n await adapter.stop()\n }\n },\n }\n}\n\nasync function detectChatIdViaPolling(\n token: string,\n terminal: InstallContext['terminal'],\n): Promise<number> {\n let lastUpdateId = 0\n try {\n const clearRes = await fetch(`https://api.telegram.org/bot${token}/getUpdates?offset=-1`)\n const clearData = (await clearRes.json()) as { ok: boolean; result?: Array<{ update_id: number }> }\n if (clearData.ok && clearData.result?.length) {\n lastUpdateId = clearData.result[clearData.result.length - 1].update_id\n }\n } catch {\n // ignore\n }\n\n const MAX_ATTEMPTS = 120\n const POLL_INTERVAL = 2000\n\n for (let i = 0; i < MAX_ATTEMPTS; i++) {\n try {\n const offset = lastUpdateId ? lastUpdateId + 1 : 0\n const res = await fetch(`https://api.telegram.org/bot${token}/getUpdates?offset=${offset}&timeout=2`)\n const data = (await res.json()) as {\n ok: boolean\n result?: Array<{\n update_id: number\n message?: { chat: { id: number; title?: string; type: string } }\n my_chat_member?: { chat: { id: number; title?: string; type: string } }\n }>\n }\n\n if (data.ok && data.result?.length) {\n for (const update of data.result) {\n lastUpdateId = update.update_id\n const chat = update.message?.chat ?? update.my_chat_member?.chat\n if (chat && (chat.type === 'supergroup' || chat.type === 'group')) {\n terminal.log.success(`Group detected: ${chat.title ?? chat.id} (${chat.id})`)\n return chat.id\n }\n }\n }\n } catch {\n // Network error, retry\n }\n await new Promise((r) => setTimeout(r, POLL_INTERVAL))\n }\n\n // Fallback to manual\n terminal.log.warning('Timed out waiting for messages. Enter chat ID manually.')\n const val = await terminal.text({\n message: 'Supergroup chat ID (e.g. -1001234567890):',\n validate: (v) => {\n const n = Number(v.trim())\n if (isNaN(n) || !Number.isInteger(n)) return 'Chat ID must be an integer'\n return undefined\n },\n })\n return Number(val.trim())\n}\n\nexport default createTelegramPlugin()\n"],"mappings":"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","names":[]}
|
package/dist/chunk-2HEFALTZ.js
DELETED
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
telegram_default
|
|
3
|
-
} from "./chunk-237WYH6H.js";
|
|
4
|
-
import {
|
|
5
|
-
notifications_default
|
|
6
|
-
} from "./chunk-3EWTPOF7.js";
|
|
7
|
-
import {
|
|
8
|
-
tunnel_default
|
|
9
|
-
} from "./chunk-PA6MNBG4.js";
|
|
10
|
-
import {
|
|
11
|
-
api_server_default
|
|
12
|
-
} from "./chunk-KDU3ZEWT.js";
|
|
13
|
-
import {
|
|
14
|
-
security_default
|
|
15
|
-
} from "./chunk-5OCGO27U.js";
|
|
16
|
-
import {
|
|
17
|
-
file_service_default
|
|
18
|
-
} from "./chunk-3NAFXVQM.js";
|
|
19
|
-
import {
|
|
20
|
-
context_default
|
|
21
|
-
} from "./chunk-UWH7KIAA.js";
|
|
22
|
-
import {
|
|
23
|
-
speech_default
|
|
24
|
-
} from "./chunk-TMVTSWVH.js";
|
|
25
|
-
|
|
26
|
-
// src/plugins/core-plugins.ts
|
|
27
|
-
var corePlugins = [
|
|
28
|
-
// Service plugins (no adapter dependencies)
|
|
29
|
-
security_default,
|
|
30
|
-
file_service_default,
|
|
31
|
-
context_default,
|
|
32
|
-
speech_default,
|
|
33
|
-
notifications_default,
|
|
34
|
-
// Infrastructure plugins
|
|
35
|
-
tunnel_default,
|
|
36
|
-
api_server_default,
|
|
37
|
-
// Adapter plugins (depend on security, notifications, etc.)
|
|
38
|
-
telegram_default
|
|
39
|
-
];
|
|
40
|
-
|
|
41
|
-
export {
|
|
42
|
-
corePlugins
|
|
43
|
-
};
|
|
44
|
-
//# sourceMappingURL=chunk-2HEFALTZ.js.map
|
|
@@ -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 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'\n\nexport const corePlugins = [\n // Service plugins (no adapter dependencies)\n securityPlugin,\n fileServicePlugin,\n contextPlugin,\n speechPlugin,\n notificationsPlugin,\n // Infrastructure plugins\n tunnelPlugin,\n apiServerPlugin,\n // Adapter plugins (depend on security, notifications, etc.)\n telegramPlugin,\n]\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAcO,IAAM,cAAc;AAAA;AAAA,EAEzB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAEA;AAAA,EACA;AAAA;AAAA,EAEA;AACF;","names":[]}
|
package/dist/chunk-2KT6TROD.js
DELETED
|
@@ -1,129 +0,0 @@
|
|
|
1
|
-
// src/plugins/speech/speech-service.ts
|
|
2
|
-
var SpeechService = class {
|
|
3
|
-
constructor(config) {
|
|
4
|
-
this.config = config;
|
|
5
|
-
}
|
|
6
|
-
sttProviders = /* @__PURE__ */ new Map();
|
|
7
|
-
ttsProviders = /* @__PURE__ */ new Map();
|
|
8
|
-
providerFactory;
|
|
9
|
-
/** Set a factory function that can recreate providers from config (for hot-reload) */
|
|
10
|
-
setProviderFactory(factory) {
|
|
11
|
-
this.providerFactory = factory;
|
|
12
|
-
}
|
|
13
|
-
registerSTTProvider(name, provider) {
|
|
14
|
-
this.sttProviders.set(name, provider);
|
|
15
|
-
}
|
|
16
|
-
registerTTSProvider(name, provider) {
|
|
17
|
-
this.ttsProviders.set(name, provider);
|
|
18
|
-
}
|
|
19
|
-
unregisterTTSProvider(name) {
|
|
20
|
-
this.ttsProviders.delete(name);
|
|
21
|
-
}
|
|
22
|
-
isSTTAvailable() {
|
|
23
|
-
const { provider, providers } = this.config.stt;
|
|
24
|
-
return provider !== null && providers[provider]?.apiKey !== void 0;
|
|
25
|
-
}
|
|
26
|
-
isTTSAvailable() {
|
|
27
|
-
const provider = this.config.tts.provider;
|
|
28
|
-
return provider !== null && this.ttsProviders.has(provider);
|
|
29
|
-
}
|
|
30
|
-
async transcribe(audioBuffer, mimeType, options) {
|
|
31
|
-
const providerName = this.config.stt.provider;
|
|
32
|
-
if (!providerName || !this.config.stt.providers[providerName]?.apiKey) {
|
|
33
|
-
throw new Error("STT not configured. Set speech.stt.provider and API key in config.");
|
|
34
|
-
}
|
|
35
|
-
const provider = this.sttProviders.get(providerName);
|
|
36
|
-
if (!provider) {
|
|
37
|
-
throw new Error(`STT provider "${providerName}" not registered. Available: ${[...this.sttProviders.keys()].join(", ") || "none"}`);
|
|
38
|
-
}
|
|
39
|
-
return provider.transcribe(audioBuffer, mimeType, options);
|
|
40
|
-
}
|
|
41
|
-
async synthesize(text, options) {
|
|
42
|
-
const providerName = this.config.tts.provider;
|
|
43
|
-
if (!providerName) {
|
|
44
|
-
throw new Error("TTS not configured. Set speech.tts.provider in config.");
|
|
45
|
-
}
|
|
46
|
-
const provider = this.ttsProviders.get(providerName);
|
|
47
|
-
if (!provider) {
|
|
48
|
-
throw new Error(`TTS provider "${providerName}" not registered. Available: ${[...this.ttsProviders.keys()].join(", ") || "none"}`);
|
|
49
|
-
}
|
|
50
|
-
return provider.synthesize(text, options);
|
|
51
|
-
}
|
|
52
|
-
updateConfig(config) {
|
|
53
|
-
this.config = config;
|
|
54
|
-
}
|
|
55
|
-
/** Re-create factory-managed providers from config. Preserves externally-registered providers (e.g. from plugins). */
|
|
56
|
-
refreshProviders(newConfig) {
|
|
57
|
-
this.config = newConfig;
|
|
58
|
-
if (this.providerFactory) {
|
|
59
|
-
const { stt, tts } = this.providerFactory(newConfig);
|
|
60
|
-
for (const [name, provider] of stt) {
|
|
61
|
-
this.sttProviders.set(name, provider);
|
|
62
|
-
}
|
|
63
|
-
for (const [name, provider] of tts) {
|
|
64
|
-
this.ttsProviders.set(name, provider);
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
};
|
|
69
|
-
|
|
70
|
-
// src/plugins/speech/providers/groq.ts
|
|
71
|
-
var GROQ_API_URL = "https://api.groq.com/openai/v1/audio/transcriptions";
|
|
72
|
-
var GroqSTT = class {
|
|
73
|
-
constructor(apiKey, defaultModel = "whisper-large-v3-turbo") {
|
|
74
|
-
this.apiKey = apiKey;
|
|
75
|
-
this.defaultModel = defaultModel;
|
|
76
|
-
}
|
|
77
|
-
name = "groq";
|
|
78
|
-
async transcribe(audioBuffer, mimeType, options) {
|
|
79
|
-
const ext = mimeToExt(mimeType);
|
|
80
|
-
const form = new FormData();
|
|
81
|
-
form.append("file", new Blob([new Uint8Array(audioBuffer)], { type: mimeType }), `audio${ext}`);
|
|
82
|
-
form.append("model", options?.model || this.defaultModel);
|
|
83
|
-
form.append("response_format", "verbose_json");
|
|
84
|
-
if (options?.language) {
|
|
85
|
-
form.append("language", options.language);
|
|
86
|
-
}
|
|
87
|
-
const resp = await fetch(GROQ_API_URL, {
|
|
88
|
-
method: "POST",
|
|
89
|
-
headers: { Authorization: `Bearer ${this.apiKey}` },
|
|
90
|
-
body: form
|
|
91
|
-
});
|
|
92
|
-
if (!resp.ok) {
|
|
93
|
-
const body = await resp.text();
|
|
94
|
-
if (resp.status === 401) {
|
|
95
|
-
throw new Error("Invalid Groq API key. Check your key at console.groq.com.");
|
|
96
|
-
}
|
|
97
|
-
if (resp.status === 413) {
|
|
98
|
-
throw new Error("Audio file too large for Groq API (max 25MB).");
|
|
99
|
-
}
|
|
100
|
-
if (resp.status === 429) {
|
|
101
|
-
throw new Error("Groq rate limit exceeded. Free tier: 28,800 seconds/day. Try again later.");
|
|
102
|
-
}
|
|
103
|
-
throw new Error(`Groq STT error (${resp.status}): ${body}`);
|
|
104
|
-
}
|
|
105
|
-
const data = await resp.json();
|
|
106
|
-
return {
|
|
107
|
-
text: data.text,
|
|
108
|
-
language: data.language,
|
|
109
|
-
duration: data.duration
|
|
110
|
-
};
|
|
111
|
-
}
|
|
112
|
-
};
|
|
113
|
-
function mimeToExt(mimeType) {
|
|
114
|
-
const map = {
|
|
115
|
-
"audio/ogg": ".ogg",
|
|
116
|
-
"audio/wav": ".wav",
|
|
117
|
-
"audio/mpeg": ".mp3",
|
|
118
|
-
"audio/mp4": ".m4a",
|
|
119
|
-
"audio/webm": ".webm",
|
|
120
|
-
"audio/flac": ".flac"
|
|
121
|
-
};
|
|
122
|
-
return map[mimeType] || ".bin";
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
export {
|
|
126
|
-
SpeechService,
|
|
127
|
-
GroqSTT
|
|
128
|
-
};
|
|
129
|
-
//# sourceMappingURL=chunk-2KT6TROD.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/plugins/speech/speech-service.ts","../../src/plugins/speech/providers/groq.ts"],"sourcesContent":["import type { STTProvider, TTSProvider, STTOptions, STTResult, TTSOptions, TTSResult, SpeechServiceConfig } from './speech-types.js';\n\nexport type ProviderFactory = (config: SpeechServiceConfig) => { stt: Map<string, STTProvider>; tts: Map<string, TTSProvider> };\n\nexport class SpeechService {\n private sttProviders = new Map<string, STTProvider>();\n private ttsProviders = new Map<string, TTSProvider>();\n private providerFactory?: ProviderFactory;\n\n constructor(private config: SpeechServiceConfig) {}\n\n /** Set a factory function that can recreate providers from config (for hot-reload) */\n setProviderFactory(factory: ProviderFactory): void {\n this.providerFactory = factory;\n }\n\n registerSTTProvider(name: string, provider: STTProvider): void {\n this.sttProviders.set(name, provider);\n }\n\n registerTTSProvider(name: string, provider: TTSProvider): void {\n this.ttsProviders.set(name, provider);\n }\n\n unregisterTTSProvider(name: string): void {\n this.ttsProviders.delete(name);\n }\n\n isSTTAvailable(): boolean {\n const { provider, providers } = this.config.stt;\n return provider !== null && providers[provider]?.apiKey !== undefined;\n }\n\n isTTSAvailable(): boolean {\n const provider = this.config.tts.provider;\n return provider !== null && this.ttsProviders.has(provider);\n }\n\n async transcribe(audioBuffer: Buffer, mimeType: string, options?: STTOptions): Promise<STTResult> {\n const providerName = this.config.stt.provider;\n if (!providerName || !this.config.stt.providers[providerName]?.apiKey) {\n throw new Error(\"STT not configured. Set speech.stt.provider and API key in config.\");\n }\n const provider = this.sttProviders.get(providerName);\n if (!provider) {\n throw new Error(`STT provider \"${providerName}\" not registered. Available: ${[...this.sttProviders.keys()].join(\", \") || \"none\"}`);\n }\n return provider.transcribe(audioBuffer, mimeType, options);\n }\n\n async synthesize(text: string, options?: TTSOptions): Promise<TTSResult> {\n const providerName = this.config.tts.provider;\n if (!providerName) {\n throw new Error(\"TTS not configured. Set speech.tts.provider in config.\");\n }\n const provider = this.ttsProviders.get(providerName);\n if (!provider) {\n throw new Error(`TTS provider \"${providerName}\" not registered. Available: ${[...this.ttsProviders.keys()].join(\", \") || \"none\"}`);\n }\n return provider.synthesize(text, options);\n }\n\n updateConfig(config: SpeechServiceConfig): void {\n this.config = config;\n }\n\n /** Re-create factory-managed providers from config. Preserves externally-registered providers (e.g. from plugins). */\n refreshProviders(newConfig: SpeechServiceConfig): void {\n this.config = newConfig;\n if (this.providerFactory) {\n const { stt, tts } = this.providerFactory(newConfig);\n // Merge: factory providers overwrite, but externally-registered providers are preserved\n for (const [name, provider] of stt) {\n this.sttProviders.set(name, provider);\n }\n for (const [name, provider] of tts) {\n this.ttsProviders.set(name, provider);\n }\n }\n }\n}\n","import type { STTProvider, STTOptions, STTResult } from '../speech-types.js';\n\nconst GROQ_API_URL = \"https://api.groq.com/openai/v1/audio/transcriptions\";\n\nexport class GroqSTT implements STTProvider {\n readonly name = \"groq\";\n\n constructor(\n private apiKey: string,\n private defaultModel: string = \"whisper-large-v3-turbo\",\n ) {}\n\n async transcribe(audioBuffer: Buffer, mimeType: string, options?: STTOptions): Promise<STTResult> {\n const ext = mimeToExt(mimeType);\n const form = new FormData();\n form.append(\"file\", new Blob([new Uint8Array(audioBuffer)], { type: mimeType }), `audio${ext}`);\n form.append(\"model\", options?.model || this.defaultModel);\n form.append(\"response_format\", \"verbose_json\");\n if (options?.language) {\n form.append(\"language\", options.language);\n }\n\n const resp = await fetch(GROQ_API_URL, {\n method: \"POST\",\n headers: { Authorization: `Bearer ${this.apiKey}` },\n body: form,\n });\n\n if (!resp.ok) {\n const body = await resp.text();\n if (resp.status === 401) {\n throw new Error(\"Invalid Groq API key. Check your key at console.groq.com.\");\n }\n if (resp.status === 413) {\n throw new Error(\"Audio file too large for Groq API (max 25MB).\");\n }\n if (resp.status === 429) {\n throw new Error(\"Groq rate limit exceeded. Free tier: 28,800 seconds/day. Try again later.\");\n }\n throw new Error(`Groq STT error (${resp.status}): ${body}`);\n }\n\n const data = await resp.json() as { text: string; language?: string; duration?: number };\n return {\n text: data.text,\n language: data.language,\n duration: data.duration,\n };\n }\n}\n\nfunction mimeToExt(mimeType: string): string {\n const map: Record<string, string> = {\n \"audio/ogg\": \".ogg\",\n \"audio/wav\": \".wav\",\n \"audio/mpeg\": \".mp3\",\n \"audio/mp4\": \".m4a\",\n \"audio/webm\": \".webm\",\n \"audio/flac\": \".flac\",\n };\n return map[mimeType] || \".bin\";\n}\n"],"mappings":"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","names":[]}
|