locadex 0.0.2-alpha.6 → 0.0.2-alpha.7

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 (110) hide show
  1. package/dist/cli.d.ts.map +1 -1
  2. package/dist/cli.js +67 -9
  3. package/dist/cli.js.map +1 -1
  4. package/dist/commands/i18n.d.ts +1 -2
  5. package/dist/commands/i18n.d.ts.map +1 -1
  6. package/dist/commands/i18n.js +5 -256
  7. package/dist/commands/i18n.js.map +1 -1
  8. package/dist/commands/setup.d.ts +1 -1
  9. package/dist/commands/setup.d.ts.map +1 -1
  10. package/dist/commands/setup.js +5 -142
  11. package/dist/commands/setup.js.map +1 -1
  12. package/dist/logging/console.d.ts +3 -3
  13. package/dist/logging/console.d.ts.map +1 -1
  14. package/dist/logging/console.js +9 -8
  15. package/dist/logging/console.js.map +1 -1
  16. package/dist/logging/logger.d.ts +4 -2
  17. package/dist/logging/logger.d.ts.map +1 -1
  18. package/dist/logging/logger.js +33 -7
  19. package/dist/logging/logger.js.map +1 -1
  20. package/dist/mcp/getDocs.d.ts.map +1 -1
  21. package/dist/mcp/getDocs.js +2 -3
  22. package/dist/mcp/getDocs.js.map +1 -1
  23. package/dist/mcp/getPort.d.ts +2 -0
  24. package/dist/mcp/getPort.d.ts.map +1 -0
  25. package/dist/mcp/getPort.js +25 -0
  26. package/dist/mcp/getPort.js.map +1 -0
  27. package/dist/mcp/tools/docs.d.ts.map +1 -1
  28. package/dist/mcp/tools/docs.js +9 -2
  29. package/dist/mcp/tools/docs.js.map +1 -1
  30. package/dist/mcp/tools/guides.d.ts.map +1 -1
  31. package/dist/mcp/tools/guides.js +5 -2
  32. package/dist/mcp/tools/guides.js.map +1 -1
  33. package/dist/mcp-sse.d.ts.map +1 -1
  34. package/dist/mcp-sse.js +10 -28
  35. package/dist/mcp-sse.js.map +1 -1
  36. package/dist/tasks/i18n.d.ts +2 -0
  37. package/dist/tasks/i18n.d.ts.map +1 -0
  38. package/dist/tasks/i18n.js +317 -0
  39. package/dist/tasks/i18n.js.map +1 -0
  40. package/dist/tasks/setup.d.ts +2 -0
  41. package/dist/tasks/setup.d.ts.map +1 -0
  42. package/dist/tasks/setup.js +171 -0
  43. package/dist/tasks/setup.js.map +1 -0
  44. package/dist/telemetry.d.ts +1 -3
  45. package/dist/telemetry.d.ts.map +1 -1
  46. package/dist/telemetry.js +27 -25
  47. package/dist/telemetry.js.map +1 -1
  48. package/dist/types/cli.d.ts +9 -0
  49. package/dist/types/cli.d.ts.map +1 -1
  50. package/dist/types/cli.js +2 -2
  51. package/dist/types/cli.js.map +1 -1
  52. package/dist/utils/claudeCode.d.ts +7 -2
  53. package/dist/utils/claudeCode.d.ts.map +1 -1
  54. package/dist/utils/claudeCode.js +50 -31
  55. package/dist/utils/claudeCode.js.map +1 -1
  56. package/dist/utils/config.d.ts +10 -0
  57. package/dist/utils/config.d.ts.map +1 -0
  58. package/dist/utils/config.js +66 -0
  59. package/dist/utils/config.js.map +1 -0
  60. package/dist/utils/dag/createDag.d.ts +1 -1
  61. package/dist/utils/dag/createDag.d.ts.map +1 -1
  62. package/dist/utils/dag/createDag.js +4 -41
  63. package/dist/utils/dag/createDag.js.map +1 -1
  64. package/dist/utils/dag/matchFiles.d.ts +2 -0
  65. package/dist/utils/dag/matchFiles.d.ts.map +1 -0
  66. package/dist/utils/dag/matchFiles.js +40 -0
  67. package/dist/utils/dag/matchFiles.js.map +1 -0
  68. package/dist/utils/getFiles.d.ts +2 -3
  69. package/dist/utils/getFiles.d.ts.map +1 -1
  70. package/dist/utils/getFiles.js +23 -14
  71. package/dist/utils/getFiles.js.map +1 -1
  72. package/dist/utils/locadexManager.d.ts +69 -0
  73. package/dist/utils/locadexManager.d.ts.map +1 -0
  74. package/dist/utils/locadexManager.js +250 -0
  75. package/dist/utils/locadexManager.js.map +1 -0
  76. package/dist/utils/session.d.ts +2 -0
  77. package/dist/utils/session.d.ts.map +1 -0
  78. package/dist/utils/session.js +12 -0
  79. package/dist/utils/session.js.map +1 -0
  80. package/dist/utils/shared.d.ts +2 -1
  81. package/dist/utils/shared.d.ts.map +1 -1
  82. package/dist/utils/shared.js +37 -14
  83. package/dist/utils/shared.js.map +1 -1
  84. package/dist/utils/shutdown.d.ts +20 -0
  85. package/dist/utils/shutdown.d.ts.map +1 -0
  86. package/dist/utils/shutdown.js +63 -0
  87. package/dist/utils/shutdown.js.map +1 -0
  88. package/dist/utils/stats.d.ts +13 -0
  89. package/dist/utils/stats.d.ts.map +1 -1
  90. package/dist/utils/stats.js +55 -2
  91. package/dist/utils/stats.js.map +1 -1
  92. package/package.json +2 -5
  93. package/.locadex-mcp-stdio.json +0 -9
  94. package/.locadex-mcp.json +0 -8
  95. package/dist/utils/agentManager.d.ts +0 -34
  96. package/dist/utils/agentManager.d.ts.map +0 -1
  97. package/dist/utils/agentManager.js +0 -123
  98. package/dist/utils/agentManager.js.map +0 -1
  99. package/dist/utils/debugLogger.d.ts +0 -3
  100. package/dist/utils/debugLogger.d.ts.map +0 -1
  101. package/dist/utils/debugLogger.js +0 -36
  102. package/dist/utils/debugLogger.js.map +0 -1
  103. package/dist/utils/mcpConfig.d.ts +0 -10
  104. package/dist/utils/mcpConfig.d.ts.map +0 -1
  105. package/dist/utils/mcpConfig.js +0 -13
  106. package/dist/utils/mcpConfig.js.map +0 -1
  107. package/dist/utils/validateConfig.d.ts +0 -2
  108. package/dist/utils/validateConfig.d.ts.map +0 -1
  109. package/dist/utils/validateConfig.js +0 -12
  110. package/dist/utils/validateConfig.js.map +0 -1
