@sumicom/quicksave 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.
Files changed (58) hide show
  1. package/LICENSE +21 -0
  2. package/dist/ai/commitSummary.d.ts +26 -0
  3. package/dist/ai/commitSummary.d.ts.map +1 -0
  4. package/dist/ai/commitSummary.js +145 -0
  5. package/dist/ai/commitSummary.js.map +1 -0
  6. package/dist/config.d.ts +22 -0
  7. package/dist/config.d.ts.map +1 -0
  8. package/dist/config.js +76 -0
  9. package/dist/config.js.map +1 -0
  10. package/dist/connection/connection.d.ts +54 -0
  11. package/dist/connection/connection.d.ts.map +1 -0
  12. package/dist/connection/connection.js +171 -0
  13. package/dist/connection/connection.js.map +1 -0
  14. package/dist/connection/signaling.d.ts +31 -0
  15. package/dist/connection/signaling.d.ts.map +1 -0
  16. package/dist/connection/signaling.js +144 -0
  17. package/dist/connection/signaling.js.map +1 -0
  18. package/dist/git/operations.d.ts +104 -0
  19. package/dist/git/operations.d.ts.map +1 -0
  20. package/dist/git/operations.js +383 -0
  21. package/dist/git/operations.js.map +1 -0
  22. package/dist/git/operations.test.d.ts +2 -0
  23. package/dist/git/operations.test.d.ts.map +1 -0
  24. package/dist/git/operations.test.js +232 -0
  25. package/dist/git/operations.test.js.map +1 -0
  26. package/dist/handlers/messageHandler.d.ts +33 -0
  27. package/dist/handlers/messageHandler.d.ts.map +1 -0
  28. package/dist/handlers/messageHandler.js +463 -0
  29. package/dist/handlers/messageHandler.js.map +1 -0
  30. package/dist/handlers/messageHandler.test.d.ts +2 -0
  31. package/dist/handlers/messageHandler.test.d.ts.map +1 -0
  32. package/dist/handlers/messageHandler.test.js +233 -0
  33. package/dist/handlers/messageHandler.test.js.map +1 -0
  34. package/dist/index.d.ts +3 -0
  35. package/dist/index.d.ts.map +1 -0
  36. package/dist/index.js +127 -0
  37. package/dist/index.js.map +1 -0
  38. package/dist/webrtc/connection.d.ts +52 -0
  39. package/dist/webrtc/connection.d.ts.map +1 -0
  40. package/dist/webrtc/connection.js +255 -0
  41. package/dist/webrtc/connection.js.map +1 -0
  42. package/dist/webrtc/signaling.d.ts +41 -0
  43. package/dist/webrtc/signaling.d.ts.map +1 -0
  44. package/dist/webrtc/signaling.js +152 -0
  45. package/dist/webrtc/signaling.js.map +1 -0
  46. package/package.json +36 -0
  47. package/src/ai/commitSummary.ts +199 -0
  48. package/src/config.ts +97 -0
  49. package/src/connection/connection.ts +223 -0
  50. package/src/connection/signaling.ts +172 -0
  51. package/src/git/operations.test.ts +305 -0
  52. package/src/git/operations.ts +443 -0
  53. package/src/handlers/messageHandler.test.ts +294 -0
  54. package/src/handlers/messageHandler.ts +550 -0
  55. package/src/index.ts +151 -0
  56. package/src/types/webrtc.d.ts +38 -0
  57. package/tsconfig.json +13 -0
  58. package/vitest.config.ts +9 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Quicksave, KingYoung Technology
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,26 @@
1
+ import type { FileDiff, ClaudeModel, TokenUsage } from '@sumicom/quicksave-shared';
2
+ export interface GenerateSummaryOptions {
3
+ diffs: FileDiff[];
4
+ context?: string;
5
+ model?: ClaudeModel;
6
+ }
7
+ export interface GenerateSummaryResult {
8
+ summary: string;
9
+ description?: string;
10
+ tokenUsage?: TokenUsage;
11
+ cached?: boolean;
12
+ }
13
+ export declare class CommitSummaryService {
14
+ private client;
15
+ private cache;
16
+ private pendingRequests;
17
+ constructor(apiKey: string);
18
+ generateSummary(options: GenerateSummaryOptions): Promise<GenerateSummaryResult>;
19
+ private executeGeneration;
20
+ private getCacheKey;
21
+ private getFromCache;
22
+ private formatDiffsForPrompt;
23
+ private buildPrompt;
24
+ private parseResponse;
25
+ }
26
+ //# sourceMappingURL=commitSummary.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"commitSummary.d.ts","sourceRoot":"","sources":["../../src/ai/commitSummary.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AAEnF,MAAM,WAAW,sBAAsB;IACrC,KAAK,EAAE,QAAQ,EAAE,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,WAAW,CAAC;CACrB;AAED,MAAM,WAAW,qBAAqB;IACpC,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAeD,qBAAa,oBAAoB;IAC/B,OAAO,CAAC,MAAM,CAAY;IAC1B,OAAO,CAAC,KAAK,CAAiC;IAC9C,OAAO,CAAC,eAAe,CAAqD;gBAEhE,MAAM,EAAE,MAAM;IAIpB,eAAe,CAAC,OAAO,EAAE,sBAAsB,GAAG,OAAO,CAAC,qBAAqB,CAAC;YAoCxE,iBAAiB;IAyB/B,OAAO,CAAC,WAAW;IAKnB,OAAO,CAAC,YAAY;IAapB,OAAO,CAAC,oBAAoB;IAiC5B,OAAO,CAAC,WAAW;IAsBnB,OAAO,CAAC,aAAa;CAyBtB"}
@@ -0,0 +1,145 @@
1
+ import Anthropic from '@anthropic-ai/sdk';
2
+ import { createHash } from 'crypto';
3
+ const DEFAULT_MODEL = 'claude-haiku-4-5';
4
+ // Max characters per file diff for AI generation (roughly 1KB)
5
+ const MAX_DIFF_CHARS_PER_FILE = 1000;
6
+ // Max total characters for all diffs combined
7
+ const MAX_TOTAL_DIFF_CHARS = 8000;
8
+ // Cache TTL: 5 minutes
9
+ const CACHE_TTL_MS = 5 * 60 * 1000;
10
+ export class CommitSummaryService {
11
+ client;
12
+ cache = new Map();
13
+ pendingRequests = new Map();
14
+ constructor(apiKey) {
15
+ this.client = new Anthropic({ apiKey });
16
+ }
17
+ async generateSummary(options) {
18
+ const { diffs, context, model = DEFAULT_MODEL } = options;
19
+ const diffText = this.formatDiffsForPrompt(diffs);
20
+ if (!diffText.trim()) {
21
+ return { summary: 'Update files' };
22
+ }
23
+ // Generate cache key from diff content and model
24
+ const cacheKey = this.getCacheKey(diffText, context, model);
25
+ // Check cache first
26
+ const cached = this.getFromCache(cacheKey);
27
+ if (cached) {
28
+ return { ...cached, cached: true };
29
+ }
30
+ // Check if there's already a pending request for this exact content
31
+ const pending = this.pendingRequests.get(cacheKey);
32
+ if (pending) {
33
+ const result = await pending;
34
+ return { ...result, cached: true };
35
+ }
36
+ // Create the request promise and store it
37
+ const requestPromise = this.executeGeneration(diffText, context, model, cacheKey);
38
+ this.pendingRequests.set(cacheKey, requestPromise);
39
+ try {
40
+ return await requestPromise;
41
+ }
42
+ finally {
43
+ this.pendingRequests.delete(cacheKey);
44
+ }
45
+ }
46
+ async executeGeneration(diffText, context, model, cacheKey) {
47
+ const prompt = this.buildPrompt(diffText, context);
48
+ const response = await this.client.messages.create({
49
+ model,
50
+ max_tokens: 500,
51
+ messages: [{ role: 'user', content: prompt }],
52
+ });
53
+ const result = this.parseResponse(response);
54
+ // Store in cache
55
+ this.cache.set(cacheKey, {
56
+ result,
57
+ timestamp: Date.now(),
58
+ });
59
+ return result;
60
+ }
61
+ getCacheKey(diffText, context, model) {
62
+ const content = `${model}:${context || ''}:${diffText}`;
63
+ return createHash('sha256').update(content).digest('hex').slice(0, 16);
64
+ }
65
+ getFromCache(key) {
66
+ const entry = this.cache.get(key);
67
+ if (!entry)
68
+ return null;
69
+ // Check if cache is still valid
70
+ if (Date.now() - entry.timestamp > CACHE_TTL_MS) {
71
+ this.cache.delete(key);
72
+ return null;
73
+ }
74
+ return entry.result;
75
+ }
76
+ formatDiffsForPrompt(diffs) {
77
+ const formattedDiffs = [];
78
+ let totalChars = 0;
79
+ for (const diff of diffs) {
80
+ if (diff.isBinary) {
81
+ formattedDiffs.push(`File: ${diff.path}\n[Binary file]`);
82
+ continue;
83
+ }
84
+ const hunksContent = diff.hunks.map((h) => h.content).join('\n');
85
+ let fileContent = hunksContent;
86
+ // Truncate individual file if too large
87
+ if (fileContent.length > MAX_DIFF_CHARS_PER_FILE) {
88
+ fileContent = fileContent.slice(0, MAX_DIFF_CHARS_PER_FILE) + '\n... [truncated]';
89
+ }
90
+ const formatted = `File: ${diff.path}\n${fileContent}`;
91
+ // Check if adding this would exceed total limit
92
+ if (totalChars + formatted.length > MAX_TOTAL_DIFF_CHARS) {
93
+ formattedDiffs.push(`... and ${diffs.length - formattedDiffs.length} more files`);
94
+ break;
95
+ }
96
+ formattedDiffs.push(formatted);
97
+ totalChars += formatted.length;
98
+ }
99
+ return formattedDiffs.join('\n\n---\n\n');
100
+ }
101
+ buildPrompt(diffText, context) {
102
+ return `You are a helpful assistant that generates concise, descriptive git commit messages.
103
+
104
+ Analyze the following git diff and generate a commit message following these guidelines:
105
+ - Use conventional commit format when appropriate (feat:, fix:, docs:, refactor:, etc.)
106
+ - Keep the summary line under 72 characters
107
+ - Focus on WHAT changed and WHY, not HOW
108
+ - Be specific but concise
109
+
110
+ ${context ? `Additional context from the user: ${context}\n\n` : ''}
111
+ Git diff:
112
+ \`\`\`
113
+ ${diffText}
114
+ \`\`\`
115
+
116
+ Respond in this exact JSON format:
117
+ {
118
+ "summary": "the commit summary line",
119
+ "description": "optional extended description if the changes are complex"
120
+ }`;
121
+ }
122
+ parseResponse(response) {
123
+ const content = response.content[0];
124
+ if (content.type !== 'text') {
125
+ throw new Error('Unexpected response format');
126
+ }
127
+ const tokenUsage = {
128
+ inputTokens: response.usage.input_tokens,
129
+ outputTokens: response.usage.output_tokens,
130
+ };
131
+ // Parse JSON from response
132
+ const jsonMatch = content.text.match(/\{[\s\S]*\}/);
133
+ if (!jsonMatch) {
134
+ // Fallback: use the raw text as summary
135
+ return { summary: content.text.trim().slice(0, 72), tokenUsage };
136
+ }
137
+ const parsed = JSON.parse(jsonMatch[0]);
138
+ return {
139
+ summary: parsed.summary || 'Update code',
140
+ description: parsed.description,
141
+ tokenUsage,
142
+ };
143
+ }
144
+ }
145
+ //# sourceMappingURL=commitSummary.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"commitSummary.js","sourceRoot":"","sources":["../../src/ai/commitSummary.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ import { type License } from '@sumicom/quicksave-shared';
2
+ export interface AgentConfig {
3
+ agentId: string;
4
+ keyPair: {
5
+ publicKey: string;
6
+ secretKey: string;
7
+ };
8
+ license?: License;
9
+ signalingServer: string;
10
+ anthropicApiKey?: string;
11
+ }
12
+ export declare function ensureConfigDir(): void;
13
+ export declare function loadConfig(): AgentConfig | null;
14
+ export declare function saveConfig(config: AgentConfig): void;
15
+ export declare function createDefaultConfig(signalingServer: string): AgentConfig;
16
+ export declare function getOrCreateConfig(signalingServer: string): AgentConfig;
17
+ export declare function addLicense(license: License): void;
18
+ export declare function getConfigPath(): string;
19
+ export declare function getAnthropicApiKey(): string | undefined;
20
+ export declare function setAnthropicApiKey(apiKey: string): void;
21
+ export declare function hasAnthropicApiKey(): boolean;
22
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAIA,OAAO,EAAmB,KAAK,OAAO,EAAE,MAAM,2BAA2B,CAAC;AAE1E,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE;QACP,SAAS,EAAE,MAAM,CAAC;QAClB,SAAS,EAAE,MAAM,CAAC;KACnB,CAAC;IACF,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,eAAe,EAAE,MAAM,CAAC;IACxB,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAKD,wBAAgB,eAAe,IAAI,IAAI,CAItC;AAED,wBAAgB,UAAU,IAAI,WAAW,GAAG,IAAI,CAU/C;AAED,wBAAgB,UAAU,CAAC,MAAM,EAAE,WAAW,GAAG,IAAI,CAGpD;AAED,wBAAgB,mBAAmB,CAAC,eAAe,EAAE,MAAM,GAAG,WAAW,CAQxE;AAED,wBAAgB,iBAAiB,CAAC,eAAe,EAAE,MAAM,GAAG,WAAW,CActE;AAED,wBAAgB,UAAU,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAMjD;AAED,wBAAgB,aAAa,IAAI,MAAM,CAEtC;AAGD,wBAAgB,kBAAkB,IAAI,MAAM,GAAG,SAAS,CAEvD;AAED,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAMvD;AAED,wBAAgB,kBAAkB,IAAI,OAAO,CAE5C"}
package/dist/config.js ADDED
@@ -0,0 +1,76 @@
1
+ import { readFileSync, writeFileSync, existsSync, mkdirSync } from 'fs';
2
+ import { homedir } from 'os';
3
+ import { join } from 'path';
4
+ import { generateAgentKeyPair } from './connection/connection.js';
5
+ import { generateAgentId } from '@sumicom/quicksave-shared';
6
+ const CONFIG_DIR = join(homedir(), '.quicksave');
7
+ const CONFIG_FILE = join(CONFIG_DIR, 'agent.json');
8
+ export function ensureConfigDir() {
9
+ if (!existsSync(CONFIG_DIR)) {
10
+ mkdirSync(CONFIG_DIR, { recursive: true });
11
+ }
12
+ }
13
+ export function loadConfig() {
14
+ try {
15
+ if (existsSync(CONFIG_FILE)) {
16
+ const data = readFileSync(CONFIG_FILE, 'utf-8');
17
+ return JSON.parse(data);
18
+ }
19
+ }
20
+ catch (error) {
21
+ console.error('Failed to load config:', error);
22
+ }
23
+ return null;
24
+ }
25
+ export function saveConfig(config) {
26
+ ensureConfigDir();
27
+ writeFileSync(CONFIG_FILE, JSON.stringify(config, null, 2));
28
+ }
29
+ export function createDefaultConfig(signalingServer) {
30
+ const config = {
31
+ agentId: generateAgentId(),
32
+ keyPair: generateAgentKeyPair(),
33
+ signalingServer,
34
+ };
35
+ saveConfig(config);
36
+ return config;
37
+ }
38
+ export function getOrCreateConfig(signalingServer) {
39
+ let config = loadConfig();
40
+ if (!config) {
41
+ console.log('No existing config found, generating new identity...');
42
+ config = createDefaultConfig(signalingServer);
43
+ console.log('New agent identity created');
44
+ }
45
+ else if (config.signalingServer !== signalingServer) {
46
+ // Update signaling server if changed
47
+ config.signalingServer = signalingServer;
48
+ saveConfig(config);
49
+ }
50
+ return config;
51
+ }
52
+ export function addLicense(license) {
53
+ const config = loadConfig();
54
+ if (config) {
55
+ config.license = license;
56
+ saveConfig(config);
57
+ }
58
+ }
59
+ export function getConfigPath() {
60
+ return CONFIG_FILE;
61
+ }
62
+ // Anthropic API Key helpers
63
+ export function getAnthropicApiKey() {
64
+ return loadConfig()?.anthropicApiKey;
65
+ }
66
+ export function setAnthropicApiKey(apiKey) {
67
+ const config = loadConfig();
68
+ if (config) {
69
+ config.anthropicApiKey = apiKey;
70
+ saveConfig(config);
71
+ }
72
+ }
73
+ export function hasAnthropicApiKey() {
74
+ return !!loadConfig()?.anthropicApiKey;
75
+ }
76
+ //# 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,54 @@
1
+ import { EventEmitter } from 'events';
2
+ import { type Message } from '@sumicom/quicksave-shared';
3
+ export interface ConnectionConfig {
4
+ signalingServer: string;
5
+ agentId: string;
6
+ keyPair: {
7
+ publicKey: string;
8
+ secretKey: string;
9
+ };
10
+ }
11
+ export interface WebRTCConnectionEvents {
12
+ connected: () => void;
13
+ disconnected: () => void;
14
+ message: (message: Message) => void;
15
+ error: (error: Error) => void;
16
+ }
17
+ export declare class WebRTCConnection extends EventEmitter {
18
+ private config;
19
+ private signaling;
20
+ private keyPair;
21
+ private sessionDEK;
22
+ private isConnected;
23
+ private static readonly KEY_EXCHANGE_MAX_AGE_MS;
24
+ constructor(config: ConnectionConfig);
25
+ private setupSignalingHandlers;
26
+ start(): Promise<void>;
27
+ private handleDataMessage;
28
+ /**
29
+ * Check if key exchange has completed
30
+ */
31
+ private isKeyExchangeComplete;
32
+ /**
33
+ * Get the encryption key
34
+ */
35
+ private getEncryptionKey;
36
+ /**
37
+ * Handle key exchange message
38
+ */
39
+ private handleKeyExchange;
40
+ send(message: Message): void;
41
+ private sendRaw;
42
+ private handlePeerDisconnected;
43
+ disconnect(): void;
44
+ getPublicKey(): string;
45
+ getAgentId(): string;
46
+ }
47
+ /**
48
+ * Generate and encode a new key pair for the agent
49
+ */
50
+ export declare function generateAgentKeyPair(): {
51
+ publicKey: string;
52
+ secretKey: string;
53
+ };
54
+ //# sourceMappingURL=connection.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"connection.d.ts","sourceRoot":"","sources":["../../src/connection/connection.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAGtC,OAAO,EASL,KAAK,OAAO,EAGb,MAAM,2BAA2B,CAAC;AAMnC,MAAM,WAAW,gBAAgB;IAC/B,eAAe,EAAE,MAAM,CAAC;IACxB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC;CACnD;AAED,MAAM,WAAW,sBAAsB;IACrC,SAAS,EAAE,MAAM,IAAI,CAAC;IACtB,YAAY,EAAE,MAAM,IAAI,CAAC;IACzB,OAAO,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;IACpC,KAAK,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;CAC/B;AAED,qBAAa,gBAAiB,SAAQ,YAAY;IAChD,OAAO,CAAC,MAAM,CAAmB;IACjC,OAAO,CAAC,SAAS,CAAkB;IACnC,OAAO,CAAC,OAAO,CAAU;IAEzB,OAAO,CAAC,UAAU,CAA2B;IAC7C,OAAO,CAAC,WAAW,CAAS;IAG5B,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,uBAAuB,CAAS;gBAE5C,MAAM,EAAE,gBAAgB;IAQpC,OAAO,CAAC,sBAAsB;IAkBxB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;YAQd,iBAAiB;IAoC/B;;OAEG;IACH,OAAO,CAAC,qBAAqB;IAI7B;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAIxB;;OAEG;YACW,iBAAiB;IAwC/B,IAAI,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;IAgB5B,OAAO,CAAC,OAAO;IAIf,OAAO,CAAC,sBAAsB;IAY9B,UAAU,IAAI,IAAI;IAIlB,YAAY,IAAI,MAAM;IAItB,UAAU,IAAI,MAAM;CAGrB;AAED;;GAEG;AACH,wBAAgB,oBAAoB,IAAI;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAE/E"}
@@ -0,0 +1,171 @@
1
+ import { EventEmitter } from 'events';
2
+ import { gzip, gunzip } from 'zlib';
3
+ import { promisify } from 'util';
4
+ import { generateKeyPair, encodeKeyPair, decodeKeyPair, encryptWithSharedSecret, decryptWithSharedSecret, decryptDEK, parseMessage, serializeMessage, } from '@sumicom/quicksave-shared';
5
+ import { SignalingClient } from './signaling.js';
6
+ const gzipAsync = promisify(gzip);
7
+ const gunzipAsync = promisify(gunzip);
8
+ export class WebRTCConnection extends EventEmitter {
9
+ config;
10
+ signaling;
11
+ keyPair;
12
+ // Session DEK for encryption (received encrypted from PWA)
13
+ sessionDEK = null;
14
+ isConnected = false;
15
+ // Key exchange replay protection
16
+ static KEY_EXCHANGE_MAX_AGE_MS = 60000; // 60 seconds
17
+ constructor(config) {
18
+ super();
19
+ this.config = config;
20
+ this.keyPair = decodeKeyPair(config.keyPair);
21
+ this.signaling = new SignalingClient(config.signalingServer, config.agentId);
22
+ this.setupSignalingHandlers();
23
+ }
24
+ setupSignalingHandlers() {
25
+ this.signaling.on('peer-connected', () => {
26
+ console.log('PWA peer connected, waiting for key exchange...');
27
+ });
28
+ this.signaling.on('data', (data) => {
29
+ this.handleDataMessage(data);
30
+ });
31
+ this.signaling.on('peer-disconnected', () => {
32
+ this.handlePeerDisconnected();
33
+ });
34
+ this.signaling.on('error', (error) => {
35
+ this.emit('error', error);
36
+ });
37
+ }
38
+ async start() {
39
+ console.log('Connecting to signaling server...');
40
+ await this.signaling.connect();
41
+ console.log('Connected to signaling server');
42
+ console.log(`Agent ID: ${this.config.agentId}`);
43
+ console.log(`Public Key: ${this.config.keyPair.publicKey}`);
44
+ }
45
+ async handleDataMessage(data) {
46
+ try {
47
+ // Handle key exchange (uncompressed JSON) vs encrypted messages (base64 compressed)
48
+ if (!this.isKeyExchangeComplete()) {
49
+ // Try to parse as key exchange message
50
+ try {
51
+ const keyExchange = JSON.parse(data);
52
+ if (keyExchange.type === 'key-exchange') {
53
+ await this.handleKeyExchange(keyExchange);
54
+ return;
55
+ }
56
+ }
57
+ catch {
58
+ // Not a key exchange message, ignore until key exchange completes
59
+ console.error('Received message before key exchange');
60
+ return;
61
+ }
62
+ }
63
+ // Post key-exchange: messages are encrypted, then the plaintext was compressed before encryption
64
+ // Decrypt first, then decompress
65
+ const encryptionKey = this.getEncryptionKey();
66
+ if (!encryptionKey) {
67
+ console.error('No encryption key, cannot decrypt message');
68
+ return;
69
+ }
70
+ const decrypted = decryptWithSharedSecret(data, encryptionKey);
71
+ const buffer = Buffer.from(decrypted, 'base64');
72
+ const decompressed = await gunzipAsync(buffer);
73
+ const message = parseMessage(decompressed.toString('utf-8'));
74
+ this.emit('message', message);
75
+ }
76
+ catch (error) {
77
+ console.error('Failed to handle message:', error);
78
+ }
79
+ }
80
+ /**
81
+ * Check if key exchange has completed
82
+ */
83
+ isKeyExchangeComplete() {
84
+ return this.sessionDEK !== null;
85
+ }
86
+ /**
87
+ * Get the encryption key
88
+ */
89
+ getEncryptionKey() {
90
+ return this.sessionDEK;
91
+ }
92
+ /**
93
+ * Handle key exchange message
94
+ */
95
+ async handleKeyExchange(message) {
96
+ // Verify timestamp for replay protection
97
+ const age = Date.now() - message.timestamp;
98
+ if (age > WebRTCConnection.KEY_EXCHANGE_MAX_AGE_MS) {
99
+ console.error(`Key exchange expired (age: ${age}ms)`);
100
+ this.emit('error', new Error('Key exchange expired'));
101
+ return;
102
+ }
103
+ if (age < -5000) {
104
+ // Allow 5 second clock skew into the future
105
+ console.error(`Key exchange timestamp in future (age: ${age}ms)`);
106
+ this.emit('error', new Error('Key exchange timestamp invalid'));
107
+ return;
108
+ }
109
+ // Decrypt the session DEK
110
+ try {
111
+ this.sessionDEK = decryptDEK(message.encryptedDEK, this.keyPair.secretKey);
112
+ console.log('Key exchange complete, connection encrypted');
113
+ // Mark as connected
114
+ if (!this.isConnected) {
115
+ this.isConnected = true;
116
+ this.emit('connected');
117
+ }
118
+ // V2: Send acknowledgment
119
+ this.sendRaw(JSON.stringify({
120
+ type: 'key-exchange-ack',
121
+ version: 2,
122
+ }));
123
+ }
124
+ catch (error) {
125
+ console.error('Failed to decrypt session DEK:', error);
126
+ this.emit('error', new Error('Failed to decrypt session DEK'));
127
+ }
128
+ }
129
+ send(message) {
130
+ const encryptionKey = this.getEncryptionKey();
131
+ if (!encryptionKey) {
132
+ console.error('No encryption key, cannot encrypt message');
133
+ return;
134
+ }
135
+ // Compress before encryption for better compression ratio
136
+ const serialized = serializeMessage(message);
137
+ gzipAsync(Buffer.from(serialized)).then((compressed) => {
138
+ const compressedBase64 = compressed.toString('base64');
139
+ const encrypted = encryptWithSharedSecret(compressedBase64, encryptionKey);
140
+ this.signaling.sendData(encrypted);
141
+ });
142
+ }
143
+ sendRaw(data) {
144
+ this.signaling.sendData(data);
145
+ }
146
+ handlePeerDisconnected() {
147
+ if (this.isConnected) {
148
+ this.isConnected = false;
149
+ this.emit('disconnected');
150
+ }
151
+ // Clean up encryption state for next connection
152
+ this.sessionDEK = null;
153
+ console.log('Peer disconnected, waiting for new connection...');
154
+ }
155
+ disconnect() {
156
+ this.signaling.disconnect();
157
+ }
158
+ getPublicKey() {
159
+ return this.config.keyPair.publicKey;
160
+ }
161
+ getAgentId() {
162
+ return this.config.agentId;
163
+ }
164
+ }
165
+ /**
166
+ * Generate and encode a new key pair for the agent
167
+ */
168
+ export function generateAgentKeyPair() {
169
+ return encodeKeyPair(generateKeyPair());
170
+ }
171
+ //# sourceMappingURL=connection.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"connection.js","sourceRoot":"","sources":["../../src/connection/connection.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,31 @@
1
+ import { EventEmitter } from 'events';
2
+ export interface SignalingEvents {
3
+ 'peer-connected': () => void;
4
+ 'peer-disconnected': () => void;
5
+ data: (data: string) => void;
6
+ connected: () => void;
7
+ disconnected: () => void;
8
+ error: (error: Error) => void;
9
+ }
10
+ export declare class SignalingClient extends EventEmitter {
11
+ private ws;
12
+ private url;
13
+ private agentId;
14
+ private reconnectAttempts;
15
+ private maxReconnectAttempts;
16
+ private reconnectDelay;
17
+ private isConnected;
18
+ constructor(signalingServer: string, agentId: string);
19
+ connect(): Promise<void>;
20
+ private handleMessage;
21
+ sendBye(): void;
22
+ sendData(data: string): void;
23
+ private compress;
24
+ private decompress;
25
+ private send;
26
+ private attemptReconnect;
27
+ disconnect(): void;
28
+ getAgentId(): string;
29
+ getConnectionUrl(): string;
30
+ }
31
+ //# sourceMappingURL=signaling.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"signaling.d.ts","sourceRoot":"","sources":["../../src/connection/signaling.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAQtC,MAAM,WAAW,eAAe;IAC9B,gBAAgB,EAAE,MAAM,IAAI,CAAC;IAC7B,mBAAmB,EAAE,MAAM,IAAI,CAAC;IAChC,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAC7B,SAAS,EAAE,MAAM,IAAI,CAAC;IACtB,YAAY,EAAE,MAAM,IAAI,CAAC;IACzB,KAAK,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;CAC/B;AAED,qBAAa,eAAgB,SAAQ,YAAY;IAC/C,OAAO,CAAC,EAAE,CAA0B;IACpC,OAAO,CAAC,GAAG,CAAS;IACpB,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,iBAAiB,CAAK;IAC9B,OAAO,CAAC,oBAAoB,CAAK;IACjC,OAAO,CAAC,cAAc,CAAQ;IAC9B,OAAO,CAAC,WAAW,CAAS;gBAEhB,eAAe,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM;IAMpD,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAqDxB,OAAO,CAAC,aAAa;IAmBrB,OAAO,IAAI,IAAI;IAIf,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;YAQd,QAAQ;YAKR,UAAU;IAMxB,OAAO,CAAC,IAAI;IASZ,OAAO,CAAC,gBAAgB;IAkBxB,UAAU,IAAI,IAAI;IASlB,UAAU,IAAI,MAAM;IAIpB,gBAAgB,IAAI,MAAM;CAG3B"}