opencommand-plugin 0.0.1 → 0.0.2

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/index.d.ts CHANGED
@@ -1,45 +1,29 @@
1
1
  export interface ProxyConfig {
2
2
  port: number;
3
- sessionToken: string;
3
+ commandCodeToken: string;
4
+ sessionCookie?: string;
5
+ }
6
+ export interface ProxyStartConfig {
7
+ commandCodeToken: string;
8
+ sessionCookie?: string;
9
+ }
10
+ interface CookiePair {
11
+ name: string;
12
+ value: string;
4
13
  }
5
14
  export declare class ProxyManager {
6
15
  private proxyProcess;
7
16
  private config;
8
17
  private proxyBinaryPath;
9
18
  constructor(binaryPath: string);
10
- /**
11
- * Find an available port (dynamic allocation)
12
- */
13
19
  findAvailablePort(): Promise<number>;
14
- /**
15
- * Start the proxy server
16
- */
17
- start(sessionToken: string): Promise<ProxyConfig>;
18
- /**
19
- * Stop the proxy server
20
- */
20
+ start(startConfig: ProxyStartConfig): Promise<ProxyConfig>;
21
21
  stop(): Promise<void>;
22
- /**
23
- * Wait for proxy to be healthy
24
- */
25
22
  private waitForHealthz;
26
- /**
27
- * Get current proxy configuration
28
- */
29
23
  getConfig(): ProxyConfig | null;
30
- /**
31
- * Get proxy base URL
32
- */
33
24
  getBaseUrl(): string | null;
34
- /**
35
- * Check if proxy is running
36
- */
37
25
  isRunning(): boolean;
38
26
  }
39
- /**
40
- * File-based persistent secret storage.
41
- * Fix: Persists session token across plugin restarts (not instance-local Map).
42
- */
43
27
  export declare class SecretStorage {
44
28
  private filePath;
45
29
  constructor(storageDir?: string);
@@ -49,38 +33,36 @@ export declare class SecretStorage {
49
33
  get(key: string): Promise<string | undefined>;
50
34
  delete(key: string): Promise<void>;
51
35
  }
52
- /**
53
- * OpenCommand Plugin Main Class
54
- */
36
+ export declare class BrowserCookieExtractor {
37
+ private readonly homeDir;
38
+ constructor(homeDir?: string);
39
+ extractCommandCodeCookie(): Promise<string | undefined>;
40
+ static buildCookieHeader(pairs: CookiePair[]): string | undefined;
41
+ private findBrowserProfiles;
42
+ private profileDirectories;
43
+ private readCommandCodeCookies;
44
+ private cookiePairFromRow;
45
+ private decryptChromiumCookie;
46
+ private safeStoragePassword;
47
+ }
55
48
  export declare class OpenCommandPlugin {
56
49
  private proxyManager;
57
50
  private secretStorage;
58
- private SESSION_TOKEN_KEY;
51
+ private cookieExtractor;
52
+ private readonly commandCodeTokenKey;
53
+ private readonly legacyTokenKey;
54
+ private readonly sessionCookieKey;
59
55
  constructor(proxyBinaryPath: string, storageDir?: string);
60
- /**
61
- * Initialize plugin on editor startup
62
- */
63
56
  activate(): Promise<void>;
64
- /**
65
- * Clean up on editor shutdown
66
- */
67
57
  deactivate(): Promise<void>;
68
- /**
69
- * Save proxy config to OpenCode configuration.
70
- * Fix: Persist to file so OpenCodeBar can discover the dynamic port.
71
- */
58
+ private loadCommandCodeToken;
59
+ private loadSessionCookie;
72
60
  private saveOpenCodeConfig;
73
- /**
74
- * Persist proxy URL and port to a config file (Issue #5).
75
- * OpenCodeBar reads this to discover the dynamically allocated port.
76
- */
77
61
  private persistProxyConfig;
78
- /**
79
- * Set session token via command
80
- */
62
+ setCommandCodeToken(token: string): Promise<void>;
81
63
  setSessionToken(token: string): Promise<void>;
82
- /**
83
- * Get proxy configuration
84
- */
64
+ setSessionCookie(cookie: string): Promise<void>;
65
+ private restartIfPossible;
85
66
  getProxyConfig(): string;
86
67
  }
68
+ export {};
package/dist/index.js CHANGED
@@ -33,18 +33,20 @@ var __importStar = (this && this.__importStar) || (function () {
33
33
  };
34
34
  })();
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
- exports.OpenCommandPlugin = exports.SecretStorage = exports.ProxyManager = void 0;
36
+ exports.OpenCommandPlugin = exports.BrowserCookieExtractor = exports.SecretStorage = exports.ProxyManager = void 0;
37
37
  const cp = __importStar(require("child_process"));
