@vybestack/llxprt-code-core 0.1.19 → 0.1.20

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (156) hide show
  1. package/README.md +9 -0
  2. package/dist/src/auth/anthropic-device-flow.d.ts +1 -1
  3. package/dist/src/auth/anthropic-device-flow.js +4 -2
  4. package/dist/src/auth/anthropic-device-flow.js.map +1 -1
  5. package/dist/src/code_assist/setup.js +49 -15
  6. package/dist/src/code_assist/setup.js.map +1 -1
  7. package/dist/src/config/config.d.ts +9 -6
  8. package/dist/src/config/config.js +24 -21
  9. package/dist/src/config/config.js.map +1 -1
  10. package/dist/src/core/client.d.ts +3 -1
  11. package/dist/src/core/client.js +22 -6
  12. package/dist/src/core/client.js.map +1 -1
  13. package/dist/src/core/contentGenerator.js +0 -2
  14. package/dist/src/core/contentGenerator.js.map +1 -1
  15. package/dist/src/core/coreToolScheduler.d.ts +0 -1
  16. package/dist/src/core/coreToolScheduler.js +0 -3
  17. package/dist/src/core/coreToolScheduler.js.map +1 -1
  18. package/dist/src/core/geminiChat.js +57 -5
  19. package/dist/src/core/geminiChat.js.map +1 -1
  20. package/dist/src/core/nonInteractiveToolExecutor.js +158 -3
  21. package/dist/src/core/nonInteractiveToolExecutor.js.map +1 -1
  22. package/dist/src/core/prompts.js +19 -2
  23. package/dist/src/core/prompts.js.map +1 -1
  24. package/dist/src/filters/EmojiFilter.d.ts +122 -0
  25. package/dist/src/filters/EmojiFilter.js +327 -0
  26. package/dist/src/filters/EmojiFilter.js.map +1 -0
  27. package/dist/src/ide/detect-ide.d.ts +2 -0
  28. package/dist/src/ide/detect-ide.js +18 -2
  29. package/dist/src/ide/detect-ide.js.map +1 -1
  30. package/dist/src/ide/ide-installer.js +1 -26
  31. package/dist/src/ide/ide-installer.js.map +1 -1
  32. package/dist/src/ide/ideContext.d.ts +6 -6
  33. package/dist/src/index.d.ts +3 -0
  34. package/dist/src/index.js +3 -0
  35. package/dist/src/index.js.map +1 -1
  36. package/dist/src/mcp/oauth-provider.d.ts +0 -1
  37. package/dist/src/mcp/oauth-provider.js +2 -3
  38. package/dist/src/mcp/oauth-provider.js.map +1 -1
  39. package/dist/src/prompt-config/defaults/core-defaults.js +190 -6
  40. package/dist/src/prompt-config/defaults/core-defaults.js.map +1 -1
  41. package/dist/src/prompt-config/defaults/provider-defaults.js +162 -6
  42. package/dist/src/prompt-config/defaults/provider-defaults.js.map +1 -1
  43. package/dist/src/prompt-config/defaults/providers/anthropic/core.md +81 -0
  44. package/dist/src/prompt-config/defaults/providers/anthropic/tools/glob.md +34 -0
  45. package/dist/src/prompt-config/defaults/providers/anthropic/tools/list-directory.md +11 -0
  46. package/dist/src/prompt-config/defaults/providers/anthropic/tools/read-file.md +14 -0
  47. package/dist/src/prompt-config/defaults/providers/anthropic/tools/read-many-files.md +31 -0
  48. package/dist/src/prompt-config/defaults/providers/anthropic/tools/replace.md +41 -0
  49. package/dist/src/prompt-config/defaults/providers/anthropic/tools/run-shell-command.md +32 -0
  50. package/dist/src/prompt-config/defaults/providers/anthropic/tools/save-memory.md +35 -0
  51. package/dist/src/prompt-config/defaults/providers/anthropic/tools/search-file-content.md +44 -0
  52. package/dist/src/prompt-config/defaults/providers/anthropic/tools/todo-write.md +45 -0
  53. package/dist/src/prompt-config/defaults/providers/anthropic/tools/write-file.md +11 -0
  54. package/dist/src/prompt-config/defaults/tool-defaults.js +163 -6
  55. package/dist/src/prompt-config/defaults/tool-defaults.js.map +1 -1
  56. package/dist/src/prompt-config/prompt-service.d.ts +1 -1
  57. package/dist/src/prompt-config/prompt-service.js +5 -3
  58. package/dist/src/prompt-config/prompt-service.js.map +1 -1
  59. package/dist/src/providers/LoggingProviderWrapper.js +0 -12
  60. package/dist/src/providers/LoggingProviderWrapper.js.map +1 -1
  61. package/dist/src/providers/ProviderContentGenerator.d.ts +2 -2
  62. package/dist/src/providers/ProviderContentGenerator.js +5 -3
  63. package/dist/src/providers/ProviderContentGenerator.js.map +1 -1
  64. package/dist/src/providers/adapters/GeminiCompatibleWrapper.js +1 -1
  65. package/dist/src/providers/adapters/GeminiCompatibleWrapper.js.map +1 -1
  66. package/dist/src/providers/anthropic/AnthropicProvider.d.ts +1 -1
  67. package/dist/src/providers/anthropic/AnthropicProvider.js +95 -33
  68. package/dist/src/providers/anthropic/AnthropicProvider.js.map +1 -1
  69. package/dist/src/providers/gemini/GeminiProvider.d.ts +0 -5
  70. package/dist/src/providers/gemini/GeminiProvider.js +0 -25
  71. package/dist/src/providers/gemini/GeminiProvider.js.map +1 -1
  72. package/dist/src/providers/openai/OpenAIProvider.js +2 -1
  73. package/dist/src/providers/openai/OpenAIProvider.js.map +1 -1
  74. package/dist/src/providers/openai/parseResponsesStream.js +6 -6
  75. package/dist/src/providers/openai/parseResponsesStream.js.map +1 -1
  76. package/dist/src/services/todo-context-tracker.d.ts +1 -1
  77. package/dist/src/services/todo-context-tracker.js +5 -3
  78. package/dist/src/services/todo-context-tracker.js.map +1 -1
  79. package/dist/src/settings/SettingsService.js.map +1 -1
  80. package/dist/src/settings/types.d.ts +16 -0
  81. package/dist/src/telemetry/integration.test.circular.js +2 -40
  82. package/dist/src/telemetry/integration.test.circular.js.map +1 -1
  83. package/dist/src/telemetry/loggers.js +0 -20
  84. package/dist/src/telemetry/loggers.js.map +1 -1
  85. package/dist/src/telemetry/sdk.d.ts +1 -1
  86. package/dist/src/telemetry/sdk.js +13 -29
  87. package/dist/src/telemetry/sdk.js.map +1 -1
  88. package/dist/src/test-utils/tools.js +2 -2
  89. package/dist/src/test-utils/tools.js.map +1 -1
  90. package/dist/src/tools/edit.js +85 -20
  91. package/dist/src/tools/edit.js.map +1 -1
  92. package/dist/src/tools/glob.js +2 -2
  93. package/dist/src/tools/glob.js.map +1 -1
  94. package/dist/src/tools/grep.js +2 -2
  95. package/dist/src/tools/grep.js.map +1 -1
  96. package/dist/src/tools/ls.d.ts +3 -22
  97. package/dist/src/tools/ls.js +84 -113
  98. package/dist/src/tools/ls.js.map +1 -1
  99. package/dist/src/tools/mcp-client.js +2 -2
  100. package/dist/src/tools/mcp-client.js.map +1 -1
  101. package/dist/src/tools/mcp-tool.d.ts +3 -5
  102. package/dist/src/tools/mcp-tool.js +41 -18
  103. package/dist/src/tools/mcp-tool.js.map +1 -1
  104. package/dist/src/tools/memoryTool.d.ts +9 -13
  105. package/dist/src/tools/memoryTool.js +124 -117
  106. package/dist/src/tools/memoryTool.js.map +1 -1
  107. package/dist/src/tools/read-file.js +2 -2
  108. package/dist/src/tools/read-file.js.map +1 -1
  109. package/dist/src/tools/read-many-files.d.ts +4 -6
  110. package/dist/src/tools/read-many-files.js +118 -110
  111. package/dist/src/tools/read-many-files.js.map +1 -1
  112. package/dist/src/tools/shell.d.ts +7 -14
  113. package/dist/src/tools/shell.js +120 -116
  114. package/dist/src/tools/shell.js.map +1 -1
  115. package/dist/src/tools/todo-pause.js +2 -2
  116. package/dist/src/tools/todo-pause.js.map +1 -1
  117. package/dist/src/tools/todo-read.js +8 -8
  118. package/dist/src/tools/todo-read.js.map +1 -1
  119. package/dist/src/tools/todo-write.js +2 -2
  120. package/dist/src/tools/todo-write.js.map +1 -1
  121. package/dist/src/tools/tool-registry.d.ts +5 -0
  122. package/dist/src/tools/tool-registry.js +13 -2
  123. package/dist/src/tools/tool-registry.js.map +1 -1
  124. package/dist/src/tools/tools.d.ts +16 -15
  125. package/dist/src/tools/tools.js +19 -18
  126. package/dist/src/tools/tools.js.map +1 -1
  127. package/dist/src/tools/web-fetch.d.ts +4 -7
  128. package/dist/src/tools/web-fetch.js +81 -82
  129. package/dist/src/tools/web-fetch.js.map +1 -1
  130. package/dist/src/tools/web-search.js +23 -5
  131. package/dist/src/tools/web-search.js.map +1 -1
  132. package/dist/src/tools/write-file.d.ts +2 -1
  133. package/dist/src/tools/write-file.js +85 -24
  134. package/dist/src/tools/write-file.js.map +1 -1
  135. package/dist/src/utils/errorParsing.d.ts +8 -0
  136. package/dist/src/utils/errorParsing.js +109 -0
  137. package/dist/src/utils/errorParsing.js.map +1 -0
  138. package/dist/src/utils/filesearch/fileSearch.js +1 -1
  139. package/dist/src/utils/filesearch/fileSearch.js.map +1 -1
  140. package/dist/src/utils/filesearch/result-cache.d.ts +1 -2
  141. package/dist/src/utils/filesearch/result-cache.js +1 -3
  142. package/dist/src/utils/filesearch/result-cache.js.map +1 -1
  143. package/dist/src/utils/memoryImportProcessor.js +1 -1
  144. package/dist/src/utils/memoryImportProcessor.js.map +1 -1
  145. package/dist/src/utils/quotaErrorDetection.d.ts +1 -5
  146. package/dist/src/utils/quotaErrorDetection.js.map +1 -1
  147. package/package.json +2 -2
  148. package/dist/src/core/modelCheck.d.ts +0 -14
  149. package/dist/src/core/modelCheck.js +0 -62
  150. package/dist/src/core/modelCheck.js.map +0 -1
  151. package/dist/src/telemetry/clearcut-logger/clearcut-logger.d.ts +0 -48
  152. package/dist/src/telemetry/clearcut-logger/clearcut-logger.js +0 -577
  153. package/dist/src/telemetry/clearcut-logger/clearcut-logger.js.map +0 -1
  154. package/dist/src/telemetry/clearcut-logger/event-metadata-key.d.ts +0 -58
  155. package/dist/src/telemetry/clearcut-logger/event-metadata-key.js +0 -157
  156. package/dist/src/telemetry/clearcut-logger/event-metadata-key.js.map +0 -1
