@vybestack/llxprt-code-core 0.1.21 → 0.1.23

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 (199) hide show
  1. package/dist/src/auth/types.d.ts +4 -4
  2. package/dist/src/code_assist/codeAssist.d.ts +1 -1
  3. package/dist/src/code_assist/codeAssist.js +5 -2
  4. package/dist/src/code_assist/codeAssist.js.map +1 -1
  5. package/dist/src/code_assist/converter.d.ts +2 -1
  6. package/dist/src/code_assist/converter.js +6 -4
  7. package/dist/src/code_assist/converter.js.map +1 -1
  8. package/dist/src/code_assist/oauth2.d.ts +1 -0
  9. package/dist/src/code_assist/oauth2.js +32 -15
  10. package/dist/src/code_assist/oauth2.js.map +1 -1
  11. package/dist/src/code_assist/server.d.ts +1 -2
  12. package/dist/src/code_assist/server.js +10 -5
  13. package/dist/src/code_assist/server.js.map +1 -1
  14. package/dist/src/code_assist/setup.js +2 -1
  15. package/dist/src/code_assist/setup.js.map +1 -1
  16. package/dist/src/config/config.d.ts +14 -1
  17. package/dist/src/config/config.js +28 -3
  18. package/dist/src/config/config.js.map +1 -1
  19. package/dist/src/core/client.js +13 -4
  20. package/dist/src/core/client.js.map +1 -1
  21. package/dist/src/core/coreToolScheduler.d.ts +2 -1
  22. package/dist/src/core/coreToolScheduler.js +23 -0
  23. package/dist/src/core/coreToolScheduler.js.map +1 -1
  24. package/dist/src/core/geminiChat.js +73 -17
  25. package/dist/src/core/geminiChat.js.map +1 -1
  26. package/dist/src/core/loggingContentGenerator.d.ts +1 -5
  27. package/dist/src/core/loggingContentGenerator.js +4 -6
  28. package/dist/src/core/loggingContentGenerator.js.map +1 -1
  29. package/dist/src/core/nonInteractiveToolExecutor.d.ts +2 -2
  30. package/dist/src/core/nonInteractiveToolExecutor.js +13 -9
  31. package/dist/src/core/nonInteractiveToolExecutor.js.map +1 -1
  32. package/dist/src/core/subagent.js +5 -5
  33. package/dist/src/core/subagent.js.map +1 -1
  34. package/dist/src/debug/ConfigurationManager.d.ts +28 -0
  35. package/dist/src/debug/ConfigurationManager.js +211 -0
  36. package/dist/src/debug/ConfigurationManager.js.map +1 -0
  37. package/dist/src/debug/DebugLogger.d.ts +26 -0
  38. package/dist/src/debug/DebugLogger.js +230 -0
  39. package/dist/src/debug/DebugLogger.js.map +1 -0
  40. package/dist/src/debug/FileOutput.d.ts +23 -0
  41. package/dist/src/debug/FileOutput.js +144 -0
  42. package/dist/src/debug/FileOutput.js.map +1 -0
  43. package/dist/src/debug/MockConfigurationManager.d.ts +28 -0
  44. package/dist/src/debug/MockConfigurationManager.js +45 -0
  45. package/dist/src/debug/MockConfigurationManager.js.map +1 -0
  46. package/dist/src/debug/MockFileOutput.d.ts +20 -0
  47. package/dist/src/debug/MockFileOutput.js +25 -0
  48. package/dist/src/debug/MockFileOutput.js.map +1 -0
  49. package/dist/src/debug/index.d.ts +8 -0
  50. package/dist/src/debug/index.js +9 -0
  51. package/dist/src/debug/index.js.map +1 -0
  52. package/dist/src/debug/types.d.ts +23 -0
  53. package/dist/src/debug/types.js +2 -0
  54. package/dist/src/debug/types.js.map +1 -0
  55. package/dist/src/ide/ide-client.d.ts +4 -0
  56. package/dist/src/ide/ide-client.js +41 -2
  57. package/dist/src/ide/ide-client.js.map +1 -1
  58. package/dist/src/ide/ide-installer.js +17 -4
  59. package/dist/src/ide/ide-installer.js.map +1 -1
  60. package/dist/src/ide/process-utils.d.ts +10 -5
  61. package/dist/src/ide/process-utils.js +113 -30
  62. package/dist/src/ide/process-utils.js.map +1 -1
  63. package/dist/src/index.d.ts +5 -0
  64. package/dist/src/index.js +4 -0
  65. package/dist/src/index.js.map +1 -1
  66. package/dist/src/mcp/oauth-provider.js +176 -58
  67. package/dist/src/mcp/oauth-provider.js.map +1 -1
  68. package/dist/src/mcp/oauth-utils.d.ts +3 -1
  69. package/dist/src/mcp/oauth-utils.js +52 -22
  70. package/dist/src/mcp/oauth-utils.js.map +1 -1
  71. package/dist/src/prompt-config/defaults/core.md +34 -230
  72. package/dist/src/prompt-config/defaults/tools/read-file.md +1 -1
  73. package/dist/src/providers/BaseProvider.js +13 -2
  74. package/dist/src/providers/BaseProvider.js.map +1 -1
  75. package/dist/src/providers/anthropic/AnthropicProvider.d.ts +1 -0
  76. package/dist/src/providers/anthropic/AnthropicProvider.js +165 -127
  77. package/dist/src/providers/anthropic/AnthropicProvider.js.map +1 -1
  78. package/dist/src/providers/gemini/GeminiProvider.d.ts +1 -0
  79. package/dist/src/providers/gemini/GeminiProvider.js +29 -53
  80. package/dist/src/providers/gemini/GeminiProvider.js.map +1 -1
  81. package/dist/src/providers/openai/OpenAIProvider.d.ts +9 -0
  82. package/dist/src/providers/openai/OpenAIProvider.js +671 -128
  83. package/dist/src/providers/openai/OpenAIProvider.js.map +1 -1
  84. package/dist/src/providers/openai/buildResponsesRequest.js +9 -6
  85. package/dist/src/providers/openai/buildResponsesRequest.js.map +1 -1
  86. package/dist/src/providers/openai/getOpenAIProviderInfo.js +8 -3
  87. package/dist/src/providers/openai/getOpenAIProviderInfo.js.map +1 -1
  88. package/dist/src/providers/openai/parseResponsesStream.js +13 -4
  89. package/dist/src/providers/openai/parseResponsesStream.js.map +1 -1
  90. package/dist/src/providers/openai/syntheticToolResponses.d.ts +0 -9
  91. package/dist/src/providers/openai/syntheticToolResponses.js +87 -16
  92. package/dist/src/providers/openai/syntheticToolResponses.js.map +1 -1
  93. package/dist/src/services/fileSystemService.d.ts +31 -0
  94. package/dist/src/services/fileSystemService.js +18 -0
  95. package/dist/src/services/fileSystemService.js.map +1 -0
  96. package/dist/src/services/loopDetectionService.d.ts +5 -0
  97. package/dist/src/services/loopDetectionService.js +89 -1
  98. package/dist/src/services/loopDetectionService.js.map +1 -1
  99. package/dist/src/services/shellExecutionService.d.ts +8 -6
  100. package/dist/src/services/shellExecutionService.js +297 -133
  101. package/dist/src/services/shellExecutionService.js.map +1 -1
  102. package/dist/src/telemetry/index.d.ts +2 -2
  103. package/dist/src/telemetry/index.js +2 -2
  104. package/dist/src/telemetry/index.js.map +1 -1
  105. package/dist/src/telemetry/loggers.d.ts +2 -1
  106. package/dist/src/telemetry/loggers.js +15 -1
  107. package/dist/src/telemetry/loggers.js.map +1 -1
  108. package/dist/src/telemetry/metrics.d.ts +1 -1
  109. package/dist/src/telemetry/metrics.js +2 -1
  110. package/dist/src/telemetry/metrics.js.map +1 -1
  111. package/dist/src/telemetry/sdk.js +3 -3
  112. package/dist/src/telemetry/sdk.js.map +1 -1
  113. package/dist/src/telemetry/types.d.ts +9 -1
  114. package/dist/src/telemetry/types.js +32 -0
  115. package/dist/src/telemetry/types.js.map +1 -1
  116. package/dist/src/telemetry/uiTelemetry.d.ts +4 -0
  117. package/dist/src/telemetry/uiTelemetry.js +16 -1
  118. package/dist/src/telemetry/uiTelemetry.js.map +1 -1
  119. package/dist/src/test-utils/tools.d.ts +29 -8
  120. package/dist/src/test-utils/tools.js +79 -15
  121. package/dist/src/test-utils/tools.js.map +1 -1
  122. package/dist/src/tools/ToolFormatter.d.ts +1 -0
  123. package/dist/src/tools/ToolFormatter.js +90 -9
  124. package/dist/src/tools/ToolFormatter.js.map +1 -1
  125. package/dist/src/tools/edit.d.ts +2 -2
  126. package/dist/src/tools/edit.js +60 -28
  127. package/dist/src/tools/edit.js.map +1 -1
  128. package/dist/src/tools/glob.d.ts +1 -1
  129. package/dist/src/tools/glob.js +8 -8
  130. package/dist/src/tools/glob.js.map +1 -1
  131. package/dist/src/tools/grep.d.ts +1 -1
  132. package/dist/src/tools/grep.js +1 -6
  133. package/dist/src/tools/grep.js.map +1 -1
  134. package/dist/src/tools/ls.d.ts +1 -1
  135. package/dist/src/tools/ls.js +1 -6
  136. package/dist/src/tools/ls.js.map +1 -1
  137. package/dist/src/tools/mcp-client-manager.d.ts +38 -0
  138. package/dist/src/tools/mcp-client-manager.js +74 -0
  139. package/dist/src/tools/mcp-client-manager.js.map +1 -0
  140. package/dist/src/tools/mcp-client.d.ts +43 -0
  141. package/dist/src/tools/mcp-client.js +163 -32
  142. package/dist/src/tools/mcp-client.js.map +1 -1
  143. package/dist/src/tools/memoryTool.d.ts +1 -1
  144. package/dist/src/tools/memoryTool.js +1 -6
  145. package/dist/src/tools/memoryTool.js.map +1 -1
  146. package/dist/src/tools/read-file.d.ts +1 -1
  147. package/dist/src/tools/read-file.js +5 -7
  148. package/dist/src/tools/read-file.js.map +1 -1
  149. package/dist/src/tools/read-many-files.d.ts +0 -1
  150. package/dist/src/tools/read-many-files.js +16 -11
  151. package/dist/src/tools/read-many-files.js.map +1 -1
  152. package/dist/src/tools/shell.d.ts +1 -1
  153. package/dist/src/tools/shell.js +57 -36
  154. package/dist/src/tools/shell.js.map +1 -1
  155. package/dist/src/tools/tool-error.d.ts +1 -0
  156. package/dist/src/tools/tool-error.js +1 -0
  157. package/dist/src/tools/tool-error.js.map +1 -1
  158. package/dist/src/tools/tool-registry.d.ts +5 -0
  159. package/dist/src/tools/tool-registry.js +13 -4
  160. package/dist/src/tools/tool-registry.js.map +1 -1
  161. package/dist/src/tools/tools.d.ts +56 -76
  162. package/dist/src/tools/tools.js +119 -106
  163. package/dist/src/tools/tools.js.map +1 -1
  164. package/dist/src/tools/web-fetch.d.ts +1 -1
  165. package/dist/src/tools/web-fetch.js +1 -6
  166. package/dist/src/tools/web-fetch.js.map +1 -1
  167. package/dist/src/tools/web-search.d.ts +6 -1
  168. package/dist/src/tools/web-search.js +6 -6
  169. package/dist/src/tools/web-search.js.map +1 -1
  170. package/dist/src/tools/write-file.d.ts +1 -1
  171. package/dist/src/tools/write-file.js +7 -8
  172. package/dist/src/tools/write-file.js.map +1 -1
  173. package/dist/src/utils/environmentContext.js +2 -2
  174. package/dist/src/utils/environmentContext.js.map +1 -1
  175. package/dist/src/utils/errorReporting.js +1 -1
  176. package/dist/src/utils/fileUtils.d.ts +2 -1
  177. package/dist/src/utils/fileUtils.js +3 -3
  178. package/dist/src/utils/fileUtils.js.map +1 -1
  179. package/dist/src/utils/filesearch/crawler.d.ts +15 -0
  180. package/dist/src/utils/filesearch/crawler.js +50 -0
  181. package/dist/src/utils/filesearch/crawler.js.map +1 -0
  182. package/dist/src/utils/filesearch/fileSearch.d.ts +9 -53
  183. package/dist/src/utils/filesearch/fileSearch.js +62 -117
  184. package/dist/src/utils/filesearch/fileSearch.js.map +1 -1
  185. package/dist/src/utils/filesearch/ignore.d.ts +7 -0
  186. package/dist/src/utils/filesearch/ignore.js +25 -0
  187. package/dist/src/utils/filesearch/ignore.js.map +1 -1
  188. package/dist/src/utils/getPty.d.ts +19 -0
  189. package/dist/src/utils/getPty.js +23 -0
  190. package/dist/src/utils/getPty.js.map +1 -0
  191. package/dist/src/utils/shell-utils.d.ts +39 -0
  192. package/dist/src/utils/shell-utils.js +68 -0
  193. package/dist/src/utils/shell-utils.js.map +1 -1
  194. package/dist/src/utils/user_account.js +58 -53
  195. package/dist/src/utils/user_account.js.map +1 -1
  196. package/dist/src/utils/workspaceContext.d.ts +9 -0
  197. package/dist/src/utils/workspaceContext.js +37 -3
  198. package/dist/src/utils/workspaceContext.js.map +1 -1
  199. package/package.json +22 -7
