@axhub/genie 0.1.6 → 0.1.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 (37) hide show
  1. package/dist/api-docs.html +351 -909
  2. package/dist/assets/index-CVjMty4a.js +902 -0
  3. package/dist/assets/index-eo5scY_Z.css +32 -0
  4. package/dist/index.html +5 -5
  5. package/dist/manifest.json +2 -2
  6. package/package.json +8 -2
  7. package/server/channels/core/ChannelManager.js +399 -0
  8. package/server/channels/core/PluginManager.js +59 -0
  9. package/server/channels/index.js +3 -0
  10. package/server/channels/plugins/BasePlugin.js +46 -0
  11. package/server/channels/plugins/dingtalk/DingTalkAdapter.js +156 -0
  12. package/server/channels/plugins/dingtalk/DingTalkPlugin.js +592 -0
  13. package/server/channels/plugins/dingtalk/index.js +2 -0
  14. package/server/channels/plugins/lark/LarkAdapter.js +100 -0
  15. package/server/channels/plugins/lark/LarkCards.js +43 -0
  16. package/server/channels/plugins/lark/LarkPlugin.js +260 -0
  17. package/server/channels/runtime/AgentRuntimeAdapter.js +179 -0
  18. package/server/channels/runtime/DingTalkStreamWriter.js +105 -0
  19. package/server/channels/runtime/LarkStreamWriter.js +99 -0
  20. package/server/channels/store/ChannelStore.js +236 -0
  21. package/server/database/db.js +109 -1
  22. package/server/database/init.sql +47 -1
  23. package/server/gemini-cli.js +280 -0
  24. package/server/index.js +230 -11
  25. package/server/openai-codex.js +104 -8
  26. package/server/opencode-cli.js +673 -0
  27. package/server/projects.js +645 -5
  28. package/server/routes/agent.js +40 -12
  29. package/server/routes/channels.js +221 -0
  30. package/server/routes/cli-auth.js +317 -0
  31. package/server/routes/commands.js +29 -3
  32. package/server/routes/git.js +15 -5
  33. package/server/routes/opencode.js +72 -0
  34. package/shared/modelConstants.js +62 -17
  35. package/dist/assets/index-CtRxrKDm.css +0 -32
  36. package/dist/assets/index-OENtErNy.js +0 -1249
  37. package/server/database/auth.db +0 -0
@@ -4,7 +4,8 @@ import path from 'path';
4
4
  import { fileURLToPath } from 'url';
5
5
  import os from 'os';
6
6
  import matter from 'gray-matter';
7
- import { CLAUDE_MODELS, CURSOR_MODELS, CODEX_MODELS } from '../../shared/modelConstants.js';
7
+ import { CLAUDE_MODELS, CURSOR_MODELS, CODEX_MODELS, GEMINI_MODELS, OPENCODE_MODELS } from '../../shared/modelConstants.js';
8
+ import { listOpencodeModels } from '../opencode-cli.js';
8
9
 
9
10
  const __filename = fileURLToPath(import.meta.url);
10
11
  const __dirname = path.dirname(__filename);
@@ -187,11 +188,35 @@ Custom commands can be created in:
187
188
  const availableModels = {
188
189
  claude: CLAUDE_MODELS.OPTIONS.map(o => o.value),
189
190
  cursor: CURSOR_MODELS.OPTIONS.map(o => o.value),
190
- codex: CODEX_MODELS.OPTIONS.map(o => o.value)
191
+ codex: CODEX_MODELS.OPTIONS.map(o => o.value),
192
+ gemini: GEMINI_MODELS.OPTIONS.map(o => o.value),
193
+ opencode: OPENCODE_MODELS.OPTIONS.map(o => o.value)
191
194
  };
192
195
 
193
196
  const currentProvider = context?.provider || 'claude';
194
- const currentModel = context?.model || CLAUDE_MODELS.DEFAULT;
197
+ const providerDefaults = {
198
+ claude: CLAUDE_MODELS.DEFAULT,
199
+ cursor: CURSOR_MODELS.DEFAULT,
200
+ codex: CODEX_MODELS.DEFAULT,
201
+ gemini: GEMINI_MODELS.DEFAULT,
202
+ opencode: OPENCODE_MODELS.DEFAULT
203
+ };
204
+ const currentModel = context?.model || providerDefaults[currentProvider] || CLAUDE_MODELS.DEFAULT;
205
+ let opencodeDiscovery = null;
206
+
207
+ if (context?.projectPath) {
208
+ try {
209
+ opencodeDiscovery = await listOpencodeModels({
210
+ projectPath: context?.projectPath,
211
+ cwd: context?.projectPath
212
+ });
213
+ if (opencodeDiscovery.models.length > 0) {
214
+ availableModels.opencode = opencodeDiscovery.models;
215
+ }
216
+ } catch (error) {
217
+ console.warn('Failed to query OpenCode runtime models:', error.message);
218
+ }
219
+ }
195
220
 
