locadex 0.1.0-alpha.9 → 0.1.1

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 (123) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/README.md +3 -5
  3. package/dist/cli.js +11 -10
  4. package/dist/cli.js.map +1 -1
  5. package/dist/commands/i18n.d.ts.map +1 -1
  6. package/dist/commands/i18n.js +15 -14
  7. package/dist/commands/i18n.js.map +1 -1
  8. package/dist/commands/setup.d.ts.map +1 -1
  9. package/dist/commands/setup.js +15 -14
  10. package/dist/commands/setup.js.map +1 -1
  11. package/dist/index.js +1 -4
  12. package/dist/index.js.map +1 -1
  13. package/dist/logging/console.js +2 -5
  14. package/dist/logging/console.js.map +1 -1
  15. package/dist/logging/logger.d.ts +4 -2
  16. package/dist/logging/logger.d.ts.map +1 -1
  17. package/dist/logging/logger.js +1 -4
  18. package/dist/logging/logger.js.map +1 -1
  19. package/dist/mcp/getDocs.js +1 -4
  20. package/dist/mcp/getDocs.js.map +1 -1
  21. package/dist/mcp/getGuide.js +1 -4
  22. package/dist/mcp/getGuide.js.map +1 -1
  23. package/dist/mcp/getPort.js +1 -4
  24. package/dist/mcp/getPort.js.map +1 -1
  25. package/dist/mcp/tools/docs.js +1 -4
  26. package/dist/mcp/tools/docs.js.map +1 -1
  27. package/dist/mcp/tools/guides.js +1 -4
  28. package/dist/mcp/tools/guides.js.map +1 -1
  29. package/dist/mcp.d.ts +1 -1
  30. package/dist/mcp.d.ts.map +1 -1
  31. package/dist/mcp.js +56 -16
  32. package/dist/mcp.js.map +1 -1
  33. package/dist/prompts/system.js +1 -4
  34. package/dist/prompts/system.js.map +1 -1
  35. package/dist/tasks/concurrency.d.ts +72 -0
  36. package/dist/tasks/concurrency.d.ts.map +1 -0
  37. package/dist/tasks/concurrency.js +132 -0
  38. package/dist/tasks/concurrency.js.map +1 -0
  39. package/dist/tasks/i18n.d.ts.map +1 -1
  40. package/dist/tasks/i18n.js +60 -127
  41. package/dist/tasks/i18n.js.map +1 -1
  42. package/dist/tasks/setup.d.ts.map +1 -1
  43. package/dist/tasks/setup.js +40 -44
  44. package/dist/tasks/setup.js.map +1 -1
  45. package/dist/telemetry.js +1 -4
  46. package/dist/telemetry.js.map +1 -1
  47. package/dist/types/claude-sdk.d.ts +1 -1
  48. package/dist/types/claude-sdk.d.ts.map +1 -1
  49. package/dist/types/claude-sdk.js +1 -4
  50. package/dist/types/claude-sdk.js.map +1 -1
  51. package/dist/types/cli.d.ts +3 -0
  52. package/dist/types/cli.d.ts.map +1 -1
  53. package/dist/types/cli.js +1 -4
  54. package/dist/types/cli.js.map +1 -1
  55. package/dist/utils/claudeCode.d.ts +6 -5
  56. package/dist/utils/claudeCode.d.ts.map +1 -1
  57. package/dist/utils/claudeCode.js +50 -17
  58. package/dist/utils/claudeCode.js.map +1 -1
  59. package/dist/utils/config.d.ts +4 -3
  60. package/dist/utils/config.d.ts.map +1 -1
  61. package/dist/utils/config.js +33 -20
  62. package/dist/utils/config.js.map +1 -1
  63. package/dist/utils/dag/createDag.d.ts.map +1 -1
  64. package/dist/utils/dag/createDag.js +10 -11
  65. package/dist/utils/dag/createDag.js.map +1 -1
  66. package/dist/utils/dag/extractFiles.d.ts.map +1 -1
  67. package/dist/utils/dag/extractFiles.js +6 -9
  68. package/dist/utils/dag/extractFiles.js.map +1 -1
  69. package/dist/utils/dag/getFiles.d.ts +1 -12
  70. package/dist/utils/dag/getFiles.d.ts.map +1 -1
  71. package/dist/utils/dag/getFiles.js +5 -53
  72. package/dist/utils/dag/getFiles.js.map +1 -1
  73. package/dist/utils/dag/matchFiles.d.ts +2 -2
  74. package/dist/utils/dag/matchFiles.d.ts.map +1 -1
  75. package/dist/utils/dag/matchFiles.js +3 -6
  76. package/dist/utils/dag/matchFiles.js.map +1 -1
  77. package/dist/utils/fs/findConfigs.d.ts +4 -4
  78. package/dist/utils/fs/findConfigs.d.ts.map +1 -1
  79. package/dist/utils/fs/findConfigs.js +7 -13
  80. package/dist/utils/fs/findConfigs.js.map +1 -1
  81. package/dist/utils/fs/getFiles.d.ts +1 -1
  82. package/dist/utils/fs/getFiles.d.ts.map +1 -1
  83. package/dist/utils/fs/getFiles.js +3 -6
  84. package/dist/utils/fs/getFiles.js.map +1 -1
  85. package/dist/utils/fs/git.d.ts +6 -0
  86. package/dist/utils/fs/git.d.ts.map +1 -0
  87. package/dist/utils/fs/git.js +32 -0
  88. package/dist/utils/fs/git.js.map +1 -0
  89. package/dist/utils/fs/writeFiles.js +1 -4
  90. package/dist/utils/fs/writeFiles.js.map +1 -1
  91. package/dist/utils/getPaths.js +1 -4
  92. package/dist/utils/getPaths.js.map +1 -1
  93. package/dist/utils/locadexManager.d.ts +15 -5
  94. package/dist/utils/locadexManager.d.ts.map +1 -1
  95. package/dist/utils/locadexManager.js +80 -73
  96. package/dist/utils/locadexManager.js.map +1 -1
  97. package/dist/utils/lockfile.d.ts +2 -2
  98. package/dist/utils/lockfile.d.ts.map +1 -1
  99. package/dist/utils/lockfile.js +8 -17
  100. package/dist/utils/lockfile.js.map +1 -1
  101. package/dist/utils/packages/installPackage.d.ts +4 -0
  102. package/dist/utils/packages/installPackage.d.ts.map +1 -1
  103. package/dist/utils/packages/installPackage.js +41 -5
  104. package/dist/utils/packages/installPackage.js.map +1 -1
  105. package/dist/utils/session.js +1 -4
  106. package/dist/utils/session.js.map +1 -1
  107. package/dist/utils/shared.js +1 -4
  108. package/dist/utils/shared.js.map +1 -1
  109. package/dist/utils/shutdown.d.ts.map +1 -1
  110. package/dist/utils/shutdown.js +1 -9
  111. package/dist/utils/shutdown.js.map +1 -1
  112. package/dist/utils/stats.js +1 -4
  113. package/dist/utils/stats.js.map +1 -1
  114. package/guides/next/advanced/var-outside-client-server-component.md +1 -1
  115. package/package.json +4 -6
  116. package/dist/mcp/debugger.d.ts +0 -3
  117. package/dist/mcp/debugger.d.ts.map +0 -1
  118. package/dist/mcp/debugger.js +0 -37
  119. package/dist/mcp/debugger.js.map +0 -1
  120. package/dist/mcp-sse.d.ts +0 -3
  121. package/dist/mcp-sse.d.ts.map +0 -1
  122. package/dist/mcp-sse.js +0 -77
  123. package/dist/mcp-sse.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"guides.js","sources":["mcp/tools/guides.ts"],"sourceRoot":"/","sourcesContent":["import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport getGuide from '../getGuide.js';\nimport { logger } from '../../logging/logger.js';\n\ntype Guide = {\n id: string;\n description: string;\n path: string;\n type: 'important' | 'basic' | 'advanced';\n};\n\nexport const guides: Guide[] = [\n {\n id: 'important_next-functions',\n description:\n 'Important documentation outlining the imports available in `gt-next`.',\n path: 'guides/next/important/functions.md',\n type: 'important',\n },\n {\n id: 'basic_next-jsx',\n description:\n 'Basic guide for translating JSX and HTML content in a Next.js project.',\n path: 'guides/next/basic/jsx.md',\n type: 'basic',\n },\n {\n id: 'basic_next-branches',\n description:\n 'Basic guide for using branch components and dealing with conditional logic in or pluralization in JSX in a Next.js project.',\n path: 'guides/next/basic/branches.md',\n type: 'basic',\n },\n {\n id: 'basic_next-strings',\n description:\n 'Basic guide for how to use `useGT()` and `getGT()` to internationalize strings in a Next.js project.',\n path: 'guides/next/basic/strings.md',\n type: 'basic',\n },\n {\n id: 'basic_next-variables',\n description:\n 'Basic guide for using internationalizing variable content (Currency, DateTime, Numbers, and other dynamic content) in a Next.js project.',\n path: 'guides/next/basic/variables.md',\n type: 'basic',\n },\n {\n id: 'basic_next-client-side-components',\n description:\n 'Basic guide on how to internationalize client-side components.',\n path: 'guides/next/basic/client-side-components.md',\n type: 'basic',\n },\n {\n id: 'basic_next-server-side-components',\n description:\n 'Basic guide on how to internationalize server-side components.',\n path: 'guides/next/basic/server-side-components.md',\n type: 'basic',\n },\n {\n id: 'advanced_next-outside-client-component',\n description:\n 'Advanced guide for wherever you see a `const` or `let` or a function outside of a function scope that needs to be internationalized. This guide is specifically for when these variables are ONLY used or imported by client side components.',\n path: 'guides/next/advanced/var-outside-client-component.md',\n type: 'advanced',\n },\n {\n id: 'advanced_next-outside-server-component',\n description:\n 'Advanced guide for wherever you see a `const` or `let` or a function outside of a function scope that needs to be internationalized. This guide is specifically for when these variables are ONLY used or imported by server side components.',\n path: 'guides/next/advanced/var-outside-server-component.md',\n type: 'advanced',\n },\n {\n id: 'advanced_next-outside-client-server-component',\n description:\n 'Advanced guide for wherever you see a `const` or `let` or a function outside of a function scope that needs to be internationalized. This guide is specifically for when these variables are used or imported by both client side and server side components.',\n path: 'guides/next/advanced/var-outside-client-server-component.md',\n type: 'advanced',\n },\n {\n id: 'advanced_next-ternary-operators',\n description:\n 'Advanced guide for complex scenarios with ternary operators or conditional statements that needs to be internationalized.',\n path: 'guides/next/advanced/ternary-operators.md',\n type: 'advanced',\n },\n {\n id: 'advanced_next-complicated-mapping-expressions',\n description:\n 'Advanced guide for wherever you see a mapping expression or mapping expression for a nested data structure that needs to be internationalized.',\n path: 'guides/next/advanced/complicated-mapping-expressions.md',\n type: 'advanced',\n },\n {\n id: 'advanced_next-interpolated-strings',\n description:\n 'Advanced guide for wherever you see a string with variables within/around it or interpolated string (template string literal with quasis) that needs to be internationalized.',\n path: 'guides/next/advanced/interpolated-strings.md',\n type: 'advanced',\n },\n {\n id: 'advanced_next-migrating',\n description:\n 'Advanced guide for migrating from an existing i18n library such as react-i18next or next-i18next to gt-next.',\n path: 'guides/next/advanced/migrating.md',\n type: 'advanced',\n },\n];\n\nexport function addGuidesTools(server: McpServer) {\n guides.forEach((guide) => {\n server.tool(guide.id, guide.description, {}, async () => {\n const path = guide.path;\n const { content, error } = await getGuide(path);\n if (error) {\n logger.log(`[locadex-mcp: ${guide.id}] Error fetching guide: ${path}`);\n return {\n content: [\n {\n type: 'text',\n text: `Error fetching guide: ${error}`,\n },\n ],\n isError: true,\n };\n }\n logger.log(\n `[locadex-mcp: ${guide.id}] Guide fetched successfully: ${path}`\n );\n return {\n content: [\n {\n type: 'text',\n text: content ?? '',\n },\n ],\n };\n });\n });\n}\n"],"names":[],"mappings":"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","debug_id":"f1b44bfa-e246-56f1-affa-624eaaeb4b91"}
