@cloudcli-ai/cloudcli 1.31.5 → 1.33.0
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.
- package/README.de.md +1 -1
- package/README.ko.md +1 -1
- package/README.md +1 -1
- package/README.ru.md +1 -1
- package/README.tr.md +1 -1
- package/README.zh-CN.md +1 -1
- package/dist/api-docs.html +6 -7
- package/dist/assets/index-MOIvpy53.css +32 -0
- package/dist/assets/{index-DqMVUeZS.js → index-skXSjBje.js} +290 -270
- package/dist/index.html +2 -2
- package/dist/modelConstants.js +841 -0
- package/dist-server/server/claude-sdk.js +67 -39
- package/dist-server/server/claude-sdk.js.map +1 -1
- package/dist-server/server/cursor-cli.js +6 -9
- package/dist-server/server/cursor-cli.js.map +1 -1
- package/dist-server/server/gemini-cli.js +163 -35
- package/dist-server/server/gemini-cli.js.map +1 -1
- package/dist-server/server/gemini-response-handler.js +34 -0
- package/dist-server/server/gemini-response-handler.js.map +1 -1
- package/dist-server/server/index.js +131 -19
- package/dist-server/server/index.js.map +1 -1
- package/dist-server/server/modules/database/index.js +1 -0
- package/dist-server/server/modules/database/index.js.map +1 -1
- package/dist-server/server/modules/database/migrations.js +11 -0
- package/dist-server/server/modules/database/migrations.js.map +1 -1
- package/dist-server/server/modules/database/repositories/projects.db.js +12 -0
- package/dist-server/server/modules/database/repositories/projects.db.js.map +1 -1
- package/dist-server/server/modules/database/repositories/sessions.db.integration.test.js +61 -0
- package/dist-server/server/modules/database/repositories/sessions.db.integration.test.js.map +1 -0
- package/dist-server/server/modules/database/repositories/sessions.db.js +49 -8
- package/dist-server/server/modules/database/repositories/sessions.db.js.map +1 -1
- package/dist-server/server/modules/database/schema.js +1 -0
- package/dist-server/server/modules/database/schema.js.map +1 -1
- package/dist-server/server/modules/projects/projects.routes.js +12 -3
- package/dist-server/server/modules/projects/projects.routes.js.map +1 -1
- package/dist-server/server/modules/projects/services/project-delete.service.js +14 -1
- package/dist-server/server/modules/projects/services/project-delete.service.js.map +1 -1
- package/dist-server/server/modules/projects/services/project-management.service.js +1 -0
- package/dist-server/server/modules/projects/services/project-management.service.js.map +1 -1
- package/dist-server/server/modules/projects/services/projects-with-sessions-fetch.service.js +47 -0
- package/dist-server/server/modules/projects/services/projects-with-sessions-fetch.service.js.map +1 -1
- package/dist-server/server/modules/providers/index.js +1 -0
- package/dist-server/server/modules/providers/index.js.map +1 -1
- package/dist-server/server/modules/providers/list/claude/claude-auth.provider.js +27 -7
- package/dist-server/server/modules/providers/list/claude/claude-auth.provider.js.map +1 -1
- package/dist-server/server/modules/providers/list/claude/claude-models.provider.js +141 -0
- package/dist-server/server/modules/providers/list/claude/claude-models.provider.js.map +1 -0
- package/dist-server/server/modules/providers/list/claude/claude-session-synchronizer.provider.js +55 -2
- package/dist-server/server/modules/providers/list/claude/claude-session-synchronizer.provider.js.map +1 -1
- package/dist-server/server/modules/providers/list/claude/claude-sessions.provider.js +153 -14
- package/dist-server/server/modules/providers/list/claude/claude-sessions.provider.js.map +1 -1
- package/dist-server/server/modules/providers/list/claude/claude-skills.provider.js +198 -0
- package/dist-server/server/modules/providers/list/claude/claude-skills.provider.js.map +1 -0
- package/dist-server/server/modules/providers/list/claude/claude.provider.js +4 -0
- package/dist-server/server/modules/providers/list/claude/claude.provider.js.map +1 -1
- package/dist-server/server/modules/providers/list/codex/codex-models.provider.js +84 -0
- package/dist-server/server/modules/providers/list/codex/codex-models.provider.js.map +1 -0
- package/dist-server/server/modules/providers/list/codex/codex-session-synchronizer.provider.js +54 -2
- package/dist-server/server/modules/providers/list/codex/codex-session-synchronizer.provider.js.map +1 -1
- package/dist-server/server/modules/providers/list/codex/codex-sessions.provider.js +21 -6
- package/dist-server/server/modules/providers/list/codex/codex-sessions.provider.js.map +1 -1
- package/dist-server/server/modules/providers/list/codex/codex-skills.provider.js +50 -0
- package/dist-server/server/modules/providers/list/codex/codex-skills.provider.js.map +1 -0
- package/dist-server/server/modules/providers/list/codex/codex.provider.js +4 -0
- package/dist-server/server/modules/providers/list/codex/codex.provider.js.map +1 -1
- package/dist-server/server/modules/providers/list/cursor/cursor-models.provider.js +754 -0
- package/dist-server/server/modules/providers/list/cursor/cursor-models.provider.js.map +1 -0
- package/dist-server/server/modules/providers/list/cursor/cursor-session-synchronizer.provider.js +8 -30
- package/dist-server/server/modules/providers/list/cursor/cursor-session-synchronizer.provider.js.map +1 -1
- package/dist-server/server/modules/providers/list/cursor/cursor-sessions.provider.js +187 -24
- package/dist-server/server/modules/providers/list/cursor/cursor-sessions.provider.js.map +1 -1
- package/dist-server/server/modules/providers/list/cursor/cursor-skills.provider.js +28 -0
- package/dist-server/server/modules/providers/list/cursor/cursor-skills.provider.js.map +1 -0
- package/dist-server/server/modules/providers/list/cursor/cursor.provider.js +4 -0
- package/dist-server/server/modules/providers/list/cursor/cursor.provider.js.map +1 -1
- package/dist-server/server/modules/providers/list/gemini/gemini-auth.provider.js +125 -2
- package/dist-server/server/modules/providers/list/gemini/gemini-auth.provider.js.map +1 -1
- package/dist-server/server/modules/providers/list/gemini/gemini-models.provider.js +27 -0
- package/dist-server/server/modules/providers/list/gemini/gemini-models.provider.js.map +1 -0
- package/dist-server/server/modules/providers/list/gemini/gemini-session-synchronizer.provider.js +24 -8
- package/dist-server/server/modules/providers/list/gemini/gemini-session-synchronizer.provider.js.map +1 -1
- package/dist-server/server/modules/providers/list/gemini/gemini-sessions.provider.js +10 -10
- package/dist-server/server/modules/providers/list/gemini/gemini-sessions.provider.js.map +1 -1
- package/dist-server/server/modules/providers/list/gemini/gemini-skills.provider.js +33 -0
- package/dist-server/server/modules/providers/list/gemini/gemini-skills.provider.js.map +1 -0
- package/dist-server/server/modules/providers/list/gemini/gemini.provider.js +4 -0
- package/dist-server/server/modules/providers/list/gemini/gemini.provider.js.map +1 -1
- package/dist-server/server/modules/providers/list/opencode/opencode-auth.provider.js +92 -0
- package/dist-server/server/modules/providers/list/opencode/opencode-auth.provider.js.map +1 -0
- package/dist-server/server/modules/providers/list/opencode/opencode-mcp.provider.js +181 -0
- package/dist-server/server/modules/providers/list/opencode/opencode-mcp.provider.js.map +1 -0
- package/dist-server/server/modules/providers/list/opencode/opencode-models.provider.js +267 -0
- package/dist-server/server/modules/providers/list/opencode/opencode-models.provider.js.map +1 -0
- package/dist-server/server/modules/providers/list/opencode/opencode-session-synchronizer.provider.js +115 -0
- package/dist-server/server/modules/providers/list/opencode/opencode-session-synchronizer.provider.js.map +1 -0
- package/dist-server/server/modules/providers/list/opencode/opencode-sessions.provider.js +410 -0
- package/dist-server/server/modules/providers/list/opencode/opencode-sessions.provider.js.map +1 -0
- package/dist-server/server/modules/providers/list/opencode/opencode-skills.provider.js +62 -0
- package/dist-server/server/modules/providers/list/opencode/opencode-skills.provider.js.map +1 -0
- package/dist-server/server/modules/providers/list/opencode/opencode.provider.js +19 -0
- package/dist-server/server/modules/providers/list/opencode/opencode.provider.js.map +1 -0
- package/dist-server/server/modules/providers/provider.registry.js +2 -0
- package/dist-server/server/modules/providers/provider.registry.js.map +1 -1
- package/dist-server/server/modules/providers/provider.routes.js +65 -3
- package/dist-server/server/modules/providers/provider.routes.js.map +1 -1
- package/dist-server/server/modules/providers/services/mcp.service.js +1 -9
- package/dist-server/server/modules/providers/services/mcp.service.js.map +1 -1
- package/dist-server/server/modules/providers/services/provider-models.service.js +199 -0
- package/dist-server/server/modules/providers/services/provider-models.service.js.map +1 -0
- package/dist-server/server/modules/providers/services/session-conversations-search.service.js +129 -13
- package/dist-server/server/modules/providers/services/session-conversations-search.service.js.map +1 -1
- package/dist-server/server/modules/providers/services/session-synchronizer.service.js +1 -0
- package/dist-server/server/modules/providers/services/session-synchronizer.service.js.map +1 -1
- package/dist-server/server/modules/providers/services/sessions-watcher.service.js +13 -4
- package/dist-server/server/modules/providers/services/sessions-watcher.service.js.map +1 -1
- package/dist-server/server/modules/providers/services/sessions.service.js +81 -7
- package/dist-server/server/modules/providers/services/sessions.service.js.map +1 -1
- package/dist-server/server/modules/providers/services/skills.service.js +11 -0
- package/dist-server/server/modules/providers/services/skills.service.js.map +1 -0
- package/dist-server/server/modules/providers/shared/base/abstract.provider.js.map +1 -1
- package/dist-server/server/modules/providers/shared/skills/skills.provider.js +45 -0
- package/dist-server/server/modules/providers/shared/skills/skills.provider.js.map +1 -0
- package/dist-server/server/modules/providers/tests/mcp.test.js +73 -6
- package/dist-server/server/modules/providers/tests/mcp.test.js.map +1 -1
- package/dist-server/server/modules/providers/tests/opencode-models.test.js +66 -0
- package/dist-server/server/modules/providers/tests/opencode-models.test.js.map +1 -0
- package/dist-server/server/modules/providers/tests/opencode-sessions.test.js +262 -0
- package/dist-server/server/modules/providers/tests/opencode-sessions.test.js.map +1 -0
- package/dist-server/server/modules/providers/tests/provider-models.service.test.js +270 -0
- package/dist-server/server/modules/providers/tests/provider-models.service.test.js.map +1 -0
- package/dist-server/server/modules/providers/tests/skills.test.js +259 -0
- package/dist-server/server/modules/providers/tests/skills.test.js.map +1 -0
- package/dist-server/server/modules/websocket/services/chat-websocket.service.js +12 -1
- package/dist-server/server/modules/websocket/services/chat-websocket.service.js.map +1 -1
- package/dist-server/server/modules/websocket/services/plugin-websocket-proxy.service.js +4 -4
- package/dist-server/server/modules/websocket/services/plugin-websocket-proxy.service.js.map +1 -1
- package/dist-server/server/modules/websocket/services/shell-websocket.service.js +9 -1
- package/dist-server/server/modules/websocket/services/shell-websocket.service.js.map +1 -1
- package/dist-server/server/openai-codex.js +87 -29
- package/dist-server/server/openai-codex.js.map +1 -1
- package/dist-server/server/opencode-cli.js +287 -0
- package/dist-server/server/opencode-cli.js.map +1 -0
- package/dist-server/server/opencode-cli.test.js +84 -0
- package/dist-server/server/opencode-cli.test.js.map +1 -0
- package/dist-server/server/routes/agent.js +21 -8
- package/dist-server/server/routes/agent.js.map +1 -1
- package/dist-server/server/routes/commands.js +204 -211
- package/dist-server/server/routes/commands.js.map +1 -1
- package/dist-server/server/routes/cursor.js +2 -2
- package/dist-server/server/routes/cursor.js.map +1 -1
- package/dist-server/server/routes/settings.js +0 -10
- package/dist-server/server/routes/settings.js.map +1 -1
- package/dist-server/server/routes/tests/commands.test.js +76 -0
- package/dist-server/server/routes/tests/commands.test.js.map +1 -0
- package/dist-server/server/shared/claude-cli-path.js +103 -0
- package/dist-server/server/shared/claude-cli-path.js.map +1 -0
- package/dist-server/server/shared/claude-cli-path.test.js +45 -0
- package/dist-server/server/shared/claude-cli-path.test.js.map +1 -0
- package/dist-server/server/{utils → shared}/frontmatter.js +3 -3
- package/dist-server/server/shared/frontmatter.js.map +1 -0
- package/dist-server/server/shared/utils.js +368 -0
- package/dist-server/server/shared/utils.js.map +1 -1
- package/dist-server/server/utils/commandParser.js +3 -3
- package/dist-server/server/utils/commandParser.js.map +1 -1
- package/package.json +3 -1
- package/public/api-docs.html +878 -0
- package/public/modelConstants.js +841 -0
- package/server/claude-sdk.js +74 -40
- package/server/cursor-cli.js +6 -11
- package/server/gemini-cli.js +197 -43
- package/server/gemini-response-handler.js +38 -0
- package/server/index.js +144 -19
- package/server/modules/database/index.ts +1 -0
- package/server/modules/database/migrations.ts +12 -0
- package/server/modules/database/repositories/projects.db.ts +13 -0
- package/server/modules/database/repositories/sessions.db.integration.test.ts +72 -0
- package/server/modules/database/repositories/sessions.db.ts +60 -9
- package/server/modules/database/schema.ts +1 -0
- package/server/modules/projects/projects.routes.ts +20 -3
- package/server/modules/projects/services/project-delete.service.ts +16 -1
- package/server/modules/projects/services/project-management.service.ts +2 -0
- package/server/modules/projects/services/projects-with-sessions-fetch.service.ts +71 -1
- package/server/modules/providers/README.md +354 -0
- package/server/modules/providers/index.ts +2 -1
- package/server/modules/providers/list/claude/claude-auth.provider.ts +38 -13
- package/server/modules/providers/list/claude/claude-models.provider.ts +191 -0
- package/server/modules/providers/list/claude/claude-session-synchronizer.provider.ts +68 -2
- package/server/modules/providers/list/claude/claude-sessions.provider.ts +175 -14
- package/server/modules/providers/list/claude/claude-skills.provider.ts +257 -0
- package/server/modules/providers/list/claude/claude.provider.ts +11 -1
- package/server/modules/providers/list/codex/codex-models.provider.ts +125 -0
- package/server/modules/providers/list/codex/codex-session-synchronizer.provider.ts +62 -2
- package/server/modules/providers/list/codex/codex-sessions.provider.ts +25 -6
- package/server/modules/providers/list/codex/codex-skills.provider.ts +60 -0
- package/server/modules/providers/list/codex/codex.provider.ts +11 -1
- package/server/modules/providers/list/cursor/cursor-models.provider.ts +820 -0
- package/server/modules/providers/list/cursor/cursor-session-synchronizer.provider.ts +17 -40
- package/server/modules/providers/list/cursor/cursor-sessions.provider.ts +216 -26
- package/server/modules/providers/list/cursor/cursor-skills.provider.ts +31 -0
- package/server/modules/providers/list/cursor/cursor.provider.ts +11 -1
- package/server/modules/providers/list/gemini/gemini-auth.provider.ts +158 -2
- package/server/modules/providers/list/gemini/gemini-models.provider.ts +42 -0
- package/server/modules/providers/list/gemini/gemini-session-synchronizer.provider.ts +24 -20
- package/server/modules/providers/list/gemini/gemini-sessions.provider.ts +10 -11
- package/server/modules/providers/list/gemini/gemini-skills.provider.ts +36 -0
- package/server/modules/providers/list/gemini/gemini.provider.ts +11 -1
- package/server/modules/providers/list/opencode/opencode-auth.provider.ts +111 -0
- package/server/modules/providers/list/opencode/opencode-mcp.provider.ts +228 -0
- package/server/modules/providers/list/opencode/opencode-models.provider.ts +339 -0
- package/server/modules/providers/list/opencode/opencode-session-synchronizer.provider.ts +157 -0
- package/server/modules/providers/list/opencode/opencode-sessions.provider.ts +506 -0
- package/server/modules/providers/list/opencode/opencode-skills.provider.ts +78 -0
- package/server/modules/providers/list/opencode/opencode.provider.ts +27 -0
- package/server/modules/providers/provider.registry.ts +2 -0
- package/server/modules/providers/provider.routes.ts +97 -4
- package/server/modules/providers/services/mcp.service.ts +1 -12
- package/server/modules/providers/services/provider-models.service.ts +325 -0
- package/server/modules/providers/services/session-conversations-search.service.ts +162 -13
- package/server/modules/providers/services/session-synchronizer.service.ts +1 -0
- package/server/modules/providers/services/sessions-watcher.service.ts +14 -4
- package/server/modules/providers/services/sessions.service.ts +112 -9
- package/server/modules/providers/services/skills.service.ts +15 -0
- package/server/modules/providers/shared/base/abstract.provider.ts +4 -0
- package/server/modules/providers/shared/skills/skills.provider.ts +64 -0
- package/server/modules/providers/tests/mcp.test.ts +93 -6
- package/server/modules/providers/tests/opencode-models.test.ts +73 -0
- package/server/modules/providers/tests/opencode-sessions.test.ts +334 -0
- package/server/modules/providers/tests/provider-models.service.test.ts +318 -0
- package/server/modules/providers/tests/skills.test.ts +512 -0
- package/server/modules/websocket/services/chat-websocket.service.ts +15 -1
- package/server/modules/websocket/services/plugin-websocket-proxy.service.ts +4 -4
- package/server/modules/websocket/services/shell-websocket.service.ts +9 -0
- package/server/openai-codex.js +99 -30
- package/server/opencode-cli.js +336 -0
- package/server/opencode-cli.test.js +95 -0
- package/server/routes/agent.js +22 -8
- package/server/routes/commands.js +256 -233
- package/server/routes/cursor.js +2 -2
- package/server/routes/settings.js +1 -10
- package/server/routes/tests/commands.test.js +82 -0
- package/server/shared/claude-cli-path.test.ts +61 -0
- package/server/shared/claude-cli-path.ts +139 -0
- package/server/{utils/frontmatter.js → shared/frontmatter.ts} +3 -3
- package/server/shared/interfaces.ts +64 -0
- package/server/shared/types.ts +166 -1
- package/server/shared/utils.ts +478 -0
- package/server/utils/commandParser.js +5 -3
- package/dist/assets/index-6rYG_mRo.css +0 -32
- package/dist-server/server/utils/frontmatter.js.map +0 -1
- package/dist-server/shared/modelConstants.js +0 -98
- package/dist-server/shared/modelConstants.js.map +0 -1
- package/shared/modelConstants.js +0 -106
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type { IProviderModels } from '@/shared/interfaces.js';
|
|
2
|
+
import type {
|
|
3
|
+
ProviderChangeActiveModelInput,
|
|
4
|
+
ProviderCurrentActiveModel,
|
|
5
|
+
ProviderModelsDefinition,
|
|
6
|
+
ProviderSessionActiveModelChange,
|
|
7
|
+
} from '@/shared/types.js';
|
|
8
|
+
import {
|
|
9
|
+
buildDefaultProviderCurrentActiveModel,
|
|
10
|
+
writeProviderSessionActiveModelChange,
|
|
11
|
+
} from '@/shared/utils.js';
|
|
12
|
+
|
|
13
|
+
export const GEMINI_FALLBACK_MODELS: ProviderModelsDefinition = {
|
|
14
|
+
OPTIONS: [
|
|
15
|
+
{ value: 'gemini-3.1-pro-preview', label: 'Gemini 3.1 Pro Preview' },
|
|
16
|
+
{ value: 'gemini-3-pro-preview', label: 'Gemini 3 Pro Preview' },
|
|
17
|
+
{ value: 'gemini-3-flash-preview', label: 'Gemini 3 Flash Preview' },
|
|
18
|
+
{ value: 'gemini-2.5-flash', label: 'Gemini 2.5 Flash' },
|
|
19
|
+
{ value: 'gemini-2.5-pro', label: 'Gemini 2.5 Pro' },
|
|
20
|
+
{ value: 'gemini-2.0-flash-lite', label: 'Gemini 2.0 Flash Lite' },
|
|
21
|
+
{ value: 'gemini-2.0-flash', label: 'Gemini 2.0 Flash' },
|
|
22
|
+
{ value: 'gemini-2.0-pro-exp', label: 'Gemini 2.0 Pro Experimental' },
|
|
23
|
+
{ value: 'gemini-2.0-flash-thinking-exp', label: 'Gemini 2.0 Flash Thinking' },
|
|
24
|
+
],
|
|
25
|
+
DEFAULT: 'gemini-3.1-pro-preview',
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
export class GeminiProviderModels implements IProviderModels {
|
|
29
|
+
async getSupportedModels(): Promise<ProviderModelsDefinition> {
|
|
30
|
+
return GEMINI_FALLBACK_MODELS;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
async getCurrentActiveModel(): Promise<ProviderCurrentActiveModel> {
|
|
34
|
+
return buildDefaultProviderCurrentActiveModel(GEMINI_FALLBACK_MODELS);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
async changeActiveModel(
|
|
38
|
+
input: ProviderChangeActiveModelInput,
|
|
39
|
+
): Promise<ProviderSessionActiveModelChange> {
|
|
40
|
+
return writeProviderSessionActiveModelChange('gemini', input);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
@@ -39,33 +39,37 @@ export class GeminiSessionSynchronizer implements IProviderSessionSynchronizer {
|
|
|
39
39
|
async synchronize(since?: Date): Promise<number> {
|
|
40
40
|
const projectHashLookup = this.buildProjectHashLookup();
|
|
41
41
|
|
|
42
|
-
const legacySessionFiles = await findFilesRecursivelyCreatedAfter(
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
);
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
)
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
)
|
|
42
|
+
// const legacySessionFiles = await findFilesRecursivelyCreatedAfter(
|
|
43
|
+
// path.join(this.geminiHome, 'sessions'),
|
|
44
|
+
// '.json',
|
|
45
|
+
// since ?? null
|
|
46
|
+
// );
|
|
47
|
+
// Gemini creates overlapping artifacts across `sessions/` and `tmp/`.
|
|
48
|
+
// We currently index only `tmp/*/chats/*.jsonl` because those files are the
|
|
49
|
+
// live transcript source and avoid duplicate session rows from mirrored files.
|
|
50
|
+
// const legacyTempFiles = await findFilesRecursivelyCreatedAfter(
|
|
51
|
+
// path.join(this.geminiHome, 'tmp'),
|
|
52
|
+
// '.json',
|
|
53
|
+
// since ?? null
|
|
54
|
+
// );
|
|
55
|
+
// const jsonlSessionFiles = await findFilesRecursivelyCreatedAfter(
|
|
56
|
+
// path.join(this.geminiHome, 'sessions'),
|
|
57
|
+
// '.jsonl',
|
|
58
|
+
// since ?? null
|
|
59
|
+
// );
|
|
57
60
|
const jsonlTempFiles = await findFilesRecursivelyCreatedAfter(
|
|
58
61
|
path.join(this.geminiHome, 'tmp'),
|
|
59
62
|
'.jsonl',
|
|
60
63
|
since ?? null
|
|
61
64
|
);
|
|
62
65
|
|
|
63
|
-
//
|
|
64
|
-
// the JSONL artifact becomes the canonical jsonl_path via upsert.
|
|
66
|
+
// Current strategy: index only temp chat JSONL artifacts.
|
|
65
67
|
const files = [
|
|
66
|
-
...legacySessionFiles,
|
|
67
|
-
|
|
68
|
-
|
|
68
|
+
// ...legacySessionFiles,
|
|
69
|
+
// Intentionally disabled to avoid duplicate indexing from mirrored
|
|
70
|
+
// `sessions/*.json` and `sessions/*.jsonl` artifacts.
|
|
71
|
+
// ...legacyTempFiles,
|
|
72
|
+
// ...jsonlSessionFiles,
|
|
69
73
|
...jsonlTempFiles,
|
|
70
74
|
];
|
|
71
75
|
|
|
@@ -88,22 +88,15 @@ function buildGeminiTokenUsage(tokens: unknown): AnyRecord | undefined {
|
|
|
88
88
|
const record = tokens as AnyRecord;
|
|
89
89
|
const input = Number(record.input || 0);
|
|
90
90
|
const output = Number(record.output || 0);
|
|
91
|
-
const
|
|
92
|
-
const thoughts = Number(record.thoughts || 0);
|
|
93
|
-
const tool = Number(record.tool || 0);
|
|
94
|
-
|
|
95
|
-
const totalFromFields = input + output + cached + thoughts + tool;
|
|
96
|
-
const total = Number(record.total || totalFromFields || 0);
|
|
91
|
+
const total = Number(record.total || input + output || 0);
|
|
97
92
|
|
|
98
93
|
return {
|
|
99
94
|
used: total,
|
|
100
|
-
|
|
95
|
+
inputTokens: input,
|
|
96
|
+
outputTokens: output,
|
|
101
97
|
breakdown: {
|
|
102
98
|
input,
|
|
103
99
|
output,
|
|
104
|
-
cached,
|
|
105
|
-
thoughts,
|
|
106
|
-
tool,
|
|
107
100
|
},
|
|
108
101
|
};
|
|
109
102
|
}
|
|
@@ -528,10 +521,16 @@ export class GeminiSessionsProvider implements IProviderSessions {
|
|
|
528
521
|
const messages = pageLimit === null
|
|
529
522
|
? normalized.slice(start)
|
|
530
523
|
: normalized.slice(start, start + pageLimit);
|
|
524
|
+
let total = 0;
|
|
525
|
+
for (const msg of normalized) {
|
|
526
|
+
if (msg.kind !== 'tool_result') {
|
|
527
|
+
total += 1;
|
|
528
|
+
}
|
|
529
|
+
}
|
|
531
530
|
|
|
532
531
|
return {
|
|
533
532
|
messages,
|
|
534
|
-
total
|
|
533
|
+
total,
|
|
535
534
|
hasMore: pageLimit === null ? false : start + pageLimit < normalized.length,
|
|
536
535
|
offset: start,
|
|
537
536
|
limit: pageLimit,
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import os from 'node:os';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
|
|
4
|
+
import { SkillsProvider } from '@/modules/providers/shared/skills/skills.provider.js';
|
|
5
|
+
import type { ProviderSkillSource } from '@/shared/types.js';
|
|
6
|
+
|
|
7
|
+
export class GeminiSkillsProvider extends SkillsProvider {
|
|
8
|
+
constructor() {
|
|
9
|
+
super('gemini');
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
protected async getSkillSources(workspacePath: string): Promise<ProviderSkillSource[]> {
|
|
13
|
+
return [
|
|
14
|
+
{
|
|
15
|
+
scope: 'user',
|
|
16
|
+
rootDir: path.join(os.homedir(), '.gemini', 'skills'),
|
|
17
|
+
commandPrefix: '/',
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
scope: 'user',
|
|
21
|
+
rootDir: path.join(os.homedir(), '.agents', 'skills'),
|
|
22
|
+
commandPrefix: '/',
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
scope: 'project',
|
|
26
|
+
rootDir: path.join(workspacePath, '.gemini', 'skills'),
|
|
27
|
+
commandPrefix: '/',
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
scope: 'project',
|
|
31
|
+
rootDir: path.join(workspacePath, '.agents', 'skills'),
|
|
32
|
+
commandPrefix: '/',
|
|
33
|
+
},
|
|
34
|
+
];
|
|
35
|
+
}
|
|
36
|
+
}
|
|
@@ -1,13 +1,23 @@
|
|
|
1
1
|
import { AbstractProvider } from '@/modules/providers/shared/base/abstract.provider.js';
|
|
2
2
|
import { GeminiProviderAuth } from '@/modules/providers/list/gemini/gemini-auth.provider.js';
|
|
3
|
+
import { GeminiProviderModels } from '@/modules/providers/list/gemini/gemini-models.provider.js';
|
|
3
4
|
import { GeminiMcpProvider } from '@/modules/providers/list/gemini/gemini-mcp.provider.js';
|
|
4
5
|
import { GeminiSessionSynchronizer } from '@/modules/providers/list/gemini/gemini-session-synchronizer.provider.js';
|
|
5
6
|
import { GeminiSessionsProvider } from '@/modules/providers/list/gemini/gemini-sessions.provider.js';
|
|
6
|
-
import
|
|
7
|
+
import { GeminiSkillsProvider } from '@/modules/providers/list/gemini/gemini-skills.provider.js';
|
|
8
|
+
import type {
|
|
9
|
+
IProviderAuth,
|
|
10
|
+
IProviderModels,
|
|
11
|
+
IProviderSessionSynchronizer,
|
|
12
|
+
IProviderSkills,
|
|
13
|
+
IProviderSessions,
|
|
14
|
+
} from '@/shared/interfaces.js';
|
|
7
15
|
|
|
8
16
|
export class GeminiProvider extends AbstractProvider {
|
|
17
|
+
readonly models: IProviderModels = new GeminiProviderModels();
|
|
9
18
|
readonly mcp = new GeminiMcpProvider();
|
|
10
19
|
readonly auth: IProviderAuth = new GeminiProviderAuth();
|
|
20
|
+
readonly skills: IProviderSkills = new GeminiSkillsProvider();
|
|
11
21
|
readonly sessions: IProviderSessions = new GeminiSessionsProvider();
|
|
12
22
|
readonly sessionSynchronizer: IProviderSessionSynchronizer = new GeminiSessionSynchronizer();
|
|
13
23
|
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { readFile } from 'node:fs/promises';
|
|
2
|
+
import os from 'node:os';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
|
|
5
|
+
import spawn from 'cross-spawn';
|
|
6
|
+
|
|
7
|
+
import type { IProviderAuth } from '@/shared/interfaces.js';
|
|
8
|
+
import type { ProviderAuthStatus } from '@/shared/types.js';
|
|
9
|
+
import { readObjectRecord, readOptionalString } from '@/shared/utils.js';
|
|
10
|
+
|
|
11
|
+
type OpenCodeCredentialsStatus = {
|
|
12
|
+
authenticated: boolean;
|
|
13
|
+
email: string | null;
|
|
14
|
+
method: string | null;
|
|
15
|
+
error?: string;
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
const OPENCODE_ENV_CREDENTIAL_KEYS = [
|
|
19
|
+
'ANTHROPIC_API_KEY',
|
|
20
|
+
'OPENAI_API_KEY',
|
|
21
|
+
'GOOGLE_GENERATIVE_AI_API_KEY',
|
|
22
|
+
'GEMINI_API_KEY',
|
|
23
|
+
'GROQ_API_KEY',
|
|
24
|
+
'OPENROUTER_API_KEY',
|
|
25
|
+
];
|
|
26
|
+
|
|
27
|
+
export class OpenCodeProviderAuth implements IProviderAuth {
|
|
28
|
+
/**
|
|
29
|
+
* Checks whether the OpenCode CLI is available to the server process.
|
|
30
|
+
*/
|
|
31
|
+
private checkInstalled(): boolean {
|
|
32
|
+
try {
|
|
33
|
+
const result = spawn.sync('opencode', ['--version'], { stdio: 'ignore', timeout: 5000 });
|
|
34
|
+
return !result.error && result.status === 0;
|
|
35
|
+
} catch {
|
|
36
|
+
return false;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Returns OpenCode CLI installation and credential status.
|
|
42
|
+
*/
|
|
43
|
+
async getStatus(): Promise<ProviderAuthStatus> {
|
|
44
|
+
const installed = this.checkInstalled();
|
|
45
|
+
const credentials = await this.checkCredentials();
|
|
46
|
+
|
|
47
|
+
return {
|
|
48
|
+
installed,
|
|
49
|
+
provider: 'opencode',
|
|
50
|
+
authenticated: credentials.authenticated,
|
|
51
|
+
email: credentials.email,
|
|
52
|
+
method: credentials.method,
|
|
53
|
+
error: credentials.authenticated ? undefined : credentials.error || 'Not authenticated',
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Reads OpenCode's auth store or falls back to provider API key environment variables.
|
|
59
|
+
*/
|
|
60
|
+
private async checkCredentials(): Promise<OpenCodeCredentialsStatus> {
|
|
61
|
+
try {
|
|
62
|
+
const authPath = path.join(os.homedir(), '.local', 'share', 'opencode', 'auth.json');
|
|
63
|
+
const content = await readFile(authPath, 'utf8');
|
|
64
|
+
const auth = readObjectRecord(JSON.parse(content)) ?? {};
|
|
65
|
+
|
|
66
|
+
for (const [providerId, providerAuth] of Object.entries(auth)) {
|
|
67
|
+
const providerRecord = readObjectRecord(providerAuth);
|
|
68
|
+
if (!providerRecord) {
|
|
69
|
+
continue;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const hasCredential = Object.values(providerRecord).some(
|
|
73
|
+
(value) => readOptionalString(value) !== undefined || Boolean(readObjectRecord(value)),
|
|
74
|
+
);
|
|
75
|
+
if (hasCredential) {
|
|
76
|
+
return {
|
|
77
|
+
authenticated: true,
|
|
78
|
+
email: `${providerId} credentials`,
|
|
79
|
+
method: 'credentials_file',
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
} catch (error) {
|
|
84
|
+
const code = (error as NodeJS.ErrnoException).code;
|
|
85
|
+
if (code !== 'ENOENT') {
|
|
86
|
+
return {
|
|
87
|
+
authenticated: false,
|
|
88
|
+
email: null,
|
|
89
|
+
method: null,
|
|
90
|
+
error: error instanceof Error ? error.message : 'Failed to read OpenCode auth',
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
const envCredential = OPENCODE_ENV_CREDENTIAL_KEYS.find((key) => process.env[key]?.trim());
|
|
96
|
+
if (envCredential) {
|
|
97
|
+
return {
|
|
98
|
+
authenticated: true,
|
|
99
|
+
email: envCredential,
|
|
100
|
+
method: 'environment',
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
return {
|
|
105
|
+
authenticated: false,
|
|
106
|
+
email: null,
|
|
107
|
+
method: null,
|
|
108
|
+
error: 'OpenCode not configured',
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
}
|
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
import { access, mkdir, readFile, writeFile } from 'node:fs/promises';
|
|
2
|
+
import os from 'node:os';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
|
|
5
|
+
import { McpProvider } from '@/modules/providers/shared/mcp/mcp.provider.js';
|
|
6
|
+
import type { McpScope, ProviderMcpServer, UpsertProviderMcpServerInput } from '@/shared/types.js';
|
|
7
|
+
import {
|
|
8
|
+
AppError,
|
|
9
|
+
readObjectRecord,
|
|
10
|
+
readOptionalString,
|
|
11
|
+
readStringArray,
|
|
12
|
+
readStringRecord,
|
|
13
|
+
} from '@/shared/utils.js';
|
|
14
|
+
|
|
15
|
+
type OpenCodeConfigPath = {
|
|
16
|
+
filePath: string;
|
|
17
|
+
exists: boolean;
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
const fileExists = async (filePath: string): Promise<boolean> => {
|
|
21
|
+
try {
|
|
22
|
+
await access(filePath);
|
|
23
|
+
return true;
|
|
24
|
+
} catch {
|
|
25
|
+
return false;
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Removes JSONC comments without touching comment-like text inside strings.
|
|
31
|
+
*/
|
|
32
|
+
const stripJsonComments = (content: string): string => {
|
|
33
|
+
let output = '';
|
|
34
|
+
let inString = false;
|
|
35
|
+
let quote = '';
|
|
36
|
+
let escaped = false;
|
|
37
|
+
|
|
38
|
+
for (let index = 0; index < content.length; index += 1) {
|
|
39
|
+
const char = content[index];
|
|
40
|
+
const next = content[index + 1];
|
|
41
|
+
|
|
42
|
+
if (inString) {
|
|
43
|
+
output += char;
|
|
44
|
+
if (escaped) {
|
|
45
|
+
escaped = false;
|
|
46
|
+
} else if (char === '\\') {
|
|
47
|
+
escaped = true;
|
|
48
|
+
} else if (char === quote) {
|
|
49
|
+
inString = false;
|
|
50
|
+
quote = '';
|
|
51
|
+
}
|
|
52
|
+
continue;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
if (char === '"' || char === '\'') {
|
|
56
|
+
inString = true;
|
|
57
|
+
quote = char;
|
|
58
|
+
output += char;
|
|
59
|
+
continue;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
if (char === '/' && next === '/') {
|
|
63
|
+
while (index < content.length && content[index] !== '\n') {
|
|
64
|
+
index += 1;
|
|
65
|
+
}
|
|
66
|
+
output += '\n';
|
|
67
|
+
continue;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
if (char === '/' && next === '*') {
|
|
71
|
+
index += 2;
|
|
72
|
+
while (index < content.length && !(content[index] === '*' && content[index + 1] === '/')) {
|
|
73
|
+
index += 1;
|
|
74
|
+
}
|
|
75
|
+
index += 1;
|
|
76
|
+
continue;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
output += char;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
return output;
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
const stripTrailingCommas = (content: string): string =>
|
|
86
|
+
content.replace(/,\s*([}\]])/g, '$1');
|
|
87
|
+
|
|
88
|
+
const readOpenCodeConfig = async (filePath: string): Promise<Record<string, unknown>> => {
|
|
89
|
+
try {
|
|
90
|
+
const content = await readFile(filePath, 'utf8');
|
|
91
|
+
const parsed = JSON.parse(stripTrailingCommas(stripJsonComments(content))) as unknown;
|
|
92
|
+
return readObjectRecord(parsed) ?? {};
|
|
93
|
+
} catch (error) {
|
|
94
|
+
const code = (error as NodeJS.ErrnoException).code;
|
|
95
|
+
if (code === 'ENOENT') {
|
|
96
|
+
return {};
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
throw error;
|
|
100
|
+
}
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
const writeOpenCodeConfig = async (filePath: string, data: Record<string, unknown>): Promise<void> => {
|
|
104
|
+
await mkdir(path.dirname(filePath), { recursive: true });
|
|
105
|
+
await writeFile(filePath, `${JSON.stringify(data, null, 2)}\n`, 'utf8');
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
const resolveOpenCodeConfigPath = async (scope: McpScope, workspacePath: string): Promise<OpenCodeConfigPath> => {
|
|
109
|
+
const root = scope === 'user'
|
|
110
|
+
? path.join(os.homedir(), '.config', 'opencode')
|
|
111
|
+
: workspacePath;
|
|
112
|
+
const jsonPath = path.join(root, 'opencode.json');
|
|
113
|
+
const jsoncPath = path.join(root, 'opencode.jsonc');
|
|
114
|
+
|
|
115
|
+
if (await fileExists(jsonPath)) {
|
|
116
|
+
return { filePath: jsonPath, exists: true };
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
if (await fileExists(jsoncPath)) {
|
|
120
|
+
return { filePath: jsoncPath, exists: true };
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
return { filePath: jsonPath, exists: false };
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
export class OpenCodeMcpProvider extends McpProvider {
|
|
127
|
+
constructor() {
|
|
128
|
+
super('opencode', ['user', 'project'], ['stdio', 'http']);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
protected async readScopedServers(scope: McpScope, workspacePath: string): Promise<Record<string, unknown>> {
|
|
132
|
+
const { filePath } = await resolveOpenCodeConfigPath(scope, workspacePath);
|
|
133
|
+
const config = await readOpenCodeConfig(filePath);
|
|
134
|
+
return readObjectRecord(config.mcp) ?? {};
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
protected async writeScopedServers(
|
|
138
|
+
scope: McpScope,
|
|
139
|
+
workspacePath: string,
|
|
140
|
+
servers: Record<string, unknown>,
|
|
141
|
+
): Promise<void> {
|
|
142
|
+
const { filePath } = await resolveOpenCodeConfigPath(scope, workspacePath);
|
|
143
|
+
const config = await readOpenCodeConfig(filePath);
|
|
144
|
+
config.mcp = servers;
|
|
145
|
+
await writeOpenCodeConfig(filePath, config);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
protected buildServerConfig(input: UpsertProviderMcpServerInput): Record<string, unknown> {
|
|
149
|
+
if (input.transport === 'stdio') {
|
|
150
|
+
if (!input.command?.trim()) {
|
|
151
|
+
throw new AppError('command is required for stdio MCP servers.', {
|
|
152
|
+
code: 'MCP_COMMAND_REQUIRED',
|
|
153
|
+
statusCode: 400,
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
return {
|
|
158
|
+
type: 'local',
|
|
159
|
+
command: [input.command, ...(input.args ?? [])],
|
|
160
|
+
enabled: true,
|
|
161
|
+
environment: input.env ?? {},
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
if (!input.url?.trim()) {
|
|
166
|
+
throw new AppError('url is required for http MCP servers.', {
|
|
167
|
+
code: 'MCP_URL_REQUIRED',
|
|
168
|
+
statusCode: 400,
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
return {
|
|
173
|
+
type: 'remote',
|
|
174
|
+
url: input.url,
|
|
175
|
+
enabled: true,
|
|
176
|
+
headers: input.headers ?? {},
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
protected normalizeServerConfig(
|
|
181
|
+
scope: McpScope,
|
|
182
|
+
name: string,
|
|
183
|
+
rawConfig: unknown,
|
|
184
|
+
): ProviderMcpServer | null {
|
|
185
|
+
const config = readObjectRecord(rawConfig);
|
|
186
|
+
if (!config) {
|
|
187
|
+
return null;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
if (config.type === 'local' || config.command !== undefined) {
|
|
191
|
+
const commandParts = typeof config.command === 'string'
|
|
192
|
+
? [config.command, ...(readStringArray(config.args) ?? [])]
|
|
193
|
+
: readStringArray(config.command);
|
|
194
|
+
const command = commandParts?.[0];
|
|
195
|
+
if (!command) {
|
|
196
|
+
return null;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
return {
|
|
200
|
+
provider: 'opencode',
|
|
201
|
+
name,
|
|
202
|
+
scope,
|
|
203
|
+
transport: 'stdio',
|
|
204
|
+
command,
|
|
205
|
+
args: commandParts.slice(1),
|
|
206
|
+
env: readStringRecord(config.environment) ?? readStringRecord(config.env),
|
|
207
|
+
};
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
if (config.type === 'remote' || typeof config.url === 'string') {
|
|
211
|
+
const url = readOptionalString(config.url);
|
|
212
|
+
if (!url) {
|
|
213
|
+
return null;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
return {
|
|
217
|
+
provider: 'opencode',
|
|
218
|
+
name,
|
|
219
|
+
scope,
|
|
220
|
+
transport: 'http',
|
|
221
|
+
url,
|
|
222
|
+
headers: readStringRecord(config.headers),
|
|
223
|
+
};
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
return null;
|
|
227
|
+
}
|
|
228
|
+
}
|