@agent-link/agent 0.1.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/cli.js ADDED
@@ -0,0 +1,215 @@
1
+ #!/usr/bin/env node
2
+ import { Command } from 'commander';
3
+ import { resolveConfig, loadConfig, saveConfig, getConfigPath, loadRuntimeState, clearRuntimeState, getLogDir, killProcess, isProcessAlive, } from './config.js';
4
+ import { serviceInstall, serviceUninstall } from './service.js';
5
+ import { spawn } from 'child_process';
6
+ import { openSync } from 'fs';
7
+ import { join, dirname, resolve } from 'path';
8
+ import { fileURLToPath } from 'url';
9
+ const program = new Command();
10
+ program
11
+ .name('agentlink-client')
12
+ .description('Local agent that proxies a working directory to a cloud web interface')
13
+ .version('0.1.0');
14
+ program
15
+ .command('start')
16
+ .description('Start the local agent and connect to cloud relay')
17
+ .option('-d, --dir <path>', 'Working directory')
18
+ .option('-s, --server <url>', 'Relay server URL')
19
+ .option('-n, --name <name>', 'Agent name')
20
+ .option('-D, --daemon', 'Run agent in the background as a daemon')
21
+ .action(async (options) => {
22
+ const config = resolveConfig(options);
23
+ if (options.daemon) {
24
+ // Check if agent is already running
25
+ const existing = loadRuntimeState();
26
+ if (existing) {
27
+ let alive = false;
28
+ try {
29
+ process.kill(existing.pid, 0);
30
+ alive = true;
31
+ }
32
+ catch { }
33
+ if (alive) {
34
+ console.log(`Agent is already running (PID ${existing.pid}).`);
35
+ console.log(` URL: ${existing.sessionUrl}`);
36
+ console.log('Use "agentlink-client stop" to stop it first.');
37
+ process.exit(1);
38
+ }
39
+ // Stale state, clean up
40
+ clearRuntimeState();
41
+ }
42
+ // Spawn detached child process running daemon.js
43
+ const __filename = fileURLToPath(import.meta.url);
44
+ const daemonScript = resolve(dirname(__filename), 'daemon.js');
45
+ const logDir = getLogDir();
46
+ const logFile = join(logDir, 'agent.log');
47
+ const errFile = join(logDir, 'agent.err');
48
+ const out = openSync(logFile, 'a');
49
+ const err = openSync(errFile, 'a');
50
+ const child = spawn(process.execPath, [daemonScript, JSON.stringify(config)], {
51
+ detached: true,
52
+ stdio: ['ignore', out, err],
53
+ cwd: config.dir,
54
+ });
55
+ child.unref();
56
+ // Wait briefly for the daemon to write its runtime state
57
+ const maxWait = 5000;
58
+ const interval = 300;
59
+ let waited = 0;
60
+ let state = null;
61
+ while (waited < maxWait) {
62
+ await new Promise(r => setTimeout(r, interval));
63
+ waited += interval;
64
+ state = loadRuntimeState();
65
+ if (state && state.pid !== process.pid)
66
+ break;
67
+ }
68
+ if (state && state.pid !== process.pid) {
69
+ console.log(`Agent started in background (PID ${state.pid}).`);
70
+ console.log(` URL: ${state.sessionUrl}`);
71
+ console.log(` Log: ${logFile}`);
72
+ }
73
+ else {
74
+ console.error('Agent may have failed to start. Check logs:');
75
+ console.error(` ${errFile}`);
76
+ process.exit(1);
77
+ }
78
+ return;
79
+ }
80
+ // Foreground mode (default)
81
+ const { start } = await import('./index.js');
82
+ await start(config);
83
+ });
84
+ program
85
+ .command('stop')
86
+ .description('Stop the running agent')
87
+ .action(async () => {
88
+ const state = loadRuntimeState();
89
+ if (!state) {
90
+ console.log('Agent is not running (no runtime state found).');
91
+ return;
92
+ }
93
+ if (!isProcessAlive(state.pid)) {
94
+ console.log('Agent is not running (process already exited).');
95
+ clearRuntimeState();
96
+ return;
97
+ }
98
+ console.log(`Stopping agent (PID ${state.pid})...`);
99
+ if (!killProcess(state.pid)) {
100
+ console.error('Failed to stop agent.');
101
+ process.exit(1);
102
+ }
103
+ // Wait for the process to exit
104
+ const maxWait = 5000;
105
+ const interval = 200;
106
+ let waited = 0;
107
+ while (waited < maxWait) {
108
+ await new Promise(r => setTimeout(r, interval));
109
+ waited += interval;
110
+ if (!isProcessAlive(state.pid)) {
111
+ clearRuntimeState();
112
+ console.log('Agent stopped.');
113
+ return;
114
+ }
115
+ }
116
+ clearRuntimeState();
117
+ console.log('Agent stopped.');
118
+ });
119
+ program
120
+ .command('status')
121
+ .description('Show current agent status')
122
+ .action(async () => {
123
+ // Agent status
124
+ const agentState = loadRuntimeState();
125
+ if (!agentState) {
126
+ console.log('Agent: not running');
127
+ }
128
+ else if (!isProcessAlive(agentState.pid)) {
129
+ console.log('Agent: not running (stale state)');
130
+ clearRuntimeState();
131
+ }
132
+ else {
133
+ console.log('Agent: running');
134
+ console.log(` PID: ${agentState.pid}`);
135
+ console.log(` Name: ${agentState.name}`);
136
+ console.log(` Directory: ${agentState.dir}`);
137
+ console.log(` Server: ${agentState.server}`);
138
+ console.log(` Session: ${agentState.sessionId}`);
139
+ console.log(` URL: ${agentState.sessionUrl}`);
140
+ console.log(` Started: ${agentState.startedAt}`);
141
+ }
142
+ });
143
+ const configCmd = program
144
+ .command('config')
145
+ .description('View or update configuration');
146
+ configCmd
147
+ .command('list')
148
+ .description('Show all configuration')
149
+ .action(() => {
150
+ const config = loadConfig();
151
+ const path = getConfigPath();
152
+ console.log(`Config file: ${path}\n`);
153
+ if (Object.keys(config).length === 0) {
154
+ console.log('(no configuration set, using defaults)');
155
+ }
156
+ else {
157
+ for (const [key, value] of Object.entries(config)) {
158
+ console.log(` ${key} = ${value}`);
159
+ }
160
+ }
161
+ });
162
+ configCmd
163
+ .command('set <key> <value>')
164
+ .description('Set a configuration value (server, dir, name)')
165
+ .action((key, value) => {
166
+ const validKeys = ['server', 'dir', 'name'];
167
+ if (!validKeys.includes(key)) {
168
+ console.error(`Invalid key "${key}". Valid keys: ${validKeys.join(', ')}`);
169
+ process.exit(1);
170
+ }
171
+ saveConfig({ [key]: value });
172
+ console.log(`Set ${key} = ${value}`);
173
+ });
174
+ configCmd
175
+ .command('get <key>')
176
+ .description('Get a configuration value')
177
+ .action((key) => {
178
+ const config = loadConfig();
179
+ const value = config[key];
180
+ if (value !== undefined) {
181
+ console.log(value);
182
+ }
183
+ else {
184
+ console.log(`(not set)`);
185
+ }
186
+ });
187
+ // Default: show config list if no subcommand
188
+ configCmd.action(() => {
189
+ configCmd.commands.find(c => c.name() === 'list')?.parse([], { from: 'user' });
190
+ });
191
+ // ── Service management ──
192
+ const serviceCmd = program
193
+ .command('service')
194
+ .description('Manage auto-start service');
195
+ serviceCmd
196
+ .command('install')
197
+ .description('Register agent as an auto-start service and start it now')
198
+ .option('-d, --dir <path>', 'Working directory')
199
+ .option('-s, --server <url>', 'Relay server URL')
200
+ .option('-n, --name <name>', 'Agent name')
201
+ .action((options) => {
202
+ const config = resolveConfig(options);
203
+ serviceInstall(config);
204
+ });
205
+ serviceCmd
206
+ .command('uninstall')
207
+ .description('Remove auto-start service and stop the agent')
208
+ .action(() => {
209
+ serviceUninstall();
210
+ });
211
+ serviceCmd.action(() => {
212
+ serviceCmd.help();
213
+ });
214
+ program.parse();
215
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,28 @@
1
+ export interface AgentConfig {
2
+ server: string;
3
+ dir: string;
4
+ name: string;
5
+ }
6
+ export declare const CONFIG_DIR: string;
7
+ export declare function loadConfig(): Partial<AgentConfig>;
8
+ export declare function saveConfig(partial: Partial<AgentConfig>): void;
9
+ export declare function getConfigPath(): string;
10
+ /**
11
+ * Resolve final config: CLI flags > config file > defaults
12
+ */
13
+ export declare function resolveConfig(cliOptions: Partial<AgentConfig>): AgentConfig;
14
+ export interface RuntimeState {
15
+ pid: number;
16
+ sessionId: string;
17
+ sessionUrl: string;
18
+ server: string;
19
+ name: string;
20
+ dir: string;
21
+ startedAt: string;
22
+ }
23
+ export declare function saveRuntimeState(state: RuntimeState): void;
24
+ export declare function loadRuntimeState(): RuntimeState | null;
25
+ export declare function clearRuntimeState(): void;
26
+ export declare function getLogDir(): string;
27
+ export declare function killProcess(pid: number): boolean;
28
+ export declare function isProcessAlive(pid: number): boolean;
package/dist/config.js ADDED
@@ -0,0 +1,101 @@
1
+ import { readFileSync, writeFileSync, mkdirSync, existsSync, unlinkSync } from 'fs';
2
+ import { execSync } from 'child_process';
3
+ import { join } from 'path';
4
+ import { homedir } from 'os';
5
+ const DEFAULTS = {
6
+ server: 'ws://20.127.221.204:3456',
7
+ dir: process.cwd(),
8
+ name: `Agent-${process.platform}-${process.pid}`,
9
+ };
10
+ export const CONFIG_DIR = join(homedir(), '.agentlink');
11
+ const CONFIG_FILE = join(CONFIG_DIR, 'config.json');
12
+ const RUNTIME_FILE = join(CONFIG_DIR, 'agent.json');
13
+ const LOG_DIR = join(CONFIG_DIR, 'logs');
14
+ function ensureConfigDir() {
15
+ if (!existsSync(CONFIG_DIR)) {
16
+ mkdirSync(CONFIG_DIR, { recursive: true });
17
+ }
18
+ }
19
+ export function loadConfig() {
20
+ try {
21
+ const raw = readFileSync(CONFIG_FILE, 'utf-8');
22
+ return JSON.parse(raw);
23
+ }
24
+ catch {
25
+ return {};
26
+ }
27
+ }
28
+ export function saveConfig(partial) {
29
+ ensureConfigDir();
30
+ const existing = loadConfig();
31
+ const merged = { ...existing, ...partial };
32
+ writeFileSync(CONFIG_FILE, JSON.stringify(merged, null, 2) + '\n', 'utf-8');
33
+ }
34
+ export function getConfigPath() {
35
+ return CONFIG_FILE;
36
+ }
37
+ /**
38
+ * Resolve final config: CLI flags > config file > defaults
39
+ */
40
+ export function resolveConfig(cliOptions) {
41
+ const fileConfig = loadConfig();
42
+ return {
43
+ server: cliOptions.server || fileConfig.server || DEFAULTS.server,
44
+ dir: cliOptions.dir || fileConfig.dir || DEFAULTS.dir,
45
+ name: cliOptions.name || fileConfig.name || DEFAULTS.name,
46
+ };
47
+ }
48
+ export function saveRuntimeState(state) {
49
+ ensureConfigDir();
50
+ writeFileSync(RUNTIME_FILE, JSON.stringify(state, null, 2) + '\n', 'utf-8');
51
+ }
52
+ export function loadRuntimeState() {
53
+ try {
54
+ const raw = readFileSync(RUNTIME_FILE, 'utf-8');
55
+ return JSON.parse(raw);
56
+ }
57
+ catch {
58
+ return null;
59
+ }
60
+ }
61
+ export function clearRuntimeState() {
62
+ try {
63
+ unlinkSync(RUNTIME_FILE);
64
+ }
65
+ catch {
66
+ // file may not exist
67
+ }
68
+ }
69
+ export function getLogDir() {
70
+ if (!existsSync(LOG_DIR)) {
71
+ mkdirSync(LOG_DIR, { recursive: true });
72
+ }
73
+ return LOG_DIR;
74
+ }
75
+ // ── Cross-platform process kill ──
76
+ export function killProcess(pid) {
77
+ try {
78
+ if (process.platform === 'win32') {
79
+ // On Windows, process.kill(pid, 'SIGTERM') doesn't reliably terminate
80
+ // processes started in separate console windows. Use taskkill instead.
81
+ execSync(`taskkill /pid ${pid} /f /t`, { stdio: 'ignore' });
82
+ }
83
+ else {
84
+ process.kill(pid, 'SIGTERM');
85
+ }
86
+ return true;
87
+ }
88
+ catch {
89
+ return false;
90
+ }
91
+ }
92
+ export function isProcessAlive(pid) {
93
+ try {
94
+ process.kill(pid, 0);
95
+ return true;
96
+ }
97
+ catch {
98
+ return false;
99
+ }
100
+ }
101
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import type { AgentConfig } from './config.js';
2
+ export declare function connect(config: AgentConfig): Promise<string>;
3
+ export declare function disconnect(): void;
4
+ export declare function send(msg: Record<string, unknown>): void;
@@ -0,0 +1,224 @@
1
+ import WebSocket from 'ws';
2
+ import os from 'os';
3
+ import { existsSync } from 'fs';
4
+ import { readdir } from 'fs/promises';
5
+ import { resolve, isAbsolute } from 'path';
6
+ import { handleChat as claudeHandleChat, setSendFn, abort as abortClaude, cancelExecution as claudeCancelExecution, handleUserAnswer } from './claude.js';
7
+ import { listSessions, readSessionMessages } from './history.js';
8
+ import { decodeKey, parseMessage, encryptAndSend } from './encryption.js';
9
+ const RECONNECT_BASE_DELAY = 1000;
10
+ const RECONNECT_MAX_DELAY = 30_000;
11
+ const MAX_RECONNECT_ATTEMPTS = 20;
12
+ const state = {
13
+ ws: null,
14
+ sessionId: null,
15
+ sessionKey: null,
16
+ reconnectAttempts: 0,
17
+ shouldReconnect: true,
18
+ workDir: process.cwd(),
19
+ };
20
+ export function connect(config) {
21
+ state.workDir = config.dir;
22
+ // Wire up the Claude module to send messages through our WebSocket
23
+ setSendFn(send);
24
+ return new Promise((resolve, reject) => {
25
+ const wsUrl = buildWsUrl(config);
26
+ console.log(`[AgentLink] Connecting to ${config.server}...`);
27
+ const ws = new WebSocket(wsUrl);
28
+ state.ws = ws;
29
+ ws.on('open', () => {
30
+ state.reconnectAttempts = 0;
31
+ console.log('[AgentLink] Connected to server');
32
+ });
33
+ ws.on('message', async (data) => {
34
+ // The 'registered' message is always plain text (key exchange)
35
+ const raw = data.toString();
36
+ let parsed;
37
+ try {
38
+ parsed = JSON.parse(raw);
39
+ }
40
+ catch {
41
+ console.error('[AgentLink] Failed to parse message');
42
+ return;
43
+ }
44
+ if (parsed.type === 'registered') {
45
+ state.sessionId = parsed.sessionId;
46
+ if (typeof parsed.sessionKey === 'string') {
47
+ state.sessionKey = decodeKey(parsed.sessionKey);
48
+ }
49
+ resolve(parsed.sessionId);
50
+ }
51
+ else {
52
+ // All subsequent messages may be encrypted
53
+ const msg = await parseMessage(raw, state.sessionKey);
54
+ if (msg) {
55
+ handleServerMessage(msg);
56
+ }
57
+ else {
58
+ console.error('[AgentLink] Failed to decrypt message');
59
+ }
60
+ }
61
+ });
62
+ ws.on('close', () => {
63
+ console.log('[AgentLink] Disconnected from server');
64
+ if (state.shouldReconnect) {
65
+ scheduleReconnect(config);
66
+ }
67
+ });
68
+ ws.on('error', (err) => {
69
+ console.error(`[AgentLink] WebSocket error: ${err.message}`);
70
+ // 'close' event will fire after this, triggering reconnect
71
+ if (!state.sessionId) {
72
+ reject(err);
73
+ }
74
+ });
75
+ });
76
+ }
77
+ export function disconnect() {
78
+ state.shouldReconnect = false;
79
+ abortClaude();
80
+ if (state.ws) {
81
+ state.ws.close();
82
+ state.ws = null;
83
+ }
84
+ }
85
+ export function send(msg) {
86
+ if (state.ws && state.ws.readyState === WebSocket.OPEN) {
87
+ encryptAndSend(state.ws, msg, state.sessionKey);
88
+ }
89
+ }
90
+ function buildWsUrl(config) {
91
+ const base = config.server.replace(/\/$/, '');
92
+ const params = new URLSearchParams({
93
+ type: 'agent',
94
+ id: config.name,
95
+ name: config.name,
96
+ workDir: config.dir,
97
+ hostname: os.hostname(),
98
+ });
99
+ return `${base}/?${params}`;
100
+ }
101
+ function scheduleReconnect(config) {
102
+ if (state.reconnectAttempts >= MAX_RECONNECT_ATTEMPTS) {
103
+ console.error('[AgentLink] Max reconnect attempts reached. Giving up.');
104
+ process.exit(1);
105
+ }
106
+ const delay = Math.min(RECONNECT_BASE_DELAY * Math.pow(2, state.reconnectAttempts), RECONNECT_MAX_DELAY);
107
+ state.reconnectAttempts++;
108
+ console.log(`[AgentLink] Reconnecting in ${delay / 1000}s (attempt ${state.reconnectAttempts}/${MAX_RECONNECT_ATTEMPTS})...`);
109
+ setTimeout(async () => {
110
+ try {
111
+ state.sessionKey = null; // Reset key; new one will come from server
112
+ await connect(config);
113
+ console.log('[AgentLink] Reconnected successfully');
114
+ }
115
+ catch {
116
+ // close handler will trigger another reconnect
117
+ }
118
+ }, delay);
119
+ }
120
+ function handleServerMessage(msg) {
121
+ switch (msg.type) {
122
+ case 'chat':
123
+ claudeHandleChat(msg.prompt, state.workDir, msg.resumeSessionId, msg.files);
124
+ break;
125
+ case 'cancel_execution':
126
+ claudeCancelExecution();
127
+ break;
128
+ case 'list_sessions':
129
+ handleListSessions();
130
+ break;
131
+ case 'list_directory':
132
+ handleListDirectory(msg);
133
+ break;
134
+ case 'change_workdir':
135
+ handleChangeWorkDir(msg);
136
+ break;
137
+ case 'resume_conversation': {
138
+ // Kill existing Claude process and start fresh with resume
139
+ abortClaude();
140
+ const m = msg;
141
+ const history = readSessionMessages(state.workDir, m.claudeSessionId);
142
+ send({ type: 'conversation_resumed', claudeSessionId: m.claudeSessionId, history });
143
+ break;
144
+ }
145
+ case 'ask_user_answer': {
146
+ const m = msg;
147
+ handleUserAnswer(m.requestId, m.answers);
148
+ break;
149
+ }
150
+ default:
151
+ console.log(`[AgentLink] Unhandled server message: ${msg.type}`);
152
+ }
153
+ }
154
+ function handleListSessions() {
155
+ const sessions = listSessions(state.workDir);
156
+ send({ type: 'sessions_list', sessions, workDir: state.workDir });
157
+ }
158
+ async function handleListDirectory(msg) {
159
+ const dirPath = msg.dirPath || '';
160
+ try {
161
+ // Empty path: list drives (Windows) or root (Unix)
162
+ if (!dirPath) {
163
+ if (os.platform() === 'win32') {
164
+ const drives = [];
165
+ for (const letter of 'CDEFGHIJKLMNOPQRSTUVWXYZ') {
166
+ const drivePath = letter + ':\\';
167
+ if (existsSync(drivePath)) {
168
+ drives.push({ name: letter + ':', type: 'directory' });
169
+ }
170
+ }
171
+ send({ type: 'directory_listing', dirPath: '', entries: drives });
172
+ return;
173
+ }
174
+ // Unix: list root
175
+ const entries = await listDirectoryEntries('/');
176
+ send({ type: 'directory_listing', dirPath: '/', entries });
177
+ return;
178
+ }
179
+ const resolved = isAbsolute(dirPath) ? resolve(dirPath) : resolve(state.workDir, dirPath);
180
+ const entries = await listDirectoryEntries(resolved);
181
+ send({ type: 'directory_listing', dirPath: resolved, entries });
182
+ }
183
+ catch (err) {
184
+ const error = err;
185
+ send({ type: 'directory_listing', dirPath, entries: [], error: error.message });
186
+ }
187
+ }
188
+ async function listDirectoryEntries(dirPath) {
189
+ const items = await readdir(dirPath, { withFileTypes: true });
190
+ const entries = [];
191
+ for (const item of items) {
192
+ if (item.name.startsWith('.'))
193
+ continue;
194
+ if (item.name === 'node_modules')
195
+ continue;
196
+ entries.push({
197
+ name: item.name,
198
+ type: item.isDirectory() ? 'directory' : 'file',
199
+ });
200
+ }
201
+ entries.sort((a, b) => {
202
+ if (a.type !== b.type)
203
+ return a.type === 'directory' ? -1 : 1;
204
+ return a.name.localeCompare(b.name);
205
+ });
206
+ return entries;
207
+ }
208
+ function handleChangeWorkDir(msg) {
209
+ const newDir = msg.workDir;
210
+ if (!existsSync(newDir)) {
211
+ send({ type: 'error', message: `Directory does not exist: ${newDir}` });
212
+ return;
213
+ }
214
+ // Kill any existing Claude process
215
+ abortClaude();
216
+ // Update agent-side workDir
217
+ state.workDir = newDir;
218
+ console.log(`[AgentLink] Working directory changed to: ${newDir}`);
219
+ // Notify web client (server intercepts to update its state)
220
+ send({ type: 'workdir_changed', workDir: newDir });
221
+ // Auto-refresh session list for new directory
222
+ handleListSessions();
223
+ }
224
+ //# sourceMappingURL=connection.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"connection.js","sourceRoot":"","sources":["../src/connection.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export {};
package/dist/daemon.js ADDED
@@ -0,0 +1,19 @@
1
+ import { start } from './index.js';
2
+ const configArg = process.argv[2];
3
+ if (!configArg) {
4
+ console.error('daemon: missing config argument');
5
+ process.exit(1);
6
+ }
7
+ let config;
8
+ try {
9
+ config = JSON.parse(configArg);
10
+ }
11
+ catch {
12
+ console.error('daemon: invalid config JSON');
13
+ process.exit(1);
14
+ }
15
+ start(config).catch((err) => {
16
+ console.error(`daemon: ${err.message}`);
17
+ process.exit(1);
18
+ });
19
+ //# sourceMappingURL=daemon.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"daemon.js","sourceRoot":"","sources":["../src/daemon.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAEnC,MAAM,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClC,IAAI,CAAC,SAAS,EAAE,CAAC;IACf,OAAO,CAAC,KAAK,CAAC,iCAAiC,CAAC,CAAC;IACjD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC;AAED,IAAI,MAAmB,CAAC;AACxB,IAAI,CAAC;IACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,CAAgB,CAAC;AAChD,CAAC;AAAC,MAAM,CAAC;IACP,OAAO,CAAC,KAAK,CAAC,6BAA6B,CAAC,CAAC;IAC7C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC;AAED,KAAK,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;IAC1B,OAAO,CAAC,KAAK,CAAC,WAAY,GAAa,CAAC,OAAO,EAAE,CAAC,CAAC;IACnD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
@@ -0,0 +1,21 @@
1
+ export declare function encrypt(data: unknown, key: Uint8Array): Promise<{
2
+ n: string;
3
+ c: string;
4
+ z?: boolean;
5
+ }>;
6
+ export declare function decrypt(encrypted: {
7
+ n: string;
8
+ c: string;
9
+ z?: boolean;
10
+ }, key: Uint8Array): Promise<unknown | null>;
11
+ export declare function isEncrypted(msg: unknown): msg is {
12
+ n: string;
13
+ c: string;
14
+ z?: boolean;
15
+ };
16
+ export declare function decodeKey(encodedKey: string): Uint8Array;
17
+ export declare function parseMessage(data: string, sessionKey: Uint8Array | null): Promise<Record<string, unknown> | null>;
18
+ export declare function encryptAndSend(ws: {
19
+ send: (data: string) => void;
20
+ readyState: number;
21
+ }, msg: unknown, sessionKey: Uint8Array | null): Promise<void>;