@@ -1,62 +0,0 @@
1
- /**
2
- * @license
3
- * Copyright 2025 Google LLC
4
- * SPDX-License-Identifier: Apache-2.0
5
- */
6
- import { setGlobalDispatcher, ProxyAgent } from 'undici';
7
- import { DEFAULT_GEMINI_MODEL, DEFAULT_GEMINI_FLASH_MODEL, } from '../config/models.js';
8
- /**
9
- * Checks if the default "pro" model is rate-limited and returns a fallback "flash"
10
- * model if necessary. This function is designed to be silent.
11
- * @param apiKey The API key to use for the check.
12
- * @param currentConfiguredModel The model currently configured in settings.
13
- * @returns An object indicating the model to use, whether a switch occurred,
14
- * and the original model if a switch happened.
15
- */
16
- export async function getEffectiveModel(apiKey, currentConfiguredModel, proxy) {
17
- if (currentConfiguredModel !== DEFAULT_GEMINI_MODEL) {
18
- // Only check if the user is trying to use the specific pro model we want to fallback from.
19
- return currentConfiguredModel;
20
- }
21
- const modelToTest = DEFAULT_GEMINI_MODEL;
22
- const fallbackModel = DEFAULT_GEMINI_FLASH_MODEL;
23
- const endpoint = `https://generativelanguage.googleapis.com/v1beta/models/${modelToTest}:generateContent`;
24
- const body = JSON.stringify({
25
- contents: [{ parts: [{ text: 'test' }] }],
26
- generationConfig: {
27
- maxOutputTokens: 1,
28
- temperature: 0,
29
- topK: 1,
30
- thinkingConfig: { thinkingBudget: 128, includeThoughts: false },
31
- },
32
- });
33
- const controller = new AbortController();
34
- const timeoutId = setTimeout(() => controller.abort(), 2000); // 500ms timeout for the request
35
- try {
36
- if (proxy) {
37
- setGlobalDispatcher(new ProxyAgent(proxy));
38
- }
39
- const response = await fetch(endpoint, {
40
- method: 'POST',
41
- headers: {
42
- 'Content-Type': 'application/json',
43
- 'x-goog-api-key': apiKey,
44
- },
45
- body,
46
- signal: controller.signal,
47
- });
48
- clearTimeout(timeoutId);
49
- if (response.status === 429) {
50
- console.log(`[INFO] Your configured model (${modelToTest}) was temporarily unavailable. Switched to ${fallbackModel} for this session.`);
51
- return fallbackModel;
52
- }
53
- // For any other case (success, other error codes), we stick to the original model.
54
- return currentConfiguredModel;
55
- }
56
- catch (_error) {
57
- clearTimeout(timeoutId);
58
- // On timeout or any other fetch error, stick to the original model.
59
- return currentConfiguredModel;
60
- }
61
- }
62
- //# sourceMappingURL=modelCheck.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"modelCheck.js","sourceRoot":"","sources":["../../../src/core/modelCheck.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,mBAAmB,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AACzD,OAAO,EACL,oBAAoB,EACpB,0BAA0B,GAC3B,MAAM,qBAAqB,CAAC;AAE7B;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,MAAc,EACd,sBAA8B,EAC9B,KAAc;IAEd,IAAI,sBAAsB,KAAK,oBAAoB,EAAE,CAAC;QACpD,2FAA2F;QAC3F,OAAO,sBAAsB,CAAC;IAChC,CAAC;IAED,MAAM,WAAW,GAAG,oBAAoB,CAAC;IACzC,MAAM,aAAa,GAAG,0BAA0B,CAAC;IACjD,MAAM,QAAQ,GAAG,2DAA2D,WAAW,kBAAkB,CAAC;IAC1G,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC;QAC1B,QAAQ,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC;QACzC,gBAAgB,EAAE;YAChB,eAAe,EAAE,CAAC;YAClB,WAAW,EAAE,CAAC;YACd,IAAI,EAAE,CAAC;YACP,cAAc,EAAE,EAAE,cAAc,EAAE,GAAG,EAAE,eAAe,EAAE,KAAK,EAAE;SAChE;KACF,CAAC,CAAC;IAEH,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;IACzC,MAAM,SAAS,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,EAAE,IAAI,CAAC,CAAC,CAAC,gCAAgC;IAE9F,IAAI,CAAC;QACH,IAAI,KAAK,EAAE,CAAC;YACV,mBAAmB,CAAC,IAAI,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC;QAC7C,CAAC;QACD,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,QAAQ,EAAE;YACrC,MAAM,EAAE,MAAM;YACd,OAAO,EAAE;gBACP,cAAc,EAAE,kBAAkB;gBAClC,gBAAgB,EAAE,MAAM;aACzB;YACD,IAAI;YACJ,MAAM,EAAE,UAAU,CAAC,MAAM;SAC1B,CAAC,CAAC;QAEH,YAAY,CAAC,SAAS,CAAC,CAAC;QAExB,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;YAC5B,OAAO,CAAC,GAAG,CACT,iCAAiC,WAAW,8CAA8C,aAAa,oBAAoB,CAC5H,CAAC;YACF,OAAO,aAAa,CAAC;QACvB,CAAC;QACD,mFAAmF;QACnF,OAAO,sBAAsB,CAAC;IAChC,CAAC;IAAC,OAAO,MAAM,EAAE,CAAC;QAChB,YAAY,CAAC,SAAS,CAAC,CAAC;QACxB,oEAAoE;QACpE,OAAO,sBAAsB,CAAC;IAChC,CAAC;AACH,CAAC"}
@@ -1,48 +0,0 @@
1
- /**
2
- * @license
3
- * Copyright 2025 Google LLC
4
- * SPDX-License-Identifier: Apache-2.0
5
- */
6
- import { Buffer } from 'buffer';
7
- import { HttpsProxyAgent } from 'https-proxy-agent';
8
- import { StartSessionEvent, EndSessionEvent, UserPromptEvent, ToolCallEvent, ApiRequestEvent, ApiResponseEvent, ApiErrorEvent, FlashFallbackEvent, LoopDetectedEvent, NextSpeakerCheckEvent, SlashCommandEvent, MalformedJsonResponseEvent } from '../types.js';
9
- import { Config } from '../../config/config.js';
10
- export interface LogResponse {
11
- nextRequestWaitMs?: number;
12
- }
13
- export interface LogEventEntry {
14
- event_time_ms: number;
15
- source_extension_json: string;
16
- }
17
- export declare class ClearcutLogger {
18
- private static instance;
19
- private config?;
20
- private readonly events;
21
- private last_flush_time;
22
- private flush_interval_ms;
23
- private max_events;
24
- private max_retry_events;
25
- private constructor();
26
- static getInstance(_config?: Config): ClearcutLogger | undefined;
27
- static clearInstance(): void;
28
- enqueueLogEvent(event: any): void;
29
- createLogEvent(name: string, data: object[]): object;
30
- flushIfNeeded(): void;
31
- flushToClearcut(): Promise<LogResponse>;
32
- decodeLogResponse(buf: Buffer): LogResponse | undefined;
33
- logStartSessionEvent(event: StartSessionEvent): void;
34
- logNewPromptEvent(event: UserPromptEvent): void;
35
- logToolCallEvent(event: ToolCallEvent): void;
36
- logApiRequestEvent(event: ApiRequestEvent): void;
37
- logApiResponseEvent(event: ApiResponseEvent): void;
38
- logApiErrorEvent(event: ApiErrorEvent): void;
39
- logFlashFallbackEvent(event: FlashFallbackEvent): void;
40
- logLoopDetectedEvent(event: LoopDetectedEvent): void;
41
- logNextSpeakerCheck(event: NextSpeakerCheckEvent): void;
42
- logSlashCommandEvent(event: SlashCommandEvent): void;
43
- logMalformedJsonResponseEvent(event: MalformedJsonResponseEvent): void;
44
- logEndSessionEvent(event: EndSessionEvent): void;
45
- getProxyAgent(): HttpsProxyAgent<string> | undefined;
46
- private requeueFailedEvents;
47
- shutdown(): void;
48
- }
@@ -1,577 +0,0 @@
1
- /**
2
- * @license
3
- * Copyright 2025 Google LLC
4
- * SPDX-License-Identifier: Apache-2.0
5
- */
6
- // TELEMETRY REMOVED: This entire file has been disabled to remove Google data collection
7
- import { Buffer } from 'buffer';
8
- import * as https from 'https';
9
- import { HttpsProxyAgent } from 'https-proxy-agent';
10
- import { EndSessionEvent, } from '../types.js';
11
- import { EventMetadataKey } from './event-metadata-key.js';
12
- import { safeJsonStringify } from '../../utils/safeJsonStringify.js';
13
- import { getCachedGoogleAccount, getLifetimeGoogleAccounts, } from '../../utils/user_account.js';
14
- import { retryWithBackoff } from '../../utils/retry.js';
15
- import { getInstallationId } from '../../utils/user_id.js';
16
- const start_session_event_name = 'start_session';
17
- const new_prompt_event_name = 'new_prompt';
18
- const tool_call_event_name = 'tool_call';
19
- const api_request_event_name = 'api_request';
20
- const api_response_event_name = 'api_response';
21
- const api_error_event_name = 'api_error';
22
- const end_session_event_name = 'end_session';
23
- const flash_fallback_event_name = 'flash_fallback';
24
- const loop_detected_event_name = 'loop_detected';
25
- const next_speaker_check_event_name = 'next_speaker_check';
26
- const slash_command_event_name = 'slash_command';
27
- const malformed_json_response_event_name = 'malformed_json_response';
28
- // TELEMETRY REMOVED: This class has been modified to disable all Google data collection
29
- // Singleton class for batch posting log events to Clearcut. When a new event comes in, the elapsed time
30
- // is checked and events are flushed to Clearcut if at least a minute has passed since the last flush.
31
- export class ClearcutLogger {
32
- static instance;
33
- config;
34
- // Telemetry is disabled - this is just a stub to maintain API compatibility
35
- events = {
36
- items: [],
37
- toArray() {
38
- return this.items;
39
- },
40
- get size() {
41
- return this.items.length;
42
- },
43
- push(item) {
44
- this.items.push(item);
45
- if (this.items.length > 1000) {
46
- // max_events
47
- this.items.shift();
48
- }
49
- },
50
- splice(start, deleteCount) {
51
- return this.items.splice(start, deleteCount);
52
- },
53
- unshift(item) {
54
- this.items.unshift(item);
55
- },
56
- };
57
- last_flush_time = Date.now();
58
- flush_interval_ms = 1000 * 60; // Wait at least a minute before flushing events.
59
- max_events = 1000; // Maximum number of events to keep in memory
60
- max_retry_events = 100; // Maximum number of events to retry
61
- constructor(config) {
62
- this.config = config;
63
- }
64
- static getInstance(_config) {
65
- // TELEMETRY REMOVED: Always return undefined to disable telemetry
66
- return undefined;
67
- /*
68
- if (config === undefined || !config?.getUsageStatisticsEnabled())
69
- return undefined;
70
- if (!ClearcutLogger.instance) {
71
- ClearcutLogger.instance = new ClearcutLogger(config);
72
- }
73
- return ClearcutLogger.instance;
74
- */
75
- }
76
- static clearInstance() {
77
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
78
- delete ClearcutLogger.instance;
79
- }
80
- // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Clearcut expects this format.
81
- enqueueLogEvent(event) {
82
- this.events.push([
83
- {
84
- event_time_ms: Date.now(),
85
- source_extension_json: safeJsonStringify(event),
86
- },
87
- ]);
88
- }
89
- createLogEvent(name, data) {
90
- const email = getCachedGoogleAccount();
91
- const totalAccounts = getLifetimeGoogleAccounts();
92
- data.push({
93
- gemini_cli_key: EventMetadataKey.GEMINI_CLI_GOOGLE_ACCOUNTS_COUNT,
94
- value: totalAccounts.toString(),
95
- });
96
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
97
- const logEvent = {
98
- console_type: 'GEMINI_CLI',
99
- application: 102,
100
- event_name: name,
101
- event_metadata: [data],
102
- };
103
- // Should log either email or install ID, not both. See go/cloudmill-1p-oss-instrumentation#define-sessionable-id
104
- if (email) {
105
- logEvent.client_email = email;
106
- }
107
- else {
108
- logEvent.client_install_id = getInstallationId();
109
- }
110
- return logEvent;
111
- }
112
- flushIfNeeded() {
113
- if (Date.now() - this.last_flush_time < this.flush_interval_ms) {
114
- return;
115
- }
116
- this.flushToClearcut().catch((error) => {
117
- console.debug('Error flushing to Clearcut:', error);
118
- });
119
- }
120
- async flushToClearcut() {
121
- // TELEMETRY REMOVED: This method includes retry logic improvements but telemetry remains disabled
122
- if (this.config?.getDebugMode()) {
123
- console.log('Flushing log events to Clearcut.');
124
- }
125
- const eventsToSend = [...this.events.items];
126
- if (eventsToSend.length === 0) {
127
- return {};
128
- }
129
- const flushFn = () => new Promise((resolve, reject) => {
130
- const request = [
131
- {
132
- log_source_name: 'CONCORD',
133
- request_time_ms: Date.now(),
134
- log_event: eventsToSend,
135
- },
136
- ];
137
- const body = safeJsonStringify(request);
138
- const options = {
139
- hostname: 'play.googleapis.com',
140
- path: '/log',
141
- method: 'POST',
142
- headers: { 'Content-Length': Buffer.byteLength(body) },
143
- };
144
- const bufs = [];
145
- const req = https.request({
146
- ...options,
147
- agent: this.getProxyAgent(),
148
- }, (res) => {
149
- if (res.statusCode &&
150
- (res.statusCode < 200 || res.statusCode >= 300)) {
151
- const err = new Error(`Request failed with status ${res.statusCode}`);
152
- err.status = res.statusCode;
153
- res.resume();
154
- return reject(err);
155
- }
156
- res.on('data', (buf) => bufs.push(buf));
157
- res.on('end', () => resolve(Buffer.concat(bufs)));
158
- });
159
- req.on('error', reject);
160
- req.end(body);
161
- });
162
- try {
163
- const responseBuffer = await retryWithBackoff(flushFn, {
164
- maxAttempts: 3,
165
- initialDelayMs: 200,
166
- shouldRetry: (err) => {
167
- if (!(err instanceof Error))
168
- return false;
169
- const status = err.status;
170
- // If status is not available, it's likely a network error
171
- if (status === undefined)
172
- return true;
173
- // Retry on 429 (Too many Requests) and 5xx server errors.
174
- return status === 429 || (status >= 500 && status < 600);
175
- },
176
- });
177
- this.events.splice(0, eventsToSend.length);
178
- this.last_flush_time = Date.now();
179
- return this.decodeLogResponse(responseBuffer) || {};
180
- }
181
- catch (error) {
182
- if (this.config?.getDebugMode()) {
183
- console.error('Clearcut flush failed after multiple retries.', error);
184
- }
185
- return {};
186
- }
187
- }
188
- // Visible for testing. Decodes protobuf-encoded response from Clearcut server.
189
- decodeLogResponse(buf) {
190
- // TODO(obrienowen): return specific errors to facilitate debugging.
191
- if (buf.length < 1) {
192
- return undefined;
193
- }
194
- // The first byte of the buffer is `field<<3 | type`. We're looking for field
195
- // 1, with type varint, represented by type=0. If the first byte isn't 8, that
196
- // means field 1 is missing or the message is corrupted. Either way, we return
197
- // undefined.
198
- if (buf.readUInt8(0) !== 8) {
199
- return undefined;
200
- }
201
- let ms = BigInt(0);
202
- let cont = true;
203
- // In each byte, the most significant bit is the continuation bit. If it's
204
- // set, we keep going. The lowest 7 bits, are data bits. They are concatenated
205
- // in reverse order to form the final number.
206
- for (let i = 1; cont && i < buf.length; i++) {
207
- const byte = buf.readUInt8(i);
208
- ms |= BigInt(byte & 0x7f) << BigInt(7 * (i - 1));
209
- cont = (byte & 0x80) !== 0;
210
- }
211
- if (cont) {
212
- // We have fallen off the buffer without seeing a terminating byte. The
213
- // message is corrupted.
214
- return undefined;
215
- }
216
- const returnVal = {
217
- nextRequestWaitMs: Number(ms),
218
- };
219
- return returnVal;
220
- }
221
- logStartSessionEvent(event) {
222
- const surface = process.env.SURFACE || 'SURFACE_NOT_SET';
223
- const data = [
224
- {
225
- gemini_cli_key: EventMetadataKey.GEMINI_CLI_START_SESSION_MODEL,
226
- value: event.model,
227
- },
228
- {
229
- gemini_cli_key: EventMetadataKey.GEMINI_CLI_SESSION_ID,
230
- value: this.config?.getSessionId() ?? '',
231
- },
232
- {
233
- gemini_cli_key: EventMetadataKey.GEMINI_CLI_START_SESSION_EMBEDDING_MODEL,
234
- value: event.embedding_model,
235
- },
236
- {
237
- gemini_cli_key: EventMetadataKey.GEMINI_CLI_START_SESSION_SANDBOX,
238
- value: event.sandbox_enabled.toString(),
239
- },
240
- {
241
- gemini_cli_key: EventMetadataKey.GEMINI_CLI_START_SESSION_CORE_TOOLS,
242
- value: event.core_tools_enabled,
243
- },
244
- {
245
- gemini_cli_key: EventMetadataKey.GEMINI_CLI_START_SESSION_APPROVAL_MODE,
246
- value: event.approval_mode,
247
- },
248
- {
249
- gemini_cli_key: EventMetadataKey.GEMINI_CLI_START_SESSION_API_KEY_ENABLED,
250
- value: event.api_key_enabled.toString(),
251
- },
252
- {
253
- gemini_cli_key: EventMetadataKey.GEMINI_CLI_START_SESSION_VERTEX_API_ENABLED,
254
- value: event.vertex_ai_enabled.toString(),
255
- },
256
- {
257
- gemini_cli_key: EventMetadataKey.GEMINI_CLI_START_SESSION_DEBUG_MODE_ENABLED,
258
- value: event.debug_enabled.toString(),
259
- },
260
- {
261
- gemini_cli_key: EventMetadataKey.GEMINI_CLI_START_SESSION_VERTEX_API_ENABLED,
262
- value: event.vertex_ai_enabled.toString(),
263
- },
264
- {
265
- gemini_cli_key: EventMetadataKey.GEMINI_CLI_START_SESSION_MCP_SERVERS,
266
- value: event.mcp_servers,
267
- },
268
- {
269
- gemini_cli_key: EventMetadataKey.GEMINI_CLI_START_SESSION_VERTEX_API_ENABLED,
270
- value: event.vertex_ai_enabled.toString(),
271
- },
272
- {
273
- gemini_cli_key: EventMetadataKey.GEMINI_CLI_START_SESSION_TELEMETRY_ENABLED,
274
- value: event.telemetry_enabled.toString(),
275
- },
276
- {
277
- gemini_cli_key: EventMetadataKey.GEMINI_CLI_START_SESSION_TELEMETRY_LOG_USER_PROMPTS_ENABLED,
278
- value: event.telemetry_log_user_prompts_enabled.toString(),
279
- },
280
- {
281
- gemini_cli_key: EventMetadataKey.GEMINI_CLI_SURFACE,
282
- value: surface,
283
- },
284
- ];
285
- // Flush start event immediately
286
- this.enqueueLogEvent(this.createLogEvent(start_session_event_name, data));
287
- this.flushToClearcut().catch((error) => {
288
- console.debug('Error flushing to Clearcut:', error);
289
- });
290
- }
291
- logNewPromptEvent(event) {
292
- const data = [
293
- {
294
- gemini_cli_key: EventMetadataKey.GEMINI_CLI_USER_PROMPT_LENGTH,
295
- value: JSON.stringify(event.prompt_length),
296
- },
297
- {
298
- gemini_cli_key: EventMetadataKey.GEMINI_CLI_SESSION_ID,
299
- value: this.config?.getSessionId() ?? '',
300
- },
301
- {
302
- gemini_cli_key: EventMetadataKey.GEMINI_CLI_PROMPT_ID,
303
- value: JSON.stringify(event.prompt_id),
304
- },
305
- {
306
- gemini_cli_key: EventMetadataKey.GEMINI_CLI_AUTH_TYPE,
307
- value: JSON.stringify(event.auth_type),
308
- },
309
- ];
310
- this.enqueueLogEvent(this.createLogEvent(new_prompt_event_name, data));
311
- this.flushIfNeeded();
312
- }
313
- logToolCallEvent(event) {
314
- const data = [
315
- {
316
- gemini_cli_key: EventMetadataKey.GEMINI_CLI_TOOL_CALL_NAME,
317
- value: JSON.stringify(event.function_name),
318
- },
319
- {
320
- gemini_cli_key: EventMetadataKey.GEMINI_CLI_PROMPT_ID,
321
- value: JSON.stringify(event.prompt_id),
322
- },
323
- {
324
- gemini_cli_key: EventMetadataKey.GEMINI_CLI_TOOL_CALL_DECISION,
325
- value: JSON.stringify(event.decision),
326
- },
327
- {
328
- gemini_cli_key: EventMetadataKey.GEMINI_CLI_TOOL_CALL_SUCCESS,
329
- value: JSON.stringify(event.success),
330
- },
331
- {
332
- gemini_cli_key: EventMetadataKey.GEMINI_CLI_TOOL_CALL_DURATION_MS,
333
- value: JSON.stringify(event.duration_ms),
334
- },
335
- {
336
- gemini_cli_key: EventMetadataKey.GEMINI_CLI_TOOL_ERROR_MESSAGE,
337
- value: JSON.stringify(event.error),
338
- },
339
- {
340
- gemini_cli_key: EventMetadataKey.GEMINI_CLI_TOOL_CALL_ERROR_TYPE,
341
- value: JSON.stringify(event.error_type),
342
- },
343
- ];
344
- if (event.metadata) {
345
- const metadataMapping = {
346
- ai_added_lines: EventMetadataKey.GEMINI_CLI_AI_ADDED_LINES,
347
- ai_removed_lines: EventMetadataKey.GEMINI_CLI_AI_REMOVED_LINES,
348
- user_added_lines: EventMetadataKey.GEMINI_CLI_USER_ADDED_LINES,
349
- user_removed_lines: EventMetadataKey.GEMINI_CLI_USER_REMOVED_LINES,
350
- };
351
- for (const [key, gemini_cli_key] of Object.entries(metadataMapping)) {
352
- if (event.metadata[key] !== undefined) {
353
- data.push({
354
- gemini_cli_key,
355
- value: JSON.stringify(event.metadata[key]),
356
- });
357
- }
358
- }
359
- }
360
- const logEvent = this.createLogEvent(tool_call_event_name, data);
361
- this.enqueueLogEvent(logEvent);
362
- this.flushIfNeeded();
363
- }
364
- logApiRequestEvent(event) {
365
- const data = [
366
- {
367
- gemini_cli_key: EventMetadataKey.GEMINI_CLI_API_REQUEST_MODEL,
368
- value: JSON.stringify(event.model),
369
- },
370
- {
371
- gemini_cli_key: EventMetadataKey.GEMINI_CLI_PROMPT_ID,
372
- value: JSON.stringify(event.prompt_id),
373
- },
374
- ];
375
- this.enqueueLogEvent(this.createLogEvent(api_request_event_name, data));
376
- this.flushIfNeeded();
377
- }
378
- logApiResponseEvent(event) {
379
- const data = [
380
- {
381
- gemini_cli_key: EventMetadataKey.GEMINI_CLI_API_RESPONSE_MODEL,
382
- value: JSON.stringify(event.model),
383
- },
384
- {
385
- gemini_cli_key: EventMetadataKey.GEMINI_CLI_PROMPT_ID,
386
- value: JSON.stringify(event.prompt_id),
387
- },
388
- {
389
- gemini_cli_key: EventMetadataKey.GEMINI_CLI_API_RESPONSE_STATUS_CODE,
390
- value: JSON.stringify(event.status_code),
391
- },
392
- {
393
- gemini_cli_key: EventMetadataKey.GEMINI_CLI_API_RESPONSE_DURATION_MS,
394
- value: JSON.stringify(event.duration_ms),
395
- },
396
- {
397
- gemini_cli_key: EventMetadataKey.GEMINI_CLI_API_ERROR_MESSAGE,
398
- value: JSON.stringify(event.error),
399
- },
400
- {
401
- gemini_cli_key: EventMetadataKey.GEMINI_CLI_API_RESPONSE_INPUT_TOKEN_COUNT,
402
- value: JSON.stringify(event.input_token_count),
403
- },
404
- {
405
- gemini_cli_key: EventMetadataKey.GEMINI_CLI_API_RESPONSE_OUTPUT_TOKEN_COUNT,
406
- value: JSON.stringify(event.output_token_count),
407
- },
408
- {
409
- gemini_cli_key: EventMetadataKey.GEMINI_CLI_API_RESPONSE_CACHED_TOKEN_COUNT,
410
- value: JSON.stringify(event.cached_content_token_count),
411
- },
412
- {
413
- gemini_cli_key: EventMetadataKey.GEMINI_CLI_API_RESPONSE_THINKING_TOKEN_COUNT,
414
- value: JSON.stringify(event.thoughts_token_count),
415
- },
416
- {
417
- gemini_cli_key: EventMetadataKey.GEMINI_CLI_API_RESPONSE_TOOL_TOKEN_COUNT,
418
- value: JSON.stringify(event.tool_token_count),
419
- },
420
- {
421
- gemini_cli_key: EventMetadataKey.GEMINI_CLI_AUTH_TYPE,
422
- value: JSON.stringify(event.auth_type),
423
- },
424
- ];
425
- this.enqueueLogEvent(this.createLogEvent(api_response_event_name, data));
426
- this.flushIfNeeded();
427
- }
428
- logApiErrorEvent(event) {
429
- const data = [
430
- {
431
- gemini_cli_key: EventMetadataKey.GEMINI_CLI_API_ERROR_MODEL,
432
- value: JSON.stringify(event.model),
433
- },
434
- {
435
- gemini_cli_key: EventMetadataKey.GEMINI_CLI_PROMPT_ID,
436
- value: JSON.stringify(event.prompt_id),
437
- },
438
- {
439
- gemini_cli_key: EventMetadataKey.GEMINI_CLI_API_ERROR_TYPE,
440
- value: JSON.stringify(event.error_type),
441
- },
442
- {
443
- gemini_cli_key: EventMetadataKey.GEMINI_CLI_API_ERROR_STATUS_CODE,
444
- value: JSON.stringify(event.status_code),
445
- },
446
- {
447
- gemini_cli_key: EventMetadataKey.GEMINI_CLI_API_ERROR_DURATION_MS,
448
- value: JSON.stringify(event.duration_ms),
449
- },
450
- {
451
- gemini_cli_key: EventMetadataKey.GEMINI_CLI_AUTH_TYPE,
452
- value: JSON.stringify(event.auth_type),
453
- },
454
- ];
455
- this.enqueueLogEvent(this.createLogEvent(api_error_event_name, data));
456
- this.flushIfNeeded();
457
- }
458
- logFlashFallbackEvent(event) {
459
- const data = [
460
- {
461
- gemini_cli_key: EventMetadataKey.GEMINI_CLI_AUTH_TYPE,
462
- value: JSON.stringify(event.auth_type),
463
- },
464
- {
465
- gemini_cli_key: EventMetadataKey.GEMINI_CLI_SESSION_ID,
466
- value: this.config?.getSessionId() ?? '',
467
- },
468
- ];
469
- this.enqueueLogEvent(this.createLogEvent(flash_fallback_event_name, data));
470
- this.flushToClearcut().catch((error) => {
471
- console.debug('Error flushing to Clearcut:', error);
472
- });
473
- }
474
- logLoopDetectedEvent(event) {
475
- const data = [
476
- {
477
- gemini_cli_key: EventMetadataKey.GEMINI_CLI_PROMPT_ID,
478
- value: JSON.stringify(event.prompt_id),
479
- },
480
- {
481
- gemini_cli_key: EventMetadataKey.GEMINI_CLI_LOOP_DETECTED_TYPE,
482
- value: JSON.stringify(event.loop_type),
483
- },
484
- ];
485
- this.enqueueLogEvent(this.createLogEvent(loop_detected_event_name, data));
486
- this.flushIfNeeded();
487
- }
488
- logNextSpeakerCheck(event) {
489
- const data = [
490
- {
491
- gemini_cli_key: EventMetadataKey.GEMINI_CLI_PROMPT_ID,
492
- value: JSON.stringify(event.prompt_id),
493
- },
494
- {
495
- gemini_cli_key: EventMetadataKey.GEMINI_CLI_RESPONSE_FINISH_REASON,
496
- value: JSON.stringify(event.finish_reason),
497
- },
498
- {
499
- gemini_cli_key: EventMetadataKey.GEMINI_CLI_NEXT_SPEAKER_CHECK_RESULT,
500
- value: JSON.stringify(event.result),
501
- },
502
- {
503
- gemini_cli_key: EventMetadataKey.GEMINI_CLI_SESSION_ID,
504
- value: this.config?.getSessionId() ?? '',
505
- },
506
- ];
507
- this.enqueueLogEvent(this.createLogEvent(next_speaker_check_event_name, data));
508
- this.flushIfNeeded();
509
- }
510
- logSlashCommandEvent(event) {
511
- const data = [
512
- {
513
- gemini_cli_key: EventMetadataKey.GEMINI_CLI_SLASH_COMMAND_NAME,
514
- value: JSON.stringify(event.command),
515
- },
516
- ];
517
- if (event.subcommand) {
518
- data.push({
519
- gemini_cli_key: EventMetadataKey.GEMINI_CLI_SLASH_COMMAND_SUBCOMMAND,
520
- value: JSON.stringify(event.subcommand),
521
- });
522
- }
523
- this.enqueueLogEvent(this.createLogEvent(slash_command_event_name, data));
524
- this.flushIfNeeded();
525
- }
526
- logMalformedJsonResponseEvent(event) {
527
- const data = [
528
- {
529
- gemini_cli_key: EventMetadataKey.GEMINI_CLI_MALFORMED_JSON_RESPONSE_MODEL,
530
- value: JSON.stringify(event.model),
531
- },
532
- ];
533
- this.enqueueLogEvent(this.createLogEvent(malformed_json_response_event_name, data));
534
- this.flushIfNeeded();
535
- }
536
- logEndSessionEvent(event) {
537
- const data = [
538
- {
539
- gemini_cli_key: EventMetadataKey.GEMINI_CLI_SESSION_ID,
540
- value: event?.session_id?.toString() ?? '',
541
- },
542
- ];
543
- // Flush immediately on session end.
544
- this.enqueueLogEvent(this.createLogEvent(end_session_event_name, data));
545
- this.flushToClearcut().catch((error) => {
546
- console.debug('Error flushing to Clearcut:', error);
547
- });
548
- }
549
- getProxyAgent() {
550
- const proxyUrl = this.config?.getProxy();
551
- if (!proxyUrl)
552
- return undefined;
553
- // undici which is widely used in the repo can only support http & https proxy protocol,
554
- // https://github.com/nodejs/undici/issues/2224
555
- if (proxyUrl.startsWith('http')) {
556
- return new HttpsProxyAgent(proxyUrl);
557
- }
558
- else {
559
- throw new Error('Unsupported proxy type');
560
- }
561
- }
562
- requeueFailedEvents(failedEvents) {
563
- const availableSpace = this.max_events - this.events.size;
564
- const eventsToRequeue = Math.min(failedEvents.length, availableSpace, this.max_retry_events);
565
- if (eventsToRequeue > 0) {
566
- const startIndex = Math.max(0, failedEvents.length - eventsToRequeue);
567
- for (let i = failedEvents.length - 1; i >= startIndex; i--) {
568
- this.events.unshift(failedEvents[i]);
569
- }
570
- }
571
- }
572
- shutdown() {
573
- const event = new EndSessionEvent(this.config);
574
- this.logEndSessionEvent(event);
575
- }
576
- }
577
- //# sourceMappingURL=clearcut-logger.js.map