@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.
@@ -0,0 +1,77 @@
1
+ import tweetnacl from 'tweetnacl';
2
+ import tweetnaclUtil from 'tweetnacl-util';
3
+ import zlib from 'zlib';
4
+ import { promisify } from 'util';
5
+ const gzip = promisify(zlib.gzip);
6
+ const gunzip = promisify(zlib.gunzip);
7
+ const { encodeBase64, decodeBase64, encodeUTF8, decodeUTF8 } = tweetnaclUtil;
8
+ const COMPRESS_THRESHOLD = 512;
9
+ export async function encrypt(data, key) {
10
+ const nonce = tweetnacl.randomBytes(24);
11
+ const jsonStr = JSON.stringify(data);
12
+ let message;
13
+ let compressed = false;
14
+ if (jsonStr.length > COMPRESS_THRESHOLD) {
15
+ const compressedBuf = await gzip(Buffer.from(jsonStr, 'utf8'));
16
+ message = new Uint8Array(compressedBuf);
17
+ compressed = true;
18
+ }
19
+ else {
20
+ message = decodeUTF8(jsonStr);
21
+ }
22
+ const encrypted = tweetnacl.secretbox(message, nonce, key);
23
+ const result = {
24
+ n: encodeBase64(nonce),
25
+ c: encodeBase64(encrypted),
26
+ };
27
+ if (compressed)
28
+ result.z = true;
29
+ return result;
30
+ }
31
+ export async function decrypt(encrypted, key) {
32
+ try {
33
+ const nonce = decodeBase64(encrypted.n);
34
+ const ciphertext = decodeBase64(encrypted.c);
35
+ const decrypted = tweetnacl.secretbox.open(ciphertext, nonce, key);
36
+ if (!decrypted)
37
+ return null;
38
+ if (encrypted.z) {
39
+ const decompressed = await gunzip(Buffer.from(decrypted));
40
+ return JSON.parse(decompressed.toString('utf8'));
41
+ }
42
+ else {
43
+ return JSON.parse(encodeUTF8(decrypted));
44
+ }
45
+ }
46
+ catch {
47
+ return null;
48
+ }
49
+ }
50
+ export function isEncrypted(msg) {
51
+ return msg !== null && typeof msg === 'object' && typeof msg.n === 'string' && typeof msg.c === 'string';
52
+ }
53
+ export function decodeKey(encodedKey) {
54
+ return decodeBase64(encodedKey);
55
+ }
56
+ export async function parseMessage(data, sessionKey) {
57
+ try {
58
+ const parsed = JSON.parse(data);
59
+ if (sessionKey && isEncrypted(parsed)) {
60
+ return await decrypt(parsed, sessionKey);
61
+ }
62
+ return parsed;
63
+ }
64
+ catch {
65
+ return null;
66
+ }
67
+ }
68
+ export async function encryptAndSend(ws, msg, sessionKey) {
69
+ if (sessionKey) {
70
+ const encrypted = await encrypt(msg, sessionKey);
71
+ ws.send(JSON.stringify(encrypted));
72
+ }
73
+ else {
74
+ ws.send(JSON.stringify(msg));
75
+ }
76
+ }
77
+ //# sourceMappingURL=encryption.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"encryption.js","sourceRoot":"","sources":["../src/encryption.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Read Claude Code session history from ~/.claude/projects/<folder>/<sessionId>.jsonl
3
+ *
4
+ * Claude stores sessions as JSONL files organized by project directory.
5
+ * Path-to-folder mapping: `/foo/bar` → `-foo-bar`, `C:\foo\bar` → `C--foo-bar`
6
+ */
7
+ export interface SessionInfo {
8
+ sessionId: string;
9
+ title: string;
10
+ preview: string;
11
+ lastModified: number;
12
+ }
13
+ export interface HistoryMessage {
14
+ role: 'user' | 'assistant' | 'tool';
15
+ content: string;
16
+ toolName?: string;
17
+ toolInput?: string;
18
+ toolId?: string;
19
+ timestamp?: string;
20
+ }
21
+ /**
22
+ * List sessions for a given working directory by scanning JSONL files.
23
+ * Returns sessions sorted by lastModified descending.
24
+ */
25
+ export declare function listSessions(workDir: string): SessionInfo[];
26
+ /**
27
+ * Read the message history from a session's JSONL file.
28
+ * Returns user messages and assistant text/tool_use blocks as a flat list.
29
+ */
30
+ export declare function readSessionMessages(workDir: string, sessionId: string): HistoryMessage[];
@@ -0,0 +1,156 @@
1
+ /**
2
+ * Read Claude Code session history from ~/.claude/projects/<folder>/<sessionId>.jsonl
3
+ *
4
+ * Claude stores sessions as JSONL files organized by project directory.
5
+ * Path-to-folder mapping: `/foo/bar` → `-foo-bar`, `C:\foo\bar` → `C--foo-bar`
6
+ */
7
+ import { homedir } from 'os';
8
+ import { existsSync, readFileSync, readdirSync, statSync } from 'fs';
9
+ import { join } from 'path';
10
+ function getClaudeProjectsDir() {
11
+ return join(homedir(), '.claude', 'projects');
12
+ }
13
+ function pathToProjectFolder(workDir) {
14
+ return workDir
15
+ .replace(/:/g, '-')
16
+ .replace(/[/\\]/g, '-');
17
+ }
18
+ /**
19
+ * List sessions for a given working directory by scanning JSONL files.
20
+ * Returns sessions sorted by lastModified descending.
21
+ */
22
+ export function listSessions(workDir) {
23
+ const projectsDir = getClaudeProjectsDir();
24
+ const projectFolder = pathToProjectFolder(workDir);
25
+ const projectPath = join(projectsDir, projectFolder);
26
+ if (!existsSync(projectPath)) {
27
+ return [];
28
+ }
29
+ const sessions = [];
30
+ let files;
31
+ try {
32
+ files = readdirSync(projectPath);
33
+ }
34
+ catch {
35
+ return [];
36
+ }
37
+ for (const file of files) {
38
+ if (!file.endsWith('.jsonl'))
39
+ continue;
40
+ const sessionId = file.replace('.jsonl', '');
41
+ const filePath = join(projectPath, file);
42
+ let stats;
43
+ try {
44
+ stats = statSync(filePath);
45
+ }
46
+ catch {
47
+ continue;
48
+ }
49
+ let title = '';
50
+ let preview = '';
51
+ let hasUserMessage = false;
52
+ let customTitle = '';
53
+ let summary = '';
54
+ try {
55
+ const content = readFileSync(filePath, 'utf-8');
56
+ const lines = content.split('\n').filter(l => l.trim());
57
+ for (const line of lines) {
58
+ try {
59
+ const data = JSON.parse(line);
60
+ if (!hasUserMessage && data.type === 'user' && data.message?.content) {
61
+ const text = typeof data.message.content === 'string'
62
+ ? data.message.content
63
+ : data.message.content[0]?.text || '';
64
+ if (text.trim()) {
65
+ preview = text.substring(0, 100);
66
+ title = text.substring(0, 100);
67
+ hasUserMessage = true;
68
+ }
69
+ }
70
+ if (data.type === 'custom-title' && data.customTitle) {
71
+ customTitle = data.customTitle;
72
+ }
73
+ if (data.type === 'summary' && data.summary) {
74
+ summary = data.summary;
75
+ }
76
+ }
77
+ catch { /* skip malformed lines */ }
78
+ }
79
+ }
80
+ catch { /* skip unreadable files */ }
81
+ if (hasUserMessage) {
82
+ sessions.push({
83
+ sessionId,
84
+ title: customTitle || summary || title || sessionId.slice(0, 8),
85
+ preview,
86
+ lastModified: stats.mtime.getTime(),
87
+ });
88
+ }
89
+ }
90
+ sessions.sort((a, b) => b.lastModified - a.lastModified);
91
+ return sessions;
92
+ }
93
+ /**
94
+ * Read the message history from a session's JSONL file.
95
+ * Returns user messages and assistant text/tool_use blocks as a flat list.
96
+ */
97
+ export function readSessionMessages(workDir, sessionId) {
98
+ const projectsDir = getClaudeProjectsDir();
99
+ const projectFolder = pathToProjectFolder(workDir);
100
+ const filePath = join(projectsDir, projectFolder, `${sessionId}.jsonl`);
101
+ if (!existsSync(filePath)) {
102
+ return [];
103
+ }
104
+ const result = [];
105
+ try {
106
+ const content = readFileSync(filePath, 'utf-8');
107
+ const lines = content.split('\n').filter(l => l.trim());
108
+ for (const line of lines) {
109
+ try {
110
+ const data = JSON.parse(line);
111
+ const ts = data.timestamp || undefined;
112
+ if (data.type === 'user' && data.message?.content) {
113
+ const text = typeof data.message.content === 'string'
114
+ ? data.message.content
115
+ : data.message.content
116
+ .filter((b) => b.type === 'text')
117
+ .map((b) => b.text || '')
118
+ .join('');
119
+ if (text.trim()) {
120
+ result.push({ role: 'user', content: text, timestamp: ts });
121
+ }
122
+ }
123
+ if (data.type === 'assistant' && data.message?.content && Array.isArray(data.message.content)) {
124
+ // Merge all text blocks within this assistant message into one entry
125
+ const textParts = [];
126
+ const toolBlocks = [];
127
+ for (const block of data.message.content) {
128
+ if (block.type === 'text' && block.text) {
129
+ textParts.push(block.text);
130
+ }
131
+ else if (block.type === 'tool_use') {
132
+ toolBlocks.push(block);
133
+ }
134
+ }
135
+ if (textParts.length > 0) {
136
+ result.push({ role: 'assistant', content: textParts.join('\n\n'), timestamp: ts });
137
+ }
138
+ for (const tool of toolBlocks) {
139
+ result.push({
140
+ role: 'tool',
141
+ content: '',
142
+ toolName: tool.name,
143
+ toolInput: JSON.stringify(tool.input || {}),
144
+ toolId: tool.id,
145
+ timestamp: ts,
146
+ });
147
+ }
148
+ }
149
+ }
150
+ catch { /* skip malformed lines */ }
151
+ }
152
+ }
153
+ catch { /* skip unreadable files */ }
154
+ return result;
155
+ }
156
+ //# sourceMappingURL=history.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"history.js","sourceRoot":"","sources":["../src/history.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import type { AgentConfig } from './config.js';
2
+ export declare function start(config: AgentConfig): Promise<void>;
package/dist/index.js ADDED
@@ -0,0 +1,43 @@
1
+ import { saveRuntimeState, clearRuntimeState } from './config.js';
2
+ import { connect, disconnect } from './connection.js';
3
+ export async function start(config) {
4
+ console.log('[AgentLink] Starting agent...');
5
+ console.log(`[AgentLink] Working directory: ${config.dir}`);
6
+ console.log(`[AgentLink] Relay server: ${config.server}`);
7
+ console.log(`[AgentLink] Agent name: ${config.name}`);
8
+ // Derive the HTTP base URL from the WebSocket URL for session URL display
9
+ const httpBase = config.server
10
+ .replace(/^wss:/, 'https:')
11
+ .replace(/^ws:/, 'http:');
12
+ try {
13
+ const sessionId = await connect(config);
14
+ const sessionUrl = `${httpBase}/s/${sessionId}`;
15
+ // Persist runtime state so `agentlink status` can read it
16
+ saveRuntimeState({
17
+ pid: process.pid,
18
+ sessionId,
19
+ sessionUrl,
20
+ server: config.server,
21
+ name: config.name,
22
+ dir: config.dir,
23
+ startedAt: new Date().toISOString(),
24
+ });
25
+ console.log('');
26
+ console.log(`[AgentLink] Session URL: ${sessionUrl}`);
27
+ console.log('[AgentLink] Waiting for connections...');
28
+ // Keep process alive, handle graceful shutdown
29
+ const shutdown = () => {
30
+ console.log('\n[AgentLink] Shutting down...');
31
+ clearRuntimeState();
32
+ disconnect();
33
+ process.exit(0);
34
+ };
35
+ process.on('SIGINT', shutdown);
36
+ process.on('SIGTERM', shutdown);
37
+ }
38
+ catch (err) {
39
+ console.error(`[AgentLink] Failed to connect: ${err.message}`);
40
+ process.exit(1);
41
+ }
42
+ }
43
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAClE,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAEtD,MAAM,CAAC,KAAK,UAAU,KAAK,CAAC,MAAmB;IAC7C,OAAO,CAAC,GAAG,CAAC,+BAA+B,CAAC,CAAC;IAC7C,OAAO,CAAC,GAAG,CAAC,kCAAkC,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC;IAC5D,OAAO,CAAC,GAAG,CAAC,6BAA6B,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC;IAC1D,OAAO,CAAC,GAAG,CAAC,2BAA2B,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;IAEtD,0EAA0E;IAC1E,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM;SAC3B,OAAO,CAAC,OAAO,EAAE,QAAQ,CAAC;SAC1B,OAAO,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAE5B,IAAI,CAAC;QACH,MAAM,SAAS,GAAG,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;QACxC,MAAM,UAAU,GAAG,GAAG,QAAQ,MAAM,SAAS,EAAE,CAAC;QAEhD,0DAA0D;QAC1D,gBAAgB,CAAC;YACf,GAAG,EAAE,OAAO,CAAC,GAAG;YAChB,SAAS;YACT,UAAU;YACV,MAAM,EAAE,MAAM,CAAC,MAAM;YACrB,IAAI,EAAE,MAAM,CAAC,IAAI;YACjB,GAAG,EAAE,MAAM,CAAC,GAAG;YACf,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;SACpC,CAAC,CAAC;QAEH,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAChB,OAAO,CAAC,GAAG,CAAC,4BAA4B,UAAU,EAAE,CAAC,CAAC;QACtD,OAAO,CAAC,GAAG,CAAC,wCAAwC,CAAC,CAAC;QAEtD,+CAA+C;QAC/C,MAAM,QAAQ,GAAG,GAAG,EAAE;YACpB,OAAO,CAAC,GAAG,CAAC,gCAAgC,CAAC,CAAC;YAC9C,iBAAiB,EAAE,CAAC;YACpB,UAAU,EAAE,CAAC;YACb,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC,CAAC;QACF,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;QAC/B,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;IAClC,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,KAAK,CAAC,kCAAmC,GAAa,CAAC,OAAO,EAAE,CAAC,CAAC;QAC1E,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC"}
package/dist/sdk.d.ts ADDED
@@ -0,0 +1,18 @@
1
+ export declare function isWindows(): boolean;
2
+ export declare function getDefaultClaudeCodePath(): string;
3
+ export declare function getCleanEnv(): NodeJS.ProcessEnv;
4
+ export interface ResolvedCommand {
5
+ command: string;
6
+ prefixArgs: string[];
7
+ spawnOpts: Record<string, unknown>;
8
+ }
9
+ /**
10
+ * Resolve the claude executable into spawn-ready components.
11
+ * On Windows npm installs, parses the .cmd wrapper to call node directly,
12
+ * avoiding cmd.exe flash and PowerShell execution policy issues.
13
+ */
14
+ export declare function resolveClaudeCommand(): ResolvedCommand;
15
+ /**
16
+ * Pipe an AsyncIterable of messages into a child stdin as JSON lines.
17
+ */
18
+ export declare function streamToStdin(stream: AsyncIterable<unknown>, stdin: NodeJS.WritableStream, abort?: AbortSignal): Promise<void>;
package/dist/sdk.js ADDED
@@ -0,0 +1,138 @@
1
+ /**
2
+ * Utility helpers for spawning the Claude Code CLI.
3
+ * Locates the executable, builds a clean environment, and
4
+ * handles Windows .cmd wrapper parsing.
5
+ */
6
+ import { platform, homedir } from 'os';
7
+ import { join, dirname } from 'path';
8
+ import { existsSync, readFileSync } from 'fs';
9
+ import { execSync } from 'child_process';
10
+ export function isWindows() {
11
+ return platform() === 'win32';
12
+ }
13
+ function getEnhancedPath() {
14
+ if (isWindows()) {
15
+ const systemPaths = [
16
+ 'C:\\Windows\\system32',
17
+ 'C:\\Windows',
18
+ 'C:\\Windows\\System32\\Wbem',
19
+ ];
20
+ const currentPath = process.env.PATH || process.env.Path || '';
21
+ const parts = currentPath.split(';').filter(Boolean);
22
+ for (const sp of systemPaths) {
23
+ if (!parts.some(p => p.toLowerCase() === sp.toLowerCase())) {
24
+ parts.push(sp);
25
+ }
26
+ }
27
+ return parts.join(';');
28
+ }
29
+ const unixPaths = [
30
+ '/usr/local/bin',
31
+ '/usr/bin',
32
+ '/bin',
33
+ '/usr/sbin',
34
+ join(homedir(), '.local', 'bin'),
35
+ join(homedir(), '.npm-global', 'bin'),
36
+ ];
37
+ if (platform() === 'darwin')
38
+ unixPaths.push('/opt/homebrew/bin');
39
+ unixPaths.push(join(process.execPath, '..'));
40
+ const currentPath = process.env.PATH || '';
41
+ const parts = currentPath.split(':').filter(Boolean);
42
+ for (const sp of unixPaths) {
43
+ if (!parts.includes(sp))
44
+ parts.push(sp);
45
+ }
46
+ return parts.join(':');
47
+ }
48
+ export function getDefaultClaudeCodePath() {
49
+ if (process.env.CLAUDE_PATH)
50
+ return process.env.CLAUDE_PATH;
51
+ if (!isWindows()) {
52
+ const candidates = [
53
+ '/usr/local/bin/claude',
54
+ join(homedir(), '.local', 'bin', 'claude'),
55
+ join(homedir(), '.npm-global', 'bin', 'claude'),
56
+ join(process.execPath, '..', 'claude'),
57
+ ];
58
+ if (platform() === 'darwin')
59
+ candidates.push('/opt/homebrew/bin/claude');
60
+ for (const c of candidates) {
61
+ if (existsSync(c))
62
+ return c;
63
+ }
64
+ }
65
+ try {
66
+ const enhancedPath = getEnhancedPath();
67
+ const cmd = isWindows() ? 'where claude' : 'which claude';
68
+ const output = execSync(cmd, {
69
+ stdio: ['pipe', 'pipe', 'pipe'],
70
+ timeout: 5000,
71
+ env: { ...process.env, PATH: enhancedPath },
72
+ }).toString().trim();
73
+ const lines = output.split('\n').map(l => l.trim()).filter(Boolean);
74
+ if (isWindows() && lines.length > 1) {
75
+ const preferred = lines.find(l => /\.(cmd|exe)$/i.test(l));
76
+ if (preferred)
77
+ return preferred;
78
+ }
79
+ if (lines[0])
80
+ return lines[0];
81
+ }
82
+ catch { /* fallthrough */ }
83
+ return 'claude';
84
+ }
85
+ export function getCleanEnv() {
86
+ const env = { ...process.env };
87
+ if (isWindows()) {
88
+ if (!env.COMSPEC)
89
+ env.COMSPEC = 'C:\\Windows\\system32\\cmd.exe';
90
+ if (!env.SystemRoot)
91
+ env.SystemRoot = 'C:\\Windows';
92
+ }
93
+ env.PATH = getEnhancedPath();
94
+ return env;
95
+ }
96
+ /**
97
+ * Resolve the claude executable into spawn-ready components.
98
+ * On Windows npm installs, parses the .cmd wrapper to call node directly,
99
+ * avoiding cmd.exe flash and PowerShell execution policy issues.
100
+ */
101
+ export function resolveClaudeCommand() {
102
+ const execPath = getDefaultClaudeCodePath();
103
+ if (isWindows() && execPath.toLowerCase().endsWith('.cmd')) {
104
+ try {
105
+ const cmdContent = readFileSync(execPath, 'utf-8');
106
+ const match = cmdContent.match(/%dp0%\\(.+?\.js)"/i) ||
107
+ cmdContent.match(/%dp0%\\(.+?\.js)/i);
108
+ if (match) {
109
+ const cliJsPath = join(dirname(execPath), match[1]);
110
+ if (existsSync(cliJsPath)) {
111
+ return { command: process.execPath, prefixArgs: [cliJsPath], spawnOpts: {} };
112
+ }
113
+ }
114
+ }
115
+ catch { /* fallthrough */ }
116
+ const ps1Path = execPath.slice(0, -4) + '.ps1';
117
+ if (existsSync(ps1Path)) {
118
+ return {
119
+ command: 'powershell.exe',
120
+ prefixArgs: ['-NoProfile', '-ExecutionPolicy', 'Bypass', '-File', ps1Path],
121
+ spawnOpts: {},
122
+ };
123
+ }
124
+ }
125
+ return { command: execPath, prefixArgs: [], spawnOpts: {} };
126
+ }
127
+ /**
128
+ * Pipe an AsyncIterable of messages into a child stdin as JSON lines.
129
+ */
130
+ export async function streamToStdin(stream, stdin, abort) {
131
+ for await (const message of stream) {
132
+ if (abort?.aborted)
133
+ break;
134
+ stdin.write(JSON.stringify(message) + '\n');
135
+ }
136
+ stdin.end();
137
+ }
138
+ //# sourceMappingURL=sdk.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sdk.js","sourceRoot":"","sources":["../src/sdk.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { AgentConfig } from './config.js';
2
+ export declare function serviceInstall(config: AgentConfig): void;
3
+ export declare function serviceUninstall(): void;