@xdevops/issue-auto-finish 1.0.2 → 1.0.4

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 (135) hide show
  1. package/dist/KnowledgeAnalyzer-EZSJT2MJ.js +13 -0
  2. package/dist/KnowledgeAnalyzer-EZSJT2MJ.js.map +1 -0
  3. package/dist/KnowledgeStore-4ROC6F56.js +10 -0
  4. package/dist/KnowledgeStore-4ROC6F56.js.map +1 -0
  5. package/dist/ai-runner/AIRunner.d.ts +2 -0
  6. package/dist/ai-runner/AIRunner.d.ts.map +1 -1
  7. package/dist/ai-runner/BaseAIRunner.d.ts +9 -0
  8. package/dist/ai-runner/BaseAIRunner.d.ts.map +1 -1
  9. package/dist/ai-runner-RGAJPOOW.js +16 -0
  10. package/dist/ai-runner-RGAJPOOW.js.map +1 -0
  11. package/dist/analyze-ONQDTYCN.js +72 -0
  12. package/dist/analyze-ONQDTYCN.js.map +1 -0
  13. package/dist/chunk-3JUHZGX5.js +171 -0
  14. package/dist/chunk-3JUHZGX5.js.map +1 -0
  15. package/dist/chunk-5JYCGAU3.js +318 -0
  16. package/dist/chunk-5JYCGAU3.js.map +1 -0
  17. package/dist/chunk-5VUB3UUK.js +643 -0
  18. package/dist/chunk-5VUB3UUK.js.map +1 -0
  19. package/dist/{chunk-OWVT3Z34.js → chunk-JFYAXNNS.js} +121 -31
  20. package/dist/chunk-JFYAXNNS.js.map +1 -0
  21. package/dist/chunk-MH6LHFPB.js +188 -0
  22. package/dist/chunk-MH6LHFPB.js.map +1 -0
  23. package/dist/{chunk-TBIEB3JY.js → chunk-N5YK6YVI.js} +592 -767
  24. package/dist/chunk-N5YK6YVI.js.map +1 -0
  25. package/dist/{chunk-RIUI4ROA.js → chunk-PECYMYAK.js} +2 -2
  26. package/dist/{chunk-I3T573SU.js → chunk-PTIL5AY2.js} +65 -2
  27. package/dist/chunk-PTIL5AY2.js.map +1 -0
  28. package/dist/chunk-SWG2Y7YX.js +410 -0
  29. package/dist/chunk-SWG2Y7YX.js.map +1 -0
  30. package/dist/chunk-TZ6C7HL5.js +59 -0
  31. package/dist/chunk-TZ6C7HL5.js.map +1 -0
  32. package/dist/{chunk-IDUKWCC2.js → chunk-VFQYIC6L.js} +1151 -80
  33. package/dist/chunk-VFQYIC6L.js.map +1 -0
  34. package/dist/cli/commands/analyze.d.ts +8 -0
  35. package/dist/cli/commands/analyze.d.ts.map +1 -0
  36. package/dist/cli/commands/init.d.ts.map +1 -1
  37. package/dist/cli.js +67 -3
  38. package/dist/cli.js.map +1 -1
  39. package/dist/clients/GongfengClient.d.ts +5 -0
  40. package/dist/clients/GongfengClient.d.ts.map +1 -1
  41. package/dist/config-6GFBDMGD.js +7 -0
  42. package/dist/config-6GFBDMGD.js.map +1 -0
  43. package/dist/config.d.ts +19 -0
  44. package/dist/config.d.ts.map +1 -1
  45. package/dist/{doctor-B26Q6JWI.js → doctor-ZPGIBA5N.js} +3 -3
  46. package/dist/events/EventBus.d.ts +1 -1
  47. package/dist/events/EventBus.d.ts.map +1 -1
  48. package/dist/git/GitOperations.d.ts +12 -0
  49. package/dist/git/GitOperations.d.ts.map +1 -1
  50. package/dist/i18n/locales/en.d.ts.map +1 -1
  51. package/dist/i18n/locales/zh-CN.d.ts.map +1 -1
  52. package/dist/index.d.ts.map +1 -1
  53. package/dist/index.js +11 -5
  54. package/dist/{init-L3VIWCOV.js → init-QDTII4SP.js} +10 -5
  55. package/dist/init-QDTII4SP.js.map +1 -0
  56. package/dist/knowledge/KnowledgeAnalyzer.d.ts +31 -0
  57. package/dist/knowledge/KnowledgeAnalyzer.d.ts.map +1 -0
  58. package/dist/knowledge/KnowledgeDefaults.d.ts +7 -0
  59. package/dist/knowledge/KnowledgeDefaults.d.ts.map +1 -0
  60. package/dist/knowledge/KnowledgeEntry.d.ts +30 -0
  61. package/dist/knowledge/KnowledgeEntry.d.ts.map +1 -0
  62. package/dist/knowledge/KnowledgeLoader.d.ts +18 -0
  63. package/dist/knowledge/KnowledgeLoader.d.ts.map +1 -0
  64. package/dist/knowledge/KnowledgeStore.d.ts +35 -0
  65. package/dist/knowledge/KnowledgeStore.d.ts.map +1 -0
  66. package/dist/knowledge/ProjectKnowledge.d.ts +79 -0
  67. package/dist/knowledge/ProjectKnowledge.d.ts.map +1 -0
  68. package/dist/knowledge/analyze-prompt.d.ts +2 -0
  69. package/dist/knowledge/analyze-prompt.d.ts.map +1 -0
  70. package/dist/knowledge/importers/GongfengExtractor.d.ts +27 -0
  71. package/dist/knowledge/importers/GongfengExtractor.d.ts.map +1 -0
  72. package/dist/knowledge/importers/IwikiImporter.d.ts +21 -0
  73. package/dist/knowledge/importers/IwikiImporter.d.ts.map +1 -0
  74. package/dist/knowledge/index.d.ts +12 -0
  75. package/dist/knowledge/index.d.ts.map +1 -0
  76. package/dist/lib.js +19 -10
  77. package/dist/orchestrator/PipelineOrchestrator.d.ts +5 -1
  78. package/dist/orchestrator/PipelineOrchestrator.d.ts.map +1 -1
  79. package/dist/phases/BasePhase.d.ts.map +1 -1
  80. package/dist/poller/IssuePoller.d.ts +5 -0
  81. package/dist/poller/IssuePoller.d.ts.map +1 -1
  82. package/dist/prompts/chat-templates.d.ts +4 -0
  83. package/dist/prompts/chat-templates.d.ts.map +1 -0
  84. package/dist/prompts/templates.d.ts +11 -0
  85. package/dist/prompts/templates.d.ts.map +1 -1
  86. package/dist/rules/RuleResolver.d.ts +4 -0
  87. package/dist/rules/RuleResolver.d.ts.map +1 -1
  88. package/dist/run.js +11 -5
  89. package/dist/run.js.map +1 -1
  90. package/dist/services/ChatService.d.ts +39 -0
  91. package/dist/services/ChatService.d.ts.map +1 -0
  92. package/dist/shutdown/ShutdownSignal.d.ts +3 -0
  93. package/dist/shutdown/ShutdownSignal.d.ts.map +1 -0
  94. package/dist/{start-TVN4SS6E.js → start-EDOZC5WL.js} +1 -1
  95. package/dist/tracker/IssueState.d.ts +1 -0
  96. package/dist/tracker/IssueState.d.ts.map +1 -1
  97. package/dist/tracker/IssueTracker.d.ts +2 -0
  98. package/dist/tracker/IssueTracker.d.ts.map +1 -1
  99. package/dist/updater/AutoUpdater.d.ts +33 -0
  100. package/dist/updater/AutoUpdater.d.ts.map +1 -0
  101. package/dist/updater/UpdateExecutor.d.ts +7 -0
  102. package/dist/updater/UpdateExecutor.d.ts.map +1 -0
  103. package/dist/updater/VersionChecker.d.ts +22 -0
  104. package/dist/updater/VersionChecker.d.ts.map +1 -0
  105. package/dist/web/WebServer.d.ts +4 -0
  106. package/dist/web/WebServer.d.ts.map +1 -1
  107. package/dist/web/routes/api.d.ts +4 -0
  108. package/dist/web/routes/api.d.ts.map +1 -1
  109. package/dist/web/routes/chat.d.ts +7 -0
  110. package/dist/web/routes/chat.d.ts.map +1 -0
  111. package/dist/web/routes/knowledge.d.ts +13 -0
  112. package/dist/web/routes/knowledge.d.ts.map +1 -0
  113. package/dist/web/routes/setup.d.ts.map +1 -1
  114. package/dist/webhook/CommandExecutor.d.ts +4 -0
  115. package/dist/webhook/CommandExecutor.d.ts.map +1 -1
  116. package/dist/webhook/CommandParser.d.ts +2 -2
  117. package/dist/webhook/CommandParser.d.ts.map +1 -1
  118. package/dist/webhook/WebhookHandler.d.ts +8 -0
  119. package/dist/webhook/WebhookHandler.d.ts.map +1 -1
  120. package/dist/webhook/WebhookServer.d.ts +2 -0
  121. package/dist/webhook/WebhookServer.d.ts.map +1 -1
  122. package/package.json +4 -2
  123. package/src/web/frontend/dist/assets/index-AcJ0lPIv.js +67 -0
  124. package/src/web/frontend/dist/assets/index-BbRt5BAr.css +1 -0
  125. package/src/web/frontend/dist/index.html +2 -2
  126. package/dist/chunk-I3T573SU.js.map +0 -1
  127. package/dist/chunk-IDUKWCC2.js.map +0 -1
  128. package/dist/chunk-OWVT3Z34.js.map +0 -1
  129. package/dist/chunk-TBIEB3JY.js.map +0 -1
  130. package/dist/init-L3VIWCOV.js.map +0 -1
  131. package/src/web/frontend/dist/assets/index-CQdlU9PE.js +0 -65
  132. package/src/web/frontend/dist/assets/index-CgMEkyZJ.css +0 -1
  133. /package/dist/{chunk-RIUI4ROA.js.map → chunk-PECYMYAK.js.map} +0 -0
  134. /package/dist/{doctor-B26Q6JWI.js.map → doctor-ZPGIBA5N.js.map} +0 -0
  135. /package/dist/{start-TVN4SS6E.js.map → start-EDOZC5WL.js.map} +0 -0