38
+ const crypto = __importStar(require("crypto"));
39
+ const fs = __importStar(require("fs"));
40
+ const fsp = __importStar(require("fs/promises"));
38
41
  const net = __importStar(require("net"));
42
+ const os = __importStar(require("os"));
43
+ const path = __importStar(require("path"));
39
44
  class ProxyManager {
40
45
  constructor(binaryPath) {
41
46
  this.proxyProcess = null;
42
47
  this.config = null;
43
48
  this.proxyBinaryPath = binaryPath;
44
49
  }
45
- /**
46
- * Find an available port (dynamic allocation)
47
- */
48
50
  async findAvailablePort() {
49
51
  return new Promise((resolve, reject) => {
50
52
  const server = net.createServer();
@@ -52,53 +54,48 @@ class ProxyManager {
52
54
  const address = server.address();
53
55
  if (address && typeof address === "object" && address.port) {
54
56
  server.close(() => resolve(address.port));
57
+ return;
55
58
  }
56
- else {
57
- reject(new Error("Failed to find available port"));
58
- }
59
+ reject(new Error("Failed to find available port"));
59
60
  });
60
61
  server.on("error", reject);
61
62
  });
62
63
  }
63
- /**
64
- * Start the proxy server
65
- */
66
- async start(sessionToken) {
67
- // Find available port
64
+ async start(startConfig) {
68
65
  const port = await this.findAvailablePort();
69
- this.config = { port, sessionToken };
70
- // Prepare environment
66
+ this.config = {
67
+ port,
68
+ commandCodeToken: startConfig.commandCodeToken,
69
+ sessionCookie: startConfig.sessionCookie,
70
+ };
71
71
  const env = {
72
72
  ...process.env,
73
73
  PORT: String(port),
74
- CC_SESSION_COOKIE: sessionToken,
74
+ COMMAND_CODE_TOKEN: startConfig.commandCodeToken,
75
+ COMMANDCODE_API_KEY: startConfig.commandCodeToken,
75
76
  PRODUCTION: "true",
76
77
  };
77
- // Start proxy process
78
+ if (startConfig.sessionCookie) {
79
+ env.CC_SESSION_COOKIE = startConfig.sessionCookie;
80
+ }
78
81
  this.proxyProcess = cp.spawn(this.proxyBinaryPath, [], {
79
82
  env,
80
83
  stdio: ["ignore", "pipe", "pipe"],
81
84
  });
82
- // Log output
83
85
  this.proxyProcess.stdout?.on("data", (data) => {
84
86
  console.log(`[Proxy stdout] ${data}`);
85
87
  });
86
88
  this.proxyProcess.stderr?.on("data", (data) => {
87
89
  console.error(`[Proxy stderr] ${data}`);
88
90
  });
89
- // Wait for proxy to be ready
90
91
  await this.waitForHealthz(port, 30000);
91
92
  console.log(`✓ Proxy started on port ${port}`);
92
93
  return this.config;
93
94
  }
94
- /**
95
- * Stop the proxy server
96
- */
97
95
  async stop() {
98
96
  const proc = this.proxyProcess;
99
- if (!proc) {
97
+ if (!proc)
100
98
  return;
101
- }
102
99
  return new Promise((resolve) => {
103
100
  let resolved = false;
104
101
  const finish = () => {
@@ -114,9 +111,8 @@ class ProxyManager {
114
111
  finish();
115
112
  });
116
113
  try {
117
- if (!proc.killed) {
114
+ if (!proc.killed)
118
115
  proc.kill("SIGTERM");
119
- }
120
116
  }
121
117
  catch (error) {
122
118
  console.error("Failed to send SIGTERM to proxy process:", error);
@@ -136,9 +132,6 @@ class ProxyManager {
136
132
  }, 5000);
137
133
  });
138
134
  }
139
- /**
140
- * Wait for proxy to be healthy
141
- */
142
135
  async waitForHealthz(port, timeoutMs) {
143
136
  const startTime = Date.now();
144
137
  while (Date.now() - startTime < timeoutMs) {
@@ -149,9 +142,8 @@ class ProxyManager {
149
142
  signal: controller.signal,
150
143
  });
151
144
  clearTimeout(timeoutId);
152
- if (response.ok) {
145
+ if (response.ok)
153
146
  return;
154
- }
155
147
  }
156
148
  catch (err) {
157
149
  console.debug(`Health check attempt failed for port ${port}:`, err);
@@ -160,38 +152,24 @@ class ProxyManager {
160
152
  }
161
153
  throw new Error(`Proxy failed to become healthy after ${timeoutMs}ms on port ${port}`);
162
154
  }
163
- /**
164
- * Get current proxy configuration
165
- */
166
155
  getConfig() {
167
156
  return this.config;
168
157
  }
169
- /**
170
- * Get proxy base URL
171
- */
172
158
  getBaseUrl() {
173
159
  return this.config ? `http://localhost:${this.config.port}` : null;
174
160
  }
175
- /**
176
- * Check if proxy is running
177
- */
178
161
  isRunning() {
179
162
  return this.proxyProcess !== null && !this.proxyProcess.killed;
180
163
  }
181
164
  }