@@ -0,0 +1,171 @@
1
+
2
+ !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="19a2b250-5271-51d6-a2ab-f5951a2e183e")}catch(e){}}();
3
+ import { createSpinner, promptConfirm, } from '../logging/console.js';
4
+ import { getPackageJson, isPackageInstalled } from 'gtx-cli/utils/packageJson';
5
+ import { getPackageManager } from 'gtx-cli/utils/packageManager';
6
+ import { installPackage, installPackageGlobal, } from 'gtx-cli/utils/installPackage';
7
+ import chalk from 'chalk';
8
+ import { logger } from '../logging/logger.js';
9
+ import { findFilepaths } from '../utils/fs/findConfigs.js';
10
+ import { wrapContentNext } from 'gtx-cli/next/parse/wrapContent';
11
+ import { handleInitGT } from 'gtx-cli/next/parse/handleInitGT';
12
+ import { detectFormatter, formatFiles } from 'gtx-cli/hooks/postProcess';
13
+ import { createOrUpdateConfig } from 'gtx-cli/fs/config/setupConfig';
14
+ import { i18nTask } from '../tasks/i18n.js';
15
+ import { validateInitialConfig } from '../utils/config.js';
16
+ import { getNextDirectories } from '../utils/fs/getFiles.js';
17
+ import { LocadexManager } from '../utils/locadexManager.js';
18
+ import { outro } from '@clack/prompts';
19
+ import { getPackageInfo } from 'gtx-cli/utils/packageInfo';
20
+ import { CLAUDE_CODE_VERSION } from '../utils/shared.js';
21
+ import { appendFileSync } from 'node:fs';
22
+ import path from 'node:path';
23
+ import { exit } from '../utils/shutdown.js';
24
+ export async function setupTask(bypassPrompts, specifiedPackageManager) {
25
+ await validateInitialConfig();
26
+ if (!bypassPrompts) {
27
+ const answer = await promptConfirm({
28
+ message: chalk.yellow(`Locadex will modify files! Make sure you have committed or stashed any changes. Do you want to continue?`),
29
+ defaultValue: true,
30
+ cancelMessage: 'Operation cancelled.',
31
+ });
32
+ if (!answer) {
33
+ logger.info('Operation cancelled.');
34
+ await exit(0);
35
+ }
36
+ }
37
+ const packageJson = await getPackageJson();
38
+ const packageManager = await getPackageManager(specifiedPackageManager);
39
+ const spinner = createSpinner('timer');
40
+ spinner.start(`Installing gt-next with ${packageManager.name}...`);
41
+ await installPackage('gt-next', packageManager);
42
+ spinner.stop('Automatically installed gt-next.');
43
+ const nextConfigPath = findFilepaths([
44
+ './next.config.js',
45
+ './next.config.ts',
46
+ './next.config.mjs',
47
+ './next.config.mts',
48
+ ])[0];
49
+ if (!nextConfigPath) {
50
+ logger.error('No next.config.[js|ts|mjs|mts] file found.');
51
+ await exit(1);
52
+ }
53
+ const errors = [];
54
+ const warnings = [];
55
+ let filesUpdated = [];
56
+ const babel = createSpinner();
57
+ babel.start('Wrapping <GTProvider> tags...');
58
+ // Wrap all JSX elements in the src directory with a <T> tag, with unique ids
59
+ const { filesUpdated: filesUpdatedNext } = await wrapContentNext({
60
+ src: getNextDirectories(),
61
+ config: nextConfigPath,
62
+ disableIds: true,
63
+ disableFormatting: true,
64
+ skipTs: true,
65
+ addGTProvider: true,
66
+ }, 'gt-next', errors, warnings);
67
+ filesUpdated = [...filesUpdated, ...filesUpdatedNext];
68
+ babel.stop(`Modified ${filesUpdated.length} files.`);
69
+ // Add the withGTConfig() function to the next.config.js file
70
+ await handleInitGT(nextConfigPath, errors, warnings, filesUpdated);
71
+ logger.step(`Added withGTConfig() to your ${nextConfigPath} file.`);
72
+ // Create gt.config.json
73
+ await createOrUpdateConfig('gt.config.json', {
74
+ defaultLocale: 'en',
75
+ locales: ['es', 'fr', 'de', 'ja', 'zh'],
76
+ framework: 'next-app',
77
+ });
78
+ logger.success(`Feel free to edit ${chalk.cyan('gt.config.json')} to customize your translation setup. Docs: https://generaltranslation.com/docs/cli/reference/config`);
79
+ // Install claude-code if not installed
80
+ const claudeCodeInfo = await getPackageInfo('@anthropic-ai/claude-code');
81
+ if (!claudeCodeInfo) {
82
+ const spinner = createSpinner();
83
+ spinner.start('Installing claude-code...');
84
+ await installPackageGlobal('@anthropic-ai/claude-code', CLAUDE_CODE_VERSION);
85
+ spinner.stop(chalk.green('Installed claude-code.'));
86
+ }
87
+ else {
88
+ logger.step(`claude-code is already installed: v${claudeCodeInfo.version}`);
89
+ }
90
+ // Install locadex if not installed
91
+ const isLocadexInstalled = packageJson
92
+ ? isPackageInstalled('locadex', packageJson, true, true)
93
+ : true; // if no package.json, we can't install it
94
+ if (!isLocadexInstalled) {
95
+ const packageManager = await getPackageManager();
96
+ const spinner = createSpinner();
97
+ spinner.start(`Installing locadex as a dev dependency with ${packageManager.name}...`);
98
+ await installPackage('locadex', packageManager, true);
99
+ spinner.stop(chalk.green('Installed locadex.'));
100
+ }
101
+ // Set up locale selector
102
+ await setupLocaleSelector();
103
+ const formatter = await detectFormatter();
104
+ if (formatter && filesUpdated.length > 0) {
105
+ await formatFiles(filesUpdated, formatter);
106
+ }
107
+ // Run i18n command
108
+ await i18nTask();
109
+ }
110
+ async function setupLocaleSelector() {
111
+ logger.initializeSpinner();
112
+ logger.spinner.start('Creating locale selector...');
113
+ // Create agent
114
+ const manager = LocadexManager.getInstance();
115
+ const agent = manager.createSingleAgent('claude_setup_agent');
116
+ // Fix prompt
117
+ const localeSelectorPrompt = getLocaleSelectorPrompt();
118
+ try {
119
+ await agent.run({ prompt: localeSelectorPrompt }, {});
120
+ // Generate report
121
+ const report = agent.generateReport();
122
+ const reportSummary = `# Summary of locadex setup changes
123
+ ${report}`;
124
+ const summaryFilePath = path.join(manager.getWorkingDir(), 'locadex-report.md');
125
+ appendFileSync(summaryFilePath, reportSummary);
126
+ }
127
+ catch (error) {
128
+ logger.debugMessage(`[setup] Adding locale selector failed: ${error}`);
129
+ outro(chalk.red('❌ Locadex setup failed!'));
130
+ await exit(1);
131
+ }
132
+ logger.spinner.stop('Locale selector setup complete');
133
+ }
134
+ function getLocaleSelectorPrompt() {
135
+ const prompt = `# Task: Add a locale selector to the project
136
+
137
+ ## Instructions
138
+ - The locale selector should be a dropdown that allows the user to select the locale.
139
+
140
+ ## LOCALE SELECTOR USAGE
141
+ (1) Import the locale selector component from 'gt-next/client'
142
+ (2) Add the locale selector to the project
143
+
144
+ For example:
145
+ import { LocaleSelector } from 'gt-next/client';
146
+
147
+ function MyComponent() {
148
+ return (
149
+ <div>
150
+ <LocaleSelector />
151
+ <p>Hello, world!</p>
152
+ </div>
153
+ );
154
+ }
155
+
156
+ ## ADVICE
157
+ - The locale selector should be added to a header or footer or some other very obvious place in the project.
158
+ - Scan across files to find the best place to add the locale selector.
159
+
160
+ ## Final output
161
+ - When you are done, please return a brief summary of the files you modified, following this format.
162
+ - **DO NOT** include any other text in your response.
163
+ - If there were issues with some files, please include the issues in the list of changes for that file.
164
+
165
+ [file 1 path]
166
+ - List of changes to file 1
167
+ `;
168
+ return prompt;
169
+ }
170
+ //# sourceMappingURL=setup.js.map
171
+ //# debugId=19a2b250-5271-51d6-a2ab-f5951a2e183e
@@ -0,0 +1 @@
1
+ {"version":3,"file":"setup.js","sources":["tasks/setup.ts"],"sourceRoot":"/","sourcesContent":["import {\n createSpinner,\n displayHeader,\n promptConfirm,\n} from '../logging/console.js';\nimport { getPackageJson, isPackageInstalled } from 'gtx-cli/utils/packageJson';\nimport { getPackageManager } from 'gtx-cli/utils/packageManager';\nimport {\n installPackage,\n installPackageGlobal,\n} from 'gtx-cli/utils/installPackage';\nimport chalk from 'chalk';\nimport { logger } from '../logging/logger.js';\nimport { findFilepaths } from '../utils/fs/findConfigs.js';\nimport { wrapContentNext } from 'gtx-cli/next/parse/wrapContent';\nimport { handleInitGT } from 'gtx-cli/next/parse/handleInitGT';\nimport { detectFormatter, formatFiles } from 'gtx-cli/hooks/postProcess';\nimport { createOrUpdateConfig } from 'gtx-cli/fs/config/setupConfig';\nimport { i18nTask } from '../tasks/i18n.js';\nimport { validateInitialConfig } from '../utils/config.js';\nimport { getNextDirectories } from '../utils/fs/getFiles.js';\nimport { LocadexManager } from '../utils/locadexManager.js';\nimport { outro } from '@clack/prompts';\nimport { getPackageInfo } from 'gtx-cli/utils/packageInfo';\nimport { CLAUDE_CODE_VERSION } from '../utils/shared.js';\nimport { appendFileSync } from 'node:fs';\nimport path from 'node:path';\nimport { exit } from '../utils/shutdown.js';\n\nexport async function setupTask(\n bypassPrompts: boolean,\n specifiedPackageManager?: string\n) {\n await validateInitialConfig();\n\n if (!bypassPrompts) {\n const answer = await promptConfirm({\n message: chalk.yellow(\n `Locadex will modify files! Make sure you have committed or stashed any changes. Do you want to continue?`\n ),\n defaultValue: true,\n cancelMessage: 'Operation cancelled.',\n });\n if (!answer) {\n logger.info('Operation cancelled.');\n await exit(0);\n }\n }\n\n const packageJson = await getPackageJson();\n const packageManager = await getPackageManager(specifiedPackageManager);\n\n const spinner = createSpinner('timer');\n\n spinner.start(`Installing gt-next with ${packageManager.name}...`);\n\n await installPackage('gt-next', packageManager);\n\n spinner.stop('Automatically installed gt-next.');\n\n const nextConfigPath = findFilepaths([\n './next.config.js',\n './next.config.ts',\n './next.config.mjs',\n './next.config.mts',\n ])[0];\n\n if (!nextConfigPath) {\n logger.error('No next.config.[js|ts|mjs|mts] file found.');\n await exit(1);\n }\n\n const errors: string[] = [];\n const warnings: string[] = [];\n let filesUpdated: string[] = [];\n\n const babel = createSpinner();\n\n babel.start('Wrapping <GTProvider> tags...');\n\n // Wrap all JSX elements in the src directory with a <T> tag, with unique ids\n const { filesUpdated: filesUpdatedNext } = await wrapContentNext(\n {\n src: getNextDirectories(),\n config: nextConfigPath,\n disableIds: true,\n disableFormatting: true,\n skipTs: true,\n addGTProvider: true,\n },\n 'gt-next',\n errors,\n warnings\n );\n filesUpdated = [...filesUpdated, ...filesUpdatedNext];\n\n babel.stop(`Modified ${filesUpdated.length} files.`);\n\n // Add the withGTConfig() function to the next.config.js file\n await handleInitGT(nextConfigPath, errors, warnings, filesUpdated);\n logger.step(`Added withGTConfig() to your ${nextConfigPath} file.`);\n\n // Create gt.config.json\n await createOrUpdateConfig('gt.config.json', {\n defaultLocale: 'en',\n locales: ['es', 'fr', 'de', 'ja', 'zh'],\n framework: 'next-app',\n });\n\n logger.success(\n `Feel free to edit ${chalk.cyan(\n 'gt.config.json'\n )} to customize your translation setup. Docs: https://generaltranslation.com/docs/cli/reference/config`\n );\n\n // Install claude-code if not installed\n const claudeCodeInfo = await getPackageInfo('@anthropic-ai/claude-code');\n if (!claudeCodeInfo) {\n const spinner = createSpinner();\n spinner.start('Installing claude-code...');\n await installPackageGlobal(\n '@anthropic-ai/claude-code',\n CLAUDE_CODE_VERSION\n );\n spinner.stop(chalk.green('Installed claude-code.'));\n } else {\n logger.step(`claude-code is already installed: v${claudeCodeInfo.version}`);\n }\n\n // Install locadex if not installed\n const isLocadexInstalled = packageJson\n ? isPackageInstalled('locadex', packageJson, true, true)\n : true; // if no package.json, we can't install it\n\n if (!isLocadexInstalled) {\n const packageManager = await getPackageManager();\n const spinner = createSpinner();\n spinner.start(\n `Installing locadex as a dev dependency with ${packageManager.name}...`\n );\n await installPackage('locadex', packageManager, true);\n spinner.stop(chalk.green('Installed locadex.'));\n }\n\n // Set up locale selector\n await setupLocaleSelector();\n\n const formatter = await detectFormatter();\n if (formatter && filesUpdated.length > 0) {\n await formatFiles(filesUpdated, formatter);\n }\n\n // Run i18n command\n await i18nTask();\n}\n\nasync function setupLocaleSelector() {\n logger.initializeSpinner();\n logger.spinner.start('Creating locale selector...');\n\n // Create agent\n const manager = LocadexManager.getInstance();\n\n const agent = manager.createSingleAgent('claude_setup_agent');\n\n // Fix prompt\n const localeSelectorPrompt = getLocaleSelectorPrompt();\n try {\n await agent.run({ prompt: localeSelectorPrompt }, {});\n\n // Generate report\n const report = agent.generateReport();\n const reportSummary = `# Summary of locadex setup changes\n${report}`;\n const summaryFilePath = path.join(\n manager.getWorkingDir(),\n 'locadex-report.md'\n );\n appendFileSync(summaryFilePath, reportSummary);\n } catch (error) {\n logger.debugMessage(`[setup] Adding locale selector failed: ${error}`);\n outro(chalk.red('❌ Locadex setup failed!'));\n await exit(1);\n }\n\n logger.spinner.stop('Locale selector setup complete');\n}\n\nfunction getLocaleSelectorPrompt() {\n const prompt = `# Task: Add a locale selector to the project\n\n## Instructions\n- The locale selector should be a dropdown that allows the user to select the locale.\n\n## LOCALE SELECTOR USAGE\n(1) Import the locale selector component from 'gt-next/client'\n(2) Add the locale selector to the project\n\nFor example:\nimport { LocaleSelector } from 'gt-next/client';\n\nfunction MyComponent() {\n return (\n <div>\n <LocaleSelector />\n <p>Hello, world!</p>\n </div>\n );\n}\n\n## ADVICE\n- The locale selector should be added to a header or footer or some other very obvious place in the project.\n- Scan across files to find the best place to add the locale selector.\n\n## Final output\n- When you are done, please return a brief summary of the files you modified, following this format.\n- **DO NOT** include any other text in your response. \n- If there were issues with some files, please include the issues in the list of changes for that file.\n\n[file 1 path]\n- List of changes to file 1\n`;\n return prompt;\n}\n"],"names":[],"mappings":"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","debug_id":"19a2b250-5271-51d6-a2ab-f5951a2e183e"}
@@ -1,11 +1,9 @@
1
- import * as Sentry from '@sentry/node';
2
1
  import { PostHog } from 'posthog-node';