1
+ {"version":3,"file":"guides.js","sourceRoot":"/","sources":["mcp/tools/guides.ts"],"names":[],"mappings":"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","sourcesContent":["import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport getGuide from '../getGuide.js';\nimport { logger } from '../../logging/logger.js';\n\ntype Guide = {\n id: string;\n description: string;\n path: string;\n type: 'important' | 'basic' | 'advanced';\n};\n\nexport const guides: Guide[] = [\n {\n id: 'important_next-functions',\n description:\n 'Important documentation outlining the imports available in `gt-next`.',\n path: 'guides/next/important/functions.md',\n type: 'important',\n },\n {\n id: 'basic_next-jsx',\n description:\n 'Basic guide for translating JSX and HTML content in a Next.js project.',\n path: 'guides/next/basic/jsx.md',\n type: 'basic',\n },\n {\n id: 'basic_next-branches',\n description:\n 'Basic guide for using branch components and dealing with conditional logic in or pluralization in JSX in a Next.js project.',\n path: 'guides/next/basic/branches.md',\n type: 'basic',\n },\n {\n id: 'basic_next-strings',\n description:\n 'Basic guide for how to use `useGT()` and `getGT()` to internationalize strings in a Next.js project.',\n path: 'guides/next/basic/strings.md',\n type: 'basic',\n },\n {\n id: 'basic_next-variables',\n description:\n 'Basic guide for using internationalizing variable content (Currency, DateTime, Numbers, and other dynamic content) in a Next.js project.',\n path: 'guides/next/basic/variables.md',\n type: 'basic',\n },\n {\n id: 'basic_next-client-side-components',\n description:\n 'Basic guide on how to internationalize client-side components.',\n path: 'guides/next/basic/client-side-components.md',\n type: 'basic',\n },\n {\n id: 'basic_next-server-side-components',\n description:\n 'Basic guide on how to internationalize server-side components.',\n path: 'guides/next/basic/server-side-components.md',\n type: 'basic',\n },\n {\n id: 'advanced_next-outside-client-component',\n description:\n 'Advanced guide for wherever you see a `const` or `let` or a function outside of a function scope that needs to be internationalized. This guide is specifically for when these variables are ONLY used or imported by client side components.',\n path: 'guides/next/advanced/var-outside-client-component.md',\n type: 'advanced',\n },\n {\n id: 'advanced_next-outside-server-component',\n description:\n 'Advanced guide for wherever you see a `const` or `let` or a function outside of a function scope that needs to be internationalized. This guide is specifically for when these variables are ONLY used or imported by server side components.',\n path: 'guides/next/advanced/var-outside-server-component.md',\n type: 'advanced',\n },\n {\n id: 'advanced_next-outside-client-server-component',\n description:\n 'Advanced guide for wherever you see a `const` or `let` or a function outside of a function scope that needs to be internationalized. This guide is specifically for when these variables are used or imported by both client side and server side components.',\n path: 'guides/next/advanced/var-outside-client-server-component.md',\n type: 'advanced',\n },\n {\n id: 'advanced_next-ternary-operators',\n description:\n 'Advanced guide for complex scenarios with ternary operators or conditional statements that needs to be internationalized.',\n path: 'guides/next/advanced/ternary-operators.md',\n type: 'advanced',\n },\n {\n id: 'advanced_next-complicated-mapping-expressions',\n description:\n 'Advanced guide for wherever you see a mapping expression or mapping expression for a nested data structure that needs to be internationalized.',\n path: 'guides/next/advanced/complicated-mapping-expressions.md',\n type: 'advanced',\n },\n {\n id: 'advanced_next-interpolated-strings',\n description:\n 'Advanced guide for wherever you see a string with variables within/around it or interpolated string (template string literal with quasis) that needs to be internationalized.',\n path: 'guides/next/advanced/interpolated-strings.md',\n type: 'advanced',\n },\n {\n id: 'advanced_next-migrating',\n description:\n 'Advanced guide for migrating from an existing i18n library such as react-i18next or next-i18next to gt-next.',\n path: 'guides/next/advanced/migrating.md',\n type: 'advanced',\n },\n];\n\nexport function addGuidesTools(server: McpServer) {\n guides.forEach((guide) => {\n server.tool(guide.id, guide.description, {}, async () => {\n const path = guide.path;\n const { content, error } = await getGuide(path);\n if (error) {\n logger.log(`[locadex-mcp: ${guide.id}] Error fetching guide: ${path}`);\n return {\n content: [\n {\n type: 'text',\n text: `Error fetching guide: ${error}`,\n },\n ],\n isError: true,\n };\n }\n logger.log(\n `[locadex-mcp: ${guide.id}] Guide fetched successfully: ${path}`\n );\n return {\n content: [\n {\n type: 'text',\n text: content ?? '',\n },\n ],\n };\n });\n });\n}\n"]}
package/dist/mcp.d.ts CHANGED
@@ -1,3 +1,3 @@
1
1
  #!/usr/bin/env node
