@coralai/sps-cli 0.58.23 → 0.58.25
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/commands/cardAdd.d.ts.map +1 -1
- package/dist/commands/cardAdd.js +11 -2
- package/dist/commands/cardAdd.js.map +1 -1
- package/dist/commands/cardInsert.d.ts +2 -0
- package/dist/commands/cardInsert.d.ts.map +1 -0
- package/dist/commands/cardInsert.js +70 -0
- package/dist/commands/cardInsert.js.map +1 -0
- package/dist/commands/projectInit.d.ts +5 -0
- package/dist/commands/projectInit.d.ts.map +1 -1
- package/dist/commands/projectInit.js +17 -0
- package/dist/commands/projectInit.js.map +1 -1
- package/dist/commands/tick.d.ts +2 -0
- package/dist/commands/tick.d.ts.map +1 -1
- package/dist/commands/tick.js +45 -0
- package/dist/commands/tick.js.map +1 -1
- package/dist/console/routes/chat.d.ts.map +1 -1
- package/dist/console/routes/chat.js +8 -3
- package/dist/console/routes/chat.js.map +1 -1
- package/dist/console/routes/projects.d.ts.map +1 -1
- package/dist/console/routes/projects.js +1 -0
- package/dist/console/routes/projects.js.map +1 -1
- package/dist/console-assets/assets/{index-B_CpD8k2.js → index-CokfLuTe.js} +3 -3
- package/dist/console-assets/index.html +1 -1
- package/dist/core/config.d.ts +2 -0
- package/dist/core/config.d.ts.map +1 -1
- package/dist/core/config.js +1 -0
- package/dist/core/config.js.map +1 -1
- package/dist/core/memory2/external/importTranscript.d.ts +7 -0
- package/dist/core/memory2/external/importTranscript.d.ts.map +1 -0
- package/dist/core/memory2/external/importTranscript.js +44 -0
- package/dist/core/memory2/external/importTranscript.js.map +1 -0
- package/dist/core/skills/SkillsManager.d.ts +2 -0
- package/dist/core/skills/SkillsManager.d.ts.map +1 -1
- package/dist/core/skills/SkillsManager.js +7 -0
- package/dist/core/skills/SkillsManager.js.map +1 -1
- package/dist/core/skills/index.d.ts +1 -1
- package/dist/core/skills/index.d.ts.map +1 -1
- package/dist/core/skills/index.js +1 -1
- package/dist/core/skills/index.js.map +1 -1
- package/dist/core/skills/types.d.ts +5 -0
- package/dist/core/skills/types.d.ts.map +1 -1
- package/dist/engines/ReviewEngine.d.ts +68 -0
- package/dist/engines/ReviewEngine.d.ts.map +1 -0
- package/dist/engines/ReviewEngine.js +125 -0
- package/dist/engines/ReviewEngine.js.map +1 -0
- package/dist/engines/StageEngine.d.ts +5 -1
- package/dist/engines/StageEngine.d.ts.map +1 -1
- package/dist/engines/StageEngine.js +14 -2
- package/dist/engines/StageEngine.js.map +1 -1
- package/dist/main.js +12 -2
- package/dist/main.js.map +1 -1
- package/dist/manager/worker-manager-impl.d.ts.map +1 -1
- package/dist/manager/worker-manager-impl.js +4 -0
- package/dist/manager/worker-manager-impl.js.map +1 -1
- package/dist/providers/LLMClient.d.ts +23 -0
- package/dist/providers/LLMClient.d.ts.map +1 -1
- package/dist/providers/LLMClient.js +53 -4
- package/dist/providers/LLMClient.js.map +1 -1
- package/dist/providers/llm/chatTools.d.ts +1 -0
- package/dist/providers/llm/chatTools.d.ts.map +1 -1
- package/dist/providers/llm/chatTools.js +6 -4
- package/dist/providers/llm/chatTools.js.map +1 -1
- package/dist/providers/llm/monitorSkills.d.ts +9 -3
- package/dist/providers/llm/monitorSkills.d.ts.map +1 -1
- package/dist/providers/llm/monitorSkills.js +42 -23
- package/dist/providers/llm/monitorSkills.js.map +1 -1
- package/dist/providers/llm/probeTools.d.ts +5 -1
- package/dist/providers/llm/probeTools.d.ts.map +1 -1
- package/dist/providers/llm/probeTools.js +9 -5
- package/dist/providers/llm/probeTools.js.map +1 -1
- package/dist/providers/llm/skillTools.d.ts.map +1 -1
- package/dist/providers/llm/skillTools.js +5 -3
- package/dist/providers/llm/skillTools.js.map +1 -1
- package/dist/providers/mcp/spsMcpServer.d.ts.map +1 -1
- package/dist/providers/mcp/spsMcpServer.js +5 -3
- package/dist/providers/mcp/spsMcpServer.js.map +1 -1
- package/dist/services/CardService.d.ts +6 -0
- package/dist/services/CardService.d.ts.map +1 -1
- package/dist/services/CardService.js +28 -1
- package/dist/services/CardService.js.map +1 -1
- package/dist/services/ProjectService.d.ts +2 -0
- package/dist/services/ProjectService.d.ts.map +1 -1
- package/dist/services/ProjectService.js.map +1 -1
- package/package.json +4 -2
- package/skills/checklist-review/SKILL.md +44 -0
- package/{monitor-skills → skills}/probe-playbook/SKILL.md +3 -2
- package/skills/sps-pipeline/SKILL.md +48 -1
- package/{monitor-skills → skills}/visual-rubric/SKILL.md +3 -2
|
@@ -447,13 +447,13 @@ Please change the parent <Route path="${E}"> to <Route path="${E==="/"?"*":`${E}
|
|
|
447
447
|
*
|
|
448
448
|
* This source code is licensed under the ISC license.
|
|
449
449
|
* See the LICENSE file in the root directory of this source tree.
|
|
450
|
-
*/const x3=[["path",{d:"M4 14a1 1 0 0 1-.78-1.63l9.9-10.2a.5.5 0 0 1 .86.46l-1.92 6.02A1 1 0 0 0 13 10h7a1 1 0 0 1 .78 1.63l-9.9 10.2a.5.5 0 0 1-.86-.46l1.92-6.02A1 1 0 0 0 11 14z",key:"1xq2db"}]],v3=Re("zap",x3),w3={"app.title":"SPS Console","nav.chat":"Chat","nav.projects":"Projects","nav.board":"Board","nav.workers":"Workers","nav.logs":"Logs","nav.skills":"Skills","nav.system":"System","nav.processes":"Processes","nav.audit":"Audit Log","nav.memory":"Memory","nav.plugins":"Plugins","plugins.h1":"Plugins 🧩","plugins.desc":"Global plugin toggles. Applies to newly dispatched cards.","plugins.tab.memory":"Memory","plugins.tab.channel":"Channel","plugins.tab.model":"Model","plugins.tab.tool":"Tool","plugins.comingSoon":"Coming soon","plugins.model.title":"Agent models","plugins.model.desc":"Configure both agents (global). worker=claude executes, review·designer=openai supervises+orchestrates.","plugins.model.worker":"Worker (executes / claude)","plugins.model.reviewer":"Review·Designer (supervisor / openai)","plugins.model.provider":"Provider","plugins.model.model":"Model","plugins.model.official":"Official claude (default)","plugins.model.save":"Save","plugins.model.saved":"Saved","plugins.model.error":"Save failed","nav.arrange":"Arrange","arrange.h1":"SmartArrange 🧭","arrange.project":"Project","arrange.none":'Not started — click "Start" above to launch (task list appears in seconds; approve to run). If the dropdown is empty, create a project in SmartArrange mode first.',"arrange.start":"Start","arrange.stop":"Stop","arrange.startErr":"Start/stop failed","arrange.view":"Toggle canvas view","arrange.viewFree":"Free","arrange.viewLane":"Lanes","arrange.starting":"Starting — breaking down the task list…","arrange.planning":"Breaking down the task list…","arrange.orchestrating":"Orchestrating…","arrange.status":"Status","arrange.goal":"Goal","arrange.plan":"Task list + card chain","arrange.approve":"Approve plan","arrange.approveErr":"Approve failed","arrange.tasks":"Task list","arrange.collapse":"Collapse","arrange.expand":"Expand task list","arrange.noCards":"No cards yet — waiting for the orchestrator to dispatch (starts after approval).","arrange.cardPrompt":"Card prompt","arrange.cardSkills":"Skills","arrange.cardTask":"Task","arrange.cardLog":"Log","arrange.close":"Close","arrange.cardsCount":"cards","nav.aria":"Main navigation","memory.sub":"Cross-project memory · agentmemory proxied behind console auth","memory.searchPlaceholder":"Search memory… (e.g. how to fix the art race)","memory.search":"Search","memory.results":"Results","memory.rawHint":"(raw observation · distilled lessons appear after live capture + compression)","memory.sessions":"Recent sessions","memory.empty":"No memory yet · accumulates after live capture (P1)","processes.title":"Processes","processes.subtitle":"Claude processes launched by SPS ACP (others, e.g. your own session, are not shown)","processes.refresh":"Refresh","processes.aliveCount":"{n} running","processes.col.kind":"Type","processes.col.slot":"Slot","processes.col.project":"Project","processes.col.state":"State","processes.col.memory":"Memory","processes.col.action":"Action","processes.empty":"No SPS processes","processes.filter.all":"All","processes.filter.alive":"Running","processes.filter.offline":"Offline","processes.kind.all":"All types","processes.kind.worker":"Worker","processes.kind.chat":"Chat","processes.kill":"Kill","processes.killConfirm":"Kill process {slot}?","audit.title":"Audit Log","audit.subtitle":"Project lifecycle: create / modify / delete","audit.refresh":"Refresh","audit.filter.all":"All","audit.action.create":"Create","audit.action.modify":"Modify","audit.action.delete":"Delete","audit.action.daemon":"Daemon","audit.col.time":"Time","audit.col.action":"Action","audit.col.project":"Project","audit.col.detail":"Detail","audit.empty":"No audit records","lang.toggle.aria":"Switch interface language","lang.en":"EN","lang.zh":"中","status.server":"server","status.offline":"offline","status.sse.open":"SSE","status.sse.connecting":"SSE·connect","status.sse.down":"SSE·down","status.pipelines.tooltip":"Active pipelines","status.workers.tooltip":"Active workers","status.pipeline.unit":"pipeline","status.worker.unit":"worker","common.save":"Save","common.cancel":"Cancel","common.delete":"Delete","common.confirm":"Confirm","common.create":"Create","common.edit":"Edit","common.close":"Close","common.loading":"Loading…","common.error":"Error","common.retry":"Retry","common.empty":"Nothing here yet","common.search":"Search","common.refresh":"Refresh","common.copy":"Copy","common.copied":"Copied","common.yes":"Yes","common.no":"No","common.required":"Required","common.optional":"Optional","common.ok":"OK","projects.title":"Projects 🎯","projects.count":"{count} local project(s)","projects.refresh.hint":"Click refresh to retry","projects.new":"New project","projects.selectHint":"Select a project on the left to see its details.","projects.sort.label":"Sort by","projects.sort.activity":"Activity","projects.sort.date":"Modified","projects.sort.name":"Name","projects.load.failed":"Failed to load","projects.empty.title":"No projects yet ✨","projects.empty.hint":"Run {cmd} to create your first project.","newProject.title":"New project","newProject.subtitle":"Set up a project; the worker will run automatically","newProject.field.mode":"Execution mode","newProject.field.mode.pipeline":"Auto pipeline","newProject.field.mode.pipelineDesc":"Fixed-stage pipeline, claude worker runs cards","newProject.field.mode.smart":"SmartArrange","newProject.field.mode.smartDesc":"OpenAI monitor dispatches cards + claude worker","newProject.field.mode.pipelineHint":"Classic mode: you create cards, worker runs them by stage.","newProject.field.mode.smartHint":"Give one goal; the OpenAI monitor probes output each round, dispatches task cards dynamically, drives claude to finish.","newProject.field.goal":"Goal (GOAL.md)","newProject.field.goal.hint":"Written to docs/GOAL.md; SmartArrange derives the task list from it. Missing → tick skips the project.","newProject.field.goal.placeholder":"e.g. Build a pure-frontend, single-file Snake browser game…","newProject.field.name":"Project name","newProject.field.name.help":"Lowercase letters, digits, _ and - only","newProject.field.dir":"Project directory","newProject.field.dir.preview":"Project will be created at →","newProject.field.dir.help":"Absolute path; will be created if missing","newProject.field.branch":"Merge target branch","newProject.field.branch.help":"Default: main","newProject.field.maxWorkers":"Max concurrent workers","newProject.field.maxWorkers.help":"Per-project worker count (1 recommended)","newProject.field.ackTimeout":"ACK timeout (seconds)","newProject.field.ackTimeout.help":"How long to wait for the worker to ACK (default 300)","newProject.field.gitlabProject":"GitLab/GitHub remote","newProject.field.gitlabProject.help":"Format: user/repo (optional)","newProject.field.matrixRoom":"Matrix room ID","newProject.field.matrixRoom.help":"Optional, falls back to global default","newProject.field.git":"Enable git","newProject.field.git.help":"Off → non-code project, no commit/push/MR steps","newProject.submit":"Create project","newProject.creating":"Creating…","newProject.created":"Project created","newProject.error.dirRequired":"Project directory is required","newProject.dir.browse":"Browse","newProject.dir.browseAria":"Pick directory","newProject.back":"Back","newProject.back.aria":"Back to projects","newProject.field.name.placeholder":"e.g. acme-web","newProject.field.name.example":"Letters, digits, underscore, hyphen. e.g. acme-web","newProject.field.name.invalid":"Name only allows a-z A-Z 0-9 _ -","newProject.field.dir.long":"Absolute path of the PROJECT directory. The selected directory is the project root; project name defaults to the directory name. Has code → adopt (only adds .claude/ config, never touches source); empty → create new.","newProject.field.dir.placeholder":"/home/you/projects/my-app","newProject.field.dir.createIfMissing":"Auto-create if missing (recommended — otherwise .claude/ install gets skipped)","newProject.field.dir.pickerTitle":"Pick project directory","newProject.field.dir.adopt":"Existing content detected → will adopt (config only, source untouched)","newProject.field.dir.fresh":"Empty directory → create new project","newProject.field.name.derived":"Project name (defaults to directory name, editable)","newProject.field.maxWorkers.short":"Max workers","newProject.field.ackTimeout.minutes":"ACK timeout (min)","newProject.field.ackTimeout.minutes.help":"How long after dispatch before the worker is considered failed if no ACK","newProject.field.git.label":"Enable Git (worker auto commit + push)","newProject.field.git.detail":"When off, the worker only does the task, no version control — fits docs / data-processing non-code projects.","newProject.field.git.branch":"Merge branch","newProject.field.gitlabProject.label":"Git remote project path","newProject.field.gitlabProject.help2":"Like user/repo. Empty = skip remote API (commit/push local only)","newProject.field.gitlabProject.placeholder":"user/repo","newProject.field.gitlabProjectId":"GitLab project ID","newProject.field.gitlabProjectId.help":"Number; leave blank for GitHub","newProject.field.gitlabProjectId.placeholder":"42","newProject.section.notifications":"Notifications","newProject.field.matrixRoom.label":"Matrix room ID","newProject.field.matrixRoom.help2":"Empty = use global config; blank = no notifications","newProject.field.matrixRoom.placeholder":"!abc:matrix.example.com","newProject.error.create.title":"Create failed","projectDetail.tab.pipeline":"Pipeline","projectDetail.tab.conf":"Conf","projectDetail.tab.delete":"Delete project","projectDetail.delete.title":"Delete this project","projectDetail.delete.warn":"This will remove the project conf, runtime, and worktrees. The repository under {repoDir} is untouched.","projectDetail.delete.confirmLabel":"Type the project name to confirm","projectDetail.delete.button":"Delete project","projectDetail.delete.deleting":"Deleting…","projectDetail.lastActivity":"Last activity","projectDetail.notFound":"Project not found","projectDetail.notFoundHint":"It may have been deleted or renamed.","projectDetail.backToList":"Back to projects","pipeline.editor.title":"Pipeline YAML","pipeline.editor.savedAt":"Saved {time}","pipeline.editor.unsaved":"Unsaved changes","pipeline.editor.save":"Save","pipeline.editor.saving":"Saving…","pipeline.editor.reload":"Reload from disk","pipeline.editor.discard.title":"Discard unsaved changes?","pipeline.editor.discard.body":"Your edits will be lost.","pipeline.editor.errors":"YAML parse errors","pipeline.editor.list":"Pipelines","pipeline.editor.list.add":"New pipeline","pipeline.editor.list.delete":"Delete pipeline","pipeline.editor.list.use":"Use as active","pipeline.editor.list.activeBadge":"active","pipeline.editor.list.sample":"sample","pipeline.editor.delete.confirm.title":"Delete pipeline {name}?","pipeline.editor.delete.confirm.body":"This action cannot be undone.","pipeline.newDialog.title":"New pipeline","pipeline.newDialog.field.filename":"Filename","pipeline.newDialog.field.filename.help":"Letters, digits, _ and - only; .yaml will be appended","pipeline.newDialog.field.copyFrom":"Copy from","pipeline.newDialog.copyFrom.sample":"sample template","pipeline.newDialog.copyFrom.active":"current active","pipeline.newDialog.create":"Create","projectDetail.tab.overview":"Overview","projectDetail.tab.config":"Config","projectDetail.tab.pipelines":"Pipelines","projectDetail.tab.danger":"Danger zone","projectDetail.openBoard":"Board","projectDetail.overview.repoDir":"Repo path","projectDetail.overview.pmBackend":"PM backend","projectDetail.overview.agent":"Agent","projectDetail.overview.cards":"Cards","projectDetail.overview.cards.value":"{total} total · {inprogress} in progress · {done} done","projectDetail.overview.workers":"Workers","projectDetail.overview.workers.value":"{total} total ({active} active)","projectDetail.overview.pipeline":"Pipeline","projectDetail.overview.lastActivity":"Last activity","projectDetail.overview.notFound":"Project {name} not found or unreadable.","projectDetail.config.confDirty":"● Unsaved changes","projectDetail.config.reload":"Reload","projectDetail.config.save":"Save","projectDetail.config.saveAria":"Save config","projectDetail.config.editorAria":"conf file editor","projectDetail.config.error.conflict.title":"Config was modified elsewhere","projectDetail.config.error.conflict.body":"The conf file was changed while you were editing. Click Reload, then re-edit.","projectDetail.config.error.save.title":"Save failed","projectDetail.config.error.load":"Load failed: {detail}","projectDetail.pipelines.title":"Pipelines","projectDetail.pipelines.add":"New pipeline","projectDetail.pipelines.empty":'No pipeline files yet. Click "New pipeline" to start.',"projectDetail.pipelines.activeBadge":"active","projectDetail.pipelines.edit":"Edit","projectDetail.pipelines.editAria":"Edit {name}","projectDetail.pipelines.switch":"Switch","projectDetail.pipelines.switchAria":"Switch to {name}","projectDetail.pipelines.switch.confirm.title":"Switch to {name}","projectDetail.pipelines.switch.confirm.body":"The current project.yaml will be overwritten with the contents of {name}. Continue?","projectDetail.pipelines.switch.confirm.button":"Switch","projectDetail.pipelines.switch.error":"Switch failed","projectDetail.pipelines.delete.confirm.title":"Delete {name}","projectDetail.pipelines.delete.confirm.body":"This pipeline file will be permanently deleted.","projectDetail.pipelines.delete.error":"Delete failed","projectDetail.pipelines.deleteAria":"Delete {name}","projectDetail.pipelines.create.error":"Create failed","projectDetail.danger.title":"Delete project","projectDetail.danger.body":"This clears {path} (all cards, runtime, logs).","projectDetail.danger.includeClaude.label":"Also clear repo's .claude/","projectDetail.danger.includeClaude.note":"The repo itself is untouched; only this directory is cleaned.","projectDetail.danger.confirmPrompt":"Type the project name {name} to confirm:","projectDetail.danger.deleteAria":"Permanently delete project","projectDetail.danger.deleteButton":"Permanently delete","projectDetail.danger.deleted.title":"Deleted","projectDetail.danger.deleted.bodyWithList":`Project deleted. Also cleaned up:
|
|
450
|
+
*/const x3=[["path",{d:"M4 14a1 1 0 0 1-.78-1.63l9.9-10.2a.5.5 0 0 1 .86.46l-1.92 6.02A1 1 0 0 0 13 10h7a1 1 0 0 1 .78 1.63l-9.9 10.2a.5.5 0 0 1-.86-.46l1.92-6.02A1 1 0 0 0 11 14z",key:"1xq2db"}]],v3=Re("zap",x3),w3={"app.title":"SPS Console","nav.chat":"Chat","nav.projects":"Projects","nav.board":"Board","nav.workers":"Workers","nav.logs":"Logs","nav.skills":"Skills","nav.system":"System","nav.processes":"Processes","nav.audit":"Audit Log","nav.memory":"Memory","nav.plugins":"Plugins","plugins.h1":"Plugins 🧩","plugins.desc":"Global plugin toggles. Applies to newly dispatched cards.","plugins.tab.memory":"Memory","plugins.tab.channel":"Channel","plugins.tab.model":"Model","plugins.tab.tool":"Tool","plugins.comingSoon":"Coming soon","plugins.model.title":"Agent models","plugins.model.desc":"Configure both agents (global). worker=claude executes, review·designer=openai supervises+orchestrates.","plugins.model.worker":"Worker (executes / claude)","plugins.model.reviewer":"Review·Designer (supervisor / openai)","plugins.model.provider":"Provider","plugins.model.model":"Model","plugins.model.official":"Official claude (default)","plugins.model.save":"Save","plugins.model.saved":"Saved","plugins.model.error":"Save failed","nav.arrange":"Arrange","arrange.h1":"SmartArrange 🧭","arrange.project":"Project","arrange.none":'Not started — click "Start" above to launch (task list appears in seconds; approve to run). If the dropdown is empty, create a project in SmartArrange mode first.',"arrange.start":"Start","arrange.stop":"Stop","arrange.startErr":"Start/stop failed","arrange.view":"Toggle canvas view","arrange.viewFree":"Free","arrange.viewLane":"Lanes","arrange.starting":"Starting — breaking down the task list…","arrange.planning":"Breaking down the task list…","arrange.orchestrating":"Orchestrating…","arrange.status":"Status","arrange.goal":"Goal","arrange.plan":"Task list + card chain","arrange.approve":"Approve plan","arrange.approveErr":"Approve failed","arrange.tasks":"Task list","arrange.collapse":"Collapse","arrange.expand":"Expand task list","arrange.noCards":"No cards yet — waiting for the orchestrator to dispatch (starts after approval).","arrange.cardPrompt":"Card prompt","arrange.cardSkills":"Skills","arrange.cardTask":"Task","arrange.cardLog":"Log","arrange.close":"Close","arrange.cardsCount":"cards","nav.aria":"Main navigation","memory.sub":"Cross-project memory · agentmemory proxied behind console auth","memory.searchPlaceholder":"Search memory… (e.g. how to fix the art race)","memory.search":"Search","memory.results":"Results","memory.rawHint":"(raw observation · distilled lessons appear after live capture + compression)","memory.sessions":"Recent sessions","memory.empty":"No memory yet · accumulates after live capture (P1)","processes.title":"Processes","processes.subtitle":"Claude processes launched by SPS ACP (others, e.g. your own session, are not shown)","processes.refresh":"Refresh","processes.aliveCount":"{n} running","processes.col.kind":"Type","processes.col.slot":"Slot","processes.col.project":"Project","processes.col.state":"State","processes.col.memory":"Memory","processes.col.action":"Action","processes.empty":"No SPS processes","processes.filter.all":"All","processes.filter.alive":"Running","processes.filter.offline":"Offline","processes.kind.all":"All types","processes.kind.worker":"Worker","processes.kind.chat":"Chat","processes.kill":"Kill","processes.killConfirm":"Kill process {slot}?","audit.title":"Audit Log","audit.subtitle":"Project lifecycle: create / modify / delete","audit.refresh":"Refresh","audit.filter.all":"All","audit.action.create":"Create","audit.action.modify":"Modify","audit.action.delete":"Delete","audit.action.daemon":"Daemon","audit.col.time":"Time","audit.col.action":"Action","audit.col.project":"Project","audit.col.detail":"Detail","audit.empty":"No audit records","lang.toggle.aria":"Switch interface language","lang.en":"EN","lang.zh":"中","status.server":"server","status.offline":"offline","status.sse.open":"SSE","status.sse.connecting":"SSE·connect","status.sse.down":"SSE·down","status.pipelines.tooltip":"Active pipelines","status.workers.tooltip":"Active workers","status.pipeline.unit":"pipeline","status.worker.unit":"worker","common.save":"Save","common.cancel":"Cancel","common.delete":"Delete","common.confirm":"Confirm","common.create":"Create","common.edit":"Edit","common.close":"Close","common.loading":"Loading…","common.error":"Error","common.retry":"Retry","common.empty":"Nothing here yet","common.search":"Search","common.refresh":"Refresh","common.copy":"Copy","common.copied":"Copied","common.yes":"Yes","common.no":"No","common.required":"Required","common.optional":"Optional","common.ok":"OK","projects.title":"Projects 🎯","projects.count":"{count} local project(s)","projects.refresh.hint":"Click refresh to retry","projects.new":"New project","projects.selectHint":"Select a project on the left to see its details.","projects.sort.label":"Sort by","projects.sort.activity":"Activity","projects.sort.date":"Modified","projects.sort.name":"Name","projects.load.failed":"Failed to load","projects.empty.title":"No projects yet ✨","projects.empty.hint":"Run {cmd} to create your first project.","newProject.title":"New project","newProject.subtitle":"Set up a project; the worker will run automatically","newProject.field.mode":"Execution mode","newProject.field.mode.pipeline":"Auto pipeline","newProject.field.mode.pipelineDesc":"Fixed-stage pipeline, claude worker runs cards","newProject.field.mode.smart":"SmartArrange","newProject.field.mode.smartDesc":"OpenAI monitor dispatches cards + claude worker","newProject.field.mode.pipelineHint":"Classic mode: you create cards, worker runs them by stage.","newProject.field.mode.smartHint":"Give one goal; the OpenAI monitor probes output each round, dispatches task cards dynamically, drives claude to finish.","newProject.field.goal":"Goal (GOAL.md)","newProject.field.goal.hint":"Written to docs/GOAL.md; SmartArrange derives the task list from it. Missing → tick skips the project.","newProject.field.goal.placeholder":"e.g. Build a pure-frontend, single-file Snake browser game…","newProject.field.name":"Project name","newProject.field.name.help":"Lowercase letters, digits, _ and - only","newProject.field.dir":"Project directory","newProject.field.dir.preview":"Project will be created at →","newProject.field.dir.help":"Absolute path; will be created if missing","newProject.field.branch":"Merge target branch","newProject.field.branch.help":"Default: main","newProject.field.maxWorkers":"Max concurrent workers","newProject.field.maxWorkers.help":"Per-project worker count (1 recommended)","newProject.field.ackTimeout":"ACK timeout (seconds)","newProject.field.ackTimeout.help":"How long to wait for the worker to ACK (default 300)","newProject.field.gitlabProject":"GitLab/GitHub remote","newProject.field.gitlabProject.help":"Format: user/repo (optional)","newProject.field.matrixRoom":"Matrix room ID","newProject.field.matrixRoom.help":"Optional, falls back to global default","newProject.field.git":"Enable git","newProject.field.git.help":"Off → non-code project, no commit/push/MR steps","newProject.submit":"Create project","newProject.creating":"Creating…","newProject.created":"Project created","newProject.error.dirRequired":"Project directory is required","newProject.dir.browse":"Browse","newProject.dir.browseAria":"Pick directory","newProject.back":"Back","newProject.back.aria":"Back to projects","newProject.field.name.placeholder":"e.g. acme-web","newProject.field.name.example":"Letters, digits, underscore, hyphen. e.g. acme-web","newProject.field.name.invalid":"Name only allows a-z A-Z 0-9 _ -","newProject.field.dir.long":"Absolute path of the PROJECT directory. The selected directory is the project root; project name defaults to the directory name. Has code → adopt (only adds .claude/ config, never touches source); empty → create new.","newProject.field.dir.placeholder":"/home/you/projects/my-app","newProject.field.dir.createIfMissing":"Auto-create if missing (recommended — otherwise .claude/ install gets skipped)","newProject.field.dir.pickerTitle":"Pick project directory","newProject.field.dir.adopt":"Existing content detected → will adopt (config only, source untouched)","newProject.field.dir.fresh":"Empty directory → create new project","newProject.field.name.derived":"Project name (defaults to directory name, editable)","newProject.field.maxWorkers.short":"Max workers","newProject.field.ackTimeout.minutes":"ACK timeout (min)","newProject.field.ackTimeout.minutes.help":"How long after dispatch before the worker is considered failed if no ACK","newProject.field.git.label":"Enable Git (worker auto commit + push)","newProject.field.git.detail":"When off, the worker only does the task, no version control — fits docs / data-processing non-code projects.","newProject.field.review.label":"Enable checklist review (independent agent verifies each finished card)","newProject.field.review.detail":"When on: cards carrying a checklist are verified item-by-item against the real output by an independent reviewer after the worker finishes; all-pass stays Done, any fail auto-inserts a priority fix card. Cards without a checklist are not reviewed. Write acceptance points with --checklist when creating cards.","newProject.field.git.branch":"Merge branch","newProject.field.gitlabProject.label":"Git remote project path","newProject.field.gitlabProject.help2":"Like user/repo. Empty = skip remote API (commit/push local only)","newProject.field.gitlabProject.placeholder":"user/repo","newProject.field.gitlabProjectId":"GitLab project ID","newProject.field.gitlabProjectId.help":"Number; leave blank for GitHub","newProject.field.gitlabProjectId.placeholder":"42","newProject.section.notifications":"Notifications","newProject.field.matrixRoom.label":"Matrix room ID","newProject.field.matrixRoom.help2":"Empty = use global config; blank = no notifications","newProject.field.matrixRoom.placeholder":"!abc:matrix.example.com","newProject.error.create.title":"Create failed","projectDetail.tab.pipeline":"Pipeline","projectDetail.tab.conf":"Conf","projectDetail.tab.delete":"Delete project","projectDetail.delete.title":"Delete this project","projectDetail.delete.warn":"This will remove the project conf, runtime, and worktrees. The repository under {repoDir} is untouched.","projectDetail.delete.confirmLabel":"Type the project name to confirm","projectDetail.delete.button":"Delete project","projectDetail.delete.deleting":"Deleting…","projectDetail.lastActivity":"Last activity","projectDetail.notFound":"Project not found","projectDetail.notFoundHint":"It may have been deleted or renamed.","projectDetail.backToList":"Back to projects","pipeline.editor.title":"Pipeline YAML","pipeline.editor.savedAt":"Saved {time}","pipeline.editor.unsaved":"Unsaved changes","pipeline.editor.save":"Save","pipeline.editor.saving":"Saving…","pipeline.editor.reload":"Reload from disk","pipeline.editor.discard.title":"Discard unsaved changes?","pipeline.editor.discard.body":"Your edits will be lost.","pipeline.editor.errors":"YAML parse errors","pipeline.editor.list":"Pipelines","pipeline.editor.list.add":"New pipeline","pipeline.editor.list.delete":"Delete pipeline","pipeline.editor.list.use":"Use as active","pipeline.editor.list.activeBadge":"active","pipeline.editor.list.sample":"sample","pipeline.editor.delete.confirm.title":"Delete pipeline {name}?","pipeline.editor.delete.confirm.body":"This action cannot be undone.","pipeline.newDialog.title":"New pipeline","pipeline.newDialog.field.filename":"Filename","pipeline.newDialog.field.filename.help":"Letters, digits, _ and - only; .yaml will be appended","pipeline.newDialog.field.copyFrom":"Copy from","pipeline.newDialog.copyFrom.sample":"sample template","pipeline.newDialog.copyFrom.active":"current active","pipeline.newDialog.create":"Create","projectDetail.tab.overview":"Overview","projectDetail.tab.config":"Config","projectDetail.tab.pipelines":"Pipelines","projectDetail.tab.danger":"Danger zone","projectDetail.openBoard":"Board","projectDetail.overview.repoDir":"Repo path","projectDetail.overview.pmBackend":"PM backend","projectDetail.overview.agent":"Agent","projectDetail.overview.cards":"Cards","projectDetail.overview.cards.value":"{total} total · {inprogress} in progress · {done} done","projectDetail.overview.workers":"Workers","projectDetail.overview.workers.value":"{total} total ({active} active)","projectDetail.overview.pipeline":"Pipeline","projectDetail.overview.lastActivity":"Last activity","projectDetail.overview.notFound":"Project {name} not found or unreadable.","projectDetail.config.confDirty":"● Unsaved changes","projectDetail.config.reload":"Reload","projectDetail.config.save":"Save","projectDetail.config.saveAria":"Save config","projectDetail.config.editorAria":"conf file editor","projectDetail.config.error.conflict.title":"Config was modified elsewhere","projectDetail.config.error.conflict.body":"The conf file was changed while you were editing. Click Reload, then re-edit.","projectDetail.config.error.save.title":"Save failed","projectDetail.config.error.load":"Load failed: {detail}","projectDetail.pipelines.title":"Pipelines","projectDetail.pipelines.add":"New pipeline","projectDetail.pipelines.empty":'No pipeline files yet. Click "New pipeline" to start.',"projectDetail.pipelines.activeBadge":"active","projectDetail.pipelines.edit":"Edit","projectDetail.pipelines.editAria":"Edit {name}","projectDetail.pipelines.switch":"Switch","projectDetail.pipelines.switchAria":"Switch to {name}","projectDetail.pipelines.switch.confirm.title":"Switch to {name}","projectDetail.pipelines.switch.confirm.body":"The current project.yaml will be overwritten with the contents of {name}. Continue?","projectDetail.pipelines.switch.confirm.button":"Switch","projectDetail.pipelines.switch.error":"Switch failed","projectDetail.pipelines.delete.confirm.title":"Delete {name}","projectDetail.pipelines.delete.confirm.body":"This pipeline file will be permanently deleted.","projectDetail.pipelines.delete.error":"Delete failed","projectDetail.pipelines.deleteAria":"Delete {name}","projectDetail.pipelines.create.error":"Create failed","projectDetail.danger.title":"Delete project","projectDetail.danger.body":"This clears {path} (all cards, runtime, logs).","projectDetail.danger.includeClaude.label":"Also clear repo's .claude/","projectDetail.danger.includeClaude.note":"The repo itself is untouched; only this directory is cleaned.","projectDetail.danger.confirmPrompt":"Type the project name {name} to confirm:","projectDetail.danger.deleteAria":"Permanently delete project","projectDetail.danger.deleteButton":"Permanently delete","projectDetail.danger.deleted.title":"Deleted","projectDetail.danger.deleted.bodyWithList":`Project deleted. Also cleaned up:
|
|
451
451
|
{paths}`,"projectDetail.danger.deleted.body":"Project deleted.","projectDetail.danger.error":"Delete failed","pipelineEditor.close":"Close","pipelineEditor.error.conflict.title":"File was modified elsewhere","pipelineEditor.error.yaml.title":"YAML syntax error","pipelineEditor.error.save.title":"Save failed","pipelineEditor.error.serialize.title":"YAML serialize failed","pipelineEditor.error.load":"Load failed: {detail}","pipelineEditor.mode.structured":"Structured","pipelineEditor.mode.yaml":"Raw YAML","pipelineEditor.parseError.prefix":"YAML parse: {detail}","pipelineEditor.activeWarning":"⚠ This is the active pipeline — saving will take effect on the next tick","pipelineEditor.yamlAria":"pipeline YAML editor","pipelineEditor.status.unsaved":"● Unsaved","pipelineEditor.status.saved":"Saved","pipelineEditor.status.noChanges":"No changes","pipelineEditor.reload":"Reload","pipelineEditor.save":"Save","pipelineEditor.saveAria":"Save pipeline","pipelineEditor.activeBadge":"active","pipelineEditor.modeHint":"project = event-driven pipeline (default) · steps = sequential script","pipelineEditor.stages.heading":"Stages ({count})","pipelineEditor.stages.add":"Add stage","pipelineEditor.stages.empty":'No stages yet. Click "Add stage" to start.',"pipelineEditor.stage.name.hint":"Unique stage name","pipelineEditor.stage.profile.hint":"skill profile, may be empty","pipelineEditor.stage.cardState.hint":"Card state during this stage","pipelineEditor.stage.timeout.hint":"Optional, e.g. 30m 2h","pipelineEditor.stage.trigger.hint":"Trigger condition, blank uses default","pipelineEditor.stage.onComplete.hint":"Action on success","pipelineEditor.stage.onFail.action.hint":"Action on failure, e.g. label NEEDS-FIX","pipelineEditor.stage.onFail.comment.hint":"Comment written on the card","pipelineEditor.stage.halt.note":"(stops pipeline on failure; uncheck to continue with next card)","pipelineEditor.stage.moveUp":"Move up","pipelineEditor.stage.moveDown":"Move down","pipelineEditor.stage.remove":"Remove stage","newPipelineDialog.title":"New pipeline","newPipelineDialog.field.filename.label":"Filename","newPipelineDialog.field.filename.placeholder":"e.g. ci","newPipelineDialog.field.filename.help":"Will be saved as {filename}. Only a-z A-Z 0-9 _ - allowed; an existing file errors 409.","newPipelineDialog.section.template":"Initial content","newPipelineDialog.template.blank.label":"Blank template","newPipelineDialog.template.blank.desc":"Minimal 1-stage pipeline (develop → Done)","newPipelineDialog.template.sample.label":"Tutorial template","newPipelineDialog.template.sample.desc":"Copied from sample.yaml.example (annotated, every field explained)","newPipelineDialog.template.sample.unavailable":"sample.yaml.example does not exist","newPipelineDialog.template.active.label":"Copy current active","newPipelineDialog.template.active.desc":"Copied from project.yaml (build on the current config)","newPipelineDialog.template.active.unavailable":"project.yaml does not exist","newPipelineDialog.create.aria":"Create pipeline","newPipelineDialog.cancel":"Cancel","board.title":"Board ✨","board.title.bare":"Board","board.subtitle":"{name} · {cards} cards · {workers} workers active","board.pickPrompt.title":"Pick a project 🎯","board.pickPrompt.body":"The board is per-project. Pick one to start:","board.action.start":"Start","board.action.stop":"Stop","board.action.startAria":"Start pipeline","board.action.stopAria":"Stop pipeline","board.action.startError":"Failed to start pipeline","board.action.stopError":"Failed to stop pipeline","board.action.reset":"Reset","board.action.resetError":"Reset failed","board.action.reset.confirm.title":"Reset the entire pipeline","board.action.reset.confirm.body":"This clears all cards’ run state, worker markers, and branches. Cannot be undone.","board.action.reset.confirm.button":"Reset all","board.action.newCard":"New card","board.action.newCard.error":"Failed to create card","board.action.moveCard.error":"Failed to move card","board.search.placeholder":"Search title / skill / label…","board.search.aria":"Search cards","board.filter.clear":"Clear","board.filter.clearAria":"Clear filters","board.filter.aria":"Filter by {label}","board.filter.clearSelection":"Clear selection","board.error.loadCards":"Failed to load cards","board.col.planning":"Planning","board.col.backlog":"Backlog","board.col.todo":"Todo","board.col.inprogress":"Inprogress","board.col.qa":"QA / Review","board.col.done":"Done","kanban.checklist.label":"Checklist {done}/{total}","kanban.checklist.more":"… {count} more","kanban.column.empty":"— empty —","kanban.time.justNow":"just now","kanban.time.minutes":"{n}m ago","kanban.time.hours":"{n}h ago","kanban.time.days":"{n}d ago","newCard.title":"New card","newCard.field.title":"Title *","newCard.field.title.placeholder":"e.g. Add GitHub OAuth login","newCard.field.title.help":"Short, clear goal (<200 chars)","newCard.field.description":"Description","newCard.field.description.placeholder":"User story, requirements, acceptance criteria, references… Claude reads this when starting","newCard.field.description.help":"Markdown supported. If empty, Claude only sees the title.","newCard.field.skills":"Skills","newCard.field.skills.help":"Pick which skills get loaded (via frontmatter `skills:`). Optional — worker falls back to project-level skills.","newCard.field.skills.loading":"Loading skills…","newCard.field.skills.error":"Failed to load skills (creation still works): {detail}","newCard.field.skills.selected":"{count} selected: {names}","newCard.field.dispatch":"Dispatch","newCard.field.dispatch.label":"Dispatch immediately (go straight to Backlog)","newCard.field.dispatch.help":"Default off: card lands in Planning to wait; drag to Backlog when ready. On: skip Planning, the next tick assigns a worker.","newCard.create.aria":"Create card","cardDetail.loading":"Loading…","cardDetail.error.load":"Failed to load card","cardDetail.tabs.overview":"Overview","cardDetail.tabs.body":"Description","cardDetail.tabs.checklist":"Checklist","cardDetail.tabs.history":"History","cardDetail.tabs.actions":"Actions","cardDetail.field.state":"State","cardDetail.field.skills":"Skills","cardDetail.field.labels":"Labels","cardDetail.field.branch":"Branch","cardDetail.field.assignee":"Assignee","cardDetail.field.created":"Created","cardDetail.field.updated":"Updated","cardDetail.field.empty":"—","cardDetail.actions.delete":"Delete card","cardDetail.actions.delete.confirm.title":"Delete card #{seq}","cardDetail.actions.delete.confirm.body":"This card will be permanently deleted.","cardDetail.actions.delete.error":"Delete failed","cardDetail.actions.update.error":"Update failed","cardDetail.body.empty":"No description","cardDetail.checklist.empty":"No checklist","cardDetail.checklist.progress":"Progress {done}/{total}","cardDetail.history.empty":"No history","cardDetail.notFound":"Card #{seq} not found","cardDetail.copy.aria":"Copy seq","cardDetail.close.aria":"Close","cardDetail.save":"Save","cardDetail.saving":"Saving…","workers.title":"Workers 👷","workers.summary":"Across {projects} projects · {running} running · {starting} starting · {stuck} stuck · {crashed} crashed · {idle} idle","workers.summary.stuck":"{n} stuck","workers.summary.crashed":"{n} crashed","workers.refresh.aria":"Refresh","workers.refresh":"Refresh","workers.error.load":"Load failed: {detail}","workers.empty.hint":"Click a project / worker to see details","logs.title":"Logs 📜","logs.subtitle.allProjects":"All projects","logs.subtitle.project":"{name} live tail","logs.filter.errors":"Errors only","logs.filter.errors.aria":"Show errors only","logs.filter.search.placeholder":"Filter messages…","logs.empty":"No logs yet — waiting for events","logs.error.load":"Failed to load logs","logs.refresh":"Refresh","logs.refresh.aria":"Refresh logs","logs.scroll.bottom.aria":"Scroll to bottom","logs.scroll.pause":"Paused (autoscroll off)","logs.scroll.resume":"Resume autoscroll","logs.subtitle.allProjectsCount":"All projects ({count})","logs.poll.5s":"5s polling","logs.paused":"⏸ PAUSED","logs.mode.live":"Live","logs.mode.history":"History","logs.history.startAria":"Query start time","logs.history.queryAria":"Query","logs.history.query":"Query","logs.filter.project.aria":"Filter project","logs.filter.project.all":"All projects","logs.filter.keyword.placeholder":"Filter keyword…","logs.filter.keyword.aria":"Filter logs","logs.empty.match":"No matching logs","skills.title":"Skills 🧠","skills.subtitle":"Skills shared across projects (managed via `sps skill ...`)","skills.empty.title":"No skills yet","skills.empty.hint":"Run {cmd} to sync the bundled skills.","skills.linked.tooltip":"linked into this project","skills.frozen.tooltip":"frozen (per-project copy)","skills.category.all":"All","skills.category.language":"language","skills.category.end":"end","skills.category.persona":"persona","skills.category.workflow":"workflow","skills.category.other":"other","skills.subtitleCount":"{count} user-level skill(s)","skills.search.placeholder":"Search skill…","skills.search.aria":"Search skill","skillDetail.actionFailed":"{label} failed","skillDetail.unfreezeAction":"Unfreeze","skillDetail.freezeAction":"Freeze","skillDetail.removeAction":"Remove","skillDetail.removeConfirm.title":"Remove {name} from {project}","skillDetail.removeConfirm.body":"The skill link will be removed; the project will not see this skill on next run.","skillDetail.removeConfirm.button":"Remove","skillDetail.unfreezeConfirm.title":"Unfreeze {name} @ {project}","skillDetail.unfreezeConfirm.body":"Local changes to this skill will be overwritten with the latest shared version.","skillDetail.unfreezeConfirm.button":"Unfreeze","skillDetail.close.aria":"Close","skillDetail.loading":"Loading…","skillDetail.error.load":"Load failed: {detail}","skillDetail.section.projects":"Per-project link status","skillDetail.section.empty":"No projects yet. Create one first.","skillDetail.section.preview":"SKILL.md preview","skillDetail.toggleSection.aria":"{action} {file}","skillDetail.expand":"Expand","skillDetail.collapse":"Collapse","system.title":"System 🛠","system.subtitle":"Global config + diagnostics + upgrades","system.section.env":"Global env","system.section.env.help":"Stored in ~/.coral/env (mode 600). Used by all projects.","system.section.env.save":"Save env","system.section.env.error.conflict":"env was modified elsewhere","system.section.env.error.save":"Failed to save env","system.section.env.error.load":"Failed to load env","system.section.env.dirtyDot":"● Unsaved","system.section.env.aria":"env editor","system.section.env.reload":"Reload","system.section.upgrade":"Upgrade","system.section.upgrade.current":"Current: v{version}","system.section.upgrade.latest":"Latest on npm: v{version}","system.section.upgrade.uptodate":"Up to date","system.section.upgrade.update":"Upgrade now","system.section.upgrade.upgrading":"Upgrading…","system.section.upgrade.checking":"Checking npm…","system.section.upgrade.checkError":"Check failed: {detail}","system.section.upgrade.upgradeError":"Upgrade failed: {detail}","system.section.upgrade.upgradeError.title":"Upgrade failed","system.section.upgrade.command":"Or run in terminal: {cmd}","system.section.upgrade.runningPipelines":"Pipelines running — stop them first: {projects}","system.section.diagnostics":"Diagnostics","system.section.diagnostics.help":"Run sps doctor across all projects, see failures at a glance","system.section.diagnostics.run":"Run diagnostics","system.section.diagnostics.running":"Running…","system.section.diagnostics.empty":"No projects","system.section.diagnostics.checkAria":"Check {project}","system.section.diagnostics.statusOk":"OK","system.section.diagnostics.statusFail":"Issues","system.section.diagnostics.error":"Diagnostic failed: {detail}","system.h1":"System ⚙️","system.runtime":"Runtime","system.memory.title":"Memory backend","system.memory.desc":"Global setting: which backend workers read/write memory through. Applies to newly dispatched cards.","system.memory.provider":"Backend","system.memory.url":"Custom URL","system.memory.url.placeholder":"http://127.0.0.1:3111","system.memory.save":"Save","system.memory.save.aria":"Save memory backend setting","system.memory.saved":"Saved","system.memory.error":"Save failed","system.memory.opt.none":"Off (none)","system.memory.opt.builtin":"Local file memory (builtin)","system.memory.opt.agentmemory":"agentmemory (semantic)","system.memory.opt.custom":"Custom REST (custom)","system.env.title.code":"~/.coral/env","system.env.title.prefix":"Global config ","system.env.edit.aria":"Edit env file","system.env.edit.button":"Edit","system.env.editing.label":"⚠ Editing","system.env.empty.before":'env file does not exist. Click "Edit" or run ',"system.env.empty.after":" in the terminal.","system.env.warning":"⚠ This file contains plaintext credentials. Keep mode 0600 on save.","system.env.aria":"env editor","system.env.dirtyMark":" · ● Unsaved","system.env.cancel":"Cancel","system.env.save":"Save","system.env.save.aria":"Save env","system.env.error.conflict.title":"env was modified elsewhere","system.env.error.save.title":"Save failed","system.env.error.conflict.body":"Cancel and reopen the editor.","system.upgrade.title":"Version","system.upgrade.checkLatest.aria":"Check latest version","system.upgrade.checkUpdate":"Check update","system.upgrade.label.current":"sps-cli (current)","system.upgrade.label.latest":"npm (latest)","system.upgrade.latestPill":"latest","system.upgrade.button.upgradeAria":"Upgrade to latest","system.upgrade.button.upgrade":"Upgrade","system.upgrade.button.copyAria":"Copy upgrade command","system.upgrade.button.copyTitle":"Copy command (run manually if auto upgrade fails)","system.upgrade.button.copy":"Copy command","system.upgrade.label.installed":"Installed","system.upgrade.installed.ok":"Active (restart console to see)","system.upgrade.installed.fail":"Upgrade not effective","system.upgrade.label.check":"Check","system.upgrade.confirm.title":"Upgrade sps-cli","system.upgrade.confirm.body":"Current {current}, upgrade to {latest}. Requires all pipelines stopped. Restart sps console after upgrade.","system.upgrade.confirm.button":"Upgrade","system.upgrade.success.title":"Upgrade complete","system.upgrade.success.body":'Installed v{version}. Run `pkill -f "sps console"` and restart to see it.',"system.upgrade.notEffective.title":"Upgrade not effective","system.upgrade.notEffective.same":"npm finished but the version did not change (still {version}) — likely a permissions or registry issue. Copy the command below to run manually.","system.upgrade.notEffective.notInstalled":"npm did not install a new version. Copy the command to run manually, or check the log below.","system.upgrade.error.title":"Upgrade failed","system.upgrade.copy.success.title":"Command copied","system.upgrade.copy.success.body":`Paste it into a terminal:
|
|
452
452
|
{cmd}`,"system.upgrade.copy.fail.title":"Copy failed","system.upgrade.copy.fail.body":`Copy manually:
|
|
453
453
|
{cmd}`,"system.diagnostics.title":"Project health check","system.diagnostics.checkAll":"Check all","system.diagnostics.empty":"No projects yet.","system.diagnostics.expandAria":"Expand","system.diagnostics.collapseAria":"Collapse","system.diagnostics.never":'Click "Check" to run sps doctor',"system.diagnostics.checkAria":"Check","system.diagnostics.check":"Check","system.diagnostics.noFixesNeeded":"Nothing to fix","system.diagnostics.fix.tip":"Run sps doctor <proj> --fix: auto-create .claude/hooks/stop.sh, state.json, etc.","system.diagnostics.fixAria":"Auto fix","system.diagnostics.fix":"Fix","system.diagnostics.fixed":"Fixed","system.diagnostics.error.fix":"doctor fix failed","system.diagnostics.error.check":"doctor check failed","chat.title":"Chat 💬","chat.empty.title":"Chat 💬","chat.empty.hint":'Click "New chat" on the left to start a session, or just type below — a session will be auto-created.',"chat.empty.shortcuts":"Enter to send · Shift+Enter for newline · streamed reply","chat.list.heading":"History {count}","chat.list.new":"New chat","chat.list.empty":"No chats yet. Click above to start.","chat.list.delete.aria":"Delete chat","chat.list.deleteCli.aria":"Remove this CLI session from the Console (does not affect Claude jsonl history)","chat.list.openAria":"Open chat {title}{cwd}","chat.list.cwdSuffix":" (cwd: {cwd})","chat.list.msgs":"{count} msg · {time}","chat.list.olderToggle":"Earlier · {count}","chat.detail.model.tooltip":"Current model in use","chat.detail.claudeSession.tooltip":"Underlying claude session id — the anchor for resuming session & memory","chat.delete.confirm.title":"Delete chat","chat.delete.confirm.body.cli":"Will be removed from the Console list (the daemon session is stopped). The Claude CLI history under ~/.claude/projects is preserved — to continue, run `sps agent --chat --name <name>` in a terminal.","chat.delete.confirm.body.console":"Chat history will be permanently deleted.","chat.delete.confirm.button":"Delete","chat.cli.banner.bold":"CLI session","chat.cli.banner":"This session was created by sps agent. The Console only shows history. To continue, run in a terminal:","chat.input.placeholder":"Say something… (Enter to send, Shift+Enter for newline, drag files / paste images)","chat.input.dragOver":"Drop to attach…","chat.input.aria":"Message input","chat.input.attach.aria":"Attach a local file","chat.input.attach.title":"Attach a local file (also drag / paste images)","chat.input.send":"Send","chat.input.send.aria":"Send","chat.input.interrupt":"Stop","chat.input.interrupt.aria":"Stop generation","chat.input.uploading":"Uploading…","chat.input.removeAttachment":"Remove {name}","chat.error.interrupt.title":"Interrupt failed","chat.cliBadge":"CLI","chat.cliBadge.tooltip":"Created by sps agent CLI; history is read live from Claude jsonl (read-only).","chat.session.title":"{title}","chat.session.id":"{id}","chat.session.empty":"Type a question below to start · Enter to send · Shift+Enter for newline","notFound.title":"404","notFound.body":"This page does not exist.","notFound.home":"Back to home","workers.active.empty":"No workers running.","workers.alerts.allHealthy":"All workers healthy","workers.alerts.pidDead":"PID dead.","workers.alerts.markerStale":"marker stale {ago}.","workers.capacity.col.project":"Project","workers.capacity.col.usage":"Usage","workers.capacity.col.other":"Other","workers.capacity.detailHint":"details →","workers.panel.boardLink":"Board →","workers.panel.loading":"Loading workers…","workers.panel.empty.slots":"This project has no worker slots.","workers.panel.empty.noWorker":"No workers","workers.panel.empty.pickOne":"Pick a worker","workers.panel.idle.short":"idle","workers.panel.section.currentCard":"Current card","workers.panel.idle.full":"Slot idle, no current card.","workers.panel.section.claudeOutput":"Claude output · last {n} lines","workers.panel.output.loading":"Loading…","workers.panel.output.empty":"No session output yet. The worker needs a few seconds to start.","workers.panel.section.heartbeat":"Supervisor heartbeat · last {n} lines","workers.panel.heartbeat.fullLog":"View full log →","workers.panel.action.restart":"Restart","workers.panel.action.restart.confirm.title":"Restart worker-{slot}","workers.panel.action.restart.confirm.body":"Kill the process, then re-launch onto #{seq}","workers.panel.action.restart.confirm.button":"Restart","workers.panel.action.restart.error":"Restart failed","workers.panel.action.kill":"Kill","workers.panel.action.kill.confirm.title":"Kill worker-{slot}","workers.panel.action.kill.confirm.body":"The current task will be force-aborted.","workers.panel.action.kill.confirm.button":"Kill","workers.panel.action.kill.error":"Kill failed","dialog.confirm.default":"OK","dialog.alert.default":"Got it","dialog.cancel.default":"Cancel","dirPicker.title.default":"Pick a directory","dirPicker.close.aria":"Close","dirPicker.up.aria":"Parent directory","dirPicker.up.title":"Parent directory","dirPicker.home.aria":"Back to home","dirPicker.home.title":"Back to home","dirPicker.loading":"Loading…","dirPicker.error.title":"Read failed","dirPicker.empty":"— empty —","dirPicker.enter.aria":"Enter {name}/","dirPicker.pickFile.aria":"Pick {name} (double-click to confirm)","dirPicker.fileLocked":"File not selectable","dirPicker.cancel":"Cancel","dirPicker.useFile":"Use this file","dirPicker.useFile.tooltip.empty":"Click a file first","dirPicker.useDir":"Use this directory","dirPicker.newDir":"New folder","dirPicker.newDir.aria":"Create a subdirectory in the current directory","dirPicker.newDir.prompt":"New folder name (letters, digits, _ . - only)","dirPicker.newDir.placeholder":"Folder name","dirPicker.newDir.create":"Create","dirPicker.newDir.error.title":"Failed to create folder","errorBoundary.title":"💥 UI crashed","errorBoundary.refresh":"Refresh page","chat.error.create.title":"Failed to create chat","chat.error.send.title":"Send failed","chat.error.fileTooBig.title":"File too large","chat.error.fileTooBig.body":"Per-file limit is 50 MB; this is {size} MB ({name})","chat.error.uploadAttachment.title":"Attachment upload failed","chat.placeholder.attachment":"(attachment)","chat.placeholder.viewAttachment":"(see attachment)","chat.placeholder.attachmentTitle":"Attachment","chat.attachment.previewTooltip":`{name}
|
|
454
454
|
{path}
|
|
455
455
|
Click to preview`,"chat.attachment.previewSimpleTooltip":`{name}
|
|
456
|
-
Click to zoom`,"chat.attachment.preview.aria":"Preview {name}","chat.attachment.close.aria":"Close","chat.attachment.readErr":"Read failed: {detail}","chat.attachment.loading":"Loading…","chat.attachment.unsupported":"This file type cannot be previewed inline.","chat.attachment.download":"Download","chat.message.role.you":"You","chat.message.role.error":"Error","chat.message.role.assistant":"assistant","chat.message.truncated":"⚠ Output exceeded 10MB and was truncated","chat.filePicker.title":"Pick attachment file","chat.newSession.title":"New chat","chat.newSession.title.aria":"New chat","chat.newSession.close.aria":"Close","chat.newSession.field.agent":"Agent","chat.newSession.field.model":"Model (optional)","chat.newSession.field.model.default":"Use global default model","chat.newSession.field.title":"Title (optional)","chat.newSession.field.title.placeholder":"Empty = auto-generate from first message","chat.newSession.field.cwd":"Working directory (optional)","chat.newSession.field.cwd.browse":"Browse","chat.newSession.field.cwd.browseAria":"Pick directory","chat.newSession.field.cwd.title":"Pick directory","chat.newSession.field.cwd.help1":"The agent reads/writes files here. Absolute path; must exist.","chat.newSession.field.cwd.help2":"Empty = use the daemon’s startup cwd.","chat.newSession.cancel":"Cancel","chat.newSession.create":"Create","cardModal.editing":"⚠ Editing","cardModal.title.aria":"Card title","cardModal.editAria":"Edit card","cardModal.edit":"Edit","cardModal.close.aria":"Close","cardModal.error.save.title":"Save failed","cardModal.error.load":"Load failed: {detail}","cardModal.skills.loading":"Loading skill list…","cardModal.label.removeAria":"Remove {label}","cardModal.label.addPlaceholder":"+ Add label","cardModal.label.addAria":"Add label","cardModal.label.note":"Note: AI-PIPELINE / STARTED-* / COMPLETED-* / NEEDS-FIX are managed by the pipeline; manual changes may be overwritten","cardModal.section.description":"Description","cardModal.section.empty":"(empty)","cardModal.section.checklist":"Checklist","cardModal.checklist.empty":"No checklist items. Add `- [ ] item` syntax in the description.","cardModal.section.log":"Log","cardModal.body.aria":"Card description","cardModal.body.replaceNote":'Only replaces the "## Description" section; checklist and log sections are untouched.',"cardModal.action.launch":"Launch worker","cardModal.action.launch.disabledDone":"Card is done; drag back to Todo to launch","cardModal.action.launch.disabledRunning":"Pipeline is running — supervisor dispatches automatically, no manual launch needed","cardModal.action.launch.error":"Launch worker failed","cardModal.action.reset":"Reset card","cardModal.action.reset.confirm.title":"Reset card #{seq}","cardModal.action.reset.confirm.body":"Card state goes back to initial; checklist progress is cleared.","cardModal.action.reset.confirm.button":"Reset","cardModal.action.reset.error":"Reset failed","cardModal.action.delete":"Delete card","cardModal.action.delete.confirm1.title":"Delete card #{seq}","cardModal.action.delete.confirm1.body":'About to delete "{title}". This cannot be undone (the md file is physically removed). Continue?',"cardModal.action.delete.confirm1.button":"Continue","cardModal.action.delete.confirm2.title":"Final confirmation","cardModal.action.delete.confirm2.body":"Please re-confirm deleting card #{seq}.","projectDetail.tab.skills":"Skills","projectDetail.tab.rules":"Rules","projectDetail.skills.title":"Skill whitelist","projectDetail.skills.desc":"Pick which skills this project loads. Narrows what workers, subagents and chat see — cuts token cost.","projectDetail.skills.noPolicy":"No whitelist — all skills are available (subagents load the full set from disk).","projectDetail.skills.hasPolicy":"Whitelist active — {count} skill(s) eligible.","projectDetail.skills.save":"Save whitelist","projectDetail.skills.clear":"Clear (load all)","projectDetail.skills.saveError":"Failed to save whitelist","projectDetail.skills.applied":"Saved. Projected {linked} linked, {pruned} pruned.","projectDetail.skills.unknown":"Unknown skill name(s), ignored: {names}","projectDetail.skills.empty":"No skills installed. Run `sps skill sync` first.","projectDetail.skills.selectAll":"Select all","projectDetail.skills.selectNone":"Select none","projectDetail.rules.title":"Project rules (read-only)","projectDetail.rules.readonly":"sps-cli only reads these. Editing is done at project creation or by an agent later.","projectDetail.rules.missing":"Not present","nav.prompts":"Prompts","prompts.title":"Prompt library","prompts.desc":"Reusable prompts with {{variable}} templates. Insert them into chat.","prompts.new":"New prompt","prompts.search":"Search prompts…","prompts.empty":"No prompts yet. Create one.","prompts.name":"Name","prompts.namePlaceholder":"kebab-case, e.g. code-review","prompts.nameError":"Name must be kebab-case (a-z, 0-9, dashes).","prompts.description":"Description","prompts.tags":"Tags","prompts.tagsPlaceholder":"comma,separated","prompts.body":"Body","prompts.bodyPlaceholder":"Write your prompt. Use {{variable}} for fill-ins.","prompts.favorite":"Favorite","prompts.save":"Save","prompts.delete":"Delete","prompts.deleteConfirm":'Delete prompt "{name}"? This removes the file.',"prompts.saveError":"Failed to save prompt","prompts.vars":"Variables: {names}","prompts.noVars":"No variables","prompts.insert":"Insert a prompt","prompts.selectHint":"Select a prompt on the left, or create a new one.","prompts.tagAdd":"Type a tag, press Enter","prompts.ai":"AI generate","prompts.ai.title":"AI generate a prompt","prompts.ai.intent":"Describe what you want","prompts.ai.placeholder":"e.g. a prompt for reviewing TypeScript code for security issues","prompts.ai.submit":"Generate","prompts.ai.wait":"The agent is writing… this can take a while.","prompts.ai.error":"Generation failed","skills.import":"Import","skills.import.title":"Import a skill","skills.import.name":"Name (kebab-case)","skills.import.body":"SKILL.md content","skills.import.submit":"Import","skills.import.error":"Import failed","skills.export":"Export SKILL.md","skills.updates.badge":"{count} update(s) available","skills.updates.none":"Up to date","skills.ai":"AI create","skills.ai.title":"AI create a skill","skills.ai.name":"Name (kebab-case)","skills.ai.intent":"What is this skill for?","skills.ai.placeholder":"e.g. how to write idiomatic Rust error handling","skills.ai.submit":"Create","skills.ai.wait":"The agent is writing the skill… this can take a while.","skills.ai.error":"Create failed","projectDetail.tab.graph":"Code Graph","projectDetail.tab.logs":"Logs","graph.title":"Code Graph","graph.desc":"A symbol-level dependency graph of this project (tree-sitter, zero-token). Gives agents surgical context so they explore fewer files.","graph.build":"Build graph","graph.rebuild":"Rebuild","graph.building":"Building…","graph.sync":"Sync","graph.syncing":"Syncing…","graph.sync.desc":"Incremental — only re-index changed files (fast)","graph.empty":"No graph yet — build one to enable agent navigation and the dependency view.","graph.buildFailed":"Build failed","graph.stat.files":"Files","graph.stat.nodes":"Nodes","graph.stat.edges":"Edges","graph.stat.db":"DB size","graph.stat.lastBuilt":"Last built","graph.viz.title":"File dependency graph","graph.viz.loading":"Loading graph…","graph.viz.empty":"Build the graph to see the dependency view.","graph.viz.hint":"Node = file · edge = import · drag to explore · search to highlight","graph.viz.search":"Highlight files…"},k3={"app.title":"SPS 控制台","nav.chat":"对话","nav.projects":"项目","nav.board":"看板","nav.workers":"Workers","nav.logs":"日志","nav.skills":"技能","nav.system":"系统","nav.processes":"进程","nav.audit":"审计日志","nav.memory":"记忆","nav.plugins":"插件","plugins.h1":"插件 🧩","plugins.desc":"全局插件开关。改动对之后新派发的卡生效。","plugins.tab.memory":"记忆","plugins.tab.channel":"频道","plugins.tab.model":"模型","plugins.tab.tool":"工具","plugins.comingSoon":"即将上线","plugins.model.title":"智能体模型","plugins.model.desc":"配置两个智能体的模型(全局)。worker=claude 执行、review·designer=openai 监工+编排。","plugins.model.worker":"Worker(执行 / claude)","plugins.model.reviewer":"Review·Designer(监工 / openai)","plugins.model.provider":"Provider","plugins.model.model":"模型","plugins.model.official":"官方 claude(默认)","plugins.model.save":"保存","plugins.model.saved":"已保存","plugins.model.error":"保存失败","nav.arrange":"编排","arrange.h1":"智能编排 🧭","arrange.project":"项目","arrange.none":"尚未开始 — 点上方「启动」拉起编排(几秒后出任务清单,确认即跑)。若下拉无项目,先在「新建项目」选智能编排模式。","arrange.start":"启动","arrange.stop":"停止","arrange.startErr":"启动/停止失败","arrange.view":"切换画板视图","arrange.viewFree":"自由","arrange.viewLane":"泳道","arrange.starting":"启动中,正在拆解任务清单…","arrange.planning":"正在拆解任务清单…","arrange.orchestrating":"正在编排中…","arrange.status":"状态","arrange.goal":"目标","arrange.plan":"任务清单 + 卡链路","arrange.approve":"确认任务清单","arrange.approveErr":"确认失败","arrange.tasks":"任务清单","arrange.collapse":"收起","arrange.expand":"展开任务清单","arrange.noCards":"暂无卡片 — 等待 orchestrator 派卡(确认清单后开始)。","arrange.cardPrompt":"卡片提示词","arrange.cardSkills":"技能","arrange.cardTask":"所属任务","arrange.cardLog":"日志","arrange.close":"关闭","arrange.cardsCount":"张卡","nav.aria":"主导航","memory.sub":"跨项目记忆 · 经 console 鉴权代理 agentmemory","memory.searchPlaceholder":"搜索记忆…(如:三消美术竞态怎么修)","memory.search":"搜索","memory.results":"召回结果","memory.rawHint":"(原始观察 · 接入实时捕获+压缩后这里会显示提炼的教训)","memory.sessions":"最近会话","memory.empty":"暂无记忆 · 接入实时捕获(P1)后自动累积","processes.title":"进程监控","processes.subtitle":"SPS ACP 启动的 claude 进程(其它途径启动的,如你自己的会话,不显示)","processes.refresh":"刷新","processes.aliveCount":"运行中 {n}","processes.col.kind":"类型","processes.col.slot":"会话槽","processes.col.project":"项目","processes.col.state":"状态","processes.col.memory":"内存","processes.col.action":"操作","processes.empty":"没有 SPS 进程","processes.filter.all":"全部","processes.filter.alive":"运行中","processes.filter.offline":"离线","processes.kind.all":"全部类型","processes.kind.worker":"构建 Worker","processes.kind.chat":"对话","processes.kill":"关闭","processes.killConfirm":"确定关闭进程 {slot}?","audit.title":"审计日志","audit.subtitle":"项目生命周期:创建 / 修改 / 删除","audit.refresh":"刷新","audit.filter.all":"全部","audit.action.create":"创建","audit.action.modify":"修改","audit.action.delete":"删除","audit.action.daemon":"Daemon","audit.col.time":"时间","audit.col.action":"动作","audit.col.project":"项目","audit.col.detail":"详情","audit.empty":"暂无审计记录","lang.toggle.aria":"切换界面语言","lang.en":"EN","lang.zh":"中","status.server":"服务","status.offline":"离线","status.sse.open":"SSE","status.sse.connecting":"SSE·连接中","status.sse.down":"SSE·断开","status.pipelines.tooltip":"活跃流水线数","status.workers.tooltip":"活跃 Worker 数","status.pipeline.unit":"流水线","status.worker.unit":"Worker","common.save":"保存","common.cancel":"取消","common.delete":"删除","common.confirm":"确认","common.create":"创建","common.edit":"编辑","common.close":"关闭","common.loading":"加载中…","common.error":"出错","common.retry":"重试","common.empty":"暂无内容","common.search":"搜索","common.refresh":"刷新","common.copy":"复制","common.copied":"已复制","common.yes":"是","common.no":"否","common.required":"必填","common.optional":"可选","common.ok":"好","projects.title":"项目 🎯","projects.count":"本机有 {count} 个项目","projects.refresh.hint":"点击刷新重试","projects.new":"新建项目","projects.selectHint":"在左侧选择一个项目查看详情。","projects.sort.label":"排序方式","projects.sort.activity":"活跃度","projects.sort.date":"修改日期","projects.sort.name":"名字","projects.load.failed":"加载失败","projects.empty.title":"还没有项目 ✨","projects.empty.hint":"运行 {cmd} 创建第一个项目。","newProject.title":"新建项目","newProject.subtitle":"配置一个项目,worker 自动开跑","newProject.field.mode":"执行模式","newProject.field.mode.pipeline":"自动工作流","newProject.field.mode.pipelineDesc":"固定阶段流水线,claude worker 按卡执行","newProject.field.mode.smart":"智能编排","newProject.field.mode.smartDesc":"OpenAI 监工动态派卡 + claude worker 执行","newProject.field.mode.pipelineHint":"传统模式:你建卡片,worker 按阶段跑。","newProject.field.mode.smartHint":"给一个总目标,OpenAI 监工每轮探查产物、动态生成任务卡、驱动 claude 完成。","newProject.field.goal":"总目标 (GOAL.md)","newProject.field.goal.hint":"写入 docs/GOAL.md;智能编排据此拆任务清单。缺失则 tick 跳过该项目。","newProject.field.goal.placeholder":"例:做一个纯前端、单文件可运行的贪吃蛇网页小游戏…","newProject.field.name":"项目名","newProject.field.name.help":"只允许小写字母、数字、_ 和 -","newProject.field.dir":"项目目录","newProject.field.dir.preview":"项目将创建在 →","newProject.field.dir.help":"绝对路径;不存在会自动创建","newProject.field.branch":"合并目标分支","newProject.field.branch.help":"默认 main","newProject.field.maxWorkers":"最大并发 Worker 数","newProject.field.maxWorkers.help":"单项目并发数(推荐 1)","newProject.field.ackTimeout":"ACK 超时(秒)","newProject.field.ackTimeout.help":"Worker 响应等待秒数(默认 300)","newProject.field.gitlabProject":"GitLab/GitHub 远程","newProject.field.gitlabProject.help":"格式:用户名/仓库(可选)","newProject.field.matrixRoom":"Matrix 房间 ID","newProject.field.matrixRoom.help":"可选;不填则用全局默认","newProject.field.git":"启用 git","newProject.field.git.help":"关闭 → 非代码项目,跳过 commit/push/MR","newProject.submit":"创建项目","newProject.creating":"创建中…","newProject.created":"项目已创建","newProject.error.dirRequired":"项目目录必填","newProject.dir.browse":"浏览","newProject.dir.browseAria":"选择目录","newProject.back":"返回","newProject.back.aria":"返回项目列表","newProject.field.name.placeholder":"例如:acme-web","newProject.field.name.example":"只能用字母、数字、下划线、连字符。例如 acme-web","newProject.field.name.invalid":"名称只能包含 a-z A-Z 0-9 _ -","newProject.field.dir.long":"本机绝对路径的【项目目录】。选中的目录本身就是项目根;项目名默认取目录名。已有代码 → 收编(只加 .claude/ 配置,不动源码);空目录 → 新建。","newProject.field.dir.placeholder":"/home/you/projects/my-app","newProject.field.dir.createIfMissing":"目录不存在时自动创建(推荐 —— 否则 .claude/ 安装会被跳过)","newProject.field.dir.pickerTitle":"选择项目目录","newProject.field.dir.adopt":"检测到已有内容 → 将收编(只加配置,不动源码)","newProject.field.dir.fresh":"空目录 → 新建项目","newProject.field.name.derived":"项目名(默认取目录名,可微调)","newProject.field.maxWorkers.short":"最大 Worker 数","newProject.field.ackTimeout.minutes":"ACK 超时(分钟)","newProject.field.ackTimeout.minutes.help":"Worker 启动后多久没 ACK 视为失败","newProject.field.git.label":"启用 Git(Worker 自动 commit + push)","newProject.field.git.detail":"关闭后 Worker 只做任务、不做版本控制;适合文档/数据处理等非代码项目。","newProject.field.git.branch":"合并分支","newProject.field.gitlabProject.label":"Git 远程项目路径","newProject.field.gitlabProject.help2":"如 user/repo,空则跳过远程 API(只本地 commit/push)","newProject.field.gitlabProject.placeholder":"user/repo","newProject.field.gitlabProjectId":"GitLab 项目 ID","newProject.field.gitlabProjectId.help":"数字;GitHub 用户留空","newProject.field.gitlabProjectId.placeholder":"42","newProject.section.notifications":"通知","newProject.field.matrixRoom.label":"Matrix 房间 ID","newProject.field.matrixRoom.help2":"空则使用全局配置;不填 = 不通知","newProject.field.matrixRoom.placeholder":"!abc:matrix.example.com","newProject.error.create.title":"创建失败","projectDetail.tab.pipeline":"流水线","projectDetail.tab.conf":"配置","projectDetail.tab.delete":"删除项目","projectDetail.delete.title":"删除该项目","projectDetail.delete.warn":"会删除项目配置、运行时和 worktree。{repoDir} 下的代码仓库不动。","projectDetail.delete.confirmLabel":"输入项目名以确认","projectDetail.delete.button":"删除项目","projectDetail.delete.deleting":"删除中…","projectDetail.lastActivity":"最后活跃","projectDetail.notFound":"项目不存在","projectDetail.notFoundHint":"可能已被删除或重命名。","projectDetail.backToList":"返回项目列表","pipeline.editor.title":"流水线 YAML","pipeline.editor.savedAt":"{time} 已保存","pipeline.editor.unsaved":"有未保存的修改","pipeline.editor.save":"保存","pipeline.editor.saving":"保存中…","pipeline.editor.reload":"从磁盘重新加载","pipeline.editor.discard.title":"放弃未保存的修改?","pipeline.editor.discard.body":"你的编辑会丢失。","pipeline.editor.errors":"YAML 解析错误","pipeline.editor.list":"流水线","pipeline.editor.list.add":"新建流水线","pipeline.editor.list.delete":"删除流水线","pipeline.editor.list.use":"设为当前","pipeline.editor.list.activeBadge":"当前","pipeline.editor.list.sample":"示例","pipeline.editor.delete.confirm.title":"删除流水线 {name}?","pipeline.editor.delete.confirm.body":"此操作不可撤销。","pipeline.newDialog.title":"新建流水线","pipeline.newDialog.field.filename":"文件名","pipeline.newDialog.field.filename.help":"只允许字母、数字、_ 和 -;自动追加 .yaml","pipeline.newDialog.field.copyFrom":"复制自","pipeline.newDialog.copyFrom.sample":"示例模板","pipeline.newDialog.copyFrom.active":"当前活动","pipeline.newDialog.create":"创建","projectDetail.tab.overview":"概览","projectDetail.tab.config":"配置","projectDetail.tab.pipelines":"流水线","projectDetail.tab.danger":"危险操作","projectDetail.openBoard":"看板","projectDetail.overview.repoDir":"仓库路径","projectDetail.overview.pmBackend":"PM 后端","projectDetail.overview.agent":"Agent","projectDetail.overview.cards":"卡片","projectDetail.overview.cards.value":"共 {total} 张 · {inprogress} 进行中 · {done} 完成","projectDetail.overview.workers":"Worker","projectDetail.overview.workers.value":"共 {total} 个({active} 活跃)","projectDetail.overview.pipeline":"Pipeline","projectDetail.overview.lastActivity":"最近活动","projectDetail.overview.notFound":"项目 {name} 不存在或无法读取。","projectDetail.config.confDirty":"● 未保存的修改","projectDetail.config.reload":"重新加载","projectDetail.config.save":"保存","projectDetail.config.saveAria":"保存配置","projectDetail.config.editorAria":"conf 文件编辑器","projectDetail.config.error.conflict.title":"配置已被其他地方修改","projectDetail.config.error.conflict.body":'conf 文件在你编辑期间被改过。点"重新加载"后再编辑。',"projectDetail.config.error.save.title":"保存失败","projectDetail.config.error.load":"加载失败:{detail}","projectDetail.pipelines.title":"流水线","projectDetail.pipelines.add":"新建流水线","projectDetail.pipelines.empty":'还没有流水线文件。点"新建流水线"开始。',"projectDetail.pipelines.activeBadge":"当前","projectDetail.pipelines.edit":"编辑","projectDetail.pipelines.editAria":"编辑 {name}","projectDetail.pipelines.switch":"切换","projectDetail.pipelines.switchAria":"切换到 {name}","projectDetail.pipelines.switch.confirm.title":"切换到 {name}","projectDetail.pipelines.switch.confirm.body":"当前 project.yaml 会被 {name} 的内容覆盖。继续?","projectDetail.pipelines.switch.confirm.button":"切换","projectDetail.pipelines.switch.error":"切换失败","projectDetail.pipelines.delete.confirm.title":"删除 {name}","projectDetail.pipelines.delete.confirm.body":"这个流水线文件会被永久删除。","projectDetail.pipelines.delete.error":"删除失败","projectDetail.pipelines.deleteAria":"删除 {name}","projectDetail.pipelines.create.error":"创建失败","projectDetail.danger.title":"删除项目","projectDetail.danger.body":"这会清理 {path}(包括所有卡片、runtime、logs)。","projectDetail.danger.includeClaude.label":"同时清理 repo 的 .claude/","projectDetail.danger.includeClaude.note":"repo 本身不动,只清这个目录。","projectDetail.danger.confirmPrompt":"输入项目名 {name} 确认:","projectDetail.danger.deleteAria":"永久删除项目","projectDetail.danger.deleteButton":"永久删除","projectDetail.danger.deleted.title":"已删除","projectDetail.danger.deleted.bodyWithList":`项目已删除。同时清理了:
|
|
456
|
+
Click to zoom`,"chat.attachment.preview.aria":"Preview {name}","chat.attachment.close.aria":"Close","chat.attachment.readErr":"Read failed: {detail}","chat.attachment.loading":"Loading…","chat.attachment.unsupported":"This file type cannot be previewed inline.","chat.attachment.download":"Download","chat.message.role.you":"You","chat.message.role.error":"Error","chat.message.role.assistant":"assistant","chat.message.truncated":"⚠ Output exceeded 10MB and was truncated","chat.filePicker.title":"Pick attachment file","chat.newSession.title":"New chat","chat.newSession.title.aria":"New chat","chat.newSession.close.aria":"Close","chat.newSession.field.agent":"Agent","chat.newSession.field.model":"Model (optional)","chat.newSession.field.model.default":"Use global default model","chat.newSession.field.title":"Title (optional)","chat.newSession.field.title.placeholder":"Empty = auto-generate from first message","chat.newSession.field.cwd":"Working directory (optional)","chat.newSession.field.cwd.browse":"Browse","chat.newSession.field.cwd.browseAria":"Pick directory","chat.newSession.field.cwd.title":"Pick directory","chat.newSession.field.cwd.help1":"The agent reads/writes files here. Absolute path; must exist.","chat.newSession.field.cwd.help2":"Empty = use the daemon’s startup cwd.","chat.newSession.cancel":"Cancel","chat.newSession.create":"Create","cardModal.editing":"⚠ Editing","cardModal.title.aria":"Card title","cardModal.editAria":"Edit card","cardModal.edit":"Edit","cardModal.close.aria":"Close","cardModal.error.save.title":"Save failed","cardModal.error.load":"Load failed: {detail}","cardModal.skills.loading":"Loading skill list…","cardModal.label.removeAria":"Remove {label}","cardModal.label.addPlaceholder":"+ Add label","cardModal.label.addAria":"Add label","cardModal.label.note":"Note: AI-PIPELINE / STARTED-* / COMPLETED-* / NEEDS-FIX are managed by the pipeline; manual changes may be overwritten","cardModal.section.description":"Description","cardModal.section.empty":"(empty)","cardModal.section.checklist":"Checklist","cardModal.checklist.empty":"No checklist items. Add `- [ ] item` syntax in the description.","cardModal.section.log":"Log","cardModal.body.aria":"Card description","cardModal.body.replaceNote":'Only replaces the "## Description" section; checklist and log sections are untouched.',"cardModal.action.launch":"Launch worker","cardModal.action.launch.disabledDone":"Card is done; drag back to Todo to launch","cardModal.action.launch.disabledRunning":"Pipeline is running — supervisor dispatches automatically, no manual launch needed","cardModal.action.launch.error":"Launch worker failed","cardModal.action.reset":"Reset card","cardModal.action.reset.confirm.title":"Reset card #{seq}","cardModal.action.reset.confirm.body":"Card state goes back to initial; checklist progress is cleared.","cardModal.action.reset.confirm.button":"Reset","cardModal.action.reset.error":"Reset failed","cardModal.action.delete":"Delete card","cardModal.action.delete.confirm1.title":"Delete card #{seq}","cardModal.action.delete.confirm1.body":'About to delete "{title}". This cannot be undone (the md file is physically removed). Continue?',"cardModal.action.delete.confirm1.button":"Continue","cardModal.action.delete.confirm2.title":"Final confirmation","cardModal.action.delete.confirm2.body":"Please re-confirm deleting card #{seq}.","projectDetail.tab.skills":"Skills","projectDetail.tab.rules":"Rules","projectDetail.skills.title":"Skill whitelist","projectDetail.skills.desc":"Pick which skills this project loads. Narrows what workers, subagents and chat see — cuts token cost.","projectDetail.skills.noPolicy":"No whitelist — all skills are available (subagents load the full set from disk).","projectDetail.skills.hasPolicy":"Whitelist active — {count} skill(s) eligible.","projectDetail.skills.save":"Save whitelist","projectDetail.skills.clear":"Clear (load all)","projectDetail.skills.saveError":"Failed to save whitelist","projectDetail.skills.applied":"Saved. Projected {linked} linked, {pruned} pruned.","projectDetail.skills.unknown":"Unknown skill name(s), ignored: {names}","projectDetail.skills.empty":"No skills installed. Run `sps skill sync` first.","projectDetail.skills.selectAll":"Select all","projectDetail.skills.selectNone":"Select none","projectDetail.rules.title":"Project rules (read-only)","projectDetail.rules.readonly":"sps-cli only reads these. Editing is done at project creation or by an agent later.","projectDetail.rules.missing":"Not present","nav.prompts":"Prompts","prompts.title":"Prompt library","prompts.desc":"Reusable prompts with {{variable}} templates. Insert them into chat.","prompts.new":"New prompt","prompts.search":"Search prompts…","prompts.empty":"No prompts yet. Create one.","prompts.name":"Name","prompts.namePlaceholder":"kebab-case, e.g. code-review","prompts.nameError":"Name must be kebab-case (a-z, 0-9, dashes).","prompts.description":"Description","prompts.tags":"Tags","prompts.tagsPlaceholder":"comma,separated","prompts.body":"Body","prompts.bodyPlaceholder":"Write your prompt. Use {{variable}} for fill-ins.","prompts.favorite":"Favorite","prompts.save":"Save","prompts.delete":"Delete","prompts.deleteConfirm":'Delete prompt "{name}"? This removes the file.',"prompts.saveError":"Failed to save prompt","prompts.vars":"Variables: {names}","prompts.noVars":"No variables","prompts.insert":"Insert a prompt","prompts.selectHint":"Select a prompt on the left, or create a new one.","prompts.tagAdd":"Type a tag, press Enter","prompts.ai":"AI generate","prompts.ai.title":"AI generate a prompt","prompts.ai.intent":"Describe what you want","prompts.ai.placeholder":"e.g. a prompt for reviewing TypeScript code for security issues","prompts.ai.submit":"Generate","prompts.ai.wait":"The agent is writing… this can take a while.","prompts.ai.error":"Generation failed","skills.import":"Import","skills.import.title":"Import a skill","skills.import.name":"Name (kebab-case)","skills.import.body":"SKILL.md content","skills.import.submit":"Import","skills.import.error":"Import failed","skills.export":"Export SKILL.md","skills.updates.badge":"{count} update(s) available","skills.updates.none":"Up to date","skills.ai":"AI create","skills.ai.title":"AI create a skill","skills.ai.name":"Name (kebab-case)","skills.ai.intent":"What is this skill for?","skills.ai.placeholder":"e.g. how to write idiomatic Rust error handling","skills.ai.submit":"Create","skills.ai.wait":"The agent is writing the skill… this can take a while.","skills.ai.error":"Create failed","projectDetail.tab.graph":"Code Graph","projectDetail.tab.logs":"Logs","graph.title":"Code Graph","graph.desc":"A symbol-level dependency graph of this project (tree-sitter, zero-token). Gives agents surgical context so they explore fewer files.","graph.build":"Build graph","graph.rebuild":"Rebuild","graph.building":"Building…","graph.sync":"Sync","graph.syncing":"Syncing…","graph.sync.desc":"Incremental — only re-index changed files (fast)","graph.empty":"No graph yet — build one to enable agent navigation and the dependency view.","graph.buildFailed":"Build failed","graph.stat.files":"Files","graph.stat.nodes":"Nodes","graph.stat.edges":"Edges","graph.stat.db":"DB size","graph.stat.lastBuilt":"Last built","graph.viz.title":"File dependency graph","graph.viz.loading":"Loading graph…","graph.viz.empty":"Build the graph to see the dependency view.","graph.viz.hint":"Node = file · edge = import · drag to explore · search to highlight","graph.viz.search":"Highlight files…"},k3={"app.title":"SPS 控制台","nav.chat":"对话","nav.projects":"项目","nav.board":"看板","nav.workers":"Workers","nav.logs":"日志","nav.skills":"技能","nav.system":"系统","nav.processes":"进程","nav.audit":"审计日志","nav.memory":"记忆","nav.plugins":"插件","plugins.h1":"插件 🧩","plugins.desc":"全局插件开关。改动对之后新派发的卡生效。","plugins.tab.memory":"记忆","plugins.tab.channel":"频道","plugins.tab.model":"模型","plugins.tab.tool":"工具","plugins.comingSoon":"即将上线","plugins.model.title":"智能体模型","plugins.model.desc":"配置两个智能体的模型(全局)。worker=claude 执行、review·designer=openai 监工+编排。","plugins.model.worker":"Worker(执行 / claude)","plugins.model.reviewer":"Review·Designer(监工 / openai)","plugins.model.provider":"Provider","plugins.model.model":"模型","plugins.model.official":"官方 claude(默认)","plugins.model.save":"保存","plugins.model.saved":"已保存","plugins.model.error":"保存失败","nav.arrange":"编排","arrange.h1":"智能编排 🧭","arrange.project":"项目","arrange.none":"尚未开始 — 点上方「启动」拉起编排(几秒后出任务清单,确认即跑)。若下拉无项目,先在「新建项目」选智能编排模式。","arrange.start":"启动","arrange.stop":"停止","arrange.startErr":"启动/停止失败","arrange.view":"切换画板视图","arrange.viewFree":"自由","arrange.viewLane":"泳道","arrange.starting":"启动中,正在拆解任务清单…","arrange.planning":"正在拆解任务清单…","arrange.orchestrating":"正在编排中…","arrange.status":"状态","arrange.goal":"目标","arrange.plan":"任务清单 + 卡链路","arrange.approve":"确认任务清单","arrange.approveErr":"确认失败","arrange.tasks":"任务清单","arrange.collapse":"收起","arrange.expand":"展开任务清单","arrange.noCards":"暂无卡片 — 等待 orchestrator 派卡(确认清单后开始)。","arrange.cardPrompt":"卡片提示词","arrange.cardSkills":"技能","arrange.cardTask":"所属任务","arrange.cardLog":"日志","arrange.close":"关闭","arrange.cardsCount":"张卡","nav.aria":"主导航","memory.sub":"跨项目记忆 · 经 console 鉴权代理 agentmemory","memory.searchPlaceholder":"搜索记忆…(如:三消美术竞态怎么修)","memory.search":"搜索","memory.results":"召回结果","memory.rawHint":"(原始观察 · 接入实时捕获+压缩后这里会显示提炼的教训)","memory.sessions":"最近会话","memory.empty":"暂无记忆 · 接入实时捕获(P1)后自动累积","processes.title":"进程监控","processes.subtitle":"SPS ACP 启动的 claude 进程(其它途径启动的,如你自己的会话,不显示)","processes.refresh":"刷新","processes.aliveCount":"运行中 {n}","processes.col.kind":"类型","processes.col.slot":"会话槽","processes.col.project":"项目","processes.col.state":"状态","processes.col.memory":"内存","processes.col.action":"操作","processes.empty":"没有 SPS 进程","processes.filter.all":"全部","processes.filter.alive":"运行中","processes.filter.offline":"离线","processes.kind.all":"全部类型","processes.kind.worker":"构建 Worker","processes.kind.chat":"对话","processes.kill":"关闭","processes.killConfirm":"确定关闭进程 {slot}?","audit.title":"审计日志","audit.subtitle":"项目生命周期:创建 / 修改 / 删除","audit.refresh":"刷新","audit.filter.all":"全部","audit.action.create":"创建","audit.action.modify":"修改","audit.action.delete":"删除","audit.action.daemon":"Daemon","audit.col.time":"时间","audit.col.action":"动作","audit.col.project":"项目","audit.col.detail":"详情","audit.empty":"暂无审计记录","lang.toggle.aria":"切换界面语言","lang.en":"EN","lang.zh":"中","status.server":"服务","status.offline":"离线","status.sse.open":"SSE","status.sse.connecting":"SSE·连接中","status.sse.down":"SSE·断开","status.pipelines.tooltip":"活跃流水线数","status.workers.tooltip":"活跃 Worker 数","status.pipeline.unit":"流水线","status.worker.unit":"Worker","common.save":"保存","common.cancel":"取消","common.delete":"删除","common.confirm":"确认","common.create":"创建","common.edit":"编辑","common.close":"关闭","common.loading":"加载中…","common.error":"出错","common.retry":"重试","common.empty":"暂无内容","common.search":"搜索","common.refresh":"刷新","common.copy":"复制","common.copied":"已复制","common.yes":"是","common.no":"否","common.required":"必填","common.optional":"可选","common.ok":"好","projects.title":"项目 🎯","projects.count":"本机有 {count} 个项目","projects.refresh.hint":"点击刷新重试","projects.new":"新建项目","projects.selectHint":"在左侧选择一个项目查看详情。","projects.sort.label":"排序方式","projects.sort.activity":"活跃度","projects.sort.date":"修改日期","projects.sort.name":"名字","projects.load.failed":"加载失败","projects.empty.title":"还没有项目 ✨","projects.empty.hint":"运行 {cmd} 创建第一个项目。","newProject.title":"新建项目","newProject.subtitle":"配置一个项目,worker 自动开跑","newProject.field.mode":"执行模式","newProject.field.mode.pipeline":"自动工作流","newProject.field.mode.pipelineDesc":"固定阶段流水线,claude worker 按卡执行","newProject.field.mode.smart":"智能编排","newProject.field.mode.smartDesc":"OpenAI 监工动态派卡 + claude worker 执行","newProject.field.mode.pipelineHint":"传统模式:你建卡片,worker 按阶段跑。","newProject.field.mode.smartHint":"给一个总目标,OpenAI 监工每轮探查产物、动态生成任务卡、驱动 claude 完成。","newProject.field.goal":"总目标 (GOAL.md)","newProject.field.goal.hint":"写入 docs/GOAL.md;智能编排据此拆任务清单。缺失则 tick 跳过该项目。","newProject.field.goal.placeholder":"例:做一个纯前端、单文件可运行的贪吃蛇网页小游戏…","newProject.field.name":"项目名","newProject.field.name.help":"只允许小写字母、数字、_ 和 -","newProject.field.dir":"项目目录","newProject.field.dir.preview":"项目将创建在 →","newProject.field.dir.help":"绝对路径;不存在会自动创建","newProject.field.branch":"合并目标分支","newProject.field.branch.help":"默认 main","newProject.field.maxWorkers":"最大并发 Worker 数","newProject.field.maxWorkers.help":"单项目并发数(推荐 1)","newProject.field.ackTimeout":"ACK 超时(秒)","newProject.field.ackTimeout.help":"Worker 响应等待秒数(默认 300)","newProject.field.gitlabProject":"GitLab/GitHub 远程","newProject.field.gitlabProject.help":"格式:用户名/仓库(可选)","newProject.field.matrixRoom":"Matrix 房间 ID","newProject.field.matrixRoom.help":"可选;不填则用全局默认","newProject.field.git":"启用 git","newProject.field.git.help":"关闭 → 非代码项目,跳过 commit/push/MR","newProject.submit":"创建项目","newProject.creating":"创建中…","newProject.created":"项目已创建","newProject.error.dirRequired":"项目目录必填","newProject.dir.browse":"浏览","newProject.dir.browseAria":"选择目录","newProject.back":"返回","newProject.back.aria":"返回项目列表","newProject.field.name.placeholder":"例如:acme-web","newProject.field.name.example":"只能用字母、数字、下划线、连字符。例如 acme-web","newProject.field.name.invalid":"名称只能包含 a-z A-Z 0-9 _ -","newProject.field.dir.long":"本机绝对路径的【项目目录】。选中的目录本身就是项目根;项目名默认取目录名。已有代码 → 收编(只加 .claude/ 配置,不动源码);空目录 → 新建。","newProject.field.dir.placeholder":"/home/you/projects/my-app","newProject.field.dir.createIfMissing":"目录不存在时自动创建(推荐 —— 否则 .claude/ 安装会被跳过)","newProject.field.dir.pickerTitle":"选择项目目录","newProject.field.dir.adopt":"检测到已有内容 → 将收编(只加配置,不动源码)","newProject.field.dir.fresh":"空目录 → 新建项目","newProject.field.name.derived":"项目名(默认取目录名,可微调)","newProject.field.maxWorkers.short":"最大 Worker 数","newProject.field.ackTimeout.minutes":"ACK 超时(分钟)","newProject.field.ackTimeout.minutes.help":"Worker 启动后多久没 ACK 视为失败","newProject.field.git.label":"启用 Git(Worker 自动 commit + push)","newProject.field.git.detail":"关闭后 Worker 只做任务、不做版本控制;适合文档/数据处理等非代码项目。","newProject.field.review.label":"启用清单验收(每卡完成后独立 agent 审核)","newProject.field.review.detail":"开启后:卡带「检查清单」的,Worker 完成后由独立 reviewer 逐条对着真实产物验收;全过留 Done,有不过自动插一张修正卡(优先跑)。无清单的卡不审。建卡时用 --checklist 写验收点。","newProject.field.git.branch":"合并分支","newProject.field.gitlabProject.label":"Git 远程项目路径","newProject.field.gitlabProject.help2":"如 user/repo,空则跳过远程 API(只本地 commit/push)","newProject.field.gitlabProject.placeholder":"user/repo","newProject.field.gitlabProjectId":"GitLab 项目 ID","newProject.field.gitlabProjectId.help":"数字;GitHub 用户留空","newProject.field.gitlabProjectId.placeholder":"42","newProject.section.notifications":"通知","newProject.field.matrixRoom.label":"Matrix 房间 ID","newProject.field.matrixRoom.help2":"空则使用全局配置;不填 = 不通知","newProject.field.matrixRoom.placeholder":"!abc:matrix.example.com","newProject.error.create.title":"创建失败","projectDetail.tab.pipeline":"流水线","projectDetail.tab.conf":"配置","projectDetail.tab.delete":"删除项目","projectDetail.delete.title":"删除该项目","projectDetail.delete.warn":"会删除项目配置、运行时和 worktree。{repoDir} 下的代码仓库不动。","projectDetail.delete.confirmLabel":"输入项目名以确认","projectDetail.delete.button":"删除项目","projectDetail.delete.deleting":"删除中…","projectDetail.lastActivity":"最后活跃","projectDetail.notFound":"项目不存在","projectDetail.notFoundHint":"可能已被删除或重命名。","projectDetail.backToList":"返回项目列表","pipeline.editor.title":"流水线 YAML","pipeline.editor.savedAt":"{time} 已保存","pipeline.editor.unsaved":"有未保存的修改","pipeline.editor.save":"保存","pipeline.editor.saving":"保存中…","pipeline.editor.reload":"从磁盘重新加载","pipeline.editor.discard.title":"放弃未保存的修改?","pipeline.editor.discard.body":"你的编辑会丢失。","pipeline.editor.errors":"YAML 解析错误","pipeline.editor.list":"流水线","pipeline.editor.list.add":"新建流水线","pipeline.editor.list.delete":"删除流水线","pipeline.editor.list.use":"设为当前","pipeline.editor.list.activeBadge":"当前","pipeline.editor.list.sample":"示例","pipeline.editor.delete.confirm.title":"删除流水线 {name}?","pipeline.editor.delete.confirm.body":"此操作不可撤销。","pipeline.newDialog.title":"新建流水线","pipeline.newDialog.field.filename":"文件名","pipeline.newDialog.field.filename.help":"只允许字母、数字、_ 和 -;自动追加 .yaml","pipeline.newDialog.field.copyFrom":"复制自","pipeline.newDialog.copyFrom.sample":"示例模板","pipeline.newDialog.copyFrom.active":"当前活动","pipeline.newDialog.create":"创建","projectDetail.tab.overview":"概览","projectDetail.tab.config":"配置","projectDetail.tab.pipelines":"流水线","projectDetail.tab.danger":"危险操作","projectDetail.openBoard":"看板","projectDetail.overview.repoDir":"仓库路径","projectDetail.overview.pmBackend":"PM 后端","projectDetail.overview.agent":"Agent","projectDetail.overview.cards":"卡片","projectDetail.overview.cards.value":"共 {total} 张 · {inprogress} 进行中 · {done} 完成","projectDetail.overview.workers":"Worker","projectDetail.overview.workers.value":"共 {total} 个({active} 活跃)","projectDetail.overview.pipeline":"Pipeline","projectDetail.overview.lastActivity":"最近活动","projectDetail.overview.notFound":"项目 {name} 不存在或无法读取。","projectDetail.config.confDirty":"● 未保存的修改","projectDetail.config.reload":"重新加载","projectDetail.config.save":"保存","projectDetail.config.saveAria":"保存配置","projectDetail.config.editorAria":"conf 文件编辑器","projectDetail.config.error.conflict.title":"配置已被其他地方修改","projectDetail.config.error.conflict.body":'conf 文件在你编辑期间被改过。点"重新加载"后再编辑。',"projectDetail.config.error.save.title":"保存失败","projectDetail.config.error.load":"加载失败:{detail}","projectDetail.pipelines.title":"流水线","projectDetail.pipelines.add":"新建流水线","projectDetail.pipelines.empty":'还没有流水线文件。点"新建流水线"开始。',"projectDetail.pipelines.activeBadge":"当前","projectDetail.pipelines.edit":"编辑","projectDetail.pipelines.editAria":"编辑 {name}","projectDetail.pipelines.switch":"切换","projectDetail.pipelines.switchAria":"切换到 {name}","projectDetail.pipelines.switch.confirm.title":"切换到 {name}","projectDetail.pipelines.switch.confirm.body":"当前 project.yaml 会被 {name} 的内容覆盖。继续?","projectDetail.pipelines.switch.confirm.button":"切换","projectDetail.pipelines.switch.error":"切换失败","projectDetail.pipelines.delete.confirm.title":"删除 {name}","projectDetail.pipelines.delete.confirm.body":"这个流水线文件会被永久删除。","projectDetail.pipelines.delete.error":"删除失败","projectDetail.pipelines.deleteAria":"删除 {name}","projectDetail.pipelines.create.error":"创建失败","projectDetail.danger.title":"删除项目","projectDetail.danger.body":"这会清理 {path}(包括所有卡片、runtime、logs)。","projectDetail.danger.includeClaude.label":"同时清理 repo 的 .claude/","projectDetail.danger.includeClaude.note":"repo 本身不动,只清这个目录。","projectDetail.danger.confirmPrompt":"输入项目名 {name} 确认:","projectDetail.danger.deleteAria":"永久删除项目","projectDetail.danger.deleteButton":"永久删除","projectDetail.danger.deleted.title":"已删除","projectDetail.danger.deleted.bodyWithList":`项目已删除。同时清理了:
|
|
457
457
|
{paths}`,"projectDetail.danger.deleted.body":"项目已删除。","projectDetail.danger.error":"删除失败","pipelineEditor.close":"关闭","pipelineEditor.error.conflict.title":"文件已被其他地方修改","pipelineEditor.error.yaml.title":"YAML 语法错误","pipelineEditor.error.save.title":"保存失败","pipelineEditor.error.serialize.title":"YAML 序列化失败","pipelineEditor.error.load":"加载失败:{detail}","pipelineEditor.mode.structured":"结构化","pipelineEditor.mode.yaml":"原始 YAML","pipelineEditor.parseError.prefix":"YAML 解析:{detail}","pipelineEditor.activeWarning":"⚠ 这是当前激活的流水线,保存后下一轮 tick 生效","pipelineEditor.yamlAria":"pipeline YAML 编辑器","pipelineEditor.status.unsaved":"● 未保存","pipelineEditor.status.saved":"已保存","pipelineEditor.status.noChanges":"无变化","pipelineEditor.reload":"重新加载","pipelineEditor.save":"保存","pipelineEditor.saveAria":"保存 pipeline","pipelineEditor.activeBadge":"当前","pipelineEditor.modeHint":"project = 事件驱动流水线(默认) · steps = 顺序脚本","pipelineEditor.stages.heading":"Stages({count})","pipelineEditor.stages.add":"添加 stage","pipelineEditor.stages.empty":'还没 stage。点"添加 stage"开始。',"pipelineEditor.stage.name.hint":"stage 唯一名","pipelineEditor.stage.profile.hint":"skill 画像,可空","pipelineEditor.stage.cardState.hint":"本 stage 期间卡片状态","pipelineEditor.stage.timeout.hint":"可选,如 30m 2h","pipelineEditor.stage.trigger.hint":"触发条件,可空走默认","pipelineEditor.stage.onComplete.hint":"成功后动作","pipelineEditor.stage.onFail.action.hint":"失败时动作,如 label NEEDS-FIX","pipelineEditor.stage.onFail.comment.hint":"写进卡片的注释","pipelineEditor.stage.halt.note":"(失败后停流水线;去掉则继续下一张卡)","pipelineEditor.stage.moveUp":"上移","pipelineEditor.stage.moveDown":"下移","pipelineEditor.stage.remove":"删除 stage","newPipelineDialog.title":"新建流水线","newPipelineDialog.field.filename.label":"文件名","newPipelineDialog.field.filename.placeholder":"例如 ci","newPipelineDialog.field.filename.help":"实际会保存为 {filename}。只允许 a-z A-Z 0-9 _ -;已有同名文件会 409 报错。","newPipelineDialog.section.template":"初始内容","newPipelineDialog.template.blank.label":"空白模板","newPipelineDialog.template.blank.desc":"最简 1 stage(develop → Done)","newPipelineDialog.template.sample.label":"教学模板","newPipelineDialog.template.sample.desc":"从 sample.yaml.example 复制(带注释,讲解所有字段)","newPipelineDialog.template.sample.unavailable":"sample.yaml.example 不存在","newPipelineDialog.template.active.label":"复制当前活动的","newPipelineDialog.template.active.desc":"从 project.yaml 复制(基于目前的配置改)","newPipelineDialog.template.active.unavailable":"project.yaml 不存在","newPipelineDialog.create.aria":"创建 pipeline","newPipelineDialog.cancel":"取消","board.title":"看板 ✨","board.title.bare":"看板","board.subtitle":"{name} · {cards} 张卡片 · {workers} workers 活跃","board.pickPrompt.title":"选择一个项目 🎯","board.pickPrompt.body":"看板按项目分。挑一个开始:","board.action.start":"启动","board.action.stop":"停止","board.action.startAria":"启动 pipeline","board.action.stopAria":"停止 pipeline","board.action.startError":"启动 pipeline 失败","board.action.stopError":"停止 pipeline 失败","board.action.reset":"重置","board.action.resetError":"重置失败","board.action.reset.confirm.title":"重置整个流水线","board.action.reset.confirm.body":"这会清空所有卡片的运行状态、worker marker、分支。不可撤销。","board.action.reset.confirm.button":"重置全部","board.action.newCard":"新卡片","board.action.newCard.error":"新建卡片失败","board.action.moveCard.error":"移动卡片失败","board.search.placeholder":"搜索标题 / skill / label…","board.search.aria":"搜索卡片","board.filter.clear":"清空","board.filter.clearAria":"清空筛选","board.filter.aria":"按 {label} 筛选","board.filter.clearSelection":"清空选择","board.error.loadCards":"加载卡片失败","board.col.planning":"Planning","board.col.backlog":"Backlog","board.col.todo":"Todo","board.col.inprogress":"Inprogress","board.col.qa":"QA / Review","board.col.done":"Done","kanban.checklist.label":"检查清单 {done}/{total}","kanban.checklist.more":"… 还有 {count} 条","kanban.column.empty":"— 空 —","kanban.time.justNow":"刚才","kanban.time.minutes":"{n} 分钟前","kanban.time.hours":"{n} 小时前","kanban.time.days":"{n} 天前","newCard.title":"新建卡片","newCard.field.title":"标题 *","newCard.field.title.placeholder":"例如:接入 GitHub OAuth 登录","newCard.field.title.help":"写简短明了的目标(<200 字符)","newCard.field.description":"描述","newCard.field.description.placeholder":"用户故事、需求、验收标准、参考资料… Claude 启动时会读这里的内容","newCard.field.description.help":"支持 markdown。空的话就只有 title,Claude 只能靠 title 推断要做啥。","newCard.field.skills":"技能","newCard.field.skills.help":"勾选哪些 skill 会被加载(走 frontmatter `skills:`)。不选也行,Worker 默认加载项目级 skills。","newCard.field.skills.loading":"加载 skill 列表…","newCard.field.skills.error":"skill 列表加载失败,不影响创建:{detail}","newCard.field.skills.selected":"已选 {count} 个:{names}","newCard.field.dispatch":"派发","newCard.field.dispatch.label":"立即派发执行(直接进 Backlog)","newCard.field.dispatch.help":"默认不勾:卡进 Planning 暂存,等你看板上拖到 Backlog 再开工。勾上:跳过暂存,下次 tick 直接派 worker 跑。","newCard.create.aria":"创建卡片","cardDetail.loading":"加载中…","cardDetail.error.load":"卡片加载失败","cardDetail.tabs.overview":"概览","cardDetail.tabs.body":"描述","cardDetail.tabs.checklist":"检查清单","cardDetail.tabs.history":"历史","cardDetail.tabs.actions":"操作","cardDetail.field.state":"状态","cardDetail.field.skills":"技能","cardDetail.field.labels":"标签","cardDetail.field.branch":"分支","cardDetail.field.assignee":"处理人","cardDetail.field.created":"创建时间","cardDetail.field.updated":"更新时间","cardDetail.field.empty":"—","cardDetail.actions.delete":"删除卡片","cardDetail.actions.delete.confirm.title":"删除卡片 #{seq}","cardDetail.actions.delete.confirm.body":"该卡片会被永久删除。","cardDetail.actions.delete.error":"删除失败","cardDetail.actions.update.error":"更新失败","cardDetail.body.empty":"没有描述","cardDetail.checklist.empty":"没有检查清单","cardDetail.checklist.progress":"进度 {done}/{total}","cardDetail.history.empty":"没有历史记录","cardDetail.notFound":"卡片 #{seq} 不存在","cardDetail.copy.aria":"复制 seq","cardDetail.close.aria":"关闭","cardDetail.save":"保存","cardDetail.saving":"保存中…","workers.title":"Workers 👷","workers.summary":"跨 {projects} 项目 · {running} 跑 · {starting} 启动 · {stuck} 卡 · {crashed} 崩 · {idle} 闲","workers.summary.stuck":"{n} 卡","workers.summary.crashed":"{n} 崩","workers.refresh.aria":"刷新","workers.refresh":"刷新","workers.error.load":"加载失败:{detail}","workers.empty.hint":"点击项目 / worker 查看详情","logs.title":"日志 📜","logs.subtitle.allProjects":"全部项目","logs.subtitle.project":"{name} 实时日志","logs.filter.errors":"只看错误","logs.filter.errors.aria":"只显示错误","logs.filter.search.placeholder":"过滤消息…","logs.empty":"还没有日志 —— 等待事件中","logs.error.load":"日志加载失败","logs.refresh":"刷新","logs.refresh.aria":"刷新日志","logs.scroll.bottom.aria":"滚动到底部","logs.scroll.pause":"已暂停(自动滚动关闭)","logs.scroll.resume":"恢复自动滚动","logs.subtitle.allProjectsCount":"全部项目({count})","logs.poll.5s":"5s 轮询","logs.paused":"⏸ 已暂停","logs.mode.live":"实时","logs.mode.history":"历史","logs.history.startAria":"查询起始时间","logs.history.queryAria":"查询","logs.history.query":"查询","logs.filter.project.aria":"筛选项目","logs.filter.project.all":"全部项目","logs.filter.keyword.placeholder":"过滤关键字…","logs.filter.keyword.aria":"过滤日志","logs.empty.match":"没有匹配的日志","skills.title":"技能 🧠","skills.subtitle":"跨项目共用的 skill(用 `sps skill ...` 管理)","skills.empty.title":"还没有 skill","skills.empty.hint":"运行 {cmd} 同步 bundled skills。","skills.linked.tooltip":"已链接到该项目","skills.frozen.tooltip":"已冻结(项目独立副本)","skills.category.all":"全部","skills.category.language":"语言","skills.category.end":"终端","skills.category.persona":"角色","skills.category.workflow":"流程","skills.category.other":"其它","skills.subtitleCount":"{count} 个 user-level skill","skills.search.placeholder":"搜索 skill…","skills.search.aria":"搜索 skill","skillDetail.actionFailed":"{label}失败","skillDetail.unfreezeAction":"解冻","skillDetail.freezeAction":"冻结","skillDetail.removeAction":"移除","skillDetail.removeConfirm.title":"从 {project} 移除 {name}","skillDetail.removeConfirm.body":"skill 链接会被解除,项目后续运行时将无法使用该 skill。","skillDetail.removeConfirm.button":"移除","skillDetail.unfreezeConfirm.title":"解冻 {name} @ {project}","skillDetail.unfreezeConfirm.body":"本地对这个 skill 的改动会被覆盖,回到最新共享版本。","skillDetail.unfreezeConfirm.button":"解冻","skillDetail.close.aria":"关闭","skillDetail.loading":"加载中…","skillDetail.error.load":"加载失败:{detail}","skillDetail.section.projects":"项目链接状态","skillDetail.section.empty":"还没有任何项目。先去创建一个项目。","skillDetail.section.preview":"SKILL.md 预览","skillDetail.toggleSection.aria":"{action} {file}","skillDetail.expand":"展开","skillDetail.collapse":"收起","system.title":"系统 🛠","system.subtitle":"全局配置 + 诊断 + 升级","system.section.env":"全局 env","system.section.env.help":"存储在 ~/.coral/env(mode 600)。所有项目共用。","system.section.env.save":"保存 env","system.section.env.error.conflict":"env 已被其它地方修改","system.section.env.error.save":"保存 env 失败","system.section.env.error.load":"加载 env 失败","system.section.env.dirtyDot":"● 未保存","system.section.env.aria":"env 编辑器","system.section.env.reload":"重新加载","system.section.upgrade":"升级","system.section.upgrade.current":"当前:v{version}","system.section.upgrade.latest":"npm 最新:v{version}","system.section.upgrade.uptodate":"已是最新","system.section.upgrade.update":"立即升级","system.section.upgrade.upgrading":"升级中…","system.section.upgrade.checking":"正在查询 npm…","system.section.upgrade.checkError":"查询失败:{detail}","system.section.upgrade.upgradeError":"升级失败:{detail}","system.section.upgrade.upgradeError.title":"升级失败","system.section.upgrade.command":"或在终端执行:{cmd}","system.section.upgrade.runningPipelines":"有 pipeline 在跑,先停止:{projects}","system.section.diagnostics":"诊断","system.section.diagnostics.help":"一次性跑所有项目的 sps doctor,看哪些项目出问题","system.section.diagnostics.run":"运行诊断","system.section.diagnostics.running":"运行中…","system.section.diagnostics.empty":"没有项目","system.section.diagnostics.checkAria":"检查 {project}","system.section.diagnostics.statusOk":"正常","system.section.diagnostics.statusFail":"有问题","system.section.diagnostics.error":"诊断失败:{detail}","system.h1":"系统 ⚙️","system.runtime":"运行时","system.memory.title":"记忆后端","system.memory.desc":"全局设置:worker 的记忆读写走哪个后端。改动对新派发的卡生效。","system.memory.provider":"后端","system.memory.url":"自定义 URL","system.memory.url.placeholder":"http://127.0.0.1:3111","system.memory.save":"保存","system.memory.save.aria":"保存记忆后端设置","system.memory.saved":"已保存","system.memory.error":"保存失败","system.memory.opt.none":"关闭(none)","system.memory.opt.builtin":"本地文件记忆(builtin)","system.memory.opt.agentmemory":"agentmemory(语义库)","system.memory.opt.custom":"自定义 REST(custom)","system.env.title.code":"~/.coral/env","system.env.title.prefix":"全局配置 ","system.env.edit.aria":"编辑 env 文件","system.env.edit.button":"编辑","system.env.editing.label":"⚠ 编辑模式","system.env.empty.before":'env 文件不存在。点"编辑"或者终端运行 ',"system.env.empty.after":"。","system.env.warning":"⚠ 文件包含凭证明文。保存时保持 0600 权限。","system.env.aria":"env 文件编辑器","system.env.dirtyMark":" · ● 未保存","system.env.cancel":"取消","system.env.save":"保存","system.env.save.aria":"保存 env","system.env.error.conflict.title":"env 被其他地方修改了","system.env.error.save.title":"保存失败","system.env.error.conflict.body":"请点取消后重开编辑。","system.upgrade.title":"版本","system.upgrade.checkLatest.aria":"检查最新版本","system.upgrade.checkUpdate":"检查更新","system.upgrade.label.current":"sps-cli(当前)","system.upgrade.label.latest":"npm(最新)","system.upgrade.latestPill":"最新","system.upgrade.button.upgradeAria":"升级到最新版本","system.upgrade.button.upgrade":"升级","system.upgrade.button.copyAria":"复制升级命令","system.upgrade.button.copyTitle":"自动升级失败时手动跑","system.upgrade.button.copy":"复制命令","system.upgrade.label.installed":"已安装","system.upgrade.installed.ok":"已生效(重启 console 后可见)","system.upgrade.installed.fail":"未升级成功","system.upgrade.label.check":"检查","system.upgrade.confirm.title":"升级 sps-cli","system.upgrade.confirm.body":"当前 {current},升级到 {latest}。要求所有 pipeline 已停止。升级后请重启 sps console 生效。","system.upgrade.confirm.button":"升级","system.upgrade.success.title":"升级完成","system.upgrade.success.body":'装上了 v{version}。请 `pkill -f "sps console"` 再重启以生效。',"system.upgrade.notEffective.title":"升级未生效","system.upgrade.notEffective.same":"npm 执行完毕但版本没变(仍 {version})——多半是权限或 registry 问题。可复制下面的命令在终端手动跑。","system.upgrade.notEffective.notInstalled":"npm 没装上新版本。可复制命令手动跑,或看下面日志定位。","system.upgrade.error.title":"升级失败","system.upgrade.copy.success.title":"命令已复制","system.upgrade.copy.success.body":`粘贴到终端运行即可:
|
|
458
458
|
{cmd}`,"system.upgrade.copy.fail.title":"复制失败","system.upgrade.copy.fail.body":`请手动复制:
|
|
459
459
|
{cmd}`,"system.diagnostics.title":"项目健康检查","system.diagnostics.checkAll":"检查全部","system.diagnostics.empty":"还没有项目。","system.diagnostics.expandAria":"展开","system.diagnostics.collapseAria":"折叠","system.diagnostics.never":'点 "检查" 运行 sps doctor',"system.diagnostics.checkAria":"检查","system.diagnostics.check":"检查","system.diagnostics.noFixesNeeded":"已无可修问题","system.diagnostics.fix.tip":"调 sps doctor <proj> --fix:自动创建 .claude/hooks/stop.sh、state.json 等","system.diagnostics.fixAria":"自动修复","system.diagnostics.fix":"修复","system.diagnostics.fixed":"已修复","system.diagnostics.error.fix":"doctor 修复失败","system.diagnostics.error.check":"doctor 检查失败","chat.title":"对话 💬","chat.empty.title":"对话 💬","chat.empty.hint":'点左上角"新建对话"开始一个 session。或直接在下方输入,会自动建 session。',"chat.empty.shortcuts":"Enter 发送 · Shift+Enter 换行 · 内容流式返回","chat.list.heading":"历史 {count}","chat.list.new":"新建对话","chat.list.empty":"还没对话。点上面新建。","chat.list.delete.aria":"删除对话","chat.list.deleteCli.aria":"从 Console 移除该 CLI 会话(不影响 Claude jsonl 存档)","chat.list.openAria":"打开对话 {title}{cwd}","chat.list.cwdSuffix":"(工作目录 {cwd})","chat.list.msgs":"{count} 条 · {time}","chat.list.olderToggle":"更早 · {count} 条","chat.detail.model.tooltip":"当前使用的模型","chat.detail.claudeSession.tooltip":"底层 claude 会话 id —— 恢复会话与记忆的锚","chat.delete.confirm.title":"删除对话","chat.delete.confirm.body.cli":"会从 Console 列表移除(停 daemon 会话)。Claude CLI 在 ~/.claude/projects 下的对话存档会保留 —— 想恢复到终端继续聊就重新跑 sps agent --chat --name <名>。","chat.delete.confirm.body.console":"对话记录会永久删除,不可恢复。","chat.delete.confirm.button":"删除","chat.cli.banner.bold":"CLI 会话","chat.cli.banner":"这是 CLI 会话(由 sps agent 创建),Console 仅展示历史。续聊请在终端运行:","chat.input.placeholder":"说点什么… (Enter 发送,Shift+Enter 换行,可拖入文件 / 粘贴图片)","chat.input.dragOver":"松开鼠标以附加文件…","chat.input.aria":"消息输入","chat.input.attach.aria":"附加本地文件","chat.input.attach.title":"附加本地文件(也可拖拽 / 粘贴图片)","chat.input.send":"发送","chat.input.send.aria":"发送","chat.input.interrupt":"中断","chat.input.interrupt.aria":"中断生成","chat.input.uploading":"上传中…","chat.input.removeAttachment":"移除 {name}","chat.error.interrupt.title":"中断失败","chat.cliBadge":"CLI","chat.cliBadge.tooltip":"该会话由 sps agent CLI 创建,从 Claude jsonl 实时读取(只读)","chat.session.title":"{title}","chat.session.id":"{id}","chat.session.empty":"下方输入问题开始对话 · Enter 发送 · Shift+Enter 换行","notFound.title":"404","notFound.body":"这个页面不存在。","notFound.home":"回到首页","workers.active.empty":"没有 worker 在运行。","workers.alerts.allHealthy":"全部 worker 健康","workers.alerts.pidDead":"PID 已死。","workers.alerts.markerStale":"marker 停 {ago}。","workers.capacity.col.project":"项目","workers.capacity.col.usage":"占用","workers.capacity.col.other":"其它","workers.capacity.detailHint":"详情 →","workers.panel.boardLink":"看板 →","workers.panel.loading":"加载 workers…","workers.panel.empty.slots":"该项目没有 worker slot。","workers.panel.empty.noWorker":"无 worker","workers.panel.empty.pickOne":"请选择一个 worker","workers.panel.idle.short":"空闲","workers.panel.section.currentCard":"当前卡片","workers.panel.idle.full":"slot 空闲,没有当前卡片。","workers.panel.section.claudeOutput":"Claude 输出 · 最近 {n} 行","workers.panel.output.loading":"加载中…","workers.panel.output.empty":"还没收到 session 输出。Worker 刚启动时需要几秒。","workers.panel.section.heartbeat":"Supervisor 心跳 · 最近 {n} 行","workers.panel.heartbeat.fullLog":"查看完整 log →","workers.panel.action.restart":"重启","workers.panel.action.restart.confirm.title":"重启 worker-{slot}","workers.panel.action.restart.confirm.body":"先杀进程,再重新 launch 到 #{seq}","workers.panel.action.restart.confirm.button":"重启","workers.panel.action.restart.error":"重启失败","workers.panel.action.kill":"终止","workers.panel.action.kill.confirm.title":"终止 worker-{slot}","workers.panel.action.kill.confirm.body":"当前任务强制中断。","workers.panel.action.kill.confirm.button":"终止","workers.panel.action.kill.error":"终止失败","dialog.confirm.default":"确定","dialog.alert.default":"知道了","dialog.cancel.default":"取消","dirPicker.title.default":"选择目录","dirPicker.close.aria":"关闭","dirPicker.up.aria":"上级目录","dirPicker.up.title":"上级目录","dirPicker.home.aria":"回到 Home","dirPicker.home.title":"回到 Home","dirPicker.loading":"加载中...","dirPicker.error.title":"读取失败","dirPicker.empty":"— 空目录 —","dirPicker.enter.aria":"进入 {name}/","dirPicker.pickFile.aria":"选择 {name}(双击直接确认)","dirPicker.fileLocked":"文件不可选","dirPicker.cancel":"取消","dirPicker.useFile":"使用此文件","dirPicker.useFile.tooltip.empty":"请先点选一个文件","dirPicker.useDir":"选此目录","dirPicker.newDir":"新建目录","dirPicker.newDir.aria":"在当前目录下新建子目录","dirPicker.newDir.prompt":"新目录名(仅字母数字 _ . -)","dirPicker.newDir.placeholder":"目录名","dirPicker.newDir.create":"创建","dirPicker.newDir.error.title":"新建目录失败","errorBoundary.title":"💥 UI 崩了","errorBoundary.refresh":"刷新页面","chat.error.create.title":"新建对话失败","chat.error.send.title":"发送失败","chat.error.fileTooBig.title":"文件超过上限","chat.error.fileTooBig.body":"单文件上限 50 MB;当前 {size} MB({name})","chat.error.uploadAttachment.title":"附件上传失败","chat.placeholder.attachment":"(附件)","chat.placeholder.viewAttachment":"(请查看附件)","chat.placeholder.attachmentTitle":"附件","chat.attachment.previewTooltip":`{name}
|
|
@@ -599,7 +599,7 @@ ${n.comment}`:n.comment}this.doc.range[2]=n.offset;break}default:this.errors.pus
|
|
|
599
599
|
`,n)+1}yield*this.pop();break;default:yield*this.pop(),yield*this.step()}}*blockMap(t){var r;const n=t.items[t.items.length-1];switch(this.type){case"newline":if(this.onKeyLine=!1,n.value){const a="end"in n.value?n.value.end:void 0,o=Array.isArray(a)?a[a.length-1]:void 0;(o==null?void 0:o.type)==="comment"?a==null||a.push(this.sourceToken):t.items.push({start:[this.sourceToken]})}else n.sep?n.sep.push(this.sourceToken):n.start.push(this.sourceToken);return;case"space":case"comment":if(n.value)t.items.push({start:[this.sourceToken]});else if(n.sep)n.sep.push(this.sourceToken);else{if(this.atIndentedComment(n.start,t.indent)){const a=t.items[t.items.length-2],o=(r=a==null?void 0:a.value)==null?void 0:r.end;if(Array.isArray(o)){Array.prototype.push.apply(o,n.start),o.push(this.sourceToken),t.items.pop();return}}n.start.push(this.sourceToken)}return}if(this.indent>=t.indent){const a=!this.onKeyLine&&this.indent===t.indent,o=a&&(n.sep||n.explicitKey)&&this.type!=="seq-item-ind";let l=[];if(o&&n.sep&&!n.value){const d=[];for(let f=0;f<n.sep.length;++f){const h=n.sep[f];switch(h.type){case"newline":d.push(f);break;case"space":break;case"comment":h.indent>t.indent&&(d.length=0);break;default:d.length=0}}d.length>=2&&(l=n.sep.splice(d[1]))}switch(this.type){case"anchor":case"tag":o||n.value?(l.push(this.sourceToken),t.items.push({start:l}),this.onKeyLine=!0):n.sep?n.sep.push(this.sourceToken):n.start.push(this.sourceToken);return;case"explicit-key-ind":!n.sep&&!n.explicitKey?(n.start.push(this.sourceToken),n.explicitKey=!0):o||n.value?(l.push(this.sourceToken),t.items.push({start:l,explicitKey:!0})):this.stack.push({type:"block-map",offset:this.offset,indent:this.indent,items:[{start:[this.sourceToken],explicitKey:!0}]}),this.onKeyLine=!0;return;case"map-value-ind":if(n.explicitKey)if(n.sep)if(n.value)t.items.push({start:[],key:null,sep:[this.sourceToken]});else if(os(n.sep,"map-value-ind"))this.stack.push({type:"block-map",offset:this.offset,indent:this.indent,items:[{start:l,key:null,sep:[this.sourceToken]}]});else if(i2(n.key)&&!os(n.sep,"newline")){const d=ol(n.start),f=n.key,h=n.sep;h.push(this.sourceToken),delete n.key,delete n.sep,this.stack.push({type:"block-map",offset:this.offset,indent:this.indent,items:[{start:d,key:f,sep:h}]})}else l.length>0?n.sep=n.sep.concat(l,this.sourceToken):n.sep.push(this.sourceToken);else if(os(n.start,"newline"))Object.assign(n,{key:null,sep:[this.sourceToken]});else{const d=ol(n.start);this.stack.push({type:"block-map",offset:this.offset,indent:this.indent,items:[{start:d,key:null,sep:[this.sourceToken]}]})}else n.sep?n.value||o?t.items.push({start:l,key:null,sep:[this.sourceToken]}):os(n.sep,"map-value-ind")?this.stack.push({type:"block-map",offset:this.offset,indent:this.indent,items:[{start:[],key:null,sep:[this.sourceToken]}]}):n.sep.push(this.sourceToken):Object.assign(n,{key:null,sep:[this.sourceToken]});this.onKeyLine=!0;return;case"alias":case"scalar":case"single-quoted-scalar":case"double-quoted-scalar":{const d=this.flowScalar(this.type);o||n.value?(t.items.push({start:l,key:d,sep:[]}),this.onKeyLine=!0):n.sep?this.stack.push(d):(Object.assign(n,{key:d,sep:[]}),this.onKeyLine=!0);return}default:{const d=this.startBlockValue(t);if(d){if(d.type==="block-seq"){if(!n.explicitKey&&n.sep&&!os(n.sep,"newline")){yield*this.pop({type:"error",offset:this.offset,message:"Unexpected block-seq-ind on same line with key",source:this.source});return}}else a&&t.items.push({start:l});this.stack.push(d);return}}}}yield*this.pop(),yield*this.step()}*blockSequence(t){var r;const n=t.items[t.items.length-1];switch(this.type){case"newline":if(n.value){const a="end"in n.value?n.value.end:void 0,o=Array.isArray(a)?a[a.length-1]:void 0;(o==null?void 0:o.type)==="comment"?a==null||a.push(this.sourceToken):t.items.push({start:[this.sourceToken]})}else n.start.push(this.sourceToken);return;case"space":case"comment":if(n.value)t.items.push({start:[this.sourceToken]});else{if(this.atIndentedComment(n.start,t.indent)){const a=t.items[t.items.length-2],o=(r=a==null?void 0:a.value)==null?void 0:r.end;if(Array.isArray(o)){Array.prototype.push.apply(o,n.start),o.push(this.sourceToken),t.items.pop();return}}n.start.push(this.sourceToken)}return;case"anchor":case"tag":if(n.value||this.indent<=t.indent)break;n.start.push(this.sourceToken);return;case"seq-item-ind":if(this.indent!==t.indent)break;n.value||os(n.start,"seq-item-ind")?t.items.push({start:[this.sourceToken]}):n.start.push(this.sourceToken);return}if(this.indent>t.indent){const a=this.startBlockValue(t);if(a){this.stack.push(a);return}}yield*this.pop(),yield*this.step()}*flowCollection(t){const n=t.items[t.items.length-1];if(this.type==="flow-error-end"){let r;do yield*this.pop(),r=this.peek(1);while((r==null?void 0:r.type)==="flow-collection")}else if(t.end.length===0){switch(this.type){case"comma":case"explicit-key-ind":!n||n.sep?t.items.push({start:[this.sourceToken]}):n.start.push(this.sourceToken);return;case"map-value-ind":!n||n.value?t.items.push({start:[],key:null,sep:[this.sourceToken]}):n.sep?n.sep.push(this.sourceToken):Object.assign(n,{key:null,sep:[this.sourceToken]});return;case"space":case"comment":case"newline":case"anchor":case"tag":!n||n.value?t.items.push({start:[this.sourceToken]}):n.sep?n.sep.push(this.sourceToken):n.start.push(this.sourceToken);return;case"alias":case"scalar":case"single-quoted-scalar":case"double-quoted-scalar":{const a=this.flowScalar(this.type);!n||n.value?t.items.push({start:[],key:a,sep:[]}):n.sep?this.stack.push(a):Object.assign(n,{key:a,sep:[]});return}case"flow-map-end":case"flow-seq-end":t.end.push(this.sourceToken);return}const r=this.startBlockValue(t);r?this.stack.push(r):(yield*this.pop(),yield*this.step())}else{const r=this.peek(2);if(r.type==="block-map"&&(this.type==="map-value-ind"&&r.indent===t.indent||this.type==="newline"&&!r.items[r.items.length-1].sep))yield*this.pop(),yield*this.step();else if(this.type==="map-value-ind"&&r.type!=="flow-collection"){const a=jf(r),o=ol(a);kk(t);const l=t.end.splice(1,t.end.length);l.push(this.sourceToken);const d={type:"block-map",offset:t.offset,indent:t.indent,items:[{start:o,key:t,sep:l}]};this.onKeyLine=!0,this.stack[this.stack.length-1]=d}else yield*this.lineEnd(t)}}flowScalar(t){if(this.onNewLine){let n=this.source.indexOf(`
|
|
600
600
|
`)+1;for(;n!==0;)this.onNewLine(this.offset+n),n=this.source.indexOf(`
|
|
601
601
|
`,n)+1}return{type:t,offset:this.offset,indent:this.indent,source:this.source}}startBlockValue(t){switch(this.type){case"alias":case"scalar":case"single-quoted-scalar":case"double-quoted-scalar":return this.flowScalar(this.type);case"block-scalar-header":return{type:"block-scalar",offset:this.offset,indent:this.indent,props:[this.sourceToken],source:""};case"flow-map-start":case"flow-seq-start":return{type:"flow-collection",offset:this.offset,indent:this.indent,start:this.sourceToken,items:[],end:[]};case"seq-item-ind":return{type:"block-seq",offset:this.offset,indent:this.indent,items:[{start:[this.sourceToken]}]};case"explicit-key-ind":{this.onKeyLine=!0;const n=jf(t),r=ol(n);return r.push(this.sourceToken),{type:"block-map",offset:this.offset,indent:this.indent,items:[{start:r,explicitKey:!0}]}}case"map-value-ind":{this.onKeyLine=!0;const n=jf(t),r=ol(n);return{type:"block-map",offset:this.offset,indent:this.indent,items:[{start:r,key:null,sep:[this.sourceToken]}]}}}return null}atIndentedComment(t,n){return this.type!=="comment"||this.indent<=n?!1:t.every(r=>r.type==="newline"||r.type==="space")}*documentEnd(t){this.type!=="doc-mode"&&(t.end?t.end.push(this.sourceToken):t.end=[this.sourceToken],this.type==="newline"&&(yield*this.pop()))}*lineEnd(t){switch(this.type){case"comma":case"doc-start":case"doc-end":case"flow-seq-end":case"flow-map-end":case"map-value-ind":yield*this.pop(),yield*this.step();break;case"newline":this.onKeyLine=!1;case"space":case"comment":default:t.end?t.end.push(this.sourceToken):t.end=[this.sourceToken],this.type==="newline"&&(yield*this.pop())}}}function a2(e){const t=e.prettyErrors!==!1;return{lineCounter:e.lineCounter||t&&new r2||null,prettyErrors:t}}function vz(e,t={}){const{lineCounter:n,prettyErrors:r}=a2(t),a=new sx(n==null?void 0:n.addNewLine),o=new ax(t),l=Array.from(o.compose(a.parse(e)));if(r&&n)for(const d of l)d.errors.forEach(yh(e,n)),d.warnings.forEach(yh(e,n));return l.length>0?l:Object.assign([],{empty:!0},o.streamInfo())}function s2(e,t={}){const{lineCounter:n,prettyErrors:r}=a2(t),a=new sx(n==null?void 0:n.addNewLine),o=new ax(t);let l=null;for(const d of o.compose(a.parse(e),!0,e.length))if(!l)l=d;else if(l.options.logLevel!=="silent"){l.errors.push(new Zs(d.range.slice(0,2),"MULTIPLE_DOCS","Source contains multiple documents; please use YAML.parseAllDocuments()"));break}return r&&n&&(l.errors.forEach(yh(e,n)),l.warnings.forEach(yh(e,n))),l}function wz(e,t,n){let r;typeof t=="function"?r=t:n===void 0&&t&&typeof t=="object"&&(n=t);const a=s2(e,n);if(!a)return null;if(a.warnings.forEach(o=>S_(a.options.logLevel,o)),a.errors.length>0){if(a.options.logLevel!=="silent")throw a.errors[0];a.errors=[]}return a.toJS(Object.assign({reviver:r},n))}function kz(e,t,n){let r=null;if(typeof t=="function"||Array.isArray(t)?r=t:n===void 0&&t&&(n=t),typeof n=="string"&&(n=n.length),typeof n=="number"){const a=Math.round(n);n=a<1?void 0:a>8?{indent:8}:{indent:a}}if(e===void 0){const{keepUndefined:a}=n??t??{};if(!a)return}return wo(e)&&!r?e.toString(n):new ic(e,r,n).toString(n)}const Ek=Object.freeze(Object.defineProperty({__proto__:null,Alias:Kh,CST:yz,Composer:ax,Document:ic,Lexer:n2,LineCounter:r2,Pair:Vn,Parser:sx,Scalar:st,Schema:q_,YAMLError:rx,YAMLMap:Nr,YAMLParseError:Zs,YAMLSeq:ws,YAMLWarning:K_,isAlias:Ss,isCollection:ln,isDocument:wo,isMap:ec,isNode:cn,isPair:en,isScalar:Kt,isSeq:tc,parse:wz,parseAllDocuments:vz,parseDocument:s2,stringify:kz,visit:ko,visitAsync:Hh},Symbol.toStringTag,{value:"Module"}));function Ez({projectName:e,file:t,onClose:n,onSaved:r}){const a=Be(),o=Gt(),{alert:l}=un(),{data:d,isLoading:f,isError:h,error:g,refetch:m}=Ye({queryKey:["pipeline-file",e,t],queryFn:()=>V3(e,t)}),[y,b]=j.useState("structured"),[k,v]=j.useState(null),[N,E]=j.useState(null);j.useEffect(()=>{d&&k===null&&(v(d.content),E(d.etag),d.parseError&&b("yaml"))},[d,k]),j.useEffect(()=>{const L=R=>{R.key==="Escape"&&n()};return window.addEventListener("keydown",L),()=>window.removeEventListener("keydown",L)},[n]);const C=Ct({mutationFn:()=>{if(k===null||N===null)throw new Error("no draft");return Y3(e,t,k,N)},onSuccess:L=>{E(L.etag),o.invalidateQueries({queryKey:["pipeline-file",e,t]}),o.invalidateQueries({queryKey:["project-pipelines",e]}),r()},onError:L=>{const R=L.status;l({title:a(R===409?"pipelineEditor.error.conflict.title":R===422?"pipelineEditor.error.yaml.title":"pipelineEditor.error.save.title"),body:L instanceof Error?L.message:String(L)})}}),S=k!==null&&d&&k!==d.content,{parsed:_,parseError:M}=j.useMemo(()=>{if(k===null)return{parsed:null,parseError:null};try{return{parsed:Ek.parse(k)??{},parseError:null}}catch(L){return{parsed:null,parseError:L instanceof Error?L.message:String(L)}}},[k]),T=L=>{try{const R=Ek.stringify(L,{lineWidth:0});v(R)}catch(R){l({title:a("pipelineEditor.error.serialize.title"),body:R instanceof Error?R.message:String(R)})}};return c.jsx("div",{role:"dialog","aria-modal":"true",className:"fixed inset-0 z-40 flex items-start justify-center p-6 bg-black/30 overflow-auto",children:c.jsxs("div",{className:"nb-card mt-8 w-full max-w-4xl flex flex-col",style:{maxHeight:"calc(100vh - 64px)"},children:[c.jsxs("header",{className:"flex items-start justify-between gap-3 mb-3 flex-shrink-0",children:[c.jsxs("div",{children:[c.jsxs("h2",{className:"font-[family-name:var(--font-heading)] text-2xl font-bold flex items-center gap-2",children:[c.jsx(ck,{size:20,strokeWidth:2.5}),c.jsx("code",{className:"font-[family-name:var(--font-mono)] text-lg",children:t}),(d==null?void 0:d.isActive)&&c.jsx("span",{className:"nb-status",style:{background:"var(--color-running-bg)",color:"var(--color-running)",padding:"2px 8px"},children:a("pipelineEditor.activeBadge")})]}),c.jsxs("p",{className:"text-xs text-[var(--color-text-muted)] font-[family-name:var(--font-mono)] mt-1",children:[e,"/pipelines/",t,N&&` · etag ${N}`]})]}),c.jsx("button",{className:"nb-btn nb-btn-mint p-2",onClick:n,type:"button","aria-label":a("pipelineEditor.close"),children:c.jsx(Sn,{size:14,strokeWidth:3})})]}),f&&c.jsx("p",{className:"text-[var(--color-text-muted)]",children:a("common.loading")}),h&&c.jsx("p",{className:"text-[var(--color-crashed)]",children:a("pipelineEditor.error.load",{detail:g instanceof Error?g.message:String(g)})}),d&&k!==null&&c.jsxs(c.Fragment,{children:[c.jsxs("div",{className:"flex items-center gap-3 mb-3 flex-shrink-0 flex-wrap",children:[c.jsxs("div",{className:"flex gap-1 p-1 bg-[var(--color-bg)] border-[2px] border-[var(--color-text)] rounded-full shadow-[2px_2px_0_var(--color-text)]",children:[c.jsxs("button",{type:"button",onClick:()=>b("structured"),"aria-pressed":y==="structured",disabled:!!M,className:["px-3 py-1 rounded-full text-xs font-bold flex items-center gap-1.5",y==="structured"?"bg-[var(--color-primary)] text-[var(--color-text)] shadow-[1px_1px_0_var(--color-text)]":"text-[var(--color-text-muted)]",M?"opacity-50 cursor-not-allowed":""].join(" "),title:M??void 0,children:[c.jsx(Fh,{size:11,strokeWidth:2.5}),a("pipelineEditor.mode.structured")]}),c.jsxs("button",{type:"button",onClick:()=>b("yaml"),"aria-pressed":y==="yaml",className:["px-3 py-1 rounded-full text-xs font-bold flex items-center gap-1.5",y==="yaml"?"bg-[var(--color-primary)] text-[var(--color-text)] shadow-[1px_1px_0_var(--color-text)]":"text-[var(--color-text-muted)]"].join(" "),children:[c.jsx(ck,{size:11,strokeWidth:2.5}),a("pipelineEditor.mode.yaml")]})]}),M&&c.jsxs("div",{className:"flex items-center gap-1 text-xs text-[var(--color-crashed)] font-bold",children:[c.jsx(ku,{size:12,strokeWidth:2.5}),a("pipelineEditor.parseError.prefix",{detail:M})]}),(d==null?void 0:d.isActive)&&c.jsx("span",{className:"text-xs text-[var(--color-stuck)] font-bold ml-auto",children:a("pipelineEditor.activeWarning")})]}),c.jsxs("div",{className:"flex-1 overflow-auto",children:[y==="structured"&&_&&c.jsx(Sz,{parsed:_,onChange:T}),y==="yaml"&&c.jsx("textarea",{className:"nb-input w-full font-[family-name:var(--font-mono)] text-xs",style:{minHeight:400,resize:"vertical"},value:k,onChange:L=>v(L.target.value),spellCheck:!1,"aria-label":a("pipelineEditor.yamlAria")})]}),c.jsxs("div",{className:"flex items-center justify-between mt-3 pt-3 border-t-2 border-dashed border-[var(--color-text)] flex-shrink-0",children:[c.jsx("span",{className:"text-xs text-[var(--color-text-muted)]",children:S?c.jsx("span",{className:"text-[var(--color-stuck)] font-bold",children:a("pipelineEditor.status.unsaved")}):C.isSuccess?c.jsxs("span",{className:"text-[var(--color-running)] font-bold flex items-center gap-1",children:[c.jsx(Eu,{size:12,strokeWidth:2.5})," ",a("pipelineEditor.status.saved")]}):a("pipelineEditor.status.noChanges")}),c.jsxs("div",{className:"flex gap-2",children:[c.jsx("button",{className:"nb-btn",style:{padding:"6px 14px"},onClick:()=>{v(null),m()},disabled:C.isPending,type:"button",children:a("pipelineEditor.reload")}),c.jsxs("button",{className:"nb-btn nb-btn-primary",style:{padding:"6px 14px"},onClick:()=>C.mutate(),disabled:!S||C.isPending,type:"button","aria-label":a("pipelineEditor.saveAria"),children:[C.isPending?c.jsx(Xe,{size:13,strokeWidth:3,className:"animate-spin"}):c.jsx(Ri,{size:13,strokeWidth:3}),a("pipelineEditor.save")]})]})]})]})]})})}function Sz({parsed:e,onChange:t}){const n=Be(),r=e.stages??[],a=h=>{t({...e,stages:h})},o=()=>{a([...r,{name:`stage-${r.length+1}`,on_complete:"move_card Done"}])},l=h=>{a(r.filter((g,m)=>m!==h))},d=(h,g)=>{const m=[...r],y=h+g;y<0||y>=m.length||([m[h],m[y]]=[m[y],m[h]],a(m))},f=(h,g)=>{a(r.map((m,y)=>y===h?{...m,...g}:m))};return c.jsxs("div",{className:"flex flex-col gap-4",children:[c.jsxs("div",{className:"flex items-center gap-3 p-3 bg-[var(--color-bg-cream)] border-2 border-[var(--color-text)] rounded-lg",children:[c.jsxs("label",{className:"flex items-center gap-2 text-sm",children:[c.jsx("span",{className:"font-bold",children:"mode:"}),c.jsxs("select",{className:"nb-input",style:{padding:"4px 10px",fontSize:12},value:e.mode??"project",onChange:h=>t({...e,mode:h.target.value}),children:[c.jsx("option",{value:"project",children:"project"}),c.jsx("option",{value:"steps",children:"steps"})]})]}),c.jsx("span",{className:"text-xs text-[var(--color-text-muted)]",children:n("pipelineEditor.modeHint")})]}),c.jsxs("div",{children:[c.jsxs("div",{className:"flex items-center justify-between mb-2",children:[c.jsx("h3",{className:"font-[family-name:var(--font-heading)] text-sm font-bold uppercase tracking-wider",children:n("pipelineEditor.stages.heading",{count:r.length})}),c.jsxs("button",{type:"button",className:"nb-btn nb-btn-mint",style:{padding:"4px 12px",fontSize:12},onClick:o,"aria-label":n("pipelineEditor.stages.add"),children:[c.jsx(pr,{size:11,strokeWidth:3})," ",n("pipelineEditor.stages.add")]})]}),r.length===0?c.jsx("p",{className:"text-sm text-[var(--color-text-muted)] italic p-4 border-2 border-dashed border-[var(--color-text)] rounded-lg text-center",children:n("pipelineEditor.stages.empty")}):c.jsx("div",{className:"flex flex-col gap-3",children:r.map((h,g)=>c.jsx(Nz,{stage:h,index:g,total:r.length,onChange:m=>f(g,m),onRemove:()=>l(g),onMoveUp:()=>d(g,-1),onMoveDown:()=>d(g,1)},g))})]})]})}function Nz({stage:e,index:t,total:n,onChange:r,onRemove:a,onMoveUp:o,onMoveDown:l}){const d=Be(),f=e.on_fail??{};return c.jsxs("div",{className:"nb-card bg-[var(--color-bg-cream)] p-4",children:[c.jsxs("div",{className:"flex items-center justify-between mb-3",children:[c.jsxs("h4",{className:"font-[family-name:var(--font-heading)] font-bold text-sm",children:["Stage #",t+1,e.name&&c.jsx("code",{className:"ml-2 text-xs font-[family-name:var(--font-mono)] bg-[var(--color-bg)] border-2 border-[var(--color-text)] px-2 py-0.5 rounded",children:e.name})]}),c.jsxs("div",{className:"flex gap-1",children:[c.jsx("button",{type:"button",className:"nb-btn",style:{padding:"3px 8px"},onClick:o,disabled:t===0,"aria-label":d("pipelineEditor.stage.moveUp"),children:c.jsx(PR,{size:12,strokeWidth:3})}),c.jsx("button",{type:"button",className:"nb-btn",style:{padding:"3px 8px"},onClick:l,disabled:t===n-1,"aria-label":d("pipelineEditor.stage.moveDown"),children:c.jsx(Vu,{size:12,strokeWidth:3})}),c.jsx("button",{type:"button",className:"nb-btn nb-btn-danger",style:{padding:"3px 8px"},onClick:a,"aria-label":d("pipelineEditor.stage.remove"),children:c.jsx(fi,{size:12,strokeWidth:3})})]})]}),c.jsxs("div",{className:"grid grid-cols-2 gap-3 text-sm",children:[c.jsx(es,{label:"name",hint:d("pipelineEditor.stage.name.hint"),children:c.jsx("input",{type:"text",className:"nb-input w-full font-[family-name:var(--font-mono)] text-xs",value:e.name??"",onChange:h=>r({name:h.target.value}),placeholder:"develop"})}),c.jsx(es,{label:"profile",hint:d("pipelineEditor.stage.profile.hint"),children:c.jsx("input",{type:"text",className:"nb-input w-full font-[family-name:var(--font-mono)] text-xs",value:e.profile??"",onChange:h=>r({profile:h.target.value||void 0}),placeholder:"fullstack"})}),c.jsx(es,{label:"card_state",hint:d("pipelineEditor.stage.cardState.hint"),children:c.jsx("input",{type:"text",className:"nb-input w-full font-[family-name:var(--font-mono)] text-xs",value:e.card_state??"",onChange:h=>r({card_state:h.target.value||void 0}),placeholder:"Inprogress"})}),c.jsx(es,{label:"timeout",hint:d("pipelineEditor.stage.timeout.hint"),children:c.jsx("input",{type:"text",className:"nb-input w-full font-[family-name:var(--font-mono)] text-xs",value:e.timeout??"",onChange:h=>r({timeout:h.target.value||void 0}),placeholder:"2h"})}),c.jsx(es,{label:"trigger",hint:d("pipelineEditor.stage.trigger.hint"),children:c.jsx("input",{type:"text",className:"nb-input w-full font-[family-name:var(--font-mono)] text-xs",value:e.trigger??"",onChange:h=>r({trigger:h.target.value||void 0}),placeholder:"card_enters 'Todo'"})}),c.jsx(es,{label:"on_complete",hint:d("pipelineEditor.stage.onComplete.hint"),children:c.jsx("input",{type:"text",className:"nb-input w-full font-[family-name:var(--font-mono)] text-xs",value:e.on_complete??"",onChange:h=>r({on_complete:h.target.value}),placeholder:"move_card Done"})})]}),c.jsxs("div",{className:"mt-4 pt-3 border-t-2 border-dashed border-[var(--color-text)]",children:[c.jsx("h5",{className:"text-xs font-bold uppercase tracking-wider mb-2 text-[var(--color-text-muted)]",children:"on_fail"}),c.jsxs("div",{className:"grid grid-cols-2 gap-3 text-sm",children:[c.jsx(es,{label:"action",hint:d("pipelineEditor.stage.onFail.action.hint"),children:c.jsx("input",{type:"text",className:"nb-input w-full font-[family-name:var(--font-mono)] text-xs",value:f.action??"",onChange:h=>r({on_fail:{...f,action:h.target.value||void 0}}),placeholder:"label NEEDS-FIX"})}),c.jsx(es,{label:"comment",hint:d("pipelineEditor.stage.onFail.comment.hint"),children:c.jsx("input",{type:"text",className:"nb-input w-full font-[family-name:var(--font-mono)] text-xs",value:f.comment??"",onChange:h=>r({on_fail:{...f,comment:h.target.value||void 0}}),placeholder:"Worker failed. Check logs."})})]}),c.jsxs("label",{className:"flex items-center gap-2 mt-3 text-sm cursor-pointer",children:[c.jsx("input",{type:"checkbox",checked:f.halt??!0,onChange:h=>r({on_fail:{...f,halt:h.target.checked}})}),c.jsx("span",{className:"font-bold",children:"halt"}),c.jsx("span",{className:"text-xs text-[var(--color-text-muted)]",children:d("pipelineEditor.stage.halt.note")})]})]})]})}function es({label:e,hint:t,children:n}){return c.jsxs("label",{className:"flex flex-col gap-1",children:[c.jsx("span",{className:"text-xs font-bold font-[family-name:var(--font-mono)]",children:e}),n,t&&c.jsx("span",{className:"text-[10px] text-[var(--color-text-muted)]",children:t})]})}function _z({onCancel:e,onCreate:t,hasActive:n,hasSample:r,isPending:a}){const o=Be(),[l,d]=j.useState(""),[f,h]=j.useState("blank");j.useEffect(()=>{const N=E=>{E.key==="Escape"&&e()};return window.addEventListener("keydown",N),()=>window.removeEventListener("keydown",N)},[e]);const g=l.trim(),m=g.endsWith(".yaml")?g:g?`${g}.yaml`:"",y=m&&/^[a-zA-Z0-9_.-]+\.yaml$/.test(m),b=()=>{!y||a||t(m,f)},v=o("newPipelineDialog.field.filename.help",{filename:"__FN__"}).split("__FN__");return c.jsx("div",{role:"dialog","aria-modal":"true",className:"fixed inset-0 z-50 flex items-center justify-center p-6 bg-black/30",children:c.jsxs("div",{className:"nb-card max-w-md w-full",children:[c.jsxs("header",{className:"flex items-start justify-between mb-4",children:[c.jsx("h2",{className:"font-[family-name:var(--font-heading)] text-xl font-bold",children:o("newPipelineDialog.title")}),c.jsx("button",{className:"nb-btn nb-btn-mint p-2",onClick:e,type:"button","aria-label":o("common.close"),children:c.jsx(Sn,{size:14,strokeWidth:3})})]}),c.jsxs("form",{onSubmit:N=>{N.preventDefault(),b()},className:"flex flex-col gap-4",children:[c.jsxs("label",{className:"flex flex-col gap-1.5",children:[c.jsx("span",{className:"text-sm font-bold",children:o("newPipelineDialog.field.filename.label")}),c.jsx("input",{type:"text",className:"nb-input w-full font-[family-name:var(--font-mono)]",placeholder:o("newPipelineDialog.field.filename.placeholder"),value:l,onChange:N=>d(N.target.value),autoFocus:!0}),c.jsxs("span",{className:"text-xs text-[var(--color-text-muted)]",children:[v[0],c.jsx("code",{className:"font-[family-name:var(--font-mono)]",children:m||"xxx.yaml"}),v[1]]})]}),c.jsxs("fieldset",{className:"flex flex-col gap-2",children:[c.jsx("legend",{className:"text-sm font-bold mb-1",children:o("newPipelineDialog.section.template")}),c.jsx(Bg,{value:"blank",current:f,label:o("newPipelineDialog.template.blank.label"),desc:o("newPipelineDialog.template.blank.desc"),onSelect:h}),c.jsx(Bg,{value:"sample",current:f,label:o("newPipelineDialog.template.sample.label"),desc:o("newPipelineDialog.template.sample.desc"),onSelect:h,disabled:!r,disabledReason:o("newPipelineDialog.template.sample.unavailable")}),c.jsx(Bg,{value:"active",current:f,label:o("newPipelineDialog.template.active.label"),desc:o("newPipelineDialog.template.active.desc"),onSelect:h,disabled:!n,disabledReason:o("newPipelineDialog.template.active.unavailable")})]}),c.jsxs("div",{className:"flex gap-3 justify-end pt-2",children:[c.jsx("button",{className:"nb-btn",onClick:e,type:"button",disabled:a,children:o("common.cancel")}),c.jsxs("button",{className:"nb-btn nb-btn-primary",type:"submit",disabled:!y||a,"aria-label":o("newPipelineDialog.create.aria"),children:[a?c.jsx(Xe,{size:13,strokeWidth:3,className:"animate-spin"}):c.jsx(pr,{size:13,strokeWidth:3}),o("common.create")]})]})]})]})})}function Bg({value:e,current:t,label:n,desc:r,onSelect:a,disabled:o,disabledReason:l}){const d=t===e;return c.jsxs("label",{className:["flex items-start gap-2 p-2 rounded-lg border-2 cursor-pointer",o?"border-[var(--color-border-light)] opacity-50 cursor-not-allowed":d?"bg-[var(--color-accent-mint)] border-[var(--color-text)] shadow-[2px_2px_0_var(--color-text)]":"border-[var(--color-border-light)] hover:bg-[var(--color-bg-cream)] hover:border-[var(--color-text)]"].join(" "),children:[c.jsx("input",{type:"radio",name:"pipeline-template",value:e,checked:d,disabled:o,onChange:()=>a(e),className:"mt-1 flex-shrink-0"}),c.jsxs("div",{className:"flex-1",children:[c.jsx("div",{className:"text-sm font-bold",children:n}),c.jsx("div",{className:"text-xs text-[var(--color-text-muted)]",children:o?l:r})]})]})}function jz(e){return ft(`/api/rules/${encodeURIComponent(e)}`)}function ox(e){const t=e?`?project=${encodeURIComponent(e)}`:"";return ft(`/api/skills${t}`)}function Cz(e){return ft(`/api/skills/${encodeURIComponent(e)}`)}function Az(e,t){return ft(`/api/skills/${encodeURIComponent(e)}/references/${encodeURIComponent(t)}`)}async function Tz(e,t){const n=await fetch(e,{method:"POST",headers:void 0,body:void 0});if(!n.ok)throw new Error(`${n.status}: ${await n.text()}`);return n.json().catch(()=>({}))}function Mz(){return Tz("/api/skills/sync")}function Dz(e){return ft(`/api/skills/policy/${encodeURIComponent(e)}`)}function Oz(e,t){return qb(`/api/skills/policy/${encodeURIComponent(e)}`,t)}function Rz(){return ft("/api/skills/updates")}function Lz(e,t,n){return Li("/api/skills/import",{name:e,files:t,overwrite:n})}function Iz(e){return ft(`/api/skills/${encodeURIComponent(e)}/export`)}function zz(e,t){return Li("/api/skills/create",{name:e,intent:t})}function o2(){return c.jsx("div",{className:"nb-card",children:c.jsxs("p",{className:"text-[var(--color-text-muted)] flex items-center gap-2",children:[c.jsx(Xe,{size:14,className:"animate-spin"})," …"]})})}function l2({msg:e}){return c.jsx("div",{className:"nb-card bg-[var(--color-crashed-bg)]",children:c.jsx("p",{children:e})})}function Pz({name:e}){var b,k;const t=Be(),n=Gt(),{alert:r}=un(),a=Ye({queryKey:["skill-policy",e],queryFn:()=>Dz(e),enabled:!!e}),o=(b=a.data)==null?void 0:b.data,[l,d]=j.useState(null),[f,h]=j.useState(null);j.useEffect(()=>{var v;o&&l===null&&d((v=o.policy.allow)!=null&&v.length?new Set(o.policy.allow):new Set(o.skills.map(N=>N.name)))},[o,l]);const g=Ct({mutationFn:v=>Oz(e,v),onSuccess:v=>{h(v),d(null),n.invalidateQueries({queryKey:["skill-policy",e]})},onError:v=>void r({title:t("projectDetail.skills.saveError"),body:v instanceof Error?v.message:String(v)})});if(a.isLoading||o&&l===null)return c.jsx(o2,{});if(a.isError)return c.jsx(l2,{msg:a.error instanceof Error?a.error.message:String(a.error)});if(!o||!l)return null;if(o.skills.length===0)return c.jsx("div",{className:"nb-card",children:c.jsx("p",{className:"text-[var(--color-text-muted)]",children:t("projectDetail.skills.empty")})});const m=o.eligible!==null,y=v=>d(N=>{const E=new Set(N);return E.has(v)?E.delete(v):E.add(v),E});return c.jsxs("div",{className:"nb-card flex flex-col gap-4 h-full min-h-0",children:[c.jsxs("div",{className:"shrink-0",children:[c.jsxs("h2",{className:"font-[family-name:var(--font-heading)] text-lg font-bold flex items-center gap-2",children:[c.jsx(ZN,{size:18,strokeWidth:2.5}),t("projectDetail.skills.title")]}),c.jsx("p",{className:"text-sm text-[var(--color-text-muted)] mt-1",children:t("projectDetail.skills.desc")}),c.jsx("p",{className:"text-sm mt-1 font-medium",children:m?t("projectDetail.skills.hasPolicy",{count:String(((k=o.eligible)==null?void 0:k.length)??0)}):t("projectDetail.skills.noPolicy")})]}),c.jsxs("div",{className:"flex gap-2 shrink-0",children:[c.jsx("button",{type:"button",className:"nb-btn",style:{padding:"4px 10px",fontSize:12},onClick:()=>d(new Set(o.skills.map(v=>v.name))),children:t("projectDetail.skills.selectAll")}),c.jsx("button",{type:"button",className:"nb-btn",style:{padding:"4px 10px",fontSize:12},onClick:()=>d(new Set),children:t("projectDetail.skills.selectNone")})]}),c.jsx("div",{className:"flex flex-col gap-1 flex-1 min-h-0 overflow-auto border-2 border-[var(--color-text)] rounded p-2",children:o.skills.map(v=>c.jsxs("label",{className:"flex items-start gap-2 px-2 py-1 rounded hover:bg-[var(--color-bg-cream)] cursor-pointer",children:[c.jsx("input",{type:"checkbox",checked:l.has(v.name),onChange:()=>y(v.name),className:"mt-1"}),c.jsxs("span",{className:"flex-1",children:[c.jsx("code",{className:"font-[family-name:var(--font-mono)] text-sm font-bold",children:v.name}),c.jsx("span",{className:"ml-2 text-[10px] uppercase text-[var(--color-text-muted)]",children:v.category}),v.description&&c.jsx("span",{className:"block text-xs text-[var(--color-text-muted)]",children:v.description})]})]},v.name))}),c.jsxs("div",{className:"flex items-center gap-2 flex-wrap shrink-0",children:[c.jsxs("button",{type:"button",className:"nb-btn nb-btn-mint",disabled:g.isPending,onClick:()=>g.mutate({allow:[...l]}),children:[g.isPending?c.jsx(Xe,{size:14,className:"animate-spin"}):c.jsx(Ri,{size:14,strokeWidth:3}),t("projectDetail.skills.save")]}),c.jsxs("button",{type:"button",className:"nb-btn",disabled:g.isPending,onClick:()=>g.mutate({}),children:[c.jsx(Pb,{size:14,strokeWidth:3}),t("projectDetail.skills.clear")]}),c.jsxs("span",{className:"text-sm text-[var(--color-text-muted)]",children:[l.size,"/",o.skills.length]})]}),f&&c.jsxs("div",{className:"text-sm border-2 border-[var(--color-text)] rounded p-2 bg-[var(--color-bg-cream)]",children:[c.jsx("p",{children:t("projectDetail.skills.applied",{linked:String(f.applied.linked),pruned:String(f.applied.pruned)})}),f.unknown.length>0&&c.jsx("p",{className:"text-[var(--color-text-muted)]",children:t("projectDetail.skills.unknown",{names:f.unknown.join(", ")})})]})]})}function Bz({name:e}){var a;const t=Be(),n=Ye({queryKey:["rules",e],queryFn:()=>jz(e),enabled:!!e});if(n.isLoading)return c.jsx(o2,{});if(n.isError)return c.jsx(l2,{msg:n.error instanceof Error?n.error.message:String(n.error)});const r=((a=n.data)==null?void 0:a.data)??[];return c.jsxs("div",{className:"flex flex-col gap-4 min-h-full",children:[c.jsx("p",{className:"text-sm text-[var(--color-text-muted)]",children:t("projectDetail.rules.readonly")}),r.map(o=>c.jsxs("div",{className:"nb-card",children:[c.jsxs("div",{className:"flex items-center gap-2 mb-2",children:[c.jsx("code",{className:"font-[family-name:var(--font-mono)] text-sm font-bold bg-[var(--color-bg-cream)] border-2 border-[var(--color-text)] px-2 py-0.5 rounded",children:o.name}),!o.exists&&c.jsx("span",{className:"text-xs text-[var(--color-text-muted)]",children:t("projectDetail.rules.missing")})]}),o.exists&&c.jsx("pre",{className:"overflow-auto max-h-[28rem] text-xs font-[family-name:var(--font-mono)] whitespace-pre-wrap break-words bg-[var(--color-bg-cream)] border-2 border-[var(--color-text)] rounded p-3",children:o.content})]},o.name))]})}const rp=e=>`/api/projects/${encodeURIComponent(e)}/graph`;function $z(e){return ft(`${rp(e)}/status`)}function Uz(e){return ft(`${rp(e)}/data`)}function Fz(e){return Li(`${rp(e)}/build`)}function qz(e){return Li(`${rp(e)}/sync`)}const Hz={typescript:"#1D4E89",tsx:"#2563EB",javascript:"#B8860B",json:"#6B7280",yaml:"#C2410C"},Cf=e=>Hz[e]??"#2D6A4F";function Sk(e){return[parseInt(e.slice(1,3),16),parseInt(e.slice(3,5),16),parseInt(e.slice(5,7),16)]}const Kz=e=>Math.max(8,Math.min(22,8+e*2.5));function Gz(e){return e<1024?`${e} B`:e<1024*1024?`${(e/1024).toFixed(0)} KB`:`${(e/1024/1024).toFixed(2)} MB`}function Vz(e){if(!e)return"—";const t=new Date(e);if(Number.isNaN(t.getTime()))return"—";const n=r=>String(r).padStart(2,"0");return`${t.getFullYear()}-${n(t.getMonth()+1)}-${n(t.getDate())} ${n(t.getHours())}:${n(t.getMinutes())}`}function Yz({name:e,status:t}){var y,b,k,v;const n=Be(),r=Ye({queryKey:["graph-data",e],queryFn:()=>Uz(e)}),[a,o]=j.useState(""),l=j.useRef(null),d=j.useRef(null),f=j.useRef(null),h=j.useRef(null),g=[...new Set((((b=(y=r.data)==null?void 0:y.data)==null?void 0:b.nodes)??[]).map(N=>N.language))];if(j.useEffect(()=>{h.current&&(h.current.search=a.trim().toLowerCase())},[a]),j.useEffect(()=>{var De;const N=(De=r.data)==null?void 0:De.data,E=d.current,C=l.current;if(!N||!N.nodes.length||!E||!C)return;const S=E.getContext("2d");if(!S)return;const _={};for(const ce of N.links)_[ce.source]=(_[ce.source]??0)+1,_[ce.target]=(_[ce.target]??0)+1;const M=N.nodes.length,T=window.devicePixelRatio||1,L=C.getBoundingClientRect(),R=L.width||800,$=L.height||500,z=Math.min(R,$)*.35+M*1.5,q=N.nodes.map((ce,Ce)=>{const te=2*Math.PI*Ce/Math.max(M,1),he=_[ce.id]??0;return{id:ce.id,language:ce.language,symbols:ce.symbols,deg:he,name:ce.id.split("/").pop()||ce.id,x:Math.cos(te)*z+Math.sin(Ce*12.9898)*43758.5453%1*40,y:Math.sin(te)*z+Math.sin(Ce*78.233)*12345.678%1*40,vx:0,vy:0,r:Kz(he)}}),F={};for(const ce of q)F[ce.id]=ce;const Y=N.links.map(ce=>({source:ce.source,target:ce.target,weight:ce.weight})),D={nodes:q,edges:Y,map:F,panX:R/2,panY:$/2,zoom:1,drag:null,mouseX:0,mouseY:0,raf:null,tick:0,quiet:0,sel:null,search:a.trim().toLowerCase(),fitted:!1};h.current=D;const H=()=>{const ce=C.getBoundingClientRect();E.width=ce.width*T,E.height=ce.height*T,E.style.width=ce.width+"px",E.style.height=ce.height+"px",S.setTransform(T,0,0,T,0,0)};H();const O=new ResizeObserver(H);O.observe(C);const V=()=>{let ce=1/0,Ce=1/0,te=-1/0,he=-1/0;for(const ye of q)ce=Math.min(ce,ye.x-ye.r),Ce=Math.min(Ce,ye.y-ye.r),te=Math.max(te,ye.x+ye.r),he=Math.max(he,ye.y+ye.r);const Fe=E.width/T,ze=E.height/T,se=Math.min(Fe/Math.max(te-ce,1),ze/Math.max(he-Ce,1),1.4)*.88;D.zoom=se,D.panX=Fe/2-(ce+te)/2*se,D.panY=ze/2-(Ce+he)/2*se},Q=()=>{const ce=q.length;D.tick++;const Ce=.9-Math.min(.4,D.tick/1500),te=ce>1e3?3e3:ce>100?2e3:ce>50?1200:800,he=ce>100?.002:.005,Fe=ce>1e3?.012:ce>100?.005:.01,ze=ce>1e3?6:ce>200?12:24;for(let ve=0;ve<ce;ve++){const pe=q[ve];let Ne=-pe.x*Fe,je=-pe.y*Fe;for(let Ge=0;Ge<ce;Ge++){if(ve===Ge)continue;const ne=q[Ge],de=pe.x-ne.x,Le=pe.y-ne.y,Ze=de*de+Le*Le||1,it=Math.sqrt(Ze),At=te/Ze;Ne+=de/it*At,je+=Le/it*At}if(pe!==D.drag){let Ge=(pe.vx+Ne)*Ce,ne=(pe.vy+je)*Ce;Ge=Math.max(-ze,Math.min(ze,Ge)),ne=Math.max(-ze,Math.min(ze,ne)),pe.vx=Ge,pe.vy=ne}}for(const ve of Y){const pe=F[ve.source],Ne=F[ve.target];if(!pe||!Ne)continue;const je=Ne.x-pe.x,Ge=Ne.y-pe.y,ne=Math.sqrt(je*je+Ge*Ge)||1,de=(ne-100)*he,Le=je/ne*de,Ze=Ge/ne*de;pe!==D.drag&&(pe.vx+=Le,pe.vy+=Ze),Ne!==D.drag&&(Ne.vx-=Le,Ne.vy-=Ze)}let se=0;for(const ve of q)ve!==D.drag&&(ve.x+=ve.vx,ve.y+=ve.vy,se+=ve.vx*ve.vx+ve.vy*ve.vy);(ce?Math.sqrt(se/ce):0)<.05&&D.tick>60&&!D.drag?D.quiet++:D.quiet=0,!D.fitted&&(D.quiet>8||D.tick>400)&&(D.fitted=!0,V())},K=()=>{const ce=E.width/T,Ce=E.height/T;S.clearRect(0,0,ce,Ce),S.strokeStyle="rgba(45,55,72,0.05)",S.lineWidth=.5;for(let ye=0;ye<ce;ye+=24)S.beginPath(),S.moveTo(ye,0),S.lineTo(ye,Ce),S.stroke();for(let ye=0;ye<Ce;ye+=24)S.beginPath(),S.moveTo(0,ye),S.lineTo(ce,ye),S.stroke();S.save(),S.translate(D.panX,D.panY),S.scale(D.zoom,D.zoom);const te=D.search,he=q.length>40;let Fe=null;if(!D.drag){const ye=E.getBoundingClientRect(),ve=(D.mouseX-ye.left-D.panX)/D.zoom,pe=(D.mouseY-ye.top-D.panY)/D.zoom;for(let Ne=q.length-1;Ne>=0;Ne--){const je=q[Ne],Ge=je.x-ve,ne=je.y-pe;if(Ge*Ge+ne*ne<je.r*je.r+25){Fe=je.id;break}}}const ze=D.sel||Fe;for(const ye of Y){const ve=F[ye.source],pe=F[ye.target];if(!ve||!pe)continue;const Ne=te&&!(ve.name.toLowerCase().includes(te)||pe.name.toLowerCase().includes(te)),je=ze&&(ye.source===ze||ye.target===ze),Ge=pe.x-ve.x,ne=pe.y-ve.y,de=Math.sqrt(Ge*Ge+ne*ne)||1,Le=he?12:18,Ze=(ve.x+pe.x)/2+-ne/de*Le,it=(ve.y+pe.y)/2+Ge/de*Le,[At,$n,dn]=Sk(Cf(ve.language));let Mt;if(Ne?Mt=.05:ze&&je?Mt=.6:ze&&!je?Mt=.05:Mt=he?.14:.24,S.beginPath(),S.moveTo(ve.x,ve.y),S.quadraticCurveTo(Ze,it,pe.x,pe.y),S.strokeStyle=`rgba(${At},${$n},${dn},${Mt})`,S.lineWidth=je?2+ye.weight*.4:1+ye.weight*.25,S.stroke(),!he||je){const Qt=Math.atan2(pe.y-it,pe.x-Ze),yt=5+S.lineWidth;S.beginPath(),S.moveTo(pe.x-pe.r*Math.cos(Qt),pe.y-pe.r*Math.sin(Qt)),S.lineTo(pe.x-(pe.r+yt)*Math.cos(Qt-.3),pe.y-(pe.r+yt)*Math.sin(Qt-.3)),S.lineTo(pe.x-(pe.r+yt)*Math.cos(Qt+.3),pe.y-(pe.r+yt)*Math.sin(Qt+.3)),S.closePath(),S.fillStyle=`rgba(${At},${$n},${dn},${Ne?.05:je?.55:.18})`,S.fill()}}const se=he?1.5:.5;for(const ye of q){const ve=Cf(ye.language),pe=D.sel===ye.id,Ne=Fe===ye.id,je=!te||ye.name.toLowerCase().includes(te),Ge=ze&&ye.id!==ze&&!Y.some(At=>At.source===ze&&At.target===ye.id||At.target===ze&&At.source===ye.id),ne=je?Ge?.2:1:.12;S.save(),S.globalAlpha=ne,je&&!Ge&&(pe||Ne||!te)&&(S.shadowColor=ve,S.shadowBlur=pe?20:Ne?16:he?4:8);const[de,Le,Ze]=Sk(ve),it=S.createRadialGradient(ye.x-ye.r*.3,ye.y-ye.r*.3,0,ye.x,ye.y,ye.r*1.2);if(it.addColorStop(0,`rgba(${Math.min(255,de+60)},${Math.min(255,Le+60)},${Math.min(255,Ze+60)},0.95)`),it.addColorStop(1,ve),S.beginPath(),S.arc(ye.x,ye.y,ye.r,0,Math.PI*2),S.fillStyle=it,S.fill(),S.shadowBlur=0,S.lineWidth=pe?2.5:1,S.strokeStyle=pe?"#111827":"rgba(255,255,255,0.7)",S.stroke(),S.restore(),je&&!Ge&&(pe||Ne||D.zoom>se)){const At=1/D.zoom;S.save(),S.globalAlpha=ne,S.fillStyle="rgba(45,55,72,0.92)",S.font=`${(10*At).toFixed(1)}px 'DM Sans', sans-serif`,S.textAlign="center",S.fillText(ye.name,ye.x,ye.y+ye.r+11*At),S.restore()}}S.restore()},I=()=>{if(Q(),K(),D.quiet>40&&!D.drag){D.raf=null;return}D.raf=requestAnimationFrame(I)},P=()=>{D.raf==null&&(D.quiet=0,D.raf=requestAnimationFrame(I))};D.raf=requestAnimationFrame(I);let G=!1,B=0,oe=0;const xe=ce=>{const Ce=E.getBoundingClientRect();return{x:(ce.clientX-Ce.left-D.panX)/D.zoom,y:(ce.clientY-Ce.top-D.panY)/D.zoom}},ke=(ce,Ce)=>{for(let te=q.length-1;te>=0;te--){const he=q[te];if(!he)continue;const Fe=he.x-ce,ze=he.y-Ce;if(Fe*Fe+ze*ze<he.r*he.r+25)return he}return null},Ee=ce=>{const Ce=xe(ce),te=ke(Ce.x,Ce.y);te?D.drag=te:G=!0,B=ce.clientX,oe=ce.clientY,P()},J=ce=>{const Ce=ce.clientX-B,te=ce.clientY-oe;D.drag?(D.drag.x+=Ce/D.zoom,D.drag.y+=te/D.zoom,D.drag.vx=0,D.drag.vy=0,P()):G&&(D.panX+=Ce,D.panY+=te,P()),B=ce.clientX,oe=ce.clientY,D.mouseX=ce.clientX,D.mouseY=ce.clientY;const he=f.current,Fe=xe(ce),ze=!D.drag&&!G?ke(Fe.x,Fe.y):null;if(he)if(ze){const se=Y.filter(ve=>ve.source===ze.id||ve.target===ze.id).length;he.innerHTML=`<div style="font-weight:700;word-break:break-all">${ze.id}</div><div style="margin-top:4px;color:#64748b;font-family:var(--font-mono,monospace)"><span style="color:${Cf(ze.language)}">●</span> ${ze.language} · ${ze.symbols} symbols · ${se} links</div>`;const ye=E.getBoundingClientRect();he.style.left=ce.clientX-ye.left+14+"px",he.style.top=ce.clientY-ye.top+14+"px",he.style.display="block",E.style.cursor="pointer"}else he.style.display="none",E.style.cursor=D.drag||G?"grabbing":"grab";P()},ue=ce=>{D.drag&&!G?Math.abs(ce.clientX-B)>3||(D.sel=D.sel===D.drag.id?null:D.drag.id):G&&Math.abs(ce.clientX-B)<3&&Math.abs(ce.clientY-oe)<3&&(D.sel=null),D.drag=null,G=!1,P()},Te=ce=>{ce.preventDefault();const Ce=E.getBoundingClientRect(),te=ce.clientX-Ce.left,he=ce.clientY-Ce.top,Fe=ce.deltaY>0?.9:1.1,ze=Math.max(.1,Math.min(5,D.zoom*Fe));D.panX=te-(te-D.panX)/D.zoom*ze,D.panY=he-(he-D.panY)/D.zoom*ze,D.zoom=ze,P()},Oe=()=>{f.current&&(f.current.style.display="none")};return E.addEventListener("mousedown",Ee),window.addEventListener("mousemove",J),window.addEventListener("mouseup",ue),E.addEventListener("wheel",Te,{passive:!1}),E.addEventListener("mouseleave",Oe),()=>{D.raf!=null&&cancelAnimationFrame(D.raf),O.disconnect(),E.removeEventListener("mousedown",Ee),window.removeEventListener("mousemove",J),window.removeEventListener("mouseup",ue),E.removeEventListener("wheel",Te),E.removeEventListener("mouseleave",Oe),h.current=null}},[r.data]),r.isLoading)return c.jsxs("div",{className:"nb-card flex items-center gap-2 text-sm text-[var(--color-text-muted)]",children:[c.jsx(Xe,{size:14,className:"animate-spin"})," ",n("graph.viz.loading")]});if(!((v=(k=r.data)==null?void 0:k.data)!=null&&v.nodes.length))return c.jsx("div",{className:"nb-card text-sm text-[var(--color-text-muted)]",children:n("graph.viz.empty")});const m=[{label:n("graph.stat.files"),value:t.files.toLocaleString()},{label:n("graph.stat.nodes"),value:t.nodes.toLocaleString()},{label:n("graph.stat.edges"),value:t.edges.toLocaleString()},{label:n("graph.stat.db"),value:Gz(t.dbSizeBytes)},{label:n("graph.stat.lastBuilt"),value:Vz(t.lastIndexedAt)}];return c.jsxs("div",{ref:l,className:"relative w-full flex-1 min-h-[420px] nb-card p-0 overflow-hidden",style:{background:"var(--color-bg-cream)"},children:[c.jsx("canvas",{ref:d,className:"block absolute inset-0",style:{cursor:"grab"}}),c.jsx("div",{ref:f,className:"absolute z-40 pointer-events-none nb-card bg-[var(--color-bg)] px-3 py-2 text-xs max-w-xs",style:{display:"none"}}),c.jsxs("div",{className:"absolute top-3 right-3 w-52 flex flex-col gap-2 pointer-events-none",children:[c.jsxs("div",{className:"relative pointer-events-auto",children:[c.jsx(ho,{size:14,className:"absolute left-3 top-1/2 -translate-y-1/2 text-[var(--color-text-subtle)]"}),c.jsx("input",{className:"nb-input pl-9 w-full text-sm",placeholder:n("graph.viz.search"),value:a,onChange:N=>o(N.target.value),"aria-label":n("graph.viz.search")})]}),c.jsxs("div",{className:"nb-card p-3 flex flex-col gap-1.5 pointer-events-auto bg-[var(--color-bg)]",children:[m.map(N=>c.jsxs("div",{className:"flex items-center justify-between gap-2 text-xs",children:[c.jsx("span",{className:"text-[var(--color-text-subtle)] shrink-0",children:N.label}),c.jsx("span",{className:"font-bold font-[family-name:var(--font-mono)] text-right",children:N.value})]},N.label)),c.jsx("div",{className:"mt-1 pt-1.5 border-t-[1.5px] border-dashed border-[var(--color-border-light)] flex flex-wrap gap-x-2 gap-y-1",children:g.map(N=>c.jsxs("span",{className:"inline-flex items-center gap-1 text-[10px] font-[family-name:var(--font-mono)]",children:[c.jsx("span",{className:"inline-block w-2.5 h-2.5 rounded-full border-[1.5px] border-[var(--color-text)]",style:{background:Cf(N)}}),N]},N))})]}),c.jsx("p",{className:"text-[10px] text-[var(--color-text-subtle)] text-right leading-tight pointer-events-none",children:n("graph.viz.hint")})]})]})}function Qz({name:e}){var m,y;const t=Be(),n=Gt(),r=Ye({queryKey:["graph-status",e],queryFn:()=>$z(e)}),a=()=>{n.invalidateQueries({queryKey:["graph-status",e]}),n.invalidateQueries({queryKey:["graph-data",e]})},o=Ct({mutationFn:()=>Fz(e),onSuccess:a}),l=Ct({mutationFn:()=>qz(e),onSuccess:a}),d=((m=r.data)==null?void 0:m.data)??null,f=o.isPending,h=l.isPending,g=f||h;return c.jsxs("div",{className:"flex flex-col gap-3 max-w-full flex-1 min-h-0",children:[c.jsxs("header",{className:"flex items-center justify-between flex-wrap gap-3 shrink-0",children:[c.jsxs("div",{className:"flex items-center gap-2 min-w-0",children:[c.jsx(YN,{size:20,strokeWidth:2.5,className:"shrink-0"}),c.jsx("h2",{className:"font-[family-name:var(--font-heading)] text-xl font-bold shrink-0",children:t("graph.title")}),c.jsx("span",{className:"text-xs text-[var(--color-text-muted)] truncate hidden sm:inline",children:t("graph.desc")})]}),c.jsxs("div",{className:"flex items-center gap-2 shrink-0",children:[d&&c.jsxs("button",{className:"nb-btn shrink-0",onClick:()=>l.mutate(),disabled:g,type:"button",title:t("graph.sync.desc"),children:[h?c.jsx(Xe,{size:14,strokeWidth:2.5,className:"animate-spin"}):c.jsx(dL,{size:14,strokeWidth:2.5}),t(h?"graph.syncing":"graph.sync")]}),c.jsxs("button",{className:"nb-btn nb-btn-mint shrink-0",onClick:()=>o.mutate(),disabled:g,type:"button",children:[f?c.jsx(Xe,{size:14,strokeWidth:2.5,className:"animate-spin"}):d?c.jsx(ya,{size:14,strokeWidth:2.5}):c.jsx(mL,{size:14,strokeWidth:2.5}),t(f?"graph.building":d?"graph.rebuild":"graph.build")]})]})]}),(o.isError||l.isError)&&c.jsxs("div",{className:"nb-card bg-[var(--color-crashed-bg)] text-sm shrink-0",children:[t("graph.buildFailed"),": ",((y=o.error||l.error)==null?void 0:y.message)??""]}),r.isLoading?c.jsxs("div",{className:"nb-card flex items-center gap-2 text-sm text-[var(--color-text-muted)]",children:[c.jsx(Xe,{size:14,className:"animate-spin"})," ",t("graph.viz.loading")]}):d?c.jsx(Yz,{name:e,status:d}):c.jsx("div",{className:"nb-card text-sm text-[var(--color-text-muted)]",children:t("graph.empty")})]})}const Nk=["overview","config","pipelines","skills","rules","graph","logs","danger"];function Wz({name:e,embedded:t}={}){var b;const n=Be(),{name:r=""}=Mb(),a=e??r,o=ks(),[l]=BN(),[d,f]=Kb("projectDetail.tab","overview"),h=Nk.includes(d)?d:"overview",g=l.get("tab"),m=l.get("worker")??void 0;j.useEffect(()=>{g&&Nk.includes(g)&&f(g)},[g]);const y=Ye({queryKey:["project",a],queryFn:()=>$3(a),enabled:!!a});return c.jsxs("div",{className:"flex flex-col gap-4 w-full flex-1 min-h-0",children:[c.jsxs("header",{className:"flex items-center gap-3 shrink-0",children:[!t&&c.jsxs("button",{type:"button",onClick:()=>o("/projects"),className:"nb-btn",style:{padding:"6px 12px"},"aria-label":n("newProject.back.aria"),children:[c.jsx(UN,{size:14,strokeWidth:3}),n("newProject.back")]}),c.jsx("h1",{className:"font-[family-name:var(--font-heading)] text-3xl font-bold flex-1 truncate",children:a})]}),c.jsxs("nav",{className:"flex items-center gap-2 flex-wrap shrink-0",children:[c.jsx(ts,{current:h,value:"overview",onSelect:f,icon:tL,children:n("projectDetail.tab.overview")}),c.jsx(ts,{current:h,value:"config",onSelect:f,icon:XN,children:n("projectDetail.tab.config")}),c.jsx(ts,{current:h,value:"pipelines",onSelect:f,icon:Ub,children:n("projectDetail.tab.pipelines")}),c.jsx(ts,{current:h,value:"skills",onSelect:f,icon:ZN,children:n("projectDetail.tab.skills")}),c.jsx(ts,{current:h,value:"rules",onSelect:f,icon:TR,children:n("projectDetail.tab.rules")}),c.jsx(ts,{current:h,value:"graph",onSelect:f,icon:YN,children:n("projectDetail.tab.graph")}),c.jsx(ts,{current:h,value:"logs",onSelect:f,icon:Bb,children:n("projectDetail.tab.logs")}),c.jsx(ts,{current:h,value:"danger",onSelect:f,icon:fi,children:n("projectDetail.tab.danger")}),c.jsx(vs,{to:`/board?project=${encodeURIComponent(a)}`,className:"nb-btn nb-btn-mint ml-auto",children:n("projectDetail.openBoard")})]}),c.jsxs("div",{className:"flex-1 min-h-0 overflow-y-auto pr-1 flex flex-col",children:[h==="overview"&&c.jsx(Xz,{name:a,data:y.data,loading:y.isLoading}),h==="config"&&c.jsx(Zz,{name:a}),h==="pipelines"&&c.jsx(Jz,{name:a}),h==="skills"&&c.jsx(Pz,{name:a}),h==="rules"&&c.jsx(Bz,{name:a}),h==="graph"&&c.jsx(Qz,{name:a}),h==="logs"&&c.jsx(lI,{project:a,initialWorker:h==="logs"?m:void 0}),h==="danger"&&c.jsx(e4,{name:a,repoDir:((b=y.data)==null?void 0:b.repoDir)??null})]})]})}function ts({current:e,value:t,onSelect:n,icon:r,children:a}){const o=e===t;return c.jsxs("button",{type:"button",onClick:()=>n(t),"aria-current":o?"page":void 0,className:["nb-btn",o?"nb-btn-primary":""].join(" "),style:{padding:"6px 14px",fontSize:13},children:[c.jsx(r,{size:13,strokeWidth:2.5}),a]})}function Xz({name:e,data:t,loading:n}){const r=Be();return n?c.jsx("div",{className:"nb-card",children:c.jsx("p",{className:"text-[var(--color-text-muted)]",children:r("common.loading")})}):t?c.jsx("div",{className:"nb-card",children:c.jsxs("dl",{className:"grid grid-cols-[160px_1fr] gap-y-3 text-sm",children:[c.jsx("dt",{className:"font-bold",children:r("projectDetail.overview.repoDir")}),c.jsx("dd",{className:"font-[family-name:var(--font-mono)]",children:t.repoDir??"—"}),c.jsx("dt",{className:"font-bold",children:r("projectDetail.overview.pmBackend")}),c.jsx("dd",{className:"font-[family-name:var(--font-mono)]",children:t.pmBackend}),c.jsx("dt",{className:"font-bold",children:r("projectDetail.overview.agent")}),c.jsx("dd",{className:"font-[family-name:var(--font-mono)]",children:t.agentProvider}),c.jsx("dt",{className:"font-bold",children:r("projectDetail.overview.cards")}),c.jsx("dd",{className:"font-[family-name:var(--font-mono)]",children:r("projectDetail.overview.cards.value",{total:t.cards.total,inprogress:t.cards.inprogress,done:t.cards.done})}),c.jsx("dt",{className:"font-bold",children:r("projectDetail.overview.workers")}),c.jsx("dd",{className:"font-[family-name:var(--font-mono)]",children:r("projectDetail.overview.workers.value",{total:t.workers.total,active:t.workers.active})}),c.jsx("dt",{className:"font-bold",children:r("projectDetail.overview.pipeline")}),c.jsx("dd",{className:"font-[family-name:var(--font-mono)]",children:t.pipelineStatus}),c.jsx("dt",{className:"font-bold",children:r("projectDetail.overview.lastActivity")}),c.jsx("dd",{className:"font-[family-name:var(--font-mono)]",children:t.lastActivityAt?new Date(t.lastActivityAt).toLocaleString():"—"})]})}):c.jsx("div",{className:"nb-card bg-[var(--color-crashed-bg)]",children:c.jsx("p",{children:r("projectDetail.overview.notFound",{name:e})})})}function Zz({name:e}){const t=Be(),n=Gt(),{alert:r}=un(),{data:a,isLoading:o,isError:l,error:d,refetch:f}=Ye({queryKey:["project-conf",e],queryFn:()=>F3(e)}),[h,g]=j.useState(null),[m,y]=j.useState(null);j.useEffect(()=>{a&&h===null&&(g(a.content),y(a.etag))},[a,h]);const b=h!==null&&a!==void 0&&h!==a.content,k=Ct({mutationFn:()=>{if(h===null||m===null)throw new Error("no draft");return q3(e,h,m)},onSuccess:v=>{y(v.etag),n.invalidateQueries({queryKey:["project-conf",e]}),n.invalidateQueries({queryKey:["project",e]})},onError:v=>{const N=v.status;r({title:t(N===409?"projectDetail.config.error.conflict.title":"projectDetail.config.error.save.title"),body:N===409?t("projectDetail.config.error.conflict.body"):v instanceof Error?v.message:String(v)})}});return o?c.jsx("div",{className:"nb-card",children:c.jsx("p",{className:"text-[var(--color-text-muted)]",children:t("common.loading")})}):l?c.jsx("div",{className:"nb-card bg-[var(--color-crashed-bg)]",children:c.jsx("p",{children:t("projectDetail.config.error.load",{detail:d instanceof Error?d.message:String(d)})})}):c.jsxs("div",{className:"nb-card",children:[c.jsxs("div",{className:"flex items-center justify-between mb-3",children:[c.jsxs("div",{children:[c.jsx("h2",{className:"font-[family-name:var(--font-heading)] text-lg font-bold",children:c.jsxs("code",{className:"font-[family-name:var(--font-mono)] text-sm bg-[var(--color-bg-cream)] border-2 border-[var(--color-text)] px-2 py-0.5 rounded",children:["~/.coral/projects/",e,"/conf"]})}),m&&c.jsxs("p",{className:"text-xs text-[var(--color-text-muted)] font-[family-name:var(--font-mono)] mt-1",children:["etag: ",m]})]}),c.jsxs("div",{className:"flex gap-2",children:[c.jsxs("button",{type:"button",className:"nb-btn",style:{padding:"6px 12px"},onClick:()=>{g(null),f()},disabled:k.isPending,"aria-label":t("projectDetail.config.reload"),children:[c.jsx(ya,{size:13,strokeWidth:2.5}),t("projectDetail.config.reload")]}),c.jsxs("button",{type:"button",className:"nb-btn nb-btn-primary",style:{padding:"6px 12px"},onClick:()=>k.mutate(),disabled:!b||k.isPending,"aria-label":t("projectDetail.config.saveAria"),children:[k.isPending?c.jsx(Xe,{size:13,strokeWidth:3,className:"animate-spin"}):k.isSuccess&&!b?c.jsx(RR,{size:13,strokeWidth:3}):c.jsx(Ri,{size:13,strokeWidth:3}),t("projectDetail.config.save")]})]})]}),c.jsx("textarea",{className:"nb-input w-full font-[family-name:var(--font-mono)] text-xs",style:{minHeight:480,resize:"vertical"},value:h??"",onChange:v=>g(v.target.value),spellCheck:!1,"aria-label":t("projectDetail.config.editorAria")}),b&&c.jsx("p",{className:"text-xs text-[var(--color-stuck)] mt-2 font-bold",children:t("projectDetail.config.confDirty")})]})}function Jz({name:e}){const t=Be(),n=Gt(),{confirm:r,alert:a}=un(),{data:o,isLoading:l}=Ye({queryKey:["project-pipelines",e],queryFn:()=>K3(e)}),[d,f]=j.useState(null),[h,g]=j.useState(!1),m=Ct({mutationFn:v=>G3(e,v),onSuccess:()=>n.invalidateQueries({queryKey:["project-pipelines",e]}),onError:v=>{a({title:t("projectDetail.pipelines.switch.error"),body:v instanceof Error?v.message:String(v)})}}),y=Ct({mutationFn:v=>W3(e,v),onSuccess:()=>n.invalidateQueries({queryKey:["project-pipelines",e]}),onError:v=>{a({title:t("projectDetail.pipelines.delete.error"),body:v instanceof Error?v.message:String(v)})}}),b=Ct({mutationFn:v=>Q3(e,v.name,v.template),onSuccess:v=>{n.invalidateQueries({queryKey:["project-pipelines",e]}),g(!1),f(v.name)},onError:v=>{a({title:t("projectDetail.pipelines.create.error"),body:v instanceof Error?v.message:String(v)})}});if(l)return c.jsx("div",{className:"nb-card",children:c.jsx("p",{className:"text-[var(--color-text-muted)]",children:t("common.loading")})});const k=[];o!=null&&o.active&&k.push({name:o.active,isActive:!0});for(const v of(o==null?void 0:o.available)??[])k.push({name:v.name,isActive:!1});return c.jsxs(c.Fragment,{children:[c.jsxs("div",{className:"nb-card",children:[c.jsxs("div",{className:"flex items-center justify-between mb-3",children:[c.jsx("h2",{className:"font-[family-name:var(--font-heading)] text-lg font-bold",children:t("projectDetail.pipelines.title")}),c.jsxs("button",{type:"button",className:"nb-btn nb-btn-mint",style:{padding:"6px 12px",fontSize:12},onClick:()=>g(!0),disabled:b.isPending,"aria-label":t("projectDetail.pipelines.add"),children:[c.jsx(pr,{size:12,strokeWidth:3}),t("projectDetail.pipelines.add")]})]}),k.length===0?c.jsx("p",{className:"text-sm text-[var(--color-text-muted)] italic p-4 border-2 border-dashed border-[var(--color-text)] rounded-lg text-center",children:t("projectDetail.pipelines.empty")}):c.jsx("ul",{className:"flex flex-col gap-2",children:k.map(v=>c.jsxs("li",{className:"flex items-center gap-3 p-3 bg-[var(--color-bg-cream)] border-2 border-[var(--color-text)] rounded-lg",children:[c.jsx(Ub,{size:16,strokeWidth:2.5}),c.jsx("span",{className:"font-[family-name:var(--font-mono)] font-bold flex-1",children:v.name}),v.isActive&&c.jsx("span",{className:"nb-status",style:{background:"var(--color-running-bg)",color:"var(--color-running)"},children:t("projectDetail.pipelines.activeBadge")}),c.jsxs("div",{className:"flex gap-1",children:[c.jsxs("button",{type:"button",className:"nb-btn",style:{padding:"4px 10px",fontSize:11},onClick:()=>f(v.name),"aria-label":t("projectDetail.pipelines.editAria",{name:v.name}),children:[c.jsx(qh,{size:11,strokeWidth:2.5}),t("projectDetail.pipelines.edit")]}),!v.isActive&&c.jsxs(c.Fragment,{children:[c.jsx("button",{type:"button",className:"nb-btn nb-btn-primary",style:{padding:"4px 10px",fontSize:11},onClick:async()=>{await r({title:t("projectDetail.pipelines.switch.confirm.title",{name:v.name}),body:t("projectDetail.pipelines.switch.confirm.body",{name:v.name}),confirm:t("projectDetail.pipelines.switch.confirm.button")})&&m.mutate(v.name)},disabled:m.isPending,"aria-label":t("projectDetail.pipelines.switchAria",{name:v.name}),children:t("projectDetail.pipelines.switch")}),c.jsx("button",{type:"button",className:"nb-btn nb-btn-danger",style:{padding:"4px 10px",fontSize:11},onClick:async()=>{await r({title:t("projectDetail.pipelines.delete.confirm.title",{name:v.name}),body:t("projectDetail.pipelines.delete.confirm.body"),confirm:t("common.delete"),danger:!0})&&y.mutate(v.name)},disabled:y.isPending,"aria-label":t("projectDetail.pipelines.deleteAria",{name:v.name}),children:c.jsx(fi,{size:11,strokeWidth:2.5})})]})]})]},v.name))})]}),d&&c.jsx(Ez,{projectName:e,file:d,onClose:()=>f(null),onSaved:()=>{n.invalidateQueries({queryKey:["project-pipelines",e]})}}),h&&c.jsx(_z,{hasActive:!!(o!=null&&o.active),hasSample:!0,isPending:b.isPending,onCancel:()=>g(!1),onCreate:(v,N)=>b.mutate({name:v,template:N})})]})}function e4({name:e,repoDir:t}){const n=Be(),r=ks(),a=Gt(),{alert:o}=un(),[l,d]=j.useState(""),[f,h]=j.useState(!0),g=Ct({mutationFn:()=>H3(e,{includeClaudeDir:f}),onSuccess:v=>{a.invalidateQueries({queryKey:["projects"]});const N=v.claudeRemoved.filter(E=>E.ok).map(E=>E.path);o({title:n("projectDetail.danger.deleted.title"),body:N.length>0?n("projectDetail.danger.deleted.bodyWithList",{paths:N.join(`
|
|
602
|
-
`)}):n("projectDetail.danger.deleted.body")}).then(()=>r("/projects"))},onError:v=>{o({title:n("projectDetail.danger.error"),body:v instanceof Error?v.message:String(v)})}}),y=n("projectDetail.danger.body",{path:"__PATH__"}).split("__PATH__"),k=n("projectDetail.danger.confirmPrompt",{name:"__NAME__"}).split("__NAME__");return c.jsxs("div",{className:"nb-card bg-[var(--color-crashed-bg)]",children:[c.jsx("h2",{className:"font-[family-name:var(--font-heading)] text-lg font-bold mb-2 text-[var(--color-crashed)]",children:n("projectDetail.danger.title")}),c.jsxs("p",{className:"text-sm mb-4",children:[y[0],c.jsxs("code",{className:"font-[family-name:var(--font-mono)] bg-[var(--color-bg)] border-2 border-[var(--color-text)] px-1.5 py-0.5 rounded",children:["~/.coral/projects/",e,"/"]}),y[1]]}),t&&c.jsxs("label",{className:"flex items-start gap-2 mb-4 p-3 bg-[var(--color-bg)] border-2 border-[var(--color-text)] rounded-lg cursor-pointer",children:[c.jsx("input",{type:"checkbox",checked:f,onChange:v=>h(v.target.checked),className:"mt-0.5"}),c.jsxs("div",{className:"flex-1",children:[c.jsx("div",{className:"text-sm font-bold",children:n("projectDetail.danger.includeClaude.label")}),c.jsxs("div",{className:"text-xs text-[var(--color-text-muted)] font-[family-name:var(--font-mono)]",children:[t,"/.claude/"]}),c.jsx("div",{className:"text-xs text-[var(--color-text-muted)] mt-1",children:n("projectDetail.danger.includeClaude.note")})]})]}),c.jsx("div",{className:"mb-4",children:c.jsxs("label",{className:"flex flex-col gap-1.5",children:[c.jsxs("span",{className:"text-sm font-bold",children:[k[0],c.jsx("code",{className:"font-[family-name:var(--font-mono)] text-xs",children:e}),k[1]]}),c.jsx("input",{type:"text",className:"nb-input w-full font-[family-name:var(--font-mono)]",value:l,onChange:v=>d(v.target.value),placeholder:e})]})}),c.jsxs("button",{type:"button",className:"nb-btn nb-btn-danger",disabled:l!==e||g.isPending,onClick:()=>g.mutate(),"aria-label":n("projectDetail.danger.deleteAria"),children:[g.isPending?c.jsx(Xe,{size:14,strokeWidth:3,className:"animate-spin"}):c.jsx(fi,{size:14,strokeWidth:3}),n("projectDetail.danger.deleteButton")]})]})}function lx(){return ft("/api/providers")}function c2(e){const t=[];for(const n of e)for(const r of n.models)t.push({providerId:n.id,model:r,label:`${r} · ${n.name}`});return t}async function t4(e,t){const n=await fetch("/api/providers",{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify({kind:e,entry:t})});if(!n.ok)throw new Error(`${n.status}: ${await n.text()}`);return n.json()}async function n4(e,t){const n=await fetch(`/api/providers/${e}/${encodeURIComponent(t)}`,{method:"DELETE"});if(!n.ok)throw new Error(`${n.status}: ${await n.text()}`);return n.json()}function u2(e){const t=e?`?path=${encodeURIComponent(e)}`:"";return ft(`/api/fs/browse${t}`)}async function r4(e,t){const n=await fetch("/api/fs/mkdir",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({path:e,name:t})});if(!n.ok){const r=await n.text();throw new Error(`${n.status}: ${r}`)}return await n.json()}const d2=50*1024*1024;async function i4(e,t){if(t.size>d2)throw new Error(`文件超过 50 MB 上限(当前 ${(t.size/1024/1024).toFixed(2)} MB)`);const n=new FormData;n.append("sessionId",e),n.append("file",t,t.name);const r=await fetch("/api/fs/upload",{method:"POST",body:n});if(!r.ok){const a=await r.text();throw new Error(`${r.status}: ${a}`)}return await r.json()}function Yy(e,t){return`/api/fs/file?${new URLSearchParams({path:t,sessionId:e}).toString()}`}function cx({initialPath:e,onCancel:t,onSelect:n,title:r,mode:a="directory"}){var C,S,_;const o=Be(),{prompt:l,alert:d}=un(),f=r??o("dirPicker.title.default"),[h,g]=j.useState(e??null),[m,y]=j.useState(null),b=Ye({queryKey:["fs-browse",h],queryFn:()=>u2(h??void 0),staleTime:0,gcTime:0}),k=((C=b.data)==null?void 0:C.path)??h??"",v=((S=b.data)==null?void 0:S.parent)??null,N=((_=b.data)==null?void 0:_.home)??null,E=async()=>{var T;if(!k)return;const M=(T=await l({title:o("dirPicker.newDir"),body:o("dirPicker.newDir.prompt"),placeholder:o("dirPicker.newDir.placeholder"),confirm:o("dirPicker.newDir.create")}))==null?void 0:T.trim();if(M)try{const L=await r4(k,M);g(L.path)}catch(L){d({title:o("dirPicker.newDir.error.title"),body:L instanceof Error?L.message:String(L)})}};return j.useEffect(()=>{const M=T=>{T.key==="Escape"&&(T.preventDefault(),t())};return window.addEventListener("keydown",M),()=>window.removeEventListener("keydown",M)},[t]),c.jsx("div",{className:"fixed inset-0 z-50 flex items-center justify-center bg-[rgba(45,55,72,0.5)] p-4",role:"presentation",children:c.jsxs("div",{className:"nb-card bg-[var(--color-bg)] max-w-lg w-full p-5 flex flex-col",style:{maxHeight:"70vh"},role:"dialog","aria-modal":"true","aria-label":f,children:[c.jsxs("header",{className:"flex items-center justify-between mb-3 shrink-0",children:[c.jsx("div",{className:"flex items-center gap-2 min-w-0",children:c.jsx("h3",{className:"font-[family-name:var(--font-heading)] font-bold text-base truncate",children:f})}),c.jsx("button",{type:"button",className:"p-1 hover:bg-[var(--color-bg-cream)] rounded",onClick:t,"aria-label":o("dirPicker.close.aria"),children:c.jsx(Sn,{size:14,strokeWidth:3})})]}),c.jsxs("div",{className:"flex items-center gap-2 mb-3 shrink-0",children:[c.jsx("button",{type:"button",className:"nb-btn flex-shrink-0",style:{padding:"4px 10px",fontSize:12},onClick:()=>v&&g(v),disabled:!v||b.isLoading,"aria-label":o("dirPicker.up.aria"),title:o("dirPicker.up.title"),children:c.jsx(FN,{size:12,strokeWidth:3})}),c.jsx("button",{type:"button",className:"nb-btn flex-shrink-0",style:{padding:"4px 10px",fontSize:12},onClick:()=>N&&g(N),disabled:!N||b.isLoading,"aria-label":o("dirPicker.home.aria"),title:o("dirPicker.home.title"),children:c.jsx(xL,{size:12,strokeWidth:3})}),c.jsx("button",{type:"button",className:"nb-btn flex-shrink-0",style:{padding:"4px 10px",fontSize:12},onClick:()=>void E(),disabled:!k||b.isLoading||b.isError,"aria-label":o("dirPicker.newDir.aria"),title:o("dirPicker.newDir.aria"),children:c.jsx(iL,{size:12,strokeWidth:3})}),c.jsx("div",{className:"flex-1 min-w-0 nb-input font-[family-name:var(--font-mono)] text-xs px-2 py-1.5 truncate",title:k,dir:"rtl",children:k||"..."})]}),c.jsxs("div",{className:"flex-1 overflow-y-auto border-2 border-[var(--color-text)] rounded-lg bg-[var(--color-bg-cream)] min-h-0",children:[b.isLoading&&c.jsxs("div",{className:"flex items-center justify-center py-12 text-[var(--color-text-muted)]",children:[c.jsx(Xe,{size:16,strokeWidth:3,className:"animate-spin mr-2"}),o("dirPicker.loading")]}),b.isError&&c.jsxs("div",{className:"p-4 text-sm text-[var(--color-crashed)]",children:[c.jsx("p",{className:"font-bold mb-1",children:o("dirPicker.error.title")}),c.jsx("p",{className:"text-xs font-[family-name:var(--font-mono)] break-all",children:b.error instanceof Error?b.error.message:String(b.error)})]}),b.data&&c.jsxs("ul",{className:"divide-y-2 divide-[var(--color-text)]/20",children:[b.data.entries.length===0&&c.jsx("li",{className:"p-4 text-xs text-[var(--color-text-subtle)] italic text-center",children:o("dirPicker.empty")}),b.data.entries.map(M=>{const T=(()=>{const $=k.endsWith("/")||k.endsWith("\\")?"":"/";return`${k}${$}${M.name}`})(),L=a==="file"&&m===T,R=M.isDirectory||a==="file";return c.jsx("li",{children:c.jsxs("button",{type:"button",className:["w-full flex items-center gap-2 px-3 py-2 text-left text-sm font-[family-name:var(--font-mono)]","disabled:opacity-50 disabled:cursor-not-allowed",L?"bg-[var(--color-accent-mint)] font-bold":"hover:bg-[var(--color-accent-mint)]"].join(" "),disabled:!R,onClick:()=>{M.isDirectory?(y(null),g(T)):a==="file"&&y(T)},onDoubleClick:()=>{a==="file"&&!M.isDirectory&&n(T)},title:M.isDirectory?o("dirPicker.enter.aria",{name:M.name}):a==="file"?o("dirPicker.pickFile.aria",{name:M.name}):o("dirPicker.fileLocked"),children:[M.isDirectory?c.jsx(ph,{size:14,strokeWidth:2.5,className:"flex-shrink-0 text-[var(--color-text)]"}):c.jsx("span",{className:"w-3.5 h-3.5 flex-shrink-0"}),c.jsx("span",{className:"truncate",children:M.name}),M.isDirectory&&c.jsx(Zl,{size:12,strokeWidth:2.5,className:"ml-auto flex-shrink-0 text-[var(--color-text-muted)]"})]})},M.name)})]})]}),c.jsxs("div",{className:"flex gap-2 justify-end pt-3 shrink-0",children:[c.jsx("button",{type:"button",className:"nb-btn",onClick:t,children:o("dirPicker.cancel")}),a==="file"?c.jsxs("button",{type:"button",className:"nb-btn nb-btn-primary",onClick:()=>m&&n(m),disabled:!m||b.isLoading||b.isError,title:m??o("dirPicker.useFile.tooltip.empty"),children:[c.jsx(Eu,{size:14,strokeWidth:3}),o("dirPicker.useFile")]}):c.jsxs("button",{type:"button",className:"nb-btn nb-btn-primary",onClick:()=>n(k),disabled:!k||b.isLoading||b.isError,children:[c.jsx(Eu,{size:14,strokeWidth:3}),o("dirPicker.useDir")]})]})]})})}function Af(e){return(e.replace(/\/+$/,"").split("/").pop()??"").replace(/[^a-zA-Z0-9_-]/g,"-").replace(/-+/g,"-").replace(/^-+|-+$/g,"")}function f2({onCancel:e,onCreated:t}={}){var z,q,F,Y,D,H;const n=Be(),r=ks(),a=Gt(),{alert:o}=un(),l=e??(()=>r("/projects")),[d,f]=j.useState({name:"",projectDir:"",enableGit:!0,createIfMissing:!0,mergeBranch:"main",maxWorkers:"1",ackTimeoutMin:"5",pipelineMode:"pipeline"}),h=d.pipelineMode==="smartArrange",g=Ye({queryKey:["system-agents"],queryFn:Hb}),m=((z=g.data)==null?void 0:z.agents.worker.model)??"",y=((q=g.data)==null?void 0:q.agents.reviewer.model)??"",b=[...new Set((((F=g.data)==null?void 0:F.providers.openai)??[]).flatMap(O=>O.models))],k=Ye({queryKey:["providers"],queryFn:lx}),v=c2(((Y=k.data)==null?void 0:Y.anthropic)??[]),N=d.workerModel?`${d.workerProviderId??""}::${d.workerModel}`:"",[E,C]=j.useState(!1),S=Ct({mutationFn:O=>U3(O),onSuccess:O=>{a.invalidateQueries({queryKey:["projects"]}),t?t(O.name):r(`/projects/${encodeURIComponent(O.name)}`)},onError:O=>{o({title:n("newProject.error.create.title"),body:O instanceof Error?O.message:String(O)})}}),_=/^[a-zA-Z0-9_-]+$/.test(d.name),M=_&&d.projectDir.trim()!==""&&!S.isPending,T=d.projectDir.trim(),L=Ye({queryKey:["fs-browse-probe",T],queryFn:()=>u2(T),enabled:T.startsWith("/"),staleTime:0,gcTime:0,retry:!1}),R=L.isSuccess&&(((D=L.data)==null?void 0:D.entries.length)??0)>0,$=L.isError||L.isSuccess&&(((H=L.data)==null?void 0:H.entries.length)??0)===0;return c.jsxs("div",{className:"w-full",children:[c.jsxs("div",{className:"nb-card flex flex-col gap-4",children:[c.jsxs("header",{className:"flex items-center gap-3",children:[c.jsxs("button",{type:"button",onClick:l,className:"nb-btn",style:{padding:"6px 12px"},"aria-label":n("newProject.back.aria"),children:[c.jsx(UN,{size:14,strokeWidth:3}),n("newProject.back")]}),c.jsx("h1",{className:"font-[family-name:var(--font-heading)] text-2xl font-bold",children:n("newProject.title")})]}),c.jsxs("form",{onSubmit:O=>{O.preventDefault(),M&&S.mutate(d)},className:"grid grid-cols-1 md:grid-cols-2 gap-x-6 gap-y-4",children:[c.jsx(Ur,{className:"md:col-span-2",label:n("newProject.field.mode"),hint:n(h?"newProject.field.mode.smartHint":"newProject.field.mode.pipelineHint"),children:c.jsx("div",{className:"grid grid-cols-1 sm:grid-cols-2 gap-3",children:["pipeline","smartArrange"].map(O=>{const V=d.pipelineMode===O;return c.jsxs("button",{type:"button",onClick:()=>f({...d,pipelineMode:O}),"aria-pressed":V,className:["text-left rounded-xl border-2 p-3 transition-all",V?"bg-[var(--color-accent-mint)] border-[var(--color-text)] shadow-[3px_3px_0_var(--color-text)] font-bold":"bg-[var(--color-bg)] border-[var(--color-border-light)] hover:border-[var(--color-text)]"].join(" "),children:[c.jsx("div",{className:"text-sm font-bold",children:n(O==="pipeline"?"newProject.field.mode.pipeline":"newProject.field.mode.smart")}),c.jsx("div",{className:"text-xs text-[var(--color-text-muted)] mt-0.5",children:n(O==="pipeline"?"newProject.field.mode.pipelineDesc":"newProject.field.mode.smartDesc")})]},O)})})}),h&&c.jsx(Ur,{className:"md:col-span-2",label:n("newProject.field.goal"),hint:n("newProject.field.goal.hint"),children:c.jsx("textarea",{className:"nb-input w-full font-[family-name:var(--font-mono)] text-sm",style:{minHeight:110,resize:"vertical"},placeholder:n("newProject.field.goal.placeholder"),value:d.goal??"",onChange:O=>f({...d,goal:O.target.value})})}),c.jsx(Ur,{label:"Worker 模型",hint:`默认:${m||"全局默认"}(留空用默认)`,children:c.jsxs("select",{className:"nb-input w-full font-[family-name:var(--font-mono)] text-xs",value:N,onChange:O=>{const V=O.target.value;if(!V)return f({...d,workerModel:void 0,workerProviderId:void 0});const[Q,K]=V.split("::");f({...d,workerModel:K,workerProviderId:Q||void 0})},children:[c.jsx("option",{value:"",children:"用全局默认模型"}),v.map(O=>c.jsx("option",{value:`${O.providerId}::${O.model}`,children:O.label},`${O.providerId}::${O.model}`))]})}),h&&c.jsxs(Ur,{label:"OpenAI Agent(监工)模型",hint:`默认:${y||"全局默认"}(留空用默认)`,children:[c.jsx("input",{className:"nb-input w-full font-[family-name:var(--font-mono)] text-xs",value:d.reviewerModel??"",onChange:O=>f({...d,reviewerModel:O.target.value}),placeholder:y,list:"np-reviewer-models",spellCheck:!1}),c.jsx("datalist",{id:"np-reviewer-models",children:b.map(O=>c.jsx("option",{value:O},O))})]}),c.jsxs(Ur,{label:n("newProject.field.name"),hint:n("newProject.field.name.derived"),children:[c.jsx("input",{type:"text",className:"nb-input w-full font-[family-name:var(--font-mono)]",placeholder:n("newProject.field.name.placeholder"),value:d.name,onChange:O=>f({...d,name:O.target.value}),required:!0}),d.name&&!_&&c.jsx("p",{className:"text-xs text-[var(--color-crashed)] mt-1",children:n("newProject.field.name.invalid")})]}),c.jsxs(Ur,{className:"md:col-span-2",label:n("newProject.field.dir"),hint:n("newProject.field.dir.long"),children:[c.jsxs("div",{className:"flex gap-2",children:[c.jsx("input",{type:"text",className:"nb-input flex-1 font-[family-name:var(--font-mono)]",placeholder:n("newProject.field.dir.placeholder"),value:d.projectDir,onChange:O=>{const V=O.target.value,Q=Af(V),K=Af(d.projectDir),I=d.name&&d.name!==K;f({...d,projectDir:V,name:I?d.name:Q})},required:!0}),c.jsxs("button",{type:"button",className:"nb-btn flex-shrink-0",onClick:()=>C(!0),"aria-label":n("newProject.dir.browseAria"),title:n("newProject.dir.browseAria"),children:[c.jsx(KN,{size:14,strokeWidth:2.5}),n("newProject.dir.browse")]})]}),R&&c.jsx("p",{className:"text-xs mt-1.5 font-bold text-[var(--color-text)]",children:n("newProject.field.dir.adopt")}),$&&T.startsWith("/")&&c.jsx("p",{className:"text-xs mt-1.5 text-[var(--color-text-muted)]",children:n("newProject.field.dir.fresh")}),c.jsxs("label",{className:"flex items-center gap-2 mt-2 cursor-pointer select-none",children:[c.jsx("input",{type:"checkbox",checked:d.createIfMissing!==!1,onChange:O=>f({...d,createIfMissing:O.target.checked}),className:"w-4 h-4 cursor-pointer"}),c.jsx("span",{className:"text-xs text-[var(--color-text-muted)]",children:n("newProject.field.dir.createIfMissing")})]})]}),c.jsx(Ur,{label:n("newProject.field.maxWorkers.short"),children:c.jsx("input",{type:"number",min:"1",max:"8",className:"nb-input w-full font-[family-name:var(--font-mono)]",value:d.maxWorkers,onChange:O=>f({...d,maxWorkers:O.target.value})})}),c.jsx(Ur,{label:n("newProject.field.ackTimeout.minutes"),hint:n("newProject.field.ackTimeout.minutes.help"),children:c.jsx("input",{type:"number",min:"1",max:"30",className:"nb-input w-full font-[family-name:var(--font-mono)]",value:d.ackTimeoutMin??"5",onChange:O=>f({...d,ackTimeoutMin:O.target.value})})}),c.jsxs("div",{className:"md:col-span-2 pt-3 border-t-2 border-[var(--color-text)] border-dashed",children:[c.jsxs("label",{className:"flex items-center gap-3 mb-3 cursor-pointer select-none",children:[c.jsx("input",{type:"checkbox",checked:d.enableGit??!0,onChange:O=>f({...d,enableGit:O.target.checked}),className:"w-4 h-4 cursor-pointer"}),c.jsx("span",{className:"text-sm font-bold",children:n("newProject.field.git.label")})]}),c.jsx("p",{className:"text-xs text-[var(--color-text-muted)] mb-3",children:n("newProject.field.git.detail")}),d.enableGit!==!1&&c.jsxs("div",{className:"flex flex-col gap-4 bg-[var(--color-bg-cream)] border-2 border-[var(--color-text)] rounded-lg p-4",children:[c.jsx(Ur,{label:n("newProject.field.git.branch"),children:c.jsx("input",{type:"text",className:"nb-input w-full font-[family-name:var(--font-mono)]",value:d.mergeBranch??"main",onChange:O=>f({...d,mergeBranch:O.target.value})})}),c.jsx(Ur,{label:n("newProject.field.gitlabProject.label"),hint:n("newProject.field.gitlabProject.help2"),children:c.jsx("input",{type:"text",className:"nb-input w-full font-[family-name:var(--font-mono)]",placeholder:n("newProject.field.gitlabProject.placeholder"),value:d.gitlabProject??"",onChange:O=>f({...d,gitlabProject:O.target.value})})}),d.gitlabProject&&c.jsx(Ur,{label:n("newProject.field.gitlabProjectId"),hint:n("newProject.field.gitlabProjectId.help"),children:c.jsx("input",{type:"text",className:"nb-input w-full font-[family-name:var(--font-mono)]",placeholder:n("newProject.field.gitlabProjectId.placeholder"),value:d.gitlabProjectId??"",onChange:O=>f({...d,gitlabProjectId:O.target.value})})})]})]}),c.jsxs("div",{className:"md:col-span-2 pt-3 border-t-2 border-[var(--color-text)] border-dashed",children:[c.jsx("h3",{className:"font-[family-name:var(--font-heading)] text-sm font-bold uppercase tracking-wider mb-3 text-[var(--color-text-muted)]",children:n("newProject.section.notifications")}),c.jsx(Ur,{label:n("newProject.field.matrixRoom.label"),hint:n("newProject.field.matrixRoom.help2"),children:c.jsx("input",{type:"text",className:"nb-input w-full font-[family-name:var(--font-mono)]",placeholder:n("newProject.field.matrixRoom.placeholder"),value:d.matrixRoomId??"",onChange:O=>f({...d,matrixRoomId:O.target.value})})})]}),c.jsxs("div",{className:"md:col-span-2 flex gap-3 justify-end pt-3",children:[c.jsx("button",{type:"button",className:"nb-btn",onClick:l,disabled:S.isPending,children:n("common.cancel")}),c.jsx("button",{type:"submit",className:"nb-btn nb-btn-primary",disabled:!M,"aria-label":n("newProject.submit"),children:S.isPending?c.jsxs(c.Fragment,{children:[c.jsx(Xe,{size:14,strokeWidth:3,className:"animate-spin"}),n("newProject.creating")]}):c.jsxs(c.Fragment,{children:[c.jsx(pr,{size:14,strokeWidth:3}),n("common.create")]})})]})]})]}),E&&c.jsx(cx,{title:n("newProject.field.dir.pickerTitle"),initialPath:d.projectDir.trim()||void 0,onCancel:()=>C(!1),onSelect:O=>{const V=Af(O),Q=Af(d.projectDir),K=d.name&&d.name!==Q;f({...d,projectDir:O,name:K?d.name:V}),C(!1)}})]})}function Ur({label:e,hint:t,children:n,className:r}){return c.jsxs("label",{className:`flex flex-col gap-1.5 ${r??""}`,children:[c.jsx("span",{className:"text-sm font-bold",children:e}),n,t&&c.jsx("span",{className:"text-xs text-[var(--color-text-muted)]",children:t})]})}function a4({onClose:e,onCreated:t}){return c.jsx("div",{className:"fixed inset-0 z-50 flex items-start justify-center bg-black/30 p-4 overflow-auto",children:c.jsx("div",{className:"w-full max-w-4xl my-8",children:c.jsx(f2,{onCancel:e,onCreated:n=>{e(),t(n)}})})})}const _k="projects.last",s4=["activity","date","name"];function jk(){const e=Be(),t=ks(),{name:n}=Mb(),[r,a]=Kb("projects.sort","activity"),[o,l]=j.useState(!1),[d,f]=j.useState(!1),{data:h,isLoading:g,isError:m,error:y,refetch:b}=Ye({queryKey:["projects"],queryFn:Es}),k=M=>t(`/projects/${encodeURIComponent(M)}`),v=h?c_(h.data,r):[],N=r!=="name",{recent:E,older:C}=N?rI(v,M=>M.lastActivityAt):{recent:v,older:[]},S=o?C:C.filter(M=>M.name===n),_=C.length-S.length;return j.useEffect(()=>{if(n)try{localStorage.setItem(_k,n)}catch{}},[n]),j.useEffect(()=>{if(n||!h)return;let M=null;try{M=localStorage.getItem(_k)}catch{}M&&h.data.some(T=>T.name===M)&&t(`/projects/${encodeURIComponent(M)}`,{replace:!0})},[n,h,t]),c.jsxs("div",{className:"flex flex-col flex-1 min-h-0 w-full",children:[m?c.jsxs("div",{className:"nb-card bg-[var(--color-crashed-bg)]",children:[c.jsx("h2",{className:"font-[family-name:var(--font-heading)] text-xl font-bold mb-2",children:e("projects.load.failed")}),c.jsx("p",{className:"text-sm text-[var(--color-text)]",children:y instanceof Error?y.message:String(y)}),c.jsx("button",{className:"nb-btn mt-4",onClick:()=>b(),type:"button",children:e("common.retry")})]}):h&&h.data.length===0?c.jsx(u4,{onNew:()=>f(!0)}):c.jsxs("div",{className:"flex gap-5 flex-1 min-h-0",children:[c.jsxs("aside",{className:"w-80 shrink-0 flex flex-col min-h-0",children:[c.jsxs("div",{className:"shrink-0 flex flex-col gap-2 pb-3",children:[c.jsxs("div",{className:"flex items-center justify-between gap-2",children:[c.jsxs("div",{className:"min-w-0",children:[c.jsx("h1",{className:"font-[family-name:var(--font-heading)] text-2xl font-bold truncate",children:e("projects.title")}),c.jsx("p",{className:"text-xs text-[var(--color-text-muted)]",children:h?e("projects.count",{count:h.data.length}):e("common.loading")})]}),c.jsxs("button",{className:"nb-btn nb-btn-primary shrink-0",type:"button",onClick:()=>f(!0),"aria-label":e("projects.new"),children:[c.jsx(pr,{size:16,strokeWidth:3}),e("projects.new")]})]}),c.jsxs("div",{className:"flex items-center gap-2",children:[c.jsx("div",{className:"inline-flex flex-1 border-[3px] border-[var(--color-text)] rounded-xl overflow-hidden shadow-[3px_3px_0_var(--color-text)]",role:"group","aria-label":e("projects.sort.label"),children:s4.map(M=>c.jsx("button",{type:"button","aria-pressed":r===M,onClick:()=>a(M),className:["flex-1 px-2 py-1.5 text-xs font-bold font-[family-name:var(--font-mono)] focus-visible:outline focus-visible:outline-2",r===M?"bg-[var(--color-accent-mint)]":"bg-[var(--color-bg)] hover:bg-[var(--color-bg-cream)]"].join(" "),children:e(`projects.sort.${M}`)},M))}),c.jsx("button",{className:"nb-btn nb-btn-yellow shrink-0",style:{padding:"6px 10px"},onClick:()=>b(),type:"button","aria-label":e("common.refresh"),children:c.jsx($h,{size:16,strokeWidth:2.5})})]})]}),c.jsx("ul",{className:"flex-1 min-h-0 overflow-y-auto flex flex-col gap-2 pr-1",children:g?c.jsx(c4,{}):c.jsxs(c.Fragment,{children:[[...E,...S].map(M=>c.jsx(o4,{project:M,selected:M.name===n,onClick:()=>k(M.name)},M.name)),(_>0||o&&C.length>0)&&c.jsx("button",{type:"button",className:"nb-btn text-xs self-start mt-1",onClick:()=>l(M=>!M),"aria-label":o?"收起更早项目":"显示更早项目",children:o?"收起更早":`含更早 (${_})`})]})})]}),c.jsx("div",{className:"flex-1 min-w-0 min-h-0 flex flex-col",children:n?c.jsx(Wz,{name:n,embedded:!0}):c.jsx("div",{className:"nb-card",children:c.jsx("p",{className:"text-[var(--color-text-muted)]",children:e("projects.selectHint")})})})]}),d&&c.jsx(a4,{onClose:()=>f(!1),onCreated:k})]})}function o4({project:e,selected:t,onClick:n}){return c.jsx("li",{children:c.jsxs("button",{type:"button",onClick:n,className:`nb-card w-full text-left ${t?"bg-[var(--color-accent-mint)]":""}`,style:{padding:"10px 12px"},children:[c.jsxs("div",{className:"flex items-center justify-between gap-2",children:[c.jsx("h3",{className:"font-[family-name:var(--font-heading)] font-bold truncate",children:e.name}),c.jsx(l4,{status:e.pipelineStatus})]}),e.repoDir&&c.jsx("p",{className:"text-[10px] font-[family-name:var(--font-mono)] text-[var(--color-text-muted)] truncate mt-0.5",children:e.repoDir}),c.jsxs("div",{className:"flex gap-3 text-[11px] font-[family-name:var(--font-mono)] text-[var(--color-text-muted)] mt-1.5",children:[c.jsxs("span",{children:[e.cards.total," cards"]}),c.jsxs("span",{children:[e.cards.inprogress," run"]}),c.jsxs("span",{children:[e.workers.active,"/",e.workers.total," w"]})]})]})})}function l4({status:e}){const t={running:{bg:"var(--color-running-bg)",label:"running"},idle:{bg:"var(--color-idle-bg)",label:"idle"},stopping:{bg:"var(--color-stuck-bg)",label:"stopping"},error:{bg:"var(--color-crashed-bg)",label:"error"}},{bg:n,label:r}=t[e],a=e==="running"?"var(--color-running)":e==="error"?"var(--color-crashed)":e==="stopping"?"var(--color-stuck)":"var(--color-idle)";return c.jsx("span",{className:"nb-status",style:{background:n,color:a},children:r})}function c4(){return c.jsx(c.Fragment,{children:[0,1,2].map(e=>c.jsxs("div",{className:"nb-card opacity-60 animate-pulse",style:{padding:"10px 12px"},children:[c.jsx("div",{className:"h-5 w-28 bg-[var(--color-border-light)] rounded-md mb-2"}),c.jsx("div",{className:"h-3 w-2/3 bg-[var(--color-border-light)] rounded-md"})]},e))})}function u4({onNew:e}){const t=Be(),n=t("projects.empty.hint",{cmd:"__CMD__"}),[r,a]=n.split("__CMD__");return c.jsxs("div",{className:"nb-card bg-[var(--color-accent-yellow)] flex items-center gap-6 p-8",children:[c.jsx("div",{className:"w-20 h-20 rounded-2xl bg-[var(--color-accent-mint)] border-[3px] border-[var(--color-text)] shadow-[3px_3px_0_var(--color-text)] flex items-center justify-center",children:c.jsx(n_,{size:32,strokeWidth:2.5})}),c.jsxs("div",{className:"flex-1",children:[c.jsx("h2",{className:"font-[family-name:var(--font-heading)] text-2xl font-bold mb-2",children:t("projects.empty.title")}),c.jsxs("p",{className:"text-sm text-[var(--color-text)] mb-4",children:[r,c.jsx("code",{className:"bg-[var(--color-bg)] border-2 border-[var(--color-text)] px-2 py-0.5 rounded-md font-[family-name:var(--font-mono)]",children:"sps project init <name>"}),a]}),c.jsxs("button",{className:"nb-btn nb-btn-primary",type:"button",onClick:e,children:[c.jsx(pr,{size:16,strokeWidth:3}),t("projects.new")]})]})]})}function d4({project:e,isPending:t,onCancel:n,onCreate:r}){var S;const a=Be(),[o,l]=j.useState(""),[d,f]=j.useState(""),[h,g]=j.useState(new Set),[m,y]=j.useState(!1),b=Ye({queryKey:["skills-all",e],queryFn:()=>ox(e)});j.useEffect(()=>{const _=M=>{M.key==="Escape"&&n()};return window.addEventListener("keydown",_),()=>window.removeEventListener("keydown",_)},[n]);const v=o.trim().length>0&&o.trim().length<=200&&!t,N=_=>{const M=new Set(h);M.has(_)?M.delete(_):M.add(_),g(M)},E=()=>{v&&r({title:o.trim(),description:d.trim(),skills:[...h],labels:["AI-PIPELINE"],initialState:m?"Backlog":"Planning"})},C=((S=b.data)==null?void 0:S.data)??[];return c.jsx("div",{role:"dialog","aria-modal":"true",className:"fixed inset-0 z-40 flex items-start justify-center p-6 bg-black/30 overflow-auto",children:c.jsxs("div",{className:"nb-card mt-8 w-full max-w-xl flex flex-col",style:{maxHeight:"calc(100vh - 64px)"},children:[c.jsxs("header",{className:"flex items-center justify-between mb-4 flex-shrink-0",children:[c.jsx("h2",{className:"font-[family-name:var(--font-heading)] text-2xl font-bold",children:a("newCard.title")}),c.jsx("button",{className:"nb-btn nb-btn-mint p-2",onClick:n,type:"button","aria-label":a("common.close"),children:c.jsx(Sn,{size:14,strokeWidth:3})})]}),c.jsxs("form",{onSubmit:_=>{_.preventDefault(),E()},className:"flex flex-col gap-4 overflow-auto",children:[c.jsxs("label",{className:"flex flex-col gap-1.5",children:[c.jsx("span",{className:"text-sm font-bold",children:a("newCard.field.title")}),c.jsx("input",{type:"text",className:"nb-input w-full",placeholder:a("newCard.field.title.placeholder"),value:o,onChange:_=>l(_.target.value),maxLength:200,autoFocus:!0,required:!0}),c.jsx("span",{className:"text-xs text-[var(--color-text-muted)]",children:a("newCard.field.title.help")})]}),c.jsxs("label",{className:"flex flex-col gap-1.5",children:[c.jsx("span",{className:"text-sm font-bold",children:a("newCard.field.description")}),c.jsx("textarea",{className:"nb-input w-full",style:{minHeight:120,resize:"vertical"},placeholder:a("newCard.field.description.placeholder"),value:d,onChange:_=>f(_.target.value)}),c.jsx("span",{className:"text-xs text-[var(--color-text-muted)]",children:a("newCard.field.description.help")})]}),c.jsxs("div",{className:"flex flex-col gap-2",children:[c.jsx("span",{className:"text-sm font-bold",children:a("newCard.field.skills")}),c.jsx("span",{className:"text-xs text-[var(--color-text-muted)]",children:a("newCard.field.skills.help")}),b.isLoading&&c.jsx("p",{className:"text-xs text-[var(--color-text-muted)] italic",children:a("newCard.field.skills.loading")}),b.isError&&c.jsx("p",{className:"text-xs text-[var(--color-crashed)]",children:a("newCard.field.skills.error",{detail:b.error instanceof Error?b.error.message:String(b.error)})}),C.length>0&&c.jsx("div",{className:"flex flex-wrap gap-2",children:C.map(_=>{const M=h.has(_.name);return c.jsx("button",{type:"button",onClick:()=>N(_.name),className:["px-2.5 py-1 text-xs font-[family-name:var(--font-mono)] rounded-full border-2 transition-all",M?"bg-[var(--color-accent-mint)] border-[var(--color-text)] shadow-[2px_2px_0_var(--color-text)] font-bold":"bg-[var(--color-bg)] border-[var(--color-border-light)] hover:border-[var(--color-text)]"].join(" "),"aria-pressed":M,children:_.name},_.name)})}),h.size>0&&c.jsx("p",{className:"text-xs text-[var(--color-text-muted)]",children:a("newCard.field.skills.selected",{count:h.size,names:[...h].join(", ")})})]}),c.jsxs("div",{className:"flex flex-col gap-2",children:[c.jsx("span",{className:"text-sm font-bold",children:a("newCard.field.dispatch")}),c.jsxs("label",{className:"flex items-center gap-3 cursor-pointer select-none p-3 border-[2px] border-[var(--color-text)] rounded-lg bg-[var(--color-bg-cream)]",children:[c.jsx("input",{type:"checkbox",className:"w-4 h-4 accent-[var(--color-cta)] cursor-pointer",checked:m,onChange:_=>y(_.target.checked)}),c.jsxs("div",{className:"flex-1",children:[c.jsx("div",{className:"text-sm font-bold",children:a("newCard.field.dispatch.label")}),c.jsx("div",{className:"text-xs text-[var(--color-text-muted)] mt-0.5",children:a("newCard.field.dispatch.help")})]})]})]})]}),c.jsxs("div",{className:"flex gap-2 justify-end mt-4 pt-3 border-t-2 border-dashed border-[var(--color-text)] flex-shrink-0",children:[c.jsx("button",{className:"nb-btn",style:{padding:"6px 14px"},onClick:n,disabled:t,type:"button",children:a("common.cancel")}),c.jsxs("button",{className:"nb-btn nb-btn-primary",style:{padding:"6px 14px"},onClick:E,disabled:!v,type:"button","aria-label":a("newCard.create.aria"),children:[t?c.jsx(Xe,{size:13,strokeWidth:3,className:"animate-spin"}):c.jsx(pr,{size:13,strokeWidth:3}),a("common.create")]})]})]})})}function f4(e){return ft(`/api/projects/${encodeURIComponent(e)}/cards`)}function h4(e,t){return ft(`/api/projects/${encodeURIComponent(e)}/cards/${t}`)}async function ac(e,t){const n=await fetch(e,{method:"POST",headers:t?{"Content-Type":"application/json"}:void 0,body:t?JSON.stringify(t):void 0});if(!n.ok){const r=await n.text();throw new Error(`${n.status} ${n.statusText}: ${r}`)}return n.json().catch(()=>({}))}function p4(e,t){return ac(`/api/projects/${encodeURIComponent(e)}/cards/${t}/reset`)}async function m4(e,t){const n=await fetch(`/api/projects/${encodeURIComponent(e)}/cards/${t}`,{method:"DELETE"});if(!n.ok){const r=await n.text();throw new Error(`${n.status}: ${r}`)}}function g4(e,t){return ac(`/api/projects/${encodeURIComponent(e)}/cards/${t}/launch`)}function y4(e,t){const n=typeof t=="string"?{title:t}:t;return ac(`/api/projects/${encodeURIComponent(e)}/cards`,n)}async function b4(e,t,n){const r=await fetch(`/api/projects/${encodeURIComponent(e)}/cards/${t}`,{method:"PATCH",headers:{"Content-Type":"application/json"},body:JSON.stringify({state:n})});if(!r.ok){const a=await r.text();throw new Error(`${r.status}: ${a}`)}}async function x4(e,t,n){const r=await fetch(`/api/projects/${encodeURIComponent(e)}/cards/${t}`,{method:"PATCH",headers:{"Content-Type":"application/json"},body:JSON.stringify(n)});if(!r.ok){const a=await r.text();throw new Error(`${r.status}: ${a}`)}return r.json()}function h2(e){return ac(`/api/projects/${encodeURIComponent(e)}/pipeline/start`)}function p2(e){return ac(`/api/projects/${encodeURIComponent(e)}/pipeline/stop`)}function v4(e,t){return ac(`/api/projects/${encodeURIComponent(e)}/pipeline/reset`,t??{})}function w4(e){const t=Gt();j.useEffect(()=>{if(!e)return;const n=`/stream/projects/${encodeURIComponent(e)}`,r=new EventSource(n),a=d=>{try{const f=JSON.parse(d.data);t.invalidateQueries({queryKey:["cards",f.project]}),t.invalidateQueries({queryKey:["card",f.project,f.seq]}),t.invalidateQueries({queryKey:["projects"]})}catch{}},o=d=>{try{const f=JSON.parse(d.data);t.invalidateQueries({queryKey:["workers",f.project]}),t.invalidateQueries({queryKey:["projects"]})}catch{}},l=d=>{try{const f=JSON.parse(d.data);t.invalidateQueries({queryKey:["pipeline-status",f.project]}),t.invalidateQueries({queryKey:["projects"]})}catch{}};return r.addEventListener("card.created",a),r.addEventListener("card.updated",a),r.addEventListener("card.moved",a),r.addEventListener("card.deleted",a),r.addEventListener("worker.updated",o),r.addEventListener("worker.added",o),r.addEventListener("worker.deleted",o),r.addEventListener("pipeline.status",l),r.addEventListener("pipeline.started",l),r.addEventListener("pipeline.stopped",l),()=>r.close()},[e,t])}const k4=new Set(["python","typescript","golang","rust","kotlin","swift","java"]),E4=new Set(["frontend","backend","mobile","database","devops"]),S4=new Set(["backend-architect","frontend-developer","code-reviewer","database-optimizer","devops-automator","security-engineer","qa-tester","security","qa","architect","db-opt"]),N4=new Set(["coding-standards","tdd-workflow","git-workflow","architecture-decision-records","debugging-workflow"]);function _4(e){return k4.has(e)?"lang":E4.has(e)?"end":S4.has(e)?"persona":N4.has(e)?"workflow":"other"}const j4={lang:"var(--color-accent-purple)",end:"var(--color-secondary)",persona:"var(--color-primary)",workflow:"var(--color-accent-mint)",other:"var(--color-bg)"};function ux({name:e}){const t=j4[_4(e)];return c.jsx("span",{className:"nb-badge",style:{background:t},children:e})}function m2({label:e,kind:t="default"}){const n=t==="warn"?"var(--color-accent-pink)":t==="accent"?"var(--color-accent-yellow)":"var(--color-bg-cream)";return c.jsx("span",{className:"nb-badge",style:{background:n},children:e})}function C4({card:e,onClick:t,done:n,draggable:r}){const a=Be(),o=e.labels.some(l=>l.startsWith("STARTED-"))&&!n;return c.jsxs("article",{onClick:t,onKeyDown:l=>{(l.key==="Enter"||l.key===" ")&&(l.preventDefault(),t())},draggable:r,onDragStart:l=>{l.dataTransfer.setData("application/x-sps-card-seq",String(e.seq)),l.dataTransfer.effectAllowed="move"},tabIndex:0,role:"button","aria-label":`Card #${e.seq}: ${e.title}`,className:["bg-[var(--color-bg)] border-[3px] border-[var(--color-text)] rounded-xl p-3","shadow-[3px_3px_0_var(--color-text)] cursor-pointer","transition-[transform,box-shadow] duration-[180ms] ease-out","hover:-translate-x-0.5 hover:-translate-y-0.5 hover:shadow-[5px_5px_0_var(--color-text)]","focus:outline-none focus-visible:ring-[3px] focus-visible:ring-offset-2 focus-visible:ring-[var(--color-text)]",n?"opacity-60":"",r?"active:cursor-grabbing":""].join(" "),children:[c.jsxs("div",{className:"flex items-center justify-between gap-2 mb-2",children:[c.jsxs("span",{className:"font-[family-name:var(--font-mono)] font-bold text-[11px] px-2 py-0.5 bg-[var(--color-bg-cream)] border-2 border-[var(--color-text)] rounded-full",children:["#",e.seq]}),o&&c.jsx("span",{className:"nb-status",style:{background:"var(--color-running-bg)",color:"var(--color-running)"},children:"running"})]}),c.jsx("p",{className:`font-bold text-sm leading-5 mb-2 line-clamp-2 ${n?"line-through decoration-2":""}`,children:e.title}),(e.skills.length>0||e.labels.length>0)&&c.jsxs("div",{className:"flex flex-wrap gap-1 mb-2",children:[e.skills.slice(0,3).map(l=>c.jsx(ux,{name:l},l)),e.labels.filter(l=>l==="NEEDS-FIX").map(l=>c.jsx(m2,{label:l,kind:"warn"},l))]}),e.checklist&&e.checklist.total>0&&c.jsx(A4,{stats:e.checklist}),c.jsxs("div",{className:"pt-2 border-t-[1.5px] border-dashed border-[var(--color-border-light)] flex items-center gap-2 text-[11px] font-[family-name:var(--font-mono)] text-[var(--color-text-subtle)]",children:[c.jsx("span",{children:T4(e.updatedAt??e.createdAt,a)}),e.branch&&c.jsxs("span",{className:"truncate",children:["· ",e.branch]})]})]})}function A4({stats:e}){const t=Be();return c.jsxs("div",{className:"mb-2",children:[c.jsxs("div",{className:"flex items-center justify-between text-[11px] font-[family-name:var(--font-mono)] mb-1",children:[c.jsx("span",{className:"font-bold",children:t("kanban.checklist.label",{done:e.done,total:e.total})}),c.jsxs("span",{className:"text-[var(--color-text-subtle)]",children:[e.percent,"%"]})]}),c.jsx("div",{className:"w-full h-1.5 bg-[var(--color-bg-cream)] border-2 border-[var(--color-text)] rounded-full overflow-hidden mb-1.5",children:c.jsx("div",{className:"h-full bg-[var(--color-cta)] transition-[width] duration-200",style:{width:`${e.percent}%`}})}),c.jsxs("ul",{className:"text-[11px] space-y-0.5",children:[e.items.slice(0,3).map((n,r)=>c.jsxs("li",{className:`flex items-start gap-1 ${n.done?"opacity-60 line-through":""}`,children:[c.jsx("span",{className:"flex-shrink-0 mt-0.5",children:n.done?"✓":"○"}),c.jsx("span",{className:"line-clamp-1",children:n.text})]},r)),e.items.length>3&&c.jsx("li",{className:"text-[var(--color-text-subtle)] italic pl-3",children:t("kanban.checklist.more",{count:e.items.length-3})})]})]})}function T4(e,t){if(!e)return"—";const n=new Date(e),r=Date.now()-n.getTime();return r<6e4?t("kanban.time.justNow"):r<36e5?t("kanban.time.minutes",{n:Math.floor(r/6e4)}):r<864e5?t("kanban.time.hours",{n:Math.floor(r/36e5)}):n.toLocaleDateString()}function M4({label:e,bg:t,cards:n,onCardClick:r,onDropCard:a}){const o=Be(),[l,d]=j.useState(!1);return c.jsxs("div",{className:["flex flex-col p-3 rounded-2xl border-[3px] min-h-[280px] h-full min-h-0 overflow-hidden","transition-all",l?"border-[var(--color-cta)] shadow-[4px_4px_0_var(--color-cta)]":"border-[var(--color-text)]"].join(" "),style:{background:t},onDragOver:f=>{!a||!f.dataTransfer.types.includes("application/x-sps-card-seq")||(f.preventDefault(),f.dataTransfer.dropEffect="move",l||d(!0))},onDragLeave:()=>d(!1),onDrop:f=>{if(d(!1),!a)return;const h=f.dataTransfer.getData("application/x-sps-card-seq"),g=Number.parseInt(h,10);Number.isFinite(g)&&(f.preventDefault(),a(g))},children:[c.jsxs("div",{className:"flex items-center justify-between px-1 pb-2 mb-2 border-b-2 border-[var(--color-text)] shrink-0",children:[c.jsx("span",{className:"font-[family-name:var(--font-heading)] font-bold text-sm uppercase tracking-wider",children:e}),c.jsx("span",{className:"font-[family-name:var(--font-mono)] font-bold text-xs px-2 py-0.5 bg-[var(--color-bg)] border-2 border-[var(--color-text)] rounded-full",children:n.length})]}),c.jsxs("div",{className:"flex flex-col gap-2 flex-1 min-h-0 overflow-y-auto pr-1 -mr-1",style:{scrollbarWidth:"thin",scrollbarColor:"var(--color-text) transparent"},children:[n.length===0&&c.jsx("div",{className:"text-xs text-[var(--color-text-muted)] text-center py-6 italic",children:o("kanban.column.empty")}),n.map(f=>c.jsx(C4,{card:f,onClick:()=>r(f),done:e==="Done",draggable:!!a},f.seq))]})]})}function Qy(e,t){if(!e)return"";const n=e.split(`
|
|
602
|
+
`)}):n("projectDetail.danger.deleted.body")}).then(()=>r("/projects"))},onError:v=>{o({title:n("projectDetail.danger.error"),body:v instanceof Error?v.message:String(v)})}}),y=n("projectDetail.danger.body",{path:"__PATH__"}).split("__PATH__"),k=n("projectDetail.danger.confirmPrompt",{name:"__NAME__"}).split("__NAME__");return c.jsxs("div",{className:"nb-card bg-[var(--color-crashed-bg)]",children:[c.jsx("h2",{className:"font-[family-name:var(--font-heading)] text-lg font-bold mb-2 text-[var(--color-crashed)]",children:n("projectDetail.danger.title")}),c.jsxs("p",{className:"text-sm mb-4",children:[y[0],c.jsxs("code",{className:"font-[family-name:var(--font-mono)] bg-[var(--color-bg)] border-2 border-[var(--color-text)] px-1.5 py-0.5 rounded",children:["~/.coral/projects/",e,"/"]}),y[1]]}),t&&c.jsxs("label",{className:"flex items-start gap-2 mb-4 p-3 bg-[var(--color-bg)] border-2 border-[var(--color-text)] rounded-lg cursor-pointer",children:[c.jsx("input",{type:"checkbox",checked:f,onChange:v=>h(v.target.checked),className:"mt-0.5"}),c.jsxs("div",{className:"flex-1",children:[c.jsx("div",{className:"text-sm font-bold",children:n("projectDetail.danger.includeClaude.label")}),c.jsxs("div",{className:"text-xs text-[var(--color-text-muted)] font-[family-name:var(--font-mono)]",children:[t,"/.claude/"]}),c.jsx("div",{className:"text-xs text-[var(--color-text-muted)] mt-1",children:n("projectDetail.danger.includeClaude.note")})]})]}),c.jsx("div",{className:"mb-4",children:c.jsxs("label",{className:"flex flex-col gap-1.5",children:[c.jsxs("span",{className:"text-sm font-bold",children:[k[0],c.jsx("code",{className:"font-[family-name:var(--font-mono)] text-xs",children:e}),k[1]]}),c.jsx("input",{type:"text",className:"nb-input w-full font-[family-name:var(--font-mono)]",value:l,onChange:v=>d(v.target.value),placeholder:e})]})}),c.jsxs("button",{type:"button",className:"nb-btn nb-btn-danger",disabled:l!==e||g.isPending,onClick:()=>g.mutate(),"aria-label":n("projectDetail.danger.deleteAria"),children:[g.isPending?c.jsx(Xe,{size:14,strokeWidth:3,className:"animate-spin"}):c.jsx(fi,{size:14,strokeWidth:3}),n("projectDetail.danger.deleteButton")]})]})}function lx(){return ft("/api/providers")}function c2(e){const t=[];for(const n of e)for(const r of n.models)t.push({providerId:n.id,model:r,label:`${r} · ${n.name}`});return t}async function t4(e,t){const n=await fetch("/api/providers",{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify({kind:e,entry:t})});if(!n.ok)throw new Error(`${n.status}: ${await n.text()}`);return n.json()}async function n4(e,t){const n=await fetch(`/api/providers/${e}/${encodeURIComponent(t)}`,{method:"DELETE"});if(!n.ok)throw new Error(`${n.status}: ${await n.text()}`);return n.json()}function u2(e){const t=e?`?path=${encodeURIComponent(e)}`:"";return ft(`/api/fs/browse${t}`)}async function r4(e,t){const n=await fetch("/api/fs/mkdir",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({path:e,name:t})});if(!n.ok){const r=await n.text();throw new Error(`${n.status}: ${r}`)}return await n.json()}const d2=50*1024*1024;async function i4(e,t){if(t.size>d2)throw new Error(`文件超过 50 MB 上限(当前 ${(t.size/1024/1024).toFixed(2)} MB)`);const n=new FormData;n.append("sessionId",e),n.append("file",t,t.name);const r=await fetch("/api/fs/upload",{method:"POST",body:n});if(!r.ok){const a=await r.text();throw new Error(`${r.status}: ${a}`)}return await r.json()}function Yy(e,t){return`/api/fs/file?${new URLSearchParams({path:t,sessionId:e}).toString()}`}function cx({initialPath:e,onCancel:t,onSelect:n,title:r,mode:a="directory"}){var C,S,_;const o=Be(),{prompt:l,alert:d}=un(),f=r??o("dirPicker.title.default"),[h,g]=j.useState(e??null),[m,y]=j.useState(null),b=Ye({queryKey:["fs-browse",h],queryFn:()=>u2(h??void 0),staleTime:0,gcTime:0}),k=((C=b.data)==null?void 0:C.path)??h??"",v=((S=b.data)==null?void 0:S.parent)??null,N=((_=b.data)==null?void 0:_.home)??null,E=async()=>{var T;if(!k)return;const M=(T=await l({title:o("dirPicker.newDir"),body:o("dirPicker.newDir.prompt"),placeholder:o("dirPicker.newDir.placeholder"),confirm:o("dirPicker.newDir.create")}))==null?void 0:T.trim();if(M)try{const L=await r4(k,M);g(L.path)}catch(L){d({title:o("dirPicker.newDir.error.title"),body:L instanceof Error?L.message:String(L)})}};return j.useEffect(()=>{const M=T=>{T.key==="Escape"&&(T.preventDefault(),t())};return window.addEventListener("keydown",M),()=>window.removeEventListener("keydown",M)},[t]),c.jsx("div",{className:"fixed inset-0 z-50 flex items-center justify-center bg-[rgba(45,55,72,0.5)] p-4",role:"presentation",children:c.jsxs("div",{className:"nb-card bg-[var(--color-bg)] max-w-lg w-full p-5 flex flex-col",style:{maxHeight:"70vh"},role:"dialog","aria-modal":"true","aria-label":f,children:[c.jsxs("header",{className:"flex items-center justify-between mb-3 shrink-0",children:[c.jsx("div",{className:"flex items-center gap-2 min-w-0",children:c.jsx("h3",{className:"font-[family-name:var(--font-heading)] font-bold text-base truncate",children:f})}),c.jsx("button",{type:"button",className:"p-1 hover:bg-[var(--color-bg-cream)] rounded",onClick:t,"aria-label":o("dirPicker.close.aria"),children:c.jsx(Sn,{size:14,strokeWidth:3})})]}),c.jsxs("div",{className:"flex items-center gap-2 mb-3 shrink-0",children:[c.jsx("button",{type:"button",className:"nb-btn flex-shrink-0",style:{padding:"4px 10px",fontSize:12},onClick:()=>v&&g(v),disabled:!v||b.isLoading,"aria-label":o("dirPicker.up.aria"),title:o("dirPicker.up.title"),children:c.jsx(FN,{size:12,strokeWidth:3})}),c.jsx("button",{type:"button",className:"nb-btn flex-shrink-0",style:{padding:"4px 10px",fontSize:12},onClick:()=>N&&g(N),disabled:!N||b.isLoading,"aria-label":o("dirPicker.home.aria"),title:o("dirPicker.home.title"),children:c.jsx(xL,{size:12,strokeWidth:3})}),c.jsx("button",{type:"button",className:"nb-btn flex-shrink-0",style:{padding:"4px 10px",fontSize:12},onClick:()=>void E(),disabled:!k||b.isLoading||b.isError,"aria-label":o("dirPicker.newDir.aria"),title:o("dirPicker.newDir.aria"),children:c.jsx(iL,{size:12,strokeWidth:3})}),c.jsx("div",{className:"flex-1 min-w-0 nb-input font-[family-name:var(--font-mono)] text-xs px-2 py-1.5 truncate",title:k,dir:"rtl",children:k||"..."})]}),c.jsxs("div",{className:"flex-1 overflow-y-auto border-2 border-[var(--color-text)] rounded-lg bg-[var(--color-bg-cream)] min-h-0",children:[b.isLoading&&c.jsxs("div",{className:"flex items-center justify-center py-12 text-[var(--color-text-muted)]",children:[c.jsx(Xe,{size:16,strokeWidth:3,className:"animate-spin mr-2"}),o("dirPicker.loading")]}),b.isError&&c.jsxs("div",{className:"p-4 text-sm text-[var(--color-crashed)]",children:[c.jsx("p",{className:"font-bold mb-1",children:o("dirPicker.error.title")}),c.jsx("p",{className:"text-xs font-[family-name:var(--font-mono)] break-all",children:b.error instanceof Error?b.error.message:String(b.error)})]}),b.data&&c.jsxs("ul",{className:"divide-y-2 divide-[var(--color-text)]/20",children:[b.data.entries.length===0&&c.jsx("li",{className:"p-4 text-xs text-[var(--color-text-subtle)] italic text-center",children:o("dirPicker.empty")}),b.data.entries.map(M=>{const T=(()=>{const $=k.endsWith("/")||k.endsWith("\\")?"":"/";return`${k}${$}${M.name}`})(),L=a==="file"&&m===T,R=M.isDirectory||a==="file";return c.jsx("li",{children:c.jsxs("button",{type:"button",className:["w-full flex items-center gap-2 px-3 py-2 text-left text-sm font-[family-name:var(--font-mono)]","disabled:opacity-50 disabled:cursor-not-allowed",L?"bg-[var(--color-accent-mint)] font-bold":"hover:bg-[var(--color-accent-mint)]"].join(" "),disabled:!R,onClick:()=>{M.isDirectory?(y(null),g(T)):a==="file"&&y(T)},onDoubleClick:()=>{a==="file"&&!M.isDirectory&&n(T)},title:M.isDirectory?o("dirPicker.enter.aria",{name:M.name}):a==="file"?o("dirPicker.pickFile.aria",{name:M.name}):o("dirPicker.fileLocked"),children:[M.isDirectory?c.jsx(ph,{size:14,strokeWidth:2.5,className:"flex-shrink-0 text-[var(--color-text)]"}):c.jsx("span",{className:"w-3.5 h-3.5 flex-shrink-0"}),c.jsx("span",{className:"truncate",children:M.name}),M.isDirectory&&c.jsx(Zl,{size:12,strokeWidth:2.5,className:"ml-auto flex-shrink-0 text-[var(--color-text-muted)]"})]})},M.name)})]})]}),c.jsxs("div",{className:"flex gap-2 justify-end pt-3 shrink-0",children:[c.jsx("button",{type:"button",className:"nb-btn",onClick:t,children:o("dirPicker.cancel")}),a==="file"?c.jsxs("button",{type:"button",className:"nb-btn nb-btn-primary",onClick:()=>m&&n(m),disabled:!m||b.isLoading||b.isError,title:m??o("dirPicker.useFile.tooltip.empty"),children:[c.jsx(Eu,{size:14,strokeWidth:3}),o("dirPicker.useFile")]}):c.jsxs("button",{type:"button",className:"nb-btn nb-btn-primary",onClick:()=>n(k),disabled:!k||b.isLoading||b.isError,children:[c.jsx(Eu,{size:14,strokeWidth:3}),o("dirPicker.useDir")]})]})]})})}function Af(e){return(e.replace(/\/+$/,"").split("/").pop()??"").replace(/[^a-zA-Z0-9_-]/g,"-").replace(/-+/g,"-").replace(/^-+|-+$/g,"")}function f2({onCancel:e,onCreated:t}={}){var z,q,F,Y,D,H;const n=Be(),r=ks(),a=Gt(),{alert:o}=un(),l=e??(()=>r("/projects")),[d,f]=j.useState({name:"",projectDir:"",enableGit:!0,createIfMissing:!0,mergeBranch:"main",maxWorkers:"1",ackTimeoutMin:"5",pipelineMode:"pipeline"}),h=d.pipelineMode==="smartArrange",g=Ye({queryKey:["system-agents"],queryFn:Hb}),m=((z=g.data)==null?void 0:z.agents.worker.model)??"",y=((q=g.data)==null?void 0:q.agents.reviewer.model)??"",b=[...new Set((((F=g.data)==null?void 0:F.providers.openai)??[]).flatMap(O=>O.models))],k=Ye({queryKey:["providers"],queryFn:lx}),v=c2(((Y=k.data)==null?void 0:Y.anthropic)??[]),N=d.workerModel?`${d.workerProviderId??""}::${d.workerModel}`:"",[E,C]=j.useState(!1),S=Ct({mutationFn:O=>U3(O),onSuccess:O=>{a.invalidateQueries({queryKey:["projects"]}),t?t(O.name):r(`/projects/${encodeURIComponent(O.name)}`)},onError:O=>{o({title:n("newProject.error.create.title"),body:O instanceof Error?O.message:String(O)})}}),_=/^[a-zA-Z0-9_-]+$/.test(d.name),M=_&&d.projectDir.trim()!==""&&!S.isPending,T=d.projectDir.trim(),L=Ye({queryKey:["fs-browse-probe",T],queryFn:()=>u2(T),enabled:T.startsWith("/"),staleTime:0,gcTime:0,retry:!1}),R=L.isSuccess&&(((D=L.data)==null?void 0:D.entries.length)??0)>0,$=L.isError||L.isSuccess&&(((H=L.data)==null?void 0:H.entries.length)??0)===0;return c.jsxs("div",{className:"w-full",children:[c.jsxs("div",{className:"nb-card flex flex-col gap-4",children:[c.jsxs("header",{className:"flex items-center gap-3",children:[c.jsxs("button",{type:"button",onClick:l,className:"nb-btn",style:{padding:"6px 12px"},"aria-label":n("newProject.back.aria"),children:[c.jsx(UN,{size:14,strokeWidth:3}),n("newProject.back")]}),c.jsx("h1",{className:"font-[family-name:var(--font-heading)] text-2xl font-bold",children:n("newProject.title")})]}),c.jsxs("form",{onSubmit:O=>{O.preventDefault(),M&&S.mutate(d)},className:"grid grid-cols-1 md:grid-cols-2 gap-x-6 gap-y-4",children:[c.jsx(Ur,{className:"md:col-span-2",label:n("newProject.field.mode"),hint:n(h?"newProject.field.mode.smartHint":"newProject.field.mode.pipelineHint"),children:c.jsx("div",{className:"grid grid-cols-1 sm:grid-cols-2 gap-3",children:["pipeline","smartArrange"].map(O=>{const V=d.pipelineMode===O;return c.jsxs("button",{type:"button",onClick:()=>f({...d,pipelineMode:O}),"aria-pressed":V,className:["text-left rounded-xl border-2 p-3 transition-all",V?"bg-[var(--color-accent-mint)] border-[var(--color-text)] shadow-[3px_3px_0_var(--color-text)] font-bold":"bg-[var(--color-bg)] border-[var(--color-border-light)] hover:border-[var(--color-text)]"].join(" "),children:[c.jsx("div",{className:"text-sm font-bold",children:n(O==="pipeline"?"newProject.field.mode.pipeline":"newProject.field.mode.smart")}),c.jsx("div",{className:"text-xs text-[var(--color-text-muted)] mt-0.5",children:n(O==="pipeline"?"newProject.field.mode.pipelineDesc":"newProject.field.mode.smartDesc")})]},O)})})}),h&&c.jsx(Ur,{className:"md:col-span-2",label:n("newProject.field.goal"),hint:n("newProject.field.goal.hint"),children:c.jsx("textarea",{className:"nb-input w-full font-[family-name:var(--font-mono)] text-sm",style:{minHeight:110,resize:"vertical"},placeholder:n("newProject.field.goal.placeholder"),value:d.goal??"",onChange:O=>f({...d,goal:O.target.value})})}),c.jsx(Ur,{label:"Worker 模型",hint:`默认:${m||"全局默认"}(留空用默认)`,children:c.jsxs("select",{className:"nb-input w-full font-[family-name:var(--font-mono)] text-xs",value:N,onChange:O=>{const V=O.target.value;if(!V)return f({...d,workerModel:void 0,workerProviderId:void 0});const[Q,K]=V.split("::");f({...d,workerModel:K,workerProviderId:Q||void 0})},children:[c.jsx("option",{value:"",children:"用全局默认模型"}),v.map(O=>c.jsx("option",{value:`${O.providerId}::${O.model}`,children:O.label},`${O.providerId}::${O.model}`))]})}),h&&c.jsxs(Ur,{label:"OpenAI Agent(监工)模型",hint:`默认:${y||"全局默认"}(留空用默认)`,children:[c.jsx("input",{className:"nb-input w-full font-[family-name:var(--font-mono)] text-xs",value:d.reviewerModel??"",onChange:O=>f({...d,reviewerModel:O.target.value}),placeholder:y,list:"np-reviewer-models",spellCheck:!1}),c.jsx("datalist",{id:"np-reviewer-models",children:b.map(O=>c.jsx("option",{value:O},O))})]}),c.jsxs(Ur,{label:n("newProject.field.name"),hint:n("newProject.field.name.derived"),children:[c.jsx("input",{type:"text",className:"nb-input w-full font-[family-name:var(--font-mono)]",placeholder:n("newProject.field.name.placeholder"),value:d.name,onChange:O=>f({...d,name:O.target.value}),required:!0}),d.name&&!_&&c.jsx("p",{className:"text-xs text-[var(--color-crashed)] mt-1",children:n("newProject.field.name.invalid")})]}),c.jsxs(Ur,{className:"md:col-span-2",label:n("newProject.field.dir"),hint:n("newProject.field.dir.long"),children:[c.jsxs("div",{className:"flex gap-2",children:[c.jsx("input",{type:"text",className:"nb-input flex-1 font-[family-name:var(--font-mono)]",placeholder:n("newProject.field.dir.placeholder"),value:d.projectDir,onChange:O=>{const V=O.target.value,Q=Af(V),K=Af(d.projectDir),I=d.name&&d.name!==K;f({...d,projectDir:V,name:I?d.name:Q})},required:!0}),c.jsxs("button",{type:"button",className:"nb-btn flex-shrink-0",onClick:()=>C(!0),"aria-label":n("newProject.dir.browseAria"),title:n("newProject.dir.browseAria"),children:[c.jsx(KN,{size:14,strokeWidth:2.5}),n("newProject.dir.browse")]})]}),R&&c.jsx("p",{className:"text-xs mt-1.5 font-bold text-[var(--color-text)]",children:n("newProject.field.dir.adopt")}),$&&T.startsWith("/")&&c.jsx("p",{className:"text-xs mt-1.5 text-[var(--color-text-muted)]",children:n("newProject.field.dir.fresh")}),c.jsxs("label",{className:"flex items-center gap-2 mt-2 cursor-pointer select-none",children:[c.jsx("input",{type:"checkbox",checked:d.createIfMissing!==!1,onChange:O=>f({...d,createIfMissing:O.target.checked}),className:"w-4 h-4 cursor-pointer"}),c.jsx("span",{className:"text-xs text-[var(--color-text-muted)]",children:n("newProject.field.dir.createIfMissing")})]})]}),c.jsx(Ur,{label:n("newProject.field.maxWorkers.short"),children:c.jsx("input",{type:"number",min:"1",max:"8",className:"nb-input w-full font-[family-name:var(--font-mono)]",value:d.maxWorkers,onChange:O=>f({...d,maxWorkers:O.target.value})})}),c.jsx(Ur,{label:n("newProject.field.ackTimeout.minutes"),hint:n("newProject.field.ackTimeout.minutes.help"),children:c.jsx("input",{type:"number",min:"1",max:"30",className:"nb-input w-full font-[family-name:var(--font-mono)]",value:d.ackTimeoutMin??"5",onChange:O=>f({...d,ackTimeoutMin:O.target.value})})}),c.jsxs("div",{className:"md:col-span-2 pt-3 border-t-2 border-[var(--color-text)] border-dashed",children:[c.jsxs("label",{className:"flex items-center gap-3 mb-2 cursor-pointer select-none",children:[c.jsx("input",{type:"checkbox",checked:d.enableReview??!1,onChange:O=>f({...d,enableReview:O.target.checked}),className:"w-4 h-4 cursor-pointer"}),c.jsx("span",{className:"text-sm font-bold",children:n("newProject.field.review.label")})]}),c.jsx("p",{className:"text-xs text-[var(--color-text-muted)]",children:n("newProject.field.review.detail")})]}),c.jsxs("div",{className:"md:col-span-2 pt-3 border-t-2 border-[var(--color-text)] border-dashed",children:[c.jsxs("label",{className:"flex items-center gap-3 mb-3 cursor-pointer select-none",children:[c.jsx("input",{type:"checkbox",checked:d.enableGit??!0,onChange:O=>f({...d,enableGit:O.target.checked}),className:"w-4 h-4 cursor-pointer"}),c.jsx("span",{className:"text-sm font-bold",children:n("newProject.field.git.label")})]}),c.jsx("p",{className:"text-xs text-[var(--color-text-muted)] mb-3",children:n("newProject.field.git.detail")}),d.enableGit!==!1&&c.jsxs("div",{className:"flex flex-col gap-4 bg-[var(--color-bg-cream)] border-2 border-[var(--color-text)] rounded-lg p-4",children:[c.jsx(Ur,{label:n("newProject.field.git.branch"),children:c.jsx("input",{type:"text",className:"nb-input w-full font-[family-name:var(--font-mono)]",value:d.mergeBranch??"main",onChange:O=>f({...d,mergeBranch:O.target.value})})}),c.jsx(Ur,{label:n("newProject.field.gitlabProject.label"),hint:n("newProject.field.gitlabProject.help2"),children:c.jsx("input",{type:"text",className:"nb-input w-full font-[family-name:var(--font-mono)]",placeholder:n("newProject.field.gitlabProject.placeholder"),value:d.gitlabProject??"",onChange:O=>f({...d,gitlabProject:O.target.value})})}),d.gitlabProject&&c.jsx(Ur,{label:n("newProject.field.gitlabProjectId"),hint:n("newProject.field.gitlabProjectId.help"),children:c.jsx("input",{type:"text",className:"nb-input w-full font-[family-name:var(--font-mono)]",placeholder:n("newProject.field.gitlabProjectId.placeholder"),value:d.gitlabProjectId??"",onChange:O=>f({...d,gitlabProjectId:O.target.value})})})]})]}),c.jsxs("div",{className:"md:col-span-2 pt-3 border-t-2 border-[var(--color-text)] border-dashed",children:[c.jsx("h3",{className:"font-[family-name:var(--font-heading)] text-sm font-bold uppercase tracking-wider mb-3 text-[var(--color-text-muted)]",children:n("newProject.section.notifications")}),c.jsx(Ur,{label:n("newProject.field.matrixRoom.label"),hint:n("newProject.field.matrixRoom.help2"),children:c.jsx("input",{type:"text",className:"nb-input w-full font-[family-name:var(--font-mono)]",placeholder:n("newProject.field.matrixRoom.placeholder"),value:d.matrixRoomId??"",onChange:O=>f({...d,matrixRoomId:O.target.value})})})]}),c.jsxs("div",{className:"md:col-span-2 flex gap-3 justify-end pt-3",children:[c.jsx("button",{type:"button",className:"nb-btn",onClick:l,disabled:S.isPending,children:n("common.cancel")}),c.jsx("button",{type:"submit",className:"nb-btn nb-btn-primary",disabled:!M,"aria-label":n("newProject.submit"),children:S.isPending?c.jsxs(c.Fragment,{children:[c.jsx(Xe,{size:14,strokeWidth:3,className:"animate-spin"}),n("newProject.creating")]}):c.jsxs(c.Fragment,{children:[c.jsx(pr,{size:14,strokeWidth:3}),n("common.create")]})})]})]})]}),E&&c.jsx(cx,{title:n("newProject.field.dir.pickerTitle"),initialPath:d.projectDir.trim()||void 0,onCancel:()=>C(!1),onSelect:O=>{const V=Af(O),Q=Af(d.projectDir),K=d.name&&d.name!==Q;f({...d,projectDir:O,name:K?d.name:V}),C(!1)}})]})}function Ur({label:e,hint:t,children:n,className:r}){return c.jsxs("label",{className:`flex flex-col gap-1.5 ${r??""}`,children:[c.jsx("span",{className:"text-sm font-bold",children:e}),n,t&&c.jsx("span",{className:"text-xs text-[var(--color-text-muted)]",children:t})]})}function a4({onClose:e,onCreated:t}){return c.jsx("div",{className:"fixed inset-0 z-50 flex items-start justify-center bg-black/30 p-4 overflow-auto",children:c.jsx("div",{className:"w-full max-w-4xl my-8",children:c.jsx(f2,{onCancel:e,onCreated:n=>{e(),t(n)}})})})}const _k="projects.last",s4=["activity","date","name"];function jk(){const e=Be(),t=ks(),{name:n}=Mb(),[r,a]=Kb("projects.sort","activity"),[o,l]=j.useState(!1),[d,f]=j.useState(!1),{data:h,isLoading:g,isError:m,error:y,refetch:b}=Ye({queryKey:["projects"],queryFn:Es}),k=M=>t(`/projects/${encodeURIComponent(M)}`),v=h?c_(h.data,r):[],N=r!=="name",{recent:E,older:C}=N?rI(v,M=>M.lastActivityAt):{recent:v,older:[]},S=o?C:C.filter(M=>M.name===n),_=C.length-S.length;return j.useEffect(()=>{if(n)try{localStorage.setItem(_k,n)}catch{}},[n]),j.useEffect(()=>{if(n||!h)return;let M=null;try{M=localStorage.getItem(_k)}catch{}M&&h.data.some(T=>T.name===M)&&t(`/projects/${encodeURIComponent(M)}`,{replace:!0})},[n,h,t]),c.jsxs("div",{className:"flex flex-col flex-1 min-h-0 w-full",children:[m?c.jsxs("div",{className:"nb-card bg-[var(--color-crashed-bg)]",children:[c.jsx("h2",{className:"font-[family-name:var(--font-heading)] text-xl font-bold mb-2",children:e("projects.load.failed")}),c.jsx("p",{className:"text-sm text-[var(--color-text)]",children:y instanceof Error?y.message:String(y)}),c.jsx("button",{className:"nb-btn mt-4",onClick:()=>b(),type:"button",children:e("common.retry")})]}):h&&h.data.length===0?c.jsx(u4,{onNew:()=>f(!0)}):c.jsxs("div",{className:"flex gap-5 flex-1 min-h-0",children:[c.jsxs("aside",{className:"w-80 shrink-0 flex flex-col min-h-0",children:[c.jsxs("div",{className:"shrink-0 flex flex-col gap-2 pb-3",children:[c.jsxs("div",{className:"flex items-center justify-between gap-2",children:[c.jsxs("div",{className:"min-w-0",children:[c.jsx("h1",{className:"font-[family-name:var(--font-heading)] text-2xl font-bold truncate",children:e("projects.title")}),c.jsx("p",{className:"text-xs text-[var(--color-text-muted)]",children:h?e("projects.count",{count:h.data.length}):e("common.loading")})]}),c.jsxs("button",{className:"nb-btn nb-btn-primary shrink-0",type:"button",onClick:()=>f(!0),"aria-label":e("projects.new"),children:[c.jsx(pr,{size:16,strokeWidth:3}),e("projects.new")]})]}),c.jsxs("div",{className:"flex items-center gap-2",children:[c.jsx("div",{className:"inline-flex flex-1 border-[3px] border-[var(--color-text)] rounded-xl overflow-hidden shadow-[3px_3px_0_var(--color-text)]",role:"group","aria-label":e("projects.sort.label"),children:s4.map(M=>c.jsx("button",{type:"button","aria-pressed":r===M,onClick:()=>a(M),className:["flex-1 px-2 py-1.5 text-xs font-bold font-[family-name:var(--font-mono)] focus-visible:outline focus-visible:outline-2",r===M?"bg-[var(--color-accent-mint)]":"bg-[var(--color-bg)] hover:bg-[var(--color-bg-cream)]"].join(" "),children:e(`projects.sort.${M}`)},M))}),c.jsx("button",{className:"nb-btn nb-btn-yellow shrink-0",style:{padding:"6px 10px"},onClick:()=>b(),type:"button","aria-label":e("common.refresh"),children:c.jsx($h,{size:16,strokeWidth:2.5})})]})]}),c.jsx("ul",{className:"flex-1 min-h-0 overflow-y-auto flex flex-col gap-2 pr-1",children:g?c.jsx(c4,{}):c.jsxs(c.Fragment,{children:[[...E,...S].map(M=>c.jsx(o4,{project:M,selected:M.name===n,onClick:()=>k(M.name)},M.name)),(_>0||o&&C.length>0)&&c.jsx("button",{type:"button",className:"nb-btn text-xs self-start mt-1",onClick:()=>l(M=>!M),"aria-label":o?"收起更早项目":"显示更早项目",children:o?"收起更早":`含更早 (${_})`})]})})]}),c.jsx("div",{className:"flex-1 min-w-0 min-h-0 flex flex-col",children:n?c.jsx(Wz,{name:n,embedded:!0}):c.jsx("div",{className:"nb-card",children:c.jsx("p",{className:"text-[var(--color-text-muted)]",children:e("projects.selectHint")})})})]}),d&&c.jsx(a4,{onClose:()=>f(!1),onCreated:k})]})}function o4({project:e,selected:t,onClick:n}){return c.jsx("li",{children:c.jsxs("button",{type:"button",onClick:n,className:`nb-card w-full text-left ${t?"bg-[var(--color-accent-mint)]":""}`,style:{padding:"10px 12px"},children:[c.jsxs("div",{className:"flex items-center justify-between gap-2",children:[c.jsx("h3",{className:"font-[family-name:var(--font-heading)] font-bold truncate",children:e.name}),c.jsx(l4,{status:e.pipelineStatus})]}),e.repoDir&&c.jsx("p",{className:"text-[10px] font-[family-name:var(--font-mono)] text-[var(--color-text-muted)] truncate mt-0.5",children:e.repoDir}),c.jsxs("div",{className:"flex gap-3 text-[11px] font-[family-name:var(--font-mono)] text-[var(--color-text-muted)] mt-1.5",children:[c.jsxs("span",{children:[e.cards.total," cards"]}),c.jsxs("span",{children:[e.cards.inprogress," run"]}),c.jsxs("span",{children:[e.workers.active,"/",e.workers.total," w"]})]})]})})}function l4({status:e}){const t={running:{bg:"var(--color-running-bg)",label:"running"},idle:{bg:"var(--color-idle-bg)",label:"idle"},stopping:{bg:"var(--color-stuck-bg)",label:"stopping"},error:{bg:"var(--color-crashed-bg)",label:"error"}},{bg:n,label:r}=t[e],a=e==="running"?"var(--color-running)":e==="error"?"var(--color-crashed)":e==="stopping"?"var(--color-stuck)":"var(--color-idle)";return c.jsx("span",{className:"nb-status",style:{background:n,color:a},children:r})}function c4(){return c.jsx(c.Fragment,{children:[0,1,2].map(e=>c.jsxs("div",{className:"nb-card opacity-60 animate-pulse",style:{padding:"10px 12px"},children:[c.jsx("div",{className:"h-5 w-28 bg-[var(--color-border-light)] rounded-md mb-2"}),c.jsx("div",{className:"h-3 w-2/3 bg-[var(--color-border-light)] rounded-md"})]},e))})}function u4({onNew:e}){const t=Be(),n=t("projects.empty.hint",{cmd:"__CMD__"}),[r,a]=n.split("__CMD__");return c.jsxs("div",{className:"nb-card bg-[var(--color-accent-yellow)] flex items-center gap-6 p-8",children:[c.jsx("div",{className:"w-20 h-20 rounded-2xl bg-[var(--color-accent-mint)] border-[3px] border-[var(--color-text)] shadow-[3px_3px_0_var(--color-text)] flex items-center justify-center",children:c.jsx(n_,{size:32,strokeWidth:2.5})}),c.jsxs("div",{className:"flex-1",children:[c.jsx("h2",{className:"font-[family-name:var(--font-heading)] text-2xl font-bold mb-2",children:t("projects.empty.title")}),c.jsxs("p",{className:"text-sm text-[var(--color-text)] mb-4",children:[r,c.jsx("code",{className:"bg-[var(--color-bg)] border-2 border-[var(--color-text)] px-2 py-0.5 rounded-md font-[family-name:var(--font-mono)]",children:"sps project init <name>"}),a]}),c.jsxs("button",{className:"nb-btn nb-btn-primary",type:"button",onClick:e,children:[c.jsx(pr,{size:16,strokeWidth:3}),t("projects.new")]})]})]})}function d4({project:e,isPending:t,onCancel:n,onCreate:r}){var S;const a=Be(),[o,l]=j.useState(""),[d,f]=j.useState(""),[h,g]=j.useState(new Set),[m,y]=j.useState(!1),b=Ye({queryKey:["skills-all",e],queryFn:()=>ox(e)});j.useEffect(()=>{const _=M=>{M.key==="Escape"&&n()};return window.addEventListener("keydown",_),()=>window.removeEventListener("keydown",_)},[n]);const v=o.trim().length>0&&o.trim().length<=200&&!t,N=_=>{const M=new Set(h);M.has(_)?M.delete(_):M.add(_),g(M)},E=()=>{v&&r({title:o.trim(),description:d.trim(),skills:[...h],labels:["AI-PIPELINE"],initialState:m?"Backlog":"Planning"})},C=((S=b.data)==null?void 0:S.data)??[];return c.jsx("div",{role:"dialog","aria-modal":"true",className:"fixed inset-0 z-40 flex items-start justify-center p-6 bg-black/30 overflow-auto",children:c.jsxs("div",{className:"nb-card mt-8 w-full max-w-xl flex flex-col",style:{maxHeight:"calc(100vh - 64px)"},children:[c.jsxs("header",{className:"flex items-center justify-between mb-4 flex-shrink-0",children:[c.jsx("h2",{className:"font-[family-name:var(--font-heading)] text-2xl font-bold",children:a("newCard.title")}),c.jsx("button",{className:"nb-btn nb-btn-mint p-2",onClick:n,type:"button","aria-label":a("common.close"),children:c.jsx(Sn,{size:14,strokeWidth:3})})]}),c.jsxs("form",{onSubmit:_=>{_.preventDefault(),E()},className:"flex flex-col gap-4 overflow-auto",children:[c.jsxs("label",{className:"flex flex-col gap-1.5",children:[c.jsx("span",{className:"text-sm font-bold",children:a("newCard.field.title")}),c.jsx("input",{type:"text",className:"nb-input w-full",placeholder:a("newCard.field.title.placeholder"),value:o,onChange:_=>l(_.target.value),maxLength:200,autoFocus:!0,required:!0}),c.jsx("span",{className:"text-xs text-[var(--color-text-muted)]",children:a("newCard.field.title.help")})]}),c.jsxs("label",{className:"flex flex-col gap-1.5",children:[c.jsx("span",{className:"text-sm font-bold",children:a("newCard.field.description")}),c.jsx("textarea",{className:"nb-input w-full",style:{minHeight:120,resize:"vertical"},placeholder:a("newCard.field.description.placeholder"),value:d,onChange:_=>f(_.target.value)}),c.jsx("span",{className:"text-xs text-[var(--color-text-muted)]",children:a("newCard.field.description.help")})]}),c.jsxs("div",{className:"flex flex-col gap-2",children:[c.jsx("span",{className:"text-sm font-bold",children:a("newCard.field.skills")}),c.jsx("span",{className:"text-xs text-[var(--color-text-muted)]",children:a("newCard.field.skills.help")}),b.isLoading&&c.jsx("p",{className:"text-xs text-[var(--color-text-muted)] italic",children:a("newCard.field.skills.loading")}),b.isError&&c.jsx("p",{className:"text-xs text-[var(--color-crashed)]",children:a("newCard.field.skills.error",{detail:b.error instanceof Error?b.error.message:String(b.error)})}),C.length>0&&c.jsx("div",{className:"flex flex-wrap gap-2",children:C.map(_=>{const M=h.has(_.name);return c.jsx("button",{type:"button",onClick:()=>N(_.name),className:["px-2.5 py-1 text-xs font-[family-name:var(--font-mono)] rounded-full border-2 transition-all",M?"bg-[var(--color-accent-mint)] border-[var(--color-text)] shadow-[2px_2px_0_var(--color-text)] font-bold":"bg-[var(--color-bg)] border-[var(--color-border-light)] hover:border-[var(--color-text)]"].join(" "),"aria-pressed":M,children:_.name},_.name)})}),h.size>0&&c.jsx("p",{className:"text-xs text-[var(--color-text-muted)]",children:a("newCard.field.skills.selected",{count:h.size,names:[...h].join(", ")})})]}),c.jsxs("div",{className:"flex flex-col gap-2",children:[c.jsx("span",{className:"text-sm font-bold",children:a("newCard.field.dispatch")}),c.jsxs("label",{className:"flex items-center gap-3 cursor-pointer select-none p-3 border-[2px] border-[var(--color-text)] rounded-lg bg-[var(--color-bg-cream)]",children:[c.jsx("input",{type:"checkbox",className:"w-4 h-4 accent-[var(--color-cta)] cursor-pointer",checked:m,onChange:_=>y(_.target.checked)}),c.jsxs("div",{className:"flex-1",children:[c.jsx("div",{className:"text-sm font-bold",children:a("newCard.field.dispatch.label")}),c.jsx("div",{className:"text-xs text-[var(--color-text-muted)] mt-0.5",children:a("newCard.field.dispatch.help")})]})]})]})]}),c.jsxs("div",{className:"flex gap-2 justify-end mt-4 pt-3 border-t-2 border-dashed border-[var(--color-text)] flex-shrink-0",children:[c.jsx("button",{className:"nb-btn",style:{padding:"6px 14px"},onClick:n,disabled:t,type:"button",children:a("common.cancel")}),c.jsxs("button",{className:"nb-btn nb-btn-primary",style:{padding:"6px 14px"},onClick:E,disabled:!v,type:"button","aria-label":a("newCard.create.aria"),children:[t?c.jsx(Xe,{size:13,strokeWidth:3,className:"animate-spin"}):c.jsx(pr,{size:13,strokeWidth:3}),a("common.create")]})]})]})})}function f4(e){return ft(`/api/projects/${encodeURIComponent(e)}/cards`)}function h4(e,t){return ft(`/api/projects/${encodeURIComponent(e)}/cards/${t}`)}async function ac(e,t){const n=await fetch(e,{method:"POST",headers:t?{"Content-Type":"application/json"}:void 0,body:t?JSON.stringify(t):void 0});if(!n.ok){const r=await n.text();throw new Error(`${n.status} ${n.statusText}: ${r}`)}return n.json().catch(()=>({}))}function p4(e,t){return ac(`/api/projects/${encodeURIComponent(e)}/cards/${t}/reset`)}async function m4(e,t){const n=await fetch(`/api/projects/${encodeURIComponent(e)}/cards/${t}`,{method:"DELETE"});if(!n.ok){const r=await n.text();throw new Error(`${n.status}: ${r}`)}}function g4(e,t){return ac(`/api/projects/${encodeURIComponent(e)}/cards/${t}/launch`)}function y4(e,t){const n=typeof t=="string"?{title:t}:t;return ac(`/api/projects/${encodeURIComponent(e)}/cards`,n)}async function b4(e,t,n){const r=await fetch(`/api/projects/${encodeURIComponent(e)}/cards/${t}`,{method:"PATCH",headers:{"Content-Type":"application/json"},body:JSON.stringify({state:n})});if(!r.ok){const a=await r.text();throw new Error(`${r.status}: ${a}`)}}async function x4(e,t,n){const r=await fetch(`/api/projects/${encodeURIComponent(e)}/cards/${t}`,{method:"PATCH",headers:{"Content-Type":"application/json"},body:JSON.stringify(n)});if(!r.ok){const a=await r.text();throw new Error(`${r.status}: ${a}`)}return r.json()}function h2(e){return ac(`/api/projects/${encodeURIComponent(e)}/pipeline/start`)}function p2(e){return ac(`/api/projects/${encodeURIComponent(e)}/pipeline/stop`)}function v4(e,t){return ac(`/api/projects/${encodeURIComponent(e)}/pipeline/reset`,t??{})}function w4(e){const t=Gt();j.useEffect(()=>{if(!e)return;const n=`/stream/projects/${encodeURIComponent(e)}`,r=new EventSource(n),a=d=>{try{const f=JSON.parse(d.data);t.invalidateQueries({queryKey:["cards",f.project]}),t.invalidateQueries({queryKey:["card",f.project,f.seq]}),t.invalidateQueries({queryKey:["projects"]})}catch{}},o=d=>{try{const f=JSON.parse(d.data);t.invalidateQueries({queryKey:["workers",f.project]}),t.invalidateQueries({queryKey:["projects"]})}catch{}},l=d=>{try{const f=JSON.parse(d.data);t.invalidateQueries({queryKey:["pipeline-status",f.project]}),t.invalidateQueries({queryKey:["projects"]})}catch{}};return r.addEventListener("card.created",a),r.addEventListener("card.updated",a),r.addEventListener("card.moved",a),r.addEventListener("card.deleted",a),r.addEventListener("worker.updated",o),r.addEventListener("worker.added",o),r.addEventListener("worker.deleted",o),r.addEventListener("pipeline.status",l),r.addEventListener("pipeline.started",l),r.addEventListener("pipeline.stopped",l),()=>r.close()},[e,t])}const k4=new Set(["python","typescript","golang","rust","kotlin","swift","java"]),E4=new Set(["frontend","backend","mobile","database","devops"]),S4=new Set(["backend-architect","frontend-developer","code-reviewer","database-optimizer","devops-automator","security-engineer","qa-tester","security","qa","architect","db-opt"]),N4=new Set(["coding-standards","tdd-workflow","git-workflow","architecture-decision-records","debugging-workflow"]);function _4(e){return k4.has(e)?"lang":E4.has(e)?"end":S4.has(e)?"persona":N4.has(e)?"workflow":"other"}const j4={lang:"var(--color-accent-purple)",end:"var(--color-secondary)",persona:"var(--color-primary)",workflow:"var(--color-accent-mint)",other:"var(--color-bg)"};function ux({name:e}){const t=j4[_4(e)];return c.jsx("span",{className:"nb-badge",style:{background:t},children:e})}function m2({label:e,kind:t="default"}){const n=t==="warn"?"var(--color-accent-pink)":t==="accent"?"var(--color-accent-yellow)":"var(--color-bg-cream)";return c.jsx("span",{className:"nb-badge",style:{background:n},children:e})}function C4({card:e,onClick:t,done:n,draggable:r}){const a=Be(),o=e.labels.some(l=>l.startsWith("STARTED-"))&&!n;return c.jsxs("article",{onClick:t,onKeyDown:l=>{(l.key==="Enter"||l.key===" ")&&(l.preventDefault(),t())},draggable:r,onDragStart:l=>{l.dataTransfer.setData("application/x-sps-card-seq",String(e.seq)),l.dataTransfer.effectAllowed="move"},tabIndex:0,role:"button","aria-label":`Card #${e.seq}: ${e.title}`,className:["bg-[var(--color-bg)] border-[3px] border-[var(--color-text)] rounded-xl p-3","shadow-[3px_3px_0_var(--color-text)] cursor-pointer","transition-[transform,box-shadow] duration-[180ms] ease-out","hover:-translate-x-0.5 hover:-translate-y-0.5 hover:shadow-[5px_5px_0_var(--color-text)]","focus:outline-none focus-visible:ring-[3px] focus-visible:ring-offset-2 focus-visible:ring-[var(--color-text)]",n?"opacity-60":"",r?"active:cursor-grabbing":""].join(" "),children:[c.jsxs("div",{className:"flex items-center justify-between gap-2 mb-2",children:[c.jsxs("span",{className:"font-[family-name:var(--font-mono)] font-bold text-[11px] px-2 py-0.5 bg-[var(--color-bg-cream)] border-2 border-[var(--color-text)] rounded-full",children:["#",e.seq]}),o&&c.jsx("span",{className:"nb-status",style:{background:"var(--color-running-bg)",color:"var(--color-running)"},children:"running"})]}),c.jsx("p",{className:`font-bold text-sm leading-5 mb-2 line-clamp-2 ${n?"line-through decoration-2":""}`,children:e.title}),(e.skills.length>0||e.labels.length>0)&&c.jsxs("div",{className:"flex flex-wrap gap-1 mb-2",children:[e.skills.slice(0,3).map(l=>c.jsx(ux,{name:l},l)),e.labels.filter(l=>l==="NEEDS-FIX").map(l=>c.jsx(m2,{label:l,kind:"warn"},l))]}),e.checklist&&e.checklist.total>0&&c.jsx(A4,{stats:e.checklist}),c.jsxs("div",{className:"pt-2 border-t-[1.5px] border-dashed border-[var(--color-border-light)] flex items-center gap-2 text-[11px] font-[family-name:var(--font-mono)] text-[var(--color-text-subtle)]",children:[c.jsx("span",{children:T4(e.updatedAt??e.createdAt,a)}),e.branch&&c.jsxs("span",{className:"truncate",children:["· ",e.branch]})]})]})}function A4({stats:e}){const t=Be();return c.jsxs("div",{className:"mb-2",children:[c.jsxs("div",{className:"flex items-center justify-between text-[11px] font-[family-name:var(--font-mono)] mb-1",children:[c.jsx("span",{className:"font-bold",children:t("kanban.checklist.label",{done:e.done,total:e.total})}),c.jsxs("span",{className:"text-[var(--color-text-subtle)]",children:[e.percent,"%"]})]}),c.jsx("div",{className:"w-full h-1.5 bg-[var(--color-bg-cream)] border-2 border-[var(--color-text)] rounded-full overflow-hidden mb-1.5",children:c.jsx("div",{className:"h-full bg-[var(--color-cta)] transition-[width] duration-200",style:{width:`${e.percent}%`}})}),c.jsxs("ul",{className:"text-[11px] space-y-0.5",children:[e.items.slice(0,3).map((n,r)=>c.jsxs("li",{className:`flex items-start gap-1 ${n.done?"opacity-60 line-through":""}`,children:[c.jsx("span",{className:"flex-shrink-0 mt-0.5",children:n.done?"✓":"○"}),c.jsx("span",{className:"line-clamp-1",children:n.text})]},r)),e.items.length>3&&c.jsx("li",{className:"text-[var(--color-text-subtle)] italic pl-3",children:t("kanban.checklist.more",{count:e.items.length-3})})]})]})}function T4(e,t){if(!e)return"—";const n=new Date(e),r=Date.now()-n.getTime();return r<6e4?t("kanban.time.justNow"):r<36e5?t("kanban.time.minutes",{n:Math.floor(r/6e4)}):r<864e5?t("kanban.time.hours",{n:Math.floor(r/36e5)}):n.toLocaleDateString()}function M4({label:e,bg:t,cards:n,onCardClick:r,onDropCard:a}){const o=Be(),[l,d]=j.useState(!1);return c.jsxs("div",{className:["flex flex-col p-3 rounded-2xl border-[3px] min-h-[280px] h-full min-h-0 overflow-hidden","transition-all",l?"border-[var(--color-cta)] shadow-[4px_4px_0_var(--color-cta)]":"border-[var(--color-text)]"].join(" "),style:{background:t},onDragOver:f=>{!a||!f.dataTransfer.types.includes("application/x-sps-card-seq")||(f.preventDefault(),f.dataTransfer.dropEffect="move",l||d(!0))},onDragLeave:()=>d(!1),onDrop:f=>{if(d(!1),!a)return;const h=f.dataTransfer.getData("application/x-sps-card-seq"),g=Number.parseInt(h,10);Number.isFinite(g)&&(f.preventDefault(),a(g))},children:[c.jsxs("div",{className:"flex items-center justify-between px-1 pb-2 mb-2 border-b-2 border-[var(--color-text)] shrink-0",children:[c.jsx("span",{className:"font-[family-name:var(--font-heading)] font-bold text-sm uppercase tracking-wider",children:e}),c.jsx("span",{className:"font-[family-name:var(--font-mono)] font-bold text-xs px-2 py-0.5 bg-[var(--color-bg)] border-2 border-[var(--color-text)] rounded-full",children:n.length})]}),c.jsxs("div",{className:"flex flex-col gap-2 flex-1 min-h-0 overflow-y-auto pr-1 -mr-1",style:{scrollbarWidth:"thin",scrollbarColor:"var(--color-text) transparent"},children:[n.length===0&&c.jsx("div",{className:"text-xs text-[var(--color-text-muted)] text-center py-6 italic",children:o("kanban.column.empty")}),n.map(f=>c.jsx(C4,{card:f,onClick:()=>r(f),done:e==="Done",draggable:!!a},f.seq))]})]})}function Qy(e,t){if(!e)return"";const n=e.split(`
|
|
603
603
|
`),r=new RegExp(`^##\\s+${t}\\s*$`),a=n.findIndex(l=>r.test(l));if(a===-1)return"";let o=n.length;for(let l=a+1;l<n.length;l++)if(/^##\s+/.test(n[l]??"")){o=l;break}return n.slice(a+1,o).join(`
|
|
604
604
|
`).trim()}function $g(e){return Qy(e,"描述")}function D4({project:e,seq:t,onClose:n,onChanged:r}){var V,Q,K,I,P,G,B,oe,xe,ke,Ee;const a=Be(),o=Gt(),{confirm:l,alert:d}=un(),{data:f,isLoading:h,isError:g,error:m,refetch:y}=Ye({queryKey:["card",e,t],queryFn:()=>h4(e,t)}),[b,k]=j.useState(!1),[v,N]=j.useState(""),[E,C]=j.useState(""),[S,_]=j.useState(new Set),[M,T]=j.useState([]),[L,R]=j.useState(""),$=Ye({queryKey:["skills-all",e],queryFn:()=>ox(e),enabled:b}),q=((Q=(V=Ye({queryKey:["projects"],queryFn:Es,refetchInterval:1e4}).data)==null?void 0:V.data.find(J=>J.name===e))==null?void 0:Q.pipelineStatus)==="running";j.useEffect(()=>{b&&f&&(N(f.title),C($g(f.body)),_(new Set(f.skills)),T([...f.labels]))},[b,f]),j.useEffect(()=>{const J=ue=>{ue.key==="Escape"&&(b?k(!1):n())};return window.addEventListener("keydown",J),()=>window.removeEventListener("keydown",J)},[n,b]);const F=Ct({mutationFn:()=>{if(!f)throw new Error("no data");const J={},ue=v.trim();ue&&ue!==f.title&&(J.title=ue);const Te=$g(f.body);E!==Te&&(J.description=E);const Oe=[...S].sort(),De=[...f.skills].sort();return JSON.stringify(Oe)!==JSON.stringify(De)&&(J.skills=Oe),JSON.stringify(M)!==JSON.stringify(f.labels)&&(J.labels=M),Object.keys(J).length===0?Promise.resolve({ok:!0,noop:!0}):x4(e,t,J)},onSuccess:()=>{o.invalidateQueries({queryKey:["card",e,t]}),o.invalidateQueries({queryKey:["cards",e]}),k(!1),r()},onError:J=>{d({title:a("cardModal.error.save.title"),body:J instanceof Error?J.message:String(J)})}}),Y=j.useMemo(()=>{if(!b||!f)return!1;if(v.trim()!==f.title||E!==$g(f.body))return!0;const J=[...S].sort(),ue=[...f.skills].sort();return JSON.stringify(J)!==JSON.stringify(ue)||JSON.stringify(M)!==JSON.stringify(f.labels)},[b,f,v,E,S,M]),D=J=>{const ue=new Set(S);ue.has(J)?ue.delete(J):ue.add(J),_(ue)},H=()=>{const J=L.trim();if(J){if(M.includes(J)){R("");return}T([...M,J]),R("")}},O=J=>{T(M.filter(ue=>ue!==J))};return c.jsx("div",{role:"dialog","aria-modal":"true","aria-labelledby":"card-modal-title",className:"fixed inset-0 z-40 flex items-start justify-center p-6 bg-black/30 overflow-auto",children:c.jsxs("div",{className:"nb-card mt-12 w-full max-w-3xl bg-[var(--color-bg)]",children:[c.jsxs("header",{className:"flex items-start justify-between gap-4 mb-4",children:[c.jsxs("div",{className:"flex-1 min-w-0",children:[c.jsxs("div",{className:"flex items-center gap-3 mb-1",children:[c.jsxs("span",{className:"font-[family-name:var(--font-mono)] font-bold text-xs px-2 py-0.5 bg-[var(--color-accent-purple)] border-2 border-[var(--color-text)] rounded-full",children:["#",t]}),(f==null?void 0:f.state)&&c.jsx("span",{className:"font-[family-name:var(--font-mono)] text-xs px-2 py-0.5 bg-[var(--color-bg-cream)] border-2 border-[var(--color-text)] rounded-full font-semibold",children:f.state}),b&&c.jsx("span",{className:"text-xs font-bold text-[var(--color-stuck)]",children:a("cardModal.editing")})]}),b?c.jsx("input",{type:"text",className:"nb-input w-full font-[family-name:var(--font-heading)] text-xl font-bold",value:v,onChange:J=>N(J.target.value),maxLength:200,"aria-label":a("cardModal.title.aria")}):c.jsx("h2",{id:"card-modal-title",className:"font-[family-name:var(--font-heading)] text-2xl font-bold break-words",children:(f==null?void 0:f.title)??a("common.loading")})]}),c.jsxs("div",{className:"flex gap-2 flex-shrink-0",children:[!b&&f&&c.jsxs("button",{onClick:()=>k(!0),className:"nb-btn",style:{padding:"6px 12px"},type:"button","aria-label":a("cardModal.editAria"),children:[c.jsx(qh,{size:12,strokeWidth:2.5})," ",a("cardModal.edit")]}),c.jsx("button",{onClick:n,className:"nb-btn nb-btn-mint p-2","aria-label":a("cardModal.close.aria"),type:"button",children:c.jsx(Sn,{size:14,strokeWidth:3})})]})]}),h&&c.jsx("p",{className:"text-[var(--color-text-muted)]",children:a("common.loading")}),g&&c.jsx("p",{className:"text-[var(--color-crashed)]",children:a("cardModal.error.load",{detail:m instanceof Error?m.message:String(m)})}),f&&c.jsxs("div",{className:"flex flex-col gap-4",children:[f.branch&&!b&&c.jsxs("div",{className:"flex items-center gap-2 text-sm",children:[c.jsx(cL,{size:14}),c.jsx("span",{className:"font-[family-name:var(--font-mono)]",children:f.branch})]}),b?c.jsxs(c.Fragment,{children:[c.jsxs("div",{children:[c.jsx("div",{className:"text-sm font-bold mb-1.5",children:"Skills"}),$.isLoading&&c.jsx("p",{className:"text-xs text-[var(--color-text-muted)] italic",children:a("cardModal.skills.loading")}),$.data&&$.data.data.length>0&&c.jsx("div",{className:"flex flex-wrap gap-1.5",children:$.data.data.map(J=>{const ue=S.has(J.name);return c.jsx("button",{type:"button",onClick:()=>D(J.name),"aria-pressed":ue,className:["px-2.5 py-1 text-xs font-[family-name:var(--font-mono)] rounded-full border-2 transition-all",ue?"bg-[var(--color-accent-mint)] border-[var(--color-text)] shadow-[2px_2px_0_var(--color-text)] font-bold":"bg-[var(--color-bg)] border-[var(--color-border-light)] hover:border-[var(--color-text)]"].join(" "),children:J.name},J.name)})})]}),c.jsxs("div",{children:[c.jsx("div",{className:"text-sm font-bold mb-1.5",children:"Labels"}),c.jsxs("div",{className:"flex flex-wrap gap-1.5 items-center",children:[M.map(J=>c.jsxs("span",{className:"inline-flex items-center gap-1 px-2 py-0.5 text-xs font-[family-name:var(--font-mono)] bg-[var(--color-accent-yellow)] border-2 border-[var(--color-text)] rounded-full",children:[J,c.jsx("button",{type:"button",onClick:()=>O(J),className:"hover:text-[var(--color-crashed)]","aria-label":a("cardModal.label.removeAria",{label:J}),children:c.jsx(Sn,{size:10,strokeWidth:3})})]},J)),c.jsx("input",{type:"text",className:"nb-input",style:{padding:"4px 8px",fontSize:12,width:140},placeholder:a("cardModal.label.addPlaceholder"),value:L,onChange:J=>R(J.target.value),onKeyDown:J=>{J.key==="Enter"&&!J.nativeEvent.isComposing&&(J.preventDefault(),H())}}),L&&c.jsx("button",{type:"button",className:"nb-btn",style:{padding:"2px 6px",fontSize:11},onClick:H,"aria-label":a("cardModal.label.addAria"),children:c.jsx(pr,{size:10,strokeWidth:3})})]}),c.jsx("p",{className:"text-[10px] text-[var(--color-text-muted)] mt-1",children:a("cardModal.label.note")})]})]}):c.jsxs(c.Fragment,{children:[f.skills.length>0&&c.jsxs("div",{children:[c.jsx("div",{className:"text-sm font-bold mb-1.5",children:"Skills"}),c.jsx("div",{className:"flex items-center gap-2 flex-wrap",children:f.skills.map(J=>c.jsx(ux,{name:J},J))})]}),f.labels.length>0&&c.jsxs("div",{children:[c.jsx("div",{className:"text-sm font-bold mb-1.5",children:"Labels"}),c.jsx("div",{className:"flex items-center gap-2 flex-wrap",children:f.labels.map(J=>c.jsx(m2,{label:J,kind:J==="NEEDS-FIX"?"warn":"default"},J))})]})]}),b?c.jsxs(c.Fragment,{children:[c.jsxs("div",{children:[c.jsx("h3",{className:"font-[family-name:var(--font-heading)] text-sm font-bold mb-2 uppercase tracking-wider",children:a("cardModal.section.description")}),c.jsx("textarea",{className:"nb-input w-full font-[family-name:var(--font-mono)] text-xs",style:{minHeight:180,resize:"vertical"},value:E,onChange:J=>C(J.target.value),"aria-label":a("cardModal.body.aria")}),c.jsx("p",{className:"text-[10px] text-[var(--color-text-muted)] mt-1",children:a("cardModal.body.replaceNote")})]}),(((oe=f.checklist)==null?void 0:oe.total)??0)>0&&c.jsxs("div",{className:"nb-card bg-[var(--color-bg-cream)] p-3",children:[c.jsx("div",{className:"flex items-center justify-between mb-2",children:c.jsxs("span",{className:"font-bold text-sm",children:[a("cardModal.section.checklist")," ",((xe=f.checklist)==null?void 0:xe.done)??0,"/",((ke=f.checklist)==null?void 0:ke.total)??0]})}),c.jsx("ul",{className:"text-sm space-y-1",children:(((Ee=f.checklist)==null?void 0:Ee.items)??[]).map((J,ue)=>c.jsxs("li",{className:`flex items-start gap-2 ${J.done?"opacity-60 line-through":""}`,children:[c.jsx("span",{children:J.done?"✓":"○"}),c.jsx("span",{children:J.text})]},ue))})]})]}):c.jsxs(c.Fragment,{children:[c.jsxs("div",{children:[c.jsx("h3",{className:"font-[family-name:var(--font-heading)] text-sm font-bold mb-2 uppercase tracking-wider",children:a("cardModal.section.description")}),c.jsx("pre",{className:"text-xs whitespace-pre-wrap font-[family-name:var(--font-mono)] bg-[var(--color-bg-cream)] border-2 border-[var(--color-text)] rounded-lg p-4 max-h-64 overflow-auto",children:Qy(f.body,"描述")||a("cardModal.section.empty")})]}),c.jsxs("div",{children:[c.jsxs("h3",{className:"font-[family-name:var(--font-heading)] text-sm font-bold mb-2 uppercase tracking-wider",children:[a("cardModal.section.checklist")," ",c.jsxs("span",{className:"text-[var(--color-text-muted)] normal-case tracking-normal",children:[((K=f.checklist)==null?void 0:K.done)??0,"/",((I=f.checklist)==null?void 0:I.total)??0]})]}),c.jsx("div",{className:"nb-card bg-[var(--color-bg-cream)] p-3",children:(((P=f.checklist)==null?void 0:P.total)??0)>0?c.jsxs(c.Fragment,{children:[c.jsx("div",{className:"flex items-center justify-end mb-2",children:c.jsx("div",{className:"w-24 h-2 bg-[var(--color-bg)] border-2 border-[var(--color-text)] rounded-full overflow-hidden",children:c.jsx("div",{className:"h-full bg-[var(--color-cta)]",style:{width:`${((G=f.checklist)==null?void 0:G.percent)??0}%`}})})}),c.jsx("ul",{className:"text-sm space-y-1",children:(((B=f.checklist)==null?void 0:B.items)??[]).map((J,ue)=>c.jsxs("li",{className:`flex items-start gap-2 ${J.done?"opacity-60 line-through":""}`,children:[c.jsx("span",{children:J.done?"✓":"○"}),c.jsx("span",{children:J.text})]},ue))})]}):c.jsx("p",{className:"text-xs text-[var(--color-text-muted)] italic",children:a("cardModal.checklist.empty")})})]}),c.jsxs("div",{children:[c.jsx("h3",{className:"font-[family-name:var(--font-heading)] text-sm font-bold mb-2 uppercase tracking-wider",children:a("cardModal.section.log")}),c.jsx("pre",{className:"text-xs whitespace-pre-wrap font-[family-name:var(--font-mono)] bg-[var(--color-bg-cream)] border-2 border-[var(--color-text)] rounded-lg p-4 max-h-64 overflow-auto",children:Qy(f.body,"日志")||a("cardModal.section.empty")})]})]}),c.jsx("div",{className:"flex gap-2 pt-2 border-t-2 border-[var(--color-border-light)] justify-end flex-wrap",children:b?c.jsxs(c.Fragment,{children:[c.jsx("button",{className:"nb-btn",type:"button",onClick:()=>{k(!1),y()},disabled:F.isPending,children:a("common.cancel")}),c.jsxs("button",{className:"nb-btn nb-btn-primary",type:"button",onClick:()=>F.mutate(),disabled:!Y||!v.trim()||F.isPending,"aria-label":a("cardDetail.save"),children:[F.isPending?c.jsx(Xe,{size:14,strokeWidth:3,className:"animate-spin"}):c.jsx(Ri,{size:14,strokeWidth:3}),a("common.save")]})]}):c.jsxs(c.Fragment,{children:[c.jsxs("button",{className:"nb-btn nb-btn-primary",type:"button",disabled:f.state==="Done"||q,title:f.state==="Done"?a("cardModal.action.launch.disabledDone"):q?a("cardModal.action.launch.disabledRunning"):void 0,onClick:async()=>{try{await g4(e,t),r()}catch(J){d({title:a("cardModal.action.launch.error"),body:J instanceof Error?J.message:String(J)})}},children:[c.jsx(Yu,{size:14,strokeWidth:3}),a("cardModal.action.launch")]}),c.jsxs("button",{className:"nb-btn nb-btn-yellow",type:"button",onClick:async()=>{if(await l({title:a("cardModal.action.reset.confirm.title",{seq:t}),body:a("cardModal.action.reset.confirm.body"),confirm:a("cardModal.action.reset.confirm.button"),danger:!0}))try{await p4(e,t),r(),n()}catch(ue){d({title:a("cardModal.action.reset.error"),body:ue instanceof Error?ue.message:String(ue)})}},children:[c.jsx(Pb,{size:14,strokeWidth:2.5}),a("cardModal.action.reset")]}),c.jsxs("button",{className:"nb-btn",style:{background:"var(--color-crashed)",color:"var(--color-bg)"},type:"button",onClick:async()=>{if(!(!await l({title:a("cardModal.action.delete.confirm1.title",{seq:t}),body:a("cardModal.action.delete.confirm1.body",{title:f.title}),confirm:a("cardModal.action.delete.confirm1.button"),danger:!0})||!await l({title:a("cardModal.action.delete.confirm2.title"),body:a("cardModal.action.delete.confirm2.body",{seq:t}),confirm:a("cardModal.action.delete"),danger:!0})))try{await m4(e,t),r(),n()}catch(Te){d({title:a("projectDetail.pipelines.delete.error"),body:Te instanceof Error?Te.message:String(Te)})}},"aria-label":a("cardModal.action.delete"),children:[c.jsx(fi,{size:14,strokeWidth:2.5}),a("cardModal.action.delete")]})]})})]})]})})}function O4({current:e,onChange:t}){const[n,r]=j.useState(!1),a=j.useRef(null),{data:o}=Ye({queryKey:["projects"],queryFn:Es});return j.useEffect(()=>{const l=d=>{var f;(f=a.current)!=null&&f.contains(d.target)||r(!1)};return document.addEventListener("mousedown",l),()=>document.removeEventListener("mousedown",l)},[]),c.jsxs("div",{className:"relative",ref:a,children:[c.jsxs("button",{type:"button",className:"inline-flex items-center gap-2 px-3 py-2 bg-[var(--color-bg)] border-[3px] border-[var(--color-text)] rounded-xl shadow-[3px_3px_0_var(--color-text)] font-[family-name:var(--font-mono)] text-sm font-bold hover:-translate-x-px hover:-translate-y-px hover:shadow-[4px_4px_0_var(--color-text)] transition-[transform,box-shadow] duration-150",onClick:()=>r(l=>!l),children:[e,c.jsx(Vu,{size:14,strokeWidth:2.5})]}),n&&o&&c.jsx("div",{className:"absolute right-0 mt-2 z-20 min-w-[200px] max-h-[60vh] overflow-y-auto bg-[var(--color-bg)] border-[3px] border-[var(--color-text)] rounded-xl shadow-[5px_5px_0_var(--color-text)]",children:c_(o.data,"activity").map(l=>{const d=l.pipelineStatus==="running";return c.jsxs("button",{type:"button",onClick:()=>{t(l.name),r(!1)},className:["w-full text-left px-4 py-2 text-sm font-semibold flex items-center gap-2",l.name===e?"bg-[var(--color-accent-mint)]":"hover:bg-[var(--color-bg-cream)]"].join(" "),children:[d&&c.jsx(Yu,{size:12,strokeWidth:3,className:"text-[var(--color-running)] shrink-0","aria-label":"运行中"}),c.jsx("span",{className:"font-[family-name:var(--font-mono)]",children:l.name}),c.jsxs("span",{className:"ml-auto text-xs text-[var(--color-text-muted)]",children:[l.cards.total," cards"]})]},l.name)})})]})}const R4=[{state:"Planning",labelKey:"board.col.planning",bg:"var(--color-accent-purple)"},{state:"Backlog",labelKey:"board.col.backlog",bg:"var(--color-bg-cream)"},{state:"Todo",labelKey:"board.col.todo",bg:"var(--color-accent-yellow)"},{state:"Inprogress",labelKey:"board.col.inprogress",bg:"var(--color-secondary)"},{state:"QA",labelKey:"board.col.qa",bg:"var(--color-accent-pink)"},{state:"Done",labelKey:"board.col.done",bg:"var(--color-accent-mint)"}],g2="sps-console:last-board-project";function L4(){if(typeof window>"u")return null;try{return localStorage.getItem(g2)}catch{return null}}function I4(e){if(!(typeof window>"u"))try{localStorage.setItem(g2,e)}catch{}}function z4(){var O,V,Q;const e=Be(),[t,n]=BN(),r=t.get("project"),[a,o]=j.useState(null),[l,d]=j.useState(""),[f,h]=j.useState(()=>new Set),[g,m]=j.useState(()=>new Set),{confirm:y,alert:b}=un();w4(r);const k=Ye({queryKey:["projects"],queryFn:Es}),v=Ye({queryKey:["cards",r],queryFn:()=>f4(r??""),enabled:!!r}),N=Gt(),E=()=>{N.invalidateQueries({queryKey:["cards",r]}),N.invalidateQueries({queryKey:["projects"]}),N.invalidateQueries({queryKey:["pipeline-status",r]})},C=K=>{n({project:K})};j.useEffect(()=>{var I;if(r){I4(r);return}const K=L4();K&&((I=k.data)!=null&&I.data.some(P=>P.name===K))&&n({project:K},{replace:!0})},[r,k.data,n]);const S=Ct({mutationFn:()=>h2(r),onSuccess:()=>{E()},onError:K=>{b({title:e("board.action.startError"),body:K instanceof Error?K.message:String(K)})}}),_=Ct({mutationFn:()=>p2(r),onSuccess:()=>E(),onError:K=>{b({title:e("board.action.stopError"),body:K instanceof Error?K.message:String(K)})}}),M=Ct({mutationFn:()=>v4(r,{all:!0}),onSuccess:()=>E(),onError:K=>{b({title:e("board.action.resetError"),body:K instanceof Error?K.message:String(K)})}}),[T,L]=j.useState(!1),R=Ct({mutationFn:K=>y4(r,K),onSuccess:()=>{E(),L(!1)},onError:K=>{b({title:e("board.action.newCard.error"),body:K instanceof Error?K.message:String(K)})}}),$=Ct({mutationFn:({seq:K,state:I})=>b4(r,K,I),onMutate:async({seq:K,state:I})=>{await N.cancelQueries({queryKey:["cards",r]});const P=N.getQueryData(["cards",r]);return P&&N.setQueryData(["cards",r],{...P,data:P.data.map(G=>G.seq===K?{...G,state:I}:G)}),{prev:P}},onError:(K,I,P)=>{P!=null&&P.prev&&N.setQueryData(["cards",r],P.prev),b({title:e("board.action.moveCard.error"),body:K instanceof Error?K.message:String(K)})},onSettled:()=>{N.invalidateQueries({queryKey:["cards",r]})}}),z=((O=v.data)==null?void 0:O.data)??[],{allSkills:q,allLabels:F}=j.useMemo(()=>{const K=new Set,I=new Set;for(const P of z){for(const G of P.skills)K.add(G);for(const G of P.labels)I.add(G)}return{allSkills:[...K].sort(),allLabels:[...I].sort()}},[z]);if(!r)return c.jsxs("div",{className:"flex flex-col gap-6 w-full",children:[c.jsx("h1",{className:"font-[family-name:var(--font-heading)] text-4xl font-bold",children:e("board.title.bare")}),c.jsxs("div",{className:"nb-card bg-[var(--color-accent-yellow)] max-w-2xl",children:[c.jsx("h2",{className:"font-[family-name:var(--font-heading)] text-xl font-bold mb-3",children:e("board.pickPrompt.title")}),c.jsx("p",{className:"text-sm mb-4 text-[var(--color-text-muted)]",children:e("board.pickPrompt.body")}),c.jsx("div",{className:"flex flex-wrap gap-2",children:(V=k.data)==null?void 0:V.data.map(K=>c.jsx("button",{className:"nb-btn nb-btn-blue",onClick:()=>C(K.name),type:"button",children:K.name},K.name))})]})]});const Y=z.filter(K=>{if(l){const I=l.toLowerCase();if(!(K.title.toLowerCase().includes(I)||K.skills.some(G=>G.toLowerCase().includes(I))||K.labels.some(G=>G.toLowerCase().includes(I))))return!1}return!(f.size>0&&!K.skills.some(P=>f.has(P))||g.size>0&&!K.labels.some(P=>g.has(P)))}),D=(Q=k.data)==null?void 0:Q.data.find(K=>K.name===r),H=(D==null?void 0:D.pipelineStatus)==="running";return c.jsxs("div",{className:"flex flex-col gap-4 max-w-full flex-1 min-h-0",children:[c.jsxs("header",{className:"flex items-center justify-between flex-wrap gap-3 shrink-0",children:[c.jsxs("div",{children:[c.jsx("h1",{className:"font-[family-name:var(--font-heading)] text-4xl font-bold tracking-tight",children:e("board.title")}),c.jsx("p",{className:"text-[var(--color-text-muted)] text-sm mt-1",children:D?e("board.subtitle",{name:D.name,cards:D.cards.total,workers:D.workers.active}):e("common.loading")})]}),c.jsxs("div",{className:"flex items-center gap-3 flex-wrap",children:[c.jsx(O4,{current:r,onChange:C}),c.jsxs("button",{className:H?"nb-btn nb-btn-danger":"nb-btn nb-btn-primary",onClick:()=>H?_.mutate():S.mutate(),disabled:S.isPending||_.isPending,type:"button","aria-label":e(H?"board.action.stopAria":"board.action.startAria"),title:e(H?"board.action.stopAria":"board.action.startAria"),children:[S.isPending||_.isPending?c.jsx(Xe,{size:14,strokeWidth:3,className:"animate-spin"}):H?c.jsx($b,{size:14,strokeWidth:3}):c.jsx(Yu,{size:14,strokeWidth:3}),e(H?"board.action.stop":"board.action.start")]}),c.jsxs("button",{className:"nb-btn nb-btn-yellow",type:"button",onClick:async()=>{await y({title:e("board.action.reset.confirm.title"),body:e("board.action.reset.confirm.body"),confirm:e("board.action.reset.confirm.button"),danger:!0})&&M.mutate()},disabled:M.isPending,children:[M.isPending?c.jsx(Xe,{size:14,strokeWidth:3,className:"animate-spin"}):c.jsx(Pb,{size:14,strokeWidth:2.5}),e("board.action.reset")]}),c.jsxs("button",{className:"nb-btn nb-btn-mint",type:"button",onClick:()=>L(!0),disabled:R.isPending,children:[R.isPending?c.jsx(Xe,{size:14,strokeWidth:3,className:"animate-spin"}):c.jsx(pr,{size:14,strokeWidth:3}),e("board.action.newCard")]})]})]}),c.jsxs("div",{className:"flex items-center gap-3 flex-wrap shrink-0",children:[c.jsxs("div",{className:"relative flex-1 max-w-md",children:[c.jsx(ho,{size:14,className:"absolute left-3 top-1/2 -translate-y-1/2 text-[var(--color-text-subtle)]"}),c.jsx("input",{className:"nb-input pl-9 w-full",placeholder:e("board.search.placeholder"),value:l,onChange:K=>d(K.target.value),"aria-label":e("board.search.aria")})]}),c.jsx(Ck,{label:"skill",options:q,selected:f,onChange:h}),c.jsx(Ck,{label:"label",options:F,selected:g,onChange:m}),(l||f.size>0||g.size>0)&&c.jsxs("button",{className:"nb-btn",style:{padding:"4px 10px",fontSize:11},onClick:()=>{d(""),h(new Set),m(new Set)},type:"button","aria-label":e("board.filter.clearAria"),children:[c.jsx(Sn,{size:11,strokeWidth:3}),e("board.filter.clear")]}),c.jsxs("span",{className:"text-xs text-[var(--color-text-muted)] flex items-center gap-1 font-[family-name:var(--font-mono)]",children:[c.jsx(oL,{size:12}),Y.length," / ",z.length]})]}),v.isError&&c.jsxs("div",{className:"nb-card bg-[var(--color-crashed-bg)]",children:[c.jsx("p",{className:"font-semibold",children:e("board.error.loadCards")}),c.jsx("p",{className:"text-sm mt-1 text-[var(--color-text-muted)]",children:v.error instanceof Error?v.error.message:String(v.error)})]}),!v.isError&&c.jsx("div",{className:"grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-6 auto-rows-fr gap-3 flex-1 min-h-0",children:R4.map(K=>c.jsx(M4,{label:e(K.labelKey),bg:K.bg,cards:Y.filter(P4(K.state)),onCardClick:I=>o(I.seq),onDropCard:I=>$.mutate({seq:I,state:K.state})},K.state))}),a!==null&&c.jsx(D4,{project:r,seq:a,onClose:()=>o(null),onChanged:E}),T&&c.jsx(d4,{project:r,isPending:R.isPending,onCancel:()=>L(!1),onCreate:K=>R.mutate(K)})]})}function P4(e){return t=>e==="QA"?t.state==="QA"||t.state==="Review":e==="Done"?t.state==="Done"||t.state==="Canceled":t.state===e}function Ck({label:e,options:t,selected:n,onChange:r}){const a=Be(),[o,l]=j.useState(!1),d=j.useRef(null);j.useEffect(()=>{if(!o)return;const m=b=>{var k;(k=d.current)!=null&&k.contains(b.target)||l(!1)},y=b=>{b.key==="Escape"&&l(!1)};return window.addEventListener("click",m),window.addEventListener("keydown",y),()=>{window.removeEventListener("click",m),window.removeEventListener("keydown",y)}},[o]);const f=m=>{const y=new Set(n);y.has(m)?y.delete(m):y.add(m),r(y)},h=t.length===0,g=n.size;return c.jsxs("div",{ref:d,className:"relative",children:[c.jsxs("button",{type:"button",className:"nb-btn",style:{padding:"6px 12px",fontSize:12},onClick:()=>!h&&l(m=>!m),disabled:h,"aria-haspopup":"listbox","aria-expanded":o,"aria-label":a("board.filter.aria",{label:e}),children:[e,g>0&&c.jsx("span",{className:"ml-1 px-1.5 py-0.5 text-[10px] font-bold rounded-full bg-[var(--color-primary)] text-[var(--color-text)] border border-[var(--color-text)]",children:g}),c.jsx(Vu,{size:11,strokeWidth:3,className:["transition-transform",o?"rotate-180":""].join(" ")})]}),o&&c.jsxs("div",{role:"listbox",className:"absolute left-0 top-full mt-2 z-20 min-w-[200px] max-h-64 overflow-auto nb-card p-2",style:{padding:8},children:[t.map(m=>{const y=n.has(m);return c.jsxs("label",{className:["flex items-center gap-2 px-2 py-1.5 rounded cursor-pointer text-sm font-[family-name:var(--font-mono)]",y?"bg-[var(--color-accent-mint)]":"hover:bg-[var(--color-bg-cream)]"].join(" "),children:[c.jsx("input",{type:"checkbox",checked:y,onChange:()=>f(m),className:"flex-shrink-0"}),c.jsx("span",{className:"truncate",children:m})]},m)}),g>0&&c.jsx("button",{type:"button",className:"w-full mt-2 pt-2 border-t-2 border-dashed border-[var(--color-text)] text-xs font-bold text-[var(--color-crashed)] text-center",onClick:()=>r(new Set),children:a("board.filter.clearSelection")})]})]})}function B4(){return ft("/api/workers/all")}function $4(e){return ft(`/api/projects/${encodeURIComponent(e)}/workers`)}function U4(e,t){return ft(`/api/projects/${encodeURIComponent(e)}/workers/${t}`)}async function y2(e,t){const n=await fetch(e,{method:"POST",headers:t?{"Content-Type":"application/json"}:void 0,body:t?JSON.stringify(t):void 0});if(!n.ok)throw new Error(`${n.status}: ${await n.text()}`);return n.json().catch(()=>({}))}function Ak(e,t){return y2(`/api/projects/${encodeURIComponent(e)}/workers/${t}/kill`)}function F4(e,t,n){return y2(`/api/projects/${encodeURIComponent(e)}/workers/${t}/launch`,n?{seq:n}:void 0)}function dx({state:e}){const n={running:{bg:"var(--color-running-bg)",color:"var(--color-running)",label:"running"},starting:{bg:"var(--color-secondary)",color:"var(--color-text)",label:"starting",icon:c.jsx(Xe,{size:9,strokeWidth:3,className:"animate-spin"})},stuck:{bg:"var(--color-stuck-bg)",color:"var(--color-stuck)",label:"stuck"},crashed:{bg:"var(--color-crashed-bg)",color:"var(--color-crashed)",label:"crashed",icon:c.jsx(n3,{size:9,strokeWidth:2.5})},idle:{bg:"var(--color-idle-bg)",color:"var(--color-idle)",label:"idle"}}[e];return c.jsxs("span",{className:"nb-status inline-flex items-center gap-1",style:{background:n.bg,color:n.color},children:[n.icon,n.label]})}function fx(e){if(e==null||e<=0)return"—";const t=Math.floor(e/1e3),n=Math.floor(t/3600),r=Math.floor(t%3600/60),a=t%60;return n>0?`${n}h ${r}m`:r>0?`${r}m ${a}s`:`${a}s`}function q4(e){if(e==null||e<=0)return"text-[var(--color-text-muted)]";const t=e/6e4;return t<10?"text-[var(--color-running)]":t<60?"text-[var(--color-stuck)]":"text-[var(--color-crashed)]"}function hx(e){const t=Date.now()-new Date(e).getTime();return t<6e4?`${Math.floor(t/1e3)}s 前`:t<36e5?`${Math.floor(t/6e4)}m 前`:`${Math.floor(t/36e5)}h 前`}function H4({alerts:e,selected:t,onSelect:n}){const r=Be();return e.length===0?c.jsxs("div",{className:"nb-card bg-[var(--color-running-bg)] flex items-center gap-3",children:[c.jsx(Eu,{size:18,strokeWidth:2.5,className:"text-[var(--color-running)]"}),c.jsx("span",{className:"text-sm font-bold text-[var(--color-running)]",children:r("workers.alerts.allHealthy")})]}):c.jsxs("section",{children:[c.jsxs("h2",{className:"font-[family-name:var(--font-heading)] text-sm font-bold uppercase tracking-wider mb-2 flex items-center gap-2 text-[var(--color-crashed)]",children:[c.jsx(h3,{size:14,strokeWidth:2.5}),"Alerts (",e.length,")"]}),c.jsx("div",{className:"flex flex-col gap-2",children:e.map(a=>{const o=(t==null?void 0:t.project)===a.project&&(t==null?void 0:t.slot)===a.slot;return c.jsxs("button",{type:"button",onClick:()=>n(a.project,a.slot),className:["nb-card p-3 text-left",a.state==="crashed"?"bg-[var(--color-crashed-bg)]":"bg-[var(--color-stuck-bg)]",o?"ring-4 ring-[var(--color-text)]":""].join(" "),children:[c.jsxs("div",{className:"flex items-center gap-2 text-sm",children:[c.jsx(dx,{state:a.state}),c.jsxs("span",{className:"font-[family-name:var(--font-mono)] font-bold",children:[a.project,"/worker-",a.slot]}),a.card&&c.jsxs("span",{className:"truncate",children:["#",a.card.seq," ",a.card.title]}),c.jsxs("span",{className:"ml-auto text-xs text-[var(--color-text-muted)] font-[family-name:var(--font-mono)] flex items-center gap-1",children:[c.jsx(HN,{size:10,strokeWidth:2.5}),fx(a.runtimeMs)]})]}),a.markerUpdatedAt&&c.jsx("div",{className:"text-xs text-[var(--color-text-muted)] mt-1 font-[family-name:var(--font-mono)]",children:a.state==="crashed"?r("workers.alerts.pidDead"):r("workers.alerts.markerStale",{ago:hx(a.markerUpdatedAt)})})]},`${a.project}-${a.slot}`)})})]})}function K4({active:e,selected:t,onSelect:n}){const r=Be();return e.length===0?c.jsx("div",{className:"nb-card bg-[var(--color-bg-cream)]",children:c.jsx("p",{className:"text-sm text-[var(--color-text-muted)] italic",children:r("workers.active.empty")})}):c.jsxs("section",{children:[c.jsxs("h2",{className:"font-[family-name:var(--font-heading)] text-sm font-bold uppercase tracking-wider mb-2 flex items-center gap-2",children:[c.jsx($h,{size:14,strokeWidth:2.5}),"Active (",e.length,")"]}),c.jsx("div",{className:"grid grid-cols-1 md:grid-cols-2 gap-3",children:e.map(a=>{const o=(t==null?void 0:t.project)===a.project&&(t==null?void 0:t.slot)===a.slot;return c.jsxs("button",{type:"button",onClick:()=>n(a.project,a.slot),className:["nb-card p-3 text-left",a.state==="starting"?"bg-[var(--color-secondary)]":"bg-[var(--color-running-bg)]",o?"ring-4 ring-[var(--color-text)]":""].join(" "),children:[c.jsxs("div",{className:"flex items-center gap-2 mb-1",children:[c.jsx(dx,{state:a.state}),c.jsxs("span",{className:"font-[family-name:var(--font-mono)] font-bold text-sm flex-1 truncate",children:[a.project,"/worker-",a.slot]}),c.jsx("span",{className:`text-xs font-[family-name:var(--font-mono)] ${q4(a.runtimeMs)}`,children:fx(a.runtimeMs)})]}),a.card&&c.jsxs("div",{className:"text-sm font-semibold mb-1 truncate",children:["#",a.card.seq," · ",a.card.title]}),c.jsxs("div",{className:"text-xs text-[var(--color-text-muted)] font-[family-name:var(--font-mono)] flex items-center gap-2 mb-1",children:[a.stage&&c.jsxs("span",{children:["stage: ",a.stage]}),a.markerUpdatedAt&&c.jsxs("span",{className:"ml-auto",children:["marker ",hx(a.markerUpdatedAt)]})]}),a.lastLogLine&&c.jsxs("div",{className:"text-[11px] font-[family-name:var(--font-mono)] text-[var(--color-text-muted)] bg-[var(--color-bg)] border-2 border-[var(--color-text)] rounded px-2 py-1 mt-2 truncate",children:[c.jsx(e_,{size:9,strokeWidth:2.5,className:"inline-block mr-1 align-text-bottom"}),a.lastLogLine.msg]})]},`${a.project}-${a.slot}`)})})]})}function G4({capacity:e,selected:t,onSelect:n}){const r=Be();return e.length===0?null:c.jsxs("section",{className:"flex flex-col min-h-0 flex-1",children:[c.jsx("h2",{className:"font-[family-name:var(--font-heading)] text-sm font-bold uppercase tracking-wider mb-2 shrink-0",children:"Capacity"}),c.jsx("div",{className:"nb-card p-0 overflow-y-auto min-h-0 flex-1",children:c.jsxs("table",{className:"w-full text-sm",children:[c.jsx("thead",{children:c.jsxs("tr",{className:"bg-[var(--color-bg-cream)] border-b-2 border-[var(--color-text)]",children:[c.jsx("th",{className:"px-3 py-2 text-left font-bold text-xs uppercase tracking-wider",children:r("workers.capacity.col.project")}),c.jsx("th",{className:"px-3 py-2 text-left font-bold text-xs uppercase tracking-wider",children:r("workers.capacity.col.usage")}),c.jsx("th",{className:"px-3 py-2 text-right font-bold text-xs uppercase tracking-wider",children:"running"}),c.jsx("th",{className:"px-3 py-2 text-right font-bold text-xs uppercase tracking-wider",children:r("workers.capacity.col.other")}),c.jsx("th",{className:"px-3 py-2"})]})}),c.jsx("tbody",{children:e.map(a=>{const o=a.running+a.starting+a.stuck+a.crashed,l=(t==null?void 0:t.project)===a.project;return c.jsxs("tr",{onClick:()=>n(a.project),className:["border-b border-dashed border-[var(--color-border-light)] last:border-0 cursor-pointer hover:bg-[var(--color-accent-yellow)]",l?"bg-[var(--color-accent-yellow)]":""].join(" "),children:[c.jsx("td",{className:"px-3 py-2 font-[family-name:var(--font-mono)] font-bold",children:a.project}),c.jsx("td",{className:"px-3 py-2",children:c.jsx(V4,{total:a.total,cap:a})}),c.jsxs("td",{className:"px-3 py-2 text-right font-[family-name:var(--font-mono)]",children:[c.jsx("span",{className:"text-[var(--color-running)] font-bold",children:a.running}),c.jsxs("span",{className:"text-[var(--color-text-muted)]",children:["/",a.total]})]}),c.jsxs("td",{className:"px-3 py-2 text-right text-xs font-[family-name:var(--font-mono)] text-[var(--color-text-muted)]",children:[a.starting>0&&c.jsxs("span",{className:"mr-2",children:["starting ",a.starting]}),a.stuck>0&&c.jsxs("span",{className:"text-[var(--color-stuck)] font-bold mr-2",children:["stuck ",a.stuck]}),a.crashed>0&&c.jsxs("span",{className:"text-[var(--color-crashed)] font-bold mr-2",children:["crashed ",a.crashed]}),o===0&&c.jsx("span",{children:"idle"})]}),c.jsx("td",{className:"px-3 py-2 text-right",children:c.jsx("span",{className:"text-xs text-[var(--color-text-muted)]",children:r("workers.capacity.detailHint")})})]},a.project)})})]})})]})}function V4({total:e,cap:t}){const n=[];for(let r=0;r<t.crashed;r++)n.push("crashed");for(let r=0;r<t.stuck;r++)n.push("stuck");for(let r=0;r<t.starting;r++)n.push("starting");for(let r=0;r<t.running;r++)n.push("running");for(let r=0;r<t.idle;r++)n.push("idle");return c.jsxs("div",{className:"flex gap-1 items-center",children:[n.map((r,a)=>c.jsx("span",{className:"inline-block w-3 h-3 rounded-full border-2 border-[var(--color-text)]",style:{background:Y4(r)},title:r},a)),c.jsxs("span",{className:"text-xs text-[var(--color-text-muted)] ml-2 font-[family-name:var(--font-mono)]",children:[e," slot",e!==1?"s":""]})]})}function Y4(e){switch(e){case"running":return"var(--color-running-bg)";case"starting":return"var(--color-secondary)";case"stuck":return"var(--color-stuck-bg)";case"crashed":return"var(--color-crashed-bg)";default:return"var(--color-idle-bg)"}}function Q4({project:e,initialSlot:t,onChange:n}){var h;const r=Be(),a=Ye({queryKey:["workers",e],queryFn:()=>$4(e),refetchInterval:3e3}),o=((h=a.data)==null?void 0:h.data)??[],[l,d]=j.useState(null);j.useEffect(()=>{if(o.length===0){d(null);return}const g=o[0].slot;d(m=>m!=null&&o.some(y=>y.slot===m)?m:t!=null&&o.some(y=>y.slot===t)?t:g)},[e,t,o.length]);const f=o.find(g=>g.slot===l)??null;return c.jsxs("div",{className:"flex flex-col h-full",children:[c.jsxs("div",{className:"px-4 py-3 border-b-2 border-[var(--color-text)] bg-[var(--color-bg-cream)]",children:[c.jsxs("div",{className:"flex items-center justify-between mb-2",children:[c.jsx("span",{className:"font-[family-name:var(--font-mono)] font-bold truncate",children:e}),c.jsx(vs,{to:`/board?project=${encodeURIComponent(e)}`,className:"text-xs underline text-[var(--color-text-muted)] hover:text-[var(--color-text)]",children:r("workers.panel.boardLink")})]}),a.isLoading&&o.length===0?c.jsx("p",{className:"text-xs text-[var(--color-text-muted)] italic",children:r("workers.panel.loading")}):o.length===0?c.jsx("p",{className:"text-xs text-[var(--color-text-muted)] italic",children:r("workers.panel.empty.slots")}):c.jsx("div",{className:"flex flex-wrap gap-2",children:o.map(g=>c.jsx(W4,{worker:g,active:g.slot===l,onClick:()=>d(g.slot)},g.slot))})]}),f?c.jsx(X4,{project:e,worker:f,onChange:n}):c.jsx("div",{className:"flex-1 flex items-center justify-center p-6 text-center",children:c.jsx("p",{className:"text-sm text-[var(--color-text-muted)]",children:o.length===0?r("workers.panel.empty.noWorker"):r("workers.panel.empty.pickOne")})})]})}function W4({worker:e,active:t,onClick:n}){const r=Be();return c.jsxs("button",{type:"button",onClick:n,className:["nb-card p-2 text-left min-w-[130px] transition-transform",t?"ring-4 ring-[var(--color-text)]":"opacity-80 hover:opacity-100"].join(" "),children:[c.jsxs("div",{className:"flex items-center gap-2 mb-1",children:[c.jsx(dx,{state:e.state}),c.jsxs("span",{className:"font-[family-name:var(--font-mono)] font-bold text-xs",children:["worker-",e.slot]})]}),e.card?c.jsxs("div",{className:"text-[11px] truncate font-[family-name:var(--font-mono)]",children:["#",e.card.seq," ",e.card.title]}):c.jsx("div",{className:"text-[11px] text-[var(--color-text-muted)] italic",children:r("workers.panel.idle.short")})]})}function X4({project:e,worker:t,onChange:n}){var y,b;const r=Be(),{confirm:a,alert:o}=un(),l=t.state==="crashed"||t.state==="stuck",d=Ye({queryKey:["worker-detail",e,t.slot],queryFn:()=>U4(e,t.slot),refetchInterval:3e3}),f=((y=d.data)==null?void 0:y.recentOutput)??[],h=((b=d.data)==null?void 0:b.recentLogs)??[],g=j.useRef(null),m=j.useRef(!0);return j.useEffect(()=>{const k=g.current;k&&m.current&&(k.scrollTop=k.scrollHeight)},[f]),c.jsxs(c.Fragment,{children:[c.jsxs("div",{className:"flex-1 overflow-auto p-4 flex flex-col gap-4",children:[t.card?c.jsxs("div",{children:[c.jsx("div",{className:"text-xs font-bold uppercase tracking-wider text-[var(--color-text-muted)] mb-1",children:r("workers.panel.section.currentCard")}),c.jsxs("div",{className:"text-sm font-semibold break-words",children:["#",t.card.seq," · ",t.card.title]})]}):c.jsx("div",{className:"text-sm text-[var(--color-text-muted)] italic",children:r("workers.panel.idle.full")}),c.jsxs("dl",{className:"grid grid-cols-[100px_1fr] gap-y-2 text-sm",children:[c.jsx("dt",{className:"font-bold",children:"Stage"}),c.jsx("dd",{className:"font-[family-name:var(--font-mono)]",children:t.stage??"—"}),c.jsx("dt",{className:"font-bold",children:"PID"}),c.jsx("dd",{className:"font-[family-name:var(--font-mono)]",children:t.pid??"—"}),c.jsx("dt",{className:"font-bold",children:"Runtime"}),c.jsx("dd",{className:"font-[family-name:var(--font-mono)]",children:fx(t.runtimeMs)}),c.jsx("dt",{className:"font-bold",children:"Started"}),c.jsx("dd",{className:"font-[family-name:var(--font-mono)] text-xs",children:t.startedAt?new Date(t.startedAt).toLocaleString():"—"}),c.jsx("dt",{className:"font-bold",children:"Marker"}),c.jsx("dd",{className:"font-[family-name:var(--font-mono)] text-xs",children:t.markerUpdatedAt?hx(t.markerUpdatedAt):"—"})]}),c.jsxs("div",{children:[c.jsxs("div",{className:"text-xs font-bold uppercase tracking-wider text-[var(--color-text-muted)] mb-1 flex items-center gap-1",children:[c.jsx(e_,{size:10,strokeWidth:2.5}),r("workers.panel.section.claudeOutput",{n:f.length})]}),d.isLoading&&f.length===0?c.jsx("p",{className:"text-xs text-[var(--color-text-muted)] italic",children:r("workers.panel.output.loading")}):f.length===0?c.jsx("p",{className:"text-xs text-[var(--color-text-muted)] italic",children:r("workers.panel.output.empty")}):c.jsx("pre",{ref:g,onScroll:k=>{const v=k.currentTarget;m.current=v.scrollHeight-v.scrollTop-v.clientHeight<24},className:"text-xs font-[family-name:var(--font-mono)] bg-[var(--color-bg-cream)] border-2 border-[var(--color-text)] rounded p-2 max-h-80 overflow-auto whitespace-pre-wrap break-words",children:f.map(k=>`${k.ts?`${k.ts} [${k.kind}] `:`[${k.kind}] `}${k.text}`).join(`
|
|
605
605
|
`)})]}),h.length>0&&c.jsxs("div",{children:[c.jsx("div",{className:"text-xs font-bold uppercase tracking-wider text-[var(--color-text-muted)] mb-1 opacity-60",children:r("workers.panel.section.heartbeat",{n:h.length})}),c.jsx("pre",{className:"text-xs font-[family-name:var(--font-mono)] bg-[var(--color-bg-cream)] border-2 border-[var(--color-text)] rounded p-2 max-h-40 overflow-auto whitespace-pre-wrap break-words opacity-80",children:h.map(k=>`${k.ts??""} [${k.level}] ${k.msg}`).join(`
|