@cloudcli-ai/cloudcli 1.35.1 → 1.36.1
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 +17 -18
- package/README.ja.md +16 -17
- package/README.ko.md +17 -18
- package/README.md +19 -20
- package/README.ru.md +17 -18
- package/README.tr.md +17 -18
- package/README.zh-CN.md +17 -18
- package/README.zh-TW.md +17 -18
- package/dist/api-docs.html +8 -3
- package/dist/assets/{index-D1IdCTT6.js → index-Bz9vXV2m.js} +265 -260
- package/dist/assets/index-DLmhQ15L.css +32 -0
- package/dist/assets/{vendor-xterm-CJZjLICi.js → vendor-xterm-CS4rQ5Mr.js} +12 -12
- package/dist/index.html +3 -3
- package/dist-server/server/claude-sdk.js +62 -116
- package/dist-server/server/claude-sdk.js.map +1 -1
- package/dist-server/server/cli.js +1 -4
- package/dist-server/server/cli.js.map +1 -1
- package/dist-server/server/cursor-cli.js +12 -11
- package/dist-server/server/cursor-cli.js.map +1 -1
- package/dist-server/server/index.js +10 -141
- package/dist-server/server/index.js.map +1 -1
- package/dist-server/server/modules/assets/assets.routes.js +89 -0
- package/dist-server/server/modules/assets/assets.routes.js.map +1 -0
- package/dist-server/server/modules/assets/index.js +4 -0
- package/dist-server/server/modules/assets/index.js.map +1 -0
- package/dist-server/server/modules/assets/services/image-assets.service.js +57 -0
- package/dist-server/server/modules/assets/services/image-assets.service.js.map +1 -0
- package/dist-server/server/modules/assets/tests/image-assets.service.test.js +36 -0
- package/dist-server/server/modules/assets/tests/image-assets.service.test.js.map +1 -0
- package/dist-server/server/modules/browser-use/browser-use.service.js +6 -3
- package/dist-server/server/modules/browser-use/browser-use.service.js.map +1 -1
- package/dist-server/server/modules/database/tests/sessions-provider-mapping.test.js +2 -2
- package/dist-server/server/modules/database/tests/sessions-provider-mapping.test.js.map +1 -1
- package/dist-server/server/modules/notifications/services/notification-orchestrator.service.js +0 -1
- package/dist-server/server/modules/notifications/services/notification-orchestrator.service.js.map +1 -1
- package/dist-server/server/modules/projects/services/project-clone.service.js +2 -1
- package/dist-server/server/modules/projects/services/project-clone.service.js.map +1 -1
- package/dist-server/server/modules/providers/list/claude/claude-models.provider.js +70 -1
- package/dist-server/server/modules/providers/list/claude/claude-models.provider.js.map +1 -1
- package/dist-server/server/modules/providers/list/claude/claude-sessions.provider.js +28 -0
- package/dist-server/server/modules/providers/list/claude/claude-sessions.provider.js.map +1 -1
- package/dist-server/server/modules/providers/list/codex/codex-models.provider.js +52 -11
- package/dist-server/server/modules/providers/list/codex/codex-models.provider.js.map +1 -1
- package/dist-server/server/modules/providers/list/codex/codex-session-synchronizer.provider.js +54 -1
- 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 +36 -1
- package/dist-server/server/modules/providers/list/codex/codex-sessions.provider.js.map +1 -1
- package/dist-server/server/modules/providers/list/cursor/cursor-models.provider.js +3 -17
- package/dist-server/server/modules/providers/list/cursor/cursor-models.provider.js.map +1 -1
- package/dist-server/server/modules/providers/list/cursor/cursor-session-synchronizer.provider.js +7 -1
- 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 +49 -13
- package/dist-server/server/modules/providers/list/cursor/cursor-sessions.provider.js.map +1 -1
- package/dist-server/server/modules/providers/list/opencode/opencode-auth.provider.js +0 -1
- package/dist-server/server/modules/providers/list/opencode/opencode-auth.provider.js.map +1 -1
- package/dist-server/server/modules/providers/list/opencode/opencode-models.provider.js +145 -14
- package/dist-server/server/modules/providers/list/opencode/opencode-models.provider.js.map +1 -1
- package/dist-server/server/modules/providers/list/opencode/opencode-session-synchronizer.provider.js +24 -5
- package/dist-server/server/modules/providers/list/opencode/opencode-session-synchronizer.provider.js.map +1 -1
- package/dist-server/server/modules/providers/list/opencode/opencode-sessions.provider.js +10 -21
- package/dist-server/server/modules/providers/list/opencode/opencode-sessions.provider.js.map +1 -1
- package/dist-server/server/modules/providers/provider.registry.js +0 -2
- package/dist-server/server/modules/providers/provider.registry.js.map +1 -1
- package/dist-server/server/modules/providers/provider.routes.js +0 -1
- package/dist-server/server/modules/providers/provider.routes.js.map +1 -1
- package/dist-server/server/modules/providers/services/provider-capabilities.service.js +11 -13
- package/dist-server/server/modules/providers/services/provider-capabilities.service.js.map +1 -1
- package/dist-server/server/modules/providers/services/provider-models.service.js +2 -2
- package/dist-server/server/modules/providers/services/provider-models.service.js.map +1 -1
- package/dist-server/server/modules/providers/services/session-conversations-search.service.js +3 -77
- 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 +0 -1
- 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 +0 -13
- package/dist-server/server/modules/providers/services/sessions-watcher.service.js.map +1 -1
- package/dist-server/server/modules/providers/tests/codex-sessions.test.js +96 -0
- package/dist-server/server/modules/providers/tests/codex-sessions.test.js.map +1 -0
- package/dist-server/server/modules/providers/tests/mcp.test.js +3 -29
- package/dist-server/server/modules/providers/tests/mcp.test.js.map +1 -1
- package/dist-server/server/modules/providers/tests/opencode-models.test.js +65 -1
- package/dist-server/server/modules/providers/tests/opencode-models.test.js.map +1 -1
- package/dist-server/server/modules/providers/tests/opencode-sessions.test.js +117 -0
- package/dist-server/server/modules/providers/tests/opencode-sessions.test.js.map +1 -1
- package/dist-server/server/modules/providers/tests/provider-image-history.test.js +147 -0
- package/dist-server/server/modules/providers/tests/provider-image-history.test.js.map +1 -0
- package/dist-server/server/modules/providers/tests/provider-models.service.test.js +8 -8
- package/dist-server/server/modules/providers/tests/skills.test.js +3 -26
- package/dist-server/server/modules/providers/tests/skills.test.js.map +1 -1
- package/dist-server/server/modules/websocket/services/chat-run-registry.service.js +14 -0
- package/dist-server/server/modules/websocket/services/chat-run-registry.service.js.map +1 -1
- package/dist-server/server/modules/websocket/services/chat-websocket.service.js +36 -2
- package/dist-server/server/modules/websocket/services/chat-websocket.service.js.map +1 -1
- package/dist-server/server/modules/websocket/services/shell-websocket.service.js +3 -12
- package/dist-server/server/modules/websocket/services/shell-websocket.service.js.map +1 -1
- package/dist-server/server/modules/websocket/tests/chat-image-filter.test.js +33 -0
- package/dist-server/server/modules/websocket/tests/chat-image-filter.test.js.map +1 -0
- package/dist-server/server/modules/websocket/tests/chat-run-registry.test.js +37 -4
- package/dist-server/server/modules/websocket/tests/chat-run-registry.test.js.map +1 -1
- package/dist-server/server/openai-codex.js +16 -9
- package/dist-server/server/openai-codex.js.map +1 -1
- package/dist-server/server/opencode-cli.js +62 -7
- package/dist-server/server/opencode-cli.js.map +1 -1
- package/dist-server/server/opencode-cli.test.js +103 -3
- package/dist-server/server/opencode-cli.test.js.map +1 -1
- package/dist-server/server/routes/agent.js +22 -21
- package/dist-server/server/routes/agent.js.map +1 -1
- package/dist-server/server/routes/commands.js +1 -2
- package/dist-server/server/routes/commands.js.map +1 -1
- package/dist-server/server/routes/git.js +179 -53
- package/dist-server/server/routes/git.js.map +1 -1
- package/dist-server/server/routes/git.test.js +80 -0
- package/dist-server/server/routes/git.test.js.map +1 -0
- package/dist-server/server/routes/taskmaster.js +3 -1
- package/dist-server/server/routes/taskmaster.js.map +1 -1
- package/dist-server/server/routes/user.js +2 -1
- package/dist-server/server/routes/user.js.map +1 -1
- package/dist-server/server/shared/image-attachments.js +270 -0
- package/dist-server/server/shared/image-attachments.js.map +1 -0
- package/dist-server/server/shared/tests/image-attachments.test.js +220 -0
- package/dist-server/server/shared/tests/image-attachments.test.js.map +1 -0
- package/dist-server/server/shared/utils.js +43 -0
- package/dist-server/server/shared/utils.js.map +1 -1
- package/dist-server/server/utils/gitConfig.js +2 -1
- package/dist-server/server/utils/gitConfig.js.map +1 -1
- package/dist-server/server/utils/plugin-process-manager.js +2 -1
- package/dist-server/server/utils/plugin-process-manager.js.map +1 -1
- package/electron/launcher/launcher.js +1 -1
- package/package.json +3 -3
- package/public/api-docs.html +8 -3
- package/server/claude-sdk.js +69 -131
- package/server/cli.js +1 -4
- package/server/cursor-cli.js +13 -12
- package/server/index.js +11 -159
- package/server/modules/assets/assets.routes.ts +103 -0
- package/server/modules/assets/index.ts +3 -0
- package/server/modules/assets/services/image-assets.service.ts +82 -0
- package/server/modules/assets/tests/image-assets.service.test.ts +46 -0
- package/server/modules/browser-use/browser-use.service.ts +7 -3
- package/server/modules/database/tests/sessions-provider-mapping.test.ts +2 -2
- package/server/modules/notifications/services/notification-orchestrator.service.js +0 -1
- package/server/modules/projects/services/project-clone.service.ts +3 -1
- package/server/modules/providers/README.md +1 -7
- package/server/modules/providers/list/claude/claude-models.provider.ts +73 -1
- package/server/modules/providers/list/claude/claude-sessions.provider.ts +30 -0
- package/server/modules/providers/list/codex/codex-models.provider.ts +59 -11
- package/server/modules/providers/list/codex/codex-session-synchronizer.provider.ts +60 -1
- package/server/modules/providers/list/codex/codex-sessions.provider.ts +41 -1
- package/server/modules/providers/list/cursor/cursor-models.provider.ts +3 -17
- package/server/modules/providers/list/cursor/cursor-session-synchronizer.provider.ts +7 -1
- package/server/modules/providers/list/cursor/cursor-sessions.provider.ts +56 -15
- package/server/modules/providers/list/opencode/opencode-auth.provider.ts +0 -1
- package/server/modules/providers/list/opencode/opencode-models.provider.ts +193 -18
- package/server/modules/providers/list/opencode/opencode-session-synchronizer.provider.ts +25 -4
- package/server/modules/providers/list/opencode/opencode-sessions.provider.ts +10 -21
- package/server/modules/providers/provider.registry.ts +0 -2
- package/server/modules/providers/provider.routes.ts +0 -1
- package/server/modules/providers/services/provider-capabilities.service.ts +13 -13
- package/server/modules/providers/services/provider-models.service.ts +2 -2
- package/server/modules/providers/services/session-conversations-search.service.ts +3 -93
- package/server/modules/providers/services/session-synchronizer.service.ts +0 -1
- package/server/modules/providers/services/sessions-watcher.service.ts +0 -14
- package/server/modules/providers/tests/codex-sessions.test.ts +111 -0
- package/server/modules/providers/tests/mcp.test.ts +3 -34
- package/server/modules/providers/tests/opencode-models.test.ts +69 -0
- package/server/modules/providers/tests/opencode-sessions.test.ts +139 -0
- package/server/modules/providers/tests/provider-image-history.test.ts +180 -0
- package/server/modules/providers/tests/provider-models.service.test.ts +8 -8
- package/server/modules/providers/tests/skills.test.ts +3 -42
- package/server/modules/websocket/services/chat-run-registry.service.ts +16 -0
- package/server/modules/websocket/services/chat-websocket.service.ts +41 -2
- package/server/modules/websocket/services/shell-websocket.service.ts +1 -11
- package/server/modules/websocket/tests/chat-image-filter.test.ts +44 -0
- package/server/modules/websocket/tests/chat-run-registry.test.ts +42 -4
- package/server/openai-codex.js +18 -8
- package/server/opencode-cli.js +64 -7
- package/server/opencode-cli.test.js +112 -3
- package/server/routes/agent.js +22 -21
- package/server/routes/commands.js +1 -2
- package/server/routes/git.js +201 -60
- package/server/routes/git.test.js +106 -0
- package/server/routes/taskmaster.js +3 -1
- package/server/routes/user.js +2 -1
- package/server/shared/image-attachments.ts +341 -0
- package/server/shared/tests/image-attachments.test.ts +298 -0
- package/server/shared/types.ts +8 -1
- package/server/shared/utils.ts +45 -0
- package/server/utils/gitConfig.js +2 -1
- package/server/utils/plugin-process-manager.js +3 -1
- package/dist/assets/index-BvX30NW5.css +0 -32
- package/dist/icons/gemini-ai-icon.svg +0 -1
- package/dist-server/server/gemini-cli.js +0 -551
- package/dist-server/server/gemini-cli.js.map +0 -1
- package/dist-server/server/gemini-response-handler.js +0 -106
- package/dist-server/server/gemini-response-handler.js.map +0 -1
- package/dist-server/server/modules/providers/list/gemini/gemini-auth.provider.js +0 -254
- package/dist-server/server/modules/providers/list/gemini/gemini-auth.provider.js.map +0 -1
- package/dist-server/server/modules/providers/list/gemini/gemini-mcp.provider.js +0 -82
- package/dist-server/server/modules/providers/list/gemini/gemini-mcp.provider.js.map +0 -1
- package/dist-server/server/modules/providers/list/gemini/gemini-models.provider.js +0 -24
- package/dist-server/server/modules/providers/list/gemini/gemini-models.provider.js.map +0 -1
- package/dist-server/server/modules/providers/list/gemini/gemini-session-synchronizer.provider.js +0 -312
- package/dist-server/server/modules/providers/list/gemini/gemini-session-synchronizer.provider.js.map +0 -1
- package/dist-server/server/modules/providers/list/gemini/gemini-sessions.provider.js +0 -474
- package/dist-server/server/modules/providers/list/gemini/gemini-sessions.provider.js.map +0 -1
- package/dist-server/server/modules/providers/list/gemini/gemini-skills.provider.js +0 -40
- package/dist-server/server/modules/providers/list/gemini/gemini-skills.provider.js.map +0 -1
- package/dist-server/server/modules/providers/list/gemini/gemini.provider.js +0 -19
- package/dist-server/server/modules/providers/list/gemini/gemini.provider.js.map +0 -1
- package/dist-server/server/routes/gemini.js +0 -21
- package/dist-server/server/routes/gemini.js.map +0 -1
- package/dist-server/server/sessionManager.js +0 -194
- package/dist-server/server/sessionManager.js.map +0 -1
- package/server/gemini-cli.js +0 -638
- package/server/gemini-response-handler.js +0 -117
- package/server/modules/providers/list/gemini/gemini-auth.provider.ts +0 -307
- package/server/modules/providers/list/gemini/gemini-mcp.provider.ts +0 -110
- package/server/modules/providers/list/gemini/gemini-models.provider.ts +0 -39
- package/server/modules/providers/list/gemini/gemini-session-synchronizer.provider.ts +0 -405
- package/server/modules/providers/list/gemini/gemini-sessions.provider.ts +0 -540
- package/server/modules/providers/list/gemini/gemini-skills.provider.ts +0 -44
- package/server/modules/providers/list/gemini/gemini.provider.ts +0 -27
- package/server/routes/gemini.js +0 -25
- package/server/sessionManager.js +0 -226
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import { spawn } from 'node:child_process';
|
|
2
|
-
|
|
3
1
|
import Database from 'better-sqlite3';
|
|
4
2
|
import crossSpawn from 'cross-spawn';
|
|
5
3
|
|
|
@@ -51,29 +49,28 @@ export const OPENCODE_FALLBACK_MODELS: ProviderModelsDefinition = {
|
|
|
51
49
|
label: 'GPT-5.4 Mini',
|
|
52
50
|
description: 'openai - openai/gpt-5.4-mini',
|
|
53
51
|
},
|
|
54
|
-
{
|
|
55
|
-
value: 'google/gemini-2.5-pro',
|
|
56
|
-
label: 'Gemini 2.5 Pro',
|
|
57
|
-
description: 'google - google/gemini-2.5-pro',
|
|
58
|
-
},
|
|
59
|
-
{
|
|
60
|
-
value: 'google/gemini-2.5-flash',
|
|
61
|
-
label: 'Gemini 2.5 Flash',
|
|
62
|
-
description: 'google - google/gemini-2.5-flash',
|
|
63
|
-
},
|
|
64
52
|
],
|
|
65
53
|
DEFAULT: 'anthropic/claude-sonnet-4-5',
|
|
66
54
|
};
|
|
67
55
|
|
|
68
56
|
const OPEN_CODE_MODELS_TIMEOUT_MS = 20_000;
|
|
69
57
|
const MODEL_ID_LINE = /^[a-z0-9][a-z0-9._-]*\/[a-z0-9][a-z0-9._-]*$/i;
|
|
70
|
-
|
|
58
|
+
// cross-spawn resolves .cmd shims/PATHEXT on Windows and delegates to
|
|
59
|
+
// child_process.spawn everywhere else.
|
|
60
|
+
const spawnFunction = crossSpawn;
|
|
71
61
|
const DATE_TOKEN = /^\d{8}$/;
|
|
72
62
|
const SIMPLE_NUMBER_TOKEN = /^\d$/;
|
|
73
63
|
const VERSION_TOKEN = /^[a-z]\d+$/i;
|
|
74
64
|
const NUMERIC_TOKEN = /^\d+(?:\.\d+)*$/;
|
|
75
65
|
const SHORT_ACRONYM_TOKEN = /^[a-z]{2,3}$/;
|
|
76
66
|
|
|
67
|
+
type OpenCodeVerboseModel = {
|
|
68
|
+
id?: string;
|
|
69
|
+
name?: string;
|
|
70
|
+
providerID?: string;
|
|
71
|
+
variants?: Record<string, unknown>;
|
|
72
|
+
};
|
|
73
|
+
|
|
77
74
|
export const parseOpenCodeModelsStdout = (stdout: string): string[] => {
|
|
78
75
|
const ids: string[] = [];
|
|
79
76
|
|
|
@@ -91,6 +88,83 @@ export const parseOpenCodeModelsStdout = (stdout: string): string[] => {
|
|
|
91
88
|
return [...new Set(ids)];
|
|
92
89
|
};
|
|
93
90
|
|
|
91
|
+
const countJsonBraceDelta = (value: string): number => {
|
|
92
|
+
let delta = 0;
|
|
93
|
+
let inString = false;
|
|
94
|
+
let escaped = false;
|
|
95
|
+
|
|
96
|
+
for (const character of value) {
|
|
97
|
+
if (escaped) {
|
|
98
|
+
escaped = false;
|
|
99
|
+
continue;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
if (character === '\\') {
|
|
103
|
+
escaped = inString;
|
|
104
|
+
continue;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
if (character === '"') {
|
|
108
|
+
inString = !inString;
|
|
109
|
+
continue;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
if (inString) {
|
|
113
|
+
continue;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
if (character === '{') {
|
|
117
|
+
delta += 1;
|
|
118
|
+
} else if (character === '}') {
|
|
119
|
+
delta -= 1;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
return delta;
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
const isOpenCodeVerboseModel = (value: unknown): value is OpenCodeVerboseModel => {
|
|
127
|
+
const record = readObjectRecord(value);
|
|
128
|
+
return Boolean(record && readOptionalString(record.id));
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
export const parseOpenCodeVerboseModelsStdout = (stdout: string): OpenCodeVerboseModel[] => {
|
|
132
|
+
const models: OpenCodeVerboseModel[] = [];
|
|
133
|
+
let buffer: string[] = [];
|
|
134
|
+
let depth = 0;
|
|
135
|
+
|
|
136
|
+
for (const rawLine of stdout.split(/\r?\n/)) {
|
|
137
|
+
const line = rawLine.trim();
|
|
138
|
+
if (buffer.length === 0) {
|
|
139
|
+
if (line === '{') {
|
|
140
|
+
buffer = [rawLine];
|
|
141
|
+
depth = 1;
|
|
142
|
+
}
|
|
143
|
+
continue;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
buffer.push(rawLine);
|
|
147
|
+
depth += countJsonBraceDelta(rawLine);
|
|
148
|
+
|
|
149
|
+
if (depth !== 0) {
|
|
150
|
+
continue;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
try {
|
|
154
|
+
const parsed = JSON.parse(buffer.join('\n'));
|
|
155
|
+
if (isOpenCodeVerboseModel(parsed)) {
|
|
156
|
+
models.push(parsed);
|
|
157
|
+
}
|
|
158
|
+
} catch {
|
|
159
|
+
// Ignore malformed verbose blocks and fall back to the plain id parser.
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
buffer = [];
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
return models;
|
|
166
|
+
};
|
|
167
|
+
|
|
94
168
|
const formatDateToken = (token: string): string => (
|
|
95
169
|
`${token.slice(0, 4)}-${token.slice(4, 6)}-${token.slice(6, 8)}`
|
|
96
170
|
);
|
|
@@ -155,6 +229,24 @@ const readOpenCodeModelParts = (id: string): { upstreamProvider: string; slug: s
|
|
|
155
229
|
};
|
|
156
230
|
};
|
|
157
231
|
|
|
232
|
+
const isSupportedOpenCodeModelId = (id: string): boolean => (
|
|
233
|
+
readOpenCodeModelParts(id).upstreamProvider.toLowerCase() !== 'google'
|
|
234
|
+
);
|
|
235
|
+
|
|
236
|
+
const readOpenCodeVerboseModelId = (model: OpenCodeVerboseModel): string | null => {
|
|
237
|
+
const id = readOptionalString(model.id);
|
|
238
|
+
if (!id) {
|
|
239
|
+
return null;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
if (id.includes('/')) {
|
|
243
|
+
return id;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
const upstreamProvider = readOptionalString(model.providerID);
|
|
247
|
+
return upstreamProvider ? `${upstreamProvider}/${id}` : id;
|
|
248
|
+
};
|
|
249
|
+
|
|
158
250
|
const labelForOpenCodeModelId = (id: string): string => {
|
|
159
251
|
const fallbackLabel = OPENCODE_FALLBACK_MODELS.OPTIONS.find((option) => option.value === id)?.label;
|
|
160
252
|
if (fallbackLabel) {
|
|
@@ -170,12 +262,90 @@ const descriptionForOpenCodeModelId = (id: string): string => {
|
|
|
170
262
|
return upstreamProvider ? `${upstreamProvider} - ${id}` : id;
|
|
171
263
|
};
|
|
172
264
|
|
|
173
|
-
|
|
174
|
-
const
|
|
265
|
+
const readOpenCodeVariantEffort = (key: string, value: unknown): string | null => {
|
|
266
|
+
const variant = readObjectRecord(value);
|
|
267
|
+
return readOptionalString(variant?.reasoningEffort)
|
|
268
|
+
?? readOptionalString(variant?.effort)
|
|
269
|
+
?? key;
|
|
270
|
+
};
|
|
271
|
+
|
|
272
|
+
const readOpenCodeEffortValues = (
|
|
273
|
+
variants: OpenCodeVerboseModel['variants'],
|
|
274
|
+
): NonNullable<ProviderModelOption['effort']>['values'] => {
|
|
275
|
+
const effortValues: NonNullable<ProviderModelOption['effort']>['values'] = [];
|
|
276
|
+
const seenValues = new Set<string>();
|
|
277
|
+
|
|
278
|
+
for (const [key, value] of Object.entries(variants ?? {})) {
|
|
279
|
+
const effort = readOpenCodeVariantEffort(key, value);
|
|
280
|
+
if (!effort || seenValues.has(effort)) {
|
|
281
|
+
continue;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
seenValues.add(effort);
|
|
285
|
+
effortValues.push({ value: effort });
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
return effortValues;
|
|
289
|
+
};
|
|
290
|
+
|
|
291
|
+
const mapOpenCodeVerboseModel = (model: OpenCodeVerboseModel): ProviderModelOption | null => {
|
|
292
|
+
const value = readOpenCodeVerboseModelId(model);
|
|
293
|
+
if (!value || !isSupportedOpenCodeModelId(value)) {
|
|
294
|
+
return null;
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
const effortValues = readOpenCodeEffortValues(model.variants);
|
|
298
|
+
|
|
299
|
+
return {
|
|
175
300
|
value,
|
|
176
|
-
label: labelForOpenCodeModelId(value),
|
|
301
|
+
label: readOptionalString(model.name) ?? labelForOpenCodeModelId(value),
|
|
177
302
|
description: descriptionForOpenCodeModelId(value),
|
|
178
|
-
|
|
303
|
+
effort: effortValues.length > 0
|
|
304
|
+
? {
|
|
305
|
+
values: effortValues,
|
|
306
|
+
}
|
|
307
|
+
: undefined,
|
|
308
|
+
};
|
|
309
|
+
};
|
|
310
|
+
|
|
311
|
+
export const buildOpenCodeDefinitionFromIds = (ids: string[]): ProviderModelsDefinition => {
|
|
312
|
+
const options: ProviderModelOption[] = ids
|
|
313
|
+
.filter(isSupportedOpenCodeModelId)
|
|
314
|
+
.map((value) => ({
|
|
315
|
+
value,
|
|
316
|
+
label: labelForOpenCodeModelId(value),
|
|
317
|
+
description: descriptionForOpenCodeModelId(value),
|
|
318
|
+
}));
|
|
319
|
+
|
|
320
|
+
const defaultValue = options.find((option) => option.value === OPENCODE_FALLBACK_MODELS.DEFAULT)?.value
|
|
321
|
+
?? options[0]?.value
|
|
322
|
+
?? OPENCODE_FALLBACK_MODELS.DEFAULT;
|
|
323
|
+
|
|
324
|
+
return {
|
|
325
|
+
OPTIONS: options,
|
|
326
|
+
DEFAULT: defaultValue,
|
|
327
|
+
};
|
|
328
|
+
};
|
|
329
|
+
|
|
330
|
+
export const buildOpenCodeDefinitionFromVerboseModels = (
|
|
331
|
+
models: OpenCodeVerboseModel[],
|
|
332
|
+
): ProviderModelsDefinition => {
|
|
333
|
+
const options: ProviderModelOption[] = [];
|
|
334
|
+
const seenValues = new Set<string>();
|
|
335
|
+
|
|
336
|
+
for (const model of models) {
|
|
337
|
+
const mappedModel = mapOpenCodeVerboseModel(model);
|
|
338
|
+
if (!mappedModel || seenValues.has(mappedModel.value)) {
|
|
339
|
+
continue;
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
seenValues.add(mappedModel.value);
|
|
343
|
+
options.push(mappedModel);
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
if (options.length === 0) {
|
|
347
|
+
return OPENCODE_FALLBACK_MODELS;
|
|
348
|
+
}
|
|
179
349
|
|
|
180
350
|
const defaultValue = options.find((option) => option.value === OPENCODE_FALLBACK_MODELS.DEFAULT)?.value
|
|
181
351
|
?? options[0]?.value
|
|
@@ -214,7 +384,7 @@ const parseOpenCodeSessionModelValue = (rawModel: unknown): string | null => {
|
|
|
214
384
|
};
|
|
215
385
|
|
|
216
386
|
const runOpenCodeModelsCommand = (): Promise<string> => new Promise((resolve, reject) => {
|
|
217
|
-
const openCodeProcess = spawnFunction('opencode', ['models'], {
|
|
387
|
+
const openCodeProcess = spawnFunction('opencode', ['models', '--verbose'], {
|
|
218
388
|
cwd: process.cwd(),
|
|
219
389
|
env: { ...process.env },
|
|
220
390
|
});
|
|
@@ -273,6 +443,11 @@ export class OpenCodeProviderModels implements IProviderModels {
|
|
|
273
443
|
async getSupportedModels(): Promise<ProviderModelsDefinition> {
|
|
274
444
|
try {
|
|
275
445
|
const stdout = await runOpenCodeModelsCommand();
|
|
446
|
+
const verboseModels = parseOpenCodeVerboseModelsStdout(stdout);
|
|
447
|
+
if (verboseModels.length > 0) {
|
|
448
|
+
return buildOpenCodeDefinitionFromVerboseModels(verboseModels);
|
|
449
|
+
}
|
|
450
|
+
|
|
276
451
|
const ids = parseOpenCodeModelsStdout(stdout);
|
|
277
452
|
if (ids.length === 0) {
|
|
278
453
|
return OPENCODE_FALLBACK_MODELS;
|
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
normalizeSessionName,
|
|
12
12
|
readJsonRecord,
|
|
13
13
|
readOptionalString,
|
|
14
|
+
unwrapJsonStringLiteral,
|
|
14
15
|
} from '@/shared/utils.js';
|
|
15
16
|
|
|
16
17
|
type OpenCodeSessionRow = {
|
|
@@ -128,9 +129,26 @@ export class OpenCodeSessionSynchronizer implements IProviderSessionSynchronizer
|
|
|
128
129
|
const existingSession = sessionsDb.getSessionByProviderSessionId(sessionId)
|
|
129
130
|
?? sessionsDb.getSessionById(sessionId);
|
|
130
131
|
const existingName = existingSession?.custom_name;
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
132
|
+
|
|
133
|
+
// Sessions started by sending a message from cloudcli carry a distinct
|
|
134
|
+
// app-allocated session_id mapped to the provider id. For these we title the
|
|
135
|
+
// conversation from the first user message the user typed, matching how the
|
|
136
|
+
// app titles a brand-new conversation. Sessions discovered purely by
|
|
137
|
+
// indexing (session_id === provider_session_id) keep OpenCode's own stored
|
|
138
|
+
// title.
|
|
139
|
+
const isAppCreated =
|
|
140
|
+
existingSession != null &&
|
|
141
|
+
existingSession.provider_session_id != null &&
|
|
142
|
+
existingSession.session_id !== existingSession.provider_session_id;
|
|
143
|
+
|
|
144
|
+
let nextName: string | undefined;
|
|
145
|
+
if (existingName && existingName !== fallbackTitle) {
|
|
146
|
+
nextName = existingName;
|
|
147
|
+
} else if (isAppCreated) {
|
|
148
|
+
nextName = this.readFirstUserText(db, sessionId) ?? readOptionalString(row.title);
|
|
149
|
+
} else {
|
|
150
|
+
nextName = readOptionalString(row.title) ?? this.readFirstUserText(db, sessionId);
|
|
151
|
+
}
|
|
134
152
|
|
|
135
153
|
// OpenCode stores every session in one shared sqlite database, so jsonl_path
|
|
136
154
|
// must stay null to avoid deleting opencode.db when one app session is removed.
|
|
@@ -163,7 +181,10 @@ export class OpenCodeSessionSynchronizer implements IProviderSessionSynchronizer
|
|
|
163
181
|
`).get(sessionId) as { data: string | null } | undefined;
|
|
164
182
|
|
|
165
183
|
const data = readJsonRecord(row?.data);
|
|
166
|
-
|
|
184
|
+
const text = readOptionalString(data?.text);
|
|
185
|
+
// OpenCode persists the first prompt as a JSON string literal (e.g.
|
|
186
|
+
// `"hello"`), so decode it to avoid titling the session with quotes.
|
|
187
|
+
return text === undefined ? undefined : unwrapJsonStringLiteral(text);
|
|
167
188
|
} catch {
|
|
168
189
|
return undefined;
|
|
169
190
|
}
|
|
@@ -2,6 +2,7 @@ import fsSync from 'node:fs';
|
|
|
2
2
|
|
|
3
3
|
import Database from 'better-sqlite3';
|
|
4
4
|
|
|
5
|
+
import { parseImagesInputTag } from '@/shared/image-attachments.js';
|
|
5
6
|
import type { IProviderSessions } from '@/shared/interfaces.js';
|
|
6
7
|
import type { AnyRecord, FetchHistoryOptions, FetchHistoryResult, NormalizedMessage } from '@/shared/types.js';
|
|
7
8
|
import {
|
|
@@ -13,6 +14,7 @@ import {
|
|
|
13
14
|
readJsonRecord,
|
|
14
15
|
readOptionalString,
|
|
15
16
|
sliceTailPage,
|
|
17
|
+
unwrapJsonStringLiteral,
|
|
16
18
|
} from '@/shared/utils.js';
|
|
17
19
|
|
|
18
20
|
const PROVIDER = 'opencode';
|
|
@@ -59,25 +61,6 @@ const formatToolContent = (value: unknown): string => {
|
|
|
59
61
|
}
|
|
60
62
|
};
|
|
61
63
|
|
|
62
|
-
/**
|
|
63
|
-
* OpenCode can persist the first prompt as a JSON string literal inside a text
|
|
64
|
-
* part, for example `"hello"` instead of `hello`. Decode only complete JSON
|
|
65
|
-
* string literals so normal assistant/user prose remains untouched.
|
|
66
|
-
*/
|
|
67
|
-
const unwrapJsonStringLiteral = (value: string): string => {
|
|
68
|
-
const trimmed = value.trim();
|
|
69
|
-
if (!trimmed.startsWith('"') || !trimmed.endsWith('"')) {
|
|
70
|
-
return value;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
try {
|
|
74
|
-
const parsed = JSON.parse(trimmed);
|
|
75
|
-
return typeof parsed === 'string' ? parsed : value;
|
|
76
|
-
} catch {
|
|
77
|
-
return value;
|
|
78
|
-
}
|
|
79
|
-
};
|
|
80
|
-
|
|
81
64
|
const extractText = (value: unknown): string => {
|
|
82
65
|
if (typeof value === 'string') {
|
|
83
66
|
return unwrapJsonStringLiteral(value);
|
|
@@ -418,8 +401,13 @@ export class OpenCodeSessionsProvider implements IProviderSessions {
|
|
|
418
401
|
}
|
|
419
402
|
|
|
420
403
|
if (partType === 'text') {
|
|
421
|
-
const
|
|
422
|
-
|
|
404
|
+
const rawContent = extractText(partData);
|
|
405
|
+
// User prompts sent with attachments carry an <images_input> path
|
|
406
|
+
// list; strip it for display and surface the paths as images.
|
|
407
|
+
const { text: content, attachments } = messageRole === 'user'
|
|
408
|
+
? parseImagesInputTag(rawContent)
|
|
409
|
+
: { text: rawContent, attachments: [] };
|
|
410
|
+
if (content.trim() || attachments.length > 0) {
|
|
423
411
|
normalized.push(createNormalizedMessage({
|
|
424
412
|
id: baseId,
|
|
425
413
|
sessionId,
|
|
@@ -428,6 +416,7 @@ export class OpenCodeSessionsProvider implements IProviderSessions {
|
|
|
428
416
|
kind: 'text',
|
|
429
417
|
role: messageRole === 'user' ? 'user' : 'assistant',
|
|
430
418
|
content,
|
|
419
|
+
images: attachments.length > 0 ? attachments : undefined,
|
|
431
420
|
}));
|
|
432
421
|
}
|
|
433
422
|
continue;
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { ClaudeProvider } from '@/modules/providers/list/claude/claude.provider.js';
|
|
2
2
|
import { CodexProvider } from '@/modules/providers/list/codex/codex.provider.js';
|
|
3
3
|
import { CursorProvider } from '@/modules/providers/list/cursor/cursor.provider.js';
|
|
4
|
-
import { GeminiProvider } from '@/modules/providers/list/gemini/gemini.provider.js';
|
|
5
4
|
import { OpenCodeProvider } from '@/modules/providers/list/opencode/opencode.provider.js';
|
|
6
5
|
import type { IProvider } from '@/shared/interfaces.js';
|
|
7
6
|
import type { LLMProvider } from '@/shared/types.js';
|
|
@@ -11,7 +10,6 @@ const providers: Record<LLMProvider, IProvider> = {
|
|
|
11
10
|
claude: new ClaudeProvider(),
|
|
12
11
|
codex: new CodexProvider(),
|
|
13
12
|
cursor: new CursorProvider(),
|
|
14
|
-
gemini: new GeminiProvider(),
|
|
15
13
|
opencode: new OpenCodeProvider(),
|
|
16
14
|
};
|
|
17
15
|
|
|
@@ -21,6 +21,8 @@ type ProviderCapabilities = {
|
|
|
21
21
|
supportsPermissionRequests: boolean;
|
|
22
22
|
/** Whether the token-usage endpoint has data for this provider. */
|
|
23
23
|
supportsTokenUsage: boolean;
|
|
24
|
+
/** Whether the provider runtime can accept model-level reasoning effort. */
|
|
25
|
+
supportsEffort: boolean;
|
|
24
26
|
};
|
|
25
27
|
|
|
26
28
|
/**
|
|
@@ -38,42 +40,40 @@ const PROVIDER_CAPABILITIES: Record<LLMProvider, ProviderCapabilities> = {
|
|
|
38
40
|
supportsAbort: true,
|
|
39
41
|
supportsPermissionRequests: true,
|
|
40
42
|
supportsTokenUsage: true,
|
|
43
|
+
supportsEffort: true,
|
|
41
44
|
},
|
|
42
45
|
cursor: {
|
|
43
46
|
provider: 'cursor',
|
|
44
47
|
permissionModes: ['default', 'acceptEdits', 'bypassPermissions', 'plan'],
|
|
45
48
|
defaultPermissionMode: 'default',
|
|
46
|
-
supportsImages:
|
|
49
|
+
supportsImages: true,
|
|
47
50
|
supportsAbort: true,
|
|
48
51
|
supportsPermissionRequests: false,
|
|
49
52
|
supportsTokenUsage: false,
|
|
53
|
+
supportsEffort: false,
|
|
50
54
|
},
|
|
51
55
|
codex: {
|
|
52
56
|
provider: 'codex',
|
|
53
57
|
permissionModes: ['default', 'acceptEdits', 'bypassPermissions'],
|
|
54
58
|
defaultPermissionMode: 'default',
|
|
55
|
-
supportsImages:
|
|
56
|
-
supportsAbort: true,
|
|
57
|
-
supportsPermissionRequests: false,
|
|
58
|
-
supportsTokenUsage: true,
|
|
59
|
-
},
|
|
60
|
-
gemini: {
|
|
61
|
-
provider: 'gemini',
|
|
62
|
-
permissionModes: ['default', 'acceptEdits', 'bypassPermissions', 'plan'],
|
|
63
|
-
defaultPermissionMode: 'default',
|
|
64
|
-
supportsImages: false,
|
|
59
|
+
supportsImages: true,
|
|
65
60
|
supportsAbort: true,
|
|
66
61
|
supportsPermissionRequests: false,
|
|
67
62
|
supportsTokenUsage: true,
|
|
63
|
+
supportsEffort: true,
|
|
68
64
|
},
|
|
69
65
|
opencode: {
|
|
70
66
|
provider: 'opencode',
|
|
71
|
-
|
|
67
|
+
// Mapped by the runtime onto OpenCode's controls: `--agent plan` (plan),
|
|
68
|
+
// `--auto` (bypassPermissions) and the OPENCODE_PERMISSION env var
|
|
69
|
+
// (acceptEdits). See resolveOpenCodePermissionOptions in opencode-cli.js.
|
|
70
|
+
permissionModes: ['default', 'acceptEdits', 'bypassPermissions', 'plan'],
|
|
72
71
|
defaultPermissionMode: 'default',
|
|
73
|
-
supportsImages:
|
|
72
|
+
supportsImages: true,
|
|
74
73
|
supportsAbort: true,
|
|
75
74
|
supportsPermissionRequests: false,
|
|
76
75
|
supportsTokenUsage: true,
|
|
76
|
+
supportsEffort: true,
|
|
77
77
|
},
|
|
78
78
|
};
|
|
79
79
|
|
|
@@ -16,8 +16,8 @@ import type {
|
|
|
16
16
|
import { readProviderSessionActiveModelChange } from '@/shared/utils.js';
|
|
17
17
|
|
|
18
18
|
export const PROVIDER_MODELS_CACHE_TTL_MS = 3 * 24 * 60 * 60 * 1000;
|
|
19
|
-
const PROVIDER_MODELS_CACHE_VERSION =
|
|
20
|
-
const UNCACHED_PROVIDERS = new Set<LLMProvider>(['claude'
|
|
19
|
+
const PROVIDER_MODELS_CACHE_VERSION = 2;
|
|
20
|
+
const UNCACHED_PROVIDERS = new Set<LLMProvider>(['claude']);
|
|
21
21
|
|
|
22
22
|
type ProviderModelsServiceDependencies = {
|
|
23
23
|
resolveProvider?: (provider: LLMProvider) => Pick<IProvider, 'models'>;
|
|
@@ -8,7 +8,7 @@ import { rgPath } from '@vscode/ripgrep';
|
|
|
8
8
|
import { projectsDb, sessionsDb } from '@/modules/database/index.js';
|
|
9
9
|
|
|
10
10
|
type AnyRecord = Record<string, any>;
|
|
11
|
-
type SearchableProvider = 'claude' | 'codex'
|
|
11
|
+
type SearchableProvider = 'claude' | 'codex';
|
|
12
12
|
|
|
13
13
|
type SearchSnippetHighlight = {
|
|
14
14
|
start: number;
|
|
@@ -82,7 +82,7 @@ type ProjectBucket = {
|
|
|
82
82
|
sessions: SearchableSessionRow[];
|
|
83
83
|
};
|
|
84
84
|
|
|
85
|
-
const SUPPORTED_PROVIDERS = new Set<SearchableProvider>(['claude', 'codex'
|
|
85
|
+
const SUPPORTED_PROVIDERS = new Set<SearchableProvider>(['claude', 'codex']);
|
|
86
86
|
const MAX_MATCHES_PER_SESSION = 2;
|
|
87
87
|
const RIPGREP_FILE_CHUNK_SIZE = 40;
|
|
88
88
|
const RIPGREP_CHUNK_CONCURRENCY = 6;
|
|
@@ -455,21 +455,6 @@ function extractCodexText(content: unknown): string {
|
|
|
455
455
|
.join(' ');
|
|
456
456
|
}
|
|
457
457
|
|
|
458
|
-
function extractGeminiText(content: unknown): string {
|
|
459
|
-
if (typeof content === 'string') {
|
|
460
|
-
return content;
|
|
461
|
-
}
|
|
462
|
-
|
|
463
|
-
if (!Array.isArray(content)) {
|
|
464
|
-
return '';
|
|
465
|
-
}
|
|
466
|
-
|
|
467
|
-
return content
|
|
468
|
-
.filter((part: AnyRecord) => typeof part?.text === 'string')
|
|
469
|
-
.map((part: AnyRecord) => String(part.text))
|
|
470
|
-
.join(' ');
|
|
471
|
-
}
|
|
472
|
-
|
|
473
458
|
function normalizeSearchableSessions(rows: SessionRepositoryRow[]): SearchableSessionRow[] {
|
|
474
459
|
const normalizedRows: SearchableSessionRow[] = [];
|
|
475
460
|
const projectArchiveStateByPath = new Map<string, boolean>();
|
|
@@ -1065,81 +1050,6 @@ async function parseCodexSessionMatches(
|
|
|
1065
1050
|
};
|
|
1066
1051
|
}
|
|
1067
1052
|
|
|
1068
|
-
async function parseGeminiSessionMatches(
|
|
1069
|
-
session: SearchableSessionRow,
|
|
1070
|
-
runtime: SearchRuntime,
|
|
1071
|
-
): Promise<SessionConversationResult | null> {
|
|
1072
|
-
let data: string;
|
|
1073
|
-
try {
|
|
1074
|
-
data = await fs.readFile(session.jsonl_path, 'utf8');
|
|
1075
|
-
} catch {
|
|
1076
|
-
return null;
|
|
1077
|
-
}
|
|
1078
|
-
|
|
1079
|
-
let parsed: AnyRecord;
|
|
1080
|
-
try {
|
|
1081
|
-
parsed = JSON.parse(data) as AnyRecord;
|
|
1082
|
-
} catch {
|
|
1083
|
-
return null;
|
|
1084
|
-
}
|
|
1085
|
-
|
|
1086
|
-
const sourceMessages = Array.isArray(parsed.messages) ? parsed.messages as AnyRecord[] : [];
|
|
1087
|
-
if (sourceMessages.length === 0) {
|
|
1088
|
-
return null;
|
|
1089
|
-
}
|
|
1090
|
-
|
|
1091
|
-
const matches: SessionConversationMatch[] = [];
|
|
1092
|
-
let firstUserText: string | null = null;
|
|
1093
|
-
|
|
1094
|
-
for (const msg of sourceMessages) {
|
|
1095
|
-
if (runtime.totalMatches >= runtime.limit || runtime.isAborted()) {
|
|
1096
|
-
break;
|
|
1097
|
-
}
|
|
1098
|
-
|
|
1099
|
-
const role = msg.type === 'user'
|
|
1100
|
-
? 'user'
|
|
1101
|
-
: (msg.type === 'gemini' || msg.type === 'assistant')
|
|
1102
|
-
? 'assistant'
|
|
1103
|
-
: null;
|
|
1104
|
-
if (!role) {
|
|
1105
|
-
continue;
|
|
1106
|
-
}
|
|
1107
|
-
|
|
1108
|
-
const text = extractGeminiText(msg.content);
|
|
1109
|
-
if (!text) {
|
|
1110
|
-
continue;
|
|
1111
|
-
}
|
|
1112
|
-
|
|
1113
|
-
if (role === 'user' && !firstUserText) {
|
|
1114
|
-
firstUserText = text;
|
|
1115
|
-
}
|
|
1116
|
-
|
|
1117
|
-
if (!runtime.matchesQuery(text)) {
|
|
1118
|
-
continue;
|
|
1119
|
-
}
|
|
1120
|
-
|
|
1121
|
-
const { snippet, highlights } = runtime.buildSnippet(text);
|
|
1122
|
-
addSessionMatch(runtime, matches, {
|
|
1123
|
-
role,
|
|
1124
|
-
snippet,
|
|
1125
|
-
highlights,
|
|
1126
|
-
timestamp: msg.timestamp ? String(msg.timestamp) : null,
|
|
1127
|
-
provider: 'gemini',
|
|
1128
|
-
});
|
|
1129
|
-
}
|
|
1130
|
-
|
|
1131
|
-
if (matches.length === 0) {
|
|
1132
|
-
return null;
|
|
1133
|
-
}
|
|
1134
|
-
|
|
1135
|
-
return {
|
|
1136
|
-
sessionId: session.session_id,
|
|
1137
|
-
provider: 'gemini',
|
|
1138
|
-
sessionSummary: toSummaryText(session.custom_name, firstUserText, 'Gemini Session'),
|
|
1139
|
-
matches,
|
|
1140
|
-
};
|
|
1141
|
-
}
|
|
1142
|
-
|
|
1143
1053
|
async function parseSessionMatches(
|
|
1144
1054
|
session: SearchableSessionRow,
|
|
1145
1055
|
runtime: SearchRuntime,
|
|
@@ -1150,7 +1060,7 @@ async function parseSessionMatches(
|
|
|
1150
1060
|
if (session.provider === 'codex') {
|
|
1151
1061
|
return parseCodexSessionMatches(session, runtime);
|
|
1152
1062
|
}
|
|
1153
|
-
return
|
|
1063
|
+
return null;
|
|
1154
1064
|
}
|
|
1155
1065
|
|
|
1156
1066
|
export async function searchConversations(
|
|
@@ -25,16 +25,6 @@ const PROVIDER_WATCH_PATHS: Array<{ provider: LLMProvider; rootPath: string }> =
|
|
|
25
25
|
provider: 'codex',
|
|
26
26
|
rootPath: path.join(os.homedir(), '.codex', 'sessions'),
|
|
27
27
|
},
|
|
28
|
-
// {
|
|
29
|
-
// provider: 'gemini',
|
|
30
|
-
// rootPath: path.join(os.homedir(), '.gemini', 'sessions'),
|
|
31
|
-
// },
|
|
32
|
-
// Keep `sessions/` watcher disabled: Gemini also mirrors artifacts there,
|
|
33
|
-
// which causes duplicate synchronization events.
|
|
34
|
-
{
|
|
35
|
-
provider: 'gemini',
|
|
36
|
-
rootPath: path.join(os.homedir(), '.gemini', 'tmp'),
|
|
37
|
-
},
|
|
38
28
|
{
|
|
39
29
|
provider: 'opencode',
|
|
40
30
|
rootPath: path.join(os.homedir(), '.local', 'share', 'opencode'),
|
|
@@ -81,10 +71,6 @@ function isWatcherTargetFile(provider: LLMProvider, filePath: string): boolean {
|
|
|
81
71
|
return path.basename(filePath) === 'opencode.db';
|
|
82
72
|
}
|
|
83
73
|
|
|
84
|
-
if (provider === 'gemini') {
|
|
85
|
-
return filePath.endsWith('.json') || filePath.endsWith('.jsonl');
|
|
86
|
-
}
|
|
87
|
-
|
|
88
74
|
return filePath.endsWith('.jsonl');
|
|
89
75
|
}
|
|
90
76
|
|