hanzi-browse 2.2.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 (78) hide show
  1. package/README.md +182 -0
  2. package/dist/agent/loop.d.ts +63 -0
  3. package/dist/agent/loop.js +186 -0
  4. package/dist/agent/system-prompt.d.ts +7 -0
  5. package/dist/agent/system-prompt.js +41 -0
  6. package/dist/agent/tools.d.ts +9 -0
  7. package/dist/agent/tools.js +154 -0
  8. package/dist/cli/detect-credentials.d.ts +31 -0
  9. package/dist/cli/detect-credentials.js +44 -0
  10. package/dist/cli/import-credentials-handler.d.ts +14 -0
  11. package/dist/cli/import-credentials-handler.js +22 -0
  12. package/dist/cli/session-files.d.ts +28 -0
  13. package/dist/cli/session-files.js +118 -0
  14. package/dist/cli/setup.d.ts +10 -0
  15. package/dist/cli/setup.js +915 -0
  16. package/dist/cli.d.ts +16 -0
  17. package/dist/cli.js +506 -0
  18. package/dist/dashboard/assets/index-CEFyesbT.js +46 -0
  19. package/dist/dashboard/assets/index-Dnht2kLU.css +1 -0
  20. package/dist/dashboard/index.html +13 -0
  21. package/dist/index.d.ts +2 -0
  22. package/dist/index.js +1116 -0
  23. package/dist/ipc/index.d.ts +8 -0
  24. package/dist/ipc/index.js +8 -0
  25. package/dist/ipc/native-host.d.ts +96 -0
  26. package/dist/ipc/native-host.js +223 -0
  27. package/dist/ipc/websocket-client.d.ts +73 -0
  28. package/dist/ipc/websocket-client.js +199 -0
  29. package/dist/license/manager.d.ts +20 -0
  30. package/dist/license/manager.js +15 -0
  31. package/dist/llm/client.d.ts +72 -0
  32. package/dist/llm/client.js +227 -0
  33. package/dist/llm/credentials.d.ts +61 -0
  34. package/dist/llm/credentials.js +200 -0
  35. package/dist/llm/vertex.d.ts +22 -0
  36. package/dist/llm/vertex.js +335 -0
  37. package/dist/managed/api-http.test.d.ts +7 -0
  38. package/dist/managed/api-http.test.js +623 -0
  39. package/dist/managed/api.d.ts +51 -0
  40. package/dist/managed/api.js +1448 -0
  41. package/dist/managed/api.test.d.ts +10 -0
  42. package/dist/managed/api.test.js +146 -0
  43. package/dist/managed/auth.d.ts +38 -0
  44. package/dist/managed/auth.js +192 -0
  45. package/dist/managed/billing.d.ts +70 -0
  46. package/dist/managed/billing.js +227 -0
  47. package/dist/managed/deploy.d.ts +17 -0
  48. package/dist/managed/deploy.js +385 -0
  49. package/dist/managed/e2e.test.d.ts +15 -0
  50. package/dist/managed/e2e.test.js +151 -0
  51. package/dist/managed/hardening.test.d.ts +14 -0
  52. package/dist/managed/hardening.test.js +346 -0
  53. package/dist/managed/integration.test.d.ts +8 -0
  54. package/dist/managed/integration.test.js +274 -0
  55. package/dist/managed/log.d.ts +18 -0
  56. package/dist/managed/log.js +31 -0
  57. package/dist/managed/server.d.ts +12 -0
  58. package/dist/managed/server.js +69 -0
  59. package/dist/managed/store-pg.d.ts +191 -0
  60. package/dist/managed/store-pg.js +479 -0
  61. package/dist/managed/store.d.ts +188 -0
  62. package/dist/managed/store.js +379 -0
  63. package/dist/relay/auto-start.d.ts +19 -0
  64. package/dist/relay/auto-start.js +71 -0
  65. package/dist/relay/server.d.ts +17 -0
  66. package/dist/relay/server.js +403 -0
  67. package/dist/types/index.d.ts +5 -0
  68. package/dist/types/index.js +4 -0
  69. package/dist/types/session.d.ts +134 -0
  70. package/dist/types/session.js +16 -0
  71. package/package.json +61 -0
  72. package/skills/README.md +48 -0
  73. package/skills/a11y-auditor/SKILL.md +42 -0
  74. package/skills/e2e-tester/SKILL.md +154 -0
  75. package/skills/hanzi-browse/SKILL.md +182 -0
  76. package/skills/linkedin-prospector/SKILL.md +149 -0
  77. package/skills/social-poster/SKILL.md +146 -0
  78. package/skills/x-marketer/SKILL.md +479 -0
