@coffer-org/plugin-telegram 1.1.0 → 1.2.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/dist/index.d.ts CHANGED
@@ -1,3 +1,2 @@
1
1
  declare const _default: import("@coffer-org/sdk/plugin").PluginManifest;
2
2
  export default _default;
3
- //# sourceMappingURL=index.d.ts.map
package/dist/index.js CHANGED
@@ -1,15 +1,10 @@
1
- /**
2
- * Плагін telegram — воркер без vaults/modules. Маніфест ІЗОМОРФНИЙ: не імпортує
3
- * node-рантайм (src/runtime/*), бо потрапляє у web-бандл через src/registry.ts.
4
- * Запуск/зупинка бота — у серверних хуках (packages/server/src/plugin-hooks.ts).
5
- */
6
1
  import { definePlugin } from '@coffer-org/sdk/plugin';
7
2
  import { defineSettings } from '@coffer-org/sdk/settings';
8
3
  import { field } from '@coffer-org/sdk/fields';
9
4
  export default definePlugin({
10
5
  id: 'telegram',
11
6
  version: '1.0.0',
12
- dependsOn: [],
7
+ dependsOn: ['orchestrator'],
13
8
  settings: defineSettings({
14
9
  label: 'telegram.settings.label',
15
10
  fields: [
@@ -17,11 +12,6 @@ export default definePlugin({
17
12
  field.password({ key: 'api_hash', label: 'telegram.settings.api_hash' }),
18
13
  field.password({ key: 'bot_token', label: 'telegram.settings.bot_token' }),
19
14
  field.tel({ key: 'phone', label: 'telegram.settings.phone' }),
20
- field.string({ key: 'claude_model', label: 'telegram.settings.claude_model' }),
21
- field.string({ key: 'trigger_prefix', label: 'telegram.settings.trigger_prefix' }),
22
- field.int({ key: 'response_timeout', label: 'telegram.settings.response_timeout' }),
23
- field.boolean({ key: 'skip_permissions', label: 'telegram.settings.skip_permissions' }),
24
15
  ],
25
16
  }),
26
17
  });
27
- //# sourceMappingURL=index.js.map
@@ -1,19 +1,4 @@
1
- /** Env-оверрайди для `claude`: ізольований конфіг-дім (auth — через symlink у claude-home). */
2
- export function claudeEnv(cfg: any): {
3
- CLAUDE_CONFIG_DIR: any;
4
- };
5
- /** Зібрати argv для `claude -p`. sessionId=null → нова сесія (json), інакше --resume. */
6
- export function buildClaudeArgs(cfg: any, sessionId: any): any[];
7
- /** Розпарсити stdout `claude --output-format json` → { text, sessionId }. */
8
- export function parseClaudeResult(stdout: any): {
9
- text: any;
10
- sessionId: any;
11
- };
12
- /**
13
- * Стартувати бота. Тихо не запускається, якщо немає креденшелів
14
- * (сервер працює далі). Кидає лише на справжній збій підключення.
15
- */
16
- export function startBot(opts?: {}): Promise<boolean>;
17
- /** Зупинити бота (викликається з shutdown сервера). Безпечно за відсутності клієнта. */
18
- export function stopBot(): Promise<void>;
19
- //# sourceMappingURL=bot.d.ts.map
1
+ import type { LoadOpts } from './config.ts';
2
+ export type StartOpts = LoadOpts;
3
+ export declare function startBot(opts?: StartOpts): Promise<boolean>;
4
+ export declare function stopBot(): Promise<void>;
@@ -1,16 +1,11 @@
1
1
  import fs from 'node:fs';
2
2
  import path from 'node:path';
3
- import { fileURLToPath } from 'node:url';
4
- import { spawn } from 'node:child_process';
5
- import pkg from 'telegram';
3
+ import { TelegramClient, Api } from 'telegram';
4
+ import { LogLevel } from 'telegram/extensions/Logger.js';
6
5
  import { StringSession } from 'telegram/sessions/index.js';
7
6
  import { NewMessage } from 'telegram/events/index.js';
8
- import { loadBotConfig, hasCredentials } from './config.js';
9
- import { ensureWorkspace } from './workspace.js';
10
- import { loadThreads, saveThreads, resolveParent, getSession, recordSession, pruneThreads } from './threads.js';
11
- const { TelegramClient } = pkg;
12
- const __dirname = path.dirname(fileURLToPath(import.meta.url));
13
- const MAX_MESSAGE_LENGTH = 4096;
7
+ import { handleIncoming } from '@coffer-org/plugin-orchestrator/runtime';
8
+ import { loadBotConfig, hasCredentials } from "./config.js";
14
9
  const log = {
15
10
  info: (m) => console.log(`[telegram-bot] ${new Date().toISOString().slice(0, 19)} ${m}`),
16
11
  warn: (m) => console.warn(`[telegram-bot] ${new Date().toISOString().slice(0, 19)} WARN ${m}`),
@@ -28,202 +23,136 @@ function saveSessionString(file, s) {
28
23
  fs.mkdirSync(path.dirname(file), { recursive: true });
29
24
  fs.writeFileSync(file, s, 'utf-8');
30
25
  }
31
- /** Env-оверрайди для `claude`: ізольований конфіг-дім (auth — через symlink у claude-home). */
32
- export function claudeEnv(cfg) {
33
- return { CLAUDE_CONFIG_DIR: cfg.claudeHomeDir };
34
- }
35
- /** Зібрати argv для `claude -p`. sessionId=null → нова сесія (json), інакше --resume. */
36
- export function buildClaudeArgs(cfg, sessionId) {
37
- const args = ['-p', '--model', cfg.claudeModel, '--output-format', 'json'];
38
- if (cfg.skipPermissions)
39
- args.push('--dangerously-skip-permissions');
40
- if (sessionId)
41
- args.push('--resume', sessionId);
42
- args.push('--mcp-config', path.join(cfg.workspaceDir, '.mcp.json'));
43
- return args;
44
- }
45
- /** Розпарсити stdout `claude --output-format json` → { text, sessionId }. */
46
- export function parseClaudeResult(stdout) {
47
- try {
48
- const obj = JSON.parse(stdout);
49
- return { text: (obj.result ?? '').trim() || '(порожня відповідь)', sessionId: obj.session_id ?? null };
50
- }
51
- catch {
52
- return { text: stdout.trim() || '(порожня відповідь)', sessionId: null };
53
- }
54
- }
55
- /**
56
- * Запустити `claude` headless в ІЗОЛЬОВАНОМУ runtime: cwd=workspace,
57
- * CLAUDE_CONFIG_DIR=claude-home (0 глобальних плагінів/скілів), тільки coffer MCP.
58
- * @returns {Promise<{text:string|null, sessionId:string|null}>}
59
- */
60
- function runClaude(prompt, cfg, sessionId) {
61
- return new Promise((resolve) => {
62
- const args = buildClaudeArgs(cfg, sessionId);
63
- const proc = spawn('claude', args, {
64
- cwd: cfg.workspaceDir,
65
- env: { ...process.env, ...claudeEnv(cfg) },
66
- });
67
- let stdout = '';
68
- let stderr = '';
69
- const timer = setTimeout(() => {
70
- log.warn(`claude таймаут ${cfg.responseTimeout}s — kill`);
71
- proc.kill('SIGKILL');
72
- }, cfg.responseTimeout * 1000);
73
- proc.stdout.on('data', (d) => {
74
- stdout += d.toString();
75
- });
76
- proc.stderr.on('data', (d) => {
77
- stderr += d.toString();
78
- });
79
- proc.on('error', (e) => {
80
- clearTimeout(timer);
81
- log.error(`claude spawn: ${e.message}`);
82
- resolve({ text: `⚠️ не вдалося запустити claude: ${e.message}`, sessionId: null });
83
- });
84
- proc.on('close', (code) => {
85
- clearTimeout(timer);
86
- if (code === 0) {
87
- resolve(parseClaudeResult(stdout));
88
- return;
89
- }
90
- log.error(`claude exit ${code}: ${stderr.slice(0, 800)}`);
91
- resolve({ text: stderr.trim() ? `⚠️ ${stderr.slice(0, 400)}` : null, sessionId: null });
92
- });
93
- proc.stdin.write(prompt);
94
- proc.stdin.end();
95
- });
96
- }
97
- async function sendLong(client, peer, text) {
98
- let last;
99
- for (let i = 0; i < text.length; i += MAX_MESSAGE_LENGTH) {
100
- last = await client.sendMessage(peer, { message: text.slice(i, i + MAX_MESSAGE_LENGTH) });
101
- if (i + MAX_MESSAGE_LENGTH < text.length)
102
- await new Promise((r) => setTimeout(r, 500));
103
- }
104
- return last;
105
- }
106
- let client; // активний клієнт (для stopBot)
107
- /**
108
- * Стартувати бота. Тихо не запускається, якщо немає креденшелів
109
- * (сервер працює далі). Кидає лише на справжній збій підключення.
110
- */
26
+ let client;
27
+ let healthTimer;
111
28
  export async function startBot(opts = {}) {
112
29
  const cfg = loadBotConfig(opts);
113
30
  if (!hasCredentials(cfg)) {
114
- log.warn('немає креденшелів (api_id/api_hash + bot_token|phone) — не стартую. Заповни налаштування плагіна або встанови env-змінні TELEGRAM_*');
31
+ log.warn('no credentials (api_id/api_hash + bot_token|phone) — not starting. Fill in the plugin settings or set the TELEGRAM_* env vars');
115
32
  return false;
116
33
  }
117
- ensureWorkspace(cfg, log);
118
34
  const sessionFile = path.join(cfg.stateDir, '.sessions', 'claude_bot.session');
119
- const threadsFile = path.join(cfg.stateDir, 'threads.json');
120
- client = new TelegramClient(new StringSession(loadSessionString(sessionFile)), cfg.apiId, cfg.apiHash, {
121
- connectionRetries: 5,
35
+ const tg = new TelegramClient(new StringSession(loadSessionString(sessionFile)), cfg.apiId, cfg.apiHash, {
36
+ connectionRetries: Infinity,
37
+ retryDelay: 2000,
38
+ autoReconnect: true,
122
39
  });
123
- // bot_token → неінтерактивний запуск; інакше phone (потрібен TTY).
124
- await client.start(cfg.botToken
40
+ client = tg;
41
+ tg.setLogLevel(LogLevel.NONE);
42
+ const authParams = (cfg.botToken
125
43
  ? { botAuthToken: cfg.botToken }
126
44
  : { phoneNumber: async () => cfg.phone, onError: (e) => log.error(e.message) });
127
- saveSessionString(sessionFile, client.session.save());
128
- const me = await client.getMe();
45
+ await tg.start(authParams);
46
+ saveSessionString(sessionFile, tg.session.save());
47
+ const me = (await tg.getMe());
129
48
  const meId = me?.id?.toString();
130
- log.info(`підключено як @${me?.username || me?.firstName || meId}`);
131
- const prefix = cfg.triggerPrefix.toLowerCase();
132
- client.addEventHandler(async (event) => {
49
+ log.info(`connected as @${me?.username || me?.firstName || meId}`);
50
+ async function sendMd(peer, text) {
51
+ try {
52
+ return await tg.sendMessage(peer, { message: text, parseMode: 'md' });
53
+ }
54
+ catch {
55
+ try {
56
+ return await tg.sendMessage(peer, { message: text });
57
+ }
58
+ catch {
59
+ return undefined;
60
+ }
61
+ }
62
+ }
63
+ async function editMd(peer, msgId, text) {
64
+ try {
65
+ await tg.editMessage(peer, { message: msgId, text, parseMode: 'md' });
66
+ }
67
+ catch {
68
+ try {
69
+ await tg.editMessage(peer, { message: msgId, text });
70
+ }
71
+ catch {
72
+ }
73
+ }
74
+ }
75
+ function startTypingPeer(peer) {
76
+ const ping = () => tg.invoke(new Api.messages.SetTyping({ peer, action: new Api.SendMessageTypingAction() })).catch(() => { });
77
+ void ping();
78
+ const timer = setInterval(() => void ping(), 5000);
79
+ return () => clearInterval(timer);
80
+ }
81
+ tg.addEventHandler(async (event) => {
133
82
  try {
134
83
  const message = event.message;
135
84
  if (!message)
136
85
  return;
137
86
  if (message.out)
138
- return; // власні повідомлення (анти-петля)
87
+ return;
139
88
  if (message.senderId && meId && message.senderId.toString() === meId)
140
89
  return;
141
90
  const text = (message.text || message.message || '').trim();
142
91
  if (!text)
143
92
  return;
144
- // Діагностика: бачимо КОЖНЕ вхідне повідомлення в логах сервера.
145
93
  let chatLabel = String(event.chatId ?? '?');
146
94
  let peer = event.chatId;
147
95
  try {
148
- const chat = await event.getChat();
96
+ const chat = (await event.getChat());
149
97
  chatLabel = chat?.title || chat?.username || chatLabel;
150
- peer = chat ?? peer;
98
+ if (chat)
99
+ peer = chat;
151
100
  }
152
101
  catch {
153
- /* ignore */
154
102
  }
155
103
  log.info(`msg [${chatLabel}]: ${text.slice(0, 80)}`);
156
- // Тригер: за замовч. (порожній префікс) — відповідаємо на все.
157
- if (prefix && !text.toLowerCase().startsWith(prefix))
158
- return;
159
- const query = prefix ? text.slice(prefix.length).trim() : text;
160
- if (!query)
161
- return;
162
- let placeholder;
163
- try {
164
- placeholder = await message.reply({ message: '⌛' });
165
- }
166
- catch {
167
- /* ignore */
168
- }
169
- // Резолв гілки: explicit reply > implicit (вікно replyWindow) > нова сесія.
170
- const now = Date.now();
171
- let threads = loadThreads(threadsFile);
172
- const replyToMsgId = message.replyTo?.replyToMsgId ?? null;
173
- const parent = resolveParent(threads, { replyToMsgId, now }, cfg.replyWindow);
174
- const parentSession = getSession(threads, parent);
175
- let { text: responseText, sessionId } = await runClaude(query, cfg, parentSession);
176
- // --resume з протухлим id → fallback на нову сесію.
177
- if (responseText == null && parentSession) {
178
- ({ text: responseText, sessionId } = await runClaude(query, cfg, null));
179
- }
180
- // Прибрати плейсхолдер ⌛.
181
- if (placeholder) {
182
- try {
183
- await client.deleteMessages(peer, [placeholder.id], { revoke: true });
184
- }
185
- catch {
186
- /* ignore */
187
- }
188
- }
189
- let botMsgId = null;
190
- if (responseText) {
191
- const sent = await sendLong(client, peer, responseText);
192
- botMsgId = sent?.id ?? null;
193
- }
194
- else {
195
- try {
196
- await client.sendMessage(peer, { message: '⚠️ claude не повернув відповіді' });
197
- }
198
- catch {
199
- /* ignore */
200
- }
201
- }
202
- // Зберегти мапінг лише якщо є sessionId (нова або продовжена сесія).
203
- if (sessionId) {
204
- threads = recordSession(threads, { msgId: message.id, botMsgId, sessionId, now });
205
- threads = pruneThreads(threads, now, 7);
206
- saveThreads(threadsFile, threads);
207
- }
104
+ const chatId = String(event.chatId ?? '?');
105
+ const userId = message.senderId?.toString() ?? '?';
106
+ const replyTo = message.replyTo?.replyToMsgId ?? null;
107
+ const connector = {
108
+ id: 'telegram',
109
+ capabilities: { streaming: true, typing: true, maxMessageLength: 4096 },
110
+ async sendMessage(_chatId, msgText) {
111
+ const sent = await sendMd(peer, msgText);
112
+ if (!sent)
113
+ return null;
114
+ return { msgId: String(sent.id) };
115
+ },
116
+ async editMessage(_chatId, msgId, msgText) {
117
+ await editMd(peer, Number(msgId), msgText);
118
+ },
119
+ startTyping(_chatId) {
120
+ return startTypingPeer(peer);
121
+ },
122
+ };
123
+ await handleIncoming(connector, {
124
+ chatId,
125
+ userId,
126
+ text,
127
+ replyToId: replyTo != null ? String(replyTo) : null,
128
+ });
208
129
  }
209
130
  catch (err) {
210
- log.error(`обробка повідомлення: ${err.message}`);
131
+ log.error(`message handling: ${err instanceof Error ? err.message : String(err)}`);
211
132
  }
212
133
  }, new NewMessage({}));
213
- log.info(`слухаю повідомлення (тригер: ${prefix ? `'${prefix}'` : 'усі'})`);
134
+ clearInterval(healthTimer);
135
+ healthTimer = setInterval(() => {
136
+ if (!tg.connected) {
137
+ log.warn('watchdog: connection lost — reconnecting');
138
+ tg.connect().catch((e) => log.warn(`watchdog reconnect: ${e instanceof Error ? e.message : String(e)}`));
139
+ }
140
+ }, 30_000);
141
+ if (typeof healthTimer.unref === 'function')
142
+ healthTimer.unref();
143
+ log.info('listening for messages (gate policy — in the orchestrator settings)');
214
144
  return true;
215
145
  }
216
- /** Зупинити бота (викликається з shutdown сервера). Безпечно за відсутності клієнта. */
217
146
  export async function stopBot() {
147
+ clearInterval(healthTimer);
148
+ healthTimer = undefined;
218
149
  if (!client)
219
150
  return;
220
151
  try {
221
152
  await client.disconnect();
222
- log.info('зупинено');
153
+ log.info('stopped');
223
154
  }
224
155
  catch {
225
- /* ignore */
226
156
  }
227
157
  client = undefined;
228
158
  }
229
- //# sourceMappingURL=bot.js.map
@@ -1,33 +1,14 @@
1
- /**
2
- * Звести конфіг бота: значення з DB-налаштувань, env має пріоритет.
3
- * @param {{ env?: Record<string,string|undefined>, dbSettings?: Record<string,unknown> }} [opts]
4
- */
5
- export function loadBotConfig(opts?: {
6
- env?: Record<string, string | undefined>;
7
- dbSettings?: Record<string, unknown>;
8
- }): {
1
+ export declare const PLUGIN_ROOT: string;
2
+ export interface BotConfig {
9
3
  apiId: number;
10
- apiHash: {};
11
- botToken: {};
12
- phone: {};
13
- claudeModel: {};
14
- appRoot: string;
15
- cofferUrl: {};
16
- globalCredentials: string;
17
- replyWindow: number;
18
- runtimeDir: string;
19
- workspaceDir: string;
20
- claudeHomeDir: string;
4
+ apiHash: string;
5
+ botToken: string;
6
+ phone: string;
21
7
  stateDir: string;
22
- workingDir: string;
23
- triggerPrefix: {};
24
- skipPermissions: boolean;
25
- responseTimeout: number;
26
- };
27
- /** Чи достатньо креденшелів для запуску: apiId+apiHash і (botToken або phone). */
28
- export function hasCredentials(cfg: any): boolean;
29
- /** Корінь app (packages/plugin-telegram/src/runtime → ../../../..). */
30
- export const APP_ROOT: string;
31
- /** Корінь plugin-telegram (src/runtime → ../..). */
32
- export const PLUGIN_ROOT: string;
33
- //# sourceMappingURL=config.d.ts.map
8
+ }
9
+ export interface LoadOpts {
10
+ env?: Record<string, string | undefined>;
11
+ dbSettings?: Record<string, unknown>;
12
+ }
13
+ export declare function loadBotConfig(opts?: LoadOpts): BotConfig;
14
+ export declare function hasCredentials(cfg: Pick<BotConfig, 'apiId' | 'apiHash' | 'botToken' | 'phone'>): boolean;
@@ -1,42 +1,18 @@
1
- import os from 'node:os';
2
1
  import path from 'node:path';
3
2
  import { fileURLToPath } from 'node:url';
4
3
  const __dirname = path.dirname(fileURLToPath(import.meta.url));
5
- /** Корінь app (packages/plugin-telegram/src/runtime → ../../../..). */
6
- export const APP_ROOT = path.resolve(__dirname, '../../../..');
7
- /** Корінь plugin-telegram (src/runtime → ../..). */
8
4
  export const PLUGIN_ROOT = path.resolve(__dirname, '../..');
9
- /**
10
- * Звести конфіг бота: значення з DB-налаштувань, env має пріоритет.
11
- * @param {{ env?: Record<string,string|undefined>, dbSettings?: Record<string,unknown> }} [opts]
12
- */
13
5
  export function loadBotConfig(opts = {}) {
14
6
  const env = opts.env ?? process.env;
15
- const db = opts.dbSettings ?? {};
7
+ const db = (opts.dbSettings ?? {});
16
8
  return {
17
9
  apiId: Number(env.TELEGRAM_API_ID ?? db.api_id ?? 0) || 0,
18
10
  apiHash: env.TELEGRAM_API_HASH ?? db.api_hash ?? '',
19
11
  botToken: env.TELEGRAM_BOT_TOKEN ?? db.bot_token ?? '',
20
12
  phone: env.TELEGRAM_PHONE ?? db.phone ?? '',
21
- claudeModel: env.TELEGRAM_CLAUDE_MODEL ?? db.claude_model ?? 'haiku',
22
- appRoot: APP_ROOT,
23
- cofferUrl: env.COFFER_URL ?? db.coffer_url ?? 'http://localhost:7023',
24
- // Авторизація: symlink на глобальний логін claude (баланс підписки). Окремого
25
- // api_key немає — бот свідомо шарить уже налаштовану сесію ~/.claude.
26
- globalCredentials: env.CLAUDE_GLOBAL_CREDENTIALS ?? path.join(os.homedir(), '.claude', '.credentials.json'),
27
- replyWindow: Number(env.TELEGRAM_REPLY_WINDOW ?? db.reply_window ?? 1800) || 1800,
28
- runtimeDir: path.join(PLUGIN_ROOT, 'runtime'),
29
- workspaceDir: path.join(PLUGIN_ROOT, 'runtime', 'workspace'),
30
- claudeHomeDir: path.join(PLUGIN_ROOT, 'runtime', 'claude-home'),
31
13
  stateDir: path.join(PLUGIN_ROOT, 'runtime', 'state'),
32
- workingDir: path.join(PLUGIN_ROOT, 'runtime', 'workspace'),
33
- triggerPrefix: env.TELEGRAM_TRIGGER_PREFIX ?? db.trigger_prefix ?? '',
34
- skipPermissions: db.skip_permissions !== false,
35
- responseTimeout: Number(env.TELEGRAM_RESPONSE_TIMEOUT ?? db.response_timeout ?? 600) || 600,
36
14
  };
37
15
  }
38
- /** Чи достатньо креденшелів для запуску: apiId+apiHash і (botToken або phone). */
39
16
  export function hasCredentials(cfg) {
40
17
  return Boolean(cfg.apiId && cfg.apiHash && (cfg.botToken || cfg.phone));
41
18
  }
42
- //# sourceMappingURL=config.js.map
@@ -1,30 +1,7 @@
1
1
  import type { PluginHooks } from '@coffer-org/server/plugin-hooks';
2
- import { startBot, stopBot } from './bot.js';
3
- export interface BotConfig {
4
- apiId: number;
5
- apiHash: string;
6
- botToken: string;
7
- phone: string;
8
- claudeModel: string;
9
- globalCredentials: string;
10
- cofferUrl: string;
11
- replyWindow: number;
12
- appRoot: string;
13
- runtimeDir: string;
14
- workspaceDir: string;
15
- claudeHomeDir: string;
16
- stateDir: string;
17
- workingDir: string;
18
- triggerPrefix: string;
19
- skipPermissions: boolean;
20
- responseTimeout: number;
21
- }
22
- export interface StartOpts {
23
- env?: Record<string, string | undefined>;
24
- dbSettings?: Record<string, unknown>;
25
- }
2
+ import { startBot, stopBot } from './bot.ts';
3
+ export type { BotConfig, LoadOpts } from './config.ts';
4
+ export type { StartOpts } from './bot.ts';
26
5
  export { startBot, stopBot };
27
- export { loadBotConfig, hasCredentials } from './config.js';
28
- /** Серверні хуки telegram-бота (збирає loadServerHooks через discovery). */
6
+ export { loadBotConfig, hasCredentials } from './config.ts';
29
7
  export declare const serverHooks: PluginHooks;
30
- //# sourceMappingURL=index.d.ts.map
@@ -1,22 +1,13 @@
1
- // TypeScript entry-point для plugin-hooks.ts (server-only, динамічний import).
2
- // Реалізація — в bot.js / config.js (чистий ESM без TS-компілятора).
3
1
  import { getPluginSettings } from '@coffer-org/server/plugin-runtime';
4
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
5
- // @ts-ignore — bot.js є чистим ESM без .d.ts; resolve різниться між root-typecheck і tsc -b.
6
- import { startBot, stopBot } from './bot.js';
2
+ import { startBot, stopBot } from "./bot.js";
7
3
  export { startBot, stopBot };
8
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
9
- // @ts-ignore — config.js є чистим ESM без .d.ts.
10
- export { loadBotConfig, hasCredentials } from './config.js';
11
- /** Серверні хуки telegram-бота (збирає loadServerHooks через discovery). */
4
+ export { loadBotConfig, hasCredentials } from "./config.js";
12
5
  export const serverHooks = {
13
6
  init: async () => {
14
7
  const dbSettings = await getPluginSettings('telegram');
15
- // fire-and-forget: мережеве підключення не блокує bootstrap і не валить старт.
16
- void startBot({ dbSettings }).catch((e) => console.warn(`[telegram] не стартував: ${e.message}`));
8
+ void startBot({ dbSettings }).catch((e) => console.warn(`[telegram] failed to start: ${e.message}`));
17
9
  },
18
10
  teardown: async () => {
19
11
  await stopBot();
20
12
  },
21
13
  };
22
- //# sourceMappingURL=index.js.map
package/package.json CHANGED
@@ -1,7 +1,10 @@
1
1
  {
2
2
  "name": "@coffer-org/plugin-telegram",
3
- "version": "1.1.0",
3
+ "version": "1.2.0",
4
4
  "type": "module",
5
+ "engines": {
6
+ "node": ">=24"
7
+ },
5
8
  "files": [
6
9
  "dist"
7
10
  ],
@@ -19,12 +22,14 @@
19
22
  "build": "tsc -b tsconfig.build.json",
20
23
  "prepack": "npm run build && node ../../scripts/swap-exports.mjs dist",
21
24
  "postpack": "node ../../scripts/swap-exports.mjs src",
22
- "test": "node --test \"src/runtime/*.test.js\""
25
+ "test": "node --import tsx --test \"src/runtime/*.test.ts\""
23
26
  },
24
27
  "dependencies": {
25
- "@coffer-org/sdk": "^1.1.0",
26
- "@coffer-org/server": "^1.1.0",
27
- "telegram": "^2.26.0",
28
- "input": "^1.0.1"
29
- }
28
+ "@coffer-org/plugin-orchestrator": "^1.2.0",
29
+ "@coffer-org/sdk": "^1.2.0",
30
+ "@coffer-org/server": "^1.2.0",
31
+ "input": "^1.0.1",
32
+ "telegram": "^2.26.0"
33
+ },
34
+ "devDependencies": {}
30
35
  }
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AASA,wBAiBG"}
package/dist/index.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AACtD,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC1D,OAAO,EAAE,KAAK,EAAE,MAAM,wBAAwB,CAAC;AAE/C,eAAe,YAAY,CAAC;IAC1B,EAAE,EAAE,UAAU;IACd,OAAO,EAAE,OAAO;IAChB,SAAS,EAAE,EAAE;IACb,QAAQ,EAAE,cAAc,CAAC;QACvB,KAAK,EAAE,yBAAyB;QAChC,MAAM,EAAE;YACN,KAAK,CAAC,GAAG,CAAC,EAAE,GAAG,EAAE,QAAQ,EAAE,KAAK,EAAE,0BAA0B,EAAE,CAAC;YAC/D,KAAK,CAAC,QAAQ,CAAC,EAAE,GAAG,EAAE,UAAU,EAAE,KAAK,EAAE,4BAA4B,EAAE,CAAC;YACxE,KAAK,CAAC,QAAQ,CAAC,EAAE,GAAG,EAAE,WAAW,EAAE,KAAK,EAAE,6BAA6B,EAAE,CAAC;YAC1E,KAAK,CAAC,GAAG,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,KAAK,EAAE,yBAAyB,EAAE,CAAC;YAC7D,KAAK,CAAC,MAAM,CAAC,EAAE,GAAG,EAAE,cAAc,EAAE,KAAK,EAAE,gCAAgC,EAAE,CAAC;YAC9E,KAAK,CAAC,MAAM,CAAC,EAAE,GAAG,EAAE,gBAAgB,EAAE,KAAK,EAAE,kCAAkC,EAAE,CAAC;YAClF,KAAK,CAAC,GAAG,CAAC,EAAE,GAAG,EAAE,kBAAkB,EAAE,KAAK,EAAE,oCAAoC,EAAE,CAAC;YACnF,KAAK,CAAC,OAAO,CAAC,EAAE,GAAG,EAAE,kBAAkB,EAAE,KAAK,EAAE,oCAAoC,EAAE,CAAC;SACxF;KACF,CAAC;CACH,CAAC,CAAC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"bot.d.ts","sourceRoot":"","sources":["../../src/runtime/bot.js"],"names":[],"mappings":"AAkCA,+FAA+F;AAC/F;;EAEC;AAED,yFAAyF;AACzF,iEAMC;AAED,6EAA6E;AAC7E;;;EAOC;AA0DD;;;GAGG;AACH,sDAiHC;AAED,wFAAwF;AACxF,yCASC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"bot.js","sourceRoot":"","sources":["../../src/runtime/bot.js"],"names":[],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/runtime/config.js"],"names":[],"mappings":"AAYA;;;GAGG;AACH,qCAFW;IAAE,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAC,MAAM,GAAC,SAAS,CAAC,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAC,OAAO,CAAC,CAAA;CAAE;;;;;;;;;;;;;;;;;;EA2BxF;AAED,kFAAkF;AAClF,kDAEC;AAxCD,uEAAuE;AACvE,8BAA+D;AAE/D,oDAAoD;AACpD,iCAA4D"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/runtime/config.js"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAE/D,uEAAuE;AACvE,MAAM,CAAC,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,aAAa,CAAC,CAAC;AAE/D,oDAAoD;AACpD,MAAM,CAAC,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;AAE5D;;;GAGG;AACH,MAAM,UAAU,aAAa,CAAC,IAAI,GAAG,EAAE;IACrC,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,CAAC;IACpC,MAAM,EAAE,GAAG,IAAI,CAAC,UAAU,IAAI,EAAE,CAAC;IAEjC,OAAO;QACL,KAAK,EAAE,MAAM,CAAC,GAAG,CAAC,eAAe,IAAI,EAAE,CAAC,MAAM,IAAI,CAAC,CAAC,IAAI,CAAC;QACzD,OAAO,EAAE,GAAG,CAAC,iBAAiB,IAAI,EAAE,CAAC,QAAQ,IAAI,EAAE;QACnD,QAAQ,EAAE,GAAG,CAAC,kBAAkB,IAAI,EAAE,CAAC,SAAS,IAAI,EAAE;QACtD,KAAK,EAAE,GAAG,CAAC,cAAc,IAAI,EAAE,CAAC,KAAK,IAAI,EAAE;QAC3C,WAAW,EAAE,GAAG,CAAC,qBAAqB,IAAI,EAAE,CAAC,YAAY,IAAI,OAAO;QACpE,OAAO,EAAE,QAAQ;QACjB,SAAS,EAAE,GAAG,CAAC,UAAU,IAAI,EAAE,CAAC,UAAU,IAAI,uBAAuB;QACrE,8EAA8E;QAC9E,sEAAsE;QACtE,iBAAiB,EAAE,GAAG,CAAC,yBAAyB,IAAI,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,mBAAmB,CAAC;QAC3G,WAAW,EAAE,MAAM,CAAC,GAAG,CAAC,qBAAqB,IAAI,EAAE,CAAC,YAAY,IAAI,IAAI,CAAC,IAAI,IAAI;QACjF,UAAU,EAAE,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,SAAS,CAAC;QAC7C,YAAY,EAAE,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,SAAS,EAAE,WAAW,CAAC;QAC5D,aAAa,EAAE,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,SAAS,EAAE,aAAa,CAAC;QAC/D,QAAQ,EAAE,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,SAAS,EAAE,OAAO,CAAC;QACpD,UAAU,EAAE,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,SAAS,EAAE,WAAW,CAAC;QAC1D,aAAa,EAAE,GAAG,CAAC,uBAAuB,IAAI,EAAE,CAAC,cAAc,IAAI,EAAE;QACrE,eAAe,EAAE,EAAE,CAAC,gBAAgB,KAAK,KAAK;QAC9C,eAAe,EAAE,MAAM,CAAC,GAAG,CAAC,yBAAyB,IAAI,EAAE,CAAC,gBAAgB,IAAI,GAAG,CAAC,IAAI,GAAG;KAC5F,CAAC;AACJ,CAAC;AAED,kFAAkF;AAClF,MAAM,UAAU,cAAc,CAAC,GAAG;IAChC,OAAO,OAAO,CAAC,GAAG,CAAC,KAAK,IAAI,GAAG,CAAC,OAAO,IAAI,CAAC,GAAG,CAAC,QAAQ,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC;AAC1E,CAAC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/runtime/index.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iCAAiC,CAAC;AAInE,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AAE7C,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,eAAe,EAAE,OAAO,CAAC;IACzB,eAAe,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,SAAS;IACxB,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC;IACzC,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACtC;AAED,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC;AAG7B,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAE5D,4EAA4E;AAC5E,eAAO,MAAM,WAAW,EAAE,WAWzB,CAAC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/runtime/index.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,qEAAqE;AAGrE,OAAO,EAAE,iBAAiB,EAAE,MAAM,mCAAmC,CAAC;AACtE,6DAA6D;AAC7D,6FAA6F;AAC7F,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AA2B7C,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC;AAC7B,6DAA6D;AAC7D,iDAAiD;AACjD,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAE5D,4EAA4E;AAC5E,MAAM,CAAC,MAAM,WAAW,GAAgB;IACtC,IAAI,EAAE,KAAK,IAAI,EAAE;QACf,MAAM,UAAU,GAAG,MAAM,iBAAiB,CAAC,UAAU,CAAC,CAAC;QACvD,+EAA+E;QAC/E,KAAK,QAAQ,CAAC,EAAE,UAAU,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAU,EAAE,EAAE,CACjD,OAAO,CAAC,IAAI,CAAC,4BAA6B,CAAW,CAAC,OAAO,EAAE,CAAC,CACjE,CAAC;IACJ,CAAC;IACD,QAAQ,EAAE,KAAK,IAAI,EAAE;QACnB,MAAM,OAAO,EAAE,CAAC;IAClB,CAAC;CACF,CAAC"}
@@ -1,41 +0,0 @@
1
- /** Порожній стан гілок. */
2
- export function emptyThreads(): {
3
- map: {};
4
- last: null;
5
- };
6
- /**
7
- * Визначити parent-повідомлення для прив'язки сесії:
8
- * - explicit reply → той msgId;
9
- * - інакше, якщо last у вікні replyWindow (сек) → last.msgId (implicit reply);
10
- * - інакше null (нова гілка → нова сесія).
11
- */
12
- export function resolveParent(threads: any, { replyToMsgId, now }: {
13
- replyToMsgId: any;
14
- now: any;
15
- }, replyWindowSec: any): any;
16
- /** sessionId, прив'язаний до parent-повідомлення, або null. */
17
- export function getSession(threads: any, parentId: any): any;
18
- /**
19
- * Записати: вхідне повідомлення і відповідь бота → та сама сесія
20
- * (щоб reply на будь-яке з них продовжував гілку). Оновити last.
21
- */
22
- export function recordSession(threads: any, { msgId, botMsgId, sessionId, now }: {
23
- msgId: any;
24
- botMsgId: any;
25
- sessionId: any;
26
- now: any;
27
- }): {
28
- map: any;
29
- last: {
30
- msgId: any;
31
- ts: any;
32
- };
33
- };
34
- /** Прибрати записи старші за ttlDays (щоб файл не ріс безмежно). */
35
- export function pruneThreads(threads: any, now: any, ttlDays: any): {
36
- map: {};
37
- last: any;
38
- };
39
- export function loadThreads(file: any): any;
40
- export function saveThreads(file: any, threads: any): void;
41
- //# sourceMappingURL=threads.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"threads.d.ts","sourceRoot":"","sources":["../../src/runtime/threads.js"],"names":[],"mappings":"AAGA,2BAA2B;AAC3B;;;EAEC;AAED;;;;;GAKG;AACH;;;6BAKC;AAED,+DAA+D;AAC/D,6DAGC;AAED;;;GAGG;AACH;;;;;;;;;;;EAKC;AAED,oEAAoE;AACpE;;;EAOC;AAED,4CAQC;AAED,2DAGC"}
@@ -1,63 +0,0 @@
1
- import fs from 'node:fs';
2
- import path from 'node:path';
3
- /** Порожній стан гілок. */
4
- export function emptyThreads() {
5
- return { map: {}, last: null };
6
- }
7
- /**
8
- * Визначити parent-повідомлення для прив'язки сесії:
9
- * - explicit reply → той msgId;
10
- * - інакше, якщо last у вікні replyWindow (сек) → last.msgId (implicit reply);
11
- * - інакше null (нова гілка → нова сесія).
12
- */
13
- export function resolveParent(threads, { replyToMsgId, now }, replyWindowSec) {
14
- if (replyToMsgId != null)
15
- return replyToMsgId;
16
- const last = threads.last;
17
- if (last && now - last.ts < replyWindowSec * 1000)
18
- return last.msgId;
19
- return null;
20
- }
21
- /** sessionId, прив'язаний до parent-повідомлення, або null. */
22
- export function getSession(threads, parentId) {
23
- if (parentId == null)
24
- return null;
25
- return threads.map[parentId]?.sessionId ?? null;
26
- }
27
- /**
28
- * Записати: вхідне повідомлення і відповідь бота → та сама сесія
29
- * (щоб reply на будь-яке з них продовжував гілку). Оновити last.
30
- */
31
- export function recordSession(threads, { msgId, botMsgId, sessionId, now }) {
32
- const map = { ...threads.map };
33
- map[msgId] = { sessionId, ts: now };
34
- if (botMsgId != null)
35
- map[botMsgId] = { sessionId, ts: now };
36
- return { map, last: { msgId: botMsgId ?? msgId, ts: now } };
37
- }
38
- /** Прибрати записи старші за ttlDays (щоб файл не ріс безмежно). */
39
- export function pruneThreads(threads, now, ttlDays) {
40
- const cutoff = now - ttlDays * 86_400_000;
41
- const map = {};
42
- for (const [k, v] of Object.entries(threads.map)) {
43
- if (v.ts >= cutoff)
44
- map[k] = v;
45
- }
46
- return { map, last: threads.last };
47
- }
48
- export function loadThreads(file) {
49
- try {
50
- const obj = JSON.parse(fs.readFileSync(file, 'utf-8'));
51
- if (obj && typeof obj === 'object' && obj.map)
52
- return obj;
53
- return emptyThreads();
54
- }
55
- catch {
56
- return emptyThreads();
57
- }
58
- }
59
- export function saveThreads(file, threads) {
60
- fs.mkdirSync(path.dirname(file), { recursive: true });
61
- fs.writeFileSync(file, JSON.stringify(threads), 'utf-8');
62
- }
63
- //# sourceMappingURL=threads.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"threads.js","sourceRoot":"","sources":["../../src/runtime/threads.js"],"names":[],"mappings":"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"}
@@ -1,18 +0,0 @@
1
- /**
2
- * Прив'язати auth: symlink claude-home/.credentials.json → глобальний логін
3
- * (~/.claude/.credentials.json). Так бот шарить уже налаштовану сесію і витрачає
4
- * баланс підписки, а не окремий рахунок. Перестворюється щоразу (ідемпотентно).
5
- * Якщо глобального файлу нема (напр. macOS keychain) — пропускаємо з warn.
6
- * Безпека: claude-home лежить під APP_ROOT, а в settings.json є deny Read(APP_ROOT/**),
7
- * тому Read-tool бота не може прочитати цей токен; внутрішнє auth-завантаження claude
8
- * працює повз tool-дозволи.
9
- */
10
- export function linkCredentials(cfg: any, log?: Console): boolean;
11
- /**
12
- * Ідемпотентно підготувати ізольований runtime бота: створити папки, згенерувати
13
- * конфіги з абсолютними шляхами (APP_ROOT) — .mcp.json (тільки coffer) та
14
- * claude-home/settings.json (обмежені інструменти, deny на код app), і прив'язати
15
- * auth (symlink на глобальний логін). CLAUDE.md і skills не чіпаємо — версіонуються в git.
16
- */
17
- export function ensureWorkspace(cfg: any, log?: Console): void;
18
- //# sourceMappingURL=workspace.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"workspace.d.ts","sourceRoot":"","sources":["../../src/runtime/workspace.js"],"names":[],"mappings":"AAGA;;;;;;;;GAQG;AACH,kEASC;AAED;;;;;GAKG;AACH,+DAiCC"}
@@ -1,59 +0,0 @@
1
- import fs from 'node:fs';
2
- import path from 'node:path';
3
- /**
4
- * Прив'язати auth: symlink claude-home/.credentials.json → глобальний логін
5
- * (~/.claude/.credentials.json). Так бот шарить уже налаштовану сесію і витрачає
6
- * баланс підписки, а не окремий рахунок. Перестворюється щоразу (ідемпотентно).
7
- * Якщо глобального файлу нема (напр. macOS keychain) — пропускаємо з warn.
8
- * Безпека: claude-home лежить під APP_ROOT, а в settings.json є deny Read(APP_ROOT/**),
9
- * тому Read-tool бота не може прочитати цей токен; внутрішнє auth-завантаження claude
10
- * працює повз tool-дозволи.
11
- */
12
- export function linkCredentials(cfg, log = console) {
13
- const target = path.join(cfg.claudeHomeDir, '.credentials.json');
14
- fs.rmSync(target, { force: true });
15
- if (fs.existsSync(cfg.globalCredentials)) {
16
- fs.symlinkSync(cfg.globalCredentials, target);
17
- return true;
18
- }
19
- log.warn?.(`[telegram-bot] global credentials не знайдено (${cfg.globalCredentials}) — claude буде "Not logged in"`);
20
- return false;
21
- }
22
- /**
23
- * Ідемпотентно підготувати ізольований runtime бота: створити папки, згенерувати
24
- * конфіги з абсолютними шляхами (APP_ROOT) — .mcp.json (тільки coffer) та
25
- * claude-home/settings.json (обмежені інструменти, deny на код app), і прив'язати
26
- * auth (symlink на глобальний логін). CLAUDE.md і skills не чіпаємо — версіонуються в git.
27
- */
28
- export function ensureWorkspace(cfg, log = console) {
29
- fs.mkdirSync(path.join(cfg.stateDir, '.sessions'), { recursive: true });
30
- fs.mkdirSync(path.join(cfg.workspaceDir, '.claude', 'skills'), { recursive: true });
31
- fs.mkdirSync(cfg.claudeHomeDir, { recursive: true });
32
- const mcp = {
33
- mcpServers: {
34
- coffer: {
35
- command: 'npx',
36
- args: ['tsx', path.join(cfg.appRoot, 'packages', 'mcp', 'bin', 'stdio.ts')],
37
- env: { COFFER_URL: cfg.cofferUrl },
38
- },
39
- },
40
- };
41
- fs.writeFileSync(path.join(cfg.workspaceDir, '.mcp.json'), JSON.stringify(mcp, null, 2) + '\n', 'utf-8');
42
- // Абсолютний шлях у permission-патернах Claude Code анкериться ПОДВІЙНИМ слешем
43
- // (//abs/path); одинарний `/` означає відносно проєкту і НЕ матчить. deny має
44
- // пріоритет і застосовується навіть під --dangerously-skip-permissions.
45
- // Read у default-режимі авто-дозволений, тож код app блокуємо явним deny.
46
- // appRoot покриває і workspace, і claude-home (вони під ним) → Read-tool бота не
47
- // дістане ні код, ні .credentials.json. Skills вантажаться через Skill-tool, не Read.
48
- const appGlob = `//${cfg.appRoot.replace(/^\/+/, '')}/**`;
49
- const settings = {
50
- permissions: {
51
- allow: ['mcp__coffer__*', 'WebSearch', 'WebFetch', 'Skill'],
52
- deny: ['Bash', 'Edit', 'Write', `Read(${appGlob})`, `Glob(${appGlob})`, `Grep(${appGlob})`],
53
- },
54
- enableAllProjectMcpServers: false,
55
- };
56
- fs.writeFileSync(path.join(cfg.claudeHomeDir, 'settings.json'), JSON.stringify(settings, null, 2) + '\n', 'utf-8');
57
- linkCredentials(cfg, log);
58
- }
59
- //# sourceMappingURL=workspace.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"workspace.js","sourceRoot":"","sources":["../../src/runtime/workspace.js"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B;;;;;;;;GAQG;AACH,MAAM,UAAU,eAAe,CAAC,GAAG,EAAE,GAAG,GAAG,OAAO;IAChD,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,aAAa,EAAE,mBAAmB,CAAC,CAAC;IACjE,EAAE,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IACnC,IAAI,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,iBAAiB,CAAC,EAAE,CAAC;QACzC,EAAE,CAAC,WAAW,CAAC,GAAG,CAAC,iBAAiB,EAAE,MAAM,CAAC,CAAC;QAC9C,OAAO,IAAI,CAAC;IACd,CAAC;IACD,GAAG,CAAC,IAAI,EAAE,CAAC,kDAAkD,GAAG,CAAC,iBAAiB,iCAAiC,CAAC,CAAC;IACrH,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,eAAe,CAAC,GAAG,EAAE,GAAG,GAAG,OAAO;IAChD,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,WAAW,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACxE,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,YAAY,EAAE,SAAS,EAAE,QAAQ,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACpF,EAAE,CAAC,SAAS,CAAC,GAAG,CAAC,aAAa,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAErD,MAAM,GAAG,GAAG;QACV,UAAU,EAAE;YACV,MAAM,EAAE;gBACN,OAAO,EAAE,KAAK;gBACd,IAAI,EAAE,CAAC,KAAK,EAAE,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,KAAK,EAAE,UAAU,CAAC,CAAC;gBAC3E,GAAG,EAAE,EAAE,UAAU,EAAE,GAAG,CAAC,SAAS,EAAE;aACnC;SACF;KACF,CAAC;IACF,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,YAAY,EAAE,WAAW,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,EAAE,OAAO,CAAC,CAAC;IAEzG,gFAAgF;IAChF,8EAA8E;IAC9E,wEAAwE;IACxE,0EAA0E;IAC1E,iFAAiF;IACjF,sFAAsF;IACtF,MAAM,OAAO,GAAG,KAAK,GAAG,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,KAAK,CAAC;IAC1D,MAAM,QAAQ,GAAG;QACf,WAAW,EAAE;YACX,KAAK,EAAE,CAAC,gBAAgB,EAAE,WAAW,EAAE,UAAU,EAAE,OAAO,CAAC;YAC3D,IAAI,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ,OAAO,GAAG,EAAE,QAAQ,OAAO,GAAG,EAAE,QAAQ,OAAO,GAAG,CAAC;SAC5F;QACD,0BAA0B,EAAE,KAAK;KAClC,CAAC;IACF,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,aAAa,EAAE,eAAe,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,EAAE,OAAO,CAAC,CAAC;IAEnH,eAAe,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;AAC5B,CAAC"}