coding-tool-x 3.8.7 → 3.8.9

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 (143) hide show
  1. package/README.md +2 -2
  2. package/dist/web/assets/{AgentsDrawer-C7ePByZx.js → AgentsDrawer-Cj5CJ4d9.js} +1 -1
  3. package/dist/web/assets/Analytics-1doS-8uC.js +1 -0
  4. package/dist/web/assets/AssetPathField-C9TOPl7o.js +1 -0
  5. package/dist/web/assets/{ChatHistoryDrawer-Ccl4rhdz.js → ChatHistoryDrawer-BTmQ1aQr.js} +1 -1
  6. package/dist/web/assets/{CollapseItem-MxG_UD4o.js → CollapseItem-CwqJk3bE.js} +1 -1
  7. package/dist/web/assets/{CommandsDrawer-DWbaxHRZ.js → CommandsDrawer-CaZWDI_G.js} +1 -1
  8. package/dist/web/assets/ConfigExportDrawer-C3vSZEsS.js +1 -0
  9. package/dist/web/assets/{ConfigTemplates-AiRPv2cd.js → ConfigTemplates-gyERg9iC.js} +1 -1
  10. package/dist/web/assets/{ConfigTemplatesDrawer-CKMFsfEF.js → ConfigTemplatesDrawer-B17RqFi4.js} +1 -1
  11. package/dist/web/assets/{ConfigTemplatesPanel-Cvbnkvpt.js → ConfigTemplatesPanel-DKIC_FqG.js} +1 -1
  12. package/dist/web/assets/{Divider-D28g1gwj.js → Divider-DsdbkHrG.js} +1 -1
  13. package/dist/web/assets/{FavoritesDrawer-DA-dR_vP.js → FavoritesDrawer-DaziQmBp.js} +1 -1
  14. package/dist/web/assets/Forward-DLCL7aMY.js +1 -0
  15. package/dist/web/assets/{GatewayConvertDrawer-402_raGb.js → GatewayConvertDrawer-OMgWUUSc.js} +1 -1
  16. package/dist/web/assets/Home-DOSUTfrE.js +1 -0
  17. package/dist/web/assets/{MarkdownEditor-BvkDECwH.js → MarkdownEditor-9TTwTS-U.js} +1 -1
  18. package/dist/web/assets/McpDrawer-I8rl8lGH.js +1 -0
  19. package/dist/web/assets/{McpFormDrawer-DPMnyt5L.js → McpFormDrawer-DEP3C7ut.js} +1 -1
  20. package/dist/web/assets/{PluginManager-FKVeugr4.js → PluginManager-BuRcWuBj.js} +1 -1
  21. package/dist/web/assets/{PluginsDrawer-MvM1R55d.js → PluginsDrawer-_zZENaQn.js} +1 -1
  22. package/dist/web/assets/PluginsPanel-Bs5qZ-TK.js +1 -0
  23. package/dist/web/assets/PluginsPanel-CzGMK-Ap.css +1 -0
  24. package/dist/web/assets/ProjectList-BSxuL2td.js +1 -0
  25. package/dist/web/assets/{ProjectList-677RLZ8O.css → ProjectList-VbIYSHbH.css} +1 -1
  26. package/dist/web/assets/PromptsDrawer-CoZ-ZtsY.js +1 -0
  27. package/dist/web/assets/RecentSessionsDrawer-B_17aJBG.js +1 -0
  28. package/dist/web/assets/RecentSessionsDrawer-yrAD4p1A.css +1 -0
  29. package/dist/web/assets/SessionCard-BL_x0d3t.js +1 -0
  30. package/dist/web/assets/SessionList-DhRYZ6vl.js +1 -0
  31. package/dist/web/assets/SessionList-qG_XpPBJ.css +1 -0
  32. package/dist/web/assets/{SettingsDrawer-lMjttbkD.js → SettingsDrawer-fYb0DU7X.js} +1 -1
  33. package/dist/web/assets/SkillManager-S698Hns8.js +1 -0
  34. package/dist/web/assets/{SkillsDrawer-DF6JsSyj.js → SkillsDrawer-Ms4lPCow.js} +1 -1
  35. package/dist/web/assets/{SkillsPanel-B3Nm5j32.css → SkillsPanel-C4ke56nF.css} +1 -1
  36. package/dist/web/assets/SkillsPanel-rqnqAOGL.js +1 -0
  37. package/dist/web/assets/{SpeedTestDrawer-BaZkZqPP.js → SpeedTestDrawer-Bbn38SfV.js} +1 -1
  38. package/dist/web/assets/Upload-CdyVHxCI.js +1 -0
  39. package/dist/web/assets/{WorkspaceDrawer-BFSwZ5yU.js → WorkspaceDrawer-L7HJRc6u.js} +1 -1
  40. package/dist/web/assets/{WorkspaceManager-BHL1uYct.js → WorkspaceManager-DsoNg2z8.js} +1 -1
  41. package/dist/web/assets/{WorkspacePanel-B5PooBtg.js → WorkspacePanel-Be8PVZah.js} +1 -1
  42. package/dist/web/assets/{headers-cf-QapUq.js → headers-B5JWGn3v.js} +1 -1
  43. package/dist/web/assets/{icons-B2Vg-IOC.js → icons-DmFe4b5j.js} +1 -1
  44. package/dist/web/assets/{index-BohDDAy_.css → index-3Lp6z8TQ.css} +1 -1
  45. package/dist/web/assets/index-BKlAWTH-.js +2 -0
  46. package/dist/web/assets/{light-Cp0t7v32.js → light-0eavxNvt.js} +1 -1
  47. package/dist/web/assets/platforms-BmzzwnSw.js +1 -0
  48. package/dist/web/assets/platforms-DWXgmy2w.js +1 -0
  49. package/dist/web/assets/session-visibility-BAmxh3cK.js +1 -0
  50. package/dist/web/assets/sessions-CC0j-KH_.js +1 -0
  51. package/dist/web/assets/sessions-D4yQtfKb.js +1 -0
  52. package/dist/web/assets/use-message-DqCwefG6.js +1 -0
  53. package/dist/web/assets/{useResponsiveDrawer-D-DDpbnI.js → useResponsiveDrawer-V_onl9NV.js} +1 -1
  54. package/dist/web/index.html +7 -7
  55. package/package.json +1 -1
  56. package/src/commands/daemon.js +27 -4
  57. package/src/commands/search.js +17 -2
  58. package/src/config/paths.js +2 -0
  59. package/src/platforms/channel-auth-registry.js +36 -6
  60. package/src/platforms/channel-auth-service.js +12 -2
  61. package/src/platforms/driver-registry.js +9 -1
  62. package/src/platforms/drivers/claude/session-history-adapter.js +72 -1
  63. package/src/platforms/drivers/claude/sessions-implementation.js +49 -7
  64. package/src/platforms/drivers/claude/sessions.js +30 -6
  65. package/src/platforms/drivers/codex/parser.js +57 -1
  66. package/src/platforms/drivers/codex/session-history-adapter.js +8 -2
  67. package/src/platforms/drivers/codex/sessions-implementation.js +25 -3
  68. package/src/platforms/drivers/codex/sessions.js +18 -1
  69. package/src/platforms/drivers/dsh/api-operations.js +396 -0
  70. package/src/platforms/drivers/dsh/channels-implementation.js +458 -0
  71. package/src/platforms/drivers/dsh/channels.js +191 -0
  72. package/src/platforms/drivers/dsh/common.js +571 -0
  73. package/src/platforms/drivers/dsh/native-config.js +93 -0
  74. package/src/platforms/drivers/dsh/native-logs.js +116 -0
  75. package/src/platforms/drivers/dsh/plugin-manager.js +117 -0
  76. package/src/platforms/drivers/dsh/projects.js +23 -0
  77. package/src/platforms/drivers/dsh/proxy-implementation.js +260 -0
  78. package/src/platforms/drivers/dsh/proxy.js +23 -0
  79. package/src/platforms/drivers/dsh/resources.js +346 -0
  80. package/src/platforms/drivers/dsh/sessions.js +587 -0
  81. package/src/platforms/drivers/dsh/statistics-implementation.js +238 -0
  82. package/src/platforms/drivers/dsh/statistics.js +24 -0
  83. package/src/platforms/drivers/gemini/session-history-adapter.js +49 -1
  84. package/src/platforms/drivers/gemini/sessions-implementation.js +46 -1
  85. package/src/platforms/drivers/gemini/sessions.js +2 -1
  86. package/src/platforms/drivers/omp/prompts.js +58 -2
  87. package/src/platforms/drivers/omp/proxy-implementation.js +25 -1
  88. package/src/platforms/drivers/omp/session-history-adapter.js +42 -1
  89. package/src/platforms/drivers/omp/sessions-implementation.js +51 -3
  90. package/src/platforms/drivers/omp/sessions.js +33 -2
  91. package/src/platforms/drivers/opencode/channels-implementation.js +25 -22
  92. package/src/platforms/drivers/opencode/channels.js +6 -1
  93. package/src/platforms/drivers/opencode/sessions-implementation.js +89 -9
  94. package/src/platforms/drivers/opencode/sessions.js +37 -1
  95. package/src/platforms/manifest-schema.js +43 -3
  96. package/src/platforms/manifests/dsh.json +542 -0
  97. package/src/platforms/manifests/omp.json +2 -1
  98. package/src/platforms/manifests/opencode.json +28 -0
  99. package/src/platforms/native-oauth-adapters.js +318 -18
  100. package/src/platforms/oauth-credentials-service.js +344 -13
  101. package/src/platforms/path-resolver.js +2 -0
  102. package/src/platforms/platform-path-context.js +12 -2
  103. package/src/platforms/registry.js +16 -1
  104. package/src/platforms/runtime.js +5 -0
  105. package/src/platforms/session-history-adapters.js +1 -0
  106. package/src/server/api/platform-api-config.js +23 -2
  107. package/src/server/api/platform-route-factory.js +9 -2
  108. package/src/server/api/platforms.js +19 -1
  109. package/src/server/api/plugins.js +108 -13
  110. package/src/server/index.js +35 -1
  111. package/src/server/services/config-registry-service.js +10 -1
  112. package/src/server/services/config-templates-service.js +1 -0
  113. package/src/server/services/plugins-service.js +474 -103
  114. package/src/server/services/session-history-index.js +900 -140
  115. package/src/server/services/session-history-worker.js +3 -1
  116. package/src/server/services/skill-service.js +214 -7
  117. package/src/server/services/usage-log-utils.js +1 -0
  118. package/src/server/services/workspace-service.js +39 -10
  119. package/src/shared/driver-factories/api.js +22 -6
  120. package/src/shared/driver-factories/projects.js +8 -0
  121. package/dist/web/assets/Analytics-BVG6ehFv.js +0 -1
  122. package/dist/web/assets/AssetPathField-BZI9NvEr.js +0 -1
  123. package/dist/web/assets/ConfigExportDrawer-DrawKwxE.js +0 -1
  124. package/dist/web/assets/Home-CTF8ZWKW.js +0 -1
  125. package/dist/web/assets/McpDrawer-DZGHkuDm.js +0 -1
  126. package/dist/web/assets/PluginsPanel-CKuBs38B.js +0 -1
  127. package/dist/web/assets/PluginsPanel-D6ZqITcR.css +0 -1
  128. package/dist/web/assets/ProjectList-tsjwjXV1.js +0 -1
  129. package/dist/web/assets/PromptsDrawer-B-X9ci8n.js +0 -1
  130. package/dist/web/assets/RecentSessionsDrawer-CKFsOYDM.css +0 -1
  131. package/dist/web/assets/RecentSessionsDrawer-wLktMF_c.js +0 -1
  132. package/dist/web/assets/SessionCard-DkJPy0TY.js +0 -1
  133. package/dist/web/assets/SessionList-BpYRz1cX.css +0 -1
  134. package/dist/web/assets/SessionList-Gzhh4FOZ.js +0 -1
  135. package/dist/web/assets/SkillManager-CzFxWxx-.js +0 -1
  136. package/dist/web/assets/SkillsPanel--lLEts9y.js +0 -1
  137. package/dist/web/assets/Upload-BEQ-3Kqq.js +0 -1
  138. package/dist/web/assets/index-BFInlZGI.js +0 -2
  139. package/dist/web/assets/platforms-CBkB45JP.js +0 -1
  140. package/dist/web/assets/platforms-FTpjxAT6.js +0 -1
  141. package/dist/web/assets/sessions-Cmy31slD.js +0 -1
  142. package/dist/web/assets/sessions-yC_oVVh8.js +0 -1
  143. package/dist/web/assets/use-message-DoLM8C1C.js +0 -1
