@axhub/genie 0.2.7 → 0.2.8

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 (117) hide show
  1. package/dist/api-docs.html +2 -2
  2. package/dist/assets/App-CTKZtqB1.js +460 -0
  3. package/dist/assets/App-qxJ8_QYu.css +32 -0
  4. package/dist/assets/ReviewApp-DM6BNAzR.js +1 -0
  5. package/dist/assets/{_basePickBy-C19AekOu.js → _basePickBy-CqJbRZ9y.js} +1 -1
  6. package/dist/assets/{_baseUniq-JsnevLw_.js → _baseUniq-BS8YH8jO.js} +1 -1
  7. package/dist/assets/{arc-BLpcuBlf.js → arc-BBmKEN-S.js} +1 -1
  8. package/dist/assets/architectureDiagram-2XIMDMQ5-N5lcb82R.js +36 -0
  9. package/dist/assets/{blockDiagram-WCTKOSBZ-DQBLwsUS.js → blockDiagram-WCTKOSBZ-DTMwHuLn.js} +3 -3
  10. package/dist/assets/c4Diagram-IC4MRINW-BTKlkXI9.js +10 -0
  11. package/dist/assets/channel-1oJBvF-0.js +1 -0
  12. package/dist/assets/{chunk-4BX2VUAB-De63kbgc.js → chunk-4BX2VUAB-DUdoTxAc.js} +1 -1
  13. package/dist/assets/{chunk-55IACEB6-DtTDDdM9.js → chunk-55IACEB6-Bm_92xe4.js} +1 -1
  14. package/dist/assets/{chunk-FMBD7UC4-DHuwd8tw.js → chunk-FMBD7UC4-CGW0g62g.js} +1 -1
  15. package/dist/assets/{chunk-JSJVCQXG-BgytFtmO.js → chunk-JSJVCQXG-DYkTH3w1.js} +1 -1
  16. package/dist/assets/{chunk-KX2RTZJC-nZdp86aN.js → chunk-KX2RTZJC-C9oTlISU.js} +1 -1
  17. package/dist/assets/chunk-NQ4KR5QH-CM50ygWP.js +220 -0
  18. package/dist/assets/{chunk-QZHKN3VN-DvUQ3mnO.js → chunk-QZHKN3VN-7dzpYeNJ.js} +1 -1
  19. package/dist/assets/chunk-WL4C6EOR-Cm9nQrsr.js +189 -0
  20. package/dist/assets/classDiagram-VBA2DB6C-d5TeKFM4.js +1 -0
  21. package/dist/assets/classDiagram-v2-RAHNMMFH-d5TeKFM4.js +1 -0
  22. package/dist/assets/clone-CinxIlEu.js +1 -0
  23. package/dist/assets/cose-bilkent-S5V4N54A-Ccp_p0JZ.js +1 -0
  24. package/dist/assets/cytoscape.esm-2ZfV8NB5.js +331 -0
  25. package/dist/assets/{dagre-KLK3FWXG-CHYIvW47.js → dagre-KLK3FWXG-fBwTLUp9.js} +1 -1
  26. package/dist/assets/diagram-E7M64L7V-CeNVmFUp.js +24 -0
  27. package/dist/assets/{diagram-IFDJBPK2-Dzsiln_C.js → diagram-IFDJBPK2-CtavyLGa.js} +1 -1
  28. package/dist/assets/{diagram-P4PSJMXO-DKnGbUpE.js → diagram-P4PSJMXO-CpQTjQwc.js} +1 -1
  29. package/dist/assets/erDiagram-INFDFZHY-B8R5vwhd.js +70 -0
  30. package/dist/assets/{flowDiagram-PKNHOUZH-BAZ2-jKp.js → flowDiagram-PKNHOUZH-BvkVVwIQ.js} +4 -4
  31. package/dist/assets/ganttDiagram-A5KZAMGK-DOu3hSNa.js +292 -0
  32. package/dist/assets/{gitGraphDiagram-K3NZZRJ6-BflpyjGy.js → gitGraphDiagram-K3NZZRJ6-C7zT67YE.js} +1 -1
  33. package/dist/assets/{graph-suelaXFh.js → graph-D11wiwHo.js} +1 -1
  34. package/dist/assets/highlighted-body-TPN3WLV5-Babpthg-.js +1 -0
  35. package/dist/assets/index-DFxzgWoO.js +2 -0
  36. package/dist/assets/index-YCFGDVKw.css +1 -0
  37. package/dist/assets/{infoDiagram-LFFYTUFH-pfD1FA3p.js → infoDiagram-LFFYTUFH-BmA7IpQG.js} +1 -1
  38. package/dist/assets/ishikawaDiagram-PHBUUO56-BEquZd3E.js +70 -0
  39. package/dist/assets/journeyDiagram-4ABVD52K-BfemGz7f.js +139 -0
  40. package/dist/assets/{kanban-definition-K7BYSVSG-FWinmur1.js → kanban-definition-K7BYSVSG-CWja3mln.js} +5 -5
  41. package/dist/assets/{layout-vcz43XvZ.js → layout-BLUNf-PJ.js} +1 -1
  42. package/dist/assets/{linear-le4gc0vx.js → linear-DukIV_Xv.js} +1 -1
  43. package/dist/assets/mermaid-O7DHMXV3-SgtM28qI.js +1038 -0
  44. package/dist/assets/mindmap-definition-YRQLILUH-4UjqXITU.js +68 -0
  45. package/dist/assets/{pieDiagram-SKSYHLDU-C7PKDh3b.js → pieDiagram-SKSYHLDU-8AxqJd0M.js} +2 -2
  46. package/dist/assets/quadrantDiagram-337W2JSQ-D60m8V8r.js +7 -0
  47. package/dist/assets/requirementDiagram-Z7DCOOCP-zqh9jBVf.js +73 -0
  48. package/dist/assets/{sankeyDiagram-WA2Y5GQK-4gulcOP4.js → sankeyDiagram-WA2Y5GQK-CDZILTLI.js} +3 -3
  49. package/dist/assets/sequenceDiagram-2WXFIKYE-7BReFd0L.js +145 -0
  50. package/dist/assets/{stateDiagram-RAJIS63D-CB4Vl7qM.js → stateDiagram-RAJIS63D-HPTVdIG4.js} +1 -1
  51. package/dist/assets/stateDiagram-v2-FVOUBMTO-DTUf5_gC.js +1 -0
  52. package/dist/assets/timeline-definition-YZTLITO2-CTVllFgr.js +61 -0
  53. package/dist/assets/{treemap-KZPCXAKY-DZSEE6Hz.js → treemap-KZPCXAKY-BtyxboJZ.js} +58 -58
  54. package/dist/assets/vendor-codemirror-Dz7_EqNA.js +39 -0
  55. package/dist/assets/vendor-react-Cpt6D04s.js +59 -0
  56. package/dist/assets/vendor-xterm-DfaPXD3y.js +66 -0
  57. package/dist/assets/{vennDiagram-LZ73GAT5-8E_G06fI.js → vennDiagram-LZ73GAT5-D96ZI6Mg.js} +4 -4
  58. package/dist/assets/xychartDiagram-JWTSCODW-eRk-39YO.js +7 -0
  59. package/dist/index.html +4 -4
  60. package/package.json +34 -33
  61. package/server/acp-runtime/client.js +82 -15
  62. package/server/acp-runtime/index.js +5 -16
  63. package/server/channels/runtime/AgentRuntimeAdapter.js +1 -10
  64. package/server/claude-sdk.js +1 -3
  65. package/server/cli.js +136 -0
  66. package/server/gemini-cli.js +1 -3
  67. package/server/index.js +86 -14
  68. package/server/openai-codex.js +1 -3
  69. package/server/opencode-cli.js +1 -3
  70. package/server/projects.js +128 -85
  71. package/server/routes/cc-connect.js +1131 -0
  72. package/server/routes/cli-auth.js +1 -73
  73. package/server/routes/commands.js +4 -9
  74. package/server/routes/projects.js +45 -24
  75. package/server/session-core/providerDiscovery.js +8 -3
  76. package/server/utils/ccConnectManager.js +390 -0
  77. package/server/utils/ccConnectState.js +575 -0
  78. package/server/utils/resolveCommandPath.js +71 -0
  79. package/server/utils/workspaceRoots.js +154 -0
  80. package/dist/assets/App-BWSqiXAT.js +0 -220
  81. package/dist/assets/App-DrlLKa8f.css +0 -1
  82. package/dist/assets/ReviewApp-nz3mbArg.js +0 -1
  83. package/dist/assets/architectureDiagram-2XIMDMQ5-CarjBOOv.js +0 -36
  84. package/dist/assets/c4Diagram-IC4MRINW-CGobwBIj.js +0 -10
  85. package/dist/assets/channel-DkFNxV_H.js +0 -1
  86. package/dist/assets/chunk-NQ4KR5QH-CMH6EDP2.js +0 -220
  87. package/dist/assets/chunk-WL4C6EOR-Dn7db_6t.js +0 -189
  88. package/dist/assets/classDiagram-VBA2DB6C-DtwCEe8S.js +0 -1
  89. package/dist/assets/classDiagram-v2-RAHNMMFH-DtwCEe8S.js +0 -1
  90. package/dist/assets/clone-C0lCEIEO.js +0 -1
  91. package/dist/assets/cose-bilkent-S5V4N54A-DD_nzqsz.js +0 -1
  92. package/dist/assets/cytoscape.esm-5J0xJHOV.js +0 -321
  93. package/dist/assets/diagram-E7M64L7V-TVdvHtGc.js +0 -24
  94. package/dist/assets/erDiagram-INFDFZHY-5Kw0bByo.js +0 -70
  95. package/dist/assets/ganttDiagram-A5KZAMGK-CsADFkcq.js +0 -292
  96. package/dist/assets/highlighted-body-OFNGDK62-CZrBMazC.js +0 -1
  97. package/dist/assets/index-B01NxbUv.css +0 -1
  98. package/dist/assets/index-DW5pGgQ_.js +0 -2
  99. package/dist/assets/ishikawaDiagram-PHBUUO56-ndm9snwO.js +0 -70
  100. package/dist/assets/journeyDiagram-4ABVD52K-HgF2t7z5.js +0 -139
  101. package/dist/assets/mermaid-GHXKKRXX-CK8m3lad.js +0 -870
  102. package/dist/assets/mindmap-definition-YRQLILUH-CNq9SKj4.js +0 -68
  103. package/dist/assets/quadrantDiagram-337W2JSQ-B7FnztNO.js +0 -7
  104. package/dist/assets/requirementDiagram-Z7DCOOCP-Bl_BM2Th.js +0 -73
  105. package/dist/assets/sequenceDiagram-2WXFIKYE-VEuJDwyJ.js +0 -145
  106. package/dist/assets/stateDiagram-v2-FVOUBMTO-C85ucl39.js +0 -1
  107. package/dist/assets/timeline-definition-YZTLITO2-BPGKhi7f.js +0 -61
  108. package/dist/assets/vendor-codemirror-CyOKkaQZ.js +0 -31
  109. package/dist/assets/vendor-react-CP4yFTs7.js +0 -8
  110. package/dist/assets/vendor-xterm-DfcmCpbH.js +0 -66
  111. package/dist/assets/xychartDiagram-JWTSCODW-CbBk50-O.js +0 -7
  112. package/server/acp-runtime/client.test.js +0 -688
  113. package/server/acp-runtime/session-store.test.js +0 -89
  114. package/server/cli.test.js +0 -76
  115. package/server/external-agent/service.test.js +0 -53
  116. package/server/external-agent/ws.test.js +0 -289
  117. package/shared/conversationEvents.test.js +0 -403
