coding-tool-x 3.9.5-261012 → 3.9.5-261014

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "coding-tool-x",
3
- "version": "3.9.5-261012",
3
+ "version": "3.9.5-261014",
4
4
  "description": "Vibe Coding 增强工作助手 - 智能会话管理、动态渠道切换、全局搜索、实时监控",
5
5
  "main": "src/index.js",
6
6
  "bin": {
@@ -12,7 +12,8 @@ const {
12
12
  formatPortToolIssue
13
13
  } = require('../utils/port-helper');
14
14
  const { hasHostFlag } = require('../utils/cli-flags');
15
- const { getPlatformRegistry, getPlatformRuntime } = require('../platforms/runtime');
15
+ const { getPlatformRegistry } = require('../platforms/runtime');
16
+ const { createProxyControl } = require('./proxy-control');
16
17
  const PM2_APP_NAME = 'cc-tool';
17
18
  const STARTUP_LOG_FILE = 'cc-tool-out.log';
18
19
  const PM2_RUNTIME_ENV_KEYS = [
@@ -279,40 +280,48 @@ function getPlatformPort(platform, config = {}) {
279
280
  return configured || platform.defaultPort || null;
280
281
  }
281
282
 
282
- async function getProxyStatusEntries({ registry = getPlatformRegistry(), runtime = getPlatformRuntime(), config = loadConfig() } = {}) {
283
- const entries = [];
284
- for (const platform of listProxyPlatforms(registry)) {
283
+ function getUIConnectionOptions(existing, config = loadConfig()) {
284
+ const env = existing?.pm2_env || {};
285
+ const port = Number(env.CC_TOOL_PORT || env.env?.CC_TOOL_PORT || config.ports?.webUI || 19999);
286
+ const args = Array.isArray(env.args) ? env.args : String(env.args || '').split(/\s+/);
287
+ return { port, useHttps: args.includes('--https') };
288
+ }
289
+
290
+ async function getProxyStatusEntries({ registry = getPlatformRegistry(), config = loadConfig(), httpRequest, connection } = {}) {
291
+ // Servers live in the UI daemon. Loading a driver here creates a separate
292
+ // singleton in the CLI process whose status will always be stopped.
293
+ const control = createProxyControl({ registry, loadConfig: () => config, httpRequest, connection });
294
+ return Promise.all(listProxyPlatforms(registry).map(async (platform) => {
285
295
  const context = {
286
296
  platform: platform.key,
287
297
  capability: 'proxy',
288
298
  operation: 'status'
289
299
  };
290
300
  try {
291
- const driver = runtime && typeof runtime.getDriver === 'function'
292
- ? runtime.getDriver(platform.key, 'proxy')
293
- : null;
294
- if (!driver || (typeof driver.status === 'string' && driver.status !== 'ok')) {
295
- entries.push({ platform, state: { status: 'unsupported', ...context }, port: getPlatformPort(platform, config) });
296
- continue;
301
+ if (platform.capabilities?.proxy === 'unsupported' || platform.capabilities?.proxy === false) {
302
+ return { platform, state: { status: 'unsupported', ...context }, port: getPlatformPort(platform, config) };
297
303
  }
298
- if (typeof driver.status !== 'function') {
299
- entries.push({ platform, state: { status: 'unsupported', ...context }, port: getPlatformPort(platform, config) });
300
- continue;
304
+ const { response } = await control.status(platform.key);
305
+ const result = response.data;
306
+ if (!Number.isInteger(response.status) || response.status < 200 || response.status >= 300) {
307
+ const failure = result?.error;
308
+ if (failure && typeof failure === 'object') {
309
+ return { platform, state: { ...failure, status: failure.status && failure.status !== 'ok' ? failure.status : 'failed', ...context }, port: getPlatformPort(platform, config) };
310
+ }
311
+ throw new Error(typeof failure === 'string' ? failure : `HTTP ${response.status}`);
301
312
  }
302
- const result = await Promise.resolve(driver.status());
303
- // Proxy drivers use the shared Driver contract and wrap successful
304
- // service status payloads in { status: 'ok', data }. Keep compatibility
305
- // with legacy drivers that return the service payload directly.
313
+ // The API normally unwraps the Driver result. Accept wrapped payloads
314
+ // too, but never interpret an invalid response as a stopped proxy.
306
315
  const state = result && result.status === 'ok'
307
316
  ? (result.data && typeof result.data === 'object' ? result.data : {})
308
317
  : result;
309
318
  if (state && typeof state.status === 'string' && state.status !== 'ok') {
310
- entries.push({ platform, state: { ...state, ...context }, port: getPlatformPort(platform, config) });
311
- } else {
312
- entries.push({ platform, state: state || {}, port: getPlatformPort(platform, config) });
319
+ return { platform, state: { ...state, ...context }, port: getPlatformPort(platform, config) };
313
320
  }
321
+ if (!state || typeof state.running !== 'boolean') throw new Error('Invalid proxy status response');
322
+ return { platform, state, port: getPlatformPort(platform, config) };
314
323
  } catch (error) {
315
- entries.push({
324
+ return {
316
325
  platform,
317
326
  state: {
318
327
  status: 'failed',
@@ -320,10 +329,9 @@ async function getProxyStatusEntries({ registry = getPlatformRegistry(), runtime
320
329
  error: error && error.message ? error.message : String(error)
321
330
  },
322
331
  port: getPlatformPort(platform, config)
323
- });
332
+ };
324
333
  }
325
- }
326
- return entries;
334
+ }));
327
335
  }
328
336
 
329
337
  function getManagedPorts(config = loadConfig(), registry = getPlatformRegistry()) {
@@ -739,6 +747,12 @@ async function handleStatus() {
739
747
 
740
748
  const existing = await getCCToolProcess();
741
749
  const config = loadConfig();
750
+ const connection = getUIConnectionOptions(existing, config);
751
+ const protocol = connection.useHttps ? 'https' : 'http';
752
+ if (connection.useHttps && PATHS.config) {
753
+ const certPath = path.join(PATHS.config, 'https', 'localhost-cert.pem');
754
+ if (fs.existsSync(certPath)) connection.ca = fs.readFileSync(certPath);
755
+ }
742
756
 
743
757
  console.log(chalk.bold.cyan('\n╔======================================╗'));
744
758
  console.log(chalk.bold.cyan('║ Coding-Tool 服务状态 ║'));
@@ -748,7 +762,7 @@ async function handleStatus() {
748
762
  console.log(chalk.bold('[UI] Web UI 服务:'));
749
763
  if (existing && existing.pm2_env.status === 'online') {
750
764
  console.log(chalk.green(' [OK] 状态: 运行中'));
751
- console.log(chalk.gray(` [NET] 地址: http://localhost:${config.ports?.webUI || 19999}`));
765
+ console.log(chalk.gray(` [NET] 地址: ${protocol}://localhost:${connection.port}`));
752
766
  console.log(chalk.gray(` [KEY] 进程 ID: ${existing.pid}`));
753
767
  console.log(chalk.gray(` [TIMER] 运行时长: ${formatUptime(existing.pm2_env.pm_uptime)}`));
754
768
  console.log(chalk.gray(` [SAVE] 内存使用: ${formatMemory(existing.monit?.memory)}`));
@@ -757,8 +771,11 @@ async function handleStatus() {
757
771
  console.log(chalk.gray(' [ERROR] 状态: 未运行'));
758
772
  }
759
773
 
760
- // 代理服务状态由 Registry 中声明的 proxy driver 提供
761
- const proxyStatuses = await getProxyStatusEntries({ config });
774
+ // Query the drivers in the running backend through manifest-declared APIs.
775
+ const proxyStatuses = await getProxyStatusEntries({
776
+ config: { ...config, ports: { ...config.ports, webUI: connection.port } },
777
+ connection
778
+ });
762
779
 
763
780
  console.log(chalk.bold('\n[PROXY] 代理服务:'));
764
781
  for (const entry of proxyStatuses) {
@@ -835,6 +852,7 @@ module.exports = {
835
852
  shouldTreatPortOwnershipAsReady,
836
853
  getManagedPorts,
837
854
  getProxyStatusEntries,
855
+ getUIConnectionOptions,
838
856
  listProxyPlatforms,
839
857
  shouldStopPM2Process
840
858
  }
@@ -1,5 +1,6 @@
1
1
  const chalk = require('chalk');
2
2
  const http = require('http');
3
+ const https = require('https');
3
4
  const { loadConfig } = require('../config/loader');
4
5
  const { normalizePlatformKey } = require('../shared/platforms');
5
6
 
@@ -38,7 +39,7 @@ function getPlatformInfo(channel, registry = getDefaultRegistry()) {
38
39
  };
39
40
  }
40
41
 
41
- function createHttpRequest(loadConfigImpl = loadConfig) {
42
+ function createHttpRequest(loadConfigImpl = loadConfig, { useHttps = false, ca } = {}) {
42
43
  return function request(method, requestPath, data = null) {
43
44
  const config = loadConfigImpl();
44
45
  const port = config.ports?.webUI || 19999;
@@ -56,10 +57,19 @@ function createHttpRequest(loadConfigImpl = loadConfig) {
56
57
  },
57
58
  timeout: 5000
58
59
  };
60
+ if (useHttps) {
61
+ // This client only connects to localhost. Trust the daemon's generated
62
+ // certificate when available (Windows may use a PFX instead of PEM).
63
+ options.ca = ca;
64
+ options.rejectUnauthorized = Boolean(ca);
65
+ }
59
66
 
60
- const req = http.request(options, (res) => {
67
+ const req = (useHttps ? https : http).request(options, (res) => {
61
68
  let responseData = '';
62
69
 
70
+ res.on('error', reject);
71
+ res.on('aborted', () => reject(new Error('Response connection closed unexpectedly')));
72
+
63
73
  res.on('data', (chunk) => {
64
74
  responseData += chunk;
65
75
  });
@@ -86,8 +96,8 @@ function createHttpRequest(loadConfigImpl = loadConfig) {
86
96
  };
87
97
  }
88
98
 
89
- function createProxyControl({ registry = getDefaultRegistry(), httpRequest: request, loadConfig: loadConfigImpl, sleep = (ms) => new Promise(resolve => setTimeout(resolve, ms)) } = {}) {
90
- const requestImpl = request || createHttpRequest(loadConfigImpl || loadConfig);
99
+ function createProxyControl({ registry = getDefaultRegistry(), httpRequest: request, loadConfig: loadConfigImpl, connection, sleep = (ms) => new Promise(resolve => setTimeout(resolve, ms)) } = {}) {
100
+ const requestImpl = request || createHttpRequest(loadConfigImpl || loadConfig, connection);
91
101
 
92
102
  function resolve(channel) {
93
103
  const info = getPlatformInfo(channel, registry);
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "source": "models.dev",
3
3
  "sourceUrl": "https://models.dev/api.json",
4
- "lastUpdated": "2026-10-09",
4
+ "lastUpdated": "2026-10-14",
5
5
  "defaultModels": {
6
6
  "claude": [
7
7
  "claude-opus-4-7",
@@ -82,7 +82,8 @@
82
82
  "gemini-3.1-flash-lite",
83
83
  "gemini-3.1-flash-live-preview",
84
84
  "gemini-3.1-pro-preview-customtools",
85
- "gemini-2.5-computer-use-preview-10-2025"
85
+ "gemini-2.5-computer-use-preview-10-2025",
86
+ "gemini-4-argon"
86
87
  ]
87
88
  },
88
89
  "defaultSpeedTestModels": {
@@ -2392,6 +2393,32 @@
2392
2393
  "omp"
2393
2394
  ]
2394
2395
  },
2396
+ "gemini-4-argon": {
2397
+ "id": "gemini-4-argon",
2398
+ "input": [
2399
+ "text",
2400
+ "image"
2401
+ ],
2402
+ "limit": {
2403
+ "context": 1048576,
2404
+ "output": 32768
2405
+ },
2406
+ "name": "Gemini 4 Argon",
2407
+ "pricing": {
2408
+ "cacheRead": 0.1,
2409
+ "input": 2,
2410
+ "output": 10
2411
+ },
2412
+ "provider": "google",
2413
+ "reasoning": true,
2414
+ "sourceId": "google/gemini-4-argon",
2415
+ "supportsTools": true,
2416
+ "toolTypes": [
2417
+ "gemini",
2418
+ "opencode",
2419
+ "omp"
2420
+ ]
2421
+ },
2395
2422
  "gemini-flash-latest": {
2396
2423
  "id": "gemini-flash-latest",
2397
2424
  "input": [