@@ -0,0 +1,8 @@
1
+ /**
2
+ * IPC Module - Communication with Chrome Extension
3
+ *
4
+ * WebSocketClient is the primary transport for MCP traffic.
5
+ * NativeHostConnection is retained only for legacy utility flows.
6
+ */
7
+ export { WebSocketClient, type WebSocketClientOptions } from './websocket-client.js';
8
+ export { NativeHostConnection, type NativeMessage, type MessageHandler, type ConnectionOptions, type OutgoingMessageType, type IncomingMessageType, } from './native-host.js';
@@ -0,0 +1,8 @@
1
+ /**
2
+ * IPC Module - Communication with Chrome Extension
3
+ *
4
+ * WebSocketClient is the primary transport for MCP traffic.
5
+ * NativeHostConnection is retained only for legacy utility flows.
6
+ */
7
+ export { WebSocketClient } from './websocket-client.js';
8
+ export { NativeHostConnection, } from './native-host.js';
@@ -0,0 +1,96 @@
1
+ /**
2
+ * Native Host IPC Module
3
+ *
4
+ * Handles communication with the installed native host via Chrome native
5
+ * messaging protocol.
6
+ *
7
+ * Protocol: Chrome Native Messaging (4-byte little-endian length prefix + JSON)
8
+ *
9
+ * This transport is no longer used for MCP task delivery. It remains for
10
+ * native-host-backed utilities such as credential reads, debug logging, and
11
+ * API proxy support.
12
+ */
13
+ /** Message types sent TO the native host */
14
+ export type OutgoingMessageType = 'ping' | 'debug_log' | 'agent_log' | 'check_file' | 'read_cli_credentials' | 'read_codex_credentials' | 'proxy_api_call';
15
+ /** Message types received FROM the native host */
16
+ export type IncomingMessageType = 'pong' | 'debug_logged' | 'file_check_result' | 'cli_credentials' | 'codex_credentials' | 'credentials_not_found' | 'api_response' | 'api_error' | 'error';
17
+ /** Base message structure */
18
+ export interface NativeMessage {
19
+ type: string;
20
+ sessionId?: string;
21
+ requestId?: string;
22
+ [key: string]: any;
23
+ }
24
+ /** Callback for handling incoming messages */
25
+ export type MessageHandler = (message: NativeMessage) => void | Promise<void>;
26
+ /** Connection options */
27
+ export interface ConnectionOptions {
28
+ /** Custom path to native host executable */
29
+ hostPath?: string;
30
+ /** Callback when connection is lost */
31
+ onDisconnect?: (code: number | null) => void;
32
+ /** Callback for native host stderr output */
33
+ onStderr?: (data: string) => void;
34
+ }
35
+ /**
36
+ * Manages a connection to the native host process.
37
+ *
38
+ * Usage:
39
+ * const conn = new NativeHostConnection();
40
+ * conn.onMessage((msg) => console.log('Received:', msg));
41
+ * await conn.connect();
42
+ * await conn.send({ type: 'ping' });
43
+ */
44
+ export declare class NativeHostConnection {
45
+ private process;
46
+ private messageBuffer;
47
+ private messageHandlers;
48
+ private options;
49
+ private connected;
50
+ constructor(options?: ConnectionOptions);
51
+ /**
52
+ * Find the native host executable path from the installed Chrome manifest
53
+ */
54
+ private findHostPath;
55
+ /**
56
+ * Register a handler for incoming messages
57
+ */
58
+ onMessage(handler: MessageHandler): void;
59
+ /**
60
+ * Remove a message handler
61
+ */
62
+ offMessage(handler: MessageHandler): void;
63
+ /**
64
+ * Connect to the native host process
65
+ */
66
+ connect(): Promise<void>;
67
+ /**
68
+ * Process buffered messages using the native messaging protocol
69
+ * (4-byte little-endian length prefix + JSON payload)
70
+ */
71
+ private processMessages;
72
+ /**
73
+ * Dispatch a message to all registered handlers
74
+ */
75
+ private dispatchMessage;
76
+ /**
77
+ * Send a message to the native host
78
+ */
79
+ send(message: NativeMessage): Promise<void>;
80
+ /**
81
+ * Check if connected to native host
82
+ */
83
+ isConnected(): boolean;
84
+ /**
85
+ * Disconnect from the native host
86
+ */
87
+ disconnect(): void;
88
+ }
89
+ /**
90
+ * Get the default native host connection (creates one if needed)
91
+ */
92
+ export declare function getDefaultConnection(): NativeHostConnection;
93
+ /**
94
+ * Reset the default connection (useful for testing)
95
+ */
96
+ export declare function resetDefaultConnection(): void;
@@ -0,0 +1,223 @@
1
+ /**
2
+ * Native Host IPC Module
3
+ *
4
+ * Handles communication with the installed native host via Chrome native
5
+ * messaging protocol.
6
+ *
7
+ * Protocol: Chrome Native Messaging (4-byte little-endian length prefix + JSON)
8
+ *
9
+ * This transport is no longer used for MCP task delivery. It remains for
10
+ * native-host-backed utilities such as credential reads, debug logging, and
11
+ * API proxy support.
12
+ */
13
+ import { spawn } from 'child_process';
14
+ import { existsSync, readFileSync } from 'fs';
15
+ import { join } from 'path';
16
+ import { homedir } from 'os';
17
+ // ============================================================================
18
+ // Native Host Connection Class
19
+ // ============================================================================
20
+ /**
21
+ * Manages a connection to the native host process.
22
+ *
23
+ * Usage:
24
+ * const conn = new NativeHostConnection();
25
+ * conn.onMessage((msg) => console.log('Received:', msg));
26
+ * await conn.connect();
27
+ * await conn.send({ type: 'ping' });
28
+ */
29
+ export class NativeHostConnection {
30
+ process = null;
31
+ messageBuffer = Buffer.alloc(0);
32
+ messageHandlers = [];
33
+ options;
34
+ connected = false;
35
+ constructor(options = {}) {
36
+ this.options = options;
37
+ }
38
+ /**
39
+ * Find the native host executable path from the installed Chrome manifest
40
+ */
41
+ findHostPath() {
42
+ // Check user-provided path first
43
+ if (this.options.hostPath && existsSync(this.options.hostPath)) {
44
+ return this.options.hostPath;
45
+ }
46
+ // Look for Chrome native messaging manifest
47
+ const manifestPath = join(homedir(), 'Library', 'Application Support', 'Google', 'Chrome', 'NativeMessagingHosts', 'com.hanzi_browse.oauth_host.json');
48
+ if (existsSync(manifestPath)) {
49
+ try {
50
+ const manifest = JSON.parse(readFileSync(manifestPath, 'utf8'));
51
+ if (manifest.path && existsSync(manifest.path)) {
52
+ return manifest.path;
53
+ }
54
+ }
55
+ catch {
56
+ // Fall through to error
57
+ }
58
+ }
59
+ throw new Error('Native host not found. Please install the Chrome extension first.\n' +
60
+ 'Expected manifest at: ' + manifestPath);
61
+ }
62
+ /**
63
+ * Register a handler for incoming messages
64
+ */
65
+ onMessage(handler) {
66
+ this.messageHandlers.push(handler);
67
+ }
68
+ /**
69
+ * Remove a message handler
70
+ */
71
+ offMessage(handler) {
72
+ const index = this.messageHandlers.indexOf(handler);
73
+ if (index !== -1) {
74
+ this.messageHandlers.splice(index, 1);
75
+ }
76
+ }
77
+ /**
78
+ * Connect to the native host process
79
+ */
80
+ async connect() {
81
+ if (this.connected && this.process?.stdin?.writable) {
82
+ return; // Already connected
83
+ }
84
+ const hostPath = this.findHostPath();
85
+ console.error(`[NativeHost] Connecting to: ${hostPath}`);
86
+ return new Promise((resolve, reject) => {
87
+ try {
88
+ this.process = spawn(hostPath, [], {
89
+ stdio: ['pipe', 'pipe', 'pipe'],
90
+ });
91
+ this.process.stdout?.on('data', (chunk) => {
92
+ this.messageBuffer = Buffer.concat([this.messageBuffer, chunk]);
93
+ this.processMessages();
94
+ });
95
+ this.process.stderr?.on('data', (data) => {
96
+ const text = data.toString().trim();
97
+ if (this.options.onStderr) {
98
+ this.options.onStderr(text);
99
+ }
100
+ else {
101
+ console.error(`[NativeHost] ${text}`);
102
+ }
103
+ });
104
+ this.process.on('error', (err) => {
105
+ console.error('[NativeHost] Process error:', err.message);
106
+ this.connected = false;
107
+ reject(err);
108
+ });
109
+ this.process.on('close', (code) => {
110
+ console.error(`[NativeHost] Process exited with code: ${code}`);
111
+ this.connected = false;
112
+ this.process = null;
113
+ if (this.options.onDisconnect) {
114
+ this.options.onDisconnect(code);
115
+ }
116
+ });
117
+ this.connected = true;
118
+ // Give the process a moment to initialize
119
+ setTimeout(() => resolve(), 100);
120
+ }
121
+ catch (err) {
122
+ reject(err);
123
+ }
124
+ });
125
+ }
126
+ /**
127
+ * Process buffered messages using the native messaging protocol
128
+ * (4-byte little-endian length prefix + JSON payload)
129
+ */
130
+ processMessages() {
131
+ while (this.messageBuffer.length >= 4) {
132
+ const msgLen = this.messageBuffer.readUInt32LE(0);
133
+ if (this.messageBuffer.length < 4 + msgLen) {
134
+ break; // Wait for more data
135
+ }
136
+ const msgStr = this.messageBuffer.subarray(4, 4 + msgLen).toString();
137
+ this.messageBuffer = this.messageBuffer.subarray(4 + msgLen);
138
+ try {
139
+ const message = JSON.parse(msgStr);
140
+ this.dispatchMessage(message);
141
+ }
142
+ catch (e) {
143
+ console.error('[NativeHost] Failed to parse message:', e);
144
+ console.error('[NativeHost] Raw message (first 200 chars):', msgStr.substring(0, 200));
145
+ }
146
+ }
147
+ }
148
+ /**
149
+ * Dispatch a message to all registered handlers
150
+ */
151
+ async dispatchMessage(message) {
152
+ for (const handler of this.messageHandlers) {
153
+ try {
154
+ await handler(message);
155
+ }
156
+ catch (err) {
157
+ console.error('[NativeHost] Handler error:', err);
158
+ }
159
+ }
160
+ }
161
+ /**
162
+ * Send a message to the native host
163
+ */
164
+ async send(message) {
165
+ if (!this.process?.stdin?.writable) {
166
+ await this.connect();
167
+ }
168
+ const json = JSON.stringify(message);
169
+ const buffer = Buffer.from(json);
170
+ const len = Buffer.alloc(4);
171
+ len.writeUInt32LE(buffer.length, 0);
172
+ try {
173
+ this.process.stdin.write(len);
174
+ this.process.stdin.write(buffer);
175
+ }
176
+ catch (err) {
177
+ console.error('[NativeHost] Send failed:', err.message);
178
+ this.connected = false;
179
+ this.process = null;
180
+ throw new Error(`Failed to send message: ${err.message}`);
181
+ }
182
+ }
183
+ /**
184
+ * Check if connected to native host
185
+ */
186
+ isConnected() {
187
+ return this.connected && !!this.process?.stdin?.writable;
188
+ }
189
+ /**
190
+ * Disconnect from the native host
191
+ */
192
+ disconnect() {
193
+ if (this.process) {
194
+ this.process.kill();
195
+ this.process = null;
196
+ }
197
+ this.connected = false;
198
+ this.messageBuffer = Buffer.alloc(0);
199
+ }
200
+ }
201
+ // ============================================================================
202
+ // Convenience Functions
203
+ // ============================================================================
204
+ /** Singleton instance for simple usage */
205
+ let defaultConnection = null;
206
+ /**
207
+ * Get the default native host connection (creates one if needed)
208
+ */
209
+ export function getDefaultConnection() {
210
+ if (!defaultConnection) {
211
+ defaultConnection = new NativeHostConnection();
212
+ }
213
+ return defaultConnection;
214
+ }
215
+ /**
216
+ * Reset the default connection (useful for testing)
217
+ */
218
+ export function resetDefaultConnection() {
219
+ if (defaultConnection) {
220
+ defaultConnection.disconnect();
221
+ defaultConnection = null;
222
+ }
223
+ }
@@ -0,0 +1,73 @@
1
+ /**
2
+ * WebSocket Client for Relay Communication
3
+ *
4
+ * Drop-in replacement for NativeHostConnection that communicates
5
+ * via the WebSocket relay server instead of native messaging.
6
+ *
7
+ * Same interface: connect(), send(), onMessage(), isConnected(), disconnect()
8
+ */
9
+ import type { NativeMessage, MessageHandler, ConnectionOptions } from './native-host.js';
10
+ type ClientRole = 'mcp' | 'cli';
11
+ export interface WebSocketClientOptions extends ConnectionOptions {
12
+ /** Role to register as with the relay */
13
+ role: ClientRole;
14
+ /** Custom relay URL (defaults to ws://localhost:7862) */
15
+ relayUrl?: string;
16
+ /** Auto-start relay server if not running (default: true) */
17
+ autoStartRelay?: boolean;
18
+ /** Extra fields to include in the register message (e.g., relay_secret) */
19
+ registerExtra?: Record<string, string>;
20
+ }
21
+ /**
22
+ * WebSocket-based connection to the Chrome extension via relay server.
23
+ *
24
+ * Usage:
25
+ * const client = new WebSocketClient({ role: 'mcp' });
26
+ * client.onMessage((msg) => console.log('Received:', msg));
27
+ * await client.connect();
28
+ * await client.send({ type: 'mcp_start_task', sessionId: 'abc', task: '...' });
29
+ */
30
+ export declare class WebSocketClient {
31
+ private ws;
32
+ private messageHandlers;
33
+ private options;
34
+ private connected;
35
+ private reconnectTimer;
36
+ private reconnectAttempts;
37
+ private maxReconnectDelay;
38
+ constructor(options: WebSocketClientOptions);
39
+ /**
40
+ * Register a handler for incoming messages
41
+ */
42
+ onMessage(handler: MessageHandler): void;
43
+ /**
44
+ * Remove a message handler
45
+ */
46
+ offMessage(handler: MessageHandler): void;
47
+ /**
48
+ * Connect to the relay server.
49
+ * Auto-starts the relay if needed.
50
+ */
51
+ connect(): Promise<void>;
52
+ /**
53
+ * Dispatch a message to all registered handlers
54
+ */
55
+ private dispatchMessage;
56
+ /**
57
+ * Send a message to the extension via relay
58
+ */
59
+ send(message: NativeMessage): Promise<void>;
60
+ /**
61
+ * Check if connected to relay
62
+ */
63
+ isConnected(): boolean;
64
+ /**
65
+ * Disconnect from relay
66
+ */
67
+ disconnect(): void;
68
+ /**
69
+ * Schedule a reconnection attempt with exponential backoff
70
+ */
71
+ private scheduleReconnect;
72
+ }
73
+ export {};
@@ -0,0 +1,199 @@
1
+ /**
2
+ * WebSocket Client for Relay Communication
3
+ *
4
+ * Drop-in replacement for NativeHostConnection that communicates
5
+ * via the WebSocket relay server instead of native messaging.
6
+ *
7
+ * Same interface: connect(), send(), onMessage(), isConnected(), disconnect()
8
+ */
9
+ import WebSocket from 'ws';
10
+ import { ensureRelayRunning, getRelayUrl } from '../relay/auto-start.js';
11
+ /**
12
+ * WebSocket-based connection to the Chrome extension via relay server.
13
+ *
14
+ * Usage:
15
+ * const client = new WebSocketClient({ role: 'mcp' });
16
+ * client.onMessage((msg) => console.log('Received:', msg));
17
+ * await client.connect();
18
+ * await client.send({ type: 'mcp_start_task', sessionId: 'abc', task: '...' });
19
+ */
20
+ export class WebSocketClient {
21
+ ws = null;
22
+ messageHandlers = [];
23
+ options;
24
+ connected = false;
25
+ reconnectTimer = null;
26
+ reconnectAttempts = 0;
27
+ maxReconnectDelay = 30000; // Max 30 second backoff
28
+ constructor(options) {
29
+ this.options = {
30
+ autoStartRelay: true,
31
+ ...options,
32
+ };
33
+ }
34
+ /**
35
+ * Register a handler for incoming messages
36
+ */
37
+ onMessage(handler) {
38
+ this.messageHandlers.push(handler);
39
+ }
40
+ /**
41
+ * Remove a message handler
42
+ */
43
+ offMessage(handler) {
44
+ const index = this.messageHandlers.indexOf(handler);
45
+ if (index !== -1) {
46
+ this.messageHandlers.splice(index, 1);
47
+ }
48
+ }
49
+ /**
50
+ * Connect to the relay server.
51
+ * Auto-starts the relay if needed.
52
+ */
53
+ async connect() {
54
+ if (this.connected && this.ws?.readyState === WebSocket.OPEN) {
55
+ return; // Already connected
56
+ }
57
+ const relayUrl = this.options.relayUrl || getRelayUrl();
58
+ // Auto-start relay if configured
59
+ if (this.options.autoStartRelay) {
60
+ try {
61
+ await ensureRelayRunning(relayUrl);
62
+ }
63
+ catch (err) {
64
+ console.error(`[WSClient] Failed to start relay: ${err.message}`);
65
+ throw err;
66
+ }
67
+ }
68
+ return new Promise((resolve, reject) => {
69
+ try {
70
+ console.error(`[WSClient] Connecting to relay: ${relayUrl}`);
71
+ this.ws = new WebSocket(relayUrl);
72
+ const connectTimeout = setTimeout(() => {
73
+ if (!this.connected) {
74
+ this.ws?.terminate();
75
+ reject(new Error('WebSocket connection timed out'));
76
+ }
77
+ }, 5000);
78
+ this.ws.on('open', () => {
79
+ clearTimeout(connectTimeout);
80
+ this.connected = true;
81
+ this.reconnectAttempts = 0;
82
+ // Register with relay
83
+ this.ws.send(JSON.stringify({
84
+ type: 'register',
85
+ role: this.options.role,
86
+ ...this.options.registerExtra,
87
+ }));
88
+ console.error(`[WSClient] Connected as ${this.options.role}`);
89
+ resolve();
90
+ });
91
+ this.ws.on('message', (data) => {
92
+ try {
93
+ const message = JSON.parse(data.toString());
94
+ // Skip relay protocol messages
95
+ if (message.type === 'registered')
96
+ return;
97
+ if (message.type === 'error') {
98
+ console.error(`[WSClient] Relay error: ${message.error}`);
99
+ return;
100
+ }
101
+ this.dispatchMessage(message);
102
+ }
103
+ catch (e) {
104
+ console.error('[WSClient] Failed to parse message:', e);
105
+ }
106
+ });
107
+ this.ws.on('close', () => {
108
+ console.error('[WSClient] Disconnected from relay');
109
+ this.connected = false;
110
+ this.ws = null;
111
+ if (this.options.onDisconnect) {
112
+ this.options.onDisconnect(null);
113
+ }
114
+ // Schedule reconnect with exponential backoff
115
+ this.scheduleReconnect();
116
+ });
117
+ this.ws.on('error', (err) => {
118
+ clearTimeout(connectTimeout);
119
+ console.error(`[WSClient] WebSocket error: ${err.message}`);
120
+ if (!this.connected) {
121
+ reject(err);
122
+ }
123
+ });
124
+ }
125
+ catch (err) {
126
+ reject(err);
127
+ }
128
+ });
129
+ }
130
+ /**
131
+ * Dispatch a message to all registered handlers
132
+ */
133
+ async dispatchMessage(message) {
134
+ for (const handler of this.messageHandlers) {
135
+ try {
136
+ await handler(message);
137
+ }
138
+ catch (err) {
139
+ console.error('[WSClient] Handler error:', err);
140
+ }
141
+ }
142
+ }
143
+ /**
144
+ * Send a message to the extension via relay
145
+ */
146
+ async send(message) {
147
+ if (!this.ws || this.ws.readyState !== WebSocket.OPEN) {
148
+ // Try to reconnect
149
+ try {
150
+ await this.connect();
151
+ }
152
+ catch {
153
+ throw new Error('Not connected to relay and reconnection failed');
154
+ }
155
+ }
156
+ this.ws.send(JSON.stringify(message));
157
+ }
158
+ /**
159
+ * Check if connected to relay
160
+ */
161
+ isConnected() {
162
+ return this.connected && this.ws?.readyState === WebSocket.OPEN;
163
+ }
164
+ /**
165
+ * Disconnect from relay
166
+ */
167
+ disconnect() {
168
+ if (this.reconnectTimer) {
169
+ clearTimeout(this.reconnectTimer);
170
+ this.reconnectTimer = null;
171
+ }
172
+ if (this.ws) {
173
+ this.ws.close();
174
+ this.ws = null;
175
+ }
176
+ this.connected = false;
177
+ }
178
+ /**
179
+ * Schedule a reconnection attempt with exponential backoff
180
+ */
181
+ scheduleReconnect() {
182
+ if (this.reconnectTimer)
183
+ return;
184
+ const delay = Math.min(1000 * Math.pow(2, this.reconnectAttempts), this.maxReconnectDelay);
185
+ this.reconnectAttempts++;
186
+ console.error(`[WSClient] Reconnecting in ${delay}ms (attempt ${this.reconnectAttempts})`);
187
+ this.reconnectTimer = setTimeout(async () => {
188
+ this.reconnectTimer = null;
189
+ try {
190
+ await this.connect();
191
+ console.error('[WSClient] Reconnected successfully');
192
+ }
193
+ catch (err) {
194
+ console.error(`[WSClient] Reconnection failed: ${err.message}`);
195
+ // onclose handler will schedule next attempt
196
+ }
197
+ }, delay);
198
+ }
199
+ }
@@ -0,0 +1,20 @@
1
+ /**
2
+ * License Manager for MCP Server (BYOM mode)
3
+ *
4
+ * BYOM is free and unlimited — no license check needed.
5
+ * Managed mode uses the per-task credit system in api.ts instead.
6
+ *
7
+ * This file is kept for backwards compatibility (index.ts imports it)
8
+ * but always returns "allowed".
9
+ */
10
+ export declare function checkAndIncrementUsage(): Promise<{
11
+ allowed: boolean;
12
+ remaining: number | null;
13
+ message: string;
14
+ }>;
15
+ export declare function getLicenseStatus(): {
16
+ isPro: boolean;
17
+ tasksUsed: number;
18
+ taskLimit: number | null;
19
+ message: string;
20
+ };
@@ -0,0 +1,15 @@
1
+ /**
2
+ * License Manager for MCP Server (BYOM mode)
3
+ *
4
+ * BYOM is free and unlimited — no license check needed.
5
+ * Managed mode uses the per-task credit system in api.ts instead.
6
+ *
7
+ * This file is kept for backwards compatibility (index.ts imports it)
8
+ * but always returns "allowed".
9
+ */
10
+ export async function checkAndIncrementUsage() {
11
+ return { allowed: true, remaining: null, message: "BYOM — unlimited tasks" };
12
+ }
13
+ export function getLicenseStatus() {
14
+ return { isPro: true, tasksUsed: 0, taskLimit: null, message: "BYOM — Free, unlimited" };
15
+ }