@@ -1,10 +1,4 @@
1
1
  import { resolveWorkingDirectory } from '../utils/defaultWorkingDirectory.js';
2
- import {
3
- CLAUDE_MODELS,
4
- CODEX_MODELS,
5
- GEMINI_MODELS,
6
- OPENCODE_MODELS
7
- } from '../../shared/modelConstants.js';
8
2
  import { AcpClient } from './client.js';
9
3
  import {
10
4
  findAcpSessionRecord,
@@ -54,16 +48,11 @@ function registerActiveClient(provider, sessionId, client) {
54
48
  return entry;
55
49
  }
56
50
 
57
- function resolveDefaultModel(agentKey, requestedModel) {
58
- if (requestedModel) {
59
- return requestedModel;
60
- }
61
-
62
- if (agentKey === 'claude') return CLAUDE_MODELS.DEFAULT;
63
- if (agentKey === 'codex') return CODEX_MODELS.DEFAULT;
64
- if (agentKey === 'gemini') return GEMINI_MODELS.DEFAULT;
65
- if (agentKey === 'opencode') return OPENCODE_MODELS.DEFAULT;
66
- return null;
51
+ export function resolveDefaultModel(agentKey, requestedModel) {
52
+ const normalizedRequestedModel = typeof requestedModel === 'string'
53
+ ? requestedModel.trim()
54
+ : '';
55
+ return normalizedRequestedModel || null;
67
56
  }
68
57
 
69
58
  function unregisterActiveClient(provider, sessionId, client = null) {
@@ -1,4 +1,3 @@
1
- import { CODEX_MODELS, GEMINI_MODELS, OPENCODE_MODELS } from '../../../shared/modelConstants.js';
2
1
  import { executeAgentPrompt } from '../../acp-runtime/index.js';
3
2
 
4
3
  function normalizeBackend(backend) {
@@ -9,13 +8,6 @@ function normalizeBackend(backend) {
9
8
  return 'codex';
10
9
  }
11
10
 
12
- function getDefaultModel(backend) {
13
- if (backend === 'codex') return CODEX_MODELS.DEFAULT;
14
- if (backend === 'gemini') return GEMINI_MODELS.DEFAULT;
15
- if (backend === 'opencode') return OPENCODE_MODELS.DEFAULT;
16
- return undefined;
17
- }
18
-
19
11
  function createWriter(callbacks) {
20
12
  const state = {
21
13
  sessionId: null,
@@ -96,7 +88,6 @@ export async function runBackendSession({
96
88
  onError,
97
89
  }) {
98
90
  const resolvedBackend = normalizeBackend(backend);
99
- const resolvedModel = model || getDefaultModel(resolvedBackend);
100
91
 
101
92
  const writer = createWriter({
102
93
  onSessionId,
@@ -108,7 +99,7 @@ export async function runBackendSession({
108
99
  projectPath,
109
100
  cwd: projectPath,
110
101
  sessionId: sessionId || undefined,
111
- model: resolvedModel,
102
+ model: model || undefined,
112
103
  permissionMode: 'bypassPermissions',
113
104
  resume: !!sessionId,
114
105
  skipPermissions: true,
@@ -5,15 +5,13 @@ import {
5
5
  isAgentSessionActive,
6
6
  resolveAgentPermission
7
7
  } from './acp-runtime/index.js';
8
- import { CLAUDE_MODELS } from '../shared/modelConstants.js';
9
8
 
10
9
  export async function queryClaudeSDK(command, options = {}, writer) {
11
10
  return executeAgentPrompt({
12
11
  agentKey: 'claude',
13
12
  command,
14
13
  options: {
15
- ...options,
16
- model: options.model || CLAUDE_MODELS.DEFAULT
14
+ ...options
17
15
  },
18
16
  writer
19
17
  });
package/server/cli.js CHANGED
@@ -24,6 +24,10 @@ import {
24
24
  DEFAULT_WORKING_DIRECTORY_ENV,
25
25
  getConfiguredDefaultProjectPath,
26
26
  } from './utils/defaultWorkingDirectory.js';
27
+ import {
28
+ getCcConnectConnectionSummary,
29
+ updateCcConnectPlatformBinding,
30
+ } from './utils/ccConnectManager.js';
27
31
 
28
32
  const __filename = fileURLToPath(import.meta.url);
29
33
  const __dirname = dirname(__filename);
@@ -374,6 +378,27 @@ function buildEditorErrorResponse({ requestId, channel = null, targetClientId =
374
378
  };
375
379
  }
376
380
 
381
+ function buildCcConnectSuccessResponse({ command, platform = null, data = {} }) {
382
+ return {
383
+ ok: true,
384
+ command,
385
+ platform,
386
+ data,
387
+ };
388
+ }
389
+
390
+ function buildCcConnectErrorResponse({ command, platform = null, code, message }) {
391
+ return {
392
+ ok: false,
393
+ command,
394
+ platform,
395
+ error: {
396
+ code,
397
+ message,
398
+ },
399
+ };
400
+ }
401
+
377
402
  function printJson(payload) {
378
403
  console.log(JSON.stringify(payload, null, 2));
379
404
  }
@@ -627,6 +652,96 @@ async function runEditorCommand(positionals, options) {
627
652
  }
628
653
  }
629
654
 
655
+ function buildCcConnectCommand(positionals, options) {
656
+ const commandPath = positionals.join(' ');
657
+ const requestedPlatform = typeof options.platform === 'string' ? options.platform.trim() : '';
658
+
659
+ if (commandPath === 'cc-connect' || commandPath === 'cc-connect status') {
660
+ return {
661
+ command: 'cc-connect status',
662
+ action: 'status',
663
+ platform: requestedPlatform || null,
664
+ };
665
+ }
666
+
667
+ if (commandPath === 'cc-connect set') {
668
+ const platform = requireOption(options, 'platform', '--platform is required');
669
+ const provider = typeof options.provider === 'string' && options.provider.trim()
670
+ ? options.provider.trim()
671
+ : null;
672
+ const projectPath = typeof options.projectPath === 'string' && options.projectPath.trim()
673
+ ? path.resolve(options.projectPath)
674
+ : null;
675
+
676
+ if (!provider && !projectPath) {
677
+ throw new Error('At least one of --provider or --project-path is required.');
678
+ }
679
+
680
+ return {
681
+ command: 'cc-connect set',
682
+ action: 'set',
683
+ platform,
684
+ provider,
685
+ projectPath,
686
+ };
687
+ }
688
+
689
+ throw new Error(`Unknown cc-connect command: ${commandPath}`);
690
+ }
691
+
692
+ async function runCcConnectCommand(positionals, options) {
693
+ const command = buildCcConnectCommand(positionals, options);
694
+
695
+ try {
696
+ if (command.action === 'status') {
697
+ const summary = await getCcConnectConnectionSummary(command.platform);
698
+ const data = command.platform
699
+ ? {
700
+ ccConnect: summary.ccConnect,
701
+ providers: summary.providers,
702
+ platform: summary.platform,
703
+ }
704
+ : {
705
+ ccConnect: summary.ccConnect,
706
+ providers: summary.providers,
707
+ platforms: summary.platforms,
708
+ };
709
+
710
+ printJson(buildCcConnectSuccessResponse({
711
+ command: command.command,
712
+ platform: command.platform,
713
+ data,
714
+ }));
715
+ return;
716
+ }
717
+
718
+ if (command.action === 'set') {
719
+ const result = await updateCcConnectPlatformBinding({
720
+ platformId: command.platform,
721
+ provider: command.provider === null ? undefined : command.provider,
722
+ projectPath: command.projectPath === null ? undefined : command.projectPath,
723
+ });
724
+
725
+ printJson(buildCcConnectSuccessResponse({
726
+ command: command.command,
727
+ platform: result.platform,
728
+ data: result,
729
+ }));
730
+ return;
731
+ }
732
+
733
+ throw new Error(`Unsupported cc-connect action: ${command.action}`);
734
+ } catch (error) {
735
+ printJson(buildCcConnectErrorResponse({
736
+ command: command.command,
737
+ platform: command.platform || null,
738
+ code: error.code || 'CC_CONNECT_COMMAND_FAILED',
739
+ message: error.message,
740
+ }));
741
+ process.exit(1);
742
+ }
743
+ }
744
+
630
745
  // Show status command
631
746
  function showStatus(options = {}) {
632
747
  const runtimeStatus = getRuntimeStatus();
@@ -754,6 +869,7 @@ Commands:
754
869
  start Start the Axhub Genie server (default)
755
870
  stop Stop the running Axhub Genie server
756
871
  status Show configuration and data locations
872
+ cc-connect Inspect or update platform connection bindings
757
873
  editor Query or control a connected web editor frontend
758
874
  update Update to the latest version
759
875
  help Show this help information
@@ -769,9 +885,12 @@ Options:
769
885
  --json Output JSON (status or editor commands)
770
886
  --api-base <url> Override API base URL for editor commands
771
887
  --api-key <key> API key for /api/agent/ws editor commands
888
+ --platform <id> Target platform for cc-connect commands
889
+ --provider <id> Provider for cc-connect updates or editor task references
772
890
  --channel <name> Integration channel for editor commands
773
891
  --target-client-id <id> Target frontend client ID for editor commands
774
892
  --client-id <id> Optional client filter for editor clients list
893
+ --project-path <path> Project path for cc-connect platform binding updates
775
894
  --element-key <key> Target element key for editor node commands
776
895
  --status <values> Comma-separated status filters for editor nodes list
777
896
  --state <editing|idle> Target editing state for editor editing set
@@ -790,6 +909,9 @@ Examples:
790
909
  $ axhub-genie stop # Stop running server
791
910
  $ axhub-genie status # Show configuration
792
911
  $ axhub-genie status --json # Get machine-readable status
912
+ $ axhub-genie cc-connect status
913
+ $ axhub-genie cc-connect set --platform weixin --provider codex
914
+ $ axhub-genie cc-connect set --platform feishu --project-path /path/to/repo
793
915
  $ axhub-genie editor clients list --channel project-a
794
916
  $ axhub-genie editor snapshot --channel project-a --target-client-id figma-123
795
917
  $ axhub-genie editor nodes list --channel project-a --target-client-id figma-123 --status pending-dispatch,dirty
@@ -940,10 +1062,18 @@ function parseArgs(args) {
940
1062
  parsed.options.apiKey = args[++i];
941
1063
  } else if (arg.startsWith('--api-key=')) {
942
1064
  parsed.options.apiKey = arg.split('=')[1];
1065
+ } else if (arg === '--platform') {
1066
+ parsed.options.platform = args[++i];
1067
+ } else if (arg.startsWith('--platform=')) {
1068
+ parsed.options.platform = arg.split('=')[1];
943
1069
  } else if (arg === '--channel') {
944
1070
  parsed.options.channel = args[++i];
945
1071
  } else if (arg.startsWith('--channel=')) {
946
1072
  parsed.options.channel = arg.split('=')[1];
1073
+ } else if (arg === '--project-path') {
1074
+ parsed.options.projectPath = args[++i];
1075
+ } else if (arg.startsWith('--project-path=')) {
1076
+ parsed.options.projectPath = arg.split('=')[1];
947
1077
  } else if (arg === '--target-client-id') {
948
1078
  parsed.options.targetClientId = args[++i];
949
1079
  } else if (arg.startsWith('--target-client-id=')) {
@@ -1041,6 +1171,9 @@ async function main() {
1041
1171
  case 'editor':
1042
1172
  await runEditorCommand(positionals, options);
1043
1173
  break;
1174
+ case 'cc-connect':
1175
+ await runCcConnectCommand(positionals, options);
1176
+ break;
1044
1177
  case 'status':
1045
1178
  case 'info':
1046
1179
  showStatus(options);
@@ -1078,6 +1211,9 @@ if (isDirectExecution) {
1078
1211
  }
1079
1212
 
1080
1213
  export {
1214
+ buildCcConnectCommand,
1215
+ buildCcConnectErrorResponse,
1216
+ buildCcConnectSuccessResponse,
1081
1217
  buildEditorRequest,
1082
1218
  buildEditorSuccessResponse,
1083
1219
  buildEditorErrorResponse,
@@ -4,15 +4,13 @@ import {
4
4
  getActiveAgentSessions,
5
5
  isAgentSessionActive
6
6
  } from './acp-runtime/index.js';
7
- import { GEMINI_MODELS } from '../shared/modelConstants.js';
8
7
 
9
8
  export async function queryGemini(command, options = {}, writer) {
10
9
  return executeAgentPrompt({
11
10
  agentKey: 'gemini',
12
11
  command,
13
12
  options: {
14
- ...options,
15
- model: options.model || GEMINI_MODELS.DEFAULT
13
+ ...options
16
14
  },
17
15
  writer
18
16
  });
package/server/index.js CHANGED
@@ -113,8 +113,20 @@ import commandsRoutes from './routes/commands.js';
113
113
  import settingsRoutes from './routes/settings.js';
114
114
  import channelsRoutes from './routes/channels.js';
115
115
  import agentRoutes from './routes/agent.js';
116
- import projectsRoutes, { WORKSPACES_ROOT, validateWorkspacePath } from './routes/projects.js';
116
+ import projectsRoutes, {
117
+ DEFAULT_WORKSPACES_ROOT,
118
+ HAS_WORKSPACES_ROOT_RESTRICTION,
119
+ WORKSPACES_ROOTS,
120
+ validateWorkspacePath
121
+ } from './routes/projects.js';
122
+ import {
123
+ UNIX_WORKSPACE_ROOTS,
124
+ buildWorkspaceRootSuggestions,
125
+ expandWorkspacePath,
126
+ shouldUseVirtualWorkspaceRoots
127
+ } from './utils/workspaceRoots.js';
117
128
  import cliAuthRoutes, { detectProviderInstallationStatus } from './routes/cli-auth.js';
129
+ import ccConnectRoutes from './routes/cc-connect.js';
118
130
  import userRoutes from './routes/user.js';
119
131
  import codexRoutes from './routes/codex.js';
120
132
  import opencodeRoutes from './routes/opencode.js';
@@ -138,6 +150,7 @@ const UPDATE_PACKAGE_NAME = process.env.UPDATE_PACKAGE_NAME || packageInfo.id ||
138
150
  const VERSION_CACHE_TTL_MS = 60 * 60 * 1000; // 1 hour
139
151
  let cachedSystemVersion = null;
140
152
  let cachedSystemVersionExpiresAt = 0;
153
+ const WINDOWS_DRIVES_ROOT = '__windows_drives__';
141
154
  const RUNTIME_STATUS_PATH = (() => {
142
155
  if (process.env.AXHUB_GENIE_STATUS_PATH) {
143
156
  return process.env.AXHUB_GENIE_STATUS_PATH;
@@ -504,6 +517,7 @@ app.use('/api/channels', authenticateToken, channelsRoutes);
504
517
 
505
518
  // CLI Authentication API Routes (protected)
506
519
  app.use('/api/cli', authenticateToken, cliAuthRoutes);
520
+ app.use('/api/cc-connect', authenticateToken, ccConnectRoutes);
507
521
 
508
522
  // User API Routes (protected)
509
523
  app.use('/api/user', authenticateToken, userRoutes);
@@ -743,16 +757,31 @@ app.post('/api/projects/create', authenticateToken, async (req, res) => {
743
757
  }
744
758
  });
745
759
 
746
- const expandWorkspacePath = (inputPath) => {
747
- if (!inputPath) return inputPath;
748
- if (inputPath === '~') {
749
- return WORKSPACES_ROOT;
750
- }
751
- if (inputPath.startsWith('~/') || inputPath.startsWith('~\\')) {
752
- return path.join(WORKSPACES_ROOT, inputPath.slice(2));
753
- }
754
- return inputPath;
755
- };
760
+ async function listWindowsDrives() {
761
+ const checks = await Promise.all(
762
+ 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'.split('').map(async (letter) => {
763
+ const drivePath = `${letter}:\\`;
764
+ try {
765
+ await fsPromises.access(drivePath, fs.constants.R_OK);
766
+ const stats = await fsPromises.stat(drivePath);
767
+ if (!stats.isDirectory()) {
768
+ return null;
769
+ }
770
+
771
+ return {
772
+ path: drivePath,
773
+ name: drivePath,
774
+ type: 'directory',
775
+ isDrive: true
776
+ };
777
+ } catch (error) {
778
+ return null;
779
+ }
780
+ })
781
+ );
782
+
783
+ return checks.filter(Boolean);
784
+ }
756
785
 
757
786
  // Browse filesystem endpoint for project suggestions - uses existing getFileTree
758
787
  app.get('/api/browse-filesystem', authenticateToken, async (req, res) => {
@@ -760,9 +789,47 @@ app.get('/api/browse-filesystem', authenticateToken, async (req, res) => {
760
789
  const { path: dirPath } = req.query;
761
790
 
762
791
  console.log('[API] Browse filesystem request for path:', dirPath);
763
- console.log('[API] WORKSPACES_ROOT is:', WORKSPACES_ROOT);
792
+ console.log('[API] WORKSPACES_ROOTS are:', WORKSPACES_ROOTS.length > 0 ? WORKSPACES_ROOTS : '(unrestricted)');
793
+
794
+ if (process.platform === 'win32' && dirPath === WINDOWS_DRIVES_ROOT) {
795
+ const suggestions = await listWindowsDrives();
796
+ return res.json({
797
+ path: WINDOWS_DRIVES_ROOT,
798
+ displayPath: 'This PC',
799
+ suggestions,
800
+ platform: process.platform,
801
+ virtualRoot: 'windows-drives',
802
+ hasWorkspaceRootRestriction: HAS_WORKSPACES_ROOT_RESTRICTION,
803
+ allowedRoots: WORKSPACES_ROOTS
804
+ });
805
+ }
806
+
807
+ if (shouldUseVirtualWorkspaceRoots({ dirPath })) {
808
+ const suggestions = buildWorkspaceRootSuggestions({
809
+ allowedWorkspaceRoots: WORKSPACES_ROOTS,
810
+ homeDir: DEFAULT_WORKSPACES_ROOT,
811
+ platform: process.platform
812
+ }).filter((entry) => {
813
+ try {
814
+ return fs.existsSync(entry.path);
815
+ } catch (error) {
816
+ return false;
817
+ }
818
+ });
819
+
820
+ return res.json({
821
+ path: UNIX_WORKSPACE_ROOTS,
822
+ displayPath: 'Allowed workspace roots',
823
+ suggestions,
824
+ platform: process.platform,
825
+ virtualRoot: 'workspace-roots',
826
+ hasWorkspaceRootRestriction: HAS_WORKSPACES_ROOT_RESTRICTION,
827
+ allowedRoots: WORKSPACES_ROOTS
828
+ });
829
+ }
830
+
764
831
  // Default to home directory if no path provided
765
- const defaultRoot = WORKSPACES_ROOT;
832
+ const defaultRoot = DEFAULT_WORKSPACES_ROOT;
766
833
  let targetPath = dirPath ? expandWorkspacePath(dirPath) : defaultRoot;
767
834
 
768
835
  // Resolve and normalize the path
@@ -826,7 +893,12 @@ app.get('/api/browse-filesystem', authenticateToken, async (req, res) => {
826
893
 
827
894
  res.json({
828
895
  path: resolvedPath,
829
- suggestions: suggestions
896
+ displayPath: resolvedPath,
897
+ suggestions: suggestions,
898
+ platform: process.platform,
899
+ virtualRoot: null,
900
+ hasWorkspaceRootRestriction: HAS_WORKSPACES_ROOT_RESTRICTION,
901
+ allowedRoots: WORKSPACES_ROOTS
830
902
  });
831
903
 
832
904
  } catch (error) {
@@ -4,15 +4,13 @@ import {
4
4
  getActiveAgentSessions,
5
5
  isAgentSessionActive
6
6
  } from './acp-runtime/index.js';
7
- import { CODEX_MODELS } from '../shared/modelConstants.js';
8
7
 
9
8
  export async function queryCodex(command, options = {}, writer) {
10
9
  return executeAgentPrompt({
11
10
  agentKey: 'codex',
12
11
  command,
13
12
  options: {
14
- ...options,
15
- model: options.model || CODEX_MODELS.DEFAULT
13
+ ...options
16
14
  },
17
15
  writer
18
16
  });
@@ -4,7 +4,6 @@ import {
4
4
  getActiveAgentSessions,
5
5
  isAgentSessionActive
6
6
  } from './acp-runtime/index.js';
7
- import { OPENCODE_MODELS } from '../shared/modelConstants.js';
8
7
  import { spawnCommand } from './utils/spawnCommand.js';
9
8
  import { resolveWorkingDirectory } from './utils/defaultWorkingDirectory.js';
10
9
 
@@ -84,8 +83,7 @@ export async function queryOpencode(command, options = {}, writer) {
84
83
  agentKey: 'opencode',
85
84
  command,
86
85
  options: {
87
- ...options,
88
- model: options.model || OPENCODE_MODELS.DEFAULT
86
+ ...options
89
87
  },
90
88
  writer
91
89
  });