182
165
  exports.ProxyManager = ProxyManager;
183
- /**
184
- * File-based persistent secret storage.
185
- * Fix: Persists session token across plugin restarts (not instance-local Map).
186
- */
187
166
  class SecretStorage {
188
167
  constructor(storageDir = `${process.env.HOME || "/tmp"}/.opencommand`) {
189
168
  this.filePath = `${storageDir}/opencommand-secrets.json`;
190
169
  }
191
170
  async readStore() {
192
- const fs = await Promise.resolve().then(() => __importStar(require("fs/promises")));
193
171
  try {
194
- const data = await fs.readFile(this.filePath, "utf-8");
172
+ const data = await fsp.readFile(this.filePath, "utf-8");
195
173
  return JSON.parse(data);
196
174
  }
197
175
  catch (error) {
@@ -202,11 +180,9 @@ class SecretStorage {
202
180
  }
203
181
  }
204
182
  async writeStore(store) {
205
- const fs = await Promise.resolve().then(() => __importStar(require("fs/promises")));
206
- const path = await Promise.resolve().then(() => __importStar(require("path")));
207
183
  const dir = path.dirname(this.filePath);
208
- await fs.mkdir(dir, { recursive: true });
209
- await fs.writeFile(this.filePath, JSON.stringify(store, null, 2), {
184
+ await fsp.mkdir(dir, { recursive: true });
185
+ await fsp.writeFile(this.filePath, JSON.stringify(store, null, 2), {
210
186
  mode: 0o600,
211
187
  });
212
188
  }
@@ -226,70 +202,253 @@ class SecretStorage {
226
202
  }
227
203
  }
228
204
  exports.SecretStorage = SecretStorage;
229
- /**
230
- * OpenCommand Plugin Main Class
231
- */
205
+ class BrowserCookieExtractor {
206
+ constructor(homeDir = os.homedir()) {
207
+ this.homeDir = homeDir;
208
+ }
209
+ async extractCommandCodeCookie() {
210
+ const rows = this.findBrowserProfiles().flatMap((profile) => this.readCommandCodeCookies(profile));
211
+ const pairs = rows
212
+ .map((row) => this.cookiePairFromRow(row))
213
+ .filter((pair) => pair !== undefined);
214
+ return BrowserCookieExtractor.buildCookieHeader(pairs);
215
+ }
216
+ static buildCookieHeader(pairs) {
217
+ const unique = new Map();
218
+ for (const pair of pairs) {
219
+ if (pair.name && pair.value)
220
+ unique.set(pair.name, pair.value);
221
+ }
222
+ if (unique.size === 0)
223
+ return undefined;
224
+ return [...unique.entries()]
225
+ .map(([name, value]) => `${name}=${value}`)
226
+ .join("; ");
227
+ }
228
+ findBrowserProfiles() {
229
+ const candidates = [
230
+ {
231
+ browser: "Chrome",
232
+ base: "Library/Application Support/Google/Chrome",
233
+ services: ["Chrome Safe Storage", "Google Chrome Safe Storage"],
234
+ },
235
+ {
236
+ browser: "Comet",
237
+ base: "Library/Application Support/Comet",
238
+ services: ["Comet Safe Storage", "Chrome Safe Storage"],
239
+ },
240
+ {
241
+ browser: "Brave",
242
+ base: "Library/Application Support/BraveSoftware/Brave-Browser",
243
+ services: ["Brave Safe Storage", "Chrome Safe Storage"],
244
+ },
245
+ {
246
+ browser: "Edge",
247
+ base: "Library/Application Support/Microsoft Edge",
248
+ services: ["Microsoft Edge Safe Storage", "Chrome Safe Storage"],
249
+ },
250
+ ];
251
+ const profiles = [];
252
+ for (const candidate of candidates) {
253
+ const basePath = path.join(this.homeDir, candidate.base);
254
+ for (const profileDir of this.profileDirectories(basePath)) {
255
+ for (const cookieDatabase of [
256
+ path.join(profileDir, "Network", "Cookies"),
257
+ path.join(profileDir, "Cookies"),
258
+ ]) {
259
+ if (fs.existsSync(cookieDatabase)) {
260
+ profiles.push({
261
+ browser: candidate.browser,
262
+ safeStorageServices: candidate.services,
263
+ cookieDatabase,
264
+ });
265
+ }
266
+ }
267
+ }
268
+ }
269
+ const firefoxBase = path.join(this.homeDir, "Library/Application Support/Firefox/Profiles");
270
+ for (const profileDir of this.profileDirectories(firefoxBase)) {
271
+ const cookieDatabase = path.join(profileDir, "cookies.sqlite");
272
+ if (fs.existsSync(cookieDatabase)) {
273
+ profiles.push({
274
+ browser: "Firefox",
275
+ safeStorageServices: [],
276
+ cookieDatabase,
277
+ });
278
+ }
279
+ }
280
+ return profiles;
281
+ }
282
+ profileDirectories(basePath) {
283
+ if (!fs.existsSync(basePath))
284
+ return [];
285
+ const directCookie = path.join(basePath, "cookies.sqlite");
286
+ if (fs.existsSync(directCookie))
287
+ return [basePath];
288
+ return fs
289
+ .readdirSync(basePath, { withFileTypes: true })
290
+ .filter((entry) => entry.isDirectory())
291
+ .map((entry) => path.join(basePath, entry.name));
292
+ }
293
+ readCommandCodeCookies(profile) {
294
+ const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "opencommand-cookies-"));
295
+ const tmpDb = path.join(tmpDir, "cookies.sqlite");
296
+ try {
297
+ fs.copyFileSync(profile.cookieDatabase, tmpDb);
298
+ const query = profile.browser === "Firefox" ? firefoxCookieQuery : chromiumCookieQuery;
299
+ const output = cp.execFileSync("/usr/bin/sqlite3", [tmpDb, query], {
300
+ encoding: "utf8",
301
+ timeout: 5000,
302
+ });
303
+ return output
304
+ .split("\n")
305
+ .filter(Boolean)
306
+ .map((line) => {
307
+ const [host = "", name = "", value = "", encryptedHex = ""] = line.split("\t");
308
+ return {
309
+ host,
310
+ name,
311
+ value,
312
+ encryptedHex,
313
+ browser: profile.browser,
314
+ safeStorageServices: profile.safeStorageServices,
315
+ };
316
+ });
317
+ }
318
+ catch (error) {
319
+ console.debug(`Could not read ${profile.browser} cookies:`, error);
320
+ return [];
321
+ }
322
+ finally {
323
+ fs.rmSync(tmpDir, { recursive: true, force: true });
324
+ }
325
+ }
326
+ cookiePairFromRow(row) {
327
+ if (!row.host.includes("commandcode.ai") || !row.name)
328
+ return undefined;
329
+ const value = row.value || this.decryptChromiumCookie(row);
330
+ if (!value)
331
+ return undefined;
332
+ return { name: row.name, value };
333
+ }
334
+ decryptChromiumCookie(row) {
335
+ if (!row.encryptedHex || row.browser === "Firefox")
336
+ return undefined;
337
+ const encrypted = Buffer.from(row.encryptedHex, "hex");
338
+ if (encrypted.length <= 3)
339
+ return undefined;
340
+ for (const service of row.safeStorageServices) {
341
+ const password = this.safeStoragePassword(service);
342
+ if (!password)
343
+ continue;
344
+ const decrypted = decryptMacChromiumCookie(encrypted, password);
345
+ if (decrypted)
346
+ return decrypted;
347
+ }
348
+ return undefined;
349
+ }
350
+ safeStoragePassword(service) {
351
+ try {
352
+ return cp
353
+ .execFileSync("/usr/bin/security", [
354
+ "find-generic-password",
355
+ "-w",
356
+ "-s",
357
+ service,
358
+ ], { encoding: "utf8", timeout: 5000 })
359
+ .trim();
360
+ }
361
+ catch {
362
+ return undefined;
363
+ }
364
+ }
365
+ }
366
+ exports.BrowserCookieExtractor = BrowserCookieExtractor;
367
+ function decryptMacChromiumCookie(encryptedValue, safeStoragePassword) {
368
+ try {
369
+ const payload = encryptedValue.subarray(0, 3).toString() === "v10"
370
+ ? encryptedValue.subarray(3)
371
+ : encryptedValue;
372
+ const key = crypto.pbkdf2Sync(safeStoragePassword, "saltysalt", 1003, 16, "sha1");
373
+ const decipher = crypto.createDecipheriv("aes-128-cbc", key, Buffer.alloc(16, " "));
374
+ return Buffer.concat([decipher.update(payload), decipher.final()]).toString("utf8");
375
+ }
376
+ catch {
377
+ return undefined;
378
+ }
379
+ }
380
+ const chromiumCookieQuery = [
381
+ ".mode tabs",
382
+ "SELECT host_key, name, value, hex(encrypted_value) FROM cookies WHERE host_key LIKE '%commandcode.ai%';",
383
+ ].join("\n");
384
+ const firefoxCookieQuery = [
385
+ ".mode tabs",
386
+ "SELECT host, name, value, '' FROM moz_cookies WHERE host LIKE '%commandcode.ai%';",
387
+ ].join("\n");
232
388
  class OpenCommandPlugin {
233
389
  constructor(proxyBinaryPath, storageDir) {
234
- this.SESSION_TOKEN_KEY = "opencommand.cc_session_token";
390
+ this.commandCodeTokenKey = "opencommand.command_code_token";
391
+ this.legacyTokenKey = "opencommand.cc_session_token";
392
+ this.sessionCookieKey = "opencommand.cc_session_cookie";
235
393
  this.proxyManager = new ProxyManager(proxyBinaryPath);
236
394
  const dir = storageDir || `${process.env.HOME || "/tmp"}/.opencommand`;
237
395
  this.secretStorage = new SecretStorage(dir);
396
+ this.cookieExtractor = new BrowserCookieExtractor();
238
397
  }
239
- /**
240
- * Initialize plugin on editor startup
241
- */
242
398
  async activate() {
243
399
  console.log("OpenCommand Plugin activating...");
244
- // Try to retrieve stored session token
245
- const storedToken = await this.secretStorage.get(this.SESSION_TOKEN_KEY);
246
- if (!storedToken) {
247
- console.warn("No CC_SESSION_COOKIE found. Please configure token.");
400
+ const commandCodeToken = await this.loadCommandCodeToken();
401
+ if (!commandCodeToken) {
402
+ console.warn("No COMMAND_CODE_TOKEN found. Please configure your CommandCode API key.");
248
403
  return;
249
404
  }
250
- // Start proxy
405
+ const sessionCookie = await this.loadSessionCookie();
406
+ if (!sessionCookie) {
407
+ console.warn("No CommandCode Studio cookie found. Inference works, but usage scraping may be unavailable.");
408
+ }
251
409
  try {
252
- const config = await this.proxyManager.start(storedToken);
410
+ const config = await this.proxyManager.start({
411
+ commandCodeToken,
412
+ sessionCookie,
413
+ });
253
414
  console.log(`✓ OpenCommand proxy ready at ${config.port}`);
254
- // Store config for use by OpenCode
255
415
  this.saveOpenCodeConfig(config);
256
416
  }
257
417
  catch (error) {
258
418
  console.error("Failed to start proxy:", error);
259
419
  }
260
420
  }
261
- /**
262
- * Clean up on editor shutdown
263
- */
264
421
  async deactivate() {
265
422
  console.log("OpenCommand Plugin deactivating...");
266
423
  await this.proxyManager.stop();
267
424
  console.log("✓ Proxy stopped");
268
425
  }
269
- /**
270
- * Save proxy config to OpenCode configuration.
271
- * Fix: Persist to file so OpenCodeBar can discover the dynamic port.
272
- */
426
+ async loadCommandCodeToken() {
427
+ const token = firstDefined(process.env.COMMAND_CODE_TOKEN, process.env.COMMANDCODE_API_KEY, await this.secretStorage.get(this.commandCodeTokenKey), await this.secretStorage.get(this.legacyTokenKey));
428
+ if (token && token === (await this.secretStorage.get(this.legacyTokenKey))) {
429
+ await this.secretStorage.set(this.commandCodeTokenKey, token);
430
+ }
431
+ return token;
432
+ }
433
+ async loadSessionCookie() {
434
+ const configured = firstDefined(process.env.CC_SESSION_COOKIE, await this.secretStorage.get(this.sessionCookieKey));
435
+ if (configured)
436
+ return configured;
437
+ const extracted = await this.cookieExtractor.extractCommandCodeCookie();
438
+ if (extracted) {
439
+ await this.secretStorage.set(this.sessionCookieKey, extracted);
440
+ console.log("✓ CommandCode Studio cookie discovered from local browser profile");
441
+ }
442
+ return extracted;
443
+ }
273
444
  saveOpenCodeConfig(config) {
274
445
  const proxyUrl = `http://localhost:${config.port}`;
275
- const openCodeConfig = {
276
- opencommand: {
277
- proxyUrl,
278
- apiBaseUrl: `${proxyUrl}/v1`,
279
- },
280
- };
281
- // Log for debugging
282
- console.log("Proxy configuration saved:", openCodeConfig);
283
- // Persist to config file (readable by OpenCodeBar)
446
+ console.log("Proxy configuration saved:", {
447
+ opencommand: { proxyUrl, apiBaseUrl: `${proxyUrl}/v1` },
448
+ });
284
449
  this.persistProxyConfig(proxyUrl, config.port);
285
450
  }
286
- /**
287
- * Persist proxy URL and port to a config file (Issue #5).
288
- * OpenCodeBar reads this to discover the dynamically allocated port.
289
- */
290
451
  persistProxyConfig(url, port) {
291
- const fs = require("fs");
292
- const path = require("path");
293
452
  const configDir = `${process.env.HOME || "/tmp"}/.opencommand`;
294
453
  const configPath = path.join(configDir, "proxy-config.json");
295
454
  try {
@@ -301,26 +460,43 @@ class OpenCommandPlugin {
301
460
  console.error("Failed to persist proxy config:", err);
302
461
  }
303
462
  }
304
- /**
305
- * Set session token via command
306
- */
463
+ async setCommandCodeToken(token) {
464
+ await this.secretStorage.set(this.commandCodeTokenKey, token);
465
+ console.log("✓ CommandCode API key saved securely");
466
+ await this.restartIfPossible();
467
+ }
307
468
  async setSessionToken(token) {
308
- await this.secretStorage.set(this.SESSION_TOKEN_KEY, token);
309
- console.log("✓ Session token saved securely");
310
- // Restart proxy with new token
469
+ await this.setCommandCodeToken(token);
470
+ }
471
+ async setSessionCookie(cookie) {
472
+ await this.secretStorage.set(this.sessionCookieKey, cookie);
473
+ console.log("✓ CommandCode Studio cookie saved securely");
474
+ await this.restartIfPossible();
475
+ }
476
+ async restartIfPossible() {
477
+ const commandCodeToken = await this.loadCommandCodeToken();
478
+ if (!commandCodeToken)
479
+ return;
311
480
  await this.proxyManager.stop();
312
- const config = await this.proxyManager.start(token);
481
+ const config = await this.proxyManager.start({
482
+ commandCodeToken,
483
+ sessionCookie: await this.loadSessionCookie(),
484
+ });
313
485
  this.saveOpenCodeConfig(config);
314
486
  }
315
- /**
316
- * Get proxy configuration
317
- */
318
487
  getProxyConfig() {
319
488
  const config = this.proxyManager.getConfig();
320
- if (!config) {
489
+ if (!config)
321
490
  return "Proxy not running";
322
- }
323
491
  return JSON.stringify(config, null, 2);
324
492
  }
325
493
  }
326
494
  exports.OpenCommandPlugin = OpenCommandPlugin;
495
+ function firstDefined(...values) {
496
+ for (const value of values) {
497
+ const trimmed = value?.trim();
498
+ if (trimmed)
499
+ return trimmed;
500
+ }
501
+ return undefined;
502
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencommand-plugin",
3
- "version": "0.0.1",
3
+ "version": "0.0.2",
4
4
  "description": "OpenCommand - CommandCode API Plugin for OpenCode",
5
5
  "main": "dist/index.js",
6
6
  "scripts": {