3
2
  import { CliOptions } from './types/cli.js';
4
3
  declare const posthog: PostHog;
5
- export { posthog };
6
- export { Sentry };
7
4
  export declare function withTelemetry<F>(params: {
8
5
  enabled: boolean;
9
6
  options: CliOptions;
10
7
  }, callback: () => F | Promise<F>): Promise<F>;
8
+ export { posthog };
11
9
  //# sourceMappingURL=telemetry.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"telemetry.d.ts","sourceRoot":"/","sources":["telemetry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAEvC,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAO5C,QAAA,MAAM,OAAO,SAcX,CAAC;AAEH,OAAO,EAAE,OAAO,EAAE,CAAC;AACnB,OAAO,EAAE,MAAM,EAAE,CAAC;AAqClB,wBAAsB,aAAa,CAAC,CAAC,EACnC,MAAM,EAAE;IACN,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,UAAU,CAAC;CACrB,EACD,QAAQ,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,GAC7B,OAAO,CAAC,CAAC,CAAC,CAiCZ"}
1
+ {"version":3,"file":"telemetry.d.ts","sourceRoot":"/","sources":["telemetry.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAEvC,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAQ5C,QAAA,MAAM,OAAO,SAcX,CAAC;AA0CH,wBAAsB,aAAa,CAAC,CAAC,EACnC,MAAM,EAAE;IACN,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,UAAU,CAAC;CACrB,EACD,QAAQ,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,GAC7B,OAAO,CAAC,CAAC,CAAC,CAmCZ;AAcD,OAAO,EAAE,OAAO,EAAE,CAAC"}
package/dist/telemetry.js CHANGED
@@ -1,8 +1,10 @@
1
1
 
2
- !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="1778889b-e97a-571b-a4e0-eaccf88a9e01")}catch(e){}}();
2
+ !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="098a5a64-e899-5a52-b0ad-69dc35b385a7")}catch(e){}}();
3
+ import { exit, gracefulShutdown } from './utils/shutdown.js';
3
4
  import * as Sentry from '@sentry/node';