196
221
  return {
197
222
  type: 'builtin',
@@ -202,6 +227,7 @@ Custom commands can be created in:
202
227
  model: currentModel
203
228
  },
204
229
  available: availableModels,
230
+ opencodeDiscovery,
205
231
  message: args.length > 0
206
232
  ? `Switching to model: ${args[0]}`
207
233
  : `Current model: ${currentModel}`
@@ -6,6 +6,7 @@ import { promises as fs } from 'fs';
6
6
  import { extractProjectDirectory } from '../projects.js';
7
7
  import { queryClaudeSDK } from '../claude-sdk.js';
8
8
  import { spawnCursor } from '../cursor-cli.js';
9
+ import { queryGemini } from '../gemini-cli.js';
9
10
 
10
11
  const router = express.Router();
11
12
  const execAsync = promisify(exec);
@@ -519,8 +520,8 @@ router.post('/generate-commit-message', async (req, res) => {
519
520
  }
520
521
 
521
522
  // Validate provider
522
- if (!['claude', 'cursor'].includes(provider)) {
523
- return res.status(400).json({ error: 'provider must be "claude" or "cursor"' });
523
+ if (!['claude', 'cursor', 'gemini'].includes(provider)) {
524
+ return res.status(400).json({ error: 'provider must be "claude", "cursor", or "gemini"' });
524
525
  }
525
526
 
526
527
  try {
@@ -573,10 +574,10 @@ router.post('/generate-commit-message', async (req, res) => {
573
574
  });
574
575
 
575
576
  /**
576
- * Generates a commit message using AI (Claude SDK or Cursor CLI)
577
+ * Generates a commit message using AI (Claude SDK, Cursor CLI, or Gemini CLI)
577
578
  * @param {Array<string>} files - List of changed files
578
579
  * @param {string} diffContext - Git diff content
579
- * @param {string} provider - 'claude' or 'cursor'
580
+ * @param {string} provider - 'claude', 'cursor', or 'gemini'
580
581
  * @param {string} projectPath - Project directory path
581
582
  * @returns {Promise<string>} Generated commit message
582
583
  */
@@ -630,6 +631,9 @@ Generate the commit message:`;
630
631
  console.log('✅ Cursor output:', parsed.output.substring(0, 100));
631
632
  responseText += parsed.output;
632
633
  }
634
+ else if (parsed.type === 'claude-response' && parsed.data?.type === 'content_block_delta' && parsed.data?.delta?.text) {
635
+ responseText += parsed.data.delta.text;
636
+ }
633
637
  // Also handle direct text messages
634
638
  else if (parsed.type === 'text' && parsed.text) {
635
639
  console.log('✅ Direct text:', parsed.text.substring(0, 100));
@@ -658,6 +662,12 @@ Generate the commit message:`;
658
662
  cwd: projectPath,
659
663
  skipPermissions: true
660
664
  }, writer);
665
+ } else if (provider === 'gemini') {
666
+ await queryGemini(prompt, {
667
+ cwd: projectPath,
668
+ projectPath,
669
+ permissionMode: 'bypassPermissions'
670
+ }, writer);
661
671
  }
662
672
 
663
673
  console.log('📊 Total response text collected:', responseText.length, 'characters');
@@ -1125,4 +1135,4 @@ router.post('/delete-untracked', async (req, res) => {
1125
1135
  }
1126
1136
  });
1127
1137
 
