@axhub/genie 0.2.8 → 0.2.10

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 (106) hide show
  1. package/LICENSE +21 -675
  2. package/dist/api-docs.html +2 -2
  3. package/dist/assets/App-CYCCsgwf.js +264 -0
  4. package/dist/assets/ReviewApp-0srHIXwb.js +1 -0
  5. package/dist/assets/{_basePickBy-CqJbRZ9y.js → _basePickBy-DVVb07UV.js} +1 -1
  6. package/dist/assets/{_baseUniq-BS8YH8jO.js → _baseUniq-BtbziL5G.js} +1 -1
  7. package/dist/assets/{arc-BBmKEN-S.js → arc-BsCC8yBD.js} +1 -1
  8. package/dist/assets/{architectureDiagram-2XIMDMQ5-N5lcb82R.js → architectureDiagram-2XIMDMQ5-woFp6eNI.js} +1 -1
  9. package/dist/assets/{blockDiagram-WCTKOSBZ-DTMwHuLn.js → blockDiagram-WCTKOSBZ-ya8VAc2k.js} +1 -1
  10. package/dist/assets/{c4Diagram-IC4MRINW-BTKlkXI9.js → c4Diagram-IC4MRINW-CY1dZmIZ.js} +1 -1
  11. package/dist/assets/channel-BMhScXFe.js +1 -0
  12. package/dist/assets/{chunk-4BX2VUAB-DUdoTxAc.js → chunk-4BX2VUAB-CR1lAd74.js} +1 -1
  13. package/dist/assets/{chunk-55IACEB6-Bm_92xe4.js → chunk-55IACEB6-CP98WcFC.js} +1 -1
  14. package/dist/assets/{chunk-FMBD7UC4-CGW0g62g.js → chunk-FMBD7UC4-D9c7ijAB.js} +1 -1
  15. package/dist/assets/{chunk-JSJVCQXG-DYkTH3w1.js → chunk-JSJVCQXG-DQAGYOn-.js} +1 -1
  16. package/dist/assets/{chunk-KX2RTZJC-C9oTlISU.js → chunk-KX2RTZJC-BbTXiDq7.js} +1 -1
  17. package/dist/assets/{chunk-NQ4KR5QH-CM50ygWP.js → chunk-NQ4KR5QH-BI6AX0dr.js} +1 -1
  18. package/dist/assets/{chunk-QZHKN3VN-7dzpYeNJ.js → chunk-QZHKN3VN-DB3V2Ifo.js} +1 -1
  19. package/dist/assets/{chunk-WL4C6EOR-Cm9nQrsr.js → chunk-WL4C6EOR-DhzTthv6.js} +1 -1
  20. package/dist/assets/classDiagram-VBA2DB6C-CMIxlWcT.js +1 -0
  21. package/dist/assets/classDiagram-v2-RAHNMMFH-CMIxlWcT.js +1 -0
  22. package/dist/assets/clone-BPqOt4r3.js +1 -0
  23. package/dist/assets/{cose-bilkent-S5V4N54A-Ccp_p0JZ.js → cose-bilkent-S5V4N54A-BQ09ZE2j.js} +1 -1
  24. package/dist/assets/{dagre-KLK3FWXG-fBwTLUp9.js → dagre-KLK3FWXG-Dc2ueD_R.js} +1 -1
  25. package/dist/assets/{diagram-E7M64L7V-CeNVmFUp.js → diagram-E7M64L7V-DP-LsQoL.js} +1 -1
  26. package/dist/assets/{diagram-IFDJBPK2-CtavyLGa.js → diagram-IFDJBPK2-Cg6r42cB.js} +1 -1
  27. package/dist/assets/{diagram-P4PSJMXO-CpQTjQwc.js → diagram-P4PSJMXO-aHsfoUZE.js} +1 -1
  28. package/dist/assets/{erDiagram-INFDFZHY-B8R5vwhd.js → erDiagram-INFDFZHY-qBXJ4aAz.js} +1 -1
  29. package/dist/assets/{flowDiagram-PKNHOUZH-BvkVVwIQ.js → flowDiagram-PKNHOUZH-D_13emJM.js} +1 -1
  30. package/dist/assets/{ganttDiagram-A5KZAMGK-DOu3hSNa.js → ganttDiagram-A5KZAMGK-BvIcOLwz.js} +1 -1
  31. package/dist/assets/{gitGraphDiagram-K3NZZRJ6-C7zT67YE.js → gitGraphDiagram-K3NZZRJ6-ad0vvNcU.js} +1 -1
  32. package/dist/assets/{graph-D11wiwHo.js → graph-CeJCMjan.js} +1 -1
  33. package/dist/assets/{highlighted-body-TPN3WLV5-Babpthg-.js → highlighted-body-TPN3WLV5-B_novwSz.js} +1 -1
  34. package/dist/assets/index-C514cLyb.js +2 -0
  35. package/dist/assets/index-h1DBl_g3.css +1 -0
  36. package/dist/assets/{infoDiagram-LFFYTUFH-BmA7IpQG.js → infoDiagram-LFFYTUFH-lOxAqb3m.js} +1 -1
  37. package/dist/assets/{ishikawaDiagram-PHBUUO56-BEquZd3E.js → ishikawaDiagram-PHBUUO56-DIr-51gj.js} +1 -1
  38. package/dist/assets/{journeyDiagram-4ABVD52K-BfemGz7f.js → journeyDiagram-4ABVD52K-CYcIW0ZU.js} +1 -1
  39. package/dist/assets/{kanban-definition-K7BYSVSG-CWja3mln.js → kanban-definition-K7BYSVSG-C1ZK616a.js} +1 -1
  40. package/dist/assets/{layout-BLUNf-PJ.js → layout-CI2RM-v6.js} +1 -1
  41. package/dist/assets/{linear-DukIV_Xv.js → linear-DE7bISck.js} +1 -1
  42. package/dist/assets/{mermaid-O7DHMXV3-SgtM28qI.js → mermaid-O7DHMXV3-XxAJo8EK.js} +6 -6
  43. package/dist/assets/{mindmap-definition-YRQLILUH-4UjqXITU.js → mindmap-definition-YRQLILUH-Dz6EFjmn.js} +1 -1
  44. package/dist/assets/{pieDiagram-SKSYHLDU-8AxqJd0M.js → pieDiagram-SKSYHLDU-DPpEzUed.js} +1 -1
  45. package/dist/assets/{quadrantDiagram-337W2JSQ-D60m8V8r.js → quadrantDiagram-337W2JSQ-xdoXNet7.js} +1 -1
  46. package/dist/assets/{requirementDiagram-Z7DCOOCP-zqh9jBVf.js → requirementDiagram-Z7DCOOCP-DUq8H3CL.js} +1 -1
  47. package/dist/assets/{sankeyDiagram-WA2Y5GQK-CDZILTLI.js → sankeyDiagram-WA2Y5GQK-CmqEUxRu.js} +1 -1
  48. package/dist/assets/{sequenceDiagram-2WXFIKYE-7BReFd0L.js → sequenceDiagram-2WXFIKYE-DhtXRNiH.js} +1 -1
  49. package/dist/assets/{stateDiagram-RAJIS63D-HPTVdIG4.js → stateDiagram-RAJIS63D-Dj0HOlbN.js} +1 -1
  50. package/dist/assets/stateDiagram-v2-FVOUBMTO-C9utf5gv.js +1 -0
  51. package/dist/assets/{timeline-definition-YZTLITO2-CTVllFgr.js → timeline-definition-YZTLITO2-DUuJzZB5.js} +1 -1
  52. package/dist/assets/{treemap-KZPCXAKY-BtyxboJZ.js → treemap-KZPCXAKY-DpYBQ0qr.js} +1 -1
  53. package/dist/assets/vendor-codemirror-CMHSJ_9p.js +9 -0
  54. package/dist/assets/{vendor-react-Cpt6D04s.js → vendor-react-xmA_f8ig.js} +1 -1
  55. package/dist/assets/{vennDiagram-LZ73GAT5-D96ZI6Mg.js → vennDiagram-LZ73GAT5-DpePUyOd.js} +1 -1
  56. package/dist/assets/{xychartDiagram-JWTSCODW-eRk-39YO.js → xychartDiagram-JWTSCODW-Cfp1I4_U.js} +1 -1
  57. package/dist/index.html +5 -5
  58. package/package.json +8 -7
  59. package/server/acp-runtime/client.js +129 -16
  60. package/server/acp-runtime/index.js +54 -0
  61. package/server/acp-runtime/registry.js +2 -2
  62. package/server/acp-runtime/session-store.js +79 -5
  63. package/server/cli.js +55 -10
  64. package/server/database/db.js +20 -0
  65. package/server/external-agent/service.js +24 -6
  66. package/server/external-agent/ws.js +540 -27
  67. package/server/index.js +112 -151
  68. package/server/lan-access/core.js +79 -0
  69. package/server/lan-access/state.js +102 -0
  70. package/server/middleware/auth.js +57 -14
  71. package/server/projects.js +930 -667
  72. package/server/routes/auth.js +24 -4
  73. package/server/routes/cli-auth.js +21 -25
  74. package/server/routes/codex.js +84 -298
  75. package/server/routes/commands.js +322 -407
  76. package/server/routes/lan-access.js +231 -0
  77. package/server/routes/projects.js +154 -158
  78. package/server/routes/session-core.js +160 -91
  79. package/server/routes/settings.js +113 -99
  80. package/server/session-core/eventStore.js +60 -20
  81. package/server/session-core/providerAdapters.js +75 -38
  82. package/server/session-core/runtimeState.js +8 -0
  83. package/server/session-core/sessionListMerge.js +47 -0
  84. package/shared/conversationEvents.js +174 -15
  85. package/shared/modelConstants.js +79 -99
  86. package/dist/assets/App-CTKZtqB1.js +0 -460
  87. package/dist/assets/ReviewApp-DM6BNAzR.js +0 -1
  88. package/dist/assets/channel-1oJBvF-0.js +0 -1
  89. package/dist/assets/classDiagram-VBA2DB6C-d5TeKFM4.js +0 -1
  90. package/dist/assets/classDiagram-v2-RAHNMMFH-d5TeKFM4.js +0 -1
  91. package/dist/assets/clone-CinxIlEu.js +0 -1
  92. package/dist/assets/index-DFxzgWoO.js +0 -2
  93. package/dist/assets/index-YCFGDVKw.css +0 -1
  94. package/dist/assets/stateDiagram-v2-FVOUBMTO-DTUf5_gC.js +0 -1
  95. package/dist/assets/vendor-codemirror-Dz7_EqNA.js +0 -39
  96. package/server/_legacy-providers/README.md +0 -30
  97. package/server/_legacy-providers/claude-sdk.js +0 -956
  98. package/server/_legacy-providers/gemini-cli.js +0 -368
  99. package/server/_legacy-providers/openai-codex.js +0 -705
  100. package/server/_legacy-providers/opencode-cli.js +0 -674
  101. package/server/routes/git.js +0 -1110
  102. package/server/routes/mcp-utils.js +0 -48
  103. package/server/routes/mcp.js +0 -536
  104. package/server/routes/taskmaster.js +0 -1963
  105. package/server/utils/mcp-detector.js +0 -198
  106. package/server/utils/taskmaster-websocket.js +0 -129