4
5
  import { PostHog } from 'posthog-node';
5
6
  import { getLocadexVersion } from './utils/getPaths.js';
7
+ import { getSessionId } from './utils/session.js';
6
8
  let _posthog = null;
7
9
  let sentryInitialized = false;
8
10
  let telemetryEnabled = false;
@@ -20,8 +22,6 @@ const posthog = new Proxy({}, {
20
22
  return _posthog[prop];
21
23
  },
22
24
  });
23
- export { posthog };
24
- export { Sentry };
25
25
  function initializeTelemetry(enabled) {
26
26
  telemetryEnabled = enabled;
27
27
  if (!sentryInitialized) {
@@ -29,6 +29,7 @@ function initializeTelemetry(enabled) {
29
29
  dsn: 'https://f542d2155ab069c9de0fcd913ed3ce3b@o4508407294853120.ingest.us.sentry.io/4509441836843008',
30
30
  release: getLocadexVersion(),
31
31
  enabled,
32
+ tracesSampleRate: 1.0,
32
33
  beforeSend: (event) => {
33
34
  event.exception?.values?.forEach((exception) => {
34
35
  delete exception.stacktrace;
@@ -36,6 +37,10 @@ function initializeTelemetry(enabled) {
36
37
  delete event.server_name;
37
38
  return event;
38
39
  },
40
+ beforeSendTransaction: (event) => {
41
+ delete event.server_name;
42
+ return event;
43
+ },
39
44
  });
40
45
  sentryInitialized = true;
41
46
  }
@@ -48,7 +53,7 @@ function initializeTelemetry(enabled) {
48
53
  }
49
54
  function updateProgress(status) {
50
55
  posthog.capture({
51
- distinctId: 'anonymous',
56
+ distinctId: getSessionId(),
52
57
  event: 'locadex_progress',
53
58
  properties: { status },
54
59
  });
@@ -60,11 +65,16 @@ export async function withTelemetry(params, callback) {
60
65
  return await callback();
61
66
  }
62
67
  Sentry.setTag('args.verbose', !!options.verbose);
68
+ Sentry.setTag('args.debug', !!options.debug);
63
69
  Sentry.setTag('args.noTelemetry', !!options.noTelemetry);
70
+ Sentry.setTag('args.batchSize', options.batchSize);
71
+ Sentry.setTag('args.concurrency', options.concurrency);
72
+ Sentry.setTag('args.matchingFiles', options.matchingFiles);
73
+ Sentry.setTag('args.matchingExtensions', options.matchingExtensions);
64
74
  try {
65
75
  return await Sentry.startSpan({
66
76
  name: 'locadex-execution',
67
- op: 'locadex.flow',
77
+ op: 'locadex.exec',
68
78
  }, async () => {
69
79
  updateProgress('start');
70
80
  const res = await callback();
@@ -77,28 +87,20 @@ export async function withTelemetry(params, callback) {
77
87
  throw e;
78
88
  }
79
89
  finally {
80
- await Sentry.flush(3000).then(null, () => { });
90
+ await exit(0);
91
+ }
92
+ }
93
+ // Register telemetry cleanup with graceful shutdown
94
+ gracefulShutdown.addHandler({
95
+ name: 'telemetry-cleanup',
96
+ handler: async () => {
81
97
  if (_posthog) {
82
98
  await _posthog.shutdown();
83
99
  }
84
- }
85
- }
86
- const shutdown = async () => {
87
- if (_posthog) {
88
- await _posthog.shutdown();
89
- }
90
- process.exit(0);
91
- };
92
- process.on('SIGINT', () => {
93
- shutdown();
94
- });
95
- process.on('SIGTERM', () => {
96
- shutdown();
97
- });
98
- process.on('exit', () => {
99
- if (_posthog) {
100
- _posthog.shutdown();
101
- }
100
+ await Sentry.flush(3000).then(null, () => { });
101
+ },
102
+ timeout: 3000,
102
103
  });
104
+ export { posthog };
103
105
  //# sourceMappingURL=telemetry.js.map
104
- //# debugId=1778889b-e97a-571b-a4e0-eaccf88a9e01
106
+ //# debugId=098a5a64-e899-5a52-b0ad-69dc35b385a7
@@ -1 +1 @@
1
- {"version":3,"file":"telemetry.js","sources":["telemetry.ts"],"sourceRoot":"/","sourcesContent":["import * as Sentry from '@sentry/node';\nimport { PostHog } from 'posthog-node';\nimport { getLocadexVersion } from './utils/getPaths.js';\nimport { CliOptions } from './types/cli.js';\n\nlet _posthog: PostHog | null = null;\nlet sentryInitialized = false;\nlet telemetryEnabled = false;\n\n// Create a PostHog proxy that behaves like PostHog but does nothing when disabled\nconst posthog = new Proxy({} as PostHog, {\n get(target, prop) {\n if (!telemetryEnabled || !_posthog) {\n // Return no-op functions for all PostHog methods\n if (\n typeof prop === 'string' &&\n ['capture', 'identify', 'alias', 'shutdown'].includes(prop)\n ) {\n return () => {};\n }\n return undefined;\n }\n return _posthog[prop as keyof PostHog];\n },\n});\n\nexport { posthog };\nexport { Sentry };\n\nfunction initializeTelemetry(enabled: boolean) {\n telemetryEnabled = enabled;\n\n if (!sentryInitialized) {\n Sentry.init({\n dsn: 'https://f542d2155ab069c9de0fcd913ed3ce3b@o4508407294853120.ingest.us.sentry.io/4509441836843008',\n release: getLocadexVersion(),\n enabled,\n beforeSend: (event) => {\n event.exception?.values?.forEach((exception) => {\n delete exception.stacktrace;\n });\n delete event.server_name;\n return event;\n },\n });\n sentryInitialized = true;\n }\n\n if (!_posthog && enabled) {\n _posthog = new PostHog('phc_LJRRBlhH8kgjiydp2bKjC7QPMguDoNd1b4QHQArxtha', {\n host: 'https://us.i.posthog.com',\n disableGeoip: true,\n });\n }\n}\n\nfunction updateProgress(status: string) {\n posthog.capture({\n distinctId: 'anonymous',\n event: 'locadex_progress',\n properties: { status },\n });\n}\n\nexport async function withTelemetry<F>(\n params: {\n enabled: boolean;\n options: CliOptions;\n },\n callback: () => F | Promise<F>\n): Promise<F> {\n const { enabled, options } = params;\n initializeTelemetry(enabled);\n\n if (!enabled) {\n return await callback();\n }\n\n Sentry.setTag('args.verbose', !!options.verbose);\n Sentry.setTag('args.noTelemetry', !!options.noTelemetry);\n\n try {\n return await Sentry.startSpan(\n {\n name: 'locadex-execution',\n op: 'locadex.flow',\n },\n async () => {\n updateProgress('start');\n const res = await callback();\n updateProgress('finished');\n return res;\n }\n );\n } catch (e) {\n Sentry.captureException(e);\n throw e;\n } finally {\n await Sentry.flush(3000).then(null, () => {});\n if (_posthog) {\n await _posthog.shutdown();\n }\n }\n}\n\nconst shutdown = async () => {\n if (_posthog) {\n await _posthog.shutdown();\n }\n process.exit(0);\n};\n\nprocess.on('SIGINT', () => {\n shutdown();\n});\nprocess.on('SIGTERM', () => {\n shutdown();\n});\nprocess.on('exit', () => {\n if (_posthog) {\n _posthog.shutdown();\n }\n});\n"],"names":[],"mappings":"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","debug_id":"1778889b-e97a-571b-a4e0-eaccf88a9e01"}
1
+ {"version":3,"file":"telemetry.js","sources":["telemetry.ts"],"sourceRoot":"/","sourcesContent":["import { exit, gracefulShutdown } from './utils/shutdown.js';\nimport * as Sentry from '@sentry/node';\nimport { PostHog } from 'posthog-node';\nimport { getLocadexVersion } from './utils/getPaths.js';\nimport { CliOptions } from './types/cli.js';\nimport { getSessionId } from './utils/session.js';\n\nlet _posthog: PostHog | null = null;\nlet sentryInitialized = false;\nlet telemetryEnabled = false;\n\n// Create a PostHog proxy that behaves like PostHog but does nothing when disabled\nconst posthog = new Proxy({} as PostHog, {\n get(target, prop) {\n if (!telemetryEnabled || !_posthog) {\n // Return no-op functions for all PostHog methods\n if (\n typeof prop === 'string' &&\n ['capture', 'identify', 'alias', 'shutdown'].includes(prop)\n ) {\n return () => {};\n }\n return undefined;\n }\n return _posthog[prop as keyof PostHog];\n },\n});\n\nfunction initializeTelemetry(enabled: boolean) {\n telemetryEnabled = enabled;\n\n if (!sentryInitialized) {\n Sentry.init({\n dsn: 'https://f542d2155ab069c9de0fcd913ed3ce3b@o4508407294853120.ingest.us.sentry.io/4509441836843008',\n release: getLocadexVersion(),\n enabled,\n tracesSampleRate: 1.0,\n beforeSend: (event) => {\n event.exception?.values?.forEach((exception) => {\n delete exception.stacktrace;\n });\n delete event.server_name;\n return event;\n },\n beforeSendTransaction: (event) => {\n delete event.server_name;\n return event;\n },\n });\n sentryInitialized = true;\n }\n\n if (!_posthog && enabled) {\n _posthog = new PostHog('phc_LJRRBlhH8kgjiydp2bKjC7QPMguDoNd1b4QHQArxtha', {\n host: 'https://us.i.posthog.com',\n disableGeoip: true,\n });\n }\n}\n\nfunction updateProgress(status: string) {\n posthog.capture({\n distinctId: getSessionId(),\n event: 'locadex_progress',\n properties: { status },\n });\n}\n\nexport async function withTelemetry<F>(\n params: {\n enabled: boolean;\n options: CliOptions;\n },\n callback: () => F | Promise<F>\n): Promise<F> {\n const { enabled, options } = params;\n initializeTelemetry(enabled);\n\n if (!enabled) {\n return await callback();\n }\n\n Sentry.setTag('args.verbose', !!options.verbose);\n Sentry.setTag('args.debug', !!options.debug);\n Sentry.setTag('args.noTelemetry', !!options.noTelemetry);\n Sentry.setTag('args.batchSize', options.batchSize);\n Sentry.setTag('args.concurrency', options.concurrency);\n Sentry.setTag('args.matchingFiles', options.matchingFiles);\n Sentry.setTag('args.matchingExtensions', options.matchingExtensions);\n\n try {\n return await Sentry.startSpan(\n {\n name: 'locadex-execution',\n op: 'locadex.exec',\n },\n async () => {\n updateProgress('start');\n const res = await callback();\n updateProgress('finished');\n return res;\n }\n );\n } catch (e) {\n Sentry.captureException(e);\n throw e;\n } finally {\n await exit(0);\n }\n}\n\n// Register telemetry cleanup with graceful shutdown\ngracefulShutdown.addHandler({\n name: 'telemetry-cleanup',\n handler: async () => {\n if (_posthog) {\n await _posthog.shutdown();\n }\n await Sentry.flush(3000).then(null, () => {});\n },\n timeout: 3000,\n});\n\nexport { posthog };\n"],"names":[],"mappings":"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","debug_id":"098a5a64-e899-5a52-b0ad-69dc35b385a7"}
@@ -3,5 +3,14 @@ export type CliOptions = {
3
3
  debug?: boolean;
4
4
  noTelemetry?: boolean;
5
5
  batchSize?: string;
6
+ concurrency?: string;
7
+ matchingFiles?: string;
8
+ matchingExtensions?: string;
9
+ };
10
+ export type LocadexConfig = {
11
+ batchSize: number;
12
+ maxConcurrency: number;
13
+ matchingFiles: string[];
14
+ matchingExtensions: string[];
6
15
  };
7
16
  //# sourceMappingURL=cli.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"cli.d.ts","sourceRoot":"/","sources":["types/cli.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,UAAU,GAAG;IACvB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC"}
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"/","sources":["types/cli.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,UAAU,GAAG;IACvB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,MAAM,CAAC;IACvB,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,kBAAkB,EAAE,MAAM,EAAE,CAAC;CAC9B,CAAC"}
package/dist/types/cli.js CHANGED
@@ -1,5 +1,5 @@
1
1
 
2
- !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="0bcfa866-9916-5f4e-8612-cd741b840359")}catch(e){}}();
2
+ !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="c89b6b75-84a4-59f5-9013-ab5de6871b18")}catch(e){}}();
3
3
  export {};
