@clinebot/core 0.0.36 → 0.0.37
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/dist/ClineCore.d.ts +312 -3
- package/dist/ClineCore.d.ts.map +1 -1
- package/dist/account/cline-account-service.d.ts.map +1 -1
- package/dist/cron/cron-event-ingress.d.ts +38 -0
- package/dist/cron/cron-event-ingress.d.ts.map +1 -0
- package/dist/cron/cron-materializer.d.ts +36 -0
- package/dist/cron/cron-materializer.d.ts.map +1 -0
- package/dist/cron/cron-reconciler.d.ts +62 -0
- package/dist/cron/cron-reconciler.d.ts.map +1 -0
- package/dist/cron/cron-report-writer.d.ts +41 -0
- package/dist/cron/cron-report-writer.d.ts.map +1 -0
- package/dist/cron/cron-runner.d.ts +43 -0
- package/dist/cron/cron-runner.d.ts.map +1 -0
- package/dist/cron/cron-schema.d.ts +3 -0
- package/dist/cron/cron-schema.d.ts.map +1 -0
- package/dist/cron/cron-service.d.ts +57 -0
- package/dist/cron/cron-service.d.ts.map +1 -0
- package/dist/cron/cron-spec-parser.d.ts +27 -0
- package/dist/cron/cron-spec-parser.d.ts.map +1 -0
- package/dist/cron/cron-watcher.d.ts +23 -0
- package/dist/cron/cron-watcher.d.ts.map +1 -0
- package/dist/cron/scheduler.d.ts +3 -1
- package/dist/cron/scheduler.d.ts.map +1 -1
- package/dist/cron/sqlite-cron-store.d.ts +230 -0
- package/dist/cron/sqlite-cron-store.d.ts.map +1 -0
- package/dist/extensions/plugin/plugin-config-loader.d.ts +7 -1
- package/dist/extensions/plugin/plugin-config-loader.d.ts.map +1 -1
- package/dist/extensions/plugin/plugin-loader.d.ts +10 -6
- package/dist/extensions/plugin/plugin-loader.d.ts.map +1 -1
- package/dist/extensions/plugin/plugin-sandbox.d.ts +7 -1
- package/dist/extensions/plugin/plugin-sandbox.d.ts.map +1 -1
- package/dist/extensions/plugin-sandbox-bootstrap.js +236 -275
- package/dist/extensions/tools/constants.d.ts +1 -0
- package/dist/extensions/tools/constants.d.ts.map +1 -1
- package/dist/extensions/tools/definitions.d.ts +2 -3
- package/dist/extensions/tools/definitions.d.ts.map +1 -1
- package/dist/extensions/tools/executors/editor.d.ts.map +1 -1
- package/dist/extensions/tools/helpers.d.ts +1 -0
- package/dist/extensions/tools/helpers.d.ts.map +1 -1
- package/dist/extensions/tools/index.d.ts +1 -2
- package/dist/extensions/tools/index.d.ts.map +1 -1
- package/dist/extensions/tools/presets.d.ts +1 -1
- package/dist/extensions/tools/schemas.d.ts +25 -3
- package/dist/extensions/tools/schemas.d.ts.map +1 -1
- package/dist/extensions/tools/team/delegated-agent.d.ts +2 -2
- package/dist/extensions/tools/team/delegated-agent.d.ts.map +1 -1
- package/dist/extensions/tools/team/multi-agent.d.ts +7 -3
- package/dist/extensions/tools/team/multi-agent.d.ts.map +1 -1
- package/dist/extensions/tools/team/team-tools.d.ts.map +1 -1
- package/dist/extensions/tools/types.d.ts +0 -5
- package/dist/extensions/tools/types.d.ts.map +1 -1
- package/dist/hooks/hook-bridge.d.ts +118 -0
- package/dist/hooks/hook-bridge.d.ts.map +1 -0
- package/dist/hooks/hook-file-hooks.d.ts +2 -1
- package/dist/hooks/hook-file-hooks.d.ts.map +1 -1
- package/dist/hooks/hook-registry.d.ts +16 -0
- package/dist/hooks/hook-registry.d.ts.map +1 -0
- package/dist/hub/browser-websocket.d.ts.map +1 -1
- package/dist/hub/client.d.ts +7 -1
- package/dist/hub/client.d.ts.map +1 -1
- package/dist/hub/daemon-entry.js +721 -461
- package/dist/hub/daemon.d.ts.map +1 -1
- package/dist/hub/defaults.d.ts +8 -4
- package/dist/hub/defaults.d.ts.map +1 -1
- package/dist/hub/index.js +665 -415
- package/dist/hub/runtime-handlers.d.ts.map +1 -1
- package/dist/hub/server.d.ts +18 -0
- package/dist/hub/server.d.ts.map +1 -1
- package/dist/hub/session-client.d.ts +3 -0
- package/dist/hub/session-client.d.ts.map +1 -1
- package/dist/hub/start-shared-server.d.ts.map +1 -1
- package/dist/hub/ui-client.d.ts +1 -0
- package/dist/hub/ui-client.d.ts.map +1 -1
- package/dist/index.d.ts +9 -7
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +756 -467
- package/dist/llms/cline-recommended-models.d.ts +20 -0
- package/dist/llms/cline-recommended-models.d.ts.map +1 -0
- package/dist/llms/handler-factory.d.ts +16 -0
- package/dist/llms/handler-factory.d.ts.map +1 -0
- package/dist/llms/provider-defaults.d.ts.map +1 -1
- package/dist/llms/provider-settings.d.ts +45 -2
- package/dist/llms/provider-settings.d.ts.map +1 -1
- package/dist/llms/runtime-registry.d.ts.map +1 -1
- package/dist/runtime/agent-config-adapter.d.ts +148 -0
- package/dist/runtime/agent-config-adapter.d.ts.map +1 -0
- package/dist/runtime/agent-runtime-config-builder.d.ts +96 -0
- package/dist/runtime/agent-runtime-config-builder.d.ts.map +1 -0
- package/dist/runtime/history.d.ts +6 -0
- package/dist/runtime/history.d.ts.map +1 -1
- package/dist/runtime/host.d.ts.map +1 -1
- package/dist/runtime/loop-detection.d.ts +59 -0
- package/dist/runtime/loop-detection.d.ts.map +1 -0
- package/dist/runtime/mistake-tracker.d.ts +69 -0
- package/dist/runtime/mistake-tracker.d.ts.map +1 -0
- package/dist/runtime/runtime-builder.d.ts.map +1 -1
- package/dist/runtime/runtime-event-adapter.d.ts +102 -0
- package/dist/runtime/runtime-event-adapter.d.ts.map +1 -0
- package/dist/runtime/runtime-host.d.ts +28 -3
- package/dist/runtime/runtime-host.d.ts.map +1 -1
- package/dist/runtime/session-runtime-orchestrator.d.ts +261 -0
- package/dist/runtime/session-runtime-orchestrator.d.ts.map +1 -0
- package/dist/runtime/session-runtime.d.ts +16 -3
- package/dist/runtime/session-runtime.d.ts.map +1 -1
- package/dist/runtime/user-input-builder.d.ts +24 -0
- package/dist/runtime/user-input-builder.d.ts.map +1 -0
- package/dist/services/index.js +28 -0
- package/dist/services/local-runtime-bootstrap.d.ts.map +1 -1
- package/dist/services/plugin-tools.d.ts.map +1 -1
- package/dist/services/providers/local-provider-registry.d.ts +197 -21
- package/dist/services/providers/local-provider-registry.d.ts.map +1 -1
- package/dist/services/providers/local-provider-service.d.ts +3 -1
- package/dist/services/providers/local-provider-service.d.ts.map +1 -1
- package/dist/services/session-data.d.ts.map +1 -1
- package/dist/services/session-telemetry.d.ts +7 -2
- package/dist/services/session-telemetry.d.ts.map +1 -1
- package/dist/services/storage/file-team-store.d.ts.map +1 -1
- package/dist/services/storage/provider-settings-legacy-migration.d.ts.map +1 -1
- package/dist/services/storage/provider-settings-manager.d.ts +1 -0
- package/dist/services/storage/provider-settings-manager.d.ts.map +1 -1
- package/dist/services/storage/sqlite-team-store.d.ts.map +1 -1
- package/dist/session/conversation-store.d.ts +30 -0
- package/dist/session/conversation-store.d.ts.map +1 -0
- package/dist/session/message-builder.d.ts +65 -0
- package/dist/session/message-builder.d.ts.map +1 -0
- package/dist/session/session-manifest.d.ts +1 -1
- package/dist/transports/hub.d.ts +14 -3
- package/dist/transports/hub.d.ts.map +1 -1
- package/dist/transports/local.d.ts +14 -4
- package/dist/transports/local.d.ts.map +1 -1
- package/dist/transports/remote.d.ts.map +1 -1
- package/dist/types/chat-schema.d.ts +5 -5
- package/dist/types/config.d.ts +9 -0
- package/dist/types/config.d.ts.map +1 -1
- package/dist/types/events.d.ts +7 -6
- package/dist/types/events.d.ts.map +1 -1
- package/dist/types/provider-settings.d.ts +2 -2
- package/dist/types/provider-settings.d.ts.map +1 -1
- package/dist/types/session.d.ts +5 -2
- package/dist/types/session.d.ts.map +1 -1
- package/dist/types.d.ts +4 -4
- package/dist/types.d.ts.map +1 -1
- package/package.json +4 -4
- package/src/ClineCore.ts +691 -6
- package/src/account/cline-account-service.ts +44 -6
- package/src/cron/cron-event-ingress.ts +357 -0
- package/src/cron/cron-materializer.ts +97 -0
- package/src/cron/cron-reconciler.ts +241 -0
- package/src/cron/cron-report-writer.ts +153 -0
- package/src/cron/cron-runner.ts +495 -0
- package/src/cron/cron-schema.ts +127 -0
- package/src/cron/cron-service.ts +163 -0
- package/src/cron/cron-spec-parser.ts +489 -0
- package/src/cron/cron-watcher.ts +102 -0
- package/src/cron/index.ts +10 -0
- package/src/cron/scheduler.ts +141 -6
- package/src/cron/sqlite-cron-store.ts +1286 -0
- package/src/extensions/plugin/plugin-config-loader.ts +21 -1
- package/src/extensions/plugin/plugin-loader.ts +25 -9
- package/src/extensions/plugin/plugin-sandbox-bootstrap.ts +151 -1
- package/src/extensions/plugin/plugin-sandbox.ts +131 -7
- package/src/extensions/tools/constants.ts +2 -0
- package/src/extensions/tools/definitions.ts +31 -22
- package/src/extensions/tools/executors/editor.ts +4 -3
- package/src/extensions/tools/helpers.ts +24 -0
- package/src/extensions/tools/index.ts +1 -2
- package/src/extensions/tools/presets.ts +1 -1
- package/src/extensions/tools/schemas.ts +13 -18
- package/src/extensions/tools/team/delegated-agent.ts +8 -3
- package/src/extensions/tools/team/multi-agent.ts +135 -19
- package/src/extensions/tools/team/team-tools.ts +151 -91
- package/src/extensions/tools/types.ts +0 -6
- package/src/hooks/hook-bridge.ts +489 -0
- package/src/hooks/hook-file-hooks.ts +58 -3
- package/src/hooks/hook-registry.ts +257 -0
- package/src/hub/browser-websocket.ts +26 -4
- package/src/hub/client.ts +72 -13
- package/src/hub/daemon-entry.ts +35 -0
- package/src/hub/daemon.ts +117 -14
- package/src/hub/defaults.ts +39 -12
- package/src/hub/runtime-handlers.ts +4 -3
- package/src/hub/server.ts +506 -77
- package/src/hub/session-client.ts +43 -1
- package/src/hub/start-shared-server.ts +3 -0
- package/src/hub/ui-client.ts +4 -0
- package/src/index.ts +46 -1
- package/src/llms/cline-recommended-models.ts +167 -0
- package/src/llms/handler-factory.ts +56 -0
- package/src/llms/provider-defaults.ts +17 -1
- package/src/llms/provider-settings.ts +48 -1
- package/src/llms/runtime-registry.ts +1 -0
- package/src/runtime/agent-config-adapter.ts +636 -0
- package/src/runtime/agent-runtime-config-builder.ts +205 -0
- package/src/runtime/error-feedback.ts +142 -0
- package/src/runtime/history.ts +137 -0
- package/src/runtime/host.ts +22 -0
- package/src/runtime/loop-detection.ts +162 -0
- package/src/runtime/mistake-tracker.ts +221 -0
- package/src/runtime/runtime-builder.ts +61 -5
- package/src/runtime/runtime-event-adapter.ts +412 -0
- package/src/runtime/runtime-host.ts +45 -1
- package/src/runtime/session-runtime-orchestrator.ts +1253 -0
- package/src/runtime/session-runtime.ts +16 -2
- package/src/runtime/user-input-builder.ts +167 -0
- package/src/services/local-runtime-bootstrap.ts +128 -22
- package/src/services/plugin-tools.ts +1 -0
- package/src/services/providers/local-provider-registry.ts +273 -57
- package/src/services/providers/local-provider-service.ts +67 -7
- package/src/services/session-data.ts +16 -14
- package/src/services/session-telemetry.ts +6 -15
- package/src/services/storage/file-team-store.ts +1 -5
- package/src/services/storage/provider-settings-legacy-migration.ts +8 -47
- package/src/services/storage/provider-settings-manager.ts +16 -1
- package/src/services/storage/sqlite-team-store.ts +1 -5
- package/src/session/conversation-store.ts +77 -0
- package/src/session/message-builder.ts +941 -0
- package/src/transports/hub.ts +458 -33
- package/src/transports/local.ts +296 -65
- package/src/transports/remote.ts +1 -0
- package/src/types/config.ts +9 -0
- package/src/types/events.ts +8 -6
- package/src/types/index.ts +3 -0
- package/src/types/provider-settings.ts +8 -1
- package/src/types/session.ts +5 -2
- package/src/types.ts +15 -1
- package/dist/cron/index.d.ts +0 -6
- package/dist/cron/index.d.ts.map +0 -1
- package/dist/services/telemetry/index.js +0 -28
|
@@ -2,34 +2,70 @@ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
|
2
2
|
import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|
3
3
|
import { dirname, join } from "node:path";
|
|
4
4
|
import * as LlmsModels from "@clinebot/llms";
|
|
5
|
-
import
|
|
5
|
+
import {
|
|
6
|
+
type ModelCapability,
|
|
7
|
+
ModelCapabilitySchema,
|
|
8
|
+
type ModelInfo,
|
|
9
|
+
type ProviderCapability,
|
|
10
|
+
ProviderCapabilitySchema,
|
|
11
|
+
type ProviderClient,
|
|
12
|
+
ProviderClientSchema,
|
|
13
|
+
type ProviderModel,
|
|
14
|
+
type ProviderProtocol,
|
|
15
|
+
ProviderProtocolSchema,
|
|
16
|
+
} from "@clinebot/shared";
|
|
17
|
+
import { z } from "zod";
|
|
18
|
+
import type {
|
|
19
|
+
ProviderSettings,
|
|
20
|
+
StoredProviderSettings,
|
|
21
|
+
} from "../../types/provider-settings";
|
|
6
22
|
import type { ProviderSettingsManager } from "../storage/provider-settings-manager";
|
|
7
23
|
|
|
8
|
-
export
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
string,
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
24
|
+
export const StoredModelEntrySchema = z
|
|
25
|
+
.object({
|
|
26
|
+
id: z.string().optional(),
|
|
27
|
+
name: z.string().optional(),
|
|
28
|
+
capabilities: z.array(ModelCapabilitySchema).optional(),
|
|
29
|
+
supportsVision: z.boolean().optional(),
|
|
30
|
+
supportsAttachments: z.boolean().optional(),
|
|
31
|
+
supportsReasoning: z.boolean().optional(),
|
|
32
|
+
})
|
|
33
|
+
.passthrough();
|
|
34
|
+
|
|
35
|
+
export type StoredModelEntry = z.infer<typeof StoredModelEntrySchema>;
|
|
36
|
+
|
|
37
|
+
export const StoredProviderMetadataSchema = z
|
|
38
|
+
.object({
|
|
39
|
+
name: z.string(),
|
|
40
|
+
baseUrl: z.string(),
|
|
41
|
+
defaultModelId: z.string().optional(),
|
|
42
|
+
protocol: ProviderProtocolSchema.optional(),
|
|
43
|
+
client: ProviderClientSchema.optional(),
|
|
44
|
+
capabilities: z.array(ProviderCapabilitySchema).optional(),
|
|
45
|
+
modelsSourceUrl: z.string().optional(),
|
|
46
|
+
})
|
|
47
|
+
.passthrough();
|
|
48
|
+
|
|
49
|
+
export const StoredProviderEntrySchema = z
|
|
50
|
+
.object({
|
|
51
|
+
provider: StoredProviderMetadataSchema.optional(),
|
|
52
|
+
models: z.record(z.string(), StoredModelEntrySchema).optional(),
|
|
53
|
+
})
|
|
54
|
+
.passthrough();
|
|
55
|
+
|
|
56
|
+
export type StoredProviderEntry = z.infer<typeof StoredProviderEntrySchema>;
|
|
57
|
+
|
|
58
|
+
export const StoredModelsFileSchema = z.object({
|
|
59
|
+
version: z.literal(1),
|
|
60
|
+
providers: z.record(z.string(), StoredProviderEntrySchema),
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
export type StoredModelsFile = z.infer<typeof StoredModelsFileSchema>;
|
|
64
|
+
|
|
65
|
+
const StoredModelsFileEnvelopeSchema = z.object({
|
|
66
|
+
version: z.literal(1),
|
|
67
|
+
providers: z.record(z.string(), z.unknown()),
|
|
68
|
+
});
|
|
33
69
|
|
|
34
70
|
const LOADED_MODELS_REGISTRY_PATHS = new Set<string>();
|
|
35
71
|
|
|
@@ -51,21 +87,29 @@ export function emptyModelsFile(): StoredModelsFile {
|
|
|
51
87
|
return { version: 1, providers: {} };
|
|
52
88
|
}
|
|
53
89
|
|
|
90
|
+
export function parseModelsFile(input: unknown): StoredModelsFile {
|
|
91
|
+
const result = StoredModelsFileEnvelopeSchema.safeParse(input);
|
|
92
|
+
if (!result.success) {
|
|
93
|
+
return emptyModelsFile();
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
const providers: StoredModelsFile["providers"] = {};
|
|
97
|
+
for (const [providerId, entry] of Object.entries(result.data.providers)) {
|
|
98
|
+
const provider = StoredProviderEntrySchema.safeParse(entry);
|
|
99
|
+
if (provider.success) {
|
|
100
|
+
providers[providerId] = provider.data;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
return { version: 1, providers };
|
|
104
|
+
}
|
|
105
|
+
|
|
54
106
|
export function readModelsFileSync(filePath: string): StoredModelsFile {
|
|
55
107
|
if (!existsSync(filePath)) {
|
|
56
108
|
return emptyModelsFile();
|
|
57
109
|
}
|
|
58
110
|
try {
|
|
59
111
|
const raw = readFileSync(filePath, "utf8");
|
|
60
|
-
|
|
61
|
-
if (
|
|
62
|
-
parsed &&
|
|
63
|
-
parsed.version === 1 &&
|
|
64
|
-
parsed.providers &&
|
|
65
|
-
typeof parsed.providers === "object"
|
|
66
|
-
) {
|
|
67
|
-
return { version: 1, providers: parsed.providers };
|
|
68
|
-
}
|
|
112
|
+
return parseModelsFile(JSON.parse(raw) as unknown);
|
|
69
113
|
} catch {
|
|
70
114
|
// Invalid or missing files fall back to an empty registry.
|
|
71
115
|
}
|
|
@@ -77,15 +121,7 @@ export async function readModelsFile(
|
|
|
77
121
|
): Promise<StoredModelsFile> {
|
|
78
122
|
try {
|
|
79
123
|
const raw = await readFile(filePath, "utf8");
|
|
80
|
-
|
|
81
|
-
if (
|
|
82
|
-
parsed &&
|
|
83
|
-
parsed.version === 1 &&
|
|
84
|
-
parsed.providers &&
|
|
85
|
-
typeof parsed.providers === "object"
|
|
86
|
-
) {
|
|
87
|
-
return { version: 1, providers: parsed.providers };
|
|
88
|
-
}
|
|
124
|
+
return parseModelsFile(JSON.parse(raw) as unknown);
|
|
89
125
|
} catch {
|
|
90
126
|
// Invalid or missing files fall back to an empty registry.
|
|
91
127
|
}
|
|
@@ -97,7 +133,8 @@ export function writeModelsFileSync(
|
|
|
97
133
|
state: StoredModelsFile,
|
|
98
134
|
): void {
|
|
99
135
|
mkdirSync(dirname(filePath), { recursive: true });
|
|
100
|
-
|
|
136
|
+
const parsed = StoredModelsFileSchema.parse(state);
|
|
137
|
+
writeFileSync(filePath, `${JSON.stringify(parsed, null, 2)}\n`, "utf8");
|
|
101
138
|
}
|
|
102
139
|
|
|
103
140
|
export async function writeModelsFile(
|
|
@@ -105,7 +142,8 @@ export async function writeModelsFile(
|
|
|
105
142
|
state: StoredModelsFile,
|
|
106
143
|
): Promise<void> {
|
|
107
144
|
await mkdir(dirname(filePath), { recursive: true });
|
|
108
|
-
|
|
145
|
+
const parsed = StoredModelsFileSchema.parse(state);
|
|
146
|
+
await writeFile(filePath, `${JSON.stringify(parsed, null, 2)}\n`, "utf8");
|
|
109
147
|
}
|
|
110
148
|
|
|
111
149
|
export function toProviderModel(
|
|
@@ -167,6 +205,168 @@ function toModelCapabilities(
|
|
|
167
205
|
return [...next];
|
|
168
206
|
}
|
|
169
207
|
|
|
208
|
+
function isCompleteProviderMetadata(
|
|
209
|
+
provider: StoredProviderEntry["provider"],
|
|
210
|
+
): provider is NonNullable<StoredProviderEntry["provider"]> {
|
|
211
|
+
return (
|
|
212
|
+
provider != null &&
|
|
213
|
+
typeof provider.name === "string" &&
|
|
214
|
+
typeof provider.baseUrl === "string"
|
|
215
|
+
);
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
function resolveProviderProtocol(
|
|
219
|
+
protocol: ProviderProtocol | undefined,
|
|
220
|
+
fallback: ProviderProtocol | undefined,
|
|
221
|
+
): ProviderProtocol {
|
|
222
|
+
return protocol ?? fallback ?? "openai-chat";
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
function resolveProviderClient(
|
|
226
|
+
client: ProviderClient | undefined,
|
|
227
|
+
protocol: ProviderProtocol,
|
|
228
|
+
fallback: ProviderClient | undefined,
|
|
229
|
+
): ProviderClient {
|
|
230
|
+
return (
|
|
231
|
+
client ??
|
|
232
|
+
fallback ??
|
|
233
|
+
(protocol === "openai-responses" ? "openai" : "openai-compatible")
|
|
234
|
+
);
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
function toStoredModelInfo(
|
|
238
|
+
modelId: string,
|
|
239
|
+
model: StoredModelEntry | undefined,
|
|
240
|
+
): ModelInfo {
|
|
241
|
+
const capabilities = new Set<ModelCapability>(model?.capabilities ?? []);
|
|
242
|
+
if (model?.supportsVision) capabilities.add("images");
|
|
243
|
+
if (model?.supportsAttachments) capabilities.add("files");
|
|
244
|
+
if (model?.supportsReasoning) capabilities.add("reasoning");
|
|
245
|
+
|
|
246
|
+
return {
|
|
247
|
+
id: modelId,
|
|
248
|
+
name: model?.name ?? modelId,
|
|
249
|
+
capabilities: capabilities.size > 0 ? [...capabilities] : undefined,
|
|
250
|
+
};
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
function registerCustomModels(
|
|
254
|
+
providerId: string,
|
|
255
|
+
models: StoredProviderEntry["models"] | undefined,
|
|
256
|
+
): void {
|
|
257
|
+
for (const [modelKey, model] of Object.entries(models ?? {})) {
|
|
258
|
+
const modelId = model.id?.trim() || modelKey.trim();
|
|
259
|
+
if (!modelId) {
|
|
260
|
+
continue;
|
|
261
|
+
}
|
|
262
|
+
LlmsModels.registerModel(
|
|
263
|
+
providerId,
|
|
264
|
+
modelId,
|
|
265
|
+
toStoredModelInfo(modelId, model),
|
|
266
|
+
);
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
function modelInfoWithDefaults(
|
|
271
|
+
modelId: string,
|
|
272
|
+
info: ModelInfo | undefined,
|
|
273
|
+
capabilities: ModelInfo["capabilities"] | undefined,
|
|
274
|
+
): ModelInfo {
|
|
275
|
+
return {
|
|
276
|
+
...(info ?? {}),
|
|
277
|
+
id: modelId,
|
|
278
|
+
name: info?.name ?? modelId,
|
|
279
|
+
capabilities: info?.capabilities ?? capabilities,
|
|
280
|
+
};
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
function getGeneratedModelsForProvider(
|
|
284
|
+
providerId: string,
|
|
285
|
+
): Record<string, ModelInfo> {
|
|
286
|
+
const generated = Object.assign(
|
|
287
|
+
{},
|
|
288
|
+
...LlmsModels.resolveProviderModelCatalogKeys(providerId).map(
|
|
289
|
+
(catalogKey) => LlmsModels.getGeneratedModelsForProvider(catalogKey),
|
|
290
|
+
),
|
|
291
|
+
);
|
|
292
|
+
return generated as Record<string, ModelInfo>;
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
export function registerProviderSettingsProvider(
|
|
296
|
+
settings: ProviderSettings,
|
|
297
|
+
): void {
|
|
298
|
+
const providerId = settings.provider.trim();
|
|
299
|
+
if (!providerId || LlmsModels.isBuiltInProviderId(providerId)) {
|
|
300
|
+
return;
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
const baseUrl = settings.baseUrl?.trim();
|
|
304
|
+
if (!baseUrl) {
|
|
305
|
+
return;
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
const existingCollection = LlmsModels.MODEL_COLLECTIONS_BY_PROVIDER_ID[
|
|
309
|
+
providerId
|
|
310
|
+
] as LlmsModels.ModelCollection | undefined;
|
|
311
|
+
const generatedModels = getGeneratedModelsForProvider(providerId);
|
|
312
|
+
const modelCapabilities = toModelCapabilities(settings.capabilities);
|
|
313
|
+
const fallbackCapabilities =
|
|
314
|
+
modelCapabilities.length > 0 ? modelCapabilities : undefined;
|
|
315
|
+
const modelId = settings.model?.trim();
|
|
316
|
+
const models: Record<string, ModelInfo> = {
|
|
317
|
+
...generatedModels,
|
|
318
|
+
...(existingCollection?.models ?? {}),
|
|
319
|
+
};
|
|
320
|
+
|
|
321
|
+
if (modelId) {
|
|
322
|
+
models[modelId] = modelInfoWithDefaults(
|
|
323
|
+
modelId,
|
|
324
|
+
models[modelId],
|
|
325
|
+
fallbackCapabilities,
|
|
326
|
+
);
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
const modelIds = Object.keys(models).filter(Boolean);
|
|
330
|
+
const defaultModelId = modelId || modelIds[0];
|
|
331
|
+
if (!defaultModelId) {
|
|
332
|
+
return;
|
|
333
|
+
}
|
|
334
|
+
const protocol = resolveProviderProtocol(
|
|
335
|
+
settings.protocol,
|
|
336
|
+
existingCollection?.provider.protocol,
|
|
337
|
+
);
|
|
338
|
+
const client = resolveProviderClient(
|
|
339
|
+
settings.client,
|
|
340
|
+
protocol,
|
|
341
|
+
existingCollection?.provider.client,
|
|
342
|
+
);
|
|
343
|
+
|
|
344
|
+
LlmsModels.registerProvider({
|
|
345
|
+
provider: {
|
|
346
|
+
id: providerId,
|
|
347
|
+
name: existingCollection?.provider.name ?? titleCaseFromId(providerId),
|
|
348
|
+
description: existingCollection?.provider.description,
|
|
349
|
+
protocol,
|
|
350
|
+
client,
|
|
351
|
+
baseUrl,
|
|
352
|
+
defaultModelId,
|
|
353
|
+
capabilities:
|
|
354
|
+
toProviderCapabilities(settings.capabilities) ??
|
|
355
|
+
existingCollection?.provider.capabilities,
|
|
356
|
+
source: "file",
|
|
357
|
+
},
|
|
358
|
+
models,
|
|
359
|
+
});
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
export function registerConfiguredProvidersFromSettings(
|
|
363
|
+
state: StoredProviderSettings,
|
|
364
|
+
): void {
|
|
365
|
+
for (const entry of Object.values(state.providers)) {
|
|
366
|
+
registerProviderSettingsProvider(entry.settings);
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
|
|
170
370
|
/**
|
|
171
371
|
* Custom Provider Registry
|
|
172
372
|
*
|
|
@@ -176,20 +376,35 @@ function toModelCapabilities(
|
|
|
176
376
|
*/
|
|
177
377
|
export function registerCustomProvider(
|
|
178
378
|
providerId: string,
|
|
179
|
-
entry:
|
|
379
|
+
entry: StoredProviderEntry,
|
|
180
380
|
): void {
|
|
381
|
+
const storedModels = entry.models ?? {};
|
|
382
|
+
if (!isCompleteProviderMetadata(entry.provider)) {
|
|
383
|
+
registerCustomModels(providerId, storedModels);
|
|
384
|
+
return;
|
|
385
|
+
}
|
|
386
|
+
|
|
181
387
|
const modelCapabilities = toModelCapabilities(entry.provider.capabilities);
|
|
182
|
-
const modelEntries = Object.
|
|
183
|
-
.map((model) =>
|
|
184
|
-
|
|
388
|
+
const modelEntries = Object.entries(storedModels)
|
|
389
|
+
.map(([modelKey, model]) => ({
|
|
390
|
+
id: model.id?.trim() || modelKey.trim(),
|
|
391
|
+
model,
|
|
392
|
+
}))
|
|
393
|
+
.filter(({ id }) => id.length > 0);
|
|
185
394
|
const defaultModelId =
|
|
186
|
-
entry.provider.defaultModelId?.trim() || modelEntries[0] || "default";
|
|
395
|
+
entry.provider.defaultModelId?.trim() || modelEntries[0]?.id || "default";
|
|
396
|
+
const protocol = resolveProviderProtocol(entry.provider.protocol, undefined);
|
|
397
|
+
const client = resolveProviderClient(
|
|
398
|
+
entry.provider.client,
|
|
399
|
+
protocol,
|
|
400
|
+
undefined,
|
|
401
|
+
);
|
|
187
402
|
const normalizedModels = Object.fromEntries(
|
|
188
|
-
modelEntries.map((
|
|
189
|
-
|
|
403
|
+
modelEntries.map(({ id, model }) => [
|
|
404
|
+
id,
|
|
190
405
|
{
|
|
191
|
-
id
|
|
192
|
-
name:
|
|
406
|
+
id,
|
|
407
|
+
name: model.name ?? id,
|
|
193
408
|
capabilities:
|
|
194
409
|
modelCapabilities.length > 0 ? modelCapabilities : undefined,
|
|
195
410
|
status: "active" as const,
|
|
@@ -201,11 +416,12 @@ export function registerCustomProvider(
|
|
|
201
416
|
provider: {
|
|
202
417
|
id: providerId,
|
|
203
418
|
name: entry.provider.name.trim() || titleCaseFromId(providerId),
|
|
204
|
-
protocol
|
|
205
|
-
client
|
|
419
|
+
protocol,
|
|
420
|
+
client,
|
|
206
421
|
baseUrl: entry.provider.baseUrl,
|
|
207
422
|
defaultModelId,
|
|
208
423
|
capabilities: toProviderCapabilities(entry.provider.capabilities),
|
|
424
|
+
source: "file",
|
|
209
425
|
},
|
|
210
426
|
models: normalizedModels,
|
|
211
427
|
});
|
|
@@ -14,7 +14,9 @@ import { loginOcaOAuth } from "../../auth/oca";
|
|
|
14
14
|
import { resolveProviderConfig } from "../../llms/provider-defaults";
|
|
15
15
|
import type {
|
|
16
16
|
ModelInfo,
|
|
17
|
+
ProviderClient,
|
|
17
18
|
ProviderConfig,
|
|
19
|
+
ProviderProtocol,
|
|
18
20
|
ProviderSettings,
|
|
19
21
|
} from "../../llms/provider-settings";
|
|
20
22
|
import type { ProviderSettingsManager } from "../storage/provider-settings-manager";
|
|
@@ -38,6 +40,8 @@ export interface UpdateLocalProviderRequest {
|
|
|
38
40
|
models?: string[];
|
|
39
41
|
defaultModelId?: string | null;
|
|
40
42
|
modelsSourceUrl?: string | null;
|
|
43
|
+
protocol?: ProviderProtocol | null;
|
|
44
|
+
client?: ProviderClient | null;
|
|
41
45
|
capabilities?: ProviderCapability[] | null;
|
|
42
46
|
}
|
|
43
47
|
|
|
@@ -256,6 +260,7 @@ function removeProviderFromSettingsState(
|
|
|
256
260
|
mutated = true;
|
|
257
261
|
}
|
|
258
262
|
if (mutated) manager.write(state);
|
|
263
|
+
LlmsModels.unregisterProvider(providerId);
|
|
259
264
|
}
|
|
260
265
|
|
|
261
266
|
// --- Public API ---
|
|
@@ -338,6 +343,8 @@ export async function addLocalProvider(
|
|
|
338
343
|
headers: normalizedHeaders,
|
|
339
344
|
timeout: request.timeoutMs,
|
|
340
345
|
model: defaultModelId,
|
|
346
|
+
protocol: request.protocol,
|
|
347
|
+
client: request.client,
|
|
341
348
|
},
|
|
342
349
|
{ setLastUsed: false },
|
|
343
350
|
);
|
|
@@ -350,6 +357,8 @@ export async function addLocalProvider(
|
|
|
350
357
|
name: providerName,
|
|
351
358
|
baseUrl,
|
|
352
359
|
defaultModelId,
|
|
360
|
+
protocol: request.protocol,
|
|
361
|
+
client: request.client,
|
|
353
362
|
capabilities,
|
|
354
363
|
modelsSourceUrl: sourceUrl,
|
|
355
364
|
},
|
|
@@ -380,11 +389,40 @@ export async function updateLocalProvider(
|
|
|
380
389
|
|
|
381
390
|
const modelsPath = resolveModelsRegistryPath(manager);
|
|
382
391
|
const modelsState = await readModelsFile(modelsPath);
|
|
383
|
-
|
|
392
|
+
let existingEntry = modelsState.providers[providerId];
|
|
384
393
|
if (!existingEntry) {
|
|
385
|
-
|
|
386
|
-
|
|
394
|
+
const existingSettings = manager.getProviderSettings(providerId);
|
|
395
|
+
if (!existingSettings) {
|
|
396
|
+
throw new Error(`provider "${providerId}" does not exist`);
|
|
397
|
+
}
|
|
387
398
|
|
|
399
|
+
const seedModelId =
|
|
400
|
+
uniqueTrimmed(request.models)[0] ?? existingSettings.model?.trim();
|
|
401
|
+
if (!seedModelId) {
|
|
402
|
+
throw new Error(
|
|
403
|
+
`provider "${providerId}" cannot be updated because no model is configured`,
|
|
404
|
+
);
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
// Ephemeral seed for the existing update path; final state is computed and written below.
|
|
408
|
+
existingEntry = {
|
|
409
|
+
provider: {
|
|
410
|
+
name: request.name?.trim() || titleCaseFromId(providerId),
|
|
411
|
+
baseUrl:
|
|
412
|
+
request.baseUrl?.trim() ?? existingSettings.baseUrl?.trim() ?? "",
|
|
413
|
+
defaultModelId: seedModelId,
|
|
414
|
+
protocol: existingSettings.protocol,
|
|
415
|
+
client: existingSettings.client,
|
|
416
|
+
capabilities: existingSettings.capabilities,
|
|
417
|
+
},
|
|
418
|
+
models: buildProviderModels([seedModelId], existingSettings.capabilities),
|
|
419
|
+
};
|
|
420
|
+
}
|
|
421
|
+
if (!existingEntry.provider) {
|
|
422
|
+
throw new Error(
|
|
423
|
+
`provider "${providerId}" cannot be updated because it is a model overlay (no provider metadata)`,
|
|
424
|
+
);
|
|
425
|
+
}
|
|
388
426
|
const providerName =
|
|
389
427
|
request.name?.trim() ?? existingEntry.provider.name.trim();
|
|
390
428
|
if (!providerName) throw new Error("name is required");
|
|
@@ -399,6 +437,14 @@ export async function updateLocalProvider(
|
|
|
399
437
|
: request.capabilities === null
|
|
400
438
|
? undefined
|
|
401
439
|
: [...new Set(request.capabilities)];
|
|
440
|
+
const protocol =
|
|
441
|
+
request.protocol === undefined
|
|
442
|
+
? existingEntry.provider.protocol
|
|
443
|
+
: (request.protocol ?? undefined);
|
|
444
|
+
const client =
|
|
445
|
+
request.client === undefined
|
|
446
|
+
? existingEntry.provider.client
|
|
447
|
+
: (request.client ?? undefined);
|
|
402
448
|
|
|
403
449
|
const explicitModels = uniqueTrimmed(request.models);
|
|
404
450
|
const nextModelsSourceUrl =
|
|
@@ -408,7 +454,7 @@ export async function updateLocalProvider(
|
|
|
408
454
|
const shouldRecomputeModels =
|
|
409
455
|
request.models !== undefined ||
|
|
410
456
|
(request.modelsSourceUrl !== undefined && !!nextModelsSourceUrl);
|
|
411
|
-
const existingModelIds = Object.keys(existingEntry.models)
|
|
457
|
+
const existingModelIds = Object.keys(existingEntry.models ?? {})
|
|
412
458
|
.map((id) => id.trim())
|
|
413
459
|
.filter(Boolean);
|
|
414
460
|
const modelIds = await resolveModelIds({
|
|
@@ -440,6 +486,10 @@ export async function updateLocalProvider(
|
|
|
440
486
|
baseUrl,
|
|
441
487
|
model: defaultModelId,
|
|
442
488
|
};
|
|
489
|
+
if (protocol) nextSettings.protocol = protocol;
|
|
490
|
+
else delete nextSettings.protocol;
|
|
491
|
+
if (client) nextSettings.client = client;
|
|
492
|
+
else delete nextSettings.client;
|
|
443
493
|
if (request.apiKey !== undefined) {
|
|
444
494
|
const apiKey = request.apiKey?.trim() ?? "";
|
|
445
495
|
if (apiKey) nextSettings.apiKey = apiKey;
|
|
@@ -465,6 +515,8 @@ export async function updateLocalProvider(
|
|
|
465
515
|
name: providerName,
|
|
466
516
|
baseUrl,
|
|
467
517
|
defaultModelId,
|
|
518
|
+
protocol,
|
|
519
|
+
client,
|
|
468
520
|
capabilities,
|
|
469
521
|
modelsSourceUrl: nextModelsSourceUrl,
|
|
470
522
|
},
|
|
@@ -541,6 +593,8 @@ export async function listLocalProviders(
|
|
|
541
593
|
: undefined,
|
|
542
594
|
baseUrl: persistedSettings?.baseUrl ?? info?.baseUrl,
|
|
543
595
|
defaultModelId: info?.defaultModelId,
|
|
596
|
+
protocol: persistedSettings?.protocol ?? info?.protocol,
|
|
597
|
+
client: persistedSettings?.client ?? info?.client,
|
|
544
598
|
authDescription: "This provider uses API keys for authentication.",
|
|
545
599
|
baseUrlDescription: "The base endpoint to use for provider requests.",
|
|
546
600
|
modelList,
|
|
@@ -596,6 +650,9 @@ export function saveLocalProviderSettings(
|
|
|
596
650
|
"contextWindow",
|
|
597
651
|
"timeout",
|
|
598
652
|
"apiLine",
|
|
653
|
+
"protocol",
|
|
654
|
+
"client",
|
|
655
|
+
"routingProviderId",
|
|
599
656
|
"capabilities",
|
|
600
657
|
] as const) {
|
|
601
658
|
if (Object.hasOwn(request, key)) next[key] = request[key];
|
|
@@ -640,9 +697,12 @@ function toProviderApiKey(
|
|
|
640
697
|
providerId: OAuthProviderId,
|
|
641
698
|
credentials: { access: string },
|
|
642
699
|
): string {
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
700
|
+
if (providerId === "cline") {
|
|
701
|
+
return credentials.access.startsWith("workos:")
|
|
702
|
+
? credentials.access
|
|
703
|
+
: `workos:${credentials.access}`;
|
|
704
|
+
}
|
|
705
|
+
return credentials.access;
|
|
646
706
|
}
|
|
647
707
|
|
|
648
708
|
export async function loginLocalProvider(
|
|
@@ -153,22 +153,24 @@ export function withLatestAssistantTurnMetadata(
|
|
|
153
153
|
assistantIndexes.push(next.length - 1 - lastAssistantIndex);
|
|
154
154
|
}
|
|
155
155
|
|
|
156
|
-
const
|
|
157
|
-
const lastAssistantIndexForUsage =
|
|
158
|
-
assistantIndexes[assistantIndexes.length - 1];
|
|
156
|
+
const lastAssistantIndex = assistantIndexes[assistantIndexes.length - 1];
|
|
159
157
|
for (const targetIndex of assistantIndexes) {
|
|
160
158
|
const target = next[targetIndex];
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
:
|
|
159
|
+
// Use per-turn metrics already stamped on the message if available.
|
|
160
|
+
// Only fall back to result.usage (total run usage) for the terminal
|
|
161
|
+
// assistant message when no per-turn metrics are present, to avoid
|
|
162
|
+
// attaching session totals to intermediate turn messages.
|
|
163
|
+
let metrics = target.metrics;
|
|
164
|
+
if (!metrics && targetIndex === lastAssistantIndex) {
|
|
165
|
+
const usage = result.usage;
|
|
166
|
+
metrics = {
|
|
167
|
+
inputTokens: usage.inputTokens,
|
|
168
|
+
outputTokens: usage.outputTokens,
|
|
169
|
+
cacheReadTokens: usage.cacheReadTokens ?? 0,
|
|
170
|
+
cacheWriteTokens: usage.cacheWriteTokens ?? 0,
|
|
171
|
+
cost: usage.totalCost,
|
|
172
|
+
};
|
|
173
|
+
}
|
|
172
174
|
next[targetIndex] = {
|
|
173
175
|
...normalizeStoredMessageModelMetadata(target, {
|
|
174
176
|
id: result.model.id,
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import type { ITelemetryService } from "@clinebot/shared";
|
|
2
2
|
import { resolveDocumentsExtensionPath } from "@clinebot/shared/storage";
|
|
3
3
|
import { listHookConfigFiles } from "../extensions/config/hooks-config-loader";
|
|
4
|
-
import type { SessionSource } from "../types/common";
|
|
5
4
|
import type { CoreSessionConfig } from "../types/config";
|
|
6
5
|
import {
|
|
7
6
|
captureHookDiscovery,
|
|
@@ -14,10 +13,15 @@ import {
|
|
|
14
13
|
} from "./telemetry/core-events";
|
|
15
14
|
import type { enrichPromptWithMentions } from "./workspace";
|
|
16
15
|
|
|
16
|
+
/**
|
|
17
|
+
* Emits local-only session creation telemetry (task.created/restarted and
|
|
18
|
+
* hook discovery). The transport-agnostic `session.started` event is
|
|
19
|
+
* emitted from `ClineCore.start` so it fires for every backend (local,
|
|
20
|
+
* hub, remote) at the outer API boundary.
|
|
21
|
+
*/
|
|
17
22
|
export function emitSessionCreationTelemetry(
|
|
18
23
|
config: CoreSessionConfig,
|
|
19
24
|
sessionId: string,
|
|
20
|
-
source: SessionSource,
|
|
21
25
|
isRestart: boolean,
|
|
22
26
|
workspacePath: string,
|
|
23
27
|
agentIdentity?: Partial<TelemetryAgentIdentityProperties>,
|
|
@@ -36,19 +40,6 @@ export function emitSessionCreationTelemetry(
|
|
|
36
40
|
});
|
|
37
41
|
}
|
|
38
42
|
captureHookDiscoveryTelemetry(config.telemetry, { workspacePath });
|
|
39
|
-
config.telemetry?.capture({
|
|
40
|
-
event: "session.started",
|
|
41
|
-
properties: {
|
|
42
|
-
sessionId,
|
|
43
|
-
source,
|
|
44
|
-
providerId: config.providerId,
|
|
45
|
-
modelId: config.modelId,
|
|
46
|
-
enableTools: config.enableTools,
|
|
47
|
-
enableSpawnAgent: config.enableSpawnAgent,
|
|
48
|
-
enableAgentTeams: config.enableAgentTeams,
|
|
49
|
-
...agentIdentity,
|
|
50
|
-
},
|
|
51
|
-
});
|
|
52
43
|
}
|
|
53
44
|
|
|
54
45
|
export function captureHookDiscoveryTelemetry(
|
|
@@ -138,16 +138,12 @@ export class FileTeamStore implements TeamStore {
|
|
|
138
138
|
|
|
139
139
|
loadRuntime(teamName: string): TeamRuntimeLoadResult {
|
|
140
140
|
const envelope = this.readEnvelope(teamName);
|
|
141
|
-
const interruptedRunIds = this.markInProgressRunsInterrupted(
|
|
142
|
-
teamName,
|
|
143
|
-
"runtime_recovered",
|
|
144
|
-
);
|
|
145
141
|
return {
|
|
146
142
|
state: envelope?.teamState
|
|
147
143
|
? reviveTeamRuntimeStateDates(envelope.teamState)
|
|
148
144
|
: undefined,
|
|
149
145
|
teammates: envelope?.teammates ?? [],
|
|
150
|
-
interruptedRunIds,
|
|
146
|
+
interruptedRunIds: [],
|
|
151
147
|
};
|
|
152
148
|
}
|
|
153
149
|
|