1128
- export default router;
1138
+ export default router;
@@ -0,0 +1,72 @@
1
+ import express from 'express';
2
+ import {
3
+ getOpencodeSessions,
4
+ getOpencodeSessionMessages,
5
+ deleteOpencodeSession
6
+ } from '../projects.js';
7
+ import { listOpencodeModels } from '../opencode-cli.js';
8
+
9
+ const router = express.Router();
10
+
11
+ router.get('/models', async (req, res) => {
12
+ try {
13
+ const { projectPath } = req.query;
14
+
15
+ if (!projectPath) {
16
+ return res.status(400).json({ success: false, error: 'projectPath query parameter required' });
17
+ }
18
+
19
+ const discovery = await listOpencodeModels({ projectPath, cwd: projectPath });
20
+ res.json({ success: true, ...discovery });
21
+ } catch (error) {
22
+ console.error('Error fetching OpenCode models:', error);
23
+ res.status(500).json({ success: false, error: error.message });
24
+ }
25
+ });
26
+
27
+ router.get('/sessions', async (req, res) => {
28
+ try {
29
+ const { projectPath } = req.query;
30
+
31
+ if (!projectPath) {
32
+ return res.status(400).json({ success: false, error: 'projectPath query parameter required' });
33
+ }
34
+
35
+ const sessions = await getOpencodeSessions(projectPath);
36
+ res.json({ success: true, sessions });
37
+ } catch (error) {
38
+ console.error('Error fetching OpenCode sessions:', error);
39
+ res.status(500).json({ success: false, error: error.message });
40
+ }
41
+ });
42
+
43
+ router.get('/sessions/:sessionId/messages', async (req, res) => {
44
+ try {
45
+ const { sessionId } = req.params;
46
+ const { limit, offset } = req.query;
47
+
48
+ const result = await getOpencodeSessionMessages(
49
+ sessionId,
50
+ limit ? parseInt(limit, 10) : null,
51
+ offset ? parseInt(offset, 10) : 0
52
+ );
53
+
54
+ res.json({ success: true, ...result });
55
+ } catch (error) {
56
+ console.error('Error fetching OpenCode session messages:', error);
57
+ res.status(500).json({ success: false, error: error.message });
58
+ }
59
+ });
60
+
61
+ router.delete('/sessions/:sessionId', async (req, res) => {
62
+ try {
63
+ const { sessionId } = req.params;
64
+ await deleteOpencodeSession(sessionId);
65
+ res.json({ success: true });
66
+ } catch (error) {
67
+ console.error(`Error deleting OpenCode session ${req.params.sessionId}:`, error);
68
+ res.status(500).json({ success: false, error: error.message });
69
+ }
70
+ });
71
+
72
+ export default router;
@@ -28,26 +28,35 @@ export const CLAUDE_MODELS = {
28
28
  */
29
29
  export const CURSOR_MODELS = {
30
30
  OPTIONS: [
31
- { value: 'gpt-5.2-high', label: 'GPT-5.2 High' },
32
- { value: 'gemini-3-pro', label: 'Gemini 3 Pro' },
33
- { value: 'opus-4.5-thinking', label: 'Claude 4.5 Opus (Thinking)' },
34
- { value: 'gpt-5.2', label: 'GPT-5.2' },
35
- { value: 'gpt-5.1', label: 'GPT-5.1' },
36
- { value: 'gpt-5.1-high', label: 'GPT-5.1 High' },
37
- { value: 'composer-1', label: 'Composer 1' },
38
31
  { value: 'auto', label: 'Auto' },
39
- { value: 'sonnet-4.5', label: 'Claude 4.5 Sonnet' },
40
- { value: 'sonnet-4.5-thinking', label: 'Claude 4.5 Sonnet (Thinking)' },
32
+ { value: 'sonnet-4', label: 'Claude 4 Sonnet' },
33
+ { value: 'sonnet-4-1m', label: 'Claude 4 Sonnet 1M' },
34
+ { value: 'haiku-4.5', label: 'Claude 4.5 Haiku' },
41
35
  { value: 'opus-4.5', label: 'Claude 4.5 Opus' },
36
+ { value: 'sonnet-4.5', label: 'Claude 4.5 Sonnet' },
37
+ { value: 'opus-4.6', label: 'Claude 4.6 Opus' },
38
+ { value: 'opus-4.6-fast', label: 'Claude 4.6 Opus (Fast mode)' },
39
+ { value: 'composer-1', label: 'Composer 1' },
40
+ { value: 'composer-1.5', label: 'Composer 1.5' },
41
+ { value: 'gemini-2.5-flash', label: 'Gemini 2.5 Flash' },
42
+ { value: 'gemini-3-flash', label: 'Gemini 3 Flash' },
43
+ { value: 'gemini-3-pro-preview', label: 'Gemini 3 Pro Preview' },
44
+ { value: 'gemini-3-pro', label: 'Gemini 3 Pro' },
45
+ { value: 'gemini-3-pro-image-preview', label: 'Gemini 3 Pro Image Preview' },
46
+ { value: 'gpt-5', label: 'GPT-5' },
47
+ { value: 'gpt-5-fast', label: 'GPT-5 Fast' },
48
+ { value: 'gpt-5-mini', label: 'GPT-5 Mini' },
49
+ { value: 'gpt-5-codex', label: 'GPT-5-Codex' },
42
50
  { value: 'gpt-5.1-codex', label: 'GPT-5.1 Codex' },
43
- { value: 'gpt-5.1-codex-high', label: 'GPT-5.1 Codex High' },
44
51
  { value: 'gpt-5.1-codex-max', label: 'GPT-5.1 Codex Max' },
45
- { value: 'gpt-5.1-codex-max-high', label: 'GPT-5.1 Codex Max High' },
46
- { value: 'opus-4.1', label: 'Claude 4.1 Opus' },
47
- { value: 'grok', label: 'Grok' }
52
+ { value: 'gpt-5.1-codex-mini', label: 'GPT-5.1 Codex Mini' },
53
+ { value: 'gpt-5.2', label: 'GPT-5.2' },
54
+ { value: 'gpt-5.2-codex', label: 'GPT-5.2 Codex' },
55
+ { value: 'gpt-5.3-codex', label: 'GPT-5.3 Codex' },
56
+ { value: 'grok-code', label: 'Grok Code' }
48
57
  ],
49
58
 
50
- DEFAULT: 'gpt-5'
59
+ DEFAULT: 'auto'
51
60
  };
52
61
 
53
62
  /**
@@ -55,11 +64,47 @@ export const CURSOR_MODELS = {
55
64
  */
56
65
  export const CODEX_MODELS = {
57
66
  OPTIONS: [
58
- { value: 'gpt-5.2-codex', label: 'GPT-5.2 Codex' },
59
- { value: 'gpt-5.2', label: 'GPT-5.2' },
67
+ { value: 'gpt-5', label: 'GPT-5' },
68
+ { value: 'gpt-5-codex', label: 'GPT-5 Codex' },
69
+ { value: 'gpt-5-codex-mini', label: 'GPT-5 Codex Mini' },
70
+ { value: 'gpt-5.1', label: 'GPT-5.1' },
71
+ { value: 'gpt-5.1-codex', label: 'GPT-5.1 Codex' },
60
72
  { value: 'gpt-5.1-codex-max', label: 'GPT-5.1 Codex Max' },
61
- { value: 'gpt-5.1-codex-mini', label: 'GPT-5.1 Codex Mini' }
73
+ { value: 'gpt-5.1-codex-mini', label: 'GPT-5.1 Codex Mini' },
74
+ { value: 'gpt-5.2', label: 'GPT-5.2' },
75
+ { value: 'gpt-5.2-codex', label: 'GPT-5.2 Codex' },
76
+ { value: 'gpt-5.2-high', label: 'GPT-5.2 High' },
77
+ { value: 'gpt-5.2-low', label: 'GPT-5.2 Low' },
78
+ { value: 'gpt-5.2-medium', label: 'GPT-5.2 Medium' },
79
+ { value: 'gpt-5.2-xhigh', label: 'GPT-5.2 XHigh' },
80
+ { value: 'gpt-5.3-codex', label: 'GPT-5.3 Codex' },
81
+ { value: 'gpt-5.3-codex-high', label: 'GPT-5.3 Codex High' },
82
+ { value: 'gpt-5.3-codex-low', label: 'GPT-5.3 Codex Low' },
83
+ { value: 'gpt-5.3-codex-medium', label: 'GPT-5.3 Codex Medium' },
84
+ { value: 'gpt-5.3-codex-xhigh', label: 'GPT-5.3 Codex XHigh' }
62
85
  ],
63
86
 
64
87
  DEFAULT: 'gpt-5.2-codex'
65
88
  };
89
+
90
+ export const GEMINI_MODELS = {
91
+ OPTIONS: [
92
+ { value: 'gemini-2.5-pro', label: 'Gemini 2.5 Pro' },
93
+ { value: 'gemini-2.5-flash', label: 'Gemini 2.5 Flash' },
94
+ { value: 'gemini-3-pro-preview', label: 'Gemini 3 Pro Preview' },
95
+ { value: 'gemini-3-flash-preview', label: 'Gemini 3 Flash Preview' }
96
+ ],
97
+
98
+ DEFAULT: 'gemini-3-pro-preview'
99
+ };
100
+
101
+ /**
102
+ * OpenCode (OPENCODE) Models
103
+ */
104
+ export const OPENCODE_MODELS = {
105
+ OPTIONS: [
106
+ { value: 'kimi-k2.5', label: 'Kimi K2.5' }
107
+ ],
108
+
109
+ DEFAULT: 'kimi-k2.5'
110
+ };