4
4
  //# sourceMappingURL=cli.js.map
5
- //# debugId=0bcfa866-9916-5f4e-8612-cd741b840359
5
+ //# debugId=c89b6b75-84a4-59f5-9013-ab5de6871b18
@@ -1 +1 @@
1
- {"version":3,"file":"cli.js","sources":["types/cli.ts"],"sourceRoot":"/","sourcesContent":["export type CliOptions = {\n verbose?: boolean;\n debug?: boolean;\n noTelemetry?: boolean;\n batchSize?: string;\n};\n"],"names":[],"mappings":"","debug_id":"0bcfa866-9916-5f4e-8612-cd741b840359"}
1
+ {"version":3,"file":"cli.js","sources":["types/cli.ts"],"sourceRoot":"/","sourcesContent":["export type CliOptions = {\n verbose?: boolean;\n debug?: boolean;\n noTelemetry?: boolean;\n batchSize?: string;\n concurrency?: string;\n matchingFiles?: string;\n matchingExtensions?: string;\n};\n\nexport type LocadexConfig = {\n batchSize: number;\n maxConcurrency: number;\n matchingFiles: string[];\n matchingExtensions: string[];\n};\n"],"names":[],"mappings":"","debug_id":"c89b6b75-84a4-59f5-9013-ab5de6871b18"}
@@ -1,4 +1,4 @@
1
- import { LocadexManager } from './agentManager.js';
1
+ import { LocadexManager } from './locadexManager.js';
2
2
  export interface ClaudeCodeOptions {
3
3
  additionalSystemPrompt?: string;
4
4
  prompt: string;
@@ -8,17 +8,22 @@ export interface ClaudeCodeOptions {
8
8
  }
9
9
  export interface ClaudeCodeObservation {
10
10
  }
11
+ export declare const killAllClaudeProcesses: () => void;
11
12
  export declare class ClaudeCodeRunner {
12
13
  private options;
14
+ private id;
13
15
  private sessionId;
14
16
  private mcpConfig;
15
17
  private manager;
16
- constructor(manager: LocadexManager, options?: {
18
+ private changes;
19
+ constructor(manager: LocadexManager, options: {
20
+ id: string;
17
21
  apiKey?: string;
18
22
  mcpConfig?: string;
19
23
  });
20
24
  getSessionId(): string;
21
25
  run(options: ClaudeCodeOptions, obs: ClaudeCodeObservation): Promise<string>;
22
26
  private handleSDKOutput;
27
+ generateReport(): string;
23
28
  }
24
29
  //# sourceMappingURL=claudeCode.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"claudeCode.d.ts","sourceRoot":"/","sources":["utils/claudeCode.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAEnD,MAAM,WAAW,iBAAiB;IAChC,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,MAAM,EAAE,MAAM,CAAC;IACf,sBAAsB,CAAC,EAAE,MAAM,EAAE,CAAC;IAClC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,qBAAqB;CAAG;AAmCzC,qBAAa,gBAAgB;IAOzB,OAAO,CAAC,OAAO;IANjB,OAAO,CAAC,SAAS,CAAc;IAC/B,OAAO,CAAC,SAAS,CAAqB;IACtC,OAAO,CAAC,OAAO,CAAiB;gBAG9B,OAAO,EAAE,cAAc,EACf,OAAO,GAAE;QACf,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,SAAS,CAAC,EAAE,MAAM,CAAC;KACf;IAgBR,YAAY,IAAI,MAAM;IAIhB,GAAG,CACP,OAAO,EAAE,iBAAiB,EAC1B,GAAG,EAAE,qBAAqB,GACzB,OAAO,CAAC,MAAM,CAAC;IA4FlB,OAAO,CAAC,eAAe;CAiExB"}
1
+ {"version":3,"file":"claudeCode.d.ts","sourceRoot":"/","sources":["utils/claudeCode.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAIrD,MAAM,WAAW,iBAAiB;IAChC,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,MAAM,EAAE,MAAM,CAAC;IACf,sBAAsB,CAAC,EAAE,MAAM,EAAE,CAAC;IAClC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,qBAAqB;CAAG;AAiBzC,eAAO,MAAM,sBAAsB,YAOlC,CAAC;AAYF,qBAAa,gBAAgB;IASzB,OAAO,CAAC,OAAO;IARjB,OAAO,CAAC,EAAE,CAAS;IACnB,OAAO,CAAC,SAAS,CAAc;IAC/B,OAAO,CAAC,SAAS,CAAqB;IACtC,OAAO,CAAC,OAAO,CAAiB;IAChC,OAAO,CAAC,OAAO,CAAgB;gBAG7B,OAAO,EAAE,cAAc,EACf,OAAO,EAAE;QACf,EAAE,EAAE,MAAM,CAAC;QACX,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,SAAS,CAAC,EAAE,MAAM,CAAC;KACpB;IAiBH,YAAY,IAAI,MAAM;IAIhB,GAAG,CACP,OAAO,EAAE,iBAAiB,EAC1B,GAAG,EAAE,qBAAqB,GACzB,OAAO,CAAC,MAAM,CAAC;IAmHlB,OAAO,CAAC,eAAe;IAmEvB,cAAc,IAAI,MAAM;CAGzB"}
@@ -1,10 +1,11 @@
1
1
 
2
- !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="241bc31c-ad73-55df-abfe-d38afdd90259")}catch(e){}}();
2
+ !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="6d5939a4-358d-5c84-9b82-40f12427ee02")}catch(e){}}();
3
3
  import { spawn } from 'node:child_process';