@@ -19,7 +19,8 @@ const PUBLIC_FIELDS = Object.freeze([
19
19
  'apiPrefix',
20
20
  'modelCatalogKey',
21
21
  'promptLabel',
22
- 'resourceTypes'
22
+ 'resourceTypes',
23
+ 'resourceActions'
23
24
  ]);
24
25
 
25
26
  function publicCapabilities(capabilities) {
@@ -41,6 +42,18 @@ function publicResourceTypes(resourceTypes) {
41
42
  );
42
43
  }
43
44
 
45
+ function publicResourceActions(resourceActions) {
46
+ if (!resourceActions || typeof resourceActions !== 'object' || Array.isArray(resourceActions)) {
47
+ return null;
48
+ }
49
+ return Object.fromEntries(Object.entries(resourceActions).map(([resourceType, actions]) => [
50
+ resourceType,
51
+ actions && typeof actions === 'object' && !Array.isArray(actions)
52
+ ? Object.fromEntries(Object.entries(actions).filter(([, value]) => typeof value === 'boolean'))
53
+ : {}
54
+ ]));
55
+ }
56
+
44
57
  function toPublicDefinition(definition) {
45
58
  if (!definition || typeof definition !== 'object') return null;
46
59
  const result = {};
@@ -50,6 +63,11 @@ function toPublicDefinition(definition) {
50
63
  if (resourceTypes) result.resourceTypes = resourceTypes;
51
64
  continue;
52
65
  }
66
+ if (field === 'resourceActions') {
67
+ const resourceActions = publicResourceActions(definition.resourceActions);
68
+ if (resourceActions) result.resourceActions = resourceActions;
69
+ continue;
70
+ }
53
71
  if (field === 'apiPrefix') {
54
72
  const apiPrefix = definition.apiPrefix ?? definition.api?.prefix;
55
73
  if (apiPrefix !== undefined) result.apiPrefix = apiPrefix || null;
@@ -5,7 +5,10 @@
5
5
  */
6
6
 
7
7
  const express = require('express');
8
+ const path = require('path');
8
9
  const { PluginsService } = require('../services/plugins-service');
10
+ const { SkillRefreshTaskService } = require('../services/skill-refresh-task-service');
11
+ const { PATHS } = require('../../config/paths');
9
12
  const { maskToken } = require('../services/oauth-utils');
10
13
  const { sendApiError } = require('./validation-errors');
11
14
  const { resolveManagedPlatform } = require('../services/platform-resolution');
@@ -13,6 +16,13 @@ const { validateKnownProjectCwd } = require('../services/project-path-validation
13
16
 
14
17
  const router = express.Router();
15
18
  const pluginServices = new Map();
19
+ let routerOptions = {};
20
+ let defaultRefreshTasks;
21
+
22
+ router.createRouter = (options = {}) => {
23
+ routerOptions = options;
24
+ return router;
25
+ };
16
26
 
17
27
  function resolvePlatform(rawPlatform) {
18
28
  return resolveManagedPlatform(rawPlatform);
@@ -35,6 +45,26 @@ function getPluginsService(req) {
35
45
  };
36
46
  }
37
47
 
48
+ function getPluginServiceForPlatform(platform) {
49
+ if (!pluginServices.has(platform)) {
50
+ pluginServices.set(platform, new PluginsService(platform));
51
+ }
52
+ return pluginServices.get(platform);
53
+ }
54
+
55
+ function getRefreshTasks() {
56
+ if (routerOptions.refreshTasks) return routerOptions.refreshTasks;
57
+ if (!defaultRefreshTasks) {
58
+ const persistencePath = PATHS.pluginRefreshTasks
59
+ || path.join(PATHS.storage || process.cwd(), 'runtime', 'plugin-refresh-tasks.json');
60
+ defaultRefreshTasks = new SkillRefreshTaskService({
61
+ persistencePath,
62
+ worker: context => getPluginServiceForPlatform(context.platform).refreshRemotePlugins(context)
63
+ });
64
+ }
65
+ return defaultRefreshTasks;
66
+ }
67
+
38
68
  async function getRequestOptions(req, service) {
39
69
  const scope = String(req.query?.scope || req.body?.scope || '').trim();
40
70
  if (scope && scope !== 'user' && scope !== 'project') {
@@ -147,11 +177,15 @@ router.get('/', async (req, res) => {
147
177
  const { platform, service, warning } = getPluginsService(req);
148
178
  const options = await getRequestOptions(req, service);
149
179
  const result = invokeWithOptions(service.listPlugins.bind(service), [], options);
180
+ const plugins = typeof service.sanitizePluginList === 'function'
181
+ ? service.sanitizePluginList(result.plugins)
182
+ : result.plugins;
150
183
 
151
184
  res.json({
152
185
  success: true,
153
186
  platform,
154
187
  ...result,
188
+ plugins,
155
189
  ...(warning ? { warnings: [warning] } : {})
156
190
  });
157
191
  } catch (err) {
@@ -168,12 +202,11 @@ router.get('/market', async (req, res) => {
168
202
  try {
169
203
  const { platform, service, warning } = getPluginsService(req);
170
204
  const options = await getRequestOptions(req, service);
171
- const forceRefresh = req.query.refresh === '1';
172
- if (forceRefresh) {
173
- console.log(`[Plugins API] Refreshing market plugins for ${platform}...`);
174
- }
175
- const plugins = await invokeWithOptions(service.getMarketPlugins.bind(service), [forceRefresh], options);
176
- console.log(`[Plugins API] ${platform}: ${plugins.length} market plugins loaded (refresh=${forceRefresh})`);
205
+ const marketPlugins = await invokeWithOptions(service.getMarketPlugins.bind(service), [false], options);
206
+ const plugins = typeof service.sanitizePluginList === 'function'
207
+ ? service.sanitizePluginList(marketPlugins)
208
+ : marketPlugins;
209
+ console.log(`[Plugins API] ${platform}: ${plugins.length} cached market plugins loaded`);
177
210
 
178
211
  res.json({
179
212
  success: true,
@@ -187,6 +220,53 @@ router.get('/market', async (req, res) => {
187
220
  }
188
221
  });
189
222
 
223
+ /**
224
+ * 启动插件远端全量缓存任务
225
+ * POST /api/plugins/refresh
226
+ */
227
+ router.post('/refresh', async (req, res) => {
228
+ try {
229
+ const { platform, service } = getPluginsService(req);
230
+ const options = await getRequestOptions(req, service);
231
+ const refreshTasks = getRefreshTasks();
232
+ if (!refreshTasks) throw new Error('Plugin refresh task service is unavailable');
233
+ const task = refreshTasks.enqueue({
234
+ platform,
235
+ scope: options.scope || 'user',
236
+ projectPath: options.scope === 'project' ? options.cwd : null,
237
+ reason: 'manual'
238
+ });
239
+ res.status(202).json({ success: true, platform, task });
240
+ } catch (err) {
241
+ console.error('[Plugins API] Refresh plugins error:', err);
242
+ sendApiError(res, err);
243
+ }
244
+ });
245
+
246
+ router.get('/refresh/:taskId', async (req, res) => {
247
+ try {
248
+ const { platform, service } = getPluginsService(req);
249
+ const options = await getRequestOptions({ query: req.query }, service);
250
+ const refreshTasks = getRefreshTasks();
251
+ const task = refreshTasks?.get(req.params.taskId);
252
+ if (!task) return res.status(404).json({ success: false, message: 'Refresh task not found' });
253
+ const taskScope = task.scope || 'user';
254
+ const taskProjectPath = taskScope === 'project' ? (task.projectPath || null) : null;
255
+ const requestedProjectPath = options.scope === 'project' ? (options.cwd || null) : null;
256
+ if (
257
+ task.platform !== platform
258
+ || taskScope !== (options.scope || 'user')
259
+ || taskProjectPath !== requestedProjectPath
260
+ ) {
261
+ return res.status(404).json({ success: false, message: 'Refresh task not found' });
262
+ }
263
+ return res.json({ success: true, task });
264
+ } catch (err) {
265
+ console.error('[Plugins API] Get refresh task error:', err);
266
+ return sendApiError(res, err);
267
+ }
268
+ });
269
+
190
270
  /**
191
271
  * 安装插件
192
272
  * POST /api/plugins/install
@@ -435,20 +515,26 @@ router.put('/repos/auth', (req, res) => {
435
515
  });
436
516
 
437
517
  /**
438
- * 同步仓库到 Claude Code marketplace
518
+ * Legacy alias for the explicit plugin refresh task.
439
519
  * POST /api/plugins/repos/sync
440
520
  */
441
521
  router.post('/repos/sync', async (req, res) => {
442
522
  try {
443
523
  const { platform, service } = getPluginsService(req);
444
524
  const options = await getRequestOptions(req, service);
445
- const result = await service.syncRepos(options);
525
+ const refreshTasks = getRefreshTasks();
526
+ const task = refreshTasks.enqueue({
527
+ platform,
528
+ scope: options.scope || 'user',
529
+ projectPath: options.scope === 'project' ? options.cwd : null,
530
+ reason: 'manual'
531
+ });
446
532
 
447
- res.json({
533
+ res.status(202).json({
448
534
  success: true,
449
535
  platform,
450
- ...result,
451
- message: 'Repositories synced successfully'
536
+ task,
537
+ message: 'Plugin refresh task started'
452
538
  });
453
539
  } catch (err) {
454
540
  console.error('[Plugins API] Sync repos error:', err);
@@ -487,6 +573,7 @@ router.get('/:name/readme', async (req, res) => {
487
573
  try {
488
574
  const { platform, service } = getPluginsService(req);
489
575
  const { name } = req.params;
576
+ const options = await getRequestOptions(req, service);
490
577
  const {
491
578
  repoId,
492
579
  repoProvider,
@@ -499,7 +586,9 @@ router.get('/:name/readme', async (req, res) => {
499
586
  repoUrl,
500
587
  repoProjectPath,
501
588
  repoLocalPath,
502
- installPath
589
+ installPath,
590
+ scope: queryScope,
591
+ cwd: queryCwd
503
592
  } = req.query;
504
593
 
505
594
  const pluginInfo = {
@@ -518,7 +607,13 @@ router.get('/:name/readme', async (req, res) => {
518
607
  installPath
519
608
  };
520
609
 
521
- const readme = await service.getPluginReadme(pluginInfo);
610
+ const readmeOptions = {
611
+ ...(options.scope || queryScope ? { scope: options.scope || queryScope } : {}),
612
+ ...(options.cwd || queryCwd ? { cwd: options.cwd || queryCwd } : {})
613
+ };
614
+ const readme = Object.keys(readmeOptions).length > 0
615
+ ? await service.getPluginReadme(pluginInfo, readmeOptions)
616
+ : await service.getPluginReadme(pluginInfo);
522
617
 
523
618
  res.json({
524
619
  success: true,
@@ -58,6 +58,30 @@ function traceStartupMemory(stage) {
58
58
  })}`);
59
59
  }
60
60
 
61
+ async function refreshNativeCodexOAuthOnStartup({ oauthService } = {}) {
62
+ try {
63
+ const service = oauthService || require('../platforms/oauth-credentials-service');
64
+ if (typeof service.refreshNativeCodexOAuth !== 'function') {
65
+ return { available: false, refreshed: false, synchronized: false };
66
+ }
67
+ const result = await service.refreshNativeCodexOAuth();
68
+ if (result?.refreshed) {
69
+ console.log('[Codex OAuth] Native OAuth token refreshed during startup');
70
+ } else if (result?.refreshFailed) {
71
+ console.warn('[Codex OAuth] 启动刷新失败,请运行 codex login 重新登录');
72
+ }
73
+ return result;
74
+ } catch (error) {
75
+ console.warn(`[Codex OAuth] 启动同步失败,保留本地凭证: ${error.message}`);
76
+ return {
77
+ available: false,
78
+ refreshed: false,
79
+ synchronized: false,
80
+ error: error.message
81
+ };
82
+ }
83
+ }
84
+
61
85
  function printPortConflictHelp(port) {
62
86
  console.log(chalk.yellow('\n[TIP] 解决方案:'));
63
87
  console.log(chalk.gray(' 1. 运行 ctx 命令,选择"配置端口"修改端口'));
@@ -335,6 +359,7 @@ async function startServer(port, host = '127.0.0.1', options = {}) {
335
359
  console.log(chalk.yellow(' [LOCK] 已启用 LAN 安全保护:远程写操作默认关闭'));
336
360
  }
337
361
  }
362
+ await refreshNativeCodexOAuthOnStartup();
338
363
  // 自动恢复代理状态
339
364
  try {
340
365
  await autoRestoreProxies({ ...platformContext, config });
@@ -382,6 +407,10 @@ async function autoRestoreProxies({ registry, runtime, config, fsImpl = require(
382
407
  try {
383
408
  const result = await driver.restoreOnBoot({ config: resolvedConfig });
384
409
  if (!result || result.status === 'ok') {
410
+ const warnings = result?.warnings || result?.data?.warnings || result?.result?.warnings || [];
411
+ warnings.forEach((warning) => {
412
+ console.log(chalk.yellow(`[WARN] ${platform.label || key}: ${warning}`));
413
+ });
385
414
  const port = result?.port;
386
415
  const suffix = port
387
416
  ? platform.proxyMode === 'managed'
@@ -464,5 +493,10 @@ async function performStartupHealthCheck({ config = loadConfig() } = {}) {
464
493
 
465
494
  module.exports = {
466
495
  startServer,
467
- _test: { autoRestoreProxies, performStartupHealthCheck, traceStartupMemory }
496
+ _test: {
497
+ autoRestoreProxies,
498
+ performStartupHealthCheck,
499
+ traceStartupMemory,
500
+ refreshNativeCodexOAuthOnStartup
501
+ }
468
502
  };
@@ -32,9 +32,18 @@ const CLAUDE_DIRS = {
32
32
  // Valid config types
33
33
  const CONFIG_TYPES = ['skills', 'commands', 'agents', 'plugins'];
34
34
 
35
+ function supportsManagedResources(platform) {
36
+ const resourceTypes = platform?.resourceTypes;
37
+ if (!resourceTypes || typeof resourceTypes !== 'object' || Array.isArray(resourceTypes)) {
38
+ return true;
39
+ }
40
+ return CONFIG_TYPES.some(type => resourceTypes[type] !== false);
41
+ }
42
+
35
43
  function getSupportedPlatforms(registry = getPlatformContext().registry) {
36
44
  if (!registry || typeof registry.list !== 'function') return [];
37
45
  return registry.list()
46
+ .filter(supportsManagedResources)
38
47
  .map(platform => platform && platform.key)
39
48
  .filter(Boolean);
40
49
  }
@@ -43,7 +52,7 @@ function buildPlatformSupport(registry = getPlatformContext().registry) {
43
52
  const support = Object.fromEntries(CONFIG_TYPES.map(type => [type, {}]));
44
53
  for (const platform of (registry?.list?.() || [])) {
45
54
  const key = platform && platform.key;
46
- if (!key) continue;
55
+ if (!key || !supportsManagedResources(platform)) continue;
47
56
  const resourceDriver = platform.capabilities?.resourceSync;
48
57
  for (const type of CONFIG_TYPES) {
49
58
  const typeCapability = platform.capabilities && Object.prototype.hasOwnProperty.call(platform.capabilities, type)
@@ -26,6 +26,7 @@ function getAiConfigMap(registry = getPlatformContext().registry) {
26
26
  return Object.fromEntries(
27
27
  registry.list({ enabledOnly: true })
28
28
  .filter(platform => platform && platform.key)
29
+ .filter(platform => platform.resourceTypes?.commands !== false)
29
30
  .map(platform => [platform.key, {
30
31
  fileName: platform.promptFile || null,
31
32
  name: platform.promptLabel