@fonz/tgcc 0.0.1 → 0.3.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/LICENSE +21 -0
- package/README.md +266 -0
- package/dist/bridge.d.ts +32 -0
- package/dist/bridge.js +1193 -0
- package/dist/bridge.js.map +1 -0
- package/dist/cc-process.d.ts +75 -0
- package/dist/cc-process.js +426 -0
- package/dist/cc-process.js.map +1 -0
- package/dist/cc-protocol.d.ts +255 -0
- package/dist/cc-protocol.js +109 -0
- package/dist/cc-protocol.js.map +1 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +668 -0
- package/dist/cli.js.map +1 -0
- package/dist/config.d.ts +75 -0
- package/dist/config.js +268 -0
- package/dist/config.js.map +1 -0
- package/dist/ctl-server.d.ts +57 -0
- package/dist/ctl-server.js +98 -0
- package/dist/ctl-server.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +13 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp-bridge.d.ts +45 -0
- package/dist/mcp-bridge.js +182 -0
- package/dist/mcp-bridge.js.map +1 -0
- package/dist/mcp-server.d.ts +1 -0
- package/dist/mcp-server.js +109 -0
- package/dist/mcp-server.js.map +1 -0
- package/dist/service.d.ts +1 -0
- package/dist/service.js +84 -0
- package/dist/service.js.map +1 -0
- package/dist/session.d.ts +71 -0
- package/dist/session.js +438 -0
- package/dist/session.js.map +1 -0
- package/dist/streaming.d.ts +178 -0
- package/dist/streaming.js +814 -0
- package/dist/streaming.js.map +1 -0
- package/dist/telegram-html.d.ts +5 -0
- package/dist/telegram-html.js +120 -0
- package/dist/telegram-html.js.map +1 -0
- package/dist/telegram.d.ts +71 -0
- package/dist/telegram.js +384 -0
- package/dist/telegram.js.map +1 -0
- package/package.json +95 -4
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
import { createServer, createConnection } from 'node:net';
|
|
2
|
+
import { existsSync, unlinkSync, mkdirSync } from 'node:fs';
|
|
3
|
+
import { dirname } from 'node:path';
|
|
4
|
+
import { EventEmitter } from 'node:events';
|
|
5
|
+
// ── Bridge-side Unix socket server ──
|
|
6
|
+
export class McpBridgeServer extends EventEmitter {
|
|
7
|
+
servers = new Map();
|
|
8
|
+
handler;
|
|
9
|
+
logger;
|
|
10
|
+
constructor(handler, logger) {
|
|
11
|
+
super();
|
|
12
|
+
this.handler = handler;
|
|
13
|
+
this.logger = logger;
|
|
14
|
+
}
|
|
15
|
+
/** Start listening on a socket path for a specific agent-user pair */
|
|
16
|
+
listen(socketPath) {
|
|
17
|
+
// Clean up stale socket
|
|
18
|
+
if (existsSync(socketPath)) {
|
|
19
|
+
unlinkSync(socketPath);
|
|
20
|
+
}
|
|
21
|
+
const dir = dirname(socketPath);
|
|
22
|
+
if (!existsSync(dir))
|
|
23
|
+
mkdirSync(dir, { recursive: true });
|
|
24
|
+
const server = createServer((socket) => this.handleConnection(socket, socketPath));
|
|
25
|
+
server.on('error', (err) => {
|
|
26
|
+
this.logger.error({ err, socketPath }, 'MCP bridge socket error');
|
|
27
|
+
});
|
|
28
|
+
server.listen(socketPath, () => {
|
|
29
|
+
this.logger.info({ socketPath }, 'MCP bridge listening');
|
|
30
|
+
});
|
|
31
|
+
this.servers.set(socketPath, server);
|
|
32
|
+
}
|
|
33
|
+
handleConnection(socket, socketPath) {
|
|
34
|
+
this.logger.debug({ socketPath }, 'MCP server connected');
|
|
35
|
+
let buffer = '';
|
|
36
|
+
socket.on('data', (data) => {
|
|
37
|
+
buffer += data.toString();
|
|
38
|
+
// Process complete lines
|
|
39
|
+
let newlineIdx;
|
|
40
|
+
while ((newlineIdx = buffer.indexOf('\n')) !== -1) {
|
|
41
|
+
const line = buffer.slice(0, newlineIdx);
|
|
42
|
+
buffer = buffer.slice(newlineIdx + 1);
|
|
43
|
+
this.processLine(line, socket);
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
socket.on('error', (err) => {
|
|
47
|
+
this.logger.debug({ err, socketPath }, 'MCP connection error');
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
async processLine(line, socket) {
|
|
51
|
+
try {
|
|
52
|
+
const request = JSON.parse(line);
|
|
53
|
+
const response = await this.handler(request);
|
|
54
|
+
socket.write(JSON.stringify(response) + '\n');
|
|
55
|
+
}
|
|
56
|
+
catch (err) {
|
|
57
|
+
this.logger.error({ err, line }, 'Failed to process MCP request');
|
|
58
|
+
const errorResponse = {
|
|
59
|
+
id: 'unknown',
|
|
60
|
+
success: false,
|
|
61
|
+
error: err instanceof Error ? err.message : 'Unknown error',
|
|
62
|
+
};
|
|
63
|
+
socket.write(JSON.stringify(errorResponse) + '\n');
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
/** Stop listening on a specific socket */
|
|
67
|
+
close(socketPath) {
|
|
68
|
+
const server = this.servers.get(socketPath);
|
|
69
|
+
if (server) {
|
|
70
|
+
server.close();
|
|
71
|
+
this.servers.delete(socketPath);
|
|
72
|
+
if (existsSync(socketPath)) {
|
|
73
|
+
try {
|
|
74
|
+
unlinkSync(socketPath);
|
|
75
|
+
}
|
|
76
|
+
catch { }
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
/** Stop all sockets */
|
|
81
|
+
closeAll() {
|
|
82
|
+
for (const [socketPath, server] of this.servers) {
|
|
83
|
+
server.close();
|
|
84
|
+
if (existsSync(socketPath)) {
|
|
85
|
+
try {
|
|
86
|
+
unlinkSync(socketPath);
|
|
87
|
+
}
|
|
88
|
+
catch { }
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
this.servers.clear();
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
// ── MCP server-side client (used by mcp-server.ts) ──
|
|
95
|
+
export class McpBridgeClient {
|
|
96
|
+
socketPath;
|
|
97
|
+
socket = null;
|
|
98
|
+
pendingRequests = new Map();
|
|
99
|
+
buffer = '';
|
|
100
|
+
connected = false;
|
|
101
|
+
constructor(socketPath) {
|
|
102
|
+
this.socketPath = socketPath;
|
|
103
|
+
}
|
|
104
|
+
async connect() {
|
|
105
|
+
return new Promise((resolve, reject) => {
|
|
106
|
+
this.socket = createConnection(this.socketPath);
|
|
107
|
+
this.socket.on('connect', () => {
|
|
108
|
+
this.connected = true;
|
|
109
|
+
resolve();
|
|
110
|
+
});
|
|
111
|
+
this.socket.on('data', (data) => {
|
|
112
|
+
this.buffer += data.toString();
|
|
113
|
+
let idx;
|
|
114
|
+
while ((idx = this.buffer.indexOf('\n')) !== -1) {
|
|
115
|
+
const line = this.buffer.slice(0, idx);
|
|
116
|
+
this.buffer = this.buffer.slice(idx + 1);
|
|
117
|
+
this.handleResponse(line);
|
|
118
|
+
}
|
|
119
|
+
});
|
|
120
|
+
this.socket.on('error', (err) => {
|
|
121
|
+
this.connected = false;
|
|
122
|
+
reject(err);
|
|
123
|
+
// Reject all pending requests
|
|
124
|
+
for (const [, pending] of this.pendingRequests) {
|
|
125
|
+
pending.reject(err);
|
|
126
|
+
}
|
|
127
|
+
this.pendingRequests.clear();
|
|
128
|
+
});
|
|
129
|
+
this.socket.on('close', () => {
|
|
130
|
+
this.connected = false;
|
|
131
|
+
});
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
handleResponse(line) {
|
|
135
|
+
try {
|
|
136
|
+
const response = JSON.parse(line);
|
|
137
|
+
const pending = this.pendingRequests.get(response.id);
|
|
138
|
+
if (pending) {
|
|
139
|
+
this.pendingRequests.delete(response.id);
|
|
140
|
+
pending.resolve(response);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
catch { }
|
|
144
|
+
}
|
|
145
|
+
async sendRequest(request, timeoutMs = 30000) {
|
|
146
|
+
if (!this.connected || !this.socket) {
|
|
147
|
+
// Try to reconnect
|
|
148
|
+
await this.reconnect();
|
|
149
|
+
}
|
|
150
|
+
return new Promise((resolve, reject) => {
|
|
151
|
+
const timer = setTimeout(() => {
|
|
152
|
+
this.pendingRequests.delete(request.id);
|
|
153
|
+
reject(new Error(`MCP request timed out after ${timeoutMs}ms`));
|
|
154
|
+
}, timeoutMs);
|
|
155
|
+
this.pendingRequests.set(request.id, {
|
|
156
|
+
resolve: (r) => { clearTimeout(timer); resolve(r); },
|
|
157
|
+
reject: (e) => { clearTimeout(timer); reject(e); },
|
|
158
|
+
});
|
|
159
|
+
this.socket.write(JSON.stringify(request) + '\n');
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
async reconnect(retries = 5, intervalMs = 2000) {
|
|
163
|
+
for (let i = 0; i < retries; i++) {
|
|
164
|
+
try {
|
|
165
|
+
await this.connect();
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
catch {
|
|
169
|
+
if (i < retries - 1) {
|
|
170
|
+
await new Promise(r => setTimeout(r, intervalMs));
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
throw new Error(`Failed to connect to bridge socket at ${this.socketPath} after ${retries} retries`);
|
|
175
|
+
}
|
|
176
|
+
close() {
|
|
177
|
+
this.socket?.destroy();
|
|
178
|
+
this.socket = null;
|
|
179
|
+
this.connected = false;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
//# sourceMappingURL=mcp-bridge.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp-bridge.js","sourceRoot":"","sources":["../src/mcp-bridge.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
2
|
+
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
3
|
+
import { z } from 'zod';
|
|
4
|
+
import { v4 as uuidv4 } from 'uuid';
|
|
5
|
+
import { McpBridgeClient } from './mcp-bridge.js';
|
|
6
|
+
// ── MCP Server ──
|
|
7
|
+
// Spawned as a child of CC. Communicates with the bridge via Unix socket.
|
|
8
|
+
const AGENT_ID = process.env.TGCC_AGENT_ID ?? 'unknown';
|
|
9
|
+
const USER_ID = process.env.TGCC_USER_ID ?? 'unknown';
|
|
10
|
+
const SOCKET_PATH = process.env.TGCC_SOCKET ?? '/tmp/tgcc/sockets/default.sock';
|
|
11
|
+
async function main() {
|
|
12
|
+
const client = new McpBridgeClient(SOCKET_PATH);
|
|
13
|
+
try {
|
|
14
|
+
await client.connect();
|
|
15
|
+
}
|
|
16
|
+
catch (err) {
|
|
17
|
+
// Bridge might not be ready yet — tools will retry on each call
|
|
18
|
+
}
|
|
19
|
+
const server = new McpServer({
|
|
20
|
+
name: 'tgcc',
|
|
21
|
+
version: '0.1.0',
|
|
22
|
+
});
|
|
23
|
+
// ── send_file tool ──
|
|
24
|
+
server.tool('send_file', 'Send a file to the user on Telegram. Use this when you want to deliver a file (image, PDF, code, etc.) to the user.', {
|
|
25
|
+
path: z.string().describe('Absolute path to the file to send'),
|
|
26
|
+
caption: z.string().optional().describe('Optional caption for the file'),
|
|
27
|
+
}, async ({ path, caption }) => {
|
|
28
|
+
const request = {
|
|
29
|
+
id: uuidv4(),
|
|
30
|
+
tool: 'send_file',
|
|
31
|
+
agentId: AGENT_ID,
|
|
32
|
+
userId: USER_ID,
|
|
33
|
+
params: { path, caption },
|
|
34
|
+
};
|
|
35
|
+
try {
|
|
36
|
+
const response = await client.sendRequest(request);
|
|
37
|
+
if (response.success) {
|
|
38
|
+
return { content: [{ type: 'text', text: `File sent to user: ${path}` }] };
|
|
39
|
+
}
|
|
40
|
+
return { content: [{ type: 'text', text: `Failed to send file: ${response.error}` }], isError: true };
|
|
41
|
+
}
|
|
42
|
+
catch (err) {
|
|
43
|
+
return {
|
|
44
|
+
content: [{ type: 'text', text: `Bridge unavailable: ${err instanceof Error ? err.message : 'unknown error'}` }],
|
|
45
|
+
isError: true,
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
// ── send_image tool ──
|
|
50
|
+
server.tool('send_image', 'Send an image to the user on Telegram with a nice preview. Use for generated charts, screenshots, diagrams.', {
|
|
51
|
+
path: z.string().describe('Absolute path to the image file'),
|
|
52
|
+
caption: z.string().optional().describe('Optional caption'),
|
|
53
|
+
}, async ({ path, caption }) => {
|
|
54
|
+
const request = {
|
|
55
|
+
id: uuidv4(),
|
|
56
|
+
tool: 'send_image',
|
|
57
|
+
agentId: AGENT_ID,
|
|
58
|
+
userId: USER_ID,
|
|
59
|
+
params: { path, caption },
|
|
60
|
+
};
|
|
61
|
+
try {
|
|
62
|
+
const response = await client.sendRequest(request);
|
|
63
|
+
if (response.success) {
|
|
64
|
+
return { content: [{ type: 'text', text: `Image sent to user: ${path}` }] };
|
|
65
|
+
}
|
|
66
|
+
return { content: [{ type: 'text', text: `Failed to send image: ${response.error}` }], isError: true };
|
|
67
|
+
}
|
|
68
|
+
catch (err) {
|
|
69
|
+
return {
|
|
70
|
+
content: [{ type: 'text', text: `Bridge unavailable: ${err instanceof Error ? err.message : 'unknown error'}` }],
|
|
71
|
+
isError: true,
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
// ── send_voice tool ──
|
|
76
|
+
server.tool('send_voice', 'Send a voice message to the user on Telegram.', {
|
|
77
|
+
path: z.string().describe('Path to .ogg opus audio file'),
|
|
78
|
+
caption: z.string().optional().describe('Optional caption'),
|
|
79
|
+
}, async ({ path, caption }) => {
|
|
80
|
+
const request = {
|
|
81
|
+
id: uuidv4(),
|
|
82
|
+
tool: 'send_voice',
|
|
83
|
+
agentId: AGENT_ID,
|
|
84
|
+
userId: USER_ID,
|
|
85
|
+
params: { path, caption },
|
|
86
|
+
};
|
|
87
|
+
try {
|
|
88
|
+
const response = await client.sendRequest(request);
|
|
89
|
+
if (response.success) {
|
|
90
|
+
return { content: [{ type: 'text', text: `Voice message sent to user: ${path}` }] };
|
|
91
|
+
}
|
|
92
|
+
return { content: [{ type: 'text', text: `Failed to send voice: ${response.error}` }], isError: true };
|
|
93
|
+
}
|
|
94
|
+
catch (err) {
|
|
95
|
+
return {
|
|
96
|
+
content: [{ type: 'text', text: `Bridge unavailable: ${err instanceof Error ? err.message : 'unknown error'}` }],
|
|
97
|
+
isError: true,
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
// Start the MCP server on stdio
|
|
102
|
+
const transport = new StdioServerTransport();
|
|
103
|
+
await server.connect(transport);
|
|
104
|
+
}
|
|
105
|
+
main().catch((err) => {
|
|
106
|
+
process.stderr.write(`MCP server error: ${err}\n`);
|
|
107
|
+
process.exit(1);
|
|
108
|
+
});
|
|
109
|
+
//# sourceMappingURL=mcp-server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp-server.js","sourceRoot":"","sources":["../src/mcp-server.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/dist/service.js
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import pino from 'pino';
|
|
2
|
+
import { loadConfig, ensureDirectories, ConfigWatcher, CONFIG_PATH } from './config.js';
|
|
3
|
+
import { Bridge } from './bridge.js';
|
|
4
|
+
async function main() {
|
|
5
|
+
// ── Load config ──
|
|
6
|
+
const configPath = process.env.TGCC_CONFIG ?? CONFIG_PATH;
|
|
7
|
+
let config;
|
|
8
|
+
try {
|
|
9
|
+
config = loadConfig(configPath);
|
|
10
|
+
}
|
|
11
|
+
catch (err) {
|
|
12
|
+
console.error(`Failed to load config from ${configPath}:`);
|
|
13
|
+
console.error(err instanceof Error ? err.message : err);
|
|
14
|
+
process.exit(1);
|
|
15
|
+
}
|
|
16
|
+
// ── Setup logger ──
|
|
17
|
+
const logger = pino({
|
|
18
|
+
level: config.global.logLevel,
|
|
19
|
+
transport: process.env.NODE_ENV !== 'production'
|
|
20
|
+
? { target: 'pino/file', options: { destination: 1 } }
|
|
21
|
+
: undefined,
|
|
22
|
+
});
|
|
23
|
+
// ── Ensure directories ──
|
|
24
|
+
ensureDirectories(config);
|
|
25
|
+
// ── Startup self-test ──
|
|
26
|
+
logger.info({ configPath, agents: Object.keys(config.agents) }, 'TGCC starting');
|
|
27
|
+
// ── Create bridge ──
|
|
28
|
+
const bridge = new Bridge(config, logger);
|
|
29
|
+
// ── Config watcher (hot reload) ──
|
|
30
|
+
const watcher = new ConfigWatcher(config, configPath, logger);
|
|
31
|
+
watcher.on('change', async (newConfig, diff) => {
|
|
32
|
+
try {
|
|
33
|
+
await bridge.handleConfigChange(newConfig, diff);
|
|
34
|
+
}
|
|
35
|
+
catch (err) {
|
|
36
|
+
logger.error({ err }, 'Failed to apply config change');
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
watcher.on('error', (err) => {
|
|
40
|
+
logger.error({ err }, 'Config watcher error');
|
|
41
|
+
});
|
|
42
|
+
// ── SIGHUP → manual reload ──
|
|
43
|
+
process.on('SIGHUP', () => {
|
|
44
|
+
logger.info('SIGHUP received — reloading config');
|
|
45
|
+
watcher.reload();
|
|
46
|
+
});
|
|
47
|
+
// ── Graceful shutdown ──
|
|
48
|
+
let shuttingDown = false;
|
|
49
|
+
async function shutdown(signal) {
|
|
50
|
+
if (shuttingDown)
|
|
51
|
+
return;
|
|
52
|
+
shuttingDown = true;
|
|
53
|
+
logger.info({ signal }, 'Shutdown signal received');
|
|
54
|
+
// Stop watching config
|
|
55
|
+
watcher.stop();
|
|
56
|
+
// Stop bridge (stops all bots, kills all CC processes, closes MCP sockets)
|
|
57
|
+
try {
|
|
58
|
+
await bridge.stop();
|
|
59
|
+
}
|
|
60
|
+
catch (err) {
|
|
61
|
+
logger.error({ err }, 'Error during bridge shutdown');
|
|
62
|
+
}
|
|
63
|
+
logger.info('Shutdown complete');
|
|
64
|
+
process.exit(0);
|
|
65
|
+
}
|
|
66
|
+
process.on('SIGTERM', () => shutdown('SIGTERM'));
|
|
67
|
+
process.on('SIGINT', () => shutdown('SIGINT'));
|
|
68
|
+
// Uncaught exceptions — log and continue (don't crash on TG errors)
|
|
69
|
+
process.on('uncaughtException', (err) => {
|
|
70
|
+
logger.error({ err }, 'Uncaught exception');
|
|
71
|
+
});
|
|
72
|
+
process.on('unhandledRejection', (reason) => {
|
|
73
|
+
logger.error({ reason }, 'Unhandled rejection');
|
|
74
|
+
});
|
|
75
|
+
// ── Start ──
|
|
76
|
+
await bridge.start();
|
|
77
|
+
watcher.start();
|
|
78
|
+
logger.info('TGCC is running');
|
|
79
|
+
}
|
|
80
|
+
main().catch((err) => {
|
|
81
|
+
console.error('Fatal error:', err);
|
|
82
|
+
process.exit(1);
|
|
83
|
+
});
|
|
84
|
+
//# sourceMappingURL=service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"service.js","sourceRoot":"","sources":["../src/service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import type pino from 'pino';
|
|
2
|
+
export interface SessionInfo {
|
|
3
|
+
id: string;
|
|
4
|
+
title?: string;
|
|
5
|
+
startedAt: string;
|
|
6
|
+
lastActivity: string;
|
|
7
|
+
messageCount: number;
|
|
8
|
+
totalCostUsd: number;
|
|
9
|
+
}
|
|
10
|
+
export interface JsonlTracking {
|
|
11
|
+
size: number;
|
|
12
|
+
mtimeMs: number;
|
|
13
|
+
}
|
|
14
|
+
export interface UserState {
|
|
15
|
+
currentSessionId: string | null;
|
|
16
|
+
lastActivity: string;
|
|
17
|
+
model: string;
|
|
18
|
+
repo: string;
|
|
19
|
+
permissionMode: string;
|
|
20
|
+
sessions: SessionInfo[];
|
|
21
|
+
knownSessionIds: string[];
|
|
22
|
+
jsonlTracking?: JsonlTracking;
|
|
23
|
+
}
|
|
24
|
+
export interface AgentState {
|
|
25
|
+
users: Record<string, UserState>;
|
|
26
|
+
}
|
|
27
|
+
export interface StateStore {
|
|
28
|
+
agents: Record<string, AgentState>;
|
|
29
|
+
}
|
|
30
|
+
export declare class SessionStore {
|
|
31
|
+
private state;
|
|
32
|
+
private filePath;
|
|
33
|
+
private logger;
|
|
34
|
+
constructor(filePath: string, logger: pino.Logger);
|
|
35
|
+
private load;
|
|
36
|
+
private save;
|
|
37
|
+
private ensureUser;
|
|
38
|
+
getUser(agentId: string, userId: string): UserState;
|
|
39
|
+
setCurrentSession(agentId: string, userId: string, sessionId: string): void;
|
|
40
|
+
updateSessionActivity(agentId: string, userId: string, cost?: number): void;
|
|
41
|
+
setModel(agentId: string, userId: string, model: string): void;
|
|
42
|
+
setRepo(agentId: string, userId: string, repo: string): void;
|
|
43
|
+
setPermissionMode(agentId: string, userId: string, mode: string): void;
|
|
44
|
+
setSessionTitle(agentId: string, userId: string, sessionId: string, title: string): void;
|
|
45
|
+
updateJsonlTracking(agentId: string, userId: string, size: number, mtimeMs: number): void;
|
|
46
|
+
getJsonlTracking(agentId: string, userId: string): JsonlTracking | undefined;
|
|
47
|
+
clearJsonlTracking(agentId: string, userId: string): void;
|
|
48
|
+
clearSession(agentId: string, userId: string): void;
|
|
49
|
+
deleteSession(agentId: string, userId: string, sessionId: string): boolean;
|
|
50
|
+
getRecentSessions(agentId: string, userId: string, limit?: number): SessionInfo[];
|
|
51
|
+
getFullState(): StateStore;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Get the path to a CC session's JSONL file.
|
|
55
|
+
* CC stores sessions at ~/.claude/projects/<repo-slug>/<sessionId>.jsonl
|
|
56
|
+
*/
|
|
57
|
+
export declare function getSessionJsonlPath(sessionId: string, repo: string): string;
|
|
58
|
+
/**
|
|
59
|
+
* Read new JSONL entries from a byte offset and summarize the turns.
|
|
60
|
+
* Returns a formatted catch-up message or null if nothing meaningful was found.
|
|
61
|
+
*/
|
|
62
|
+
export declare function summarizeJsonlDelta(jsonlPath: string, fromByteOffset: number, maxChars?: number): string | null;
|
|
63
|
+
export interface MissedSession {
|
|
64
|
+
id: string;
|
|
65
|
+
mtime: Date;
|
|
66
|
+
files: string[];
|
|
67
|
+
}
|
|
68
|
+
export declare function computeProjectSlug(repoPath: string): string;
|
|
69
|
+
export declare function findMissedSessions(repo: string, knownSessionIds: string[], lastActivity: Date): MissedSession[];
|
|
70
|
+
export declare function parseSessionSummary(sessionDir: string): string;
|
|
71
|
+
export declare function formatCatchupMessage(repo: string, missed: MissedSession[]): string;
|