4
- import { createHash } from 'node:crypto';
5
4
  import { guides } from '../mcp/tools/guides.js';
6
5
  import { logger } from '../logging/logger.js';
7
6
  import { posthog } from '../telemetry.js';
7
+ import { getSessionId } from './session.js';
8
+ import * as Sentry from '@sentry/node';
8
9
  const DEFAULT_ALLOWED_TOOLS = [
9
10
  'mcp__locadex__fetch-docs',
10
11
  'mcp__locadex__list-docs',
@@ -16,31 +17,35 @@ const DEFAULT_ALLOWED_TOOLS = [
16
17
  const DISALLOWED_TOOLS = ['NotebookEdit', 'WebFetch', 'WebSearch'];
17
18
  // Global tracking of all Claude processes
18
19
  const activeClaudeProcesses = new Set();
20
+ // Function to kill all active Claude processes
21
+ export const killAllClaudeProcesses = () => {
22
+ activeClaudeProcesses.forEach((proc) => {
23
+ if (!proc.killed) {
24
+ proc.kill('SIGTERM');
25
+ }
26
+ });
27
+ activeClaudeProcesses.clear();
28
+ };
19
29
  // Setup global process termination handlers once
20
30
  let handlersSetup = false;
21
31
  const setupProcessHandlers = () => {
22
32
  if (handlersSetup)
23
33
  return;
24
34
  handlersSetup = true;
25
- const killAllClaudeProcesses = () => {
26
- activeClaudeProcesses.forEach((proc) => {
27
- if (!proc.killed) {
28
- proc.kill('SIGTERM');
29
- }
30
- });
31
- activeClaudeProcesses.clear();
32
- };
33
35
  process.on('SIGINT', killAllClaudeProcesses);
34
36
  process.on('SIGTERM', killAllClaudeProcesses);
35
37
  };
36
38
  export class ClaudeCodeRunner {
37
39
  options;
40
+ id;
38
41
  sessionId = '';
39
42
  mcpConfig;
40
43
  manager;
41
- constructor(manager, options = {}) {
44
+ changes = [];
45
+ constructor(manager, options) {
42
46
  this.options = options;
43
47
  this.manager = manager;
48
+ this.id = options.id;
44
49
  this.mcpConfig = options.mcpConfig;
45
50
  // Ensure API key is set
46
51
  if (!process.env.ANTHROPIC_API_KEY && !this.options.apiKey) {
@@ -53,7 +58,14 @@ export class ClaudeCodeRunner {
53
58
  return this.sessionId;
54
59
  }
55
60
  async run(options, obs) {
56
- return new Promise((resolve, reject) => {
61
+ this.changes = [];
62
+ return Sentry.startSpan({
63
+ name: 'claude-code-exec',
64
+ op: 'claude-code.exec',
65
+ attributes: {
66
+ 'process.command': 'claude',
67
+ },
68
+ }, () => new Promise((resolve, reject) => {
57
69
  const args = ['-p', options.prompt];
58
70
  if (options.additionalSystemPrompt) {
59
71
  args.push('--append-system-prompt', options.additionalSystemPrompt);
@@ -78,7 +90,7 @@ export class ClaudeCodeRunner {
78
90
  if (this.options.apiKey) {
79
91
  env.ANTHROPIC_API_KEY = this.options.apiKey;
80
92
  }
81
- const claude = spawn('npx', ['claude', ...args], {
93
+ const claude = spawn('claude', args, {
82
94
  stdio: ['inherit', 'pipe', 'pipe'],
83
95
  env,
84
96
  });
@@ -94,18 +106,18 @@ export class ClaudeCodeRunner {
94
106
  for (const line of lines) {
95
107
  if (line.trim()) {
96
108
  try {
97
- logger.debugMessage(`[Claude Code SDK] ${line}`);
109
+ logger.debugMessage(`[${this.id}] ${line}`);
98
110
  const outputData = JSON.parse(line);
99
111
  this.handleSDKOutput(outputData, obs);
100
112
  }
101
113
  catch (error) {
102
- logger.debugMessage(`[Claude Code SDK] Failed to parse JSON: ${error instanceof Error ? error.message : String(error)}`);
114
+ logger.debugMessage(`[${this.id}] Failed to parse JSON: ${error instanceof Error ? error.message : String(error)}`);
103
115
  }
104
116
  }
105
117
  }
106
118
  });
107
- claude.stderr?.on('data', () => {
108
- logger.warning('An error occurred while running Claude Code');
119
+ claude.stderr?.on('data', (data) => {
120
+ logger.debugMessage(`[${this.id}] ${data.toString().trim()}`);
109
121
  });
110
122
  claude.on('close', (code) => {
111
123
  activeClaudeProcesses.delete(claude);
@@ -113,14 +125,16 @@ export class ClaudeCodeRunner {
113
125
  resolve(output.trim());
114
126
  }
115
127
  else {
116
- reject(new Error(`Claude Code exited with code ${code}: ${errorOutput}`));
128
+ logger.debugMessage(`[${this.id}] Claude Code exited with code ${code}: ${errorOutput}`);
129
+ reject(new Error(`[${this.id}] Claude Code exited with code ${code}: ${errorOutput}`));
117
130
  }
118
131
  });
119
132
  claude.on('error', (error) => {
120
133
  activeClaudeProcesses.delete(claude);
121
- reject(new Error(`Failed to run Claude Code: ${error.message}`));
134
+ logger.debugMessage(`[${this.id}] failed to run Claude Code: ${error.message}`);
135
+ reject(new Error(`[${this.id}] failed to run Claude Code: ${error.message}`));
122
136
  });
123
- });
137
+ }));
124
138
  }
125
139
  handleSDKOutput(outputData, obs) {
126
140
  if (outputData.type === 'assistant') {
@@ -134,12 +148,7 @@ export class ClaudeCodeRunner {
134
148
  toolUses.push(c.name);
135
149
  if (c.name.startsWith('mcp__locadex__')) {
136
150
  posthog.capture({
137
- distinctId: this.sessionId
138
- ? createHash('sha256')
139
- .update(this.sessionId)
140
- .digest('base64url')
141
- .slice(0, 8)
142
- : 'anonymous',
151
+ distinctId: getSessionId(),
143
152
  event: 'tool_used',
144
153
  properties: {
145
154
  tool: c.name,
@@ -149,26 +158,33 @@ export class ClaudeCodeRunner {
149
158
  }
150
159
  });
151
160
  if (text.length > 0) {
152
- logger.verboseMessage(text.join('').trim());
161
+ logger.verboseMessage(`[${this.id}] ${text.join('').trim()}`);
153
162
  }
154
163
  if (toolUses.length > 0) {
155
- logger.debugMessage(`[Claude Code SDK] Used tools: ${toolUses.join(', ')}`);
164
+ logger.debugMessage(`[${this.id}] used tools: ${toolUses.join(', ')}`);
156
165
  }
157
166
  this.manager.stats.updateStats({
158
167
  newToolCalls: toolUses.length,
168
+ newInputTokens: outputData.message.usage.input_tokens,
169
+ newOutputTokens: outputData.message.usage.output_tokens,
170
+ newCachedInputTokens: outputData.message.usage.cache_read_input_tokens ?? 0,
159
171
  });
160
172
  }
161
173
  else if (outputData.type === 'result') {
162
174
  if (!outputData.is_error) {
163
- logger.verboseMessage(`[Claude Code SDK] Finished\nCost: $${Number(outputData.cost_usd).toFixed(2)}\nDuration: ${Number(outputData.duration_ms) / 1000}s`);
175
+ logger.verboseMessage(`[${this.id}] finished task.\nCost: $${Number(outputData.cost_usd).toFixed(2)}\nDuration: ${Number(outputData.duration_ms) / 1000}s`);
164
176
  }
165
177
  else {
166
- logger.verboseMessage(`[Claude Code SDK] Finished with error: ${outputData.subtype}\nCost: $${outputData.cost_usd}\nDuration: ${Number(outputData.duration_ms) / 1000}s`);
178
+ logger.verboseMessage(`[${this.id}] finished task with error: ${outputData.subtype}\nCost: $${outputData.cost_usd}\nDuration: ${Number(outputData.duration_ms) / 1000}s`);
179
+ }
180
+ if (outputData.subtype === 'success') {
181
+ this.changes.push(outputData.result);
167
182
  }
168
183
  this.manager.stats.updateStats({
169
184
  newCost: Number(outputData.cost_usd),
170
185
  newWallDuration: Number(outputData.duration_ms),
171
186
  newApiDuration: Number(outputData.duration_api_ms),
187
+ newTurns: Number(outputData.num_turns),
172
188
  });
173
189
  }
174
190
  else if (outputData.type === 'system') {
@@ -177,6 +193,9 @@ export class ClaudeCodeRunner {
177
193
  }
178
194
  }
179
195
  }
196
+ generateReport() {
197
+ return this.changes.join('\n');
198
+ }
180
199
  }
181
200
  //# sourceMappingURL=claudeCode.js.map
182
- //# debugId=241bc31c-ad73-55df-abfe-d38afdd90259
201
+ //# debugId=6d5939a4-358d-5c84-9b82-40f12427ee02