@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.
- package/dist/KnowledgeAnalyzer-EZSJT2MJ.js +13 -0
- package/dist/KnowledgeAnalyzer-EZSJT2MJ.js.map +1 -0
- package/dist/KnowledgeStore-4ROC6F56.js +10 -0
- package/dist/KnowledgeStore-4ROC6F56.js.map +1 -0
- package/dist/ai-runner/AIRunner.d.ts +2 -0
- package/dist/ai-runner/AIRunner.d.ts.map +1 -1
- package/dist/ai-runner/BaseAIRunner.d.ts +9 -0
- package/dist/ai-runner/BaseAIRunner.d.ts.map +1 -1
- package/dist/ai-runner-RGAJPOOW.js +16 -0
- package/dist/ai-runner-RGAJPOOW.js.map +1 -0
- package/dist/analyze-ONQDTYCN.js +72 -0
- package/dist/analyze-ONQDTYCN.js.map +1 -0
- package/dist/chunk-3JUHZGX5.js +171 -0
- package/dist/chunk-3JUHZGX5.js.map +1 -0
- package/dist/chunk-5JYCGAU3.js +318 -0
- package/dist/chunk-5JYCGAU3.js.map +1 -0
- package/dist/chunk-5VUB3UUK.js +643 -0
- package/dist/chunk-5VUB3UUK.js.map +1 -0
- package/dist/{chunk-OWVT3Z34.js → chunk-JFYAXNNS.js} +121 -31
- package/dist/chunk-JFYAXNNS.js.map +1 -0
- package/dist/chunk-MH6LHFPB.js +188 -0
- package/dist/chunk-MH6LHFPB.js.map +1 -0
- package/dist/{chunk-TBIEB3JY.js → chunk-N5YK6YVI.js} +592 -767
- package/dist/chunk-N5YK6YVI.js.map +1 -0
- package/dist/{chunk-RIUI4ROA.js → chunk-PECYMYAK.js} +2 -2
- package/dist/{chunk-I3T573SU.js → chunk-PTIL5AY2.js} +65 -2
- package/dist/chunk-PTIL5AY2.js.map +1 -0
- package/dist/chunk-SWG2Y7YX.js +410 -0
- package/dist/chunk-SWG2Y7YX.js.map +1 -0
- package/dist/chunk-TZ6C7HL5.js +59 -0
- package/dist/chunk-TZ6C7HL5.js.map +1 -0
- package/dist/{chunk-IDUKWCC2.js → chunk-VFQYIC6L.js} +1151 -80
- package/dist/chunk-VFQYIC6L.js.map +1 -0
- package/dist/cli/commands/analyze.d.ts +8 -0
- package/dist/cli/commands/analyze.d.ts.map +1 -0
- package/dist/cli/commands/init.d.ts.map +1 -1
- package/dist/cli.js +67 -3
- package/dist/cli.js.map +1 -1
- package/dist/clients/GongfengClient.d.ts +5 -0
- package/dist/clients/GongfengClient.d.ts.map +1 -1
- package/dist/config-6GFBDMGD.js +7 -0
- package/dist/config-6GFBDMGD.js.map +1 -0
- package/dist/config.d.ts +19 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/{doctor-B26Q6JWI.js → doctor-ZPGIBA5N.js} +3 -3
- package/dist/events/EventBus.d.ts +1 -1
- package/dist/events/EventBus.d.ts.map +1 -1
- package/dist/git/GitOperations.d.ts +12 -0
- package/dist/git/GitOperations.d.ts.map +1 -1
- package/dist/i18n/locales/en.d.ts.map +1 -1
- package/dist/i18n/locales/zh-CN.d.ts.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +11 -5
- package/dist/{init-L3VIWCOV.js → init-QDTII4SP.js} +10 -5
- package/dist/init-QDTII4SP.js.map +1 -0
- package/dist/knowledge/KnowledgeAnalyzer.d.ts +31 -0
- package/dist/knowledge/KnowledgeAnalyzer.d.ts.map +1 -0
- package/dist/knowledge/KnowledgeDefaults.d.ts +7 -0
- package/dist/knowledge/KnowledgeDefaults.d.ts.map +1 -0
- package/dist/knowledge/KnowledgeEntry.d.ts +30 -0
- package/dist/knowledge/KnowledgeEntry.d.ts.map +1 -0
- package/dist/knowledge/KnowledgeLoader.d.ts +18 -0
- package/dist/knowledge/KnowledgeLoader.d.ts.map +1 -0
- package/dist/knowledge/KnowledgeStore.d.ts +35 -0
- package/dist/knowledge/KnowledgeStore.d.ts.map +1 -0
- package/dist/knowledge/ProjectKnowledge.d.ts +79 -0
- package/dist/knowledge/ProjectKnowledge.d.ts.map +1 -0
- package/dist/knowledge/analyze-prompt.d.ts +2 -0
- package/dist/knowledge/analyze-prompt.d.ts.map +1 -0
- package/dist/knowledge/importers/GongfengExtractor.d.ts +27 -0
- package/dist/knowledge/importers/GongfengExtractor.d.ts.map +1 -0
- package/dist/knowledge/importers/IwikiImporter.d.ts +21 -0
- package/dist/knowledge/importers/IwikiImporter.d.ts.map +1 -0
- package/dist/knowledge/index.d.ts +12 -0
- package/dist/knowledge/index.d.ts.map +1 -0
- package/dist/lib.js +19 -10
- package/dist/orchestrator/PipelineOrchestrator.d.ts +5 -1
- package/dist/orchestrator/PipelineOrchestrator.d.ts.map +1 -1
- package/dist/phases/BasePhase.d.ts.map +1 -1
- package/dist/poller/IssuePoller.d.ts +5 -0
- package/dist/poller/IssuePoller.d.ts.map +1 -1
- package/dist/prompts/chat-templates.d.ts +4 -0
- package/dist/prompts/chat-templates.d.ts.map +1 -0
- package/dist/prompts/templates.d.ts +11 -0
- package/dist/prompts/templates.d.ts.map +1 -1
- package/dist/rules/RuleResolver.d.ts +4 -0
- package/dist/rules/RuleResolver.d.ts.map +1 -1
- package/dist/run.js +11 -5
- package/dist/run.js.map +1 -1
- package/dist/services/ChatService.d.ts +39 -0
- package/dist/services/ChatService.d.ts.map +1 -0
- package/dist/shutdown/ShutdownSignal.d.ts +3 -0
- package/dist/shutdown/ShutdownSignal.d.ts.map +1 -0
- package/dist/{start-TVN4SS6E.js → start-EDOZC5WL.js} +1 -1
- package/dist/tracker/IssueState.d.ts +1 -0
- package/dist/tracker/IssueState.d.ts.map +1 -1
- package/dist/tracker/IssueTracker.d.ts +2 -0
- package/dist/tracker/IssueTracker.d.ts.map +1 -1
- package/dist/updater/AutoUpdater.d.ts +33 -0
- package/dist/updater/AutoUpdater.d.ts.map +1 -0
- package/dist/updater/UpdateExecutor.d.ts +7 -0
- package/dist/updater/UpdateExecutor.d.ts.map +1 -0
- package/dist/updater/VersionChecker.d.ts +22 -0
- package/dist/updater/VersionChecker.d.ts.map +1 -0
- package/dist/web/WebServer.d.ts +4 -0
- package/dist/web/WebServer.d.ts.map +1 -1
- package/dist/web/routes/api.d.ts +4 -0
- package/dist/web/routes/api.d.ts.map +1 -1
- package/dist/web/routes/chat.d.ts +7 -0
- package/dist/web/routes/chat.d.ts.map +1 -0
- package/dist/web/routes/knowledge.d.ts +13 -0
- package/dist/web/routes/knowledge.d.ts.map +1 -0
- package/dist/web/routes/setup.d.ts.map +1 -1
- package/dist/webhook/CommandExecutor.d.ts +4 -0
- package/dist/webhook/CommandExecutor.d.ts.map +1 -1
- package/dist/webhook/CommandParser.d.ts +2 -2
- package/dist/webhook/CommandParser.d.ts.map +1 -1
- package/dist/webhook/WebhookHandler.d.ts +8 -0
- package/dist/webhook/WebhookHandler.d.ts.map +1 -1
- package/dist/webhook/WebhookServer.d.ts +2 -0
- package/dist/webhook/WebhookServer.d.ts.map +1 -1
- package/package.json +4 -2
- package/src/web/frontend/dist/assets/index-AcJ0lPIv.js +67 -0
- package/src/web/frontend/dist/assets/index-BbRt5BAr.css +1 -0
- package/src/web/frontend/dist/index.html +2 -2
- package/dist/chunk-I3T573SU.js.map +0 -1
- package/dist/chunk-IDUKWCC2.js.map +0 -1
- package/dist/chunk-OWVT3Z34.js.map +0 -1
- package/dist/chunk-TBIEB3JY.js.map +0 -1
- package/dist/init-L3VIWCOV.js.map +0 -1
- package/src/web/frontend/dist/assets/index-CQdlU9PE.js +0 -65
- package/src/web/frontend/dist/assets/index-CgMEkyZJ.css +0 -1
- /package/dist/{chunk-RIUI4ROA.js.map → chunk-PECYMYAK.js.map} +0 -0
- /package/dist/{doctor-B26Q6JWI.js.map → doctor-ZPGIBA5N.js.map} +0 -0
- /package/dist/{start-TVN4SS6E.js.map → start-EDOZC5WL.js.map} +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
.analyze-progress-bar-animated[data-v-db7fa114]{background-image:linear-gradient(-45deg,rgba(255,255,255,.2) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.2) 50%,rgba(255,255,255,.2) 75%,transparent 75%,transparent);background-size:1rem 1rem;animation:analyze-stripe-scroll-db7fa114 .6s linear infinite}@keyframes analyze-stripe-scroll-db7fa114{0%{background-position:1rem 0}to{background-position:0 0}}@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-space-y-reverse:0;--tw-space-x-reverse:0;--tw-divide-y-reverse:0;--tw-border-style:solid;--tw-leading:initial;--tw-font-weight:initial;--tw-ordinal:initial;--tw-slashed-zero:initial;--tw-numeric-figure:initial;--tw-numeric-spacing:initial;--tw-numeric-fraction:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial;--tw-duration:initial;--tw-ease:initial}}}@layer theme{:root,:host{--font-sans:ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";--font-mono:ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;--color-red-50:oklch(97.1% .013 17.38);--color-red-100:oklch(93.6% .032 17.717);--color-red-200:oklch(88.5% .062 18.334);--color-red-300:oklch(80.8% .114 19.571);--color-red-400:oklch(70.4% .191 22.216);--color-red-500:oklch(63.7% .237 25.331);--color-red-600:oklch(57.7% .245 27.325);--color-red-700:oklch(50.5% .213 27.518);--color-orange-50:oklch(98% .016 73.684);--color-orange-100:oklch(95.4% .038 75.164);--color-orange-500:oklch(70.5% .213 47.604);--color-orange-600:oklch(64.6% .222 41.116);--color-orange-700:oklch(55.3% .195 38.402);--color-orange-800:oklch(47% .157 37.304);--color-amber-600:oklch(66.6% .179 58.318);--color-yellow-50:oklch(98.7% .026 102.212);--color-yellow-100:oklch(97.3% .071 103.193);--color-yellow-200:oklch(94.5% .129 101.54);--color-yellow-300:oklch(90.5% .182 98.111);--color-yellow-400:oklch(85.2% .199 91.936);--color-yellow-500:oklch(79.5% .184 86.047);--color-yellow-600:oklch(68.1% .162 75.834);--color-yellow-700:oklch(55.4% .135 66.442);--color-yellow-800:oklch(47.6% .114 61.907);--color-green-50:oklch(98.2% .018 155.826);--color-green-100:oklch(96.2% .044 156.743);--color-green-200:oklch(92.5% .084 155.995);--color-green-400:oklch(79.2% .209 151.711);--color-green-500:oklch(72.3% .219 149.579);--color-green-600:oklch(62.7% .194 149.214);--color-green-700:oklch(52.7% .154 150.069);--color-green-800:oklch(44.8% .119 151.328);--color-blue-50:oklch(97% .014 254.604);--color-blue-100:oklch(93.2% .032 255.585);--color-blue-200:oklch(88.2% .059 254.128);--color-blue-400:oklch(70.7% .165 254.624);--color-blue-500:oklch(62.3% .214 259.815);--color-blue-600:oklch(54.6% .245 262.881);--color-blue-700:oklch(48.8% .243 264.376);--color-blue-800:oklch(42.4% .199 265.638);--color-purple-100:oklch(94.6% .033 307.174);--color-purple-700:oklch(49.6% .265 301.924);--color-gray-50:oklch(98.5% .002 247.839);--color-gray-100:oklch(96.7% .003 264.542);--color-gray-200:oklch(92.8% .006 264.531);--color-gray-300:oklch(87.2% .01 258.338);--color-gray-400:oklch(70.7% .022 261.325);--color-gray-500:oklch(55.1% .027 264.364);--color-gray-600:oklch(44.6% .03 256.802);--color-gray-700:oklch(37.3% .034 259.733);--color-gray-800:oklch(27.8% .033 256.848);--color-gray-900:oklch(21% .034 264.665);--color-black:#000;--color-white:#fff;--spacing:.25rem;--container-xs:20rem;--container-sm:24rem;--container-md:28rem;--container-lg:32rem;--container-xl:36rem;--container-2xl:42rem;--container-3xl:48rem;--container-7xl:80rem;--text-xs:.75rem;--text-xs--line-height:calc(1 / .75);--text-sm:.875rem;--text-sm--line-height:calc(1.25 / .875);--text-base:1rem;--text-base--line-height: 1.5 ;--text-lg:1.125rem;--text-lg--line-height:calc(1.75 / 1.125);--text-xl:1.25rem;--text-xl--line-height:calc(1.75 / 1.25);--text-2xl:1.5rem;--text-2xl--line-height:calc(2 / 1.5);--text-5xl:3rem;--text-5xl--line-height:1;--font-weight-medium:500;--font-weight-semibold:600;--font-weight-bold:700;--radius-lg:.5rem;--radius-xl:.75rem;--radius-2xl:1rem;--ease-out:cubic-bezier(0, 0, .2, 1);--animate-spin:spin 1s linear infinite;--animate-ping:ping 1s cubic-bezier(0, 0, .2, 1) infinite;--animate-pulse:pulse 2s cubic-bezier(.4, 0, .6, 1) infinite;--animate-bounce:bounce 1s infinite;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4, 0, .2, 1);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono)}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;tab-size:4;line-height:1.5;font-family:var(--default-font-family,ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring{outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab,red,red)){::placeholder{color:color-mix(in oklab,currentcolor 50%,transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){appearance:button}::file-selector-button{appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}}@layer components;@layer utilities{.absolute{position:absolute}.fixed{position:fixed}.relative{position:relative}.sticky{position:sticky}.inset-0{inset:calc(var(--spacing) * 0)}.start{inset-inline-start:var(--spacing)}.end{inset-inline-end:var(--spacing)}.top-0{top:calc(var(--spacing) * 0)}.top-1{top:calc(var(--spacing) * 1)}.top-2\.5{top:calc(var(--spacing) * 2.5)}.bottom-0{bottom:calc(var(--spacing) * 0)}.left-3{left:calc(var(--spacing) * 3)}.left-\[-5px\]{left:-5px}.z-10{z-index:10}.z-50{z-index:50}.mx-2{margin-inline:calc(var(--spacing) * 2)}.mx-auto{margin-inline:auto}.mt-0\.5{margin-top:calc(var(--spacing) * .5)}.mt-1{margin-top:calc(var(--spacing) * 1)}.mt-2{margin-top:calc(var(--spacing) * 2)}.mt-4{margin-top:calc(var(--spacing) * 4)}.mr-1{margin-right:calc(var(--spacing) * 1)}.mr-2{margin-right:calc(var(--spacing) * 2)}.mb-0\.5{margin-bottom:calc(var(--spacing) * .5)}.mb-1{margin-bottom:calc(var(--spacing) * 1)}.mb-2{margin-bottom:calc(var(--spacing) * 2)}.mb-3{margin-bottom:calc(var(--spacing) * 3)}.mb-4{margin-bottom:calc(var(--spacing) * 4)}.mb-6{margin-bottom:calc(var(--spacing) * 6)}.ml-0\.5{margin-left:calc(var(--spacing) * .5)}.ml-1{margin-left:calc(var(--spacing) * 1)}.ml-2{margin-left:calc(var(--spacing) * 2)}.ml-auto{margin-left:auto}.line-clamp-3{-webkit-line-clamp:3;-webkit-box-orient:vertical;display:-webkit-box;overflow:hidden}.block{display:block}.flex{display:flex}.grid{display:grid}.hidden{display:none}.inline-block{display:inline-block}.inline-flex{display:inline-flex}.table{display:table}.h-0\.5{height:calc(var(--spacing) * .5)}.h-1{height:calc(var(--spacing) * 1)}.h-2{height:calc(var(--spacing) * 2)}.h-2\.5{height:calc(var(--spacing) * 2.5)}.h-3{height:calc(var(--spacing) * 3)}.h-3\.5{height:calc(var(--spacing) * 3.5)}.h-4{height:calc(var(--spacing) * 4)}.h-5{height:calc(var(--spacing) * 5)}.h-6{height:calc(var(--spacing) * 6)}.h-10{height:calc(var(--spacing) * 10)}.h-12{height:calc(var(--spacing) * 12)}.h-16{height:calc(var(--spacing) * 16)}.h-96{height:calc(var(--spacing) * 96)}.h-\[calc\(100vh-220px\)\]{height:calc(100vh - 220px)}.h-full{height:100%}.max-h-32{max-height:calc(var(--spacing) * 32)}.max-h-40{max-height:calc(var(--spacing) * 40)}.max-h-48{max-height:calc(var(--spacing) * 48)}.max-h-80{max-height:calc(var(--spacing) * 80)}.max-h-96{max-height:calc(var(--spacing) * 96)}.max-h-\[85vh\]{max-height:85vh}.max-h-\[90vh\]{max-height:90vh}.max-h-\[600px\]{max-height:600px}.min-h-0{min-height:calc(var(--spacing) * 0)}.min-h-\[400px\]{min-height:400px}.min-h-\[500px\]{min-height:500px}.min-h-screen{min-height:100vh}.w-2{width:calc(var(--spacing) * 2)}.w-2\.5{width:calc(var(--spacing) * 2.5)}.w-3{width:calc(var(--spacing) * 3)}.w-3\.5{width:calc(var(--spacing) * 3.5)}.w-4{width:calc(var(--spacing) * 4)}.w-5{width:calc(var(--spacing) * 5)}.w-6{width:calc(var(--spacing) * 6)}.w-10{width:calc(var(--spacing) * 10)}.w-12{width:calc(var(--spacing) * 12)}.w-16{width:calc(var(--spacing) * 16)}.w-48{width:calc(var(--spacing) * 48)}.w-64{width:calc(var(--spacing) * 64)}.w-full{width:100%}.max-w-2xl{max-width:var(--container-2xl)}.max-w-3xl{max-width:var(--container-3xl)}.max-w-7xl{max-width:var(--container-7xl)}.max-w-\[75\%\]{max-width:75%}.max-w-\[200px\]{max-width:200px}.max-w-lg{max-width:var(--container-lg)}.max-w-md{max-width:var(--container-md)}.max-w-none{max-width:none}.max-w-sm{max-width:var(--container-sm)}.max-w-xl{max-width:var(--container-xl)}.max-w-xs{max-width:var(--container-xs)}.min-w-0{min-width:calc(var(--spacing) * 0)}.flex-1{flex:1}.shrink-0{flex-shrink:0}.animate-bounce{animation:var(--animate-bounce)}.animate-ping{animation:var(--animate-ping)}.animate-pulse{animation:var(--animate-pulse)}.animate-spin{animation:var(--animate-spin)}.cursor-pointer{cursor:pointer}.resize-none{resize:none}.resize-y{resize:vertical}.grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}.grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}.grid-cols-5{grid-template-columns:repeat(5,minmax(0,1fr))}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-baseline{align-items:baseline}.items-center{align-items:center}.items-end{align-items:flex-end}.justify-between{justify-content:space-between}.justify-center{justify-content:center}.justify-end{justify-content:flex-end}.justify-start{justify-content:flex-start}.gap-1{gap:calc(var(--spacing) * 1)}.gap-1\.5{gap:calc(var(--spacing) * 1.5)}.gap-2{gap:calc(var(--spacing) * 2)}.gap-3{gap:calc(var(--spacing) * 3)}.gap-4{gap:calc(var(--spacing) * 4)}:where(.space-y-1>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 1) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 1) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-2>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 2) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 2) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-3>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 3) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 3) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-4>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 4) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 4) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-5>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 5) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 5) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-6>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 6) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 6) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-x-1>:not(:last-child)){--tw-space-x-reverse:0;margin-inline-start:calc(calc(var(--spacing) * 1) * var(--tw-space-x-reverse));margin-inline-end:calc(calc(var(--spacing) * 1) * calc(1 - var(--tw-space-x-reverse)))}:where(.space-x-2>:not(:last-child)){--tw-space-x-reverse:0;margin-inline-start:calc(calc(var(--spacing) * 2) * var(--tw-space-x-reverse));margin-inline-end:calc(calc(var(--spacing) * 2) * calc(1 - var(--tw-space-x-reverse)))}:where(.space-x-3>:not(:last-child)){--tw-space-x-reverse:0;margin-inline-start:calc(calc(var(--spacing) * 3) * var(--tw-space-x-reverse));margin-inline-end:calc(calc(var(--spacing) * 3) * calc(1 - var(--tw-space-x-reverse)))}:where(.space-x-4>:not(:last-child)){--tw-space-x-reverse:0;margin-inline-start:calc(calc(var(--spacing) * 4) * var(--tw-space-x-reverse));margin-inline-end:calc(calc(var(--spacing) * 4) * calc(1 - var(--tw-space-x-reverse)))}:where(.divide-y>:not(:last-child)){--tw-divide-y-reverse:0;border-bottom-style:var(--tw-border-style);border-top-style:var(--tw-border-style);border-top-width:calc(1px * var(--tw-divide-y-reverse));border-bottom-width:calc(1px * calc(1 - var(--tw-divide-y-reverse)))}:where(.divide-gray-100>:not(:last-child)){border-color:var(--color-gray-100)}.truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.overflow-y-auto{overflow-y:auto}.rounded{border-radius:.25rem}.rounded-2xl{border-radius:var(--radius-2xl)}.rounded-full{border-radius:3.40282e38px}.rounded-lg{border-radius:var(--radius-lg)}.rounded-xl{border-radius:var(--radius-xl)}.rounded-t-xl{border-top-left-radius:var(--radius-xl);border-top-right-radius:var(--radius-xl)}.rounded-b-xl{border-bottom-right-radius:var(--radius-xl);border-bottom-left-radius:var(--radius-xl)}.border{border-style:var(--tw-border-style);border-width:1px}.border-2{border-style:var(--tw-border-style);border-width:2px}.border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.border-r{border-right-style:var(--tw-border-style);border-right-width:1px}.border-b{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.border-b-2{border-bottom-style:var(--tw-border-style);border-bottom-width:2px}.border-l-2{border-left-style:var(--tw-border-style);border-left-width:2px}.border-blue-200{border-color:var(--color-blue-200)}.border-blue-500{border-color:var(--color-blue-500)}.border-gray-100{border-color:var(--color-gray-100)}.border-gray-200{border-color:var(--color-gray-200)}.border-gray-300{border-color:var(--color-gray-300)}.border-gray-800{border-color:var(--color-gray-800)}.border-green-200{border-color:var(--color-green-200)}.border-red-200{border-color:var(--color-red-200)}.border-red-300{border-color:var(--color-red-300)}.border-transparent{border-color:#0000}.border-yellow-200{border-color:var(--color-yellow-200)}.border-yellow-300{border-color:var(--color-yellow-300)}.border-yellow-500{border-color:var(--color-yellow-500)}.border-l-blue-500{border-left-color:var(--color-blue-500)}.bg-black\/30{background-color:#0000004d}@supports (color:color-mix(in lab,red,red)){.bg-black\/30{background-color:color-mix(in oklab,var(--color-black) 30%,transparent)}}.bg-black\/40{background-color:#0006}@supports (color:color-mix(in lab,red,red)){.bg-black\/40{background-color:color-mix(in oklab,var(--color-black) 40%,transparent)}}.bg-blue-50{background-color:var(--color-blue-50)}.bg-blue-100{background-color:var(--color-blue-100)}.bg-blue-400{background-color:var(--color-blue-400)}.bg-blue-500{background-color:var(--color-blue-500)}.bg-blue-600{background-color:var(--color-blue-600)}.bg-gray-50{background-color:var(--color-gray-50)}.bg-gray-100{background-color:var(--color-gray-100)}.bg-gray-200{background-color:var(--color-gray-200)}.bg-gray-400{background-color:var(--color-gray-400)}.bg-gray-600{background-color:var(--color-gray-600)}.bg-gray-700{background-color:var(--color-gray-700)}.bg-gray-800{background-color:var(--color-gray-800)}.bg-gray-900{background-color:var(--color-gray-900)}.bg-green-50{background-color:var(--color-green-50)}.bg-green-100{background-color:var(--color-green-100)}.bg-green-400{background-color:var(--color-green-400)}.bg-green-500{background-color:var(--color-green-500)}.bg-green-600{background-color:var(--color-green-600)}.bg-orange-50{background-color:var(--color-orange-50)}.bg-orange-100{background-color:var(--color-orange-100)}.bg-orange-500{background-color:var(--color-orange-500)}.bg-purple-100{background-color:var(--color-purple-100)}.bg-red-50{background-color:var(--color-red-50)}.bg-red-100{background-color:var(--color-red-100)}.bg-red-400{background-color:var(--color-red-400)}.bg-red-500{background-color:var(--color-red-500)}.bg-red-600{background-color:var(--color-red-600)}.bg-white{background-color:var(--color-white)}.bg-white\/60{background-color:#fff9}@supports (color:color-mix(in lab,red,red)){.bg-white\/60{background-color:color-mix(in oklab,var(--color-white) 60%,transparent)}}.bg-yellow-50{background-color:var(--color-yellow-50)}.bg-yellow-100{background-color:var(--color-yellow-100)}.bg-yellow-200{background-color:var(--color-yellow-200)}.bg-yellow-300{background-color:var(--color-yellow-300)}.bg-yellow-500{background-color:var(--color-yellow-500)}.p-0\.5{padding:calc(var(--spacing) * .5)}.p-1{padding:calc(var(--spacing) * 1)}.p-2{padding:calc(var(--spacing) * 2)}.p-3{padding:calc(var(--spacing) * 3)}.p-4{padding:calc(var(--spacing) * 4)}.p-6{padding:calc(var(--spacing) * 6)}.p-8{padding:calc(var(--spacing) * 8)}.p-10{padding:calc(var(--spacing) * 10)}.px-1{padding-inline:calc(var(--spacing) * 1)}.px-1\.5{padding-inline:calc(var(--spacing) * 1.5)}.px-2{padding-inline:calc(var(--spacing) * 2)}.px-3{padding-inline:calc(var(--spacing) * 3)}.px-4{padding-inline:calc(var(--spacing) * 4)}.px-6{padding-inline:calc(var(--spacing) * 6)}.px-8{padding-inline:calc(var(--spacing) * 8)}.py-0\.5{padding-block:calc(var(--spacing) * .5)}.py-1{padding-block:calc(var(--spacing) * 1)}.py-1\.5{padding-block:calc(var(--spacing) * 1.5)}.py-2{padding-block:calc(var(--spacing) * 2)}.py-2\.5{padding-block:calc(var(--spacing) * 2.5)}.py-3{padding-block:calc(var(--spacing) * 3)}.py-4{padding-block:calc(var(--spacing) * 4)}.py-6{padding-block:calc(var(--spacing) * 6)}.py-8{padding-block:calc(var(--spacing) * 8)}.py-12{padding-block:calc(var(--spacing) * 12)}.pt-2{padding-top:calc(var(--spacing) * 2)}.pt-3{padding-top:calc(var(--spacing) * 3)}.pt-4{padding-top:calc(var(--spacing) * 4)}.pr-4{padding-right:calc(var(--spacing) * 4)}.pb-2{padding-bottom:calc(var(--spacing) * 2)}.pl-5{padding-left:calc(var(--spacing) * 5)}.pl-9{padding-left:calc(var(--spacing) * 9)}.text-center{text-align:center}.text-left{text-align:left}.text-right{text-align:right}.font-mono{font-family:var(--font-mono)}.text-2xl{font-size:var(--text-2xl);line-height:var(--tw-leading,var(--text-2xl--line-height))}.text-5xl{font-size:var(--text-5xl);line-height:var(--tw-leading,var(--text-5xl--line-height))}.text-base{font-size:var(--text-base);line-height:var(--tw-leading,var(--text-base--line-height))}.text-lg{font-size:var(--text-lg);line-height:var(--tw-leading,var(--text-lg--line-height))}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-xl{font-size:var(--text-xl);line-height:var(--tw-leading,var(--text-xl--line-height))}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.leading-none{--tw-leading:1;line-height:1}.font-bold{--tw-font-weight:var(--font-weight-bold);font-weight:var(--font-weight-bold)}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.font-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.break-words{overflow-wrap:break-word}.break-all{word-break:break-all}.whitespace-nowrap{white-space:nowrap}.whitespace-pre-wrap{white-space:pre-wrap}.text-amber-600{color:var(--color-amber-600)}.text-blue-400{color:var(--color-blue-400)}.text-blue-500{color:var(--color-blue-500)}.text-blue-600{color:var(--color-blue-600)}.text-blue-700{color:var(--color-blue-700)}.text-blue-800{color:var(--color-blue-800)}.text-gray-200{color:var(--color-gray-200)}.text-gray-300{color:var(--color-gray-300)}.text-gray-400{color:var(--color-gray-400)}.text-gray-500{color:var(--color-gray-500)}.text-gray-600{color:var(--color-gray-600)}.text-gray-700{color:var(--color-gray-700)}.text-gray-800{color:var(--color-gray-800)}.text-gray-900{color:var(--color-gray-900)}.text-green-400{color:var(--color-green-400)}.text-green-500{color:var(--color-green-500)}.text-green-600{color:var(--color-green-600)}.text-green-700{color:var(--color-green-700)}.text-green-800{color:var(--color-green-800)}.text-orange-700{color:var(--color-orange-700)}.text-orange-800{color:var(--color-orange-800)}.text-purple-700{color:var(--color-purple-700)}.text-red-500{color:var(--color-red-500)}.text-red-600{color:var(--color-red-600)}.text-red-700{color:var(--color-red-700)}.text-white{color:var(--color-white)}.text-yellow-600{color:var(--color-yellow-600)}.text-yellow-700{color:var(--color-yellow-700)}.text-yellow-800{color:var(--color-yellow-800)}.uppercase{text-transform:uppercase}.italic{font-style:italic}.tabular-nums{--tw-numeric-spacing:tabular-nums;font-variant-numeric:var(--tw-ordinal,) var(--tw-slashed-zero,) var(--tw-numeric-figure,) var(--tw-numeric-spacing,) var(--tw-numeric-fraction,)}.underline{text-decoration-line:underline}.opacity-0{opacity:0}.opacity-25{opacity:.25}.opacity-60{opacity:.6}.opacity-75{opacity:.75}.shadow-2xl{--tw-shadow:0 25px 50px -12px var(--tw-shadow-color,#00000040);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-lg{--tw-shadow:0 10px 15px -3px var(--tw-shadow-color,#0000001a), 0 4px 6px -4px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-sm{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a), 0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-xl{--tw-shadow:0 20px 25px -5px var(--tw-shadow-color,#0000001a), 0 8px 10px -6px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.filter{filter:var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,)}.transition-all{transition-property:all;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.duration-500{--tw-duration:.5s;transition-duration:.5s}.ease-out{--tw-ease:var(--ease-out);transition-timing-function:var(--ease-out)}.select-none{-webkit-user-select:none;user-select:none}@media(hover:hover){.group-hover\:opacity-100:is(:where(.group):hover *){opacity:1}.hover\:border-gray-300:hover{border-color:var(--color-gray-300)}.hover\:bg-blue-100:hover{background-color:var(--color-blue-100)}.hover\:bg-blue-200:hover{background-color:var(--color-blue-200)}.hover\:bg-blue-600:hover{background-color:var(--color-blue-600)}.hover\:bg-blue-700:hover{background-color:var(--color-blue-700)}.hover\:bg-gray-50:hover{background-color:var(--color-gray-50)}.hover\:bg-gray-100:hover{background-color:var(--color-gray-100)}.hover\:bg-gray-200:hover{background-color:var(--color-gray-200)}.hover\:bg-gray-300:hover{background-color:var(--color-gray-300)}.hover\:bg-gray-500:hover{background-color:var(--color-gray-500)}.hover\:bg-gray-600:hover{background-color:var(--color-gray-600)}.hover\:bg-gray-700:hover{background-color:var(--color-gray-700)}.hover\:bg-green-100:hover{background-color:var(--color-green-100)}.hover\:bg-green-200:hover{background-color:var(--color-green-200)}.hover\:bg-green-600:hover{background-color:var(--color-green-600)}.hover\:bg-green-700:hover{background-color:var(--color-green-700)}.hover\:bg-orange-600:hover{background-color:var(--color-orange-600)}.hover\:bg-red-50:hover{background-color:var(--color-red-50)}.hover\:bg-red-100:hover{background-color:var(--color-red-100)}.hover\:bg-red-200:hover{background-color:var(--color-red-200)}.hover\:bg-red-600:hover{background-color:var(--color-red-600)}.hover\:bg-red-700:hover{background-color:var(--color-red-700)}.hover\:bg-yellow-200:hover{background-color:var(--color-yellow-200)}.hover\:text-blue-700:hover{color:var(--color-blue-700)}.hover\:text-blue-800:hover{color:var(--color-blue-800)}.hover\:text-gray-600:hover{color:var(--color-gray-600)}.hover\:text-gray-700:hover{color:var(--color-gray-700)}.hover\:text-green-800:hover{color:var(--color-green-800)}.hover\:text-red-500:hover{color:var(--color-red-500)}.hover\:underline:hover{text-decoration-line:underline}}.focus\:border-blue-500:focus{border-color:var(--color-blue-500)}.focus\:border-transparent:focus{border-color:#0000}.focus\:ring-2:focus{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.focus\:ring-blue-400:focus{--tw-ring-color:var(--color-blue-400)}.focus\:ring-blue-500:focus{--tw-ring-color:var(--color-blue-500)}.focus\:ring-gray-400:focus{--tw-ring-color:var(--color-gray-400)}.focus\:ring-gray-800:focus{--tw-ring-color:var(--color-gray-800)}.focus\:ring-yellow-400:focus{--tw-ring-color:var(--color-yellow-400)}.focus\:outline-none:focus{--tw-outline-style:none;outline-style:none}.disabled\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\:opacity-40:disabled{opacity:.4}.disabled\:opacity-50:disabled{opacity:.5}@media(min-width:64rem){.lg\:col-span-2{grid-column:span 2/span 2}.lg\:col-span-3{grid-column:span 3/span 3}.lg\:grid-cols-5{grid-template-columns:repeat(5,minmax(0,1fr))}}}@keyframes pulse-anim{0%,to{opacity:1}50%{opacity:.4}}.pulse-dot{animation:1.5s cubic-bezier(.4,0,.6,1) infinite pulse-anim}.plan-doc h1{margin:1rem 0 .5rem;font-size:1.5rem;font-weight:700}.plan-doc h2{margin:.8rem 0 .4rem;font-size:1.25rem;font-weight:600}.plan-doc h3{margin:.6rem 0 .3rem;font-size:1.1rem;font-weight:600}.plan-doc p{margin:.4rem 0;line-height:1.6}.plan-doc ul,.plan-doc ol{margin:.4rem 0 .4rem 1.5rem}.plan-doc li{margin:.2rem 0}.plan-doc code{background:#f3f4f6;border-radius:.25rem;padding:.1rem .3rem;font-size:.875rem}.plan-doc pre{color:#e5e7eb;background:#1f2937;border-radius:.5rem;margin:.5rem 0;padding:1rem;overflow-x:auto}.plan-doc pre code{color:inherit;background:0 0}.plan-doc table{border-collapse:collapse;width:100%;margin:.5rem 0}.plan-doc th,.plan-doc td{text-align:left;border:1px solid #d1d5db;padding:.4rem .6rem}.plan-doc th{background:#f9fafb;font-weight:600}.plan-doc input[type=checkbox]{margin-right:.4rem}.agent-log{font-family:Menlo,Consolas,Monaco,monospace;font-size:.75rem;line-height:1.5}.agent-log-item{border-left:3px solid #0000;padding:.25rem .5rem}.agent-log-item.log-assistant{background:#eff6ff;border-left-color:#3b82f6}.agent-log-item.log-tool_use{background:#f5f3ff;border-left-color:#8b5cf6}.agent-log-item.log-tool_result{background:#ecfdf5;border-left-color:#10b981}.agent-log-item.log-result{background:#fffbeb;border-left-color:#f59e0b}.agent-log-item.log-stderr{background:#fef2f2;border-left-color:#ef4444}.agent-log-item.log-raw{background:#f9fafb;border-left-color:#6b7280}.agent-log-item.log-system{background:#f0f9ff;border-left-color:#0ea5e9}.agent-log-item.log-partial{background:#f8fafc;border-left-color:#94a3b8}.agent-log-item .log-badge{text-align:center;color:#fff;border-radius:.25rem;min-width:4.5rem;margin-right:.4rem;padding:.05rem .35rem;font-size:.65rem;font-weight:600;display:inline-block}.agent-log-item.log-assistant .log-badge{background:#3b82f6}.agent-log-item.log-tool_use .log-badge{background:#8b5cf6}.agent-log-item.log-tool_result .log-badge{background:#10b981}.agent-log-item.log-result .log-badge{background:#f59e0b}.agent-log-item.log-stderr .log-badge{background:#ef4444}.agent-log-item.log-raw .log-badge{background:#6b7280}.agent-log-item.log-system .log-badge{background:#0ea5e9}.agent-log-item.log-partial .log-badge{background:#94a3b8}.label-tag{border-radius:9999px;margin-bottom:.15rem;margin-right:.25rem;padding:.1rem .4rem;font-size:.65rem;font-weight:500;display:inline-block}.fade-enter-active,.fade-leave-active{transition:opacity .2s}.fade-enter-from,.fade-leave-to{opacity:0}.fullscreen-doc-overlay{z-index:60;background:#00000080;justify-content:center;align-items:center;padding:2rem;display:flex;position:fixed;inset:0}.fullscreen-doc-container{background:#fff;border-radius:.75rem;flex-direction:column;width:100%;max-width:960px;height:100%;display:flex;overflow:hidden;box-shadow:0 25px 50px -12px #00000040}@media(min-width:1280px){.fullscreen-doc-container{max-width:1100px}}.fullscreen-fade-enter-active{transition:opacity .2s}.fullscreen-fade-enter-active .fullscreen-doc-container{transition:transform .2s}.fullscreen-fade-leave-active{transition:opacity .15s}.fullscreen-fade-leave-active .fullscreen-doc-container{transition:transform .15s}.fullscreen-fade-enter-from{opacity:0}.fullscreen-fade-enter-from .fullscreen-doc-container{transform:scale(.95)}.fullscreen-fade-leave-to{opacity:0}.fullscreen-fade-leave-to .fullscreen-doc-container{transform:scale(.95)}@property --tw-space-y-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-space-x-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-divide-y-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-leading{syntax:"*";inherits:false}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-ordinal{syntax:"*";inherits:false}@property --tw-slashed-zero{syntax:"*";inherits:false}@property --tw-numeric-figure{syntax:"*";inherits:false}@property --tw-numeric-spacing{syntax:"*";inherits:false}@property --tw-numeric-fraction{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"<length>";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-blur{syntax:"*";inherits:false}@property --tw-brightness{syntax:"*";inherits:false}@property --tw-contrast{syntax:"*";inherits:false}@property --tw-grayscale{syntax:"*";inherits:false}@property --tw-hue-rotate{syntax:"*";inherits:false}@property --tw-invert{syntax:"*";inherits:false}@property --tw-opacity{syntax:"*";inherits:false}@property --tw-saturate{syntax:"*";inherits:false}@property --tw-sepia{syntax:"*";inherits:false}@property --tw-drop-shadow{syntax:"*";inherits:false}@property --tw-drop-shadow-color{syntax:"*";inherits:false}@property --tw-drop-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-drop-shadow-size{syntax:"*";inherits:false}@property --tw-duration{syntax:"*";inherits:false}@property --tw-ease{syntax:"*";inherits:false}@keyframes spin{to{transform:rotate(360deg)}}@keyframes ping{75%,to{opacity:0;transform:scale(2)}}@keyframes pulse{50%{opacity:.5}}@keyframes bounce{0%,to{animation-timing-function:cubic-bezier(.8,0,1,1);transform:translateY(-25%)}50%{animation-timing-function:cubic-bezier(0,0,.2,1);transform:none}}
|
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
<meta charset="UTF-8">
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
6
|
<title>Issue Auto-Finish Dashboard</title>
|
|
7
|
-
<script type="module" crossorigin src="/assets/index-
|
|
8
|
-
<link rel="stylesheet" crossorigin href="/assets/index-
|
|
7
|
+
<script type="module" crossorigin src="/assets/index-AcJ0lPIv.js"></script>
|
|
8
|
+
<link rel="stylesheet" crossorigin href="/assets/index-BbRt5BAr.css">
|
|
9
9
|
</head>
|
|
10
10
|
<body class="bg-gray-50 min-h-screen">
|
|
11
11
|
<div id="app"></div>
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/web/routes/setup.ts"],"sourcesContent":["import { Router, Request, Response } from 'express';\nimport fs from 'node:fs';\nimport { DependencyChecker } from '../../cli/setup/DependencyChecker.js';\nimport { ConfigGenerator, SetupConfig } from '../../cli/setup/ConfigGenerator.js';\n\nexport interface SetupRouterDeps {\n configPath?: string;\n onComplete?: (configPath: string) => void;\n serviceMode?: boolean;\n}\n\nexport function createSetupRouter(deps: SetupRouterDeps = {}): Router {\n const router = Router();\n const checker = new DependencyChecker();\n\n router.get('/api/setup/status', (_req: Request, res: Response) => {\n const initialized = deps.serviceMode || ConfigGenerator.isInitialized(deps.configPath);\n res.json({\n initialized,\n configPath: deps.configPath ?? ConfigGenerator.getGlobalConfigPath(),\n globalConfigDir: ConfigGenerator.getGlobalConfigDir(),\n });\n });\n\n router.get('/api/setup/check-env', async (_req: Request, res: Response) => {\n try {\n const aiMode = ((_req.query.aiMode as string) || undefined);\n const results = await checker.checkAll(aiMode);\n res.json({ dependencies: results });\n } catch (err) {\n res.status(500).json({ error: (err as Error).message });\n }\n });\n\n router.post('/api/setup/validate-token', async (req: Request, res: Response) => {\n const { apiUrl, token } = req.body as { apiUrl?: string; token?: string };\n if (!apiUrl || !token) {\n res.status(400).json({ error: 'apiUrl and token are required' });\n return;\n }\n try {\n const url = `${apiUrl.replace(/\\/$/, '')}/api/v3/user`;\n const resp = await fetch(url, {\n headers: { 'PRIVATE-TOKEN': token },\n signal: AbortSignal.timeout(10000),\n });\n if (resp.ok) {\n const user = (await resp.json()) as { username?: string; name?: string };\n res.json({ valid: true, user: { username: user.username, name: user.name } });\n } else {\n res.json({ valid: false, error: `HTTP ${resp.status}: ${resp.statusText}` });\n }\n } catch (err) {\n res.json({ valid: false, error: (err as Error).message });\n }\n });\n\n router.post('/api/setup/validate-repo', async (req: Request, res: Response) => {\n const { apiUrl, token, projectPath } = req.body as {\n apiUrl?: string; token?: string; projectPath?: string;\n };\n if (!apiUrl || !token || !projectPath) {\n res.status(400).json({ error: 'apiUrl, token, and projectPath are required' });\n return;\n }\n try {\n const encoded = encodeURIComponent(projectPath);\n const url = `${apiUrl.replace(/\\/$/, '')}/api/v3/projects/${encoded}`;\n const resp = await fetch(url, {\n headers: { 'PRIVATE-TOKEN': token },\n signal: AbortSignal.timeout(10000),\n });\n if (resp.ok) {\n const project = (await resp.json()) as {\n id?: number; name?: string; path_with_namespace?: string;\n };\n res.json({ valid: true, project });\n } else {\n res.json({ valid: false, error: `HTTP ${resp.status}: ${resp.statusText}` });\n }\n } catch (err) {\n res.json({ valid: false, error: (err as Error).message });\n }\n });\n\n router.post('/api/setup/install-dep', (req: Request, res: Response) => {\n const { name } = req.body as { name?: string };\n if (!name) {\n res.status(400).json({ error: 'name is required' });\n return;\n }\n\n res.setHeader('Content-Type', 'text/event-stream');\n res.setHeader('Cache-Control', 'no-cache');\n res.setHeader('Connection', 'keep-alive');\n res.flushHeaders();\n\n (async () => {\n try {\n for await (const line of checker.install(name)) {\n res.write(`data: ${JSON.stringify({ line })}\\n\\n`);\n }\n res.write(`data: ${JSON.stringify({ done: true })}\\n\\n`);\n } catch (err) {\n res.write(`data: ${JSON.stringify({ error: (err as Error).message })}\\n\\n`);\n } finally {\n res.end();\n }\n })();\n\n req.on('close', () => {\n res.end();\n });\n });\n\n router.post('/api/setup/generate-preview', (req: Request, res: Response) => {\n const config = req.body as SetupConfig;\n try {\n const preview = ConfigGenerator.generate(config);\n res.json({ preview });\n } catch (err) {\n res.status(400).json({ error: (err as Error).message });\n }\n });\n\n router.post('/api/setup/complete', (req: Request, res: Response) => {\n const { config, outputPath } = req.body as {\n config?: SetupConfig;\n outputPath?: string;\n };\n if (!config) {\n res.status(400).json({ error: 'config is required' });\n return;\n }\n try {\n const targetPath = outputPath ?? deps.configPath;\n const savedPath = ConfigGenerator.write(config, targetPath);\n res.json({ success: true, configPath: savedPath });\n deps.onComplete?.(savedPath);\n } catch (err) {\n res.status(500).json({ error: (err as Error).message });\n }\n });\n\n router.post('/api/setup/check-path', (req: Request, res: Response) => {\n const { path: dirPath } = req.body as { path?: string };\n if (!dirPath) {\n res.status(400).json({ error: 'path is required' });\n return;\n }\n try {\n const exists = fs.existsSync(dirPath);\n const isDirectory = exists && fs.statSync(dirPath).isDirectory();\n const isGitRepo = exists && fs.existsSync(dirPath + '/.git');\n res.json({ exists, isDirectory, isGitRepo });\n } catch (err) {\n res.json({ exists: false, isDirectory: false, isGitRepo: false, error: (err as Error).message });\n }\n });\n\n return router;\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/supplement/SupplementStore.ts","../src/poller/IssuePoller.ts","../src/web/WebServer.ts","../src/web/routes/api.ts","../src/web/routes/brainstorm.ts","../src/webhook/WebhookServer.ts","../src/webhook/WebhookHandler.ts","../src/webhook/CommandParser.ts","../src/webhook/CommandExecutor.ts","../src/webhook/NoteDeduplicator.ts","../src/webhook/IntentRecognizer.ts","../src/web/AgentLogStore.ts","../src/index.ts"],"sourcesContent":["import fs from 'node:fs';\nimport path from 'node:path';\nimport { logger as rootLogger } from '../logger.js';\n\nconst logger = rootLogger.child('SupplementStore');\n\nexport interface SupplementInfo {\n requirements: string;\n acceptanceCriteria: string;\n scope: string;\n constraints: string;\n references: string;\n freeText: string;\n tapdId: string;\n updatedAt: string;\n}\n\nexport class SupplementStore {\n private dir: string;\n\n constructor(dataDir: string) {\n this.dir = path.join(dataDir, 'supplements');\n }\n\n private filePath(issueIid: number): string {\n return path.join(this.dir, `${issueIid}.json`);\n }\n\n private ensureDir(): void {\n if (!fs.existsSync(this.dir)) {\n fs.mkdirSync(this.dir, { recursive: true });\n }\n }\n\n get(issueIid: number): SupplementInfo | null {\n const fp = this.filePath(issueIid);\n if (!fs.existsSync(fp)) return null;\n try {\n const raw = fs.readFileSync(fp, 'utf-8');\n return JSON.parse(raw) as SupplementInfo;\n } catch (err) {\n logger.error('Failed to read supplement', { issueIid, error: (err as Error).message });\n return null;\n }\n }\n\n save(issueIid: number, data: Omit<SupplementInfo, 'updatedAt'>): SupplementInfo {\n this.ensureDir();\n const info: SupplementInfo = {\n ...data,\n updatedAt: new Date().toISOString(),\n };\n fs.writeFileSync(this.filePath(issueIid), JSON.stringify(info, null, 2), 'utf-8');\n logger.info('Supplement saved', { issueIid });\n return info;\n }\n\n delete(issueIid: number): boolean {\n const fp = this.filePath(issueIid);\n if (!fs.existsSync(fp)) return false;\n try {\n fs.unlinkSync(fp);\n logger.info('Supplement deleted', { issueIid });\n return true;\n } catch {\n return false;\n }\n }\n\n toPromptText(issueIid: number): string {\n const info = this.get(issueIid);\n if (!info) return '';\n\n const sections: string[] = [];\n\n if (info.requirements.trim()) {\n sections.push(`### 补充需求说明\\n${info.requirements.trim()}`);\n }\n if (info.acceptanceCriteria.trim()) {\n sections.push(`### 验收标准\\n${info.acceptanceCriteria.trim()}`);\n }\n if (info.scope.trim()) {\n sections.push(`### 变更范围\\n${info.scope.trim()}`);\n }\n if (info.constraints.trim()) {\n sections.push(`### 约束条件\\n${info.constraints.trim()}`);\n }\n if (info.references.trim()) {\n sections.push(`### 参考链接\\n${info.references.trim()}`);\n }\n if (info.freeText.trim()) {\n sections.push(`### 其他补充\\n${info.freeText.trim()}`);\n }\n\n if (sections.length === 0) return '';\n return `## 补充信息\\n\\n${sections.join('\\n\\n')}`;\n }\n}\n","import { Config } from '../config.js';\nimport { GongfengClient, GongfengIssue } from '../clients/GongfengClient.js';\nimport { IssueTracker } from '../tracker/IssueTracker.js';\nimport { IssueRecord, IssueState } from '../tracker/IssueState.js';\nimport { PipelineOrchestrator } from '../orchestrator/PipelineOrchestrator.js';\nimport { eventBus } from '../events/EventBus.js';\nimport { logger as rootLogger } from '../logger.js';\nimport { t } from '../i18n/index.js';\n\nconst logger = rootLogger.child('IssuePoller');\n\nconst AUTO_FINISH_LABEL = 'auto-finish';\nconst AUTO_APPROVE_CHECK_INTERVAL_MS = 30_000;\n\nexport class IssuePoller {\n private config: Config;\n private gongfeng: GongfengClient;\n private tracker: IssueTracker;\n private orchestrator: PipelineOrchestrator;\n private discoveryTimer: ReturnType<typeof setInterval> | null = null;\n private driveTimer: ReturnType<typeof setInterval> | null = null;\n private activeIssues = new Set<number>();\n private lastAutoApproveCheckMs = 0;\n\n constructor(\n config: Config,\n gongfeng: GongfengClient,\n tracker: IssueTracker,\n orchestrator: PipelineOrchestrator,\n ) {\n this.config = config;\n this.gongfeng = gongfeng;\n this.tracker = tracker;\n this.orchestrator = orchestrator;\n }\n\n start(): void {\n const { discoveryIntervalMs, driveIntervalMs } = this.config.poll;\n logger.info('Issue poller starting', { discoveryIntervalMs, driveIntervalMs });\n\n this.discover();\n this.drive();\n\n this.discoveryTimer = setInterval(() => this.discover(), discoveryIntervalMs);\n this.driveTimer = setInterval(() => this.drive(), driveIntervalMs);\n }\n\n stop(): void {\n if (this.discoveryTimer) {\n clearInterval(this.discoveryTimer);\n this.discoveryTimer = null;\n }\n if (this.driveTimer) {\n clearInterval(this.driveTimer);\n this.driveTimer = null;\n }\n logger.info('Issue poller stopped');\n }\n\n getActiveIssueIids(): number[] {\n return [...this.activeIssues];\n }\n\n private async discover(): Promise<void> {\n try {\n logger.debug('Discovering new issues...');\n const issues = await this.gongfeng.listIssues('opened', AUTO_FINISH_LABEL);\n const newIssues = this.filterNewIssues(issues);\n\n if (newIssues.length === 0) {\n logger.debug('No new issues found');\n return;\n }\n\n logger.info('Discovered new issues', { count: newIssues.length });\n for (const issue of newIssues) {\n this.tracker.create({\n issueId: issue.id,\n issueIid: issue.iid,\n issueTitle: issue.title,\n state: IssueState.Pending,\n branchName: `${this.config.project.branchPrefix}-${issue.iid}`,\n });\n }\n } catch (err) {\n logger.error('Discovery cycle failed', { error: (err as Error).message });\n }\n }\n\n private drive(): void {\n this.maybeAutoApproveWaiting();\n\n const maxConcurrent = this.config.poll.maxConcurrent;\n const available = maxConcurrent - this.activeIssues.size;\n if (available <= 0) {\n logger.debug('Skipping drive — at concurrency limit', {\n active: this.activeIssues.size,\n max: maxConcurrent,\n });\n return;\n }\n\n const drivable = this.tracker\n .getDrivableIssues(this.config.poll.maxRetries)\n .filter((r) => !this.activeIssues.has(r.issueIid));\n\n if (drivable.length === 0) {\n return;\n }\n\n const batch = drivable.slice(0, available);\n logger.info('Driving issues', {\n batchSize: batch.length,\n active: this.activeIssues.size,\n max: maxConcurrent,\n });\n\n for (const record of batch) {\n this.activeIssues.add(record.issueIid);\n this.processInBackground(record);\n }\n }\n\n private maybeAutoApproveWaiting(): void {\n const autoLabels = this.config.review.autoApproveLabels;\n if (!autoLabels.length) return;\n\n const now = Date.now();\n if (now - this.lastAutoApproveCheckMs < AUTO_APPROVE_CHECK_INTERVAL_MS) return;\n this.lastAutoApproveCheckMs = now;\n\n const waiting = this.tracker\n .getAll()\n .filter((r) => r.state === IssueState.WaitingForReview);\n if (!waiting.length) return;\n\n this.autoApproveByLabels(waiting, autoLabels).catch((err) => {\n logger.warn('Auto-approve check failed', { error: (err as Error).message });\n });\n }\n\n private async autoApproveByLabels(\n records: IssueRecord[],\n autoLabels: string[],\n ): Promise<void> {\n for (const record of records) {\n try {\n const issue = await this.gongfeng.getIssueDetail(record.issueId);\n const matched = issue.labels.filter((l) => autoLabels.includes(l));\n if (matched.length === 0) continue;\n\n logger.info('Auto-approving waiting issue (label matched)', {\n iid: record.issueIid,\n matchedLabels: matched,\n });\n this.tracker.updateState(record.issueIid, IssueState.ReviewApproved);\n eventBus.emitTyped('review:approved', { issueIid: record.issueIid });\n\n try {\n await this.gongfeng.createIssueNote(\n record.issueId,\n t('poller.autoApproveComment', { labels: matched.join(', ') }),\n );\n } catch { /* ignore */ }\n } catch (err) {\n logger.warn('Failed to check auto-approve labels', {\n iid: record.issueIid,\n error: (err as Error).message,\n });\n }\n }\n }\n\n private async processInBackground(record: IssueRecord): Promise<void> {\n try {\n const issue = await this.resolveIssue(record.issueId);\n if (!issue) {\n logger.warn('Could not resolve issue from API, skipping', { iid: record.issueIid });\n return;\n }\n await this.orchestrator.processIssue(issue);\n } catch (err) {\n logger.error('Failed to process issue', {\n iid: record.issueIid,\n error: (err as Error).message,\n });\n } finally {\n this.activeIssues.delete(record.issueIid);\n }\n }\n\n private async resolveIssue(issueId: number): Promise<GongfengIssue | null> {\n try {\n return await this.gongfeng.getIssueDetail(issueId);\n } catch {\n return null;\n }\n }\n\n private filterNewIssues(issues: GongfengIssue[]): GongfengIssue[] {\n return issues.filter((issue) => {\n if (!issue.labels.includes(AUTO_FINISH_LABEL)) return false;\n if (issue.labels.some((l) => l === 'auto-finish:done')) return false;\n\n const record = this.tracker.get(issue.iid);\n if (record) return false;\n\n return true;\n });\n }\n}\n","import express from 'express';\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport { createApiRouter, ApiRouterDeps } from './routes/api.js';\nimport { createSetupRouter } from './routes/setup.js';\nimport { createBrainstormRouter } from './routes/brainstorm.js';\nimport { BrainstormService } from '../services/BrainstormService.js';\nimport { IssueTracker } from '../tracker/IssueTracker.js';\nimport { Config } from '../config.js';\nimport { AgentLogStore } from './AgentLogStore.js';\nimport { PipelineOrchestrator } from '../orchestrator/PipelineOrchestrator.js';\nimport { GitOperations } from '../git/GitOperations.js';\nimport { GongfengClient } from '../clients/GongfengClient.js';\nimport { SupplementStore } from '../supplement/SupplementStore.js';\nimport { logger as rootLogger } from '../logger.js';\nimport type { Server } from 'node:http';\n\nconst __dirname = path.dirname(fileURLToPath(import.meta.url));\nconst logger = rootLogger.child('WebServer');\n\nexport interface WebServerDeps {\n tracker: IssueTracker;\n config: Config;\n agentLogStore: AgentLogStore;\n orchestrator: PipelineOrchestrator;\n gongfeng: GongfengClient;\n supplementStore: SupplementStore;\n mainGit?: GitOperations;\n}\n\nexport class WebServer {\n private app: express.Application;\n private server: Server | null = null;\n private port: number;\n\n constructor(deps: WebServerDeps);\n constructor(tracker: IssueTracker, config: Config, agentLogStore: AgentLogStore, orchestrator: PipelineOrchestrator, mainGit?: GitOperations);\n constructor(\n trackerOrDeps: IssueTracker | WebServerDeps,\n config?: Config,\n agentLogStore?: AgentLogStore,\n orchestrator?: PipelineOrchestrator,\n mainGit?: GitOperations,\n ) {\n let apiDeps: ApiRouterDeps;\n\n if (trackerOrDeps instanceof IssueTracker) {\n this.port = config!.web.port;\n apiDeps = {\n tracker: trackerOrDeps,\n config: config!,\n agentLogStore: agentLogStore!,\n orchestrator: orchestrator!,\n mainGit,\n gongfeng: undefined as unknown as GongfengClient,\n supplementStore: undefined as unknown as SupplementStore,\n };\n } else {\n const deps = trackerOrDeps;\n this.port = deps.config.web.port;\n apiDeps = {\n tracker: deps.tracker,\n config: deps.config,\n agentLogStore: deps.agentLogStore,\n orchestrator: deps.orchestrator,\n mainGit: deps.mainGit,\n gongfeng: deps.gongfeng,\n supplementStore: deps.supplementStore,\n };\n }\n\n this.app = express();\n this.app.use(express.json());\n\n const setupRouter = createSetupRouter({ serviceMode: true });\n this.app.use(setupRouter);\n\n const apiRouter = createApiRouter(apiDeps);\n this.app.use(apiRouter);\n\n if (apiDeps.config.brainstorm.enabled) {\n const brainstormService = new BrainstormService(apiDeps.config);\n const brainstormRouter = createBrainstormRouter({\n brainstormService,\n gongfeng: apiDeps.gongfeng,\n });\n this.app.use(brainstormRouter);\n }\n\n const publicDir = apiDeps.config.web.frontendDistDir;\n this.app.use(express.static(publicDir));\n\n this.app.get('{*path}', (_req, res) => {\n res.sendFile(path.join(publicDir, 'index.html'));\n });\n }\n\n start(): Promise<void> {\n return new Promise((resolve) => {\n this.server = this.app.listen(this.port, () => {\n logger.info(`Web UI available at http://localhost:${this.port}`);\n resolve();\n });\n });\n }\n\n stop(): void {\n if (this.server) {\n this.server.close();\n this.server = null;\n logger.info('Web server stopped');\n }\n }\n}\n","import { Router, Request, Response } from 'express';\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport { marked } from 'marked';\nimport { IssueTracker } from '../../tracker/IssueTracker.js';\nimport { IssueState } from '../../tracker/IssueState.js';\nimport { Config } from '../../config.js';\nimport { AgentLogStore } from '../AgentLogStore.js';\nimport { PipelineOrchestrator } from '../../orchestrator/PipelineOrchestrator.js';\nimport { GitOperations } from '../../git/GitOperations.js';\nimport { GongfengClient } from '../../clients/GongfengClient.js';\nimport { SupplementStore } from '../../supplement/SupplementStore.js';\nimport { PlanPersistence } from '../../persistence/PlanPersistence.js';\nimport { getPipelineDef } from '../../pipeline/PipelineDefinition.js';\nimport type { PipelineDef } from '../../pipeline/PipelineDefinition.js';\nimport { eventBus, EventPayload } from '../../events/EventBus.js';\nimport {\n getNoteSyncEnabled, setNoteSyncOverride, isNoteSyncEnabledForIssue,\n} from '../../notesync/NoteSyncSettings.js';\nimport { getE2eEnabled, setE2eOverride } from '../../e2e/E2eSettings.js';\nimport { logger as rootLogger } from '../../logger.js';\nimport { t } from '../../i18n/index.js';\n\nconst logger = rootLogger.child('ApiRoutes');\n\nconst startTime = Date.now();\n\nexport interface ApiRouterDeps {\n tracker: IssueTracker;\n config: Config;\n agentLogStore: AgentLogStore;\n orchestrator: PipelineOrchestrator;\n gongfeng: GongfengClient;\n supplementStore: SupplementStore;\n mainGit?: GitOperations;\n}\n\nfunction buildPreviewInfo(iid: number, orch: PipelineOrchestrator) {\n const ports = orch.getPortAllocator().getPortsForIssue(iid);\n if (!ports) return null;\n const dsm = orch.getDevServerManager();\n const status = dsm.getStatus(iid);\n return {\n ...status,\n ports,\n previewUrl: orch.buildPreviewUrl(iid),\n host: orch.getPreviewHost(),\n };\n}\n\nexport function createApiRouter(deps: ApiRouterDeps): Router;\nexport function createApiRouter(tracker: IssueTracker, config: Config, agentLogStore: AgentLogStore, orchestrator: PipelineOrchestrator, mainGit?: GitOperations): Router;\nexport function createApiRouter(\n trackerOrDeps: IssueTracker | ApiRouterDeps,\n config?: Config,\n agentLogStore?: AgentLogStore,\n orchestrator?: PipelineOrchestrator,\n mainGit?: GitOperations,\n): Router {\n let tracker: IssueTracker;\n let cfg: Config;\n let logStore: AgentLogStore;\n let orch: PipelineOrchestrator;\n let git: GitOperations | undefined;\n let gongfeng: GongfengClient | undefined;\n let supplementStore: SupplementStore | undefined;\n\n if (config !== undefined) {\n tracker = trackerOrDeps as IssueTracker;\n cfg = config!;\n logStore = agentLogStore!;\n orch = orchestrator!;\n git = mainGit;\n } else {\n const deps = trackerOrDeps as ApiRouterDeps;\n tracker = deps.tracker;\n cfg = deps.config;\n logStore = deps.agentLogStore;\n orch = deps.orchestrator;\n git = deps.mainGit;\n gongfeng = deps.gongfeng;\n supplementStore = deps.supplementStore;\n }\n\n const router = Router();\n\n router.get('/api/issues', (_req: Request, res: Response) => {\n const issues = tracker.getAll();\n res.json(issues);\n });\n\n router.get('/api/issues/:iid', async (req: Request, res: Response) => {\n const iid = parseInt(req.params.iid, 10);\n const record = tracker.get(iid);\n if (!record) {\n res.status(404).json({ error: 'Issue not found' });\n return;\n }\n const progress = await readProgress(iid, cfg, tracker, git);\n const preview = buildPreviewInfo(iid, orch);\n res.json({ ...record, progress, preview });\n });\n\n function getIssuePipelineDef(iid: number): PipelineDef {\n const record = tracker.get(iid);\n const mode = record?.pipelineMode ?? orch.getPipelineDef().mode;\n return getPipelineDef(mode === 'plan-mode' ? 'plan-mode' : 'classic');\n }\n\n router.get('/api/issues/:iid/plans/:filename', async (req: Request, res: Response) => {\n const iid = parseInt(req.params.iid, 10);\n const filename = req.params.filename;\n const def = getIssuePipelineDef(iid);\n const allowed = [\n ...def.planFiles.map(f => f.filename),\n 'progress.json', 'issue-meta.json',\n ];\n if (!allowed.includes(filename)) {\n res.status(400).json({ error: 'Invalid filename' });\n return;\n }\n const content = await readPlanFile(iid, filename, cfg, tracker, git);\n if (content === null) {\n res.status(404).json({ error: 'Plan file not found' });\n return;\n }\n if (filename.endsWith('.json')) {\n res.json(JSON.parse(content));\n return;\n }\n if (req.query.format === 'html') {\n const html = await marked(content);\n res.type('html').send(html);\n return;\n }\n res.type('text/markdown').send(content);\n });\n\n router.post('/api/issues/:iid/retry', (req: Request, res: Response) => {\n const iid = parseInt(req.params.iid, 10);\n const ok = tracker.resetForRetry(iid);\n if (!ok) {\n res.status(400).json({ error: 'Issue is not in failed state or not found' });\n return;\n }\n res.json({ success: true, message: `Issue #${iid} reset for retry` });\n });\n\n router.post('/api/issues/:iid/cancel', (req: Request, res: Response) => {\n const iid = parseInt(req.params.iid, 10);\n const ok = tracker.delete(iid);\n if (!ok) {\n res.status(404).json({ error: 'Issue not found in tracker' });\n return;\n }\n res.json({ success: true, message: `Issue #${iid} removed from tracker` });\n });\n\n router.post('/api/issues/:iid/restart', async (req: Request, res: Response) => {\n const iid = parseInt(req.params.iid, 10);\n try {\n await orch.restartIssue(iid);\n res.json({ success: true, message: `Issue #${iid} restarted` });\n } catch (err) {\n const msg = (err as Error).message;\n logger.error('Restart failed', { iid, error: msg });\n res.status(400).json({ error: msg });\n }\n });\n\n router.post('/api/issues/:iid/retry-from-phase', (req: Request, res: Response) => {\n const iid = parseInt(req.params.iid, 10);\n const { phase } = req.body as { phase?: string };\n const def = getIssuePipelineDef(iid);\n const validPhases = def.phases.filter(p => p.kind === 'ai').map(p => p.name);\n if (!phase || !validPhases.includes(phase)) {\n res.status(400).json({ error: `Invalid phase. Must be one of: ${validPhases.join(', ')}` });\n return;\n }\n try {\n orch.retryFromPhase(iid, phase);\n res.json({ success: true, message: `Issue #${iid} reset to phase: ${phase}` });\n } catch (err) {\n const msg = (err as Error).message;\n logger.error('Retry-from-phase failed', { iid, phase, error: msg });\n res.status(400).json({ error: msg });\n }\n });\n\n router.put('/api/issues/:iid/plans/:filename', (req: Request, res: Response) => {\n const iid = parseInt(req.params.iid, 10);\n const filename = req.params.filename;\n const def = getIssuePipelineDef(iid);\n const editableFiles = def.planFiles.filter(f => f.editable).map(f => f.filename);\n if (!editableFiles.includes(filename)) {\n res.status(400).json({ error: `File not editable. Allowed: ${editableFiles.join(', ')}` });\n return;\n }\n const { content } = req.body as { content?: string };\n if (typeof content !== 'string') {\n res.status(400).json({ error: 'Request body must contain a \"content\" string field' });\n return;\n }\n const planDir = getWorktreePlanDir(iid, cfg);\n const filePath = path.join(planDir, filename);\n if (!fs.existsSync(planDir)) {\n res.status(404).json({ error: 'Plan directory not found (worktree may have been cleaned)' });\n return;\n }\n fs.writeFileSync(filePath, content, 'utf-8');\n logger.info('Plan file updated', { iid, filename });\n res.json({ success: true, message: `Plan file ${filename} saved` });\n });\n\n router.get('/api/issues/:iid/logs', (req: Request, res: Response) => {\n const iid = parseInt(req.params.iid, 10);\n const record = tracker.get(iid);\n if (!record) {\n res.status(404).json({ error: 'Issue not found' });\n return;\n }\n const logs = logStore.getLogs(iid);\n res.json(logs);\n });\n\n // --- Supplement endpoints ---\n\n router.get('/api/issues/:iid/supplement', (req: Request, res: Response) => {\n if (!supplementStore) {\n res.status(501).json({ error: 'Supplement store not available' });\n return;\n }\n const iid = parseInt(req.params.iid, 10);\n const info = supplementStore.get(iid);\n res.json(info);\n });\n\n router.put('/api/issues/:iid/supplement', (req: Request, res: Response) => {\n if (!supplementStore) {\n res.status(501).json({ error: 'Supplement store not available' });\n return;\n }\n const iid = parseInt(req.params.iid, 10);\n const body = req.body as Record<string, unknown>;\n const data = {\n requirements: String(body.requirements || ''),\n acceptanceCriteria: String(body.acceptanceCriteria || ''),\n scope: String(body.scope || ''),\n constraints: String(body.constraints || ''),\n references: String(body.references || ''),\n freeText: String(body.freeText || ''),\n tapdId: String(body.tapdId || ''),\n };\n const saved = supplementStore.save(iid, data);\n res.json({ success: true, data: saved });\n });\n\n // --- Gongfeng issue browsing ---\n\n router.get('/api/gongfeng/issues', async (req: Request, res: Response) => {\n if (!gongfeng) {\n res.status(501).json({ error: 'Gongfeng client not available' });\n return;\n }\n try {\n const search = (req.query.search as string) || '';\n const page = parseInt(req.query.page as string, 10) || 1;\n const perPage = parseInt(req.query.per_page as string, 10) || 20;\n\n const result = await gongfeng.listIssuesAdvanced({\n state: 'opened',\n search: search || undefined,\n page,\n perPage,\n });\n\n const trackedIids = new Set(tracker.getAll().map((r) => r.issueIid));\n\n res.json({\n issues: result.issues,\n total: result.total,\n trackedIids: Array.from(trackedIids),\n });\n } catch (err) {\n const msg = (err as Error).message;\n logger.error('Failed to fetch gongfeng issues', { error: msg });\n res.status(500).json({ error: msg });\n }\n });\n\n // --- Start processing an issue ---\n\n router.post('/api/issues/start', async (req: Request, res: Response) => {\n if (!gongfeng) {\n res.status(501).json({ error: 'Gongfeng client not available' });\n return;\n }\n const body = req.body as {\n issueId?: number;\n issueIid?: number;\n issueTitle?: string;\n supplement?: Record<string, string>;\n };\n if (!body.issueId || !body.issueIid || !body.issueTitle) {\n res.status(400).json({ error: 'issueId, issueIid, and issueTitle are required' });\n return;\n }\n\n const existing = tracker.get(body.issueIid);\n if (existing) {\n res.status(409).json({ error: `Issue #${body.issueIid} is already being tracked` });\n return;\n }\n\n try {\n await gongfeng.addLabel(body.issueId, 'auto-finish');\n } catch (err) {\n logger.warn('Failed to add auto-finish label', { error: (err as Error).message });\n }\n\n const branchName = `${cfg.project.branchPrefix}-${body.issueIid}`;\n const record = tracker.create({\n issueId: body.issueId,\n issueIid: body.issueIid,\n issueTitle: body.issueTitle,\n state: IssueState.Pending,\n branchName,\n });\n\n if (supplementStore && body.supplement) {\n supplementStore.save(body.issueIid, {\n requirements: String(body.supplement.requirements || ''),\n acceptanceCriteria: String(body.supplement.acceptanceCriteria || ''),\n scope: String(body.supplement.scope || ''),\n constraints: String(body.supplement.constraints || ''),\n references: String(body.supplement.references || ''),\n freeText: String(body.supplement.freeText || ''),\n tapdId: String(body.supplement.tapdId || ''),\n });\n }\n\n res.json({ success: true, record });\n });\n\n // --- Review Gate endpoints ---\n\n router.post('/api/issues/:iid/approve-plan', (req: Request, res: Response) => {\n const iid = parseInt(req.params.iid, 10);\n const record = tracker.get(iid);\n if (!record) {\n res.status(404).json({ error: 'Issue not found' });\n return;\n }\n if (record.state !== IssueState.WaitingForReview) {\n res.status(400).json({ error: `Issue is not waiting for review (current state: ${record.state})` });\n return;\n }\n tracker.updateState(iid, IssueState.ReviewApproved);\n const def = getIssuePipelineDef(iid);\n const reviewSpec = def.phases.find(p => p.kind === 'gate');\n if (reviewSpec) {\n const workDir = getWorktreeWorkDir(iid, cfg);\n const planPersistence = new PlanPersistence(workDir, iid);\n planPersistence.updatePhaseProgress(reviewSpec.name, 'completed');\n }\n eventBus.emitTyped('review:approved', { issueIid: iid });\n logger.info('Plan approved', { iid });\n res.json({ success: true, message: `Issue #${iid} plan approved, will resume on next drive cycle` });\n });\n\n router.post('/api/issues/:iid/reject-plan', (req: Request, res: Response) => {\n const iid = parseInt(req.params.iid, 10);\n const record = tracker.get(iid);\n if (!record) {\n res.status(404).json({ error: 'Issue not found' });\n return;\n }\n if (record.state !== IssueState.WaitingForReview) {\n res.status(400).json({ error: `Issue is not waiting for review (current state: ${record.state})` });\n return;\n }\n const { feedback } = req.body as { feedback?: string };\n if (!feedback || typeof feedback !== 'string') {\n res.status(400).json({ error: 'Feedback is required' });\n return;\n }\n const workDir = getWorktreeWorkDir(iid, cfg);\n if (fs.existsSync(workDir)) {\n const planPersistence = new PlanPersistence(workDir, iid);\n planPersistence.writeReviewFeedback(feedback);\n }\n tracker.updateState(iid, IssueState.BranchCreated);\n eventBus.emitTyped('review:rejected', { issueIid: iid, feedback });\n logger.info('Plan rejected', { iid, feedback: feedback.slice(0, 100) });\n\n if (gongfeng && isNoteSyncEnabledForIssue(iid, tracker, cfg)) {\n const baseUrl = cfg.issueNoteSync.webBaseUrl.replace(/\\/$/, '');\n const planFile = record.pipelineMode === 'plan-mode' ? '01-plan.md' : '02-design.md';\n const history = fs.existsSync(workDir)\n ? new PlanPersistence(workDir, iid).readReviewHistory()\n : [];\n const round = history.length;\n const note = [\n t('api.reviewFeedback', { round }),\n '',\n feedback,\n '',\n '---',\n t('api.viewPlan', { url: `${baseUrl}/doc/${iid}/${planFile}` }),\n t('api.viewDetail', { url: `${baseUrl}/?issue=${iid}` }),\n ].join('\\n');\n gongfeng.createIssueNote(record.issueId, note).catch((err) => {\n logger.warn('Failed to sync review feedback to issue', { error: (err as Error).message });\n });\n }\n\n res.json({ success: true, message: `Issue #${iid} plan rejected, will re-plan on next drive cycle` });\n });\n\n router.post('/api/issues/:iid/skip-review', (req: Request, res: Response) => {\n const iid = parseInt(req.params.iid, 10);\n const record = tracker.get(iid);\n if (!record) {\n res.status(404).json({ error: 'Issue not found' });\n return;\n }\n if (record.state !== IssueState.WaitingForReview) {\n res.status(400).json({ error: `Issue is not waiting for review (current state: ${record.state})` });\n return;\n }\n tracker.updateState(iid, IssueState.ReviewApproved);\n const def = getIssuePipelineDef(iid);\n const reviewSpec = def.phases.find(p => p.kind === 'gate');\n if (reviewSpec) {\n const workDir = getWorktreeWorkDir(iid, cfg);\n const planPersistence = new PlanPersistence(workDir, iid);\n planPersistence.updatePhaseProgress(reviewSpec.name, 'completed');\n }\n eventBus.emitTyped('review:approved', { issueIid: iid });\n logger.info('Review skipped', { iid });\n res.json({ success: true, message: `Issue #${iid} review skipped` });\n });\n\n router.get('/api/issues/:iid/review-history', (req: Request, res: Response) => {\n const iid = parseInt(req.params.iid, 10);\n const record = tracker.get(iid);\n if (!record) {\n res.status(404).json({ error: 'Issue not found' });\n return;\n }\n const workDir = getWorktreeWorkDir(iid, cfg);\n if (!fs.existsSync(workDir)) {\n res.json([]);\n return;\n }\n const planPersistence = new PlanPersistence(workDir, iid);\n res.json(planPersistence.readReviewHistory());\n });\n\n // --- Note Sync toggle endpoints ---\n\n router.put('/api/issues/:iid/note-sync', (req: Request, res: Response) => {\n const iid = parseInt(req.params.iid, 10);\n const record = tracker.get(iid);\n if (!record) {\n res.status(404).json({ error: 'Issue not found' });\n return;\n }\n const { enabled } = req.body as { enabled?: boolean | null };\n const value = enabled === null ? undefined : enabled;\n tracker.updateState(iid, record.state, { issueNoteSyncEnabled: value } as any);\n logger.info('Issue note-sync toggled', { iid, enabled: value });\n res.json({ success: true, issueNoteSyncEnabled: value ?? null });\n });\n\n router.put('/api/system/note-sync', (req: Request, res: Response) => {\n const { enabled } = req.body as { enabled?: boolean };\n if (typeof enabled !== 'boolean') {\n res.status(400).json({ error: 'enabled must be a boolean' });\n return;\n }\n setNoteSyncOverride(enabled);\n logger.info('System note-sync toggled', { enabled });\n res.json({ success: true, issueNoteSyncEnabled: enabled });\n });\n\n // --- Preview endpoints ---\n\n router.get('/api/issues/:iid/preview', (req: Request, res: Response) => {\n const iid = parseInt(req.params.iid, 10);\n const record = tracker.get(iid);\n if (!record) {\n res.status(404).json({ error: 'Issue not found' });\n return;\n }\n const preview = buildPreviewInfo(iid, orch);\n res.json(preview ?? { running: false });\n });\n\n router.post('/api/issues/:iid/stop-preview', (req: Request, res: Response) => {\n const iid = parseInt(req.params.iid, 10);\n const record = tracker.get(iid);\n if (!record) {\n res.status(404).json({ error: 'Issue not found' });\n return;\n }\n orch.stopPreviewServers(iid);\n res.json({ success: true, message: `Preview servers stopped for issue #${iid}` });\n });\n\n // --- E2E UI toggle endpoints ---\n\n router.put('/api/issues/:iid/e2e', (req: Request, res: Response) => {\n const iid = parseInt(req.params.iid, 10);\n const record = tracker.get(iid);\n if (!record) {\n res.status(404).json({ error: 'Issue not found' });\n return;\n }\n const { enabled } = req.body as { enabled?: boolean | null };\n const value = enabled === null ? undefined : enabled;\n tracker.updateState(iid, record.state, { e2eEnabled: value } as any);\n logger.info('Issue e2e toggled', { iid, enabled: value });\n res.json({ success: true, e2eEnabled: value ?? null });\n });\n\n router.put('/api/system/e2e', (req: Request, res: Response) => {\n const { enabled } = req.body as { enabled?: boolean };\n if (typeof enabled !== 'boolean') {\n res.status(400).json({ error: 'enabled must be a boolean' });\n return;\n }\n setE2eOverride(enabled);\n logger.info('System e2e toggled', { enabled });\n res.json({ success: true, e2eEnabled: enabled });\n });\n\n router.get('/api/system/status', (_req: Request, res: Response) => {\n const runningPreviews = orch.getDevServerManager().getRunningIssues();\n res.json({\n uptime: Date.now() - startTime,\n startedAt: new Date(startTime).toISOString(),\n config: {\n discoveryIntervalMs: cfg.poll.discoveryIntervalMs,\n driveIntervalMs: cfg.poll.driveIntervalMs,\n maxRetries: cfg.poll.maxRetries,\n aiMode: cfg.ai.mode,\n pipelineMode: orch.getPipelineDef().mode,\n baseBranch: cfg.project.baseBranch,\n projectPath: cfg.gongfeng.projectPath,\n gongfengBaseUrl: cfg.gongfeng.apiUrl.replace(/\\/$/, ''),\n issueNoteSyncEnabled: getNoteSyncEnabled(cfg),\n e2eEnabled: getE2eEnabled(cfg),\n previewEnabled: cfg.preview.enabled,\n locale: cfg.locale,\n },\n issues: {\n total: tracker.getAll().length,\n active: tracker.getAllActive().length,\n },\n preview: {\n runningCount: runningPreviews.length,\n runningIssues: runningPreviews,\n },\n });\n });\n\n router.get('/api/events', (req: Request, res: Response) => {\n res.setHeader('Content-Type', 'text/event-stream');\n res.setHeader('Cache-Control', 'no-cache');\n res.setHeader('Connection', 'keep-alive');\n res.setHeader('X-Accel-Buffering', 'no');\n res.flushHeaders();\n\n const heartbeat = setInterval(() => {\n res.write(`event: heartbeat\\ndata: ${JSON.stringify({ time: new Date().toISOString() })}\\n\\n`);\n }, 15_000);\n\n const handler = (_eventName: string | symbol, payload: EventPayload) => {\n try {\n res.write(`event: ${payload.type}\\ndata: ${JSON.stringify(payload)}\\n\\n`);\n } catch {\n logger.warn('Failed to write SSE event');\n }\n };\n\n eventBus.on('*', handler);\n res.write(`event: connected\\ndata: ${JSON.stringify({ time: new Date().toISOString() })}\\n\\n`);\n\n req.on('close', () => {\n clearInterval(heartbeat);\n eventBus.off('*', handler);\n });\n });\n\n // --- Standalone document viewer (linked from issue notes) ---\n\n router.get('/doc/:iid/:filename', async (req: Request, res: Response) => {\n const iid = parseInt(req.params.iid, 10);\n const filename = req.params.filename;\n const record = tracker.get(iid);\n const title = record?.issueTitle ?? `Issue #${iid}`;\n\n const def = getIssuePipelineDef(iid);\n const allowed = def.planFiles.map(f => f.filename);\n if (!allowed.includes(filename)) {\n res.status(400).type('html').send(renderDocPage(iid, title, t('api.invalidFilename'), filename));\n return;\n }\n\n const content = await readPlanFile(iid, filename, cfg, tracker, git);\n if (content === null) {\n res.status(404).type('html').send(renderDocPage(iid, title, t('api.docNotGenerated'), filename));\n return;\n }\n\n const htmlBody = await marked(content);\n res.type('html').send(renderDocPage(iid, title, htmlBody, filename));\n });\n\n return router;\n}\n\nconst DOC_LABELS_FUNC = (filename: string): string => t(`docLabel.${filename}`) || filename;\n\nfunction renderDocPage(iid: number, issueTitle: string, htmlBody: string, filename: string): string {\n const docLabel = DOC_LABELS_FUNC(filename);\n return `<!DOCTYPE html>\n<html lang=\"zh-CN\">\n<head>\n<meta charset=\"utf-8\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n<title>Issue #${iid} — ${docLabel}</title>\n<style>\n body { font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Helvetica, Arial, sans-serif; margin: 0; padding: 0; color: #24292f; background: #f6f8fa; }\n .header { background: #fff; border-bottom: 1px solid #d0d7de; padding: 12px 24px; display: flex; align-items: center; gap: 12px; }\n .header .crumb { font-size: 14px; color: #57606a; }\n .header .crumb a { color: #0969da; text-decoration: none; }\n .header .crumb a:hover { text-decoration: underline; }\n .header .crumb .sep { margin: 0 4px; color: #8b949e; }\n .container { max-width: 900px; margin: 24px auto; background: #fff; border: 1px solid #d0d7de; border-radius: 6px; padding: 32px 40px; }\n .markdown-body h1 { font-size: 1.6em; border-bottom: 1px solid #d0d7de; padding-bottom: .3em; }\n .markdown-body h2 { font-size: 1.3em; border-bottom: 1px solid #d0d7de; padding-bottom: .3em; }\n .markdown-body h3 { font-size: 1.1em; }\n .markdown-body pre { background: #f6f8fa; border: 1px solid #d0d7de; border-radius: 6px; padding: 16px; overflow-x: auto; }\n .markdown-body code { background: #f6f8fa; border-radius: 3px; padding: 0.2em 0.4em; font-size: 85%; }\n .markdown-body pre code { background: none; padding: 0; }\n .markdown-body table { border-collapse: collapse; width: 100%; }\n .markdown-body th, .markdown-body td { border: 1px solid #d0d7de; padding: 6px 13px; }\n .markdown-body th { background: #f6f8fa; }\n .markdown-body blockquote { margin: 0; padding: 0 1em; color: #57606a; border-left: 3px solid #d0d7de; }\n .markdown-body ul, .markdown-body ol { padding-left: 2em; }\n .markdown-body li { margin-top: 0.25em; }\n .markdown-body p { margin: 8px 0; }\n .markdown-body a { color: #0969da; }\n</style>\n</head>\n<body>\n <div class=\"header\">\n <div class=\"crumb\">\n <a href=\"/?issue=${iid}\">Issue #${iid}</a>\n <span class=\"sep\">/</span>\n <strong>${docLabel}</strong>\n <span class=\"sep\">·</span>\n <span style=\"font-size:12px;color:#57606a\">${escapeHtml(issueTitle)}</span>\n <span class=\"sep\">·</span>\n <a href=\"/?issue=${iid}\" style=\"font-size:12px\">${t('api.viewInDashboard')}</a>\n </div>\n </div>\n <div class=\"container\">\n <div class=\"markdown-body\">${htmlBody}</div>\n </div>\n</body>\n</html>`;\n}\n\nfunction escapeHtml(text: string): string {\n return text.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/\"/g, '"');\n}\n\nfunction getWorktreeWorkDir(issueIid: number, config: Config): string {\n return path.join(\n config.project.worktreeBaseDir,\n `issue-${issueIid}`,\n config.project.projectSubDir,\n );\n}\n\nfunction getWorktreePlanDir(issueIid: number, config: Config): string {\n return path.join(getWorktreeWorkDir(issueIid, config), '.claude-plan', `issue-${issueIid}`);\n}\n\nfunction getPlanGitPath(issueIid: number, filename: string, config: Config): string {\n return path.posix.join(config.project.projectSubDir, '.claude-plan', `issue-${issueIid}`, filename);\n}\n\nasync function readPlanFileFromGit(\n issueIid: number,\n filename: string,\n config: Config,\n tracker: IssueTracker,\n mainGit?: GitOperations,\n): Promise<string | null> {\n if (!mainGit) return null;\n const record = tracker.get(issueIid);\n if (!record) return null;\n const gitPath = getPlanGitPath(issueIid, filename, config);\n return mainGit.showFile(record.branchName, gitPath);\n}\n\nconst VERIFY_REPORT_FALLBACKS: Record<string, string> = {\n '02-verify-report.md': '04-verify-report.md',\n};\n\nasync function readPlanFile(\n issueIid: number,\n filename: string,\n config: Config,\n tracker: IssueTracker,\n mainGit?: GitOperations,\n): Promise<string | null> {\n const planDir = getWorktreePlanDir(issueIid, config);\n const filePath = path.join(planDir, filename);\n if (fs.existsSync(filePath)) {\n try {\n return fs.readFileSync(filePath, 'utf-8');\n } catch {\n return null;\n }\n }\n const content = await readPlanFileFromGit(issueIid, filename, config, tracker, mainGit);\n if (content !== null) return content;\n\n const fallback = VERIFY_REPORT_FALLBACKS[filename];\n if (fallback) {\n return readPlanFile(issueIid, fallback, config, tracker, mainGit);\n }\n return null;\n}\n\nasync function readProgress(\n issueIid: number,\n config: Config,\n tracker: IssueTracker,\n mainGit?: GitOperations,\n): Promise<unknown | null> {\n const content = await readPlanFile(issueIid, 'progress.json', config, tracker, mainGit);\n if (!content) return null;\n try {\n return JSON.parse(content);\n } catch {\n return null;\n }\n}\n","import { Router, Request, Response } from 'express';\nimport { BrainstormService, type BrainstormStreamEvent } from '../../services/BrainstormService.js';\nimport { GongfengClient } from '../../clients/GongfengClient.js';\nimport { logger as rootLogger } from '../../logger.js';\n\nconst logger = rootLogger.child('BrainstormRoutes');\n\nexport interface BrainstormRouterDeps {\n brainstormService: BrainstormService;\n gongfeng: GongfengClient;\n}\n\nfunction sseWriter(res: Response) {\n res.setHeader('Content-Type', 'text/event-stream');\n res.setHeader('Cache-Control', 'no-cache');\n res.setHeader('Connection', 'keep-alive');\n res.setHeader('X-Accel-Buffering', 'no');\n res.flushHeaders();\n\n return (event: BrainstormStreamEvent) => {\n try {\n res.write(`event: ${event.type}\\ndata: ${JSON.stringify(event)}\\n\\n`);\n } catch {\n logger.warn('Failed to write SSE brainstorm event');\n }\n };\n}\n\nexport function createBrainstormRouter(deps: BrainstormRouterDeps): Router {\n const router = Router();\n const { brainstormService, gongfeng } = deps;\n\n router.post('/api/brainstorm/sessions', (req: Request, res: Response) => {\n try {\n const { transcript } = req.body as { transcript?: string };\n if (!transcript?.trim()) {\n res.status(400).json({ error: 'transcript is required' });\n return;\n }\n const session = brainstormService.createSession(transcript.trim());\n res.json({ success: true, session });\n } catch (err) {\n logger.error('Failed to create brainstorm session', { error: (err as Error).message });\n res.status(500).json({ error: (err as Error).message });\n }\n });\n\n router.get('/api/brainstorm/sessions/:id', (req: Request, res: Response) => {\n const session = brainstormService.getSession(req.params.id);\n if (!session) {\n res.status(404).json({ error: 'Session not found' });\n return;\n }\n res.json({ success: true, session });\n });\n\n router.post('/api/brainstorm/sessions/:id/generate', async (req: Request, res: Response) => {\n const session = brainstormService.getSession(req.params.id);\n if (!session) {\n res.status(404).json({ error: 'Session not found' });\n return;\n }\n\n const write = sseWriter(res);\n try {\n await brainstormService.generate(req.params.id, write);\n res.write(`event: done\\ndata: ${JSON.stringify({ type: 'done' })}\\n\\n`);\n } catch (err) {\n write({ type: 'error', data: { message: (err as Error).message } });\n } finally {\n res.end();\n }\n });\n\n router.post('/api/brainstorm/sessions/:id/review', async (req: Request, res: Response) => {\n const session = brainstormService.getSession(req.params.id);\n if (!session) {\n res.status(404).json({ error: 'Session not found' });\n return;\n }\n\n const write = sseWriter(res);\n try {\n await brainstormService.review(req.params.id, write);\n res.write(`event: done\\ndata: ${JSON.stringify({ type: 'done' })}\\n\\n`);\n } catch (err) {\n write({ type: 'error', data: { message: (err as Error).message } });\n } finally {\n res.end();\n }\n });\n\n router.post('/api/brainstorm/sessions/:id/refine', async (req: Request, res: Response) => {\n const session = brainstormService.getSession(req.params.id);\n if (!session) {\n res.status(404).json({ error: 'Session not found' });\n return;\n }\n\n const write = sseWriter(res);\n try {\n await brainstormService.refine(req.params.id, write);\n res.write(`event: done\\ndata: ${JSON.stringify({ type: 'done' })}\\n\\n`);\n } catch (err) {\n write({ type: 'error', data: { message: (err as Error).message } });\n } finally {\n res.end();\n }\n });\n\n router.post('/api/brainstorm/sessions/:id/auto-refine', async (req: Request, res: Response) => {\n const session = brainstormService.getSession(req.params.id);\n if (!session) {\n res.status(404).json({ error: 'Session not found' });\n return;\n }\n\n const { rounds } = req.body as { rounds?: number };\n const write = sseWriter(res);\n try {\n await brainstormService.autoRefine(req.params.id, rounds, write);\n res.write(`event: done\\ndata: ${JSON.stringify({ type: 'done' })}\\n\\n`);\n } catch (err) {\n write({ type: 'error', data: { message: (err as Error).message } });\n } finally {\n res.end();\n }\n });\n\n router.post('/api/brainstorm/sessions/:id/create-issue', async (req: Request, res: Response) => {\n const session = brainstormService.getSession(req.params.id);\n if (!session) {\n res.status(404).json({ error: 'Session not found' });\n return;\n }\n if (!session.currentSdd) {\n res.status(400).json({ error: 'No SDD generated yet' });\n return;\n }\n\n try {\n const { title, addAutoFinishLabel } = req.body as {\n title?: string;\n addAutoFinishLabel?: boolean;\n };\n const issueTitle = title?.trim() || extractTitle(session.currentSdd);\n const labels = addAutoFinishLabel !== false ? ['auto-finish'] : [];\n const issue = await gongfeng.createIssue(issueTitle, session.currentSdd, labels);\n logger.info('Issue created from brainstorm', { issueIid: issue.iid, sessionId: session.id });\n res.json({ success: true, issue });\n } catch (err) {\n logger.error('Failed to create issue from brainstorm', { error: (err as Error).message });\n res.status(500).json({ error: (err as Error).message });\n }\n });\n\n return router;\n}\n\nfunction extractTitle(sdd: string): string {\n const firstLine = sdd.split('\\n').find(l => l.trim());\n if (firstLine) {\n return firstLine.replace(/^#+\\s*/, '').trim().slice(0, 200);\n }\n return '脑暴生成的需求';\n}\n","import express from 'express';\nimport { createWebhookRouter, WebhookHandlerDeps } from './WebhookHandler.js';\nimport { IntentRecognizer } from './IntentRecognizer.js';\nimport type { IssueTracker } from '../tracker/IssueTracker.js';\nimport type { PipelineOrchestrator } from '../orchestrator/PipelineOrchestrator.js';\nimport type { SupplementStore } from '../supplement/SupplementStore.js';\nimport type { GongfengClient } from '../clients/GongfengClient.js';\nimport type { Config } from '../config.js';\nimport { logger as rootLogger } from '../logger.js';\nimport type { Server } from 'node:http';\n\nconst logger = rootLogger.child('WebhookServer');\n\nexport interface WebhookServerDeps {\n tracker: IssueTracker;\n orchestrator: PipelineOrchestrator;\n supplementStore: SupplementStore;\n gongfeng: GongfengClient;\n config: Config;\n}\n\nexport class WebhookServer {\n private app: express.Application;\n private server: Server | null = null;\n private port: number;\n\n constructor(deps: WebhookServerDeps) {\n this.port = deps.config.webhook.port;\n\n // 使用 webhook.llmBinary(默认 claude-internal)而非 ai.binary,\n // 因为意图识别需要轻量级 CLI stdin/stdout 接口,cursor CLI 不支持此模式。\n // 详见 IntentRecognizer.ts 类注释。\n const intentRecognizer = deps.config.webhook.llmFallback\n ? new IntentRecognizer({\n binary: deps.config.webhook.llmBinary,\n nvmNodeVersion: deps.config.ai.nvmNodeVersion,\n model: deps.config.ai.model,\n })\n : undefined;\n\n const handlerDeps: WebhookHandlerDeps = {\n tracker: deps.tracker,\n orchestrator: deps.orchestrator,\n supplementStore: deps.supplementStore,\n gongfeng: deps.gongfeng,\n config: deps.config,\n intentRecognizer,\n };\n\n this.app = express();\n this.app.use(express.json());\n this.app.use(createWebhookRouter(handlerDeps));\n\n this.app.get('/health', (_req, res) => {\n res.json({ status: 'ok', service: 'webhook' });\n });\n }\n\n start(): Promise<void> {\n return new Promise((resolve) => {\n this.server = this.app.listen(this.port, () => {\n logger.info(`Webhook server listening on port ${this.port}`);\n resolve();\n });\n });\n }\n\n stop(): void {\n if (this.server) {\n this.server.close();\n this.server = null;\n logger.info('Webhook server stopped');\n }\n }\n}\n","import { Router, Request, Response } from 'express';\nimport { containsTrigger, extractCommandText, parseExact } from './CommandParser.js';\nimport { IntentRecognizer } from './IntentRecognizer.js';\nimport { CommandExecutor, CommandExecutorDeps } from './CommandExecutor.js';\nimport { NoteDeduplicator } from './NoteDeduplicator.js';\nimport type { Config } from '../config.js';\nimport { logger as rootLogger } from '../logger.js';\nimport { t } from '../i18n/index.js';\n\nconst logger = rootLogger.child('WebhookHandler');\n\nexport interface NoteEvent {\n object_kind: string;\n event_type?: string;\n user: { username: string; name: string; user_id?: number };\n object_attributes: {\n id: number;\n note: string;\n noteable_type: string;\n noteable_id: number | string;\n };\n issue?: {\n id: number | null;\n iid: number;\n title: string;\n };\n}\n\nexport interface WebhookHandlerDeps extends CommandExecutorDeps {\n config: Config;\n intentRecognizer?: IntentRecognizer;\n}\n\nexport function createWebhookRouter(deps: WebhookHandlerDeps): Router {\n const router = Router();\n const executor = new CommandExecutor(deps);\n const dedup = new NoteDeduplicator();\n const { config, intentRecognizer } = deps;\n\n const selfToken = config.gongfeng.privateToken;\n\n router.post('/webhook/gongfeng', async (req: Request, res: Response) => {\n if (!config.webhook.enabled) {\n res.status(403).json({ error: 'Webhook is disabled' });\n return;\n }\n\n if (config.webhook.secret) {\n const token = req.headers['x-gitlab-token'] as string | undefined;\n if (token !== config.webhook.secret) {\n logger.warn('Webhook token mismatch');\n res.status(401).json({ error: 'Invalid token' });\n return;\n }\n }\n\n const event = req.body as NoteEvent;\n\n if (!isNoteOnIssue(event)) {\n res.json({ ignored: true, reason: 'not a note on issue' });\n return;\n }\n\n const noteBody = event.object_attributes.note;\n if (!containsTrigger(noteBody)) {\n res.json({ ignored: true, reason: 'no @issue-auto trigger' });\n return;\n }\n\n if (isSelfNote(event, selfToken)) {\n res.json({ ignored: true, reason: 'self-posted note' });\n return;\n }\n\n const noteId = event.object_attributes.id;\n if (dedup.isDuplicate(noteId)) {\n logger.debug('Duplicate note, skipping', { noteId });\n res.json({ ignored: true, reason: 'duplicate' });\n return;\n }\n\n const issueIid = event.issue?.iid;\n const issueId = event.issue?.id;\n if (!issueIid) {\n res.status(400).json({ error: 'Missing issue iid in webhook payload' });\n return;\n }\n if (!issueId) {\n logger.info('Webhook received with null issue id (likely a test ping)', { issueIid });\n res.json({ accepted: true, noteId, issueIid, test: true });\n return;\n }\n\n res.json({ accepted: true, noteId, issueIid });\n\n processCommandAsync(\n noteBody, issueIid, issueId, executor, intentRecognizer, config,\n deps.tracker, deps.gongfeng,\n );\n });\n\n return router;\n}\n\nconst HELP_TEXT_FUNC = () => t('webhook.helpText');\n\nasync function processCommandAsync(\n noteBody: string,\n issueIid: number,\n issueId: number,\n executor: CommandExecutor,\n intentRecognizer: IntentRecognizer | undefined,\n config: Config,\n tracker: { get(iid: number): { state: string } | undefined },\n gongfeng: { createIssueNote(issueId: number, body: string): Promise<void> },\n): Promise<void> {\n try {\n const cmdText = extractCommandText(noteBody);\n if (!cmdText) return;\n\n let command = parseExact(cmdText);\n\n if (!command && intentRecognizer && config.webhook.llmFallback) {\n const record = tracker.get(issueIid);\n const state = record?.state;\n logger.info('Falling back to LLM intent recognition', { issueIid });\n command = await intentRecognizer.recognize(cmdText, state);\n }\n\n if (!command) {\n logger.info('Could not parse command from note', { issueIid, text: cmdText.slice(0, 100) });\n await gongfeng.createIssueNote(issueId, HELP_TEXT_FUNC()).catch((e) =>\n logger.warn('Failed to reply help text', { error: (e as Error).message }),\n );\n return;\n }\n\n await executor.execute(issueIid, issueId, command);\n } catch (err) {\n logger.error('Failed to process webhook command', {\n issueIid,\n error: (err as Error).message,\n });\n }\n}\n\nfunction isNoteOnIssue(event: NoteEvent): boolean {\n return (\n event.object_kind === 'note' &&\n event.object_attributes?.noteable_type?.toLowerCase() === 'issue' &&\n !!event.issue\n );\n}\n\n/**\n * Heuristic to avoid processing notes posted by the bot itself.\n * We check if the note author username matches the token owner.\n * This is imperfect but works for most setups.\n */\nfunction isSelfNote(_event: NoteEvent, _selfToken: string): boolean {\n // Gongfeng webhook payloads include user info but not a direct token mapping.\n // For now, we rely on the fact that bot-posted notes won't contain @issue-auto.\n // A more robust check can be added by comparing event.user.username against\n // a configured bot username (WEBHOOK_BOT_USERNAME env var).\n return false;\n}\n","export type CommandIntent =\n | 'retry'\n | 'retry-from'\n | 'supplement'\n | 'approve'\n | 'reject'\n | 'status'\n | 'restart'\n | 'preview'\n | 'stop-preview'\n | 'clean-notes';\n\nexport interface ParsedCommand {\n intent: CommandIntent;\n phase?: string;\n context?: string;\n feedback?: string;\n}\n\nconst TRIGGER = '@issue-auto';\n\nconst PHASE_ALIAS: Record<string, string> = {\n '分析': 'analysis', '需求分析': 'analysis',\n '设计': 'design', '系统设计': 'design',\n '实现': 'implement', '实施': 'implement', '编码': 'implement',\n '验证': 'verify', '测试': 'verify',\n '规划': 'plan', '构建': 'build',\n};\n\nfunction resolvePhase(raw: string): string {\n const lower = raw.toLowerCase();\n return PHASE_ALIAS[lower] ?? lower;\n}\n\nconst EXACT_PATTERNS: Array<{\n regex: RegExp;\n build: (match: RegExpMatchArray) => ParsedCommand;\n}> = [\n {\n regex: /retry-from\\s+(\\S+)/i,\n build: (m) => ({ intent: 'retry-from', phase: resolvePhase(m[1]) }),\n },\n {\n regex: /(?:从|回到)\\s*(\\S+?)\\s*(?:阶段)?(?:重[试来做新]|开始)/,\n build: (m) => ({ intent: 'retry-from', phase: resolvePhase(m[1]) }),\n },\n {\n regex: /retry\\b/i,\n build: () => ({ intent: 'retry' }),\n },\n {\n regex: /重试|再试/,\n build: () => ({ intent: 'retry' }),\n },\n {\n regex: /restart\\b/i,\n build: () => ({ intent: 'restart' }),\n },\n {\n regex: /(?:重新开始|从头(?:开始|来|做)|重做)/,\n build: () => ({ intent: 'restart' }),\n },\n {\n regex: /approve\\b/i,\n build: () => ({ intent: 'approve' }),\n },\n {\n regex: /(?:批准|通过|同意|LGTM)/i,\n build: () => ({ intent: 'approve' }),\n },\n {\n regex: /reject\\s+([\\s\\S]+)/i,\n build: (m) => ({ intent: 'reject', feedback: m[1].trim() }),\n },\n {\n regex: /(?:驳回|拒绝|打回)[::\\s]*([\\s\\S]+)/,\n build: (m) => ({ intent: 'reject', feedback: m[1].trim() }),\n },\n {\n regex: /supplement\\s+([\\s\\S]+)/i,\n build: (m) => ({ intent: 'supplement', context: m[1].trim() }),\n },\n {\n regex: /(?:补充)[::\\s]*([\\s\\S]+)/,\n build: (m) => ({ intent: 'supplement', context: m[1].trim() }),\n },\n {\n regex: /status\\b/i,\n build: () => ({ intent: 'status' }),\n },\n {\n regex: /(?:状态|什么状态|进度|查询)/,\n build: () => ({ intent: 'status' }),\n },\n {\n regex: /stop-preview\\b/i,\n build: () => ({ intent: 'stop-preview' }),\n },\n {\n regex: /(?:停止预览|关闭预览|停止体验)/,\n build: () => ({ intent: 'stop-preview' }),\n },\n {\n regex: /preview\\b/i,\n build: () => ({ intent: 'preview' }),\n },\n {\n regex: /(?:预览|体验|preview环境)/,\n build: () => ({ intent: 'preview' }),\n },\n {\n regex: /clean-notes\\b/i,\n build: () => ({ intent: 'clean-notes' }),\n },\n {\n regex: /(?:清理评论|清除评论|删除评论)/,\n build: () => ({ intent: 'clean-notes' }),\n },\n];\n\nexport function containsTrigger(text: string): boolean {\n return text.includes(TRIGGER);\n}\n\n/**\n * Extract the portion of text after the @issue-auto trigger.\n * Returns null if trigger is not found.\n */\nexport function extractCommandText(text: string): string | null {\n const idx = text.indexOf(TRIGGER);\n if (idx < 0) return null;\n return text.slice(idx + TRIGGER.length).trim();\n}\n\n/**\n * Try to parse an exact command from the text after the trigger.\n * Returns null if no pattern matches (caller should fall back to LLM).\n */\nexport function parseExact(commandText: string): ParsedCommand | null {\n for (const { regex, build } of EXACT_PATTERNS) {\n const match = commandText.match(regex);\n if (match) return build(match);\n }\n return null;\n}\n\n/**\n * Full parse pipeline: extract trigger text, then try exact match.\n * Returns null if trigger not found or no exact match.\n */\nexport function parseCommand(fullText: string): ParsedCommand | null {\n const commandText = extractCommandText(fullText);\n if (commandText === null) return null;\n return parseExact(commandText);\n}\n","import type { ParsedCommand } from './CommandParser.js';\nimport type { IssueTracker } from '../tracker/IssueTracker.js';\nimport type { PipelineOrchestrator } from '../orchestrator/PipelineOrchestrator.js';\nimport type { SupplementStore } from '../supplement/SupplementStore.js';\nimport type { GongfengClient } from '../clients/GongfengClient.js';\nimport type { Config } from '../config.js';\nimport { IssueState } from '../tracker/IssueState.js';\nimport { getPipelineDef, collectStateLabels } from '../pipeline/PipelineDefinition.js';\nimport { PlanPersistence } from '../persistence/PlanPersistence.js';\nimport { eventBus } from '../events/EventBus.js';\nimport path from 'node:path';\nimport fs from 'node:fs';\nimport { logger as rootLogger } from '../logger.js';\nimport { t } from '../i18n/index.js';\n\nconst logger = rootLogger.child('CommandExecutor');\n\nexport interface CommandExecutorDeps {\n tracker: IssueTracker;\n orchestrator: PipelineOrchestrator;\n supplementStore: SupplementStore;\n gongfeng: GongfengClient;\n config: Config;\n}\n\nexport interface ExecutionResult {\n success: boolean;\n message: string;\n}\n\nexport class CommandExecutor {\n private tracker: IssueTracker;\n private orchestrator: PipelineOrchestrator;\n private supplementStore: SupplementStore;\n private gongfeng: GongfengClient;\n private config: Config;\n\n constructor(deps: CommandExecutorDeps) {\n this.tracker = deps.tracker;\n this.orchestrator = deps.orchestrator;\n this.supplementStore = deps.supplementStore;\n this.gongfeng = deps.gongfeng;\n this.config = deps.config;\n }\n\n async execute(\n issueIid: number,\n issueId: number,\n command: ParsedCommand,\n ): Promise<ExecutionResult> {\n logger.info('Executing webhook command', { issueIid, command });\n\n let result: ExecutionResult;\n try {\n result = await this.dispatch(issueIid, command);\n } catch (err) {\n const msg = (err as Error).message;\n logger.error('Webhook command failed', { issueIid, error: msg });\n result = { success: false, message: msg };\n }\n\n await this.replyToIssue(issueId, result);\n return result;\n }\n\n private async dispatch(iid: number, cmd: ParsedCommand): Promise<ExecutionResult> {\n switch (cmd.intent) {\n case 'retry': return this.handleRetry(iid);\n case 'retry-from': return this.handleRetryFrom(iid, cmd.phase, cmd.context);\n case 'supplement': return this.handleSupplement(iid, cmd.context);\n case 'approve': return this.handleApprove(iid);\n case 'reject': return this.handleReject(iid, cmd.feedback);\n case 'status': return this.handleStatus(iid);\n case 'restart': return this.handleRestart(iid);\n case 'preview': return this.handlePreview(iid);\n case 'stop-preview': return this.handleStopPreview(iid);\n case 'clean-notes': return this.handleCleanNotes(iid);\n default: return { success: false, message: 'Unknown command' };\n }\n }\n\n private handleRetry(iid: number): ExecutionResult {\n const record = this.tracker.get(iid);\n if (!record) return this.notTracked(iid);\n if (record.state !== IssueState.Failed) {\n return this.fail(`Issue not in failed state (current: ${record.state})`);\n }\n const ok = this.tracker.resetForRetry(iid);\n if (!ok) return this.fail('Reset for retry failed');\n return this.ok(`Issue #${iid} has been reset and will retry on the next drive cycle.`);\n }\n\n private handleRetryFrom(iid: number, phase?: string, ctx?: string): ExecutionResult {\n if (!phase) return this.fail('Phase is required for retry-from (e.g. design, implement)');\n if (ctx) this.saveSupplement(iid, ctx);\n\n try {\n this.orchestrator.retryFromPhase(iid, phase);\n } catch (err) {\n return this.fail((err as Error).message);\n }\n\n const extra = ctx ? '\\nSupplement info recorded.' : '';\n return this.ok(`Issue #${iid} will restart from **${phase}** phase.${extra}`);\n }\n\n private handleSupplement(iid: number, ctx?: string): ExecutionResult {\n if (!ctx?.trim()) return this.fail('Supplement content cannot be empty');\n this.saveSupplement(iid, ctx);\n return this.ok('Supplement info recorded. AI will reference it on next execution.');\n }\n\n private handleApprove(iid: number): ExecutionResult {\n const record = this.tracker.get(iid);\n if (!record) return this.notTracked(iid);\n if (record.state !== IssueState.WaitingForReview) {\n return this.fail(`Issue not waiting for review (current: ${record.state})`);\n }\n\n this.tracker.updateState(iid, IssueState.ReviewApproved);\n const def = this.getIssuePipelineDef(record);\n const gate = def.phases.find((p) => p.kind === 'gate');\n if (gate) {\n const workDir = this.getWorktreeWorkDir(iid);\n if (fs.existsSync(workDir)) {\n new PlanPersistence(workDir, iid).updatePhaseProgress(gate.name, 'completed');\n }\n }\n eventBus.emitTyped('review:approved', { issueIid: iid });\n return this.ok('Plan approved. Continuing to next phases.');\n }\n\n private handleReject(iid: number, feedback?: string): ExecutionResult {\n const record = this.tracker.get(iid);\n if (!record) return this.notTracked(iid);\n if (record.state !== IssueState.WaitingForReview) {\n return this.fail(`Issue not waiting for review (current: ${record.state})`);\n }\n if (!feedback?.trim()) return this.fail('Feedback is required when rejecting');\n\n const workDir = this.getWorktreeWorkDir(iid);\n if (fs.existsSync(workDir)) {\n new PlanPersistence(workDir, iid).writeReviewFeedback(feedback);\n }\n this.tracker.updateState(iid, IssueState.BranchCreated);\n eventBus.emitTyped('review:rejected', { issueIid: iid, feedback });\n return this.ok('Plan rejected. Will re-plan based on feedback.');\n }\n\n private handleStatus(iid: number): ExecutionResult {\n const record = this.tracker.get(iid);\n if (!record) return this.notTracked(iid);\n\n const def = this.getIssuePipelineDef(record);\n const labels = collectStateLabels(def);\n const stateLabel = labels.get(record.state) ?? record.state;\n\n const lines = [\n `**Issue #${iid} Status**`,\n '',\n `- State: **${stateLabel}**`,\n `- Branch: \\`${record.branchName}\\``,\n `- Attempts: ${record.attempts}`,\n `- Pipeline: ${record.pipelineMode ?? 'N/A'}`,\n ];\n if (record.lastError) lines.push(`- Last error: ${record.lastError.slice(0, 200)}`);\n if (record.mrUrl) lines.push(`- MR: ${record.mrUrl}`);\n\n const previewUrl = this.orchestrator.buildPreviewUrl(iid);\n if (previewUrl) {\n const dsm = this.orchestrator.getDevServerManager();\n const status = dsm.getStatus(iid);\n lines.push(`- Preview: ${status.running ? `🌐 ${previewUrl}` : t('cmd.previewStopped')}`);\n }\n\n const baseUrl = this.config.issueNoteSync.webBaseUrl.replace(/\\/$/, '');\n lines.push('', `[View in dashboard](${baseUrl}/?issue=${iid})`);\n return this.ok(lines.join('\\n'));\n }\n\n private async handleRestart(iid: number): Promise<ExecutionResult> {\n try {\n await this.orchestrator.restartIssue(iid);\n } catch (err) {\n return this.fail((err as Error).message);\n }\n return this.ok(`Issue #${iid} has been fully reset and will restart from scratch.`);\n }\n\n private handlePreview(iid: number): ExecutionResult {\n const record = this.tracker.get(iid);\n if (!record) return this.notTracked(iid);\n\n const previewUrl = this.orchestrator.buildPreviewUrl(iid);\n if (!previewUrl) {\n return this.ok(\n t('cmd.previewNotStarted', { iid }),\n );\n }\n\n const dsm = this.orchestrator.getDevServerManager();\n const status = dsm.getStatus(iid);\n const ports = this.orchestrator.getPortAllocator().getPortsForIssue(iid);\n const host = this.orchestrator.getPreviewHost();\n\n const lines = [\n '🌐 **Preview Environment**',\n '',\n `| ${t('cmd.previewTable.component')} | ${t('cmd.previewTable.address')} |`,\n `|------|------|`,\n `| ${t('cmd.previewTable.frontend')} | ${previewUrl} |`,\n `| ${t('cmd.previewTable.backendApi')} | http://${host}:${ports!.backendPort}/api |`,\n '',\n `${t('cmd.previewTable.status')}: ${status.running ? t('cmd.previewRunning') : t('cmd.previewStopped')}`,\n ];\n if (status.startedAt) lines.push(`${t('cmd.previewTable.startedAt')}: ${status.startedAt}`);\n\n return this.ok(lines.join('\\n'));\n }\n\n private handleStopPreview(iid: number): ExecutionResult {\n const record = this.tracker.get(iid);\n if (!record) return this.notTracked(iid);\n\n const dsm = this.orchestrator.getDevServerManager();\n const status = dsm.getStatus(iid);\n if (!status.running) {\n return this.ok(t('cmd.noPreview', { iid }));\n }\n\n this.orchestrator.stopPreviewServers(iid);\n return this.ok(t('cmd.previewStoppedMsg', { iid }));\n }\n\n private async handleCleanNotes(iid: number): Promise<ExecutionResult> {\n const record = this.tracker.get(iid);\n if (!record) return this.notTracked(iid);\n\n try {\n const deleted = await this.gongfeng.cleanupAgentNotes(record.issueId);\n return this.ok(t('cmd.cleanNotesSuccess', { count: deleted }));\n } catch (err) {\n return this.fail((err as Error).message);\n }\n }\n\n private saveSupplement(iid: number, context: string): void {\n const existing = this.supplementStore.get(iid);\n const prev = existing?.freeText?.trim() ?? '';\n const merged = prev ? `${prev}\\n\\n---\\n${context}` : context;\n this.supplementStore.save(iid, {\n requirements: existing?.requirements ?? '',\n acceptanceCriteria: existing?.acceptanceCriteria ?? '',\n scope: existing?.scope ?? '',\n constraints: existing?.constraints ?? '',\n references: existing?.references ?? '',\n freeText: merged,\n tapdId: existing?.tapdId ?? '',\n });\n }\n\n private async replyToIssue(issueId: number, result: ExecutionResult): Promise<void> {\n try {\n const prefix = result.success ? '' : '> **Failed**\\n>\\n> ';\n await this.gongfeng.createIssueNote(issueId, `${prefix}${result.message}`);\n } catch (err) {\n logger.warn('Failed to reply', { issueId, error: (err as Error).message });\n }\n }\n\n private ok(message: string): ExecutionResult {\n return { success: true, message };\n }\n\n private fail(message: string): ExecutionResult {\n return { success: false, message };\n }\n\n private notTracked(iid: number): ExecutionResult {\n return this.fail(`Issue #${iid} is not tracked. Add the auto-finish label to start.`);\n }\n\n private getIssuePipelineDef(record: { pipelineMode?: string }) {\n const mode = record.pipelineMode === 'plan-mode' ? 'plan-mode' : 'classic';\n return getPipelineDef(mode);\n }\n\n private getWorktreeWorkDir(iid: number): string {\n return path.join(\n this.config.project.worktreeBaseDir,\n `issue-${iid}`,\n this.config.project.projectSubDir,\n );\n }\n}\n","/**\n * LRU-based deduplication for webhook note IDs.\n * Prevents the same note from being processed twice\n * (e.g. due to webhook retries or duplicate deliveries).\n */\nexport class NoteDeduplicator {\n private seen: Map<number, number>;\n private maxSize: number;\n\n constructor(maxSize: number = 1000) {\n this.seen = new Map();\n this.maxSize = maxSize;\n }\n\n /**\n * Returns true if this noteId has already been processed.\n * If not, marks it as processed and returns false.\n */\n isDuplicate(noteId: number): boolean {\n if (this.seen.has(noteId)) return true;\n this.seen.set(noteId, Date.now());\n this.evictIfNeeded();\n return false;\n }\n\n get size(): number {\n return this.seen.size;\n }\n\n private evictIfNeeded(): void {\n if (this.seen.size <= this.maxSize) return;\n const oldest = this.seen.keys().next().value;\n if (oldest !== undefined) {\n this.seen.delete(oldest);\n }\n }\n}\n","import { spawn } from 'node:child_process';\nimport type { ParsedCommand, CommandIntent } from './CommandParser.js';\nimport { logger as rootLogger } from '../logger.js';\nimport { t } from '../i18n/index.js';\n\nconst logger = rootLogger.child('IntentRecognizer');\n\nconst VALID_INTENTS: CommandIntent[] = [\n 'retry', 'retry-from', 'supplement', 'approve', 'reject', 'status', 'restart',\n];\n\nconst VALID_PHASES = [\n 'analysis', 'design', 'implement', 'verify', 'plan', 'build',\n];\n\nconst SYSTEM_PROMPT_FUNC = () => t('intent.systemPrompt');\n\nexport interface IntentRecognizerConfig {\n binary: string;\n nvmNodeVersion: string;\n model?: string;\n timeoutMs?: number;\n}\n\n/**\n * 通过 LLM 将自然语言评论解析为结构化指令。\n *\n * **为什么默认使用 claude-internal / codebuddy 而非跟随 AI_RUNNER_MODE?**\n *\n * - `cursor` CLI 不支持 `-p`(stdin prompt)、`--output-format`、`--model` 等参数,\n * 且需要连接 VS Code Server,无法在 PM2 无头进程中运行。\n * - `cursor-agent` 是面向多步骤编码任务的完整 IDE agent,对简单的意图分类来说过重。\n * - `claude-internal` 和 `codebuddy` 都提供轻量级 CLI 接口,支持 stdin 传入 prompt\n * 并返回纯文本,适合在后台服务中做短文本意图识别。\n *\n * 因此 `WEBHOOK_LLM_BINARY` 配置独立于 `AI_RUNNER_MODE`,默认值为 `claude-internal`。\n *\n * @see WebhookServer.ts — 构造 IntentRecognizer 时使用 config.webhook.llmBinary\n * @see config.ts — WEBHOOK_LLM_BINARY 环境变量定义\n */\nexport class IntentRecognizer {\n private binary: string;\n private nvmNodeVersion: string;\n private model?: string;\n private timeoutMs: number;\n\n constructor(config: IntentRecognizerConfig) {\n this.binary = config.binary;\n this.nvmNodeVersion = config.nvmNodeVersion;\n this.model = config.model;\n this.timeoutMs = config.timeoutMs ?? 30_000;\n }\n\n async recognize(userComment: string, issueState?: string): Promise<ParsedCommand | null> {\n const stateHint = issueState ? `\\n当前 Issue 状态: ${issueState}` : '';\n const userPrompt = `${SYSTEM_PROMPT_FUNC()}\\n\\n用户评论:${stateHint}\\n${userComment}`;\n\n try {\n const rawOutput = await this.runLLM(userPrompt);\n return this.parseResponse(rawOutput);\n } catch (err) {\n logger.error('Intent recognition failed', { error: (err as Error).message });\n return null;\n }\n }\n\n /** Visible for testing */\n parseResponse(raw: string): ParsedCommand | null {\n const jsonMatch = raw.match(/\\{[\\s\\S]*\\}/);\n if (!jsonMatch) {\n logger.warn('No JSON found in LLM response', { raw: raw.slice(0, 200) });\n return null;\n }\n\n let parsed: Record<string, unknown>;\n try {\n parsed = JSON.parse(jsonMatch[0]);\n } catch {\n logger.warn('Failed to parse JSON from LLM', { raw: jsonMatch[0].slice(0, 200) });\n return null;\n }\n\n if (parsed.intent === null || parsed.intent === 'null') return null;\n\n const intent = String(parsed.intent) as CommandIntent;\n if (!VALID_INTENTS.includes(intent)) {\n logger.warn('Invalid intent from LLM', { intent });\n return null;\n }\n\n const result: ParsedCommand = { intent };\n\n if (parsed.phase && parsed.phase !== 'null') {\n const phase = String(parsed.phase).toLowerCase();\n if (VALID_PHASES.includes(phase)) {\n result.phase = phase;\n }\n }\n\n if (parsed.context && parsed.context !== 'null') {\n result.context = String(parsed.context).trim();\n }\n\n if (parsed.feedback && parsed.feedback !== 'null') {\n result.feedback = String(parsed.feedback).trim();\n }\n\n return result;\n }\n\n private runLLM(prompt: string): Promise<string> {\n return new Promise((resolve, reject) => {\n const args = ['-p', '-', '--output-format', 'text', '--verbose'];\n if (this.model) args.push('--model', this.model);\n\n const { CLAUDECODE, ...env } = process.env;\n const child = spawn(this.binary, args, {\n env: { ...env, NODE_VERSION: this.nvmNodeVersion },\n stdio: ['pipe', 'pipe', 'pipe'],\n });\n\n let stdout = '';\n let stderr = '';\n\n child.stdout.on('data', (d) => { stdout += d.toString(); });\n child.stderr.on('data', (d) => { stderr += d.toString(); });\n\n const timer = setTimeout(() => {\n child.kill('SIGTERM');\n reject(new Error(`Intent recognition timed out after ${this.timeoutMs}ms`));\n }, this.timeoutMs);\n\n child.on('close', (code) => {\n clearTimeout(timer);\n if (code !== 0) {\n logger.warn('LLM process exited with non-zero code', { code, stderr: stderr.slice(0, 300) });\n }\n resolve(stdout);\n });\n\n child.on('error', (err) => {\n clearTimeout(timer);\n reject(err);\n });\n\n child.stdin.write(prompt);\n child.stdin.end();\n });\n }\n}\n","import fs from 'node:fs';\nimport path from 'node:path';\nimport { eventBus, EventPayload } from '../events/EventBus.js';\nimport { logger as rootLogger } from '../logger.js';\n\nconst logger = rootLogger.child('AgentLogStore');\n\nexport interface AgentLogEntry {\n type: string;\n phase?: string;\n timestamp: string;\n summary: string;\n}\n\nconst MAX_LOGS_PER_ISSUE = 20000;\n\nconst DEBUG_EVENT_TYPES = new Set([\n 'thinking', 'content_block_start', 'content_block_delta',\n 'content_block_stop', 'message_start', 'message_delta',\n 'message_stop', 'ping',\n]);\n\nexport class AgentLogStore {\n private logDir: string;\n\n constructor(dataDir: string) {\n this.logDir = path.join(dataDir, 'agent-logs');\n if (!fs.existsSync(this.logDir)) {\n fs.mkdirSync(this.logDir, { recursive: true });\n }\n }\n\n public startListening(): void {\n eventBus.on('agent:output', (payload: EventPayload) => {\n this.handleAgentOutput(payload);\n });\n\n eventBus.on('pipeline:progress', (payload: EventPayload) => {\n this.handlePipelineProgress(payload);\n });\n\n logger.info('AgentLogStore listening for events');\n }\n\n public getLogs(issueIid: number): AgentLogEntry[] {\n const filePath = this.logFilePath(issueIid);\n if (!fs.existsSync(filePath)) return [];\n\n try {\n const raw = fs.readFileSync(filePath, 'utf-8').trim();\n if (!raw) return [];\n return raw.split('\\n').map(line => JSON.parse(line) as AgentLogEntry);\n } catch (err) {\n logger.warn('Failed to read agent logs', { issueIid, error: (err as Error).message });\n return [];\n }\n }\n\n public clearLogs(issueIid: number): void {\n const filePath = this.logFilePath(issueIid);\n if (fs.existsSync(filePath)) {\n fs.unlinkSync(filePath);\n }\n }\n\n private logFilePath(issueIid: number): string {\n return path.join(this.logDir, `${issueIid}.jsonl`);\n }\n\n private appendLog(issueIid: number, entry: AgentLogEntry): void {\n const filePath = this.logFilePath(issueIid);\n try {\n fs.appendFileSync(filePath, `${JSON.stringify(entry)}\\n`, 'utf-8');\n this.trimIfNeeded(issueIid, filePath);\n } catch (err) {\n logger.warn('Failed to write agent log', { issueIid, error: (err as Error).message });\n }\n }\n\n private trimIfNeeded(issueIid: number, filePath: string): void {\n try {\n const raw = fs.readFileSync(filePath, 'utf-8').trim();\n if (!raw) return;\n const lines = raw.split('\\n');\n if (lines.length > MAX_LOGS_PER_ISSUE) {\n const trimmed = lines.slice(-MAX_LOGS_PER_ISSUE);\n fs.writeFileSync(filePath, `${trimmed.join('\\n')}\\n`, 'utf-8');\n logger.info('Agent logs trimmed', { issueIid, from: lines.length, to: trimmed.length });\n }\n } catch {\n // best-effort trimming\n }\n }\n\n private handleAgentOutput(payload: EventPayload): void {\n const d = payload.data as { issueIid?: number; phase?: string; event?: { type?: string; content?: unknown; timestamp?: string } };\n if (!d?.issueIid || !d.event) return;\n\n const eventType = d.event.type || 'raw';\n if (DEBUG_EVENT_TYPES.has(eventType)) return;\n\n const entry: AgentLogEntry = {\n type: eventType,\n phase: d.phase,\n timestamp: d.event.timestamp || payload.timestamp,\n summary: this.summarizeContent(d.event),\n };\n this.appendLog(d.issueIid, entry);\n }\n\n private handlePipelineProgress(payload: EventPayload): void {\n const d = payload.data as { issueIid?: number; step?: string; message?: string };\n if (!d?.issueIid) return;\n\n const entry: AgentLogEntry = {\n type: 'system',\n phase: d.step,\n timestamp: payload.timestamp,\n summary: d.message || '',\n };\n this.appendLog(d.issueIid, entry);\n }\n\n private summarizeContent(event: { type?: string; content?: unknown; timestamp?: string }): string {\n const { content } = event;\n if (!content || typeof content === 'string') return String(content || '');\n\n if (event.type === 'assistant') {\n return this.extractAssistantText(content);\n }\n if (event.type === 'tool_use') {\n return this.extractToolUseText(content);\n }\n if (event.type === 'tool_result') {\n const text = typeof (content as Record<string, unknown>).content === 'string'\n ? (content as Record<string, unknown>).content as string\n : JSON.stringify((content as Record<string, unknown>).content || '');\n return text.slice(0, 150);\n }\n if (event.type === 'result') {\n const r = content as Record<string, unknown>;\n return ((r.result as string) || JSON.stringify(content)).slice(0, 200);\n }\n\n return JSON.stringify(content).slice(0, 150);\n }\n\n private extractAssistantText(content: unknown): string {\n const msg = (content as Record<string, unknown>).message || content;\n if (typeof msg === 'string') return msg.slice(0, 200);\n const m = msg as Record<string, unknown>;\n if (m.text) return (m.text as string).slice(0, 200);\n if (m.content) {\n const parts = Array.isArray(m.content) ? m.content : [m.content];\n const texts = parts\n .filter((c: Record<string, unknown>) => c.type === 'text')\n .map((c: Record<string, unknown>) => c.text)\n .join(' ');\n return texts.slice(0, 200) || JSON.stringify(content).slice(0, 150);\n }\n return JSON.stringify(content).slice(0, 150);\n }\n\n private extractToolUseText(content: unknown): string {\n const c = content as Record<string, unknown>;\n const tool = c.tool as Record<string, unknown> | undefined;\n const name = tool?.name || c.name || '?';\n const input = (tool?.input || c.input || {}) as Record<string, unknown>;\n const detail = input.path || input.command || input.file_path || '';\n return name + (detail ? `: ${detail}` : '');\n }\n}\n","import { loadConfig } from './config.js';\nimport { setLocale } from './i18n/index.js';\nimport { logger } from './logger.js';\nimport { GongfengClient } from './clients/GongfengClient.js';\nimport { GitOperations } from './git/GitOperations.js';\nimport { createAIRunner } from './ai-runner/index.js';\nimport { IssueTracker } from './tracker/IssueTracker.js';\nimport { SupplementStore } from './supplement/SupplementStore.js';\nimport { PipelineOrchestrator } from './orchestrator/PipelineOrchestrator.js';\nimport { validatePhaseRegistry } from './phases/PhaseFactory.js';\nimport { CLASSIC_PIPELINE, PLAN_MODE_PIPELINE } from './pipeline/PipelineDefinition.js';\nimport { IssuePoller } from './poller/IssuePoller.js';\nimport { WebServer } from './web/WebServer.js';\nimport { WebhookServer } from './webhook/WebhookServer.js';\nimport { AgentLogStore } from './web/AgentLogStore.js';\nimport path from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\nconst __dirname = path.dirname(fileURLToPath(import.meta.url));\n\nexport async function main(): Promise<void> {\n logger.info('Issue Auto-Finish service starting...');\n\n const config = loadConfig();\n setLocale(config.locale);\n\n const allAiPhaseNames = [\n ...CLASSIC_PIPELINE.phases.filter(p => p.kind === 'ai').map(p => p.name),\n ...PLAN_MODE_PIPELINE.phases.filter(p => p.kind === 'ai').map(p => p.name),\n ];\n validatePhaseRegistry([...new Set(allAiPhaseNames)]);\n\n // Initialize components\n const gongfeng = new GongfengClient(config.gongfeng);\n const git = new GitOperations(config.project.gitRootDir);\n const aiRunner = createAIRunner(config.ai);\n const dataDir = path.resolve(__dirname, '../data');\n const tracker = new IssueTracker(dataDir);\n\n const supplementStore = new SupplementStore(dataDir);\n\n const agentLogStore = new AgentLogStore(dataDir);\n agentLogStore.startListening();\n\n const orchestrator = new PipelineOrchestrator(config, gongfeng, git, aiRunner, tracker, supplementStore);\n const poller = new IssuePoller(config, gongfeng, tracker, orchestrator);\n\n let webServer: WebServer | null = null;\n if (config.web.enabled) {\n webServer = new WebServer({ tracker, config, agentLogStore, orchestrator, gongfeng, supplementStore, mainGit: git });\n await webServer.start();\n }\n\n let webhookServer: WebhookServer | null = null;\n if (config.webhook.enabled) {\n webhookServer = new WebhookServer({ tracker, config, orchestrator, gongfeng, supplementStore });\n await webhookServer.start();\n }\n\n const shutdown = (): void => {\n logger.info('Shutting down...');\n poller.stop();\n webServer?.stop();\n webhookServer?.stop();\n process.exit(0);\n };\n\n process.on('SIGINT', shutdown);\n process.on('SIGTERM', shutdown);\n\n // Start polling\n poller.start();\n\n logger.info('Issue Auto-Finish service started', {\n projectPath: config.gongfeng.projectPath,\n workDir: config.project.workDir,\n discoveryIntervalMs: config.poll.discoveryIntervalMs,\n driveIntervalMs: config.poll.driveIntervalMs,\n webUI: config.web.enabled ? `http://localhost:${config.web.port}` : 'disabled',\n webhook: config.webhook.enabled ? `http://localhost:${config.webhook.port}/webhook/gongfeng` : 'disabled',\n });\n}\n"],"mappings":"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","names":["logger","logger","path","fs","path","logger","path","fs","Router","logger","Router","path","logger","express","Router","path","fs","logger","fs","path","logger","Router","logger","logger","express","fs","path","logger","path","fs","path","fileURLToPath","__dirname"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/i18n/locales/zh-CN.ts","../src/i18n/locales/en.ts","../src/i18n/index.ts"],"sourcesContent":["export const zhCN: Record<string, string> = {\n // Phase labels\n 'phase.analysis': '分析',\n 'phase.design': '设计',\n 'phase.implement': '实现',\n 'phase.verify': '验证',\n 'phase.plan': '规划',\n 'phase.build': '实施',\n 'phase.review': '审核',\n\n // Pipeline phase labels (used in PipelineDefinition)\n 'pipeline.phase.analysis': '分析',\n 'pipeline.phase.design': '设计',\n 'pipeline.phase.implement': '实施',\n 'pipeline.phase.verify': '验证',\n 'pipeline.phase.plan': '规划',\n 'pipeline.phase.review': '审核',\n 'pipeline.phase.build': '实施',\n\n // Plan file labels\n 'planFile.01-analysis.md': '需求分析',\n 'planFile.02-design.md': '系统设计',\n 'planFile.03-todolist.md': '实施清单',\n 'planFile.04-verify-report.md': '验证报告',\n 'planFile.01-plan.md': '实施计划',\n 'planFile.02-verify-report.md': '验证报告',\n 'planFile.review-feedback.md': '审核反馈',\n 'planFile.review-history.json': '审核历史',\n\n // State labels (from collectStateLabels)\n 'state.pending': '待处理',\n 'state.branchCreated': '分支已创建',\n 'state.completed': '已完成',\n 'state.failed': '失败',\n 'state.phaseDoing': '{label}中',\n 'state.phaseDone': '{label}完成',\n 'state.phaseApproved': '{label}通过',\n\n // Orchestrator messages\n 'orchestrator.retryComment': '🔄 **自动处理重试中**\\n\\n检测到之前处理失败,正在重试...',\n 'orchestrator.startComment': '🚀 **自动处理开始**\\n\\n已检测到 `auto-finish` 标签,开始自动分析和实施。',\n 'orchestrator.fetchProgress': '正在拉取最新代码...',\n 'orchestrator.worktreeProgress': '正在准备工作目录...',\n 'orchestrator.installProgress': '正在安装项目依赖 (pnpm install)...',\n 'orchestrator.initPlanProgress': '正在初始化计划目录...',\n 'orchestrator.phaseStartProgress': '准备就绪,开始执行阶段 (从 {phase} 开始)...',\n 'orchestrator.autoApproveComment': '⚡ **审核自动通过**\\n\\n检测到标签匹配 `autoApproveLabels` 配置,已自动跳过审核进入实施阶段。',\n 'orchestrator.createMrProgress': '正在创建合并请求...',\n 'orchestrator.uploadScreenshotsProgress': '正在上传 E2E 截图...',\n 'orchestrator.mrSection': '\\n\\n🔗 合并请求: {mrUrl}',\n 'orchestrator.mrFailSection': '\\n\\n⚠️ 合并请求创建失败,请手动创建。',\n 'orchestrator.completedComment': '✅ **自动处理完成**\\n\\n所有阶段已完成。分支: `{branch}`{mrSection}{previewSection}',\n 'orchestrator.failedComment': '❌ **自动处理失败**\\n\\n{error}\\n\\n将在下次轮询时重试(如果未超过最大重试次数)。',\n 'orchestrator.deployProgress': '正在启动 Preview 环境...',\n 'orchestrator.deployDoneProgress': 'Preview 环境已就绪: {url}',\n 'orchestrator.previewComment.title': '🌐 **Preview Environment 已就绪**',\n 'orchestrator.previewComment.tableHeader': '| 组件 | 地址 |',\n 'orchestrator.previewComment.tableSep': '|------|------|',\n 'orchestrator.previewComment.frontend': '前端',\n 'orchestrator.previewComment.backendApi': '后端 API',\n 'orchestrator.previewComment.hint': '可直接访问前端链接体验本次变更。',\n 'orchestrator.previewComment.expiry': 'Preview 将在 MR 合并后自动清理,或 {hours}h 后过期。',\n\n // BasePhase messages\n 'basePhase.aiStarting': '正在启动 AI Agent ({label})...',\n 'basePhase.rulesSection': '## 项目开发规范参考\\n以下是与本次任务相关的开发规范,请在编码时严格遵循:\\n\\n{rules}',\n 'basePhase.error': '错误: {message}',\n\n // IssuePoller messages\n 'poller.autoApproveComment': '⚡ **审核自动通过**\\n\\n检测到标签匹配 `autoApproveLabels` 配置(匹配: {labels}),已自动跳过审核进入实施阶段。',\n\n // Progress comment\n 'progress.completed': '已完成',\n 'progress.failed': '失败',\n 'progress.inProgress': '进行中',\n 'progress.comment': '{icon} **自动处理进度更新**\\n\\n阶段: **{phase}** — {status}',\n\n // NoteSync messages\n 'notesync.phaseCompleted': '{icon} **{label}阶段完成**',\n 'notesync.viewDoc': '📄 [查看完整{label}文档]({url})',\n 'notesync.viewDashboard': '📊 [在管理面板中查看详情]({url})',\n\n // MergeRequest messages\n 'mr.relatedIssue': '## 关联 Issue',\n 'mr.title': '标题',\n 'mr.branch': '分支',\n 'mr.issueDescription': '## Issue 描述',\n 'mr.noDescription': '(无描述)',\n 'mr.summaryFiles.01-analysis.md': '需求分析',\n 'mr.summaryFiles.01-plan.md': '实施计划',\n 'mr.summaryFiles.02-design.md': '系统设计',\n 'mr.summaryFiles.04-verify-report.md': '验证报告',\n 'mr.summaryFiles.02-verify-report.md': '验证报告',\n 'mr.aiSummary': '## AI 产物摘要',\n 'mr.autoCreated': '*此 MR 由 Issue Auto-Finish 系统自动创建*',\n 'mr.truncated': '...(已截断)',\n\n // Screenshot messages\n 'screenshot.title': '📸 **E2E 测试截图**',\n 'screenshot.truncated': '> ⚠️ 截图数量过多,仅展示前 20 张。',\n\n // Webhook handler\n 'webhook.helpText': [\n '无法识别指令,支持以下命令:',\n '',\n '| 命令 | 说明 |',\n '| --- | --- |',\n '| `@issue-auto status` / `状态` | 查询当前处理状态 |',\n '| `@issue-auto retry` / `重试` | 从失败处重试 |',\n '| `@issue-auto retry-from <阶段>` | 从指定阶段重试 |',\n '| `@issue-auto restart` / `重新开始` | 完全重做 |',\n '| `@issue-auto approve` / `通过` | 批准当前方案 |',\n '| `@issue-auto reject <原因>` / `驳回:<原因>` | 驳回方案 |',\n '| `@issue-auto supplement <内容>` / `补充:<内容>` | 补充上下文 |',\n '| `@issue-auto clean-notes` / `清理评论` | 删除 Agent 历史评论 |',\n ].join('\\n'),\n\n // Command executor\n 'cmd.previewNotStarted': 'Issue #{iid} 尚未启动 Preview 环境。\\nPreview 会在代码实现完成后自动启动(需启用 E2E 或 Preview 配置)。',\n 'cmd.previewStopped': '⏹ 已停止',\n 'cmd.previewRunning': '✅ 运行中',\n 'cmd.previewTable.component': '组件',\n 'cmd.previewTable.address': '地址',\n 'cmd.previewTable.frontend': '前端',\n 'cmd.previewTable.backendApi': '后端 API',\n 'cmd.previewTable.status': '状态',\n 'cmd.previewTable.startedAt': '启动于',\n 'cmd.noPreview': 'Issue #{iid} 没有正在运行的 Preview 环境。',\n 'cmd.previewStoppedMsg': 'Issue #{iid} 的 Preview 环境已停止。',\n 'cmd.cleanNotesSuccess': '🧹 已清理 {count} 条 Agent 评论。',\n\n // Intent recognizer\n 'intent.systemPrompt': `你是一个指令解析助手。用户会在工蜂(GitLab) Issue 评论中用自然语言描述他们想让自动化系统做什么。\n你需要从用户的评论中提取出结构化的指令。\n\n可用的 intent:\n- retry: 重试失败的任务(从上次失败的地方继续)\n- retry-from: 从指定阶段重新开始(需要提取 phase)\n- supplement: 补充额外的需求信息或上下文\n- approve: 批准/通过当前的设计方案\n- reject: 驳回当前方案(需要提取 feedback)\n- status: 查询当前处理状态\n- restart: 从头开始,完全重做\n\n可用的 phase(仅 retry-from 时需要):\n- analysis: 需求分析阶段\n- design: 系统设计阶段\n- implement: 代码实施阶段\n- verify: 验证测试阶段\n- plan: 规划阶段\n- build: 构建阶段\n\n规则:\n1. 如果用户同时表达了\"重试\"和\"补充信息\",优先使用 retry-from 或 retry 作为 intent,把补充信息放在 context 字段\n2. 如果用户只是在补充说明、提供额外信息,使用 supplement\n3. feedback 字段仅用于 reject 意图\n4. 如果无法判断用户意图,返回 null\n\n严格按以下 JSON 格式返回,不要添加任何其他文字:\n{\"intent\":\"...\",\"phase\":\"...或null\",\"context\":\"...或null\",\"feedback\":\"...或null\"}`,\n\n // API routes\n 'api.invalidFilename': '无效的文件名',\n 'api.docNotGenerated': '文档尚未生成',\n 'api.viewInDashboard': '在管理面板中查看',\n 'api.reviewFeedback': '👀 **方案审核反馈(第 {round} 轮)**',\n 'api.viewPlan': '📄 [查看实施计划]({url})',\n 'api.viewDetail': '📊 [在管理面板中查看详情]({url})',\n\n // Doc labels for api routes\n 'docLabel.01-analysis.md': '需求分析',\n 'docLabel.02-design.md': '系统设计',\n 'docLabel.03-todolist.md': '实施清单',\n 'docLabel.04-verify-report.md': '验证报告',\n 'docLabel.01-plan.md': '实施计划',\n 'docLabel.02-verify-report.md': '验证报告',\n 'docLabel.review-feedback.md': '审核反馈',\n\n // CLI DependencyChecker\n 'cli.nodeInstallHint': '通过 nvm 安装: curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.1/install.sh | bash && nvm install 20',\n 'cli.cursorInstallHint': '安装 Cursor IDE 后,CLI 自动可用: https://www.cursor.com/',\n 'cli.unknownDep': '未知依赖: {name}',\n 'cli.alreadyInstalled': '{name} 已安装 ({version})',\n 'cli.manualInstall': '{name} 需要手动安装: {hint}',\n 'cli.installing': '正在安装 {name}...',\n 'cli.installSuccess': '{name} 安装成功',\n 'cli.installFailed': '{name} 安装失败 (exit code: {code})',\n\n // Prompt templates\n 'prompt.analysis': `你是需求分析师。请分析以下工蜂 Issue 并输出需求分析文档。\n\n## Issue 信息\n- IID: #{iid}\n- 标题: {title}\n- 描述:\n{description}{supplement}\n\n## 输出要求\n请将分析结果写入 {planDir}/01-analysis.md,内容包括:\n1. **需求概述** — 用简洁的语言总结需求目标\n2. **功能点拆解** — 列出需要实现的具体功能点\n3. **影响范围分析** — 哪些模块/文件可能受到影响\n4. **非功能需求** — 性能、安全、兼容性等方面的考量\n5. **风险和依赖** — 潜在风险和外部依赖\n\n请先阅读项目根目录的 CLAUDE.md 了解项目架构,再进行分析。\n只输出文档内容,不要输出其他说明。`,\n\n 'prompt.design': `你是系统设计师。基于需求分析文档进行系统设计。\n\n## Issue 信息\n- IID: #{iid}\n- 标题: {title}{supplement}\n\n请先阅读:\n- {planDir}/01-analysis.md (需求分析)\n- CLAUDE.md (项目架构)\n\n## 输出要求\n请将设计文档写入 {planDir}/02-design.md,内容包括:\n1. **方案概述** — 整体设计思路\n2. **涉及的文件和模块** — 需要新建/修改的文件列表\n3. **数据模型变更** — 数据库或模型层的变更\n4. **接口设计** — API 接口定义\n5. **详细实施步骤** — 按顺序列出实施步骤\n\n请将实施 Todolist 写入 {planDir}/03-todolist.md,格式:\n- [ ] 步骤1: 具体描述\n- [ ] 步骤2: 具体描述\n...\n\n请确保 Todolist 足够详细,每个步骤可独立执行和验证。`,\n\n 'prompt.implement': `你是开发工程师。请按照设计文档和 Todolist 实施代码变更。\n\n## Issue 信息\n- IID: #{iid}\n- 标题: {title}\n\n请先阅读:\n- {planDir}/01-analysis.md (需求分析)\n- {planDir}/02-design.md (系统设计)\n- {planDir}/03-todolist.md (实施步骤)\n- CLAUDE.md (项目架构和代码规范)\n\n## 实施要求\n1. 逐项完成 03-todolist.md 中的任务\n2. 每完成一项,更新 03-todolist.md 中对应的勾选状态 (- [ ] → - [x])\n3. 严格遵循 CLAUDE.md 中的代码规范(2空格缩进、120字符行宽、命名规范等)\n4. 不要过度工程化,只实现设计文档中要求的内容\n5. 确保代码安全,避免 OWASP Top 10 漏洞`,\n\n 'prompt.verify': `你是测试工程师。验证代码变更的正确性。\n\n## Issue 信息\n- IID: #{iid}\n- 标题: {title}\n\n## 前置检查\n在执行验证前,先确认依赖环境:\n1. 检查 node_modules/.bin/eslint 是否存在\n2. 如不存在,运行 pnpm install;如果失败,尝试 pnpm install --ignore-scripts\n3. 如果依赖始终无法安装完整,在报告中标注为\"环境问题\"并继续后续检查\n\n## 验证步骤\n1. 运行 pnpm run lint 检查代码风格\n2. 运行 pnpm run build 检查编译\n3. 运行 pnpm test4vscode --files <涉及变更的测试文件> 运行相关测试\n4. 检查代码变更与 {planDir}/02-design.md 设计文档的一致性\n5. 检查 {planDir}/03-todolist.md 是否所有项都已完成\n\n## 已知的预存问题(忽略即可)\n- build 阶段 tests/ 目录可能出现 TS2307: Cannot find module 'japa' 或 'sinon',这是测试框架类型声明的已知问题\n- 如果某个 lint/build/test 的失败**不涉及本次变更的文件**,标注为\"预存问题\"\n\n将验证结果写入 {planDir}/04-verify-report.md,包括:\n- **Lint 结果**: 通过/失败及详情(区分本次变更 vs 预存问题)\n- **Build 结果**: 通过/失败及详情(区分本次变更 vs 预存问题)\n- **Test 结果**: 通过/失败及详情\n- **设计一致性检查**: 是否符合设计\n- **总结**: 整体评估和建议`,\n\n 'prompt.planModeVerify': `你是测试工程师。验证代码变更的正确性。\n\n## Issue 信息\n- IID: #{iid}\n- 标题: {title}\n\n## 前置检查\n在执行验证前,先确认依赖环境:\n1. 检查 node_modules/.bin/eslint 是否存在\n2. 如不存在,运行 pnpm install;如果失败,尝试 pnpm install --ignore-scripts\n3. 如果依赖始终无法安装完整,在报告中标注为\"环境问题\"并继续后续检查\n\n## 验证步骤\n1. 运行 pnpm run lint 检查代码风格\n2. 运行 pnpm run build 检查编译\n3. 运行 pnpm test4vscode --files <涉及变更的测试文件> 运行相关测试\n4. 检查代码变更与 {planDir}/01-plan.md 实施计划的一致性\n5. 检查 {planDir}/01-plan.md 中 Todolist 是否所有项都已完成\n\n## 已知的预存问题(忽略即可)\n- build 阶段 tests/ 目录可能出现 TS2307: Cannot find module 'japa' 或 'sinon',这是测试框架类型声明的已知问题\n- 如果某个 lint/build/test 的失败**不涉及本次变更的文件**,标注为\"预存问题\"\n\n将验证结果写入 {planDir}/02-verify-report.md,包括:\n- **Lint 结果**: 通过/失败及详情(区分本次变更 vs 预存问题)\n- **Build 结果**: 通过/失败及详情(区分本次变更 vs 预存问题)\n- **Test 结果**: 通过/失败及详情\n- **计划一致性检查**: 是否符合实施计划\n- **总结**: 整体评估和建议`,\n\n 'prompt.plan': `你是资深技术负责人。请一次性完成需求分析和方案设计。\n\n## Issue 信息\n- IID: #{iid}\n- 标题: {title}\n- 描述:\n{description}{supplement}\n\n## 输出要求\n请先阅读项目根目录的 CLAUDE.md 了解项目架构,再进行分析和设计。\n\n请将完整的实施计划写入 {planDir}/01-plan.md,内容包括:\n\n### 第一部分:需求分析\n1. **需求概述** — 用简洁的语言总结需求目标\n2. **功能点拆解** — 列出需要实现的具体功能点\n3. **影响范围分析** — 哪些模块/文件可能受到影响\n4. **非功能需求** — 性能、安全、兼容性等方面的考量\n5. **风险和依赖** — 潜在风险和外部依赖\n\n### 第二部分:系统设计\n1. **方案概述** — 整体设计思路\n2. **涉及的文件和模块** — 需要新建/修改的文件列表\n3. **数据模型变更** — 数据库或模型层的变更\n4. **接口设计** — API 接口定义\n5. **详细实施步骤** — 按顺序列出实施步骤\n\n### 第三部分:实施 Todolist\n- [ ] 步骤1: 具体描述\n- [ ] 步骤2: 具体描述\n...\n\n请确保 Todolist 足够详细,每个步骤可独立执行和验证。\n只输出文档内容,不要输出其他说明。不要修改任何代码文件。`,\n\n 'prompt.build': `你是开发工程师。请按照实施计划完成代码变更。\n\n## Issue 信息\n- IID: #{iid}\n- 标题: {title}\n\n请先阅读:\n- {planDir}/01-plan.md (完整实施计划,包含需求分析、系统设计和 Todolist)\n- CLAUDE.md (项目架构和代码规范)\n\n## 实施要求\n1. 严格按照 01-plan.md 中的 Todolist 逐项完成\n2. 每完成一项,更新 01-plan.md 中对应的勾选状态 (- [ ] → - [x])\n3. 严格遵循 CLAUDE.md 中的代码规范(2空格缩进、120字符行宽、命名规范等)\n4. 不要过度工程化,只实现计划中要求的内容\n5. 确保代码安全,避免 OWASP Top 10 漏洞`,\n\n 'prompt.rePlan': `你是资深技术负责人。之前的实施计划未通过审核,请根据审核反馈修改计划。\n\n## Issue 信息\n- IID: #{iid}\n- 标题: {title}\n- 描述:\n{description}{supplement}\n\n## 审核反馈历史(共 {historyCount} 轮)\n{feedbackLines}\n\n请先阅读:\n- {planDir}/01-plan.md (当前实施计划)\n- {planDir}/review-feedback.md (审核反馈完整历史)\n- CLAUDE.md (项目架构)\n\n## 输出要求\n请综合所有轮次的审核反馈修改 {planDir}/01-plan.md,保持相同的文档结构。\n重点关注最新一轮的反馈,同时确保之前轮次提出的问题也已得到解决。\n只输出文档内容,不要输出其他说明。不要修改任何代码文件。`,\n\n 'prompt.rePlanRound': '### 第 {round} 轮 ({timestamp})\\n{feedback}',\n\n 'prompt.e2eSuffix.title': '## E2E UI 验证(已启用)',\n 'prompt.e2eSuffix.intro': '本次变更已开启 E2E UI 自动验收,请额外执行以下步骤:',\n 'prompt.e2eSuffix.previewNote': '**Preview 环境已启动(由系统管理,无需手动启动):**',\n 'prompt.e2eSuffix.backend': '后端',\n 'prompt.e2eSuffix.frontend': '前端',\n};\n","export const en: Record<string, string> = {\n // Phase labels\n 'phase.analysis': 'Analysis',\n 'phase.design': 'Design',\n 'phase.implement': 'Implementation',\n 'phase.verify': 'Verification',\n 'phase.plan': 'Planning',\n 'phase.build': 'Build',\n 'phase.review': 'Review',\n\n // Pipeline phase labels\n 'pipeline.phase.analysis': 'Analysis',\n 'pipeline.phase.design': 'Design',\n 'pipeline.phase.implement': 'Implementation',\n 'pipeline.phase.verify': 'Verification',\n 'pipeline.phase.plan': 'Planning',\n 'pipeline.phase.review': 'Review',\n 'pipeline.phase.build': 'Build',\n\n // Plan file labels\n 'planFile.01-analysis.md': 'Requirements Analysis',\n 'planFile.02-design.md': 'System Design',\n 'planFile.03-todolist.md': 'Implementation Checklist',\n 'planFile.04-verify-report.md': 'Verification Report',\n 'planFile.01-plan.md': 'Implementation Plan',\n 'planFile.02-verify-report.md': 'Verification Report',\n 'planFile.review-feedback.md': 'Review Feedback',\n 'planFile.review-history.json': 'Review History',\n\n // State labels\n 'state.pending': 'Pending',\n 'state.branchCreated': 'Branch Created',\n 'state.completed': 'Completed',\n 'state.failed': 'Failed',\n 'state.phaseDoing': '{label} In Progress',\n 'state.phaseDone': '{label} Done',\n 'state.phaseApproved': '{label} Approved',\n\n // Orchestrator messages\n 'orchestrator.retryComment': '🔄 **Auto-processing Retry**\\n\\nPrevious processing failed, retrying...',\n 'orchestrator.startComment': '🚀 **Auto-processing Started**\\n\\nDetected `auto-finish` label, starting automated analysis and implementation.',\n 'orchestrator.fetchProgress': 'Fetching latest code...',\n 'orchestrator.worktreeProgress': 'Preparing working directory...',\n 'orchestrator.installProgress': 'Installing project dependencies (pnpm install)...',\n 'orchestrator.initPlanProgress': 'Initializing plan directory...',\n 'orchestrator.phaseStartProgress': 'Ready, starting phases (from {phase})...',\n 'orchestrator.autoApproveComment': '⚡ **Review Auto-approved**\\n\\nDetected label matching `autoApproveLabels` configuration, automatically skipping review and proceeding to implementation.',\n 'orchestrator.createMrProgress': 'Creating merge request...',\n 'orchestrator.uploadScreenshotsProgress': 'Uploading E2E screenshots...',\n 'orchestrator.mrSection': '\\n\\n🔗 Merge Request: {mrUrl}',\n 'orchestrator.mrFailSection': '\\n\\n⚠️ Failed to create merge request, please create manually.',\n 'orchestrator.completedComment': '✅ **Auto-processing Completed**\\n\\nAll phases completed. Branch: `{branch}`{mrSection}{previewSection}',\n 'orchestrator.failedComment': '❌ **Auto-processing Failed**\\n\\n{error}\\n\\nWill retry on next poll cycle (if max retries not exceeded).',\n 'orchestrator.deployProgress': 'Starting Preview environment...',\n 'orchestrator.deployDoneProgress': 'Preview environment ready: {url}',\n 'orchestrator.previewComment.title': '🌐 **Preview Environment Ready**',\n 'orchestrator.previewComment.tableHeader': '| Component | Address |',\n 'orchestrator.previewComment.tableSep': '|-----------|---------|',\n 'orchestrator.previewComment.frontend': 'Frontend',\n 'orchestrator.previewComment.backendApi': 'Backend API',\n 'orchestrator.previewComment.hint': 'Visit the frontend link to experience the changes.',\n 'orchestrator.previewComment.expiry': 'Preview will be cleaned up after MR merge, or expires in {hours}h.',\n\n // BasePhase messages\n 'basePhase.aiStarting': 'Starting AI Agent ({label})...',\n 'basePhase.rulesSection': '## Project Development Guidelines\\nThe following are development guidelines related to this task. Please strictly follow them when coding:\\n\\n{rules}',\n 'basePhase.error': 'Error: {message}',\n\n // IssuePoller messages\n 'poller.autoApproveComment': '⚡ **Review Auto-approved**\\n\\nDetected label matching `autoApproveLabels` configuration (matched: {labels}), automatically skipping review and proceeding to implementation.',\n\n // Progress comment\n 'progress.completed': 'Completed',\n 'progress.failed': 'Failed',\n 'progress.inProgress': 'In Progress',\n 'progress.comment': '{icon} **Auto-processing Progress Update**\\n\\nPhase: **{phase}** — {status}',\n\n // NoteSync messages\n 'notesync.phaseCompleted': '{icon} **{label} Phase Completed**',\n 'notesync.viewDoc': '📄 [View full {label} document]({url})',\n 'notesync.viewDashboard': '📊 [View details in dashboard]({url})',\n\n // MergeRequest messages\n 'mr.relatedIssue': '## Related Issue',\n 'mr.title': 'Title',\n 'mr.branch': 'Branch',\n 'mr.issueDescription': '## Issue Description',\n 'mr.noDescription': '(No description)',\n 'mr.summaryFiles.01-analysis.md': 'Requirements Analysis',\n 'mr.summaryFiles.01-plan.md': 'Implementation Plan',\n 'mr.summaryFiles.02-design.md': 'System Design',\n 'mr.summaryFiles.04-verify-report.md': 'Verification Report',\n 'mr.summaryFiles.02-verify-report.md': 'Verification Report',\n 'mr.aiSummary': '## AI Artifacts Summary',\n 'mr.autoCreated': '*This MR was automatically created by Issue Auto-Finish system*',\n 'mr.truncated': '...(truncated)',\n\n // Screenshot messages\n 'screenshot.title': '📸 **E2E Test Screenshots**',\n 'screenshot.truncated': '> ⚠️ Too many screenshots, showing only the first 20.',\n\n // Webhook handler\n 'webhook.helpText': [\n 'Unrecognized command. Available commands:',\n '',\n '| Command | Description |',\n '| --- | --- |',\n '| `@issue-auto status` | Check current processing status |',\n '| `@issue-auto retry` | Retry from failure point |',\n '| `@issue-auto retry-from <phase>` | Retry from specific phase |',\n '| `@issue-auto restart` | Start over from scratch |',\n '| `@issue-auto approve` | Approve current plan |',\n '| `@issue-auto reject <reason>` | Reject plan with feedback |',\n '| `@issue-auto supplement <content>` | Add supplementary context |',\n '| `@issue-auto clean-notes` | Delete agent history notes |',\n ].join('\\n'),\n\n // Command executor\n 'cmd.previewNotStarted': 'Issue #{iid} does not have a Preview environment yet.\\nPreview starts automatically after code implementation is complete (requires E2E or Preview to be enabled).',\n 'cmd.previewStopped': '⏹ Stopped',\n 'cmd.previewRunning': '✅ Running',\n 'cmd.previewTable.component': 'Component',\n 'cmd.previewTable.address': 'Address',\n 'cmd.previewTable.frontend': 'Frontend',\n 'cmd.previewTable.backendApi': 'Backend API',\n 'cmd.previewTable.status': 'Status',\n 'cmd.previewTable.startedAt': 'Started at',\n 'cmd.noPreview': 'Issue #{iid} does not have a running Preview environment.',\n 'cmd.previewStoppedMsg': 'Preview environment for Issue #{iid} has been stopped.',\n 'cmd.cleanNotesSuccess': '🧹 Cleaned up {count} agent note(s).',\n\n // Intent recognizer\n 'intent.systemPrompt': `You are a command parsing assistant. Users will describe in natural language what they want the automation system to do in Gongfeng (GitLab) Issue comments.\nYou need to extract structured commands from user comments.\n\nAvailable intents:\n- retry: Retry failed task (continue from last failure point)\n- retry-from: Restart from a specific phase (need to extract phase)\n- supplement: Add additional requirement info or context\n- approve: Approve/pass the current design plan\n- reject: Reject current plan (need to extract feedback)\n- status: Query current processing status\n- restart: Start from scratch, redo everything\n\nAvailable phases (only needed for retry-from):\n- analysis: Requirements analysis phase\n- design: System design phase\n- implement: Code implementation phase\n- verify: Verification testing phase\n- plan: Planning phase\n- build: Build phase\n\nRules:\n1. If user expresses both \"retry\" and \"supplement info\", prioritize retry-from or retry as intent, put supplement info in context field\n2. If user is only supplementing/providing additional info, use supplement\n3. feedback field is only for reject intent\n4. If unable to determine user intent, return null\n\nStrictly return in the following JSON format, do not add any other text:\n{\"intent\":\"...\",\"phase\":\"...or null\",\"context\":\"...or null\",\"feedback\":\"...or null\"}`,\n\n // API routes\n 'api.invalidFilename': 'Invalid filename',\n 'api.docNotGenerated': 'Document not yet generated',\n 'api.viewInDashboard': 'View in dashboard',\n 'api.reviewFeedback': '👀 **Plan Review Feedback (Round {round})**',\n 'api.viewPlan': '📄 [View implementation plan]({url})',\n 'api.viewDetail': '📊 [View details in dashboard]({url})',\n\n // Doc labels for api routes\n 'docLabel.01-analysis.md': 'Requirements Analysis',\n 'docLabel.02-design.md': 'System Design',\n 'docLabel.03-todolist.md': 'Implementation Checklist',\n 'docLabel.04-verify-report.md': 'Verification Report',\n 'docLabel.01-plan.md': 'Implementation Plan',\n 'docLabel.02-verify-report.md': 'Verification Report',\n 'docLabel.review-feedback.md': 'Review Feedback',\n\n // CLI DependencyChecker\n 'cli.nodeInstallHint': 'Install via nvm: curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.1/install.sh | bash && nvm install 20',\n 'cli.cursorInstallHint': 'Install Cursor IDE, CLI will be available automatically: https://www.cursor.com/',\n 'cli.unknownDep': 'Unknown dependency: {name}',\n 'cli.alreadyInstalled': '{name} already installed ({version})',\n 'cli.manualInstall': '{name} requires manual installation: {hint}',\n 'cli.installing': 'Installing {name}...',\n 'cli.installSuccess': '{name} installed successfully',\n 'cli.installFailed': '{name} installation failed (exit code: {code})',\n\n // Prompt templates\n 'prompt.analysis': `You are a requirements analyst. Please analyze the following Gongfeng Issue and output a requirements analysis document.\n\n## Issue Information\n- IID: #{iid}\n- Title: {title}\n- Description:\n{description}{supplement}\n\n## Output Requirements\nPlease write the analysis results to {planDir}/01-analysis.md, including:\n1. **Requirements Overview** — Summarize the requirements goal concisely\n2. **Feature Breakdown** — List specific features to implement\n3. **Impact Analysis** — Which modules/files may be affected\n4. **Non-functional Requirements** — Performance, security, compatibility considerations\n5. **Risks and Dependencies** — Potential risks and external dependencies\n\nPlease read the project's CLAUDE.md first to understand the architecture, then proceed with analysis.\nOnly output document content, no other explanations.`,\n\n 'prompt.design': `You are a system designer. Design the system based on the requirements analysis document.\n\n## Issue Information\n- IID: #{iid}\n- Title: {title}{supplement}\n\nPlease read first:\n- {planDir}/01-analysis.md (Requirements Analysis)\n- CLAUDE.md (Project Architecture)\n\n## Output Requirements\nPlease write the design document to {planDir}/02-design.md, including:\n1. **Solution Overview** — Overall design approach\n2. **Files and Modules Involved** — List of files to create/modify\n3. **Data Model Changes** — Database or model layer changes\n4. **API Design** — API interface definitions\n5. **Detailed Implementation Steps** — Step-by-step implementation plan\n\nPlease write the implementation Todolist to {planDir}/03-todolist.md, format:\n- [ ] Step 1: Specific description\n- [ ] Step 2: Specific description\n...\n\nEnsure the Todolist is detailed enough that each step can be independently executed and verified.`,\n\n 'prompt.implement': `You are a software engineer. Please implement code changes according to the design document and Todolist.\n\n## Issue Information\n- IID: #{iid}\n- Title: {title}\n\nPlease read first:\n- {planDir}/01-analysis.md (Requirements Analysis)\n- {planDir}/02-design.md (System Design)\n- {planDir}/03-todolist.md (Implementation Steps)\n- CLAUDE.md (Project Architecture and Code Standards)\n\n## Implementation Requirements\n1. Complete tasks in 03-todolist.md one by one\n2. After completing each item, update its checkbox status in 03-todolist.md (- [ ] → - [x])\n3. Strictly follow code standards in CLAUDE.md (2-space indent, 120-char line width, naming conventions, etc.)\n4. Don't over-engineer, only implement what's required in the design document\n5. Ensure code security, avoid OWASP Top 10 vulnerabilities`,\n\n 'prompt.verify': `You are a test engineer. Verify the correctness of code changes.\n\n## Issue Information\n- IID: #{iid}\n- Title: {title}\n\n## Pre-checks\nBefore running verification, confirm the dependency environment:\n1. Check if node_modules/.bin/eslint exists\n2. If not, run pnpm install; if that fails, try pnpm install --ignore-scripts\n3. If dependencies cannot be fully installed, mark as \"environment issue\" in the report and continue\n\n## Verification Steps\n1. Run pnpm run lint to check code style\n2. Run pnpm run build to check compilation\n3. Run pnpm test4vscode --files <test files related to changes> to run relevant tests\n4. Check code changes against {planDir}/02-design.md design document consistency\n5. Check if all items in {planDir}/03-todolist.md are completed\n\n## Known Pre-existing Issues (can be ignored)\n- During build, tests/ directory may show TS2307: Cannot find module 'japa' or 'sinon', these are known test framework type declaration issues\n- If a lint/build/test failure **does not involve files changed in this PR**, mark as \"pre-existing issue\"\n\nWrite verification results to {planDir}/04-verify-report.md, including:\n- **Lint Results**: Pass/fail with details (distinguish current changes vs pre-existing issues)\n- **Build Results**: Pass/fail with details (distinguish current changes vs pre-existing issues)\n- **Test Results**: Pass/fail with details\n- **Design Consistency Check**: Whether it matches the design\n- **Summary**: Overall assessment and recommendations`,\n\n 'prompt.planModeVerify': `You are a test engineer. Verify the correctness of code changes.\n\n## Issue Information\n- IID: #{iid}\n- Title: {title}\n\n## Pre-checks\nBefore running verification, confirm the dependency environment:\n1. Check if node_modules/.bin/eslint exists\n2. If not, run pnpm install; if that fails, try pnpm install --ignore-scripts\n3. If dependencies cannot be fully installed, mark as \"environment issue\" in the report and continue\n\n## Verification Steps\n1. Run pnpm run lint to check code style\n2. Run pnpm run build to check compilation\n3. Run pnpm test4vscode --files <test files related to changes> to run relevant tests\n4. Check code changes against {planDir}/01-plan.md implementation plan consistency\n5. Check if all items in {planDir}/01-plan.md Todolist are completed\n\n## Known Pre-existing Issues (can be ignored)\n- During build, tests/ directory may show TS2307: Cannot find module 'japa' or 'sinon', these are known test framework type declaration issues\n- If a lint/build/test failure **does not involve files changed in this PR**, mark as \"pre-existing issue\"\n\nWrite verification results to {planDir}/02-verify-report.md, including:\n- **Lint Results**: Pass/fail with details (distinguish current changes vs pre-existing issues)\n- **Build Results**: Pass/fail with details (distinguish current changes vs pre-existing issues)\n- **Test Results**: Pass/fail with details\n- **Plan Consistency Check**: Whether it matches the implementation plan\n- **Summary**: Overall assessment and recommendations`,\n\n 'prompt.plan': `You are a senior technical lead. Please complete requirements analysis and solution design in one go.\n\n## Issue Information\n- IID: #{iid}\n- Title: {title}\n- Description:\n{description}{supplement}\n\n## Output Requirements\nPlease read the project's CLAUDE.md first to understand the architecture, then proceed with analysis and design.\n\nPlease write the complete implementation plan to {planDir}/01-plan.md, including:\n\n### Part 1: Requirements Analysis\n1. **Requirements Overview** — Summarize the requirements goal concisely\n2. **Feature Breakdown** — List specific features to implement\n3. **Impact Analysis** — Which modules/files may be affected\n4. **Non-functional Requirements** — Performance, security, compatibility considerations\n5. **Risks and Dependencies** — Potential risks and external dependencies\n\n### Part 2: System Design\n1. **Solution Overview** — Overall design approach\n2. **Files and Modules Involved** — List of files to create/modify\n3. **Data Model Changes** — Database or model layer changes\n4. **API Design** — API interface definitions\n5. **Detailed Implementation Steps** — Step-by-step implementation plan\n\n### Part 3: Implementation Todolist\n- [ ] Step 1: Specific description\n- [ ] Step 2: Specific description\n...\n\nEnsure the Todolist is detailed enough that each step can be independently executed and verified.\nOnly output document content, no other explanations. Do not modify any code files.`,\n\n 'prompt.build': `You are a software engineer. Please complete code changes according to the implementation plan.\n\n## Issue Information\n- IID: #{iid}\n- Title: {title}\n\nPlease read first:\n- {planDir}/01-plan.md (Complete implementation plan including requirements analysis, system design and Todolist)\n- CLAUDE.md (Project Architecture and Code Standards)\n\n## Implementation Requirements\n1. Strictly follow the Todolist in 01-plan.md, completing items one by one\n2. After completing each item, update its checkbox status in 01-plan.md (- [ ] → - [x])\n3. Strictly follow code standards in CLAUDE.md (2-space indent, 120-char line width, naming conventions, etc.)\n4. Don't over-engineer, only implement what's required in the plan\n5. Ensure code security, avoid OWASP Top 10 vulnerabilities`,\n\n 'prompt.rePlan': `You are a senior technical lead. The previous implementation plan was not approved. Please modify the plan based on review feedback.\n\n## Issue Information\n- IID: #{iid}\n- Title: {title}\n- Description:\n{description}{supplement}\n\n## Review Feedback History ({historyCount} rounds)\n{feedbackLines}\n\nPlease read first:\n- {planDir}/01-plan.md (Current implementation plan)\n- {planDir}/review-feedback.md (Complete review feedback history)\n- CLAUDE.md (Project Architecture)\n\n## Output Requirements\nPlease modify {planDir}/01-plan.md incorporating all rounds of review feedback, maintaining the same document structure.\nFocus on the latest round of feedback while ensuring issues raised in previous rounds are also resolved.\nOnly output document content, no other explanations. Do not modify any code files.`,\n\n 'prompt.rePlanRound': '### Round {round} ({timestamp})\\n{feedback}',\n\n 'prompt.e2eSuffix.title': '## E2E UI Verification (Enabled)',\n 'prompt.e2eSuffix.intro': 'E2E UI auto-verification is enabled for this change. Please perform the following additional steps:',\n 'prompt.e2eSuffix.previewNote': '**Preview environment is running (managed by the system, no manual startup needed):**',\n 'prompt.e2eSuffix.backend': 'Backend',\n 'prompt.e2eSuffix.frontend': 'Frontend',\n};\n","export type Locale = 'zh-CN' | 'en';\n\ntype MessageMap = Record<string, string>;\n\nconst locales = new Map<Locale, MessageMap>();\nlet currentLocale: Locale = 'zh-CN';\n\nexport function setLocale(locale: Locale): void {\n currentLocale = locale;\n}\n\nexport function getLocale(): Locale {\n return currentLocale;\n}\n\nexport function registerLocale(locale: Locale, messages: MessageMap): void {\n locales.set(locale, messages);\n}\n\nexport function t(key: string, params?: Record<string, string | number>): string {\n const messages = locales.get(currentLocale) ?? locales.get('zh-CN');\n if (!messages) return key;\n let text = messages[key];\n if (text === undefined) {\n const fallback = locales.get('zh-CN');\n text = fallback?.[key] ?? key;\n }\n if (params) {\n for (const [k, v] of Object.entries(params)) {\n text = text.replaceAll(`{${k}}`, String(v));\n }\n }\n return text;\n}\n\nimport { zhCN } from './locales/zh-CN.js';\nimport { en } from './locales/en.js';\n\nregisterLocale('zh-CN', zhCN);\nregisterLocale('en', en);\n"],"mappings":"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","names":[]}
|