@axhub/genie 0.1.3 → 0.1.5

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.
@@ -66,7 +66,6 @@ import sqlite3 from 'sqlite3';
66
66
  import { open } from 'sqlite';
67
67
  import os from 'os';
68
68
  import { parseCodexTokenCountInfo } from './utils/codexTokenUsage.js';
69
- import { listOpencodeSessions, getOpencodeSessionMessages, deleteOpencodeSession } from './opencode-manager.js';
70
69
 
71
70
  // Import TaskMaster detection functions
72
71
  async function detectTaskMasterFolder(projectPath) {
@@ -468,14 +467,6 @@ async function getProjects(progressCallback = null) {
468
467
  project.codexSessions = [];
469
468
  }
470
469
 
471
- // Also fetch OpenCode sessions for this project
472
- try {
473
- project.opencodeSessions = await getOpencodeSessions(actualProjectDir);
474
- } catch (e) {
475
- console.warn(`Could not load OpenCode sessions for project ${entry.name}:`, e.message);
476
- project.opencodeSessions = [];
477
- }
478
-
479
470
  // Add TaskMaster detection
480
471
  try {
481
472
  const taskMasterResult = await detectTaskMasterFolder(actualProjectDir);
@@ -544,8 +535,7 @@ async function getProjects(progressCallback = null) {
544
535
  isManuallyAdded: true,
545
536
  sessions: [],
546
537
  cursorSessions: [],
547
- codexSessions: [],
548
- opencodeSessions: []
538
+ codexSessions: []
549
539
  };
550
540
 
551
541
  // Try to fetch Cursor sessions for manual projects too
@@ -562,13 +552,6 @@ async function getProjects(progressCallback = null) {
562
552
  console.warn(`Could not load Codex sessions for manual project ${projectName}:`, e.message);
563
553
  }
564
554
 
565
- // Try to fetch OpenCode sessions for manual projects too
566
- try {
567
- project.opencodeSessions = await getOpencodeSessions(actualProjectDir);
568
- } catch (e) {
569
- console.warn(`Could not load OpenCode sessions for manual project ${projectName}:`, e.message);
570
- }
571
-
572
555
  // Add TaskMaster detection for manual projects
573
556
  try {
574
557
  const taskMasterResult = await detectTaskMasterFolder(actualProjectDir);
@@ -1080,20 +1063,6 @@ async function deleteProject(projectName, force = false) {
1080
1063
  console.warn('Failed to delete Codex sessions:', err.message);
1081
1064
  }
1082
1065
 
1083
- // Delete all OpenCode sessions associated with this project
1084
- try {
1085
- const opencodeSessions = await getOpencodeSessions(projectPath, { limit: 0 });
1086
- for (const session of opencodeSessions) {
1087
- try {
1088
- await deleteOpencodeSession(session.id, { directory: projectPath });
1089
- } catch (err) {
1090
- console.warn(`Failed to delete OpenCode session ${session.id}:`, err.message);
1091
- }
1092
- }
1093
- } catch (err) {
1094
- console.warn('Failed to delete OpenCode sessions:', err.message);
1095
- }
1096
-
1097
1066
  // Delete Cursor sessions directory if it exists
1098
1067
  try {
1099
1068
  const hash = crypto.createHash('md5').update(projectPath).digest('hex');
@@ -1160,9 +1129,7 @@ async function addProjectManually(projectPath, displayName = null) {
1160
1129
  displayName: displayName || await generateDisplayName(projectName, absolutePath),
1161
1130
  isManuallyAdded: true,
1162
1131
  sessions: [],
1163
- cursorSessions: [],
1164
- codexSessions: [],
1165
- opencodeSessions: []
1132
+ cursorSessions: []
1166
1133
  };
1167
1134
  }
1168
1135
 
@@ -1354,28 +1321,6 @@ async function getCodexSessions(projectPath, options = {}) {
1354
1321
  }
1355
1322
  }
1356
1323
 
1357
-
1358
-
1359
- let opencodeDiscoveryUnavailable = false;
1360
-
1361
- async function getOpencodeSessions(projectPath, options = {}) {
1362
- const { limit = 5 } = options;
1363
-
1364
- if (opencodeDiscoveryUnavailable) {
1365
- return [];
1366
- }
1367
-
1368
- try {
1369
- const sessions = await listOpencodeSessions(projectPath, { limit });
1370
- opencodeDiscoveryUnavailable = false;
1371
- return sessions;
1372
- } catch (error) {
1373
- opencodeDiscoveryUnavailable = true;
1374
- console.error('Error fetching OpenCode sessions:', error.message);
1375
- return [];
1376
- }
1377
- }
1378
-
1379
1324
  // Parse a Codex session JSONL file to extract metadata
1380
1325
  async function parseCodexSessionFile(filePath) {
1381
1326
  try {
@@ -1677,17 +1622,6 @@ async function getCodexSessionMessages(sessionId, limit = null, offset = 0) {
1677
1622
  }
1678
1623
  }
1679
1624
 
1680
-
1681
-
1682
- async function getOpencodeSessionMessagesFromManager(sessionId, options = {}) {
1683
- try {
1684
- return await getOpencodeSessionMessages(sessionId, options);
1685
- } catch (error) {
1686
- console.error(`Error reading OpenCode session messages for ${sessionId}:`, error);
1687
- return { messages: [], total: 0, hasMore: false };
1688
- }
1689
- }
1690
-
1691
1625
  async function deleteCodexSession(sessionId) {
1692
1626
  try {
1693
1627
  const codexSessionsDir = path.join(os.homedir(), '.codex', 'sessions');
@@ -1741,8 +1675,5 @@ export {
1741
1675
  clearProjectDirectoryCache,
1742
1676
  getCodexSessions,
1743
1677
  getCodexSessionMessages,
1744
- deleteCodexSession,
1745
- getOpencodeSessions,
1746
- getOpencodeSessionMessagesFromManager,
1747
- deleteOpencodeSession
1678
+ deleteCodexSession
1748
1679
  };
@@ -9,52 +9,17 @@ import { addProjectManually } from '../projects.js';
9
9
  import { queryClaudeSDK } from '../claude-sdk.js';
10
10
  import { spawnCursor } from '../cursor-cli.js';
11
11
  import { queryCodex } from '../openai-codex.js';
12
- import { queryOpencode } from '../opencode-sdk.js';
13
12
  import { Octokit } from '@octokit/rest';
14
- import { CLAUDE_MODELS, CURSOR_MODELS, CODEX_MODELS, OPENCODE_MODELS } from '../../shared/modelConstants.js';
13
+ import { CLAUDE_MODELS, CURSOR_MODELS, CODEX_MODELS } from '../../shared/modelConstants.js';
15
14
  import { IS_PLATFORM } from '../constants/config.js';
16
15
 
17
16
  const router = express.Router();
18
17
 
19
- function getForwardedHeaderValue(value) {
20
- if (Array.isArray(value)) {
21
- return value[0]?.split(',')[0]?.trim() || null;
22
- }
23
-
24
- if (typeof value === 'string') {
25
- return value.split(',')[0].trim() || null;
26
- }
27
-
28
- return null;
29
- }
30
-
31
- function getRequestOrigin(req) {
32
- if (!req) {
33
- return null;
34
- }
35
-
36
- const forwardedProto = getForwardedHeaderValue(req.headers['x-forwarded-proto']);
37
- const forwardedHost = getForwardedHeaderValue(req.headers['x-forwarded-host']);
38
- if (forwardedProto && forwardedHost) {
39
- return `${forwardedProto}://${forwardedHost}`;
40
- }
41
-
42
- const host = req.get('host');
43
- if (host) {
44
- return `${req.protocol || 'http'}://${host}`;
45
- }
46
-
47
- return null;
48
- }
49
-
50
- function buildSessionNavigation(sessionId, req) {
18
+ function buildSessionNavigation(sessionId) {
51
19
  const normalizedSessionId = typeof sessionId === 'string' && sessionId.trim() ? sessionId.trim() : null;
52
20
  const sessionPath = normalizedSessionId ? `/session/${normalizedSessionId}` : null;
53
- const configuredFrontendUrl = (process.env.FRONTEND_URL || '').trim().replace(/\/+$/, '');
54
- const requestOrigin = getRequestOrigin(req);
55
21
  const frontendPort = process.env.VITE_PORT || '5173';
56
- const frontendBaseUrl = configuredFrontendUrl || requestOrigin || `http://localhost:${frontendPort}`;
57
- const sessionUrl = normalizedSessionId ? `${frontendBaseUrl}${sessionPath}` : null;
22
+ const sessionUrl = normalizedSessionId ? `http://localhost:${frontendPort}${sessionPath}` : null;
58
23
 
59
24
  return {
60
25
  sessionPath,
@@ -696,7 +661,7 @@ class ResponseCollector {
696
661
  * @param {string} sessionId - (Optional) Existing session ID to resume.
697
662
  * If provided, the request continues that session instead of creating a new one.
698
663
  *
699
- * @param {string} provider - (Optional) AI provider to use. Options: 'claude' | 'cursor' | 'codex' | 'opencode'
664
+ * @param {string} provider - (Optional) AI provider to use. Options: 'claude' | 'cursor'
700
665
  * Default: 'claude'
701
666
  *
702
667
  * @param {boolean} stream - (Optional) Enable Server-Sent Events (SSE) streaming for real-time updates.
@@ -814,7 +779,7 @@ class ResponseCollector {
814
779
  * Input Validations (400 Bad Request):
815
780
  * - Either githubUrl OR projectPath must be provided (not neither)
816
781
  * - message must be non-empty string
817
- * - provider must be 'claude', 'cursor', 'codex', or 'opencode'
782
+ * - provider must be 'claude' or 'cursor'
818
783
  * - createBranch/createPR requires githubUrl OR projectPath (not neither)
819
784
  * - branchName must pass Git naming rules (if provided)
820
785
  *
@@ -918,8 +883,8 @@ router.post('/', validateExternalApiKey, async (req, res) => {
918
883
  const isOpenOnly = requestedOpenOnly || (!normalizedMessage && !!normalizedSessionId);
919
884
 
920
885
  // Validate inputs
921
- if (!['claude', 'cursor', 'codex', 'opencode'].includes(provider)) {
922
- return res.status(400).json({ error: 'provider must be "claude", "cursor", "codex", or "opencode"' });
886
+ if (!['claude', 'cursor', 'codex'].includes(provider)) {
887
+ return res.status(400).json({ error: 'provider must be "claude", "cursor", or "codex"' });
923
888
  }
924
889
 
925
890
  if (sessionId !== undefined && (typeof sessionId !== 'string' || !sessionId.trim())) {
@@ -957,7 +922,7 @@ router.post('/', validateExternalApiKey, async (req, res) => {
957
922
  }
958
923
 
959
924
  if (isOpenOnly) {
960
- const { sessionPath, sessionUrl } = buildSessionNavigation(normalizedSessionId, req);
925
+ const { sessionPath, sessionUrl } = buildSessionNavigation(normalizedSessionId);
961
926
  const response = {
962
927
  success: true,
963
928
  openOnly: true,
@@ -1097,16 +1062,6 @@ router.post('/', validateExternalApiKey, async (req, res) => {
1097
1062
  model: model || CODEX_MODELS.DEFAULT,
1098
1063
  permissionMode: 'bypassPermissions'
1099
1064
  }, writer);
1100
- } else if (provider === 'opencode') {
1101
- console.log('🧠 Starting OpenCode session');
1102
-
1103
- await queryOpencode(normalizedMessage, {
1104
- projectPath: finalProjectPath,
1105
- cwd: finalProjectPath,
1106
- sessionId: normalizedSessionId,
1107
- model: model || OPENCODE_MODELS.DEFAULT,
1108
- permissionMode: 'bypassPermissions'
1109
- }, writer);
1110
1065
  }
1111
1066
 
1112
1067
  // Handle GitHub branch and PR creation after successful agent completion
@@ -1299,7 +1254,7 @@ router.post('/', validateExternalApiKey, async (req, res) => {
1299
1254
  const assistantMessages = writer.getAssistantMessages();
1300
1255
  const tokenSummary = writer.getTotalTokens();
1301
1256
  const resolvedSessionId = writer.getSessionId() || normalizedSessionId;
1302
- const { sessionPath, sessionUrl } = buildSessionNavigation(resolvedSessionId, req);
1257
+ const { sessionPath, sessionUrl } = buildSessionNavigation(resolvedSessionId);
1303
1258
 
1304
1259
  const response = {
1305
1260
  success: true,
@@ -213,7 +213,7 @@ Custom commands can be created in:
213
213
  // Read version from package.json
214
214
  const packageJsonPath = path.join(path.dirname(__dirname), '..', 'package.json');
215
215
  let version = 'unknown';
216
- let packageName = 'claude-code-ui';
216
+ let packageName = '@axhub/genie';
217
217
 
218
218
  try {
219
219
  const packageJson = JSON.parse(await fs.readFile(packageJsonPath, 'utf8'));
@@ -63,17 +63,3 @@ export const CODEX_MODELS = {
63
63
 
64
64
  DEFAULT: 'gpt-5.2-codex'
65
65
  };
66
-
67
-
68
- /**
69
- * OpenCode Models
70
- */
71
- export const OPENCODE_MODELS = {
72
- OPTIONS: [
73
- { value: 'opencode/gpt-5-nano', label: 'GPT-5 Nano (OpenCode)' },
74
- { value: 'openai/gpt-5.2', label: 'GPT-5.2 (OpenAI)' },
75
- { value: 'anthropic/claude-sonnet-4.5', label: 'Claude Sonnet 4.5 (Anthropic)' }
76
- ],
77
-
78
- DEFAULT: 'opencode/gpt-5-nano'
79
- };