@clinebot/core 0.0.6 → 0.0.10
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/agents/hooks-config-loader.d.ts +1 -0
- package/dist/auth/cline.d.ts +2 -0
- package/dist/auth/codex.d.ts +5 -1
- package/dist/auth/oca.d.ts +7 -1
- package/dist/auth/types.d.ts +2 -0
- package/dist/index.d.ts +3 -1
- package/dist/index.node.d.ts +2 -0
- package/dist/index.node.js +164 -162
- package/dist/input/mention-enricher.d.ts +1 -0
- package/dist/providers/local-provider-service.d.ts +1 -1
- package/dist/runtime/session-runtime.d.ts +1 -1
- package/dist/session/default-session-manager.d.ts +13 -17
- package/dist/session/rpc-spawn-lease.d.ts +7 -0
- package/dist/session/runtime-oauth-token-manager.d.ts +4 -2
- package/dist/session/session-agent-events.d.ts +15 -0
- package/dist/session/session-config-builder.d.ts +13 -0
- package/dist/session/session-manager.d.ts +2 -2
- package/dist/session/session-team-coordination.d.ts +12 -0
- package/dist/session/session-telemetry.d.ts +9 -0
- package/dist/session/unified-session-persistence-service.d.ts +12 -16
- package/dist/session/utils/helpers.d.ts +1 -1
- package/dist/session/utils/types.d.ts +1 -1
- package/dist/storage/provider-settings-legacy-migration.d.ts +25 -0
- package/dist/telemetry/core-events.d.ts +122 -0
- package/dist/tools/definitions.d.ts +1 -1
- package/dist/tools/executors/file-read.d.ts +1 -1
- package/dist/tools/index.d.ts +1 -1
- package/dist/tools/presets.d.ts +1 -1
- package/dist/tools/schemas.d.ts +48 -11
- package/dist/tools/types.d.ts +3 -3
- package/dist/types/config.d.ts +1 -1
- package/dist/types/events.d.ts +1 -1
- package/dist/types/provider-settings.d.ts +4 -4
- package/dist/types.d.ts +1 -1
- package/package.json +4 -3
- package/src/agents/hooks-config-loader.ts +2 -0
- package/src/auth/cline.ts +35 -1
- package/src/auth/codex.ts +27 -2
- package/src/auth/oca.ts +31 -4
- package/src/auth/types.ts +3 -0
- package/src/index.node.ts +4 -0
- package/src/index.ts +27 -0
- package/src/input/file-indexer.test.ts +40 -0
- package/src/input/file-indexer.ts +21 -0
- package/src/input/mention-enricher.test.ts +3 -0
- package/src/input/mention-enricher.ts +3 -0
- package/src/providers/local-provider-service.ts +6 -7
- package/src/runtime/hook-file-hooks.test.ts +51 -1
- package/src/runtime/hook-file-hooks.ts +91 -11
- package/src/runtime/session-runtime.ts +1 -1
- package/src/session/default-session-manager.e2e.test.ts +2 -1
- package/src/session/default-session-manager.ts +367 -601
- package/src/session/rpc-spawn-lease.test.ts +49 -0
- package/src/session/rpc-spawn-lease.ts +122 -0
- package/src/session/runtime-oauth-token-manager.ts +21 -14
- package/src/session/session-agent-events.ts +159 -0
- package/src/session/session-config-builder.ts +111 -0
- package/src/session/session-graph.ts +2 -0
- package/src/session/session-host.ts +21 -0
- package/src/session/session-manager.ts +2 -2
- package/src/session/session-team-coordination.ts +198 -0
- package/src/session/session-telemetry.ts +95 -0
- package/src/session/unified-session-persistence-service.test.ts +81 -0
- package/src/session/unified-session-persistence-service.ts +470 -469
- package/src/session/utils/helpers.ts +1 -1
- package/src/session/utils/types.ts +1 -1
- package/src/storage/provider-settings-legacy-migration.test.ts +133 -1
- package/src/storage/provider-settings-legacy-migration.ts +63 -11
- package/src/telemetry/core-events.ts +344 -0
- package/src/tools/definitions.test.ts +203 -36
- package/src/tools/definitions.ts +66 -28
- package/src/tools/executors/editor.test.ts +35 -0
- package/src/tools/executors/editor.ts +33 -46
- package/src/tools/executors/file-read.test.ts +29 -5
- package/src/tools/executors/file-read.ts +17 -6
- package/src/tools/index.ts +2 -0
- package/src/tools/presets.ts +1 -1
- package/src/tools/schemas.ts +88 -38
- package/src/tools/types.ts +7 -3
- package/src/types/config.ts +1 -1
- package/src/types/events.ts +6 -1
- package/src/types/provider-settings.ts +6 -6
- package/src/types.ts +1 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { AgentConfig, AgentEvent, AgentResult } from "@clinebot/agents";
|
|
2
|
-
import type {
|
|
2
|
+
import type { LlmsProviders } from "@clinebot/llms";
|
|
3
3
|
import type { SessionSource } from "../../types/common";
|
|
4
4
|
import type { SessionRecord } from "../../types/sessions";
|
|
5
5
|
import { nowIso } from "../session-artifacts";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Agent } from "@clinebot/agents";
|
|
2
|
-
import type {
|
|
2
|
+
import type { LlmsProviders } from "@clinebot/llms";
|
|
3
3
|
import type { BuiltRuntime } from "../../runtime/session-runtime";
|
|
4
4
|
import type { SessionSource } from "../../types/common";
|
|
5
5
|
import type { CoreSessionConfig } from "../../types/config";
|
|
@@ -2,7 +2,11 @@ import { mkdtempSync, rmSync, writeFileSync } from "node:fs";
|
|
|
2
2
|
import os from "node:os";
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
import { afterEach, describe, expect, it } from "vitest";
|
|
5
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
type LegacyClineUserInfo,
|
|
7
|
+
migrateLegacyProviderSettings,
|
|
8
|
+
resolveLegacyClineAuth,
|
|
9
|
+
} from "./provider-settings-legacy-migration";
|
|
6
10
|
import { ProviderSettingsManager } from "./provider-settings-manager";
|
|
7
11
|
|
|
8
12
|
describe("migrateLegacyProviderSettings", () => {
|
|
@@ -173,3 +177,131 @@ describe("migrateLegacyProviderSettings", () => {
|
|
|
173
177
|
);
|
|
174
178
|
});
|
|
175
179
|
});
|
|
180
|
+
|
|
181
|
+
// =============================================================================
|
|
182
|
+
// resolveLegacyClineAuth – pure in-memory tests
|
|
183
|
+
// =============================================================================
|
|
184
|
+
|
|
185
|
+
/** Builds a realistic LegacyClineUserInfo JSON string. */
|
|
186
|
+
function makeClineAccountJson(
|
|
187
|
+
overrides: Partial<LegacyClineUserInfo> & { userId?: string } = {},
|
|
188
|
+
): string {
|
|
189
|
+
return JSON.stringify({
|
|
190
|
+
idToken: overrides.idToken ?? "id-token-abc",
|
|
191
|
+
expiresAt: overrides.expiresAt ?? 1750000000000,
|
|
192
|
+
refreshToken: overrides.refreshToken ?? "refresh-token-xyz",
|
|
193
|
+
userInfo: overrides.userInfo ?? {
|
|
194
|
+
id: overrides.userId ?? "user-42",
|
|
195
|
+
email: "test@example.com",
|
|
196
|
+
displayName: "Test User",
|
|
197
|
+
termsAcceptedAt: "2025-01-01T00:00:00Z",
|
|
198
|
+
clineBenchConsent: false,
|
|
199
|
+
createdAt: "2025-01-01T00:00:00Z",
|
|
200
|
+
updatedAt: "2025-01-01T00:00:00Z",
|
|
201
|
+
},
|
|
202
|
+
provider: overrides.provider ?? "google",
|
|
203
|
+
startedAt: overrides.startedAt ?? Date.now(),
|
|
204
|
+
} satisfies LegacyClineUserInfo);
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
describe("resolveLegacyClineAuth", () => {
|
|
208
|
+
it("extracts all auth fields from a complete legacy account JSON", () => {
|
|
209
|
+
const result = resolveLegacyClineAuth(
|
|
210
|
+
makeClineAccountJson({
|
|
211
|
+
idToken: "my-id-token",
|
|
212
|
+
expiresAt: 1750000000000,
|
|
213
|
+
refreshToken: "my-refresh",
|
|
214
|
+
userId: "user-123",
|
|
215
|
+
}),
|
|
216
|
+
);
|
|
217
|
+
|
|
218
|
+
expect(result).toEqual({
|
|
219
|
+
accessToken: "my-id-token",
|
|
220
|
+
refreshToken: "my-refresh",
|
|
221
|
+
expiresAt: 1750000000000,
|
|
222
|
+
accountId: "user-123",
|
|
223
|
+
});
|
|
224
|
+
});
|
|
225
|
+
|
|
226
|
+
it("maps idToken to accessToken", () => {
|
|
227
|
+
const result = resolveLegacyClineAuth(
|
|
228
|
+
makeClineAccountJson({ idToken: "tok-abc" }),
|
|
229
|
+
);
|
|
230
|
+
expect(result?.accessToken).toBe("tok-abc");
|
|
231
|
+
});
|
|
232
|
+
|
|
233
|
+
it("preserves expiresAt as a number", () => {
|
|
234
|
+
const result = resolveLegacyClineAuth(
|
|
235
|
+
makeClineAccountJson({ expiresAt: 9999999999999 }),
|
|
236
|
+
);
|
|
237
|
+
expect(result?.expiresAt).toBe(9999999999999);
|
|
238
|
+
expect(typeof result?.expiresAt).toBe("number");
|
|
239
|
+
});
|
|
240
|
+
|
|
241
|
+
it("maps userInfo.id to accountId", () => {
|
|
242
|
+
const result = resolveLegacyClineAuth(
|
|
243
|
+
makeClineAccountJson({ userId: "uid-xyz" }),
|
|
244
|
+
);
|
|
245
|
+
expect(result?.accountId).toBe("uid-xyz");
|
|
246
|
+
});
|
|
247
|
+
|
|
248
|
+
it("returns undefined accountId when userInfo is missing entirely", () => {
|
|
249
|
+
const raw = JSON.stringify({
|
|
250
|
+
idToken: "tok",
|
|
251
|
+
expiresAt: 1000,
|
|
252
|
+
refreshToken: "ref",
|
|
253
|
+
provider: "google",
|
|
254
|
+
startedAt: 1,
|
|
255
|
+
});
|
|
256
|
+
|
|
257
|
+
const result = resolveLegacyClineAuth(raw);
|
|
258
|
+
expect(result).toBeDefined();
|
|
259
|
+
expect(result?.accessToken).toBe("tok");
|
|
260
|
+
expect(result?.accountId).toBeUndefined();
|
|
261
|
+
});
|
|
262
|
+
|
|
263
|
+
it("returns undefined accountId when userInfo.id is missing", () => {
|
|
264
|
+
const raw = JSON.stringify({
|
|
265
|
+
idToken: "tok",
|
|
266
|
+
expiresAt: 1000,
|
|
267
|
+
refreshToken: "ref",
|
|
268
|
+
userInfo: {
|
|
269
|
+
email: "x@y.com",
|
|
270
|
+
displayName: "X",
|
|
271
|
+
termsAcceptedAt: "2025-01-01T00:00:00Z",
|
|
272
|
+
clineBenchConsent: false,
|
|
273
|
+
createdAt: "2025-01-01T00:00:00Z",
|
|
274
|
+
updatedAt: "2025-01-01T00:00:00Z",
|
|
275
|
+
},
|
|
276
|
+
provider: "google",
|
|
277
|
+
startedAt: 1,
|
|
278
|
+
});
|
|
279
|
+
|
|
280
|
+
const result = resolveLegacyClineAuth(raw);
|
|
281
|
+
expect(result).toBeDefined();
|
|
282
|
+
expect(result?.accountId).toBeUndefined();
|
|
283
|
+
});
|
|
284
|
+
|
|
285
|
+
it("returns undefined for invalid json", () => {
|
|
286
|
+
expect(resolveLegacyClineAuth(undefined)).toBeUndefined();
|
|
287
|
+
expect(resolveLegacyClineAuth("")).toBeUndefined();
|
|
288
|
+
expect(resolveLegacyClineAuth(" \n\t ")).toBeUndefined();
|
|
289
|
+
expect(resolveLegacyClineAuth("not-json{{{")).toBeUndefined();
|
|
290
|
+
expect(resolveLegacyClineAuth("null")).toBeUndefined();
|
|
291
|
+
});
|
|
292
|
+
|
|
293
|
+
it("returns undefined fields when idToken/refreshToken are missing from JSON", () => {
|
|
294
|
+
const raw = JSON.stringify({
|
|
295
|
+
userInfo: { id: "uid" },
|
|
296
|
+
provider: "google",
|
|
297
|
+
startedAt: 1,
|
|
298
|
+
});
|
|
299
|
+
|
|
300
|
+
const result = resolveLegacyClineAuth(raw);
|
|
301
|
+
expect(result).toBeDefined();
|
|
302
|
+
expect(result?.accessToken).toBeUndefined();
|
|
303
|
+
expect(result?.refreshToken).toBeUndefined();
|
|
304
|
+
expect(result?.expiresAt).toBeUndefined();
|
|
305
|
+
expect(result?.accountId).toBe("uid");
|
|
306
|
+
});
|
|
307
|
+
});
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { existsSync, readFileSync } from "node:fs";
|
|
2
2
|
import { join } from "node:path";
|
|
3
|
-
import {
|
|
3
|
+
import { LlmsModels, LlmsProviders } from "@clinebot/llms";
|
|
4
4
|
import { resolveClineDataDir } from "@clinebot/shared/storage";
|
|
5
5
|
import type { ProviderSettings } from "../types/provider-settings";
|
|
6
6
|
import { emptyStoredProviderSettings } from "../types/provider-settings";
|
|
@@ -162,6 +162,53 @@ export interface MigrateLegacyProviderSettingsResult {
|
|
|
162
162
|
lastUsedProvider?: string;
|
|
163
163
|
}
|
|
164
164
|
|
|
165
|
+
export type LegacyClineUserInfo = {
|
|
166
|
+
idToken: string;
|
|
167
|
+
expiresAt: number;
|
|
168
|
+
refreshToken: string;
|
|
169
|
+
userInfo: {
|
|
170
|
+
id: string;
|
|
171
|
+
email: string;
|
|
172
|
+
displayName: string;
|
|
173
|
+
termsAcceptedAt: string;
|
|
174
|
+
clineBenchConsent: boolean;
|
|
175
|
+
createdAt: string;
|
|
176
|
+
updatedAt: string;
|
|
177
|
+
};
|
|
178
|
+
provider: string;
|
|
179
|
+
startedAt: number;
|
|
180
|
+
};
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* Resolves legacy Cline account auth data from the raw `cline:clineAccountId`
|
|
184
|
+
* secret string into the auth fields used by `ProviderSettings`.
|
|
185
|
+
*
|
|
186
|
+
* Returns `undefined` when the input is missing, empty, whitespace-only, or
|
|
187
|
+
* unparseable JSON.
|
|
188
|
+
*/
|
|
189
|
+
export function resolveLegacyClineAuth(
|
|
190
|
+
rawAccountData: string | undefined,
|
|
191
|
+
): ProviderSettings["auth"] | undefined {
|
|
192
|
+
const trimmed = rawAccountData?.trim();
|
|
193
|
+
if (!trimmed) {
|
|
194
|
+
return undefined;
|
|
195
|
+
}
|
|
196
|
+
try {
|
|
197
|
+
const data = JSON.parse(trimmed) as LegacyClineUserInfo;
|
|
198
|
+
if (!data) {
|
|
199
|
+
return undefined;
|
|
200
|
+
}
|
|
201
|
+
return {
|
|
202
|
+
accessToken: data.idToken,
|
|
203
|
+
refreshToken: data.refreshToken,
|
|
204
|
+
expiresAt: data.expiresAt,
|
|
205
|
+
accountId: data.userInfo?.id,
|
|
206
|
+
};
|
|
207
|
+
} catch {
|
|
208
|
+
return undefined;
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
|
|
165
212
|
function trimNonEmpty(value: string | undefined): string | undefined {
|
|
166
213
|
const trimmed = value?.trim();
|
|
167
214
|
return trimmed ? trimmed : undefined;
|
|
@@ -326,7 +373,7 @@ function resolveLegacyCodexAuth(
|
|
|
326
373
|
}
|
|
327
374
|
|
|
328
375
|
function getDefaultModelForProvider(providerId: string): string | undefined {
|
|
329
|
-
const builtInModels =
|
|
376
|
+
const builtInModels = LlmsModels.getGeneratedModelsForProvider(providerId);
|
|
330
377
|
const firstModelId = Object.keys(builtInModels)[0];
|
|
331
378
|
return firstModelId ?? undefined;
|
|
332
379
|
}
|
|
@@ -400,14 +447,19 @@ function buildLegacyProviderSettings(
|
|
|
400
447
|
Object.assign(providerSpecific, resolveLegacyCodexAuth(legacySecrets));
|
|
401
448
|
}
|
|
402
449
|
if (providerId === "cline") {
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
450
|
+
try {
|
|
451
|
+
const legacyAuthString = trimNonEmpty(
|
|
452
|
+
legacySecrets["cline:clineAccountId"],
|
|
453
|
+
);
|
|
454
|
+
|
|
455
|
+
if (legacyAuthString) {
|
|
456
|
+
providerSpecific.auth = {
|
|
457
|
+
...(providerSpecific.auth ?? {}),
|
|
458
|
+
...resolveLegacyClineAuth(legacyAuthString),
|
|
459
|
+
};
|
|
460
|
+
}
|
|
461
|
+
} catch {
|
|
462
|
+
// Failed to parse stored cline auth data
|
|
411
463
|
}
|
|
412
464
|
}
|
|
413
465
|
if (providerId === "openai" && legacyGlobalState.openAiHeaders) {
|
|
@@ -516,7 +568,7 @@ function buildLegacyProviderSettings(
|
|
|
516
568
|
...(timeout ? { timeout } : {}),
|
|
517
569
|
...providerSpecific,
|
|
518
570
|
};
|
|
519
|
-
const parsed =
|
|
571
|
+
const parsed = LlmsProviders.ProviderSettingsSchema.safeParse(settings);
|
|
520
572
|
if (!parsed.success) {
|
|
521
573
|
return undefined;
|
|
522
574
|
}
|
|
@@ -0,0 +1,344 @@
|
|
|
1
|
+
import type { ITelemetryService, TelemetryProperties } from "@clinebot/shared";
|
|
2
|
+
|
|
3
|
+
const MAX_ERROR_MESSAGE_LENGTH = 500;
|
|
4
|
+
|
|
5
|
+
export const LegacyTelemetryEvents = {
|
|
6
|
+
USER: {
|
|
7
|
+
AUTH_STARTED: "user.auth_started",
|
|
8
|
+
AUTH_SUCCEEDED: "user.auth_succeeded",
|
|
9
|
+
AUTH_FAILED: "user.auth_failed",
|
|
10
|
+
AUTH_LOGGED_OUT: "user.auth_logged_out",
|
|
11
|
+
},
|
|
12
|
+
TASK: {
|
|
13
|
+
CREATED: "task.created",
|
|
14
|
+
RESTARTED: "task.restarted",
|
|
15
|
+
COMPLETED: "task.completed",
|
|
16
|
+
CONVERSATION_TURN: "task.conversation_turn",
|
|
17
|
+
TOKEN_USAGE: "task.tokens",
|
|
18
|
+
MODE_SWITCH: "task.mode",
|
|
19
|
+
TOOL_USED: "task.tool_used",
|
|
20
|
+
SKILL_USED: "task.skill_used",
|
|
21
|
+
DIFF_EDIT_FAILED: "task.diff_edit_failed",
|
|
22
|
+
PROVIDER_API_ERROR: "task.provider_api_error",
|
|
23
|
+
MENTION_USED: "task.mention_used",
|
|
24
|
+
MENTION_FAILED: "task.mention_failed",
|
|
25
|
+
MENTION_SEARCH_RESULTS: "task.mention_search_results",
|
|
26
|
+
SUBAGENT_STARTED: "task.subagent_started",
|
|
27
|
+
SUBAGENT_COMPLETED: "task.subagent_completed",
|
|
28
|
+
},
|
|
29
|
+
HOOKS: {
|
|
30
|
+
DISCOVERY_COMPLETED: "hooks.discovery_completed",
|
|
31
|
+
},
|
|
32
|
+
} as const;
|
|
33
|
+
|
|
34
|
+
function emit(
|
|
35
|
+
telemetry: ITelemetryService | undefined,
|
|
36
|
+
event: string,
|
|
37
|
+
properties?: TelemetryProperties,
|
|
38
|
+
): void {
|
|
39
|
+
telemetry?.capture({ event, properties });
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function truncateErrorMessage(errorMessage?: string): string | undefined {
|
|
43
|
+
if (!errorMessage) {
|
|
44
|
+
return undefined;
|
|
45
|
+
}
|
|
46
|
+
return errorMessage.substring(0, MAX_ERROR_MESSAGE_LENGTH);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export function captureAuthStarted(
|
|
50
|
+
telemetry: ITelemetryService | undefined,
|
|
51
|
+
provider?: string,
|
|
52
|
+
): void {
|
|
53
|
+
emit(telemetry, LegacyTelemetryEvents.USER.AUTH_STARTED, { provider });
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export function captureAuthSucceeded(
|
|
57
|
+
telemetry: ITelemetryService | undefined,
|
|
58
|
+
provider?: string,
|
|
59
|
+
): void {
|
|
60
|
+
emit(telemetry, LegacyTelemetryEvents.USER.AUTH_SUCCEEDED, { provider });
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export function captureAuthFailed(
|
|
64
|
+
telemetry: ITelemetryService | undefined,
|
|
65
|
+
provider?: string,
|
|
66
|
+
errorMessage?: string,
|
|
67
|
+
): void {
|
|
68
|
+
emit(telemetry, LegacyTelemetryEvents.USER.AUTH_FAILED, {
|
|
69
|
+
provider,
|
|
70
|
+
errorMessage: truncateErrorMessage(errorMessage),
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export function captureAuthLoggedOut(
|
|
75
|
+
telemetry: ITelemetryService | undefined,
|
|
76
|
+
provider?: string,
|
|
77
|
+
reason?: string,
|
|
78
|
+
): void {
|
|
79
|
+
emit(telemetry, LegacyTelemetryEvents.USER.AUTH_LOGGED_OUT, {
|
|
80
|
+
provider,
|
|
81
|
+
reason,
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export function identifyAccount(
|
|
86
|
+
telemetry: ITelemetryService | undefined,
|
|
87
|
+
account: {
|
|
88
|
+
id?: string;
|
|
89
|
+
email?: string;
|
|
90
|
+
provider?: string;
|
|
91
|
+
organizationId?: string;
|
|
92
|
+
organizationName?: string;
|
|
93
|
+
memberId?: string;
|
|
94
|
+
},
|
|
95
|
+
): void {
|
|
96
|
+
const distinctId = account.id?.trim();
|
|
97
|
+
if (distinctId) {
|
|
98
|
+
telemetry?.setDistinctId(distinctId);
|
|
99
|
+
}
|
|
100
|
+
telemetry?.updateCommonProperties({
|
|
101
|
+
account_id: account.id,
|
|
102
|
+
account_email: account.email,
|
|
103
|
+
provider: account.provider,
|
|
104
|
+
organization_id: account.organizationId,
|
|
105
|
+
organization_name: account.organizationName,
|
|
106
|
+
member_id: account.memberId,
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
export function captureTaskCreated(
|
|
111
|
+
telemetry: ITelemetryService | undefined,
|
|
112
|
+
properties: {
|
|
113
|
+
ulid: string;
|
|
114
|
+
apiProvider?: string;
|
|
115
|
+
openAiCompatibleDomain?: string;
|
|
116
|
+
},
|
|
117
|
+
): void {
|
|
118
|
+
emit(telemetry, LegacyTelemetryEvents.TASK.CREATED, properties);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
export function captureTaskRestarted(
|
|
122
|
+
telemetry: ITelemetryService | undefined,
|
|
123
|
+
properties: {
|
|
124
|
+
ulid: string;
|
|
125
|
+
apiProvider?: string;
|
|
126
|
+
openAiCompatibleDomain?: string;
|
|
127
|
+
},
|
|
128
|
+
): void {
|
|
129
|
+
emit(telemetry, LegacyTelemetryEvents.TASK.RESTARTED, properties);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
export function captureTaskCompleted(
|
|
133
|
+
telemetry: ITelemetryService | undefined,
|
|
134
|
+
properties: {
|
|
135
|
+
ulid: string;
|
|
136
|
+
provider?: string;
|
|
137
|
+
modelId?: string;
|
|
138
|
+
mode?: string;
|
|
139
|
+
durationMs?: number;
|
|
140
|
+
},
|
|
141
|
+
): void {
|
|
142
|
+
emit(telemetry, LegacyTelemetryEvents.TASK.COMPLETED, properties);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
export function captureConversationTurnEvent(
|
|
146
|
+
telemetry: ITelemetryService | undefined,
|
|
147
|
+
properties: {
|
|
148
|
+
ulid: string;
|
|
149
|
+
provider?: string;
|
|
150
|
+
model?: string;
|
|
151
|
+
source: "user" | "assistant";
|
|
152
|
+
mode?: string;
|
|
153
|
+
tokensIn?: number;
|
|
154
|
+
tokensOut?: number;
|
|
155
|
+
cacheWriteTokens?: number;
|
|
156
|
+
cacheReadTokens?: number;
|
|
157
|
+
totalCost?: number;
|
|
158
|
+
isNativeToolCall?: boolean;
|
|
159
|
+
},
|
|
160
|
+
): void {
|
|
161
|
+
emit(telemetry, LegacyTelemetryEvents.TASK.CONVERSATION_TURN, {
|
|
162
|
+
...properties,
|
|
163
|
+
timestamp: new Date().toISOString(),
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
export function captureTokenUsage(
|
|
168
|
+
telemetry: ITelemetryService | undefined,
|
|
169
|
+
properties: {
|
|
170
|
+
ulid: string;
|
|
171
|
+
tokensIn: number;
|
|
172
|
+
tokensOut: number;
|
|
173
|
+
model: string;
|
|
174
|
+
},
|
|
175
|
+
): void {
|
|
176
|
+
emit(telemetry, LegacyTelemetryEvents.TASK.TOKEN_USAGE, properties);
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
export function captureModeSwitch(
|
|
180
|
+
telemetry: ITelemetryService | undefined,
|
|
181
|
+
ulid: string,
|
|
182
|
+
mode?: string,
|
|
183
|
+
): void {
|
|
184
|
+
emit(telemetry, LegacyTelemetryEvents.TASK.MODE_SWITCH, { ulid, mode });
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
export function captureToolUsage(
|
|
188
|
+
telemetry: ITelemetryService | undefined,
|
|
189
|
+
properties: {
|
|
190
|
+
ulid: string;
|
|
191
|
+
tool: string;
|
|
192
|
+
modelId?: string;
|
|
193
|
+
provider?: string;
|
|
194
|
+
autoApproved?: boolean;
|
|
195
|
+
success: boolean;
|
|
196
|
+
isNativeToolCall?: boolean;
|
|
197
|
+
},
|
|
198
|
+
): void {
|
|
199
|
+
emit(telemetry, LegacyTelemetryEvents.TASK.TOOL_USED, properties);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
export function captureSkillUsed(
|
|
203
|
+
telemetry: ITelemetryService | undefined,
|
|
204
|
+
properties: {
|
|
205
|
+
ulid: string;
|
|
206
|
+
skillName: string;
|
|
207
|
+
skillSource: "global" | "project";
|
|
208
|
+
skillsAvailableGlobal: number;
|
|
209
|
+
skillsAvailableProject: number;
|
|
210
|
+
provider?: string;
|
|
211
|
+
modelId?: string;
|
|
212
|
+
},
|
|
213
|
+
): void {
|
|
214
|
+
emit(telemetry, LegacyTelemetryEvents.TASK.SKILL_USED, properties);
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
export function captureDiffEditFailure(
|
|
218
|
+
telemetry: ITelemetryService | undefined,
|
|
219
|
+
properties: {
|
|
220
|
+
ulid: string;
|
|
221
|
+
modelId?: string;
|
|
222
|
+
provider?: string;
|
|
223
|
+
errorType?: string;
|
|
224
|
+
isNativeToolCall?: boolean;
|
|
225
|
+
},
|
|
226
|
+
): void {
|
|
227
|
+
emit(telemetry, LegacyTelemetryEvents.TASK.DIFF_EDIT_FAILED, properties);
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
export function captureProviderApiError(
|
|
231
|
+
telemetry: ITelemetryService | undefined,
|
|
232
|
+
properties: {
|
|
233
|
+
ulid: string;
|
|
234
|
+
model: string;
|
|
235
|
+
errorMessage: string;
|
|
236
|
+
provider?: string;
|
|
237
|
+
errorStatus?: number;
|
|
238
|
+
requestId?: string;
|
|
239
|
+
isNativeToolCall?: boolean;
|
|
240
|
+
},
|
|
241
|
+
): void {
|
|
242
|
+
emit(telemetry, LegacyTelemetryEvents.TASK.PROVIDER_API_ERROR, {
|
|
243
|
+
...properties,
|
|
244
|
+
errorMessage: truncateErrorMessage(properties.errorMessage) ?? "unknown",
|
|
245
|
+
timestamp: new Date().toISOString(),
|
|
246
|
+
});
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
export function captureMentionUsed(
|
|
250
|
+
telemetry: ITelemetryService | undefined,
|
|
251
|
+
mentionType:
|
|
252
|
+
| "file"
|
|
253
|
+
| "folder"
|
|
254
|
+
| "url"
|
|
255
|
+
| "problems"
|
|
256
|
+
| "terminal"
|
|
257
|
+
| "git-changes"
|
|
258
|
+
| "commit",
|
|
259
|
+
contentLength?: number,
|
|
260
|
+
): void {
|
|
261
|
+
emit(telemetry, LegacyTelemetryEvents.TASK.MENTION_USED, {
|
|
262
|
+
mentionType,
|
|
263
|
+
contentLength,
|
|
264
|
+
timestamp: new Date().toISOString(),
|
|
265
|
+
});
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
export function captureMentionFailed(
|
|
269
|
+
telemetry: ITelemetryService | undefined,
|
|
270
|
+
mentionType:
|
|
271
|
+
| "file"
|
|
272
|
+
| "folder"
|
|
273
|
+
| "url"
|
|
274
|
+
| "problems"
|
|
275
|
+
| "terminal"
|
|
276
|
+
| "git-changes"
|
|
277
|
+
| "commit",
|
|
278
|
+
errorType:
|
|
279
|
+
| "not_found"
|
|
280
|
+
| "permission_denied"
|
|
281
|
+
| "network_error"
|
|
282
|
+
| "parse_error"
|
|
283
|
+
| "unknown",
|
|
284
|
+
errorMessage?: string,
|
|
285
|
+
): void {
|
|
286
|
+
emit(telemetry, LegacyTelemetryEvents.TASK.MENTION_FAILED, {
|
|
287
|
+
mentionType,
|
|
288
|
+
errorType,
|
|
289
|
+
errorMessage: truncateErrorMessage(errorMessage),
|
|
290
|
+
timestamp: new Date().toISOString(),
|
|
291
|
+
});
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
export function captureMentionSearchResults(
|
|
295
|
+
telemetry: ITelemetryService | undefined,
|
|
296
|
+
query: string,
|
|
297
|
+
resultCount: number,
|
|
298
|
+
searchType: "file" | "folder" | "all",
|
|
299
|
+
isEmpty: boolean,
|
|
300
|
+
): void {
|
|
301
|
+
emit(telemetry, LegacyTelemetryEvents.TASK.MENTION_SEARCH_RESULTS, {
|
|
302
|
+
queryLength: query.length,
|
|
303
|
+
resultCount,
|
|
304
|
+
searchType,
|
|
305
|
+
isEmpty,
|
|
306
|
+
timestamp: new Date().toISOString(),
|
|
307
|
+
});
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
export function captureSubagentExecution(
|
|
311
|
+
telemetry: ITelemetryService | undefined,
|
|
312
|
+
properties: {
|
|
313
|
+
ulid: string;
|
|
314
|
+
durationMs: number;
|
|
315
|
+
outputLines: number;
|
|
316
|
+
success: boolean;
|
|
317
|
+
},
|
|
318
|
+
): void {
|
|
319
|
+
emit(
|
|
320
|
+
telemetry,
|
|
321
|
+
properties.success
|
|
322
|
+
? LegacyTelemetryEvents.TASK.SUBAGENT_COMPLETED
|
|
323
|
+
: LegacyTelemetryEvents.TASK.SUBAGENT_STARTED,
|
|
324
|
+
{
|
|
325
|
+
...properties,
|
|
326
|
+
timestamp: new Date().toISOString(),
|
|
327
|
+
},
|
|
328
|
+
);
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
export function captureHookDiscovery(
|
|
332
|
+
telemetry: ITelemetryService | undefined,
|
|
333
|
+
hookName: string,
|
|
334
|
+
globalCount: number,
|
|
335
|
+
workspaceCount: number,
|
|
336
|
+
): void {
|
|
337
|
+
emit(telemetry, LegacyTelemetryEvents.HOOKS.DISCOVERY_COMPLETED, {
|
|
338
|
+
hookName,
|
|
339
|
+
globalCount,
|
|
340
|
+
workspaceCount,
|
|
341
|
+
totalCount: globalCount + workspaceCount,
|
|
342
|
+
timestamp: new Date().toISOString(),
|
|
343
|
+
});
|
|
344
|
+
}
|