package/server/cli.js CHANGED
@@ -169,6 +169,18 @@ async function waitForRuntimeStatus(pid, timeoutMs = 10000) {
169
169
  return null;
170
170
  }
171
171
 
172
+ function shouldAutoOpenHomepage(options = {}, env = process.env) {
173
+ if (options.noOpen || env.AXHUB_GENIE_NO_OPEN === 'true') {
174
+ return false;
175
+ }
176
+
177
+ if (options.open || env.AXHUB_GENIE_OPEN === 'true') {
178
+ return true;
179
+ }
180
+
181
+ return false;
182
+ }
183
+
172
184
  function isProcessAlive(pid) {
173
185
  if (!Number.isInteger(pid) || pid <= 0) {
174
186
  return false;
@@ -478,6 +490,27 @@ async function sendEditorWebSocketRequest({ apiBaseUrl, apiKey, message, timeout
478
490
  });
479
491
  }
480
492
 
493
+ const RETRYABLE_ERROR_CODES = new Set(['CONNECTION_ERROR', 'CONNECTION_CLOSED', 'REQUEST_TIMEOUT']);
494
+ const CLI_RETRY_DELAY_MS = 1000;
495
+ const CLI_MAX_RETRIES = 1;
496
+
497
+ async function sendEditorWebSocketRequestWithRetry(options) {
498
+ let lastError = null;
499
+ for (let attempt = 0; attempt <= CLI_MAX_RETRIES; attempt++) {
500
+ try {
501
+ return await sendEditorWebSocketRequest(options);
502
+ } catch (error) {
503
+ lastError = error;
504
+ if (attempt < CLI_MAX_RETRIES && RETRYABLE_ERROR_CODES.has(error?.code)) {
505
+ await new Promise((resolve) => setTimeout(resolve, CLI_RETRY_DELAY_MS));
506
+ continue;
507
+ }
508
+ throw error;
509
+ }
510
+ }
511
+ throw lastError;
512
+ }
513
+
481
514
  function resolveOutputDirPath(outputDir) {
482
515
  return path.resolve(outputDir || process.cwd());
483
516
  }
@@ -527,7 +560,9 @@ function buildEditorRequest(positionals, options) {
527
560
  }
528
561
 
529
562
  const channel = requireOption(options, 'channel', '--channel is required for editor commands');
530
- const targetClientId = requireOption(options, 'targetClientId', '--target-client-id is required for editor commands');
563
+ const targetClientId = typeof options.targetClientId === 'string' && options.targetClientId.trim()
564
+ ? options.targetClientId.trim()
565
+ : null;
531
566
 
532
567
  if (commandPath === 'editor snapshot') {
533
568
  return {
@@ -537,7 +572,10 @@ function buildEditorRequest(positionals, options) {
537
572
  message: {
538
573
  type: 'integration.editor.snapshot.get',
539
574
  requestId: scope.requestId,
540
- payload: { channel, targetClientId },
575
+ payload: {
576
+ channel,
577
+ ...(targetClientId ? { targetClientId } : {}),
578
+ },
541
579
  },
542
580
  };
543
581
  }
@@ -552,7 +590,7 @@ function buildEditorRequest(positionals, options) {
552
590
  requestId: scope.requestId,
553
591
  payload: {
554
592
  channel,
555
- targetClientId,
593
+ ...(targetClientId ? { targetClientId } : {}),
556
594
  ...(options.status ? { status: parseCommaSeparatedList(options.status) } : {}),
557
595
  ...(options.elementKey ? { elementKey: String(options.elementKey).trim() } : {}),
558
596
  ...(options.limit ? { limit: parsePositiveInteger(options.limit, '--limit') } : {}),
@@ -571,7 +609,7 @@ function buildEditorRequest(positionals, options) {
571
609
  requestId: scope.requestId,
572
610
  payload: {
573
611
  channel,
574
- targetClientId,
612
+ ...(targetClientId ? { targetClientId } : {}),
575
613
  elementKey: requireOption(options, 'elementKey', '--element-key is required'),
576
614
  downloadPath: resolveOutputDirPath(options.outputDir),
577
615
  },
@@ -589,7 +627,7 @@ function buildEditorRequest(positionals, options) {
589
627
  requestId: scope.requestId,
590
628
  payload: {
591
629
  channel,
592
- targetClientId,
630
+ ...(targetClientId ? { targetClientId } : {}),
593
631
  downloadPath: resolveOutputDirPath(options.outputDir),
594
632
  },
595
633
  },
@@ -606,7 +644,7 @@ function buildEditorRequest(positionals, options) {
606
644
  requestId: scope.requestId,
607
645
  payload: {
608
646
  channel,
609
- targetClientId,
647
+ ...(targetClientId ? { targetClientId } : {}),
610
648
  elementKey: requireOption(options, 'elementKey', '--element-key is required'),
611
649
  state: requireOption(options, 'state', '--state is required'),
612
650
  ...(buildTaskRef(options) ? { taskRef: buildTaskRef(options) } : {}),
@@ -628,7 +666,7 @@ async function runEditorCommand(positionals, options) {
628
666
  const timeoutMs = parsePositiveInteger(options.timeoutMs || DEFAULT_EDITOR_TIMEOUT_MS, '--timeout-ms') || DEFAULT_EDITOR_TIMEOUT_MS;
629
667
 
630
668
  try {
631
- const response = await sendEditorWebSocketRequest({
669
+ const response = await sendEditorWebSocketRequestWithRetry({
632
670
  apiBaseUrl,
633
671
  apiKey: options.apiKey,
634
672
  message: editorRequest.message,
@@ -893,7 +931,7 @@ Options:
893
931
  --project-path <path> Project path for cc-connect platform binding updates
894
932
  --element-key <key> Target element key for editor node commands
895
933
  --status <values> Comma-separated status filters for editor nodes list
896
- --state <editing|idle> Target editing state for editor editing set
934
+ --state <editing|idle|completed|error> Target editing state for editor editing set
897
935
  --limit <n> Maximum number of nodes returned by editor nodes list
898
936
  --output-dir <path> Download directory for screenshot/image export commands
899
937
  --timeout-ms <ms> Timeout for editor WebSocket requests (default: ${DEFAULT_EDITOR_TIMEOUT_MS})
@@ -926,7 +964,8 @@ Environment Variables:
926
964
  CLAUDE_CLI_PATH Set custom Claude CLI path
927
965
  CONTEXT_WINDOW Set context window size (default: 160000)
928
966
  AXHUB_GENIE_STATUS_PATH Set runtime status file path
929
- AXHUB_GENIE_NO_OPEN Set to true to disable auto-opening the homepage
967
+ AXHUB_GENIE_OPEN Set to true to auto-open the homepage after startup
968
+ AXHUB_GENIE_NO_OPEN Set to true to force-disable homepage auto-open
930
969
 
931
970
  Documentation:
932
971
  ${packageJson.homepage || defaultProjectUrl}
@@ -1011,7 +1050,7 @@ async function startServer() {
1011
1050
  // Import and run the server
1012
1051
  await import('./index.js');
1013
1052
 
1014
- if (process.env.AXHUB_GENIE_NO_OPEN === 'true') {
1053
+ if (!shouldAutoOpenHomepage()) {
1015
1054
  return;
1016
1055
  }
1017
1056
 
@@ -1120,6 +1159,8 @@ function parseArgs(args) {
1120
1159
  parsed.options.taskRequestId = arg.split('=')[1];
1121
1160
  } else if (arg === '--json') {
1122
1161
  parsed.options.json = true;
1162
+ } else if (arg === '--open') {
1163
+ parsed.options.open = true;
1123
1164
  } else if (arg === '--no-open') {
1124
1165
  parsed.options.noOpen = true;
1125
1166
  } else if (arg === '--help' || arg === '-h') {
@@ -1163,6 +1204,9 @@ async function main() {
1163
1204
  await runEditorCommand(positionals, options);
1164
1205
  break;
1165
1206
  }
1207
+ if (options.open) {
1208
+ process.env.AXHUB_GENIE_OPEN = 'true';
1209
+ }
1166
1210
  if (options.noOpen) {
1167
1211
  process.env.AXHUB_GENIE_NO_OPEN = 'true';
1168
1212
  }
@@ -1221,4 +1265,5 @@ export {
1221
1265
  normalizeApiBaseUrl,
1222
1266
  parseArgs,
1223
1267
  runEditorCommand,
1268
+ shouldAutoOpenHomepage,
1224
1269
  };
@@ -224,6 +224,26 @@ const userDb = {
224
224
  return toUserPublic(user);
225
225
  },
226
226
 
227
+ ensureDefaultUser: () => {
228
+ const existingUser = userDb.getFirstUser();
229
+ if (existingUser) {
230
+ return existingUser;
231
+ }
232
+
233
+ const preferredNames = ['genie', 'axhub-genie', 'local-user'];
234
+ for (const username of preferredNames) {
235
+ try {
236
+ return userDb.createUser(username, '');
237
+ } catch (error) {
238
+ if (error?.code !== 'USERNAME_EXISTS') {
239
+ throw error;
240
+ }
241
+ }
242
+ }
243
+
244
+ return userDb.createUser(`local-user-${Date.now()}`, '');
245
+ },
246
+
227
247
  };
228
248
 
229
249
  const apiKeysDb = {
@@ -62,15 +62,21 @@ async function ensureProviderInstalled(provider) {
62
62
  throw createRequestError(messageParts.join(' '), 400);
63
63
  }
64
64
 
65
- export function buildSessionNavigation(sessionId) {
65
+ export function buildSessionNavigation({
66
+ provider,
67
+ sessionId
68
+ } = {}) {
69
+ const normalizedProvider = typeof provider === 'string' && provider.trim() ? provider.trim().toLowerCase() : null;
66
70
  const normalizedSessionId = typeof sessionId === 'string' && sessionId.trim() ? sessionId.trim() : null;
67
- const sessionPath = normalizedSessionId ? `/session/${normalizedSessionId}` : null;
71
+ const sessionPath = normalizedProvider && normalizedSessionId
72
+ ? `/session/${normalizedProvider}/${encodeURIComponent(normalizedSessionId)}`
73
+ : null;
68
74
  const frontendPort = process.env.VITE_PORT || '5173';
69
75
  const configuredFrontendUrl = typeof process.env.FRONTEND_URL === 'string'
70
76
  ? process.env.FRONTEND_URL.trim().replace(/\/+$/, '')
71
77
  : '';
72
78
  const frontendBaseUrl = configuredFrontendUrl || `http://localhost:${frontendPort}`;
73
- const sessionUrl = normalizedSessionId ? `${frontendBaseUrl}${sessionPath}` : null;
79
+ const sessionUrl = sessionPath ? `${frontendBaseUrl}${sessionPath}` : null;
74
80
 
75
81
  return {
76
82
  sessionPath,
@@ -471,7 +477,11 @@ export async function runExternalAgentRequest({
471
477
  openOnly: true,
472
478
  runtime: 'acp',
473
479
  sessionId: normalized.normalizedSessionId,
474
- ...buildSessionNavigation(normalized.normalizedSessionId),
480
+ ...buildSessionNavigation({
481
+ provider: normalized.provider,
482
+ sessionId: normalized.normalizedSessionId,
483
+ projectPath: normalized.projectPath
484
+ }),
475
485
  isResumed: true,
476
486
  message: 'Session link generated. No model call triggered.'
477
487
  };
@@ -534,7 +544,11 @@ export async function runExternalAgentRequest({
534
544
  throw new AgentSessionAbortedError();
535
545
  }
536
546
 
537
- const navigation = buildSessionNavigation(callbackSessionId);
547
+ const navigation = buildSessionNavigation({
548
+ provider: normalized.provider,
549
+ sessionId: callbackSessionId,
550
+ projectPath: finalProjectPath
551
+ });
538
552
  const response = {
539
553
  success: true,
540
554
  sessionId: callbackSessionId,
@@ -580,7 +594,11 @@ export async function runExternalAgentRequest({
580
594
  } catch (error) {
581
595
  callbackSessionId = writer.getSessionId() || callbackCaptureWriter.getSessionId() || normalized.normalizedSessionId;
582
596
  callbackResult = {
583
- ...buildSessionNavigation(callbackSessionId),
597
+ ...buildSessionNavigation({
598
+ provider: normalized.provider,
599
+ sessionId: callbackSessionId,
600
+ projectPath: finalProjectPath
601
+ }),
584
602
  messages: callbackCaptureWriter.getAssistantMessages(),
585
603
  tokens: callbackCaptureWriter.getTotalTokens()
586
604
  };