2
- import './telemetry.js';
2
+ export declare function start(): Promise<void>;
3
3
  //# sourceMappingURL=mcp.d.ts.map
package/dist/mcp.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"mcp.d.ts","sourceRoot":"/","sources":["mcp.ts"],"names":[],"mappings":";AAEA,OAAO,gBAAgB,CAAC"}
1
+ {"version":3,"file":"mcp.d.ts","sourceRoot":"/","sources":["mcp.ts"],"names":[],"mappings":";AAcA,wBAAsB,KAAK,kBAuE1B"}
package/dist/mcp.js CHANGED
@@ -1,34 +1,74 @@
1
1
  #!/usr/bin/env node
2
-
3
- !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]="d5982bc6-3621-56f8-ac4a-8f0368dd1b1e")}catch(e){}}();
4
- import './telemetry.js';
5
2
  import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
6
- import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
7
3
  import { addDocsTools } from './mcp/tools/docs.js';
8
4
  import { existsSync, readFileSync } from 'node:fs';
9
5
  import { fromPackageRoot } from './utils/getPaths.js';
10
6
  import { addGuidesTools } from './mcp/tools/guides.js';
11
- async function main() {
7
+ import express from 'express';
8
+ import { SSEServerTransport } from '@modelcontextprotocol/sdk/server/sse.js';
9
+ import { logger } from './logging/logger.js';
10
+ import { findAvailablePort } from './mcp/getPort.js';
11
+ import { exit } from './utils/shutdown.js';
12
+ export async function start() {
12
13
  const stateFile = process.env.LOCADEX_FILES_STATE_FILE_PATH;
14
+ const logFile = process.env.LOCADEX_LOG_FILE_PATH;
15
+ const requestedPort = process.env.PORT ? parseInt(process.env.PORT) : 8888;
16
+ const port = await findAvailablePort(requestedPort);
17
+ const verbose = process.env.LOCADEX_VERBOSE === 'true';
18
+ const debug = process.env.LOCADEX_DEBUG === 'true';
19
+ logger.initialize({ verbose, debug }, logFile);
13
20
  if (stateFile && existsSync(stateFile)) {
14
21
  const state = JSON.parse(readFileSync(stateFile, 'utf8'));
15
- console.error(`[locadex-mcp] state: ${JSON.stringify(state, null, 2)}`);
22
+ logger.debugMessage(`[locadex-mcp] state: ${JSON.stringify(state, null, 2)}`);
16
23
  }
17
24
  else {
18
25
  throw new Error(`[locadex-mcp] state file not found: ${stateFile}`);
19
26
  }
20
- const server = new McpServer({
27
+ const mcpServer = new McpServer({
21
28
  name: 'Locadex: AI Agent for Internationalization',
22
29
  version: JSON.parse(readFileSync(fromPackageRoot('package.json'), 'utf8'))
23
30
  .version,
24
31
  });
25
- addDocsTools(server);
26
- addGuidesTools(server);
27
- console.error('[locadex-mcp] All tools registered');
28
- const transport = new StdioServerTransport();
29
- await server.connect(transport);
30
- console.error('[locadex-mcp] started on stdio');
32
+ const app = express();
33
+ app.use(express.json());
34
+ // Store transports for each session type
35
+ const transports = {
36
+ streamable: {},
37
+ sse: {},
38
+ };
39
+ addDocsTools(mcpServer);
40
+ addGuidesTools(mcpServer);
41
+ // SSE endpoint for legacy clients
42
+ // Claude Code only supports SSE as of 2025-06-04
43
+ app.get('/sse', async (req, res) => {
44
+ const transport = new SSEServerTransport('/messages', res);
45
+ transports.sse[transport.sessionId] = transport;
46
+ res.on('close', () => {
47
+ delete transports.sse[transport.sessionId];
48
+ });
49
+ await mcpServer.connect(transport);
50
+ });
51
+ // Companion endpoint for sending messages
52
+ app.post('/messages', async (req, res) => {
53
+ const sessionId = req.query.sessionId;
54
+ const transport = transports.sse[sessionId];
55
+ if (transport) {
56
+ await transport.handlePostMessage(req, res, req.body);
57
+ }
58
+ else {
59
+ res.status(400).send('No transport found for sessionId');
60
+ }
61
+ });
62
+ app.listen(port, () => {
63
+ const portMessage = port !== requestedPort
64
+ ? `${port} (requested ${requestedPort} was in use)`
65
+ : `${port}`;
66
+ logger.debugMessage(`[locadex-mcp] started on port ${portMessage} with state file ${stateFile}`);
67
+ });
31
68
  }
32
- main();
33
- //# sourceMappingURL=mcp.js.map
34
- //# debugId=d5982bc6-3621-56f8-ac4a-8f0368dd1b1e
69
+ // Start the SSE server
70
+ start().catch(async (error) => {
71
+ logger.error(`[locadex-mcp] Failed to start: ${error instanceof Error ? error.message : String(error)}`);
72
+ await exit(1);
73
+ });
74
+ //# sourceMappingURL=mcp.js.map
package/dist/mcp.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"mcp.js","sources":["mcp.ts"],"sourceRoot":"/","sourcesContent":["#!/usr/bin/env node\n\nimport './telemetry.js';\nimport { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';\nimport { addDocsTools } from './mcp/tools/docs.js';\nimport { existsSync, readFileSync } from 'node:fs';\nimport { fromPackageRoot } from './utils/getPaths.js';\nimport { addGuidesTools } from './mcp/tools/guides.js';\n\nasync function main() {\n const stateFile = process.env.LOCADEX_FILES_STATE_FILE_PATH;\n if (stateFile && existsSync(stateFile)) {\n const state = JSON.parse(readFileSync(stateFile, 'utf8'));\n console.error(`[locadex-mcp] state: ${JSON.stringify(state, null, 2)}`);\n } else {\n throw new Error(`[locadex-mcp] state file not found: ${stateFile}`);\n }\n\n const server = new McpServer({\n name: 'Locadex: AI Agent for Internationalization',\n version: JSON.parse(readFileSync(fromPackageRoot('package.json'), 'utf8'))\n .version,\n });\n addDocsTools(server);\n addGuidesTools(server);\n\n console.error('[locadex-mcp] All tools registered');\n const transport = new StdioServerTransport();\n await server.connect(transport);\n console.error('[locadex-mcp] started on stdio');\n}\nmain();\n"],"names":[],"mappings":";;;AAEA,OAAO,gBAAgB,CAAC;AACxB,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAEvD,KAAK,UAAU,IAAI;IACjB,MAAM,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,6BAA6B,CAAC;IAC5D,IAAI,SAAS,IAAI,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;QACvC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC,CAAC;QAC1D,OAAO,CAAC,KAAK,CAAC,wBAAwB,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;IAC1E,CAAC;SAAM,CAAC;QACN,MAAM,IAAI,KAAK,CAAC,uCAAuC,SAAS,EAAE,CAAC,CAAC;IACtE,CAAC;IAED,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC;QAC3B,IAAI,EAAE,4CAA4C;QAClD,OAAO,EAAE,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,eAAe,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC,CAAC;aACvE,OAAO;KACX,CAAC,CAAC;IACH,YAAY,CAAC,MAAM,CAAC,CAAC;IACrB,cAAc,CAAC,MAAM,CAAC,CAAC;IAEvB,OAAO,CAAC,KAAK,CAAC,oCAAoC,CAAC,CAAC;IACpD,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;IAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAChC,OAAO,CAAC,KAAK,CAAC,gCAAgC,CAAC,CAAC;AAClD,CAAC;AACD,IAAI,EAAE,CAAC","debug_id":"d5982bc6-3621-56f8-ac4a-8f0368dd1b1e"}
1
+ {"version":3,"file":"mcp.js","sourceRoot":"/","sources":["mcp.ts"],"names":[],"mappings":"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","sourcesContent":["#!/usr/bin/env node\n\nimport { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { addDocsTools } from './mcp/tools/docs.js';\nimport { existsSync, readFileSync } from 'node:fs';\nimport { fromPackageRoot } from './utils/getPaths.js';\nimport { addGuidesTools } from './mcp/tools/guides.js';\nimport express from 'express';\nimport { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';\nimport { SSEServerTransport } from '@modelcontextprotocol/sdk/server/sse.js';\nimport { logger } from './logging/logger.js';\nimport { findAvailablePort } from './mcp/getPort.js';\nimport { exit } from './utils/shutdown.js';\n\nexport async function start() {\n const stateFile = process.env.LOCADEX_FILES_STATE_FILE_PATH;\n const logFile = process.env.LOCADEX_LOG_FILE_PATH;\n const requestedPort = process.env.PORT ? parseInt(process.env.PORT) : 8888;\n const port = await findAvailablePort(requestedPort);\n\n const verbose = process.env.LOCADEX_VERBOSE === 'true';\n const debug = process.env.LOCADEX_DEBUG === 'true';\n\n logger.initialize({ verbose, debug }, logFile);\n\n if (stateFile && existsSync(stateFile)) {\n const state = JSON.parse(readFileSync(stateFile, 'utf8'));\n logger.debugMessage(\n `[locadex-mcp] state: ${JSON.stringify(state, null, 2)}`\n );\n } else {\n throw new Error(`[locadex-mcp] state file not found: ${stateFile}`);\n }\n\n const mcpServer = new McpServer({\n name: 'Locadex: AI Agent for Internationalization',\n version: JSON.parse(readFileSync(fromPackageRoot('package.json'), 'utf8'))\n .version,\n });\n\n const app = express();\n app.use(express.json());\n\n // Store transports for each session type\n const transports = {\n streamable: {} as Record<string, StreamableHTTPServerTransport>,\n sse: {} as Record<string, SSEServerTransport>,\n };\n\n addDocsTools(mcpServer);\n addGuidesTools(mcpServer);\n\n // SSE endpoint for legacy clients\n // Claude Code only supports SSE as of 2025-06-04\n app.get('/sse', async (req, res) => {\n const transport = new SSEServerTransport('/messages', res);\n transports.sse[transport.sessionId] = transport;\n\n res.on('close', () => {\n delete transports.sse[transport.sessionId];\n });\n\n await mcpServer.connect(transport);\n });\n\n // Companion endpoint for sending messages\n app.post('/messages', async (req, res) => {\n const sessionId = req.query.sessionId as string;\n const transport = transports.sse[sessionId];\n if (transport) {\n await transport.handlePostMessage(req, res, req.body);\n } else {\n res.status(400).send('No transport found for sessionId');\n }\n });\n\n app.listen(port, () => {\n const portMessage =\n port !== requestedPort\n ? `${port} (requested ${requestedPort} was in use)`\n : `${port}`;\n logger.debugMessage(\n `[locadex-mcp] started on port ${portMessage} with state file ${stateFile}`\n );\n });\n}\n\n// Start the SSE server\nstart().catch(async (error) => {\n logger.error(\n `[locadex-mcp] Failed to start: ${error instanceof Error ? error.message : String(error)}`\n );\n await exit(1);\n});\n"]}
@@ -1,5 +1,3 @@
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]="1e9e969a-185e-5a86-a7a7-a61c5b750119")}catch(e){}}();
3
1
  import { guides } from '../mcp/tools/guides.js';
