feat: kakao_send_message 에이전트 도구화 + 멀티기기 메인챗 세션 동기화 + 터미널 전체화면
- src/tools/kakao.ts: 기존 KakaoNotify를 kakao_send_message 도구로 노출, 코드에디터에서는 차단 - app.js/server-v2.ts: 메인챗 마지막 활성 세션을 서버에 기록해 새 기기에서 열 때 자동 이어보기 - code.html/code.js/styles.css: 서버 터미널 패널 전체화면 토글 (Esc로 종료) - companion.py: .vbs 자동시작 시 cwd가 System32로 잡히는 문제 방지 위해 홈 디렉터리로 고정 - papa 워크스페이스: 우즈베크어 학습 진행상황, 서버 이름(지서버/클로서버) 메모 갱신 Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,61 @@
|
||||
import { ToolResult } from '../types.js';
|
||||
import { getConfig } from '../config/config.js';
|
||||
import { getVault } from '../security/vault.js';
|
||||
import { KakaoNotify } from '../gateway/kakao-notify.js';
|
||||
|
||||
function getKakaoNotify(): KakaoNotify | null {
|
||||
const cm = getConfig();
|
||||
const cfg = cm.getConfig() as any;
|
||||
const raw = cfg.channels?.kakao || {};
|
||||
const vault = getVault(cm.getConfigDir());
|
||||
|
||||
const appKey = cm.resolveSecret(raw.appKey) || vault.get('channels.kakao.appKey', 'kakao:init')?.expose() || '';
|
||||
const refreshToken = cm.resolveSecret(raw.refreshToken) || vault.get('channels.kakao.refreshToken', 'kakao:init')?.expose() || '';
|
||||
if (!appKey || !refreshToken) return null;
|
||||
|
||||
return new KakaoNotify({
|
||||
appKey,
|
||||
refreshToken,
|
||||
onTokenRefreshed: (newToken) => vault.set('channels.kakao.refreshToken', newToken, 'kakao:token'),
|
||||
});
|
||||
}
|
||||
|
||||
// ── kakao_send_message ──────────────────────────────────────────────────────
|
||||
|
||||
export const kakaoSendTool = {
|
||||
name: 'kakao_send_message',
|
||||
description: '카카오톡 "나에게 보내기"로 텍스트를 본인 카카오톡에 전송합니다. 차트 링크, 요약, 알림 등을 카카오톡으로 보내달라는 요청에 사용. 이미지 첨부는 지원하지 않으므로 링크/텍스트로만 전송합니다.',
|
||||
schema: {
|
||||
text: '보낼 메시지 내용 (URL은 텍스트에 그대로 포함)',
|
||||
},
|
||||
jsonSchema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
text: { type: 'string', description: '보낼 메시지 (URL 포함 가능, 최대 2000자 단위로 자동 분할)' },
|
||||
},
|
||||
required: ['text'],
|
||||
additionalProperties: false,
|
||||
},
|
||||
execute: async (args: any): Promise<ToolResult> => {
|
||||
const text = String(args?.text || '').trim();
|
||||
if (!text) return { success: false, error: 'text(보낼 내용)가 필요합니다.' };
|
||||
|
||||
const notifier = getKakaoNotify();
|
||||
if (!notifier) {
|
||||
return {
|
||||
success: false,
|
||||
error: '카카오 연동이 설정되어 있지 않습니다. 서버 설정에서 /api/kakao/auth/start 로 먼저 카카오 로그인을 완료하세요.',
|
||||
};
|
||||
}
|
||||
|
||||
try {
|
||||
await notifier.send(text);
|
||||
return {
|
||||
success: true,
|
||||
stdout: `✅ 카카오톡(나에게 보내기)으로 전송 완료.\n내용: ${text.slice(0, 200)}${text.length > 200 ? '...' : ''}`,
|
||||
};
|
||||
} catch (err: any) {
|
||||
return { success: false, error: `카카오톡 전송 실패: ${err.message}` };
|
||||
}
|
||||
},
|
||||
};
|
||||
@@ -22,6 +22,7 @@ import { pythonEvalTool } from './python.js';
|
||||
import { sqliteTool } from './sqlite.js';
|
||||
import { weatherSearchTool, weatherAirPollutionTool, weatherOpenMeteoTool, weatherKmaTool, weatherAirKoreaTool, weatherNasaPowerTool, weatherEra5Tool, weatherCdsTool, weatherCmip6Tool } from './weather.js';
|
||||
import { emailListTool, emailReadTool, emailSendTool, emailSearchTool, emailDeleteTool } from './email.js';
|
||||
import { kakaoSendTool } from './kakao.js';
|
||||
import { koreanLawSearchTool, koreanLawFetchTool, usCaseSearchTool } from './legal.js';
|
||||
import { excelReadTool, excelWriteTool } from './excel.js';
|
||||
|
||||
@@ -222,6 +223,8 @@ class ToolRegistry {
|
||||
this.registerSafe(emailSendTool);
|
||||
this.registerSafe(emailSearchTool);
|
||||
this.registerSafe(emailDeleteTool);
|
||||
// Kakao push (나에게 보내기)
|
||||
this.registerSafe(kakaoSendTool);
|
||||
// Legal research tools
|
||||
this.registerSafe(koreanLawSearchTool);
|
||||
this.registerSafe(koreanLawFetchTool);
|
||||
|
||||
Reference in New Issue
Block a user