@@ -0,0 +1,211 @@
1
+ /**
2
+ * @plan:PLAN-20250120-DEBUGLOGGING.P08
3
+ * @requirement REQ-003,REQ-007
4
+ */
5
+ import * as fs from 'fs';
6
+ import * as path from 'path';
7
+ import * as os from 'os';
8
+ import { LLXPRT_DIR } from '../utils/paths.js';
9
+ export class ConfigurationManager {
10
+ // Line 11: PRIVATE static instance: ConfigurationManager
11
+ static instance;
12
+ // Line 12-18: Private configuration properties
13
+ defaultConfig;
14
+ projectConfig = null;
15
+ userConfig = null;
16
+ envConfig = null;
17
+ cliConfig = null;
18
+ ephemeralConfig = null;
19
+ mergedConfig;
20
+ listeners = new Set();
21
+ // Line 21-26: Singleton getInstance()
22
+ static getInstance() {
23
+ if (!ConfigurationManager.instance) {
24
+ ConfigurationManager.instance = new ConfigurationManager();
25
+ }
26
+ return ConfigurationManager.instance;
27
+ }
28
+ // Line 28-40: Constructor with default config
29
+ constructor() {
30
+ this.defaultConfig = {
31
+ enabled: false,
32
+ namespaces: [],
33
+ level: 'info',
34
+ output: { target: 'file', directory: `~/${LLXPRT_DIR}/debug` },
35
+ lazyEvaluation: true,
36
+ redactPatterns: ['apiKey', 'token', 'password'],
37
+ };
38
+ this.listeners = new Set();
39
+ this.loadConfigurations();
40
+ this.mergeConfigurations();
41
+ }
42
+ // Line 42-46: Load all configurations
43
+ loadConfigurations() {
44
+ this.loadEnvironmentConfig();
45
+ this.loadUserConfig();
46
+ this.loadProjectConfig();
47
+ }
48
+ // Line 47-64: Load environment config (support DEBUG and LLXPRT_DEBUG)
49
+ loadEnvironmentConfig() {
50
+ if (process.env.DEBUG) {
51
+ const namespaces = this.parseDebugEnv(process.env.DEBUG);
52
+ // Only enable if DEBUG contains llxprt namespaces
53
+ const llxprtNamespaces = namespaces.filter((ns) => ns.startsWith('llxprt') || ns === '*');
54
+ if (llxprtNamespaces.length > 0) {
55
+ this.envConfig = {
56
+ enabled: true,
57
+ namespaces: llxprtNamespaces,
58
+ };
59
+ }
60
+ }
61
+ if (process.env.LLXPRT_DEBUG) {
62
+ const namespaces = this.parseDebugEnv(process.env.LLXPRT_DEBUG);
63
+ this.envConfig = {
64
+ enabled: true,
65
+ namespaces,
66
+ };
67
+ }
68
+ // Support other LLXPRT environment variables
69
+ if (process.env.DEBUG_ENABLED) {
70
+ this.envConfig = {
71
+ ...this.envConfig,
72
+ enabled: process.env.DEBUG_ENABLED === 'true',
73
+ };
74
+ }
75
+ if (process.env.DEBUG_LEVEL) {
76
+ this.envConfig = { ...this.envConfig, level: process.env.DEBUG_LEVEL };
77
+ }
78
+ }
79
+ // Line 66-79: Load user config from ~/.llxprt/settings.json
80
+ loadUserConfig() {
81
+ try {
82
+ const homeDir = os.homedir();
83
+ if (!homeDir) {
84
+ // In test environments, os.homedir() might not be available
85
+ return;
86
+ }
87
+ const configPath = path.join(homeDir, LLXPRT_DIR, 'settings.json');
88
+ if (fs.existsSync(configPath)) {
89
+ try {
90
+ const content = fs.readFileSync(configPath, 'utf8');
91
+ const parsed = JSON.parse(content);
92
+ if (parsed.debug) {
93
+ this.userConfig = parsed.debug;
94
+ }
95
+ }
96
+ catch (error) {
97
+ console.warn('Failed to load user config:', error);
98
+ }
99
+ }
100
+ }
101
+ catch (_error) {
102
+ // Silently skip if we can't determine home directory (e.g., in tests)
103
+ // This allows the debug system to work with default config
104
+ }
105
+ }
106
+ // Line 81-94: Load project config from .llxprt/config.json
107
+ loadProjectConfig() {
108
+ try {
109
+ const cwd = process.cwd();
110
+ if (!cwd) {
111
+ return;
112
+ }
113
+ const configPath = path.join(cwd, LLXPRT_DIR, 'config.json');
114
+ if (fs.existsSync(configPath)) {
115
+ try {
116
+ const content = fs.readFileSync(configPath, 'utf8');
117
+ const parsed = JSON.parse(content);
118
+ if (parsed.debug) {
119
+ this.projectConfig = parsed.debug;
120
+ }
121
+ }
122
+ catch (error) {
123
+ console.warn('Failed to load project config:', error);
124
+ }
125
+ }
126
+ }
127
+ catch (_error) {
128
+ // Silently skip if we can't determine working directory (e.g., in tests)
129
+ }
130
+ }
131
+ // Line 96-111: Merge configurations in priority order
132
+ mergeConfigurations() {
133
+ const configs = [
134
+ this.defaultConfig,
135
+ this.projectConfig,
136
+ this.userConfig,
137
+ this.envConfig,
138
+ this.cliConfig,
139
+ this.ephemeralConfig,
140
+ ].filter(Boolean);
141
+ this.mergedConfig = configs.reduce((merged, config) => Object.assign({}, merged, config), {});
142
+ // Notify all listeners of configuration change
143
+ this.listeners.forEach((listener) => listener());
144
+ }
145
+ // Line 113-121: Set CLI and ephemeral configs
146
+ setCliConfig(config) {
147
+ this.cliConfig = config;
148
+ this.mergeConfigurations();
149
+ }
150
+ setEphemeralConfig(config) {
151
+ this.ephemeralConfig = {
152
+ ...this.ephemeralConfig,
153
+ ...config,
154
+ };
155
+ this.mergeConfigurations();
156
+ }
157
+ // Line 123-150: Persist ephemeral to user config
158
+ persistEphemeralConfig() {
159
+ if (!this.ephemeralConfig) {
160
+ return;
161
+ }
162
+ const userConfigPath = path.join(os.homedir(), LLXPRT_DIR, 'settings.json');
163
+ let existing = {};
164
+ if (fs.existsSync(userConfigPath)) {
165
+ try {
166
+ existing = JSON.parse(fs.readFileSync(userConfigPath, 'utf8'));
167
+ }
168
+ catch {
169
+ existing = {};
170
+ }
171
+ }
172
+ existing.debug = Object.assign({}, existing.debug, this.ephemeralConfig);
173
+ try {
174
+ fs.mkdirSync(path.dirname(userConfigPath), { recursive: true });
175
+ fs.writeFileSync(userConfigPath, JSON.stringify(existing, null, 2));
176
+ this.userConfig = existing.debug;
177
+ this.ephemeralConfig = null;
178
+ this.mergeConfigurations();
179
+ }
180
+ catch (_error) {
181
+ throw new Error('Failed to persist configuration');
182
+ }
183
+ }
184
+ // Line 152-174: Getters and subscription management
185
+ getEffectiveConfig() {
186
+ return this.mergedConfig;
187
+ }
188
+ getOutputTarget() {
189
+ const output = this.mergedConfig.output;
190
+ if (typeof output === 'string') {
191
+ return output;
192
+ }
193
+ return output.target;
194
+ }
195
+ getRedactPatterns() {
196
+ return this.mergedConfig.redactPatterns;
197
+ }
198
+ subscribe(listener) {
199
+ this.listeners.add(listener);
200
+ }
201
+ unsubscribe(listener) {
202
+ this.listeners.delete(listener);
203
+ }
204
+ parseDebugEnv(value) {
205
+ return value
206
+ .split(',')
207
+ .map((s) => s.trim())
208
+ .filter(Boolean);
209
+ }
210
+ }
211
+ //# sourceMappingURL=ConfigurationManager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ConfigurationManager.js","sourceRoot":"","sources":["../../../src/debug/ConfigurationManager.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,26 @@
1
+ import { ConfigurationManager } from './ConfigurationManager.js';
2
+ import { FileOutput } from './FileOutput.js';
3
+ export declare class DebugLogger {
4
+ private debugInstance;
5
+ private _namespace;
6
+ private _configManager;
7
+ private _fileOutput;
8
+ private _enabled;
9
+ private _level;
10
+ constructor(namespace: string);
11
+ get namespace(): string;
12
+ get enabled(): boolean;
13
+ set enabled(value: boolean);
14
+ get level(): string;
15
+ set level(value: string);
16
+ get configManager(): ConfigurationManager;
17
+ get fileOutput(): FileOutput;
18
+ log(messageOrFn: string | (() => string), ...args: unknown[]): void;
19
+ debug(messageOrFn: string | (() => string), ...args: unknown[]): void;
20
+ error(messageOrFn: string | (() => string), ...args: unknown[]): void;
21
+ checkEnabled(): boolean;
22
+ private matchesPattern;
23
+ private redactSensitive;
24
+ private onConfigChange;
25
+ dispose(): Promise<void>;
26
+ }
@@ -0,0 +1,230 @@
1
+ /**
2
+ * @plan PLAN-20250120-DEBUGLOGGING.P05
3
+ * @requirement REQ-001,REQ-002,REQ-006
4
+ * @pseudocode lines 10-121
5
+ */
6
+ import createDebug from 'debug';
7
+ import { ConfigurationManager } from './ConfigurationManager.js';
8
+ import { FileOutput } from './FileOutput.js';
9
+ // Configure debug to use console.log instead of stderr for React UI compatibility
10
+ // This ensures debug output goes to the Ctrl+O debug console in the UI
11
+ if (typeof window === 'undefined') {
12
+ // Disable colors to respect theme settings
13
+ createDebug.useColors = () => false;
14
+ // Use a wrapper function that calls the CURRENT console.log
15
+ // This works even if console.log is patched later by the UI
16
+ createDebug.log = (...args) => {
17
+ // Call whatever console.log is at the time of logging
18
+ // This allows the UI's ConsolePatcher to intercept it
19
+ console.log(...args);
20
+ };
21
+ }
22
+ export class DebugLogger {
23
+ debugInstance; // Line 11
24
+ _namespace; // Line 12
25
+ _configManager; // Line 13
26
+ _fileOutput; // Line 14
27
+ _enabled; // Line 15
28
+ _level = 'debug';
29
+ constructor(namespace) {
30
+ // Lines 17-24: Initialize logger
31
+ this._namespace = namespace; // Line 18
32
+ this.debugInstance = createDebug(namespace); // Line 19
33
+ this._configManager = ConfigurationManager.getInstance(); // Line 20
34
+ this._fileOutput = FileOutput.getInstance(); // Line 21
35
+ this._enabled = this.checkEnabled(); // Line 22
36
+ this._configManager.subscribe(() => this.onConfigChange()); // Line 23
37
+ }
38
+ get namespace() {
39
+ return this._namespace;
40
+ }
41
+ get enabled() {
42
+ return this._enabled;
43
+ }
44
+ set enabled(value) {
45
+ this._enabled = value;
46
+ }
47
+ get level() {
48
+ return this._level;
49
+ }
50
+ set level(value) {
51
+ this._level = value;
52
+ }
53
+ get configManager() {
54
+ return this._configManager;
55
+ }
56
+ get fileOutput() {
57
+ return this._fileOutput;
58
+ }
59
+ log(messageOrFn, ...args) {
60
+ // Lines 26-60: Main log method
61
+ if (!this._enabled) {
62
+ // Line 27-29
63
+ return; // Zero overhead - no processing when disabled
64
+ }
65
+ let message;
66
+ if (typeof messageOrFn === 'function') {
67
+ // Line 32
68
+ try {
69
+ message = messageOrFn(); // Line 34
70
+ }
71
+ catch (_error) {
72
+ message = '[Error evaluating log function]'; // Line 36
73
+ }
74
+ }
75
+ else {
76
+ message = messageOrFn; // Line 39
77
+ }
78
+ message = this.redactSensitive(message); // Line 42
79
+ const timestamp = new Date().toISOString(); // Line 43
80
+ const logEntry = {
81
+ // Lines 45-51
82
+ timestamp,
83
+ namespace: this._namespace,
84
+ level: 'log',
85
+ message,
86
+ args: args.length > 0 ? args : undefined,
87
+ };
88
+ const target = this._configManager.getOutputTarget();
89
+ if (target.includes('file')) {
90
+ // Line 53-55
91
+ void this._fileOutput.write(logEntry);
92
+ }
93
+ if (target.includes('stderr')) {
94
+ // Line 57-59
95
+ this.debugInstance(message, ...args);
96
+ }
97
+ }
98
+ debug(messageOrFn, ...args) {
99
+ // Lines 62-64
100
+ if (this._level === 'error') {
101
+ return; // Don't log debug messages when level is error
102
+ }
103
+ // Create modified log entry with debug level
104
+ if (!this._enabled) {
105
+ return;
106
+ }
107
+ let message;
108
+ if (typeof messageOrFn === 'function') {
109
+ try {
110
+ message = messageOrFn();
111
+ }
112
+ catch (_error) {
113
+ message = '[Error evaluating log function]';
114
+ }
115
+ }
116
+ else {
117
+ message = messageOrFn;
118
+ }
119
+ message = this.redactSensitive(message);
120
+ const timestamp = new Date().toISOString();
121
+ const logEntry = {
122
+ timestamp,
123
+ namespace: this._namespace,
124
+ level: 'debug',
125
+ message,
126
+ args: args.length > 0 ? args : undefined,
127
+ };
128
+ const target = this._configManager.getOutputTarget();
129
+ if (target.includes('file')) {
130
+ void this._fileOutput.write(logEntry);
131
+ }
132
+ if (target.includes('stderr')) {
133
+ this.debugInstance(message, ...args);
134
+ }
135
+ }
136
+ error(messageOrFn, ...args) {
137
+ // Lines 66-70
138
+ if (!this._enabled) {
139
+ return;
140
+ }
141
+ let message;
142
+ if (typeof messageOrFn === 'function') {
143
+ try {
144
+ message = messageOrFn();
145
+ }
146
+ catch (_error) {
147
+ message = '[Error evaluating log function]';
148
+ }
149
+ }
150
+ else {
151
+ message = messageOrFn;
152
+ }
153
+ message = this.redactSensitive(message);
154
+ const timestamp = new Date().toISOString();
155
+ const logEntry = {
156
+ timestamp,
157
+ namespace: this._namespace,
158
+ level: 'error',
159
+ message,
160
+ args: args.length > 0 ? args : undefined,
161
+ };
162
+ const target = this._configManager.getOutputTarget();
163
+ if (target.includes('file')) {
164
+ void this._fileOutput.write(logEntry);
165
+ }
166
+ if (target.includes('stderr')) {
167
+ this.debugInstance(message, ...args);
168
+ }
169
+ }
170
+ checkEnabled() {
171
+ // Lines 72-85: Check if logger enabled
172
+ const config = this._configManager.getEffectiveConfig(); // Line 73
173
+ if (!config.enabled) {
174
+ // Line 74-76
175
+ return false;
176
+ }
177
+ // Handle namespaces as either array or object
178
+ const namespaces = Array.isArray(config.namespaces)
179
+ ? config.namespaces
180
+ : Object.keys(config.namespaces);
181
+ for (const pattern of namespaces) {
182
+ // Line 78-82
183
+ if (this.matchesPattern(this._namespace, pattern)) {
184
+ return true;
185
+ }
186
+ }
187
+ return false; // Line 84
188
+ }
189
+ matchesPattern(namespace, pattern) {
190
+ // Lines 87-98: Pattern matching
191
+ if (pattern === namespace) {
192
+ // Line 88-90
193
+ return true;
194
+ }
195
+ // Support wildcards anywhere in the pattern
196
+ if (pattern.includes('*')) {
197
+ // Convert pattern to regex:
198
+ // - Escape special regex chars except *
199
+ // - Replace * with .* for regex wildcard matching
200
+ const regexPattern = pattern
201
+ .replace(/[.+?^${}()|[\]\\]/g, '\\$&') // Escape special chars
202
+ .replace(/\*/g, '.*'); // Convert * to regex wildcard
203
+ const regex = new RegExp(`^${regexPattern}$`);
204
+ return regex.test(namespace);
205
+ }
206
+ return false; // Line 97
207
+ }
208
+ redactSensitive(message) {
209
+ // Lines 100-110: Redact sensitive data
210
+ const patterns = this._configManager.getRedactPatterns(); // Line 101
211
+ let result = message; // Line 102
212
+ for (const pattern of patterns) {
213
+ // Line 104-107
214
+ const regex = new RegExp(`${pattern}["']?:\\s*["']?([^"'\\s]+)`, 'gi');
215
+ result = result.replace(regex, `${pattern}: [REDACTED]`);
216
+ }
217
+ return result; // Line 109
218
+ }
219
+ onConfigChange() {
220
+ // Lines 112-114
221
+ this._enabled = this.checkEnabled();
222
+ }
223
+ async dispose() {
224
+ // Lines 116-119
225
+ this._configManager.unsubscribe(this.onConfigChange);
226
+ // Flush pending writes handled by FileOutput
227
+ await this._fileOutput.dispose();
228
+ }
229
+ }
230
+ //# sourceMappingURL=DebugLogger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DebugLogger.js","sourceRoot":"","sources":["../../../src/debug/DebugLogger.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ import type { LogEntry } from './types.js';
2
+ export declare class FileOutput {
3
+ private static instance;
4
+ private debugDir;
5
+ private currentLogFile;
6
+ private writeQueue;
7
+ private isWriting;
8
+ private disposed;
9
+ private flushTimeout;
10
+ private maxFileSize;
11
+ private maxQueueSize;
12
+ private batchSize;
13
+ private flushInterval;
14
+ private constructor();
15
+ static getInstance(): FileOutput;
16
+ write(entry: LogEntry): Promise<void>;
17
+ dispose(): Promise<void>;
18
+ private startFlushTimer;
19
+ private flushQueue;
20
+ private ensureDirectoryExists;
21
+ private checkFileRotation;
22
+ private generateLogFileName;
23
+ }
@@ -0,0 +1,144 @@
1
+ /**
2
+ * @plan PLAN-20250120-DEBUGLOGGING.P10
3
+ * @requirement REQ-005
4
+ */
5
+ import { promises as fs } from 'fs';
6
+ import { join } from 'path';
7
+ import { homedir } from 'os';
8
+ import { LLXPRT_DIR } from '../utils/paths.js';
9
+ export class FileOutput {
10
+ static instance;
11
+ debugDir;
12
+ currentLogFile;
13
+ writeQueue = [];
14
+ isWriting = false;
15
+ disposed = false;
16
+ flushTimeout = null;
17
+ maxFileSize = 10 * 1024 * 1024; // 10MB
18
+ maxQueueSize = 1000;
19
+ batchSize = 50;
20
+ flushInterval = 1000; // 1 second
21
+ constructor() {
22
+ const home = homedir();
23
+ // Handle test environments where homedir might not be available
24
+ this.debugDir = home
25
+ ? join(home, LLXPRT_DIR, 'debug')
26
+ : join(process.cwd(), LLXPRT_DIR, 'debug');
27
+ this.currentLogFile = this.generateLogFileName();
28
+ this.startFlushTimer();
29
+ }
30
+ static getInstance() {
31
+ if (!FileOutput.instance) {
32
+ FileOutput.instance = new FileOutput();
33
+ }
34
+ return FileOutput.instance;
35
+ }
36
+ async write(entry) {
37
+ if (this.disposed) {
38
+ return;
39
+ }
40
+ // Add to queue
41
+ this.writeQueue.push({
42
+ entry,
43
+ timestamp: Date.now(),
44
+ });
45
+ // Prevent queue from growing too large
46
+ if (this.writeQueue.length > this.maxQueueSize) {
47
+ this.writeQueue = this.writeQueue.slice(-this.maxQueueSize);
48
+ }
49
+ // Flush immediately if queue is large or not currently writing
50
+ if (this.writeQueue.length >= this.batchSize || !this.isWriting) {
51
+ await this.flushQueue();
52
+ }
53
+ }
54
+ async dispose() {
55
+ this.disposed = true;
56
+ if (this.flushTimeout) {
57
+ clearTimeout(this.flushTimeout);
58
+ this.flushTimeout = null;
59
+ }
60
+ // Flush any remaining entries
61
+ await this.flushQueue();
62
+ }
63
+ startFlushTimer() {
64
+ if (this.disposed) {
65
+ return;
66
+ }
67
+ this.flushTimeout = setTimeout(async () => {
68
+ await this.flushQueue();
69
+ this.startFlushTimer();
70
+ }, this.flushInterval);
71
+ }
72
+ async flushQueue() {
73
+ if (this.isWriting || this.writeQueue.length === 0 || this.disposed) {
74
+ return;
75
+ }
76
+ this.isWriting = true;
77
+ let entriesToWrite = [];
78
+ try {
79
+ await this.ensureDirectoryExists();
80
+ await this.checkFileRotation();
81
+ // Process entries in batches
82
+ entriesToWrite = this.writeQueue.splice(0, this.batchSize);
83
+ if (entriesToWrite.length === 0) {
84
+ return;
85
+ }
86
+ // Convert to JSONL format
87
+ const jsonlData = entriesToWrite.map(({ entry }) => JSON.stringify(entry)).join('\n') +
88
+ '\n';
89
+ // Write to file with proper permissions
90
+ await fs.appendFile(this.currentLogFile, jsonlData, {
91
+ encoding: 'utf8',
92
+ mode: 0o600,
93
+ });
94
+ }
95
+ catch (error) {
96
+ // Gracefully handle errors - don't crash the application
97
+ console.error('FileOutput: Failed to write log entries:', error);
98
+ // Put entries back in queue for retry (but limit retries)
99
+ if (this.writeQueue.length < this.maxQueueSize / 2) {
100
+ this.writeQueue.unshift(...entriesToWrite);
101
+ }
102
+ }
103
+ finally {
104
+ this.isWriting = false;
105
+ }
106
+ }
107
+ async ensureDirectoryExists() {
108
+ try {
109
+ await fs.access(this.debugDir);
110
+ }
111
+ catch {
112
+ await fs.mkdir(this.debugDir, {
113
+ recursive: true,
114
+ mode: 0o700,
115
+ });
116
+ }
117
+ }
118
+ async checkFileRotation() {
119
+ try {
120
+ const stats = await fs.stat(this.currentLogFile);
121
+ // Rotate by size
122
+ if (stats.size >= this.maxFileSize) {
123
+ this.currentLogFile = this.generateLogFileName();
124
+ return;
125
+ }
126
+ // Rotate by date (daily rotation)
127
+ const fileDate = new Date(stats.birthtime);
128
+ const today = new Date();
129
+ if (fileDate.toDateString() !== today.toDateString()) {
130
+ this.currentLogFile = this.generateLogFileName();
131
+ }
132
+ }
133
+ catch {
134
+ // File doesn't exist yet, that's fine
135
+ }
136
+ }
137
+ generateLogFileName() {
138
+ const now = new Date();
139
+ const dateString = now.toISOString().split('T')[0]; // YYYY-MM-DD
140
+ const timeString = now.toTimeString().split(' ')[0].replace(/:/g, '-'); // HH-MM-SS
141
+ return join(this.debugDir, `llxprt-debug-${dateString}-${timeString}.jsonl`);
142
+ }
143
+ }
144
+ //# sourceMappingURL=FileOutput.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FileOutput.js","sourceRoot":"","sources":["../../../src/debug/FileOutput.ts"],"names":[],"mappings":"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"}