4
2
  import { docsTools } from '../mcp/tools/docs.js';
5
3
  export const mcpDocsTools = Object.keys(docsTools).map((tool) => `mcp__locadex__${tool}`);
@@ -13,5 +11,4 @@ ${mcpDocsTools.join('\n')}
13
11
  ${mcpGuidesTools.join('\n')}
14
12
 
15
13
  Generally, you should use the guides tools to help you with your tasks. You should only call the docs tools when you need specific information not covered by the guides.`;
16
- //# sourceMappingURL=system.js.map
17
- //# debugId=1e9e969a-185e-5a86-a7a7-a61c5b750119
14
+ //# sourceMappingURL=system.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"system.js","sources":["prompts/system.ts"],"sourceRoot":"/","sourcesContent":["import { guides } from '../mcp/tools/guides.js';\nimport { docsTools } from '../mcp/tools/docs.js';\n\nexport const mcpDocsTools = Object.keys(docsTools).map(\n (tool) => `mcp__locadex__${tool}`\n);\n\nexport const mcpGuidesTools = guides.map(\n (guide) => `mcp__locadex__${guide.id}`\n);\n\nexport const allMcpPrompt = `You have access to mcp tools made available via the 'locadex' mcp server:\n\n## Documentation Tools:\n${mcpDocsTools.join('\\n')}\n\n## Guide Tools:\n${mcpGuidesTools.join('\\n')}\n\nGenerally, you should use the guides tools to help you with your tasks. You should only call the docs tools when you need specific information not covered by the guides.`;\n"],"names":[],"mappings":";;AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAChD,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAEjD,MAAM,CAAC,MAAM,YAAY,GAAG,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,GAAG,CACpD,CAAC,IAAI,EAAE,EAAE,CAAC,iBAAiB,IAAI,EAAE,CAClC,CAAC;AAEF,MAAM,CAAC,MAAM,cAAc,GAAG,MAAM,CAAC,GAAG,CACtC,CAAC,KAAK,EAAE,EAAE,CAAC,iBAAiB,KAAK,CAAC,EAAE,EAAE,CACvC,CAAC;AAEF,MAAM,CAAC,MAAM,YAAY,GAAG;;;EAG1B,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC;;;EAGvB,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC;;0KAE+I,CAAC","debug_id":"1e9e969a-185e-5a86-a7a7-a61c5b750119"}
1
+ {"version":3,"file":"system.js","sourceRoot":"/","sources":["prompts/system.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAChD,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAEjD,MAAM,CAAC,MAAM,YAAY,GAAG,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,GAAG,CACpD,CAAC,IAAI,EAAE,EAAE,CAAC,iBAAiB,IAAI,EAAE,CAClC,CAAC;AAEF,MAAM,CAAC,MAAM,cAAc,GAAG,MAAM,CAAC,GAAG,CACtC,CAAC,KAAK,EAAE,EAAE,CAAC,iBAAiB,KAAK,CAAC,EAAE,EAAE,CACvC,CAAC;AAEF,MAAM,CAAC,MAAM,YAAY,GAAG;;;EAG1B,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC;;;EAGvB,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC;;0KAE+I,CAAC","sourcesContent":["import { guides } from '../mcp/tools/guides.js';\nimport { docsTools } from '../mcp/tools/docs.js';\n\nexport const mcpDocsTools = Object.keys(docsTools).map(\n (tool) => `mcp__locadex__${tool}`\n);\n\nexport const mcpGuidesTools = guides.map(\n (guide) => `mcp__locadex__${guide.id}`\n);\n\nexport const allMcpPrompt = `You have access to mcp tools made available via the 'locadex' mcp server:\n\n## Documentation Tools:\n${mcpDocsTools.join('\\n')}\n\n## Guide Tools:\n${mcpGuidesTools.join('\\n')}\n\nGenerally, you should use the guides tools to help you with your tasks. You should only call the docs tools when you need specific information not covered by the guides.`;\n"]}
@@ -0,0 +1,72 @@
1
+ /**
2
+ * Interface for defining how to process tasks in parallel.
3
+ * Separates task preparation (preProcess) from result handling (postProcess).
4
+ *
5
+ * @template TTask - The type of individual tasks being processed
6
+ * @template TContext - The type of shared context/configuration
7
+ */
8
+ export interface TaskProcessor<TTask, TContext> {
9
+ /**
10
+ * Prepares tasks for processing and generates the prompt for the AI agent.
11
+ * Called before each batch is sent to an agent.
12
+ *
13
+ * @param tasks - Batch of tasks to process
14
+ * @param context - Shared context containing configuration and state
15
+ * @returns Promise that resolves to the prompt string for the AI agent
16
+ */
17
+ preProcess: (tasks: TTask[], context: TContext) => Promise<string>;
18
+ /**
19
+ * Handles the results after the AI agent completes processing.
20
+ * Called after each batch is successfully processed.
21
+ *
22
+ * @param tasks - The batch of tasks that were processed
23
+ * @param context - Shared context containing configuration and state
24
+ * @param agentReport - The report/output generated by the AI agent
25
+ */
26
+ postProcess: (tasks: TTask[], context: TContext, agentReport: string) => Promise<void>;
27
+ }
28
+ /**
29
+ * Configuration options for parallel processing behavior.
30
+ */
31
+ export interface ParallelProcessingOptions {
32
+ /** Number of concurrent agents to run in parallel */
33
+ concurrency: number;
34
+ /** Number of tasks to process in each batch */
35
+ batchSize: number;
36
+ }
37
+ /**
38
+ * Executes tasks in parallel using a pool of agents with proper concurrency control.
39
+ *
40
+ * This is a generic parallel processing framework that handles:
41
+ * - Task queue management with thread-safe access
42
+ * - Agent pool creation and lifecycle management
43
+ * - Error handling and abort signal propagation
44
+ * - Proper cleanup and resource management
45
+ *
46
+ * @template TTask - The type of tasks to process (e.g., string, object, etc.)
47
+ * @template TContext - The type of context passed to the processor functions
48
+ *
49
+ * @param taskQueue - Array of tasks to process. Will be consumed (mutated) during processing.
50
+ * @param processor - Object implementing preProcess and postProcess methods for task handling
51
+ * @param context - Context object passed to processor methods, containing shared state/config
52
+ * @param options - Configuration for parallel processing (concurrency level, batch size)
53
+ *
54
+ * @throws {Error} If processing fails or is aborted
55
+ *
56
+ * @example
57
+ * ```typescript
58
+ * const processor: TaskProcessor<string, { config: Config }> = {
59
+ * preProcess: async (files, context) => generatePrompt(files, context.config),
60
+ * postProcess: async (files, context, report) => handleResults(files, report)
61
+ * };
62
+ *
63
+ * await runParallelProcessing(
64
+ * ['file1.ts', 'file2.ts'],
65
+ * processor,
66
+ * { config: myConfig },
67
+ * { concurrency: 3, batchSize: 2 }
68
+ * );
69
+ * ```
70
+ */
71
+ export declare function runParallelProcessing<TTask, TContext>(taskQueue: TTask[], processor: TaskProcessor<TTask, TContext>, context: TContext, options: ParallelProcessingOptions, maxRetries?: number): Promise<void>;
72
+ //# sourceMappingURL=concurrency.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"concurrency.d.ts","sourceRoot":"/","sources":["tasks/concurrency.ts"],"names":[],"mappings":"AAIA;;;;;;GAMG;AACH,MAAM,WAAW,aAAa,CAAC,KAAK,EAAE,QAAQ;IAC5C;;;;;;;OAOG;IACH,UAAU,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE,OAAO,EAAE,QAAQ,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IAEnE;;;;;;;OAOG;IACH,WAAW,EAAE,CACX,KAAK,EAAE,KAAK,EAAE,EACd,OAAO,EAAE,QAAQ,EACjB,WAAW,EAAE,MAAM,KAChB,OAAO,CAAC,IAAI,CAAC,CAAC;CACpB;AAED;;GAEG;AACH,MAAM,WAAW,yBAAyB;IACxC,qDAAqD;IACrD,WAAW,EAAE,MAAM,CAAC;IACpB,+CAA+C;IAC/C,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,wBAAsB,qBAAqB,CAAC,KAAK,EAAE,QAAQ,EACzD,SAAS,EAAE,KAAK,EAAE,EAClB,SAAS,EAAE,aAAa,CAAC,KAAK,EAAE,QAAQ,CAAC,EACzC,OAAO,EAAE,QAAQ,EACjB,OAAO,EAAE,yBAAyB,EAClC,UAAU,GAAE,MAAU,GACrB,OAAO,CAAC,IAAI,CAAC,CAoHf"}
@@ -0,0 +1,132 @@
1
+ import { LocadexManager } from '../utils/locadexManager.js';
2
+ import { logger } from '../logging/logger.js';
3
+ import { exit } from '../utils/shutdown.js';
4
+ /**
5
+ * Executes tasks in parallel using a pool of agents with proper concurrency control.
6
+ *
7
+ * This is a generic parallel processing framework that handles:
8
+ * - Task queue management with thread-safe access
9
+ * - Agent pool creation and lifecycle management
10
+ * - Error handling and abort signal propagation
11
+ * - Proper cleanup and resource management
12
+ *
13
+ * @template TTask - The type of tasks to process (e.g., string, object, etc.)
14
+ * @template TContext - The type of context passed to the processor functions
15
+ *
16
+ * @param taskQueue - Array of tasks to process. Will be consumed (mutated) during processing.
17
+ * @param processor - Object implementing preProcess and postProcess methods for task handling
18
+ * @param context - Context object passed to processor methods, containing shared state/config
19
+ * @param options - Configuration for parallel processing (concurrency level, batch size)
20
+ *
21
+ * @throws {Error} If processing fails or is aborted
22
+ *
23
+ * @example
24
+ * ```typescript
25
+ * const processor: TaskProcessor<string, { config: Config }> = {
26
+ * preProcess: async (files, context) => generatePrompt(files, context.config),
27
+ * postProcess: async (files, context, report) => handleResults(files, report)
28
+ * };
29
+ *
30
+ * await runParallelProcessing(
31
+ * ['file1.ts', 'file2.ts'],
32
+ * processor,
33
+ * { config: myConfig },
34
+ * { concurrency: 3, batchSize: 2 }
35
+ * );
36
+ * ```
37
+ */
38
+ export async function runParallelProcessing(taskQueue, processor, context, options, maxRetries = 1) {
39
+ const { concurrency, batchSize } = options;
40
+ const manager = LocadexManager.getInstance();
41
+ const agentAbortController = manager.getAgentAbortController();
42
+ let firstError = null;
43
+ // Mutex for task queue access
44
+ let taskQueueMutex = Promise.resolve();
45
+ // Helper function to safely get tasks from queue
46
+ const getNextTasks = async (batchSize) => {
47
+ return new Promise((resolve) => {
48
+ taskQueueMutex = taskQueueMutex.then(() => {
49
+ const tasks = taskQueue.splice(0, batchSize);
50
+ resolve(tasks);
51
+ });
52
+ });
53
+ };
54
+ const processTask = async () => {
55
+ while (taskQueue.length > 0 && !agentAbortController.signal.aborted) {
56
+ // Check if we should abort early
57
+ if (agentAbortController.signal.aborted) {
58
+ return;
59
+ }
60
+ // Get an available agent atomically
61
+ const agentInfo = await manager.getAvailableAgent();
62
+ if (!agentInfo) {
63
+ // No available agents, wait a bit (but check for abort)
64
+ await new Promise((resolve) => {
65
+ const timeout = global.setTimeout(resolve, 100);
66
+ agentAbortController.signal.addEventListener('abort', () => {
67
+ global.clearTimeout(timeout);
68
+ resolve(undefined);
69
+ });
70
+ });
71
+ continue;
72
+ }
73
+ const { id: agentId, agent } = agentInfo;
74
+ // Get the next batch of tasks (thread-safe)
75
+ const tasks = await getNextTasks(batchSize);
76
+ if (tasks.length === 0) {
77
+ manager.markAgentFree(agentId);
78
+ break;
79
+ }
80
+ logger.debugMessage(`Using agent ${agentId} for ${tasks.length} tasks.`);
81
+ // Process tasks using the provided processor
82
+ try {
83
+ // Pre-process: generate prompt
84
+ const prompt = await processor.preProcess(tasks, context);
85
+ // dynamic timeout based on the number of tasks
86
+ const dynamicTimeoutSec = manager.getTimeoutFactor() * tasks.length;
87
+ // Claude call with timeout and retry (handled inside agent.run)
88
+ await agent.run(prompt, {}, dynamicTimeoutSec, maxRetries);
89
+ const agentReport = agent.generateReport();
90
+ manager.markAgentFree(agentId);
91
+ // Post-process: handle reports, progress, etc.
92
+ await processor.postProcess(tasks, context, agentReport);
93
+ }
94
+ catch (error) {
95
+ // Check if this is an abort
96
+ if (agentAbortController.signal.aborted) {
97
+ return;
98
+ }
99
+ // Capture the first error and signal all other agents to abort
100
+ if (!firstError) {
101
+ firstError = new Error(`Error in claude parallel process (${agentId}): ${error}`);
102
+ logger.debugMessage(firstError.message);
103
+ }
104
+ await exit(1); // Exit this agent's processing immediately
105
+ return;
106
+ }
107
+ }
108
+ };
109
+ // Create agent pool
110
+ manager.createAgentPool();
111
+ // Start parallel processing
112
+ const processingPromises = Array.from({ length: concurrency }, () => processTask());
113
+ try {
114
+ await Promise.all(processingPromises);
115
+ }
116
+ catch (error) {
117
+ // Check if this is an abort
118
+ if (agentAbortController.signal.aborted) {
119
+ throw new Error('Processing aborted');
120
+ }
121
+ // This shouldn't happen since we handle errors within processTask
122
+ logger.debugMessage(`Unexpected error in parallel processing: ${error}`);
123
+ if (!firstError) {
124
+ firstError = new Error(`Unexpected error in parallel processing: ${error}`);
125
+ }
126
+ throw firstError;
127
+ }
128
+ if (firstError) {
129
+ throw firstError;
130
+ }
131
+ }
132
+ //# sourceMappingURL=concurrency.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"concurrency.js","sourceRoot":"/","sources":["tasks/concurrency.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAC5D,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAC9C,OAAO,EAAE,IAAI,EAAE,MAAM,sBAAsB,CAAC;AA6C5C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,MAAM,CAAC,KAAK,UAAU,qBAAqB,CACzC,SAAkB,EAClB,SAAyC,EACzC,OAAiB,EACjB,OAAkC,EAClC,aAAqB,CAAC;IAEtB,MAAM,EAAE,WAAW,EAAE,SAAS,EAAE,GAAG,OAAO,CAAC;IAC3C,MAAM,OAAO,GAAG,cAAc,CAAC,WAAW,EAAE,CAAC;IAE7C,MAAM,oBAAoB,GAAG,OAAO,CAAC,uBAAuB,EAAE,CAAC;IAC/D,IAAI,UAAU,GAAiB,IAAI,CAAC;IAEpC,8BAA8B;IAC9B,IAAI,cAAc,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;IAEvC,iDAAiD;IACjD,MAAM,YAAY,GAAG,KAAK,EAAE,SAAiB,EAAoB,EAAE;QACjE,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;YAC7B,cAAc,GAAG,cAAc,CAAC,IAAI,CAAC,GAAG,EAAE;gBACxC,MAAM,KAAK,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC;gBAC7C,OAAO,CAAC,KAAK,CAAC,CAAC;YACjB,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;IACL,CAAC,CAAC;IAEF,MAAM,WAAW,GAAG,KAAK,IAAmB,EAAE;QAC5C,OAAO,SAAS,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,oBAAoB,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;YACpE,iCAAiC;YACjC,IAAI,oBAAoB,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;gBACxC,OAAO;YACT,CAAC;YAED,oCAAoC;YACpC,MAAM,SAAS,GAAG,MAAM,OAAO,CAAC,iBAAiB,EAAE,CAAC;YACpD,IAAI,CAAC,SAAS,EAAE,CAAC;gBACf,wDAAwD;gBACxD,MAAM,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;oBAC5B,MAAM,OAAO,GAAG,MAAM,CAAC,UAAU,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;oBAChD,oBAAoB,CAAC,MAAM,CAAC,gBAAgB,CAAC,OAAO,EAAE,GAAG,EAAE;wBACzD,MAAM,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC;wBAC7B,OAAO,CAAC,SAAS,CAAC,CAAC;oBACrB,CAAC,CAAC,CAAC;gBACL,CAAC,CAAC,CAAC;gBACH,SAAS;YACX,CAAC;YAED,MAAM,EAAE,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,GAAG,SAAS,CAAC;YAEzC,4CAA4C;YAC5C,MAAM,KAAK,GAAG,MAAM,YAAY,CAAC,SAAS,CAAC,CAAC;YAC5C,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBACvB,OAAO,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;gBAC/B,MAAM;YACR,CAAC;YAED,MAAM,CAAC,YAAY,CAAC,eAAe,OAAO,QAAQ,KAAK,CAAC,MAAM,SAAS,CAAC,CAAC;YAEzE,6CAA6C;YAC7C,IAAI,CAAC;gBACH,+BAA+B;gBAC/B,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,UAAU,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;gBAE1D,+CAA+C;gBAC/C,MAAM,iBAAiB,GAAG,OAAO,CAAC,gBAAgB,EAAE,GAAG,KAAK,CAAC,MAAM,CAAC;gBAEpE,gEAAgE;gBAChE,MAAM,KAAK,CAAC,GAAG,CAAC,MAAM,EAAE,EAAE,EAAE,iBAAiB,EAAE,UAAU,CAAC,CAAC;gBAE3D,MAAM,WAAW,GAAG,KAAK,CAAC,cAAc,EAAE,CAAC;gBAC3C,OAAO,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;gBAE/B,+CAA+C;gBAC/C,MAAM,SAAS,CAAC,WAAW,CAAC,KAAK,EAAE,OAAO,EAAE,WAAW,CAAC,CAAC;YAC3D,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,4BAA4B;gBAC5B,IAAI,oBAAoB,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;oBACxC,OAAO;gBACT,CAAC;gBAED,+DAA+D;gBAC/D,IAAI,CAAC,UAAU,EAAE,CAAC;oBAChB,UAAU,GAAG,IAAI,KAAK,CACpB,qCAAqC,OAAO,MAAM,KAAK,EAAE,CAC1D,CAAC;oBACF,MAAM,CAAC,YAAY,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;gBAC1C,CAAC;gBACD,MAAM,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,2CAA2C;gBAC1D,OAAO;YACT,CAAC;QACH,CAAC;IACH,CAAC,CAAC;IAEF,oBAAoB;IACpB,OAAO,CAAC,eAAe,EAAE,CAAC;IAE1B,4BAA4B;IAC5B,MAAM,kBAAkB,GAAG,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,WAAW,EAAE,EAAE,GAAG,EAAE,CAClE,WAAW,EAAE,CACd,CAAC;IAEF,IAAI,CAAC;QACH,MAAM,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC;IACxC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,4BAA4B;QAC5B,IAAI,oBAAoB,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;YACxC,MAAM,IAAI,KAAK,CAAC,oBAAoB,CAAC,CAAC;QACxC,CAAC;QAED,kEAAkE;QAClE,MAAM,CAAC,YAAY,CAAC,4CAA4C,KAAK,EAAE,CAAC,CAAC;QACzE,IAAI,CAAC,UAAU,EAAE,CAAC;YAChB,UAAU,GAAG,IAAI,KAAK,CACpB,4CAA4C,KAAK,EAAE,CACpD,CAAC;QACJ,CAAC;QACD,MAAM,UAAU,CAAC;IACnB,CAAC;IAED,IAAI,UAAU,EAAE,CAAC;QACf,MAAM,UAAU,CAAC;IACnB,CAAC;AACH,CAAC","sourcesContent":["import { LocadexManager } from '../utils/locadexManager.js';\nimport { logger } from '../logging/logger.js';\nimport { exit } from '../utils/shutdown.js';\n\n/**\n * Interface for defining how to process tasks in parallel.\n * Separates task preparation (preProcess) from result handling (postProcess).\n *\n * @template TTask - The type of individual tasks being processed\n * @template TContext - The type of shared context/configuration\n */\nexport interface TaskProcessor<TTask, TContext> {\n /**\n * Prepares tasks for processing and generates the prompt for the AI agent.\n * Called before each batch is sent to an agent.\n *\n * @param tasks - Batch of tasks to process\n * @param context - Shared context containing configuration and state\n * @returns Promise that resolves to the prompt string for the AI agent\n */\n preProcess: (tasks: TTask[], context: TContext) => Promise<string>;\n\n /**\n * Handles the results after the AI agent completes processing.\n * Called after each batch is successfully processed.\n *\n * @param tasks - The batch of tasks that were processed\n * @param context - Shared context containing configuration and state\n * @param agentReport - The report/output generated by the AI agent\n */\n postProcess: (\n tasks: TTask[],\n context: TContext,\n agentReport: string\n ) => Promise<void>;\n}\n\n/**\n * Configuration options for parallel processing behavior.\n */\nexport interface ParallelProcessingOptions {\n /** Number of concurrent agents to run in parallel */\n concurrency: number;\n /** Number of tasks to process in each batch */\n batchSize: number;\n}\n\n/**\n * Executes tasks in parallel using a pool of agents with proper concurrency control.\n *\n * This is a generic parallel processing framework that handles:\n * - Task queue management with thread-safe access\n * - Agent pool creation and lifecycle management\n * - Error handling and abort signal propagation\n * - Proper cleanup and resource management\n *\n * @template TTask - The type of tasks to process (e.g., string, object, etc.)\n * @template TContext - The type of context passed to the processor functions\n *\n * @param taskQueue - Array of tasks to process. Will be consumed (mutated) during processing.\n * @param processor - Object implementing preProcess and postProcess methods for task handling\n * @param context - Context object passed to processor methods, containing shared state/config\n * @param options - Configuration for parallel processing (concurrency level, batch size)\n *\n * @throws {Error} If processing fails or is aborted\n *\n * @example\n * ```typescript\n * const processor: TaskProcessor<string, { config: Config }> = {\n * preProcess: async (files, context) => generatePrompt(files, context.config),\n * postProcess: async (files, context, report) => handleResults(files, report)\n * };\n *\n * await runParallelProcessing(\n * ['file1.ts', 'file2.ts'],\n * processor,\n * { config: myConfig },\n * { concurrency: 3, batchSize: 2 }\n * );\n * ```\n */\nexport async function runParallelProcessing<TTask, TContext>(\n taskQueue: TTask[],\n processor: TaskProcessor<TTask, TContext>,\n context: TContext,\n options: ParallelProcessingOptions,\n maxRetries: number = 1\n): Promise<void> {\n const { concurrency, batchSize } = options;\n const manager = LocadexManager.getInstance();\n\n const agentAbortController = manager.getAgentAbortController();\n let firstError: Error | null = null;\n\n // Mutex for task queue access\n let taskQueueMutex = Promise.resolve();\n\n // Helper function to safely get tasks from queue\n const getNextTasks = async (batchSize: number): Promise<TTask[]> => {\n return new Promise((resolve) => {\n taskQueueMutex = taskQueueMutex.then(() => {\n const tasks = taskQueue.splice(0, batchSize);\n resolve(tasks);\n });\n });\n };\n\n const processTask = async (): Promise<void> => {\n while (taskQueue.length > 0 && !agentAbortController.signal.aborted) {\n // Check if we should abort early\n if (agentAbortController.signal.aborted) {\n return;\n }\n\n // Get an available agent atomically\n const agentInfo = await manager.getAvailableAgent();\n if (!agentInfo) {\n // No available agents, wait a bit (but check for abort)\n await new Promise((resolve) => {\n const timeout = global.setTimeout(resolve, 100);\n agentAbortController.signal.addEventListener('abort', () => {\n global.clearTimeout(timeout);\n resolve(undefined);\n });\n });\n continue;\n }\n\n const { id: agentId, agent } = agentInfo;\n\n // Get the next batch of tasks (thread-safe)\n const tasks = await getNextTasks(batchSize);\n if (tasks.length === 0) {\n manager.markAgentFree(agentId);\n break;\n }\n\n logger.debugMessage(`Using agent ${agentId} for ${tasks.length} tasks.`);\n\n // Process tasks using the provided processor\n try {\n // Pre-process: generate prompt\n const prompt = await processor.preProcess(tasks, context);\n\n // dynamic timeout based on the number of tasks\n const dynamicTimeoutSec = manager.getTimeoutFactor() * tasks.length;\n\n // Claude call with timeout and retry (handled inside agent.run)\n await agent.run(prompt, {}, dynamicTimeoutSec, maxRetries);\n\n const agentReport = agent.generateReport();\n manager.markAgentFree(agentId);\n\n // Post-process: handle reports, progress, etc.\n await processor.postProcess(tasks, context, agentReport);\n } catch (error) {\n // Check if this is an abort\n if (agentAbortController.signal.aborted) {\n return;\n }\n\n // Capture the first error and signal all other agents to abort\n if (!firstError) {\n firstError = new Error(\n `Error in claude parallel process (${agentId}): ${error}`\n );\n logger.debugMessage(firstError.message);\n }\n await exit(1); // Exit this agent's processing immediately\n return;\n }\n }\n };\n\n // Create agent pool\n manager.createAgentPool();\n\n // Start parallel processing\n const processingPromises = Array.from({ length: concurrency }, () =>\n processTask()\n );\n\n try {\n await Promise.all(processingPromises);\n } catch (error) {\n // Check if this is an abort\n if (agentAbortController.signal.aborted) {\n throw new Error('Processing aborted');\n }\n\n // This shouldn't happen since we handle errors within processTask\n logger.debugMessage(`Unexpected error in parallel processing: ${error}`);\n if (!firstError) {\n firstError = new Error(\n `Unexpected error in parallel processing: ${error}`\n );\n }\n throw firstError;\n }\n\n if (firstError) {\n throw firstError;\n }\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"i18n.d.ts","sourceRoot":"/","sources":["tasks/i18n.ts"],"names":[],"mappings":"AAqBA,wBAAsB,QAAQ,kBAmS7B"}
1
+ {"version":3,"file":"i18n.d.ts","sourceRoot":"/","sources":["tasks/i18n.ts"],"names":[],"mappings":"AAuBA,wBAAsB,QAAQ,kBAyN7B"}