@@ -0,0 +1,188 @@
1
+ // src/config.ts
2
+ import { config as loadDotenv } from "dotenv";
3
+ import path from "path";
4
+ import fs from "fs";
5
+ import os from "os";
6
+ import { fileURLToPath } from "url";
7
+ var __dirname = path.dirname(fileURLToPath(import.meta.url));
8
+ function resolveEnvPath() {
9
+ if (process.env.IAF_CONFIG_PATH) return process.env.IAF_CONFIG_PATH;
10
+ const localEnv = path.resolve(__dirname, "../.env");
11
+ if (fs.existsSync(localEnv)) return localEnv;
12
+ const cwdEnv = path.resolve(process.cwd(), ".env");
13
+ if (fs.existsSync(cwdEnv)) return cwdEnv;
14
+ const globalEnv = path.join(os.homedir(), ".issue-auto-finish", ".env");
15
+ if (fs.existsSync(globalEnv)) return globalEnv;
16
+ return localEnv;
17
+ }
18
+ var _dotenvLoaded = false;
19
+ function ensureDotenvLoaded() {
20
+ if (_dotenvLoaded) return;
21
+ _dotenvLoaded = true;
22
+ loadDotenv({ path: resolveEnvPath() });
23
+ }
24
+ var DEFAULT_AI_MODEL = "Claude-4.6-Opus";
25
+ function requireEnv(key) {
26
+ const val = process.env[key];
27
+ if (!val) {
28
+ throw new Error(`Missing required environment variable: ${key}`);
29
+ }
30
+ return val;
31
+ }
32
+ function optionalEnv(key, defaultValue) {
33
+ return process.env[key] || defaultValue;
34
+ }
35
+ function loadConfig() {
36
+ ensureDotenvLoaded();
37
+ return {
38
+ gongfeng: {
39
+ apiUrl: requireEnv("GONGFENG_API_URL"),
40
+ privateToken: requireEnv("GONGFENG_PRIVATE_TOKEN"),
41
+ projectPath: requireEnv("GONGFENG_PROJECT_PATH")
42
+ },
43
+ project: {
44
+ workDir: requireEnv("PROJECT_WORK_DIR"),
45
+ gitRootDir: optionalEnv("GIT_ROOT_DIR", requireEnv("PROJECT_WORK_DIR")),
46
+ baseBranch: optionalEnv("BASE_BRANCH", "master"),
47
+ branchPrefix: optionalEnv("BRANCH_PREFIX", "feat/issue"),
48
+ worktreeBaseDir: optionalEnv("WORKTREE_BASE_DIR", ""),
49
+ projectSubDir: optionalEnv("PROJECT_SUBDIR", "")
50
+ },
51
+ claude: {
52
+ binary: optionalEnv("CLAUDE_BINARY", "claude-internal"),
53
+ phaseTimeoutMs: parseInt(optionalEnv("CLAUDE_PHASE_TIMEOUT_MS", "1800000"), 10),
54
+ nvmNodeVersion: optionalEnv("NVM_NODE_VERSION", "20")
55
+ },
56
+ ai: buildAIConfig(),
57
+ poll: {
58
+ intervalMs: parseInt(optionalEnv("POLL_INTERVAL_MS", "60000"), 10),
59
+ discoveryIntervalMs: parseInt(
60
+ optionalEnv("POLL_DISCOVERY_INTERVAL_MS", optionalEnv("POLL_INTERVAL_MS", "60000")),
61
+ 10
62
+ ),
63
+ driveIntervalMs: parseInt(optionalEnv("POLL_DRIVE_INTERVAL_MS", "15000"), 10),
64
+ maxRetries: parseInt(optionalEnv("MAX_RETRIES", "3"), 10),
65
+ maxConcurrent: parseInt(optionalEnv("MAX_CONCURRENT_ISSUES", "3"), 10)
66
+ },
67
+ pipeline: {
68
+ mode: optionalEnv("PIPELINE_MODE", "auto")
69
+ },
70
+ review: {
71
+ enabled: optionalEnv("REVIEW_ENABLED", "true") === "true",
72
+ autoApproveLabels: optionalEnv("REVIEW_AUTO_APPROVE_LABELS", "").split(",").map((s) => s.trim()).filter(Boolean)
73
+ },
74
+ web: {
75
+ enabled: optionalEnv("WEB_ENABLED", "true") === "true",
76
+ port: parseInt(optionalEnv("WEB_PORT", "3000"), 10),
77
+ frontendDistDir: optionalEnv(
78
+ "FRONTEND_DIST_DIR",
79
+ path.resolve(__dirname, "..", "src/web/frontend/dist")
80
+ )
81
+ },
82
+ issueNoteSync: {
83
+ enabled: optionalEnv("ISSUE_NOTE_SYNC_ENABLED", "true") === "true",
84
+ webBaseUrl: optionalEnv(
85
+ "WEB_BASE_URL",
86
+ `http://localhost:${optionalEnv("WEB_PORT", "3000")}`
87
+ )
88
+ },
89
+ webhook: {
90
+ enabled: optionalEnv("WEBHOOK_ENABLED", "false") === "true",
91
+ port: parseInt(optionalEnv("WEBHOOK_PORT", "8081"), 10),
92
+ secret: optionalEnv("WEBHOOK_SECRET", ""),
93
+ llmFallback: optionalEnv("WEBHOOK_LLM_FALLBACK", "true") === "true",
94
+ llmBinary: optionalEnv("WEBHOOK_LLM_BINARY", "claude-internal")
95
+ },
96
+ e2e: {
97
+ enabled: optionalEnv("E2E_UI_ENABLED", "false") === "true",
98
+ baseUrl: optionalEnv("E2E_BASE_URL", "https://localhost:8890"),
99
+ backendUrl: optionalEnv("E2E_BACKEND_URL", "http://127.0.0.1:3000"),
100
+ authCookies: optionalEnv("E2E_AUTH_COOKIES", "[]"),
101
+ backendPortBase: parseInt(optionalEnv("E2E_BACKEND_PORT_BASE", "4000"), 10),
102
+ frontendPortBase: parseInt(optionalEnv("E2E_FRONTEND_PORT_BASE", "9000"), 10)
103
+ },
104
+ preview: {
105
+ enabled: optionalEnv("PREVIEW_ENABLED", "false") === "true",
106
+ host: optionalEnv("PREVIEW_HOST", ""),
107
+ ttlMs: parseInt(optionalEnv("PREVIEW_TTL_MS", String(24 * 60 * 60 * 1e3)), 10),
108
+ keepAfterComplete: optionalEnv("PREVIEW_KEEP_AFTER_COMPLETE", "true") === "true"
109
+ },
110
+ brainstorm: {
111
+ enabled: optionalEnv("BRAINSTORM_ENABLED", "true") === "true",
112
+ maxRefinementRounds: parseInt(optionalEnv("BRAINSTORM_MAX_ROUNDS", "5"), 10),
113
+ timeoutMs: parseInt(optionalEnv("BRAINSTORM_TIMEOUT_MS", "600000"), 10),
114
+ generator: buildBrainstormAgentConfig("GENERATOR"),
115
+ reviewer: buildBrainstormAgentConfig("REVIEWER")
116
+ },
117
+ chat: {
118
+ enabled: optionalEnv("CHAT_ENABLED", "true") === "true",
119
+ timeoutMs: parseInt(optionalEnv("CHAT_TIMEOUT_MS", "300000"), 10),
120
+ maxSessionMessages: parseInt(optionalEnv("CHAT_MAX_SESSION_MESSAGES", "100"), 10),
121
+ agent: buildChatAgentConfig()
122
+ },
123
+ autoUpdate: {
124
+ enabled: optionalEnv("AUTO_UPDATE_ENABLED", "true") === "true",
125
+ intervalMs: parseInt(optionalEnv("AUTO_UPDATE_INTERVAL_MS", "600000"), 10),
126
+ registry: optionalEnv("AUTO_UPDATE_REGISTRY", "https://registry.npmjs.org"),
127
+ drainTimeoutMs: parseInt(optionalEnv("AUTO_UPDATE_DRAIN_TIMEOUT_MS", "300000"), 10)
128
+ },
129
+ iwiki: {
130
+ authCookie: process.env.IWIKI_AUTH_COOKIE || void 0,
131
+ authToken: process.env.IWIKI_AUTH_TOKEN || void 0,
132
+ baseUrl: process.env.IWIKI_BASE_URL || void 0
133
+ },
134
+ locale: optionalEnv("LOCALE", "zh-CN") === "en" ? "en" : "zh-CN",
135
+ knowledgePath: process.env.KNOWLEDGE_PATH || void 0
136
+ };
137
+ }
138
+ function resolveAIRunnerMode(raw) {
139
+ if (raw === "cursor-agent") return "cursor-agent";
140
+ if (raw === "codebuddy") return "codebuddy";
141
+ return "claude-internal";
142
+ }
143
+ function resolveAIBinary(mode) {
144
+ switch (mode) {
145
+ case "cursor-agent":
146
+ return optionalEnv("CURSOR_BINARY", "cursor");
147
+ case "codebuddy":
148
+ return optionalEnv("CODEBUDDY_BINARY", "codebuddy");
149
+ default:
150
+ return optionalEnv("CLAUDE_BINARY", "claude-internal");
151
+ }
152
+ }
153
+ function buildAIConfig() {
154
+ const mode = resolveAIRunnerMode(optionalEnv("AI_RUNNER_MODE", "claude-internal"));
155
+ return {
156
+ mode,
157
+ binary: resolveAIBinary(mode),
158
+ phaseTimeoutMs: parseInt(optionalEnv("CLAUDE_PHASE_TIMEOUT_MS", "1800000"), 10),
159
+ nvmNodeVersion: optionalEnv("NVM_NODE_VERSION", "20"),
160
+ model: optionalEnv("AI_MODEL", DEFAULT_AI_MODEL)
161
+ };
162
+ }
163
+ function buildBrainstormAgentConfig(role) {
164
+ const globalMode = optionalEnv("AI_RUNNER_MODE", "claude-internal");
165
+ const roleMode = optionalEnv(`BRAINSTORM_${role}_MODE`, globalMode);
166
+ const mode = resolveAIRunnerMode(roleMode);
167
+ return {
168
+ mode,
169
+ binary: optionalEnv(`BRAINSTORM_${role}_BINARY`, resolveAIBinary(mode)),
170
+ nvmNodeVersion: optionalEnv("NVM_NODE_VERSION", "20"),
171
+ model: process.env[`BRAINSTORM_${role}_MODEL`] || optionalEnv("AI_MODEL", DEFAULT_AI_MODEL)
172
+ };
173
+ }
174
+ function buildChatAgentConfig() {
175
+ const chatMode = optionalEnv("CHAT_AGENT_MODE", "claude-internal");
176
+ const mode = resolveAIRunnerMode(chatMode);
177
+ return {
178
+ mode,
179
+ binary: optionalEnv("CHAT_AGENT_BINARY", resolveAIBinary(mode)),
180
+ nvmNodeVersion: optionalEnv("NVM_NODE_VERSION", "20"),
181
+ model: process.env.CHAT_AGENT_MODEL || optionalEnv("AI_MODEL", DEFAULT_AI_MODEL)
182
+ };
183
+ }
184
+
185
+ export {
186
+ loadConfig
187
+ };
188
+ //# sourceMappingURL=chunk-MH6LHFPB.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/config.ts"],"sourcesContent":["import { config as loadDotenv } from 'dotenv';\nimport path from 'node:path';\nimport fs from 'node:fs';\nimport os from 'node:os';\nimport { fileURLToPath } from 'node:url';\n\nconst __dirname = path.dirname(fileURLToPath(import.meta.url));\n\nfunction resolveEnvPath(): string {\n if (process.env.IAF_CONFIG_PATH) return process.env.IAF_CONFIG_PATH;\n\n const localEnv = path.resolve(__dirname, '../.env');\n if (fs.existsSync(localEnv)) return localEnv;\n\n const cwdEnv = path.resolve(process.cwd(), '.env');\n if (fs.existsSync(cwdEnv)) return cwdEnv;\n\n const globalEnv = path.join(os.homedir(), '.issue-auto-finish', '.env');\n if (fs.existsSync(globalEnv)) return globalEnv;\n\n return localEnv;\n}\n\nlet _dotenvLoaded = false;\nfunction ensureDotenvLoaded(): void {\n if (_dotenvLoaded) return;\n _dotenvLoaded = true;\n loadDotenv({ path: resolveEnvPath() });\n}\n\nexport interface Config {\n gongfeng: {\n apiUrl: string;\n privateToken: string;\n projectPath: string;\n };\n project: {\n workDir: string;\n gitRootDir: string;\n baseBranch: string;\n branchPrefix: string;\n worktreeBaseDir: string;\n projectSubDir: string;\n };\n /** @deprecated Use ai instead */\n claude?: {\n binary: string;\n phaseTimeoutMs: number;\n nvmNodeVersion: string;\n };\n ai: {\n mode: 'claude-internal' | 'cursor-agent' | 'codebuddy';\n binary: string;\n phaseTimeoutMs: number;\n nvmNodeVersion: string;\n model?: string;\n };\n poll: {\n /** @deprecated Use discoveryIntervalMs instead */\n intervalMs: number;\n discoveryIntervalMs: number;\n driveIntervalMs: number;\n maxRetries: number;\n maxConcurrent: number;\n };\n pipeline: {\n mode: 'auto' | 'classic' | 'plan-mode';\n };\n review: {\n enabled: boolean;\n autoApproveLabels: string[];\n };\n web: {\n enabled: boolean;\n port: number;\n frontendDistDir: string;\n };\n issueNoteSync: {\n enabled: boolean;\n webBaseUrl: string;\n };\n webhook: {\n enabled: boolean;\n port: number;\n secret: string;\n /** Use LLM to parse natural-language commands when regex fails */\n llmFallback: boolean;\n /** Binary for LLM intent recognition (defaults to claude-internal, independent of AI_RUNNER_MODE) */\n llmBinary: string;\n };\n e2e: {\n enabled: boolean;\n baseUrl: string;\n backendUrl: string;\n authCookies: string;\n backendPortBase: number;\n frontendPortBase: number;\n };\n preview: {\n enabled: boolean;\n host: string;\n ttlMs: number;\n keepAfterComplete: boolean;\n };\n brainstorm: {\n enabled: boolean;\n maxRefinementRounds: number;\n timeoutMs: number;\n generator: BrainstormAgentConfig;\n reviewer: BrainstormAgentConfig;\n };\n chat: {\n enabled: boolean;\n timeoutMs: number;\n maxSessionMessages: number;\n agent: ChatAgentConfig;\n };\n autoUpdate: {\n enabled: boolean;\n intervalMs: number;\n registry: string;\n drainTimeoutMs: number;\n };\n iwiki?: {\n authCookie?: string;\n authToken?: string;\n baseUrl?: string;\n };\n locale: 'zh-CN' | 'en';\n knowledgePath?: string;\n}\n\nexport type AIRunnerMode = 'claude-internal' | 'cursor-agent' | 'codebuddy';\n\nexport interface BrainstormAgentConfig {\n mode: AIRunnerMode;\n binary: string;\n nvmNodeVersion: string;\n model?: string;\n}\n\nexport type ChatAgentConfig = BrainstormAgentConfig;\n\nconst DEFAULT_AI_MODEL = 'Claude-4.6-Opus';\n\nfunction requireEnv(key: string): string {\n const val = process.env[key];\n if (!val) {\n throw new Error(`Missing required environment variable: ${key}`);\n }\n return val;\n}\n\nfunction optionalEnv(key: string, defaultValue: string): string {\n return process.env[key] || defaultValue;\n}\n\nexport function loadConfig(): Config {\n ensureDotenvLoaded();\n return {\n gongfeng: {\n apiUrl: requireEnv('GONGFENG_API_URL'),\n privateToken: requireEnv('GONGFENG_PRIVATE_TOKEN'),\n projectPath: requireEnv('GONGFENG_PROJECT_PATH'),\n },\n project: {\n workDir: requireEnv('PROJECT_WORK_DIR'),\n gitRootDir: optionalEnv('GIT_ROOT_DIR', requireEnv('PROJECT_WORK_DIR')),\n baseBranch: optionalEnv('BASE_BRANCH', 'master'),\n branchPrefix: optionalEnv('BRANCH_PREFIX', 'feat/issue'),\n worktreeBaseDir: optionalEnv('WORKTREE_BASE_DIR', ''),\n projectSubDir: optionalEnv('PROJECT_SUBDIR', ''),\n },\n claude: {\n binary: optionalEnv('CLAUDE_BINARY', 'claude-internal'),\n phaseTimeoutMs: parseInt(optionalEnv('CLAUDE_PHASE_TIMEOUT_MS', '1800000'), 10),\n nvmNodeVersion: optionalEnv('NVM_NODE_VERSION', '20'),\n },\n ai: buildAIConfig(),\n poll: {\n intervalMs: parseInt(optionalEnv('POLL_INTERVAL_MS', '60000'), 10),\n discoveryIntervalMs: parseInt(\n optionalEnv('POLL_DISCOVERY_INTERVAL_MS', optionalEnv('POLL_INTERVAL_MS', '60000')),\n 10,\n ),\n driveIntervalMs: parseInt(optionalEnv('POLL_DRIVE_INTERVAL_MS', '15000'), 10),\n maxRetries: parseInt(optionalEnv('MAX_RETRIES', '3'), 10),\n maxConcurrent: parseInt(optionalEnv('MAX_CONCURRENT_ISSUES', '3'), 10),\n },\n pipeline: {\n mode: optionalEnv('PIPELINE_MODE', 'auto') as 'auto' | 'classic' | 'plan-mode',\n },\n review: {\n enabled: optionalEnv('REVIEW_ENABLED', 'true') === 'true',\n autoApproveLabels: optionalEnv('REVIEW_AUTO_APPROVE_LABELS', '')\n .split(',').map(s => s.trim()).filter(Boolean),\n },\n web: {\n enabled: optionalEnv('WEB_ENABLED', 'true') === 'true',\n port: parseInt(optionalEnv('WEB_PORT', '3000'), 10),\n frontendDistDir: optionalEnv(\n 'FRONTEND_DIST_DIR',\n path.resolve(__dirname, '..', 'src/web/frontend/dist'),\n ),\n },\n issueNoteSync: {\n enabled: optionalEnv('ISSUE_NOTE_SYNC_ENABLED', 'true') === 'true',\n webBaseUrl: optionalEnv(\n 'WEB_BASE_URL',\n `http://localhost:${optionalEnv('WEB_PORT', '3000')}`,\n ),\n },\n webhook: {\n enabled: optionalEnv('WEBHOOK_ENABLED', 'false') === 'true',\n port: parseInt(optionalEnv('WEBHOOK_PORT', '8081'), 10),\n secret: optionalEnv('WEBHOOK_SECRET', ''),\n llmFallback: optionalEnv('WEBHOOK_LLM_FALLBACK', 'true') === 'true',\n llmBinary: optionalEnv('WEBHOOK_LLM_BINARY', 'claude-internal'),\n },\n e2e: {\n enabled: optionalEnv('E2E_UI_ENABLED', 'false') === 'true',\n baseUrl: optionalEnv('E2E_BASE_URL', 'https://localhost:8890'),\n backendUrl: optionalEnv('E2E_BACKEND_URL', 'http://127.0.0.1:3000'),\n authCookies: optionalEnv('E2E_AUTH_COOKIES', '[]'),\n backendPortBase: parseInt(optionalEnv('E2E_BACKEND_PORT_BASE', '4000'), 10),\n frontendPortBase: parseInt(optionalEnv('E2E_FRONTEND_PORT_BASE', '9000'), 10),\n },\n preview: {\n enabled: optionalEnv('PREVIEW_ENABLED', 'false') === 'true',\n host: optionalEnv('PREVIEW_HOST', ''),\n ttlMs: parseInt(optionalEnv('PREVIEW_TTL_MS', String(24 * 60 * 60 * 1000)), 10),\n keepAfterComplete: optionalEnv('PREVIEW_KEEP_AFTER_COMPLETE', 'true') === 'true',\n },\n brainstorm: {\n enabled: optionalEnv('BRAINSTORM_ENABLED', 'true') === 'true',\n maxRefinementRounds: parseInt(optionalEnv('BRAINSTORM_MAX_ROUNDS', '5'), 10),\n timeoutMs: parseInt(optionalEnv('BRAINSTORM_TIMEOUT_MS', '600000'), 10),\n generator: buildBrainstormAgentConfig('GENERATOR'),\n reviewer: buildBrainstormAgentConfig('REVIEWER'),\n },\n chat: {\n enabled: optionalEnv('CHAT_ENABLED', 'true') === 'true',\n timeoutMs: parseInt(optionalEnv('CHAT_TIMEOUT_MS', '300000'), 10),\n maxSessionMessages: parseInt(optionalEnv('CHAT_MAX_SESSION_MESSAGES', '100'), 10),\n agent: buildChatAgentConfig(),\n },\n autoUpdate: {\n enabled: optionalEnv('AUTO_UPDATE_ENABLED', 'true') === 'true',\n intervalMs: parseInt(optionalEnv('AUTO_UPDATE_INTERVAL_MS', '600000'), 10),\n registry: optionalEnv('AUTO_UPDATE_REGISTRY', 'https://registry.npmjs.org'),\n drainTimeoutMs: parseInt(optionalEnv('AUTO_UPDATE_DRAIN_TIMEOUT_MS', '300000'), 10),\n },\n iwiki: {\n authCookie: process.env.IWIKI_AUTH_COOKIE || undefined,\n authToken: process.env.IWIKI_AUTH_TOKEN || undefined,\n baseUrl: process.env.IWIKI_BASE_URL || undefined,\n },\n locale: (optionalEnv('LOCALE', 'zh-CN') === 'en' ? 'en' : 'zh-CN') as 'zh-CN' | 'en',\n knowledgePath: process.env.KNOWLEDGE_PATH || undefined,\n };\n}\n\nfunction resolveAIRunnerMode(raw: string): AIRunnerMode {\n if (raw === 'cursor-agent') return 'cursor-agent';\n if (raw === 'codebuddy') return 'codebuddy';\n return 'claude-internal';\n}\n\nfunction resolveAIBinary(mode: AIRunnerMode): string {\n switch (mode) {\n case 'cursor-agent':\n return optionalEnv('CURSOR_BINARY', 'cursor');\n case 'codebuddy':\n return optionalEnv('CODEBUDDY_BINARY', 'codebuddy');\n default:\n return optionalEnv('CLAUDE_BINARY', 'claude-internal');\n }\n}\n\nfunction buildAIConfig(): Config['ai'] {\n const mode = resolveAIRunnerMode(optionalEnv('AI_RUNNER_MODE', 'claude-internal'));\n return {\n mode,\n binary: resolveAIBinary(mode),\n phaseTimeoutMs: parseInt(optionalEnv('CLAUDE_PHASE_TIMEOUT_MS', '1800000'), 10),\n nvmNodeVersion: optionalEnv('NVM_NODE_VERSION', '20'),\n model: optionalEnv('AI_MODEL', DEFAULT_AI_MODEL),\n };\n}\n\nfunction buildBrainstormAgentConfig(role: 'GENERATOR' | 'REVIEWER'): BrainstormAgentConfig {\n const globalMode = optionalEnv('AI_RUNNER_MODE', 'claude-internal');\n const roleMode = optionalEnv(`BRAINSTORM_${role}_MODE`, globalMode);\n const mode = resolveAIRunnerMode(roleMode);\n\n return {\n mode,\n binary: optionalEnv(`BRAINSTORM_${role}_BINARY`, resolveAIBinary(mode)),\n nvmNodeVersion: optionalEnv('NVM_NODE_VERSION', '20'),\n model: process.env[`BRAINSTORM_${role}_MODEL`] || optionalEnv('AI_MODEL', DEFAULT_AI_MODEL),\n };\n}\n\nfunction buildChatAgentConfig(): ChatAgentConfig {\n // Chat defaults to claude-internal for lightweight conversational use,\n // independent of the global AI_RUNNER_MODE (which may be cursor-agent).\n const chatMode = optionalEnv('CHAT_AGENT_MODE', 'claude-internal');\n const mode = resolveAIRunnerMode(chatMode);\n\n return {\n mode,\n binary: optionalEnv('CHAT_AGENT_BINARY', resolveAIBinary(mode)),\n nvmNodeVersion: optionalEnv('NVM_NODE_VERSION', '20'),\n model: process.env.CHAT_AGENT_MODEL || optionalEnv('AI_MODEL', DEFAULT_AI_MODEL),\n };\n}\n"],"mappings":"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","names":[]}