specrails-desktop 2.59.3 → 2.60.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (132) hide show
  1. package/client/dist/assets/{ActivityFeedPage-BGEayjTY.js → ActivityFeedPage-3J7fR8yB.js} +1 -1
  2. package/client/dist/assets/{AgentBrowserCapture-Qvg4y5Tr.js → AgentBrowserCapture-D4a3wYM1.js} +1 -1
  3. package/client/dist/assets/{AgentModeAnalyticsPane-CR7aFeLJ.js → AgentModeAnalyticsPane-Dps30tk9.js} +2 -2
  4. package/client/dist/assets/{AgentModeCodePane-gAd88Gng.js → AgentModeCodePane-CvLimey8.js} +2 -2
  5. package/client/dist/assets/{AgentModeJobsPane-EjCDuTow.js → AgentModeJobsPane-25tQlLpF.js} +1 -1
  6. package/client/dist/assets/{AgentsPage-CRHHcp1V.js → AgentsPage-CUDp_sfw.js} +2 -2
  7. package/client/dist/assets/{AnalyticsPage-a0b1fNEl.js → AnalyticsPage-DXWMGn8b.js} +1 -1
  8. package/client/dist/assets/{CodePage-BmV1m7l3.js → CodePage-D981zRHy.js} +1 -1
  9. package/client/dist/assets/{DesktopAnalyticsPage-B87WmXOQ.js → DesktopAnalyticsPage-BkFBq0E6.js} +1 -1
  10. package/client/dist/assets/{DocsDialog-Co0O672q.js → DocsDialog-BL7uSbIJ.js} +1 -1
  11. package/client/dist/assets/{DocsPage-DxGI6A2T.js → DocsPage-CsDLbmZX.js} +1 -1
  12. package/client/dist/assets/{ExportDropdown-1Ce031vB.js → ExportDropdown-B4Olg1Fk.js} +1 -1
  13. package/client/dist/assets/{InteractiveJobComposer-DkqR77pO.js → InteractiveJobComposer-Z6fl4791.js} +1 -1
  14. package/client/dist/assets/{JobDetailModal-DVLDVgzz.js → JobDetailModal-DS_Owxs6.js} +1 -1
  15. package/client/dist/assets/{JobDetailPage-RcP9N-D-.js → JobDetailPage-1TUQ9vlE.js} +1 -1
  16. package/client/dist/assets/{JobsPage-R9M4xQnp.js → JobsPage-BSrl8P7u.js} +1 -1
  17. package/client/dist/assets/LoopBuilderPage-Dh5uk2Qy.js +1 -0
  18. package/client/dist/assets/{LoopPreviewModal-DA2JeKWX.js → LoopPreviewModal-CH1r-KhU.js} +1 -1
  19. package/client/dist/assets/{LoopWindowSurface-BkkeD0hx.js → LoopWindowSurface-CiZdI6aw.js} +1 -1
  20. package/client/dist/assets/{LoopsPage-BHv--iI7.js → LoopsPage-BwFujdGi.js} +1 -1
  21. package/client/dist/assets/{MinimizedChatsContext-Bc9xHByW.js → MinimizedChatsContext-BD2bsRBe.js} +1 -1
  22. package/client/dist/assets/{PluginsPage-BEy62gxK.js → PluginsPage-B8f49Mvn.js} +1 -1
  23. package/client/dist/assets/{ProjectSettingsDialog-DDQ_f94T.js → ProjectSettingsDialog-D7q-O6h3.js} +1 -1
  24. package/client/dist/assets/{RepositoryDeliveries-DIWDFLRM.js → RepositoryDeliveries-NNorcGzT.js} +1 -1
  25. package/client/dist/assets/{RepositoryScopeSelector-D3PlHIM-.js → RepositoryScopeSelector-D-jb4bI_.js} +1 -1
  26. package/client/dist/assets/{ReviewPacketPage-BXdPwmdE.js → ReviewPacketPage-DpZSzF-Q.js} +1 -1
  27. package/client/dist/assets/{TemplatePreviewModal-C7-G6lvI.js → TemplatePreviewModal-5CZdAZ0G.js} +1 -1
  28. package/client/dist/assets/{TicketDetailModalContext-gGUv7gsQ.js → TicketDetailModalContext-BHmtj1As.js} +1 -1
  29. package/client/dist/assets/{Trans-Br_OIUKP.js → Trans-wmTUDVyC.js} +1 -1
  30. package/client/dist/assets/{agentRuntime-TXPQowKJ.js → agentRuntime-7Ydcvr6P.js} +1 -1
  31. package/client/dist/assets/{agentRuntime-Bpx3yWHK.js → agentRuntime-BHVw9orA.js} +1 -1
  32. package/client/dist/assets/{agentRuntime-15Pkk6we.js → agentRuntime-DCPDaQcV.js} +1 -1
  33. package/client/dist/assets/{agentRuntime-C78n13To.js → agentRuntime-DKTw4Ajg.js} +1 -1
  34. package/client/dist/assets/{agentRuntime-CCI7XF4c.js → agentRuntime-DVhij_i_.js} +1 -1
  35. package/client/dist/assets/{agentRuntime-Ddqvp2bP.js → agentRuntime-Doss-T8o.js} +1 -1
  36. package/client/dist/assets/{agentRuntime-CKDHe2-a.js → agentRuntime-eZSMUlkM.js} +1 -1
  37. package/client/dist/assets/{agentRuntime-hqZRy08E.js → agentRuntime-qSSU7fQk.js} +1 -1
  38. package/client/dist/assets/agents-B6ZsnARo.js +1 -0
  39. package/client/dist/assets/agents-BORdhe0K.js +1 -0
  40. package/client/dist/assets/agents-C6aq9Oqs.js +1 -0
  41. package/client/dist/assets/agents-Cbsc4bcX.js +1 -0
  42. package/client/dist/assets/agents-D0uYR6hq.js +1 -0
  43. package/client/dist/assets/agents-Doe1sHY5.js +1 -0
  44. package/client/dist/assets/agents-DyNi_I9m.js +1 -0
  45. package/client/dist/assets/agents-StKxiTg0.js +1 -0
  46. package/client/dist/assets/agentstudio-7cYCXn-L.js +1 -0
  47. package/client/dist/assets/{agentstudio-QdAJIDef.js → agentstudio-BHWQh8G3.js} +1 -1
  48. package/client/dist/assets/agentstudio-BjnWHyRs.js +1 -0
  49. package/client/dist/assets/{agentstudio-fLXpRGIi.js → agentstudio-BkV8vcK4.js} +1 -1
  50. package/client/dist/assets/{agentstudio-BWAKeGgB.js → agentstudio-BzugqB_N.js} +1 -1
  51. package/client/dist/assets/{agentstudio-Cja8Sjcp.js → agentstudio-CWbp7KvH.js} +1 -1
  52. package/client/dist/assets/agentstudio-DG6plf5o.js +1 -0
  53. package/client/dist/assets/agentstudio-DkZVF-Cc.js +1 -0
  54. package/client/dist/assets/{formatDistanceToNow-Q7QPRFV4.js → formatDistanceToNow-Dax4zqPF.js} +1 -1
  55. package/client/dist/assets/{getTimezoneOffsetInMilliseconds-Bq0CXBaJ.js → getTimezoneOffsetInMilliseconds-dpIo42JZ.js} +1 -1
  56. package/client/dist/assets/{index-DVkWHOR3.js → index-g8S62tpS.js} +7 -7
  57. package/client/dist/assets/{jira-api-C2Tzc362.js → jira-api-CLrIvXFm.js} +1 -1
  58. package/client/dist/assets/{project-repositories-DZKmieH3.js → project-repositories-BkyT8AjU.js} +1 -1
  59. package/client/dist/assets/{spending-EXaboRU0.js → spending-Oov7p52A.js} +1 -1
  60. package/client/dist/assets/{useDesktop-ChSmmJfc.js → useDesktop-DpiS8Uov.js} +1 -1
  61. package/client/dist/assets/{useRuntimeRuns-w9-5OzZl.js → useRuntimeRuns-DBm1mul0.js} +1 -1
  62. package/client/dist/assets/{useSharedWebSocket-g0nTHfTT.js → useSharedWebSocket-BZxKaVNT.js} +2 -2
  63. package/client/dist/index.html +17 -17
  64. package/docs/getting-started.md +2 -2
  65. package/docs/guide/de/agents/1-meet-the-agents.md +1 -1
  66. package/docs/guide/de/agents/2-profiles-and-the-balanced-default.md +1 -1
  67. package/docs/guide/de/agents/3-customizing-models-per-agent.md +1 -1
  68. package/docs/guide/de/agents/4-custom-agents-catalog.md +3 -3
  69. package/docs/guide/en/agents/1-meet-the-agents.md +1 -1
  70. package/docs/guide/en/agents/2-profiles-and-the-balanced-default.md +1 -1
  71. package/docs/guide/en/agents/3-customizing-models-per-agent.md +1 -1
  72. package/docs/guide/en/agents/4-custom-agents-catalog.md +3 -3
  73. package/docs/guide/es/agents/1-meet-the-agents.md +1 -1
  74. package/docs/guide/es/agents/2-profiles-and-the-balanced-default.md +1 -1
  75. package/docs/guide/es/agents/3-customizing-models-per-agent.md +1 -1
  76. package/docs/guide/es/agents/4-custom-agents-catalog.md +3 -3
  77. package/docs/guide/fr/agents/1-meet-the-agents.md +1 -1
  78. package/docs/guide/fr/agents/2-profiles-and-the-balanced-default.md +1 -1
  79. package/docs/guide/fr/agents/3-customizing-models-per-agent.md +1 -1
  80. package/docs/guide/fr/agents/4-custom-agents-catalog.md +3 -3
  81. package/docs/guide/it/agents/1-meet-the-agents.md +1 -1
  82. package/docs/guide/it/agents/2-profiles-and-the-balanced-default.md +1 -1
  83. package/docs/guide/it/agents/3-customizing-models-per-agent.md +1 -1
  84. package/docs/guide/it/agents/4-custom-agents-catalog.md +3 -3
  85. package/docs/guide/ja/agents/1-meet-the-agents.md +1 -1
  86. package/docs/guide/ja/agents/2-profiles-and-the-balanced-default.md +1 -1
  87. package/docs/guide/ja/agents/3-customizing-models-per-agent.md +1 -1
  88. package/docs/guide/ja/agents/4-custom-agents-catalog.md +3 -3
  89. package/docs/guide/pt/agents/1-meet-the-agents.md +1 -1
  90. package/docs/guide/pt/agents/2-profiles-and-the-balanced-default.md +1 -1
  91. package/docs/guide/pt/agents/3-customizing-models-per-agent.md +1 -1
  92. package/docs/guide/pt/agents/4-custom-agents-catalog.md +3 -3
  93. package/docs/guide/zh/agents/1-meet-the-agents.md +1 -1
  94. package/docs/guide/zh/agents/2-profiles-and-the-balanced-default.md +1 -1
  95. package/docs/guide/zh/agents/3-customizing-models-per-agent.md +1 -1
  96. package/docs/guide/zh/agents/4-custom-agents-catalog.md +3 -3
  97. package/docs/internals/adding-a-provider.md +7 -6
  98. package/docs/internals/core-runtime-updates.md +19 -0
  99. package/docs/internals/profiles.md +17 -10
  100. package/docs/internals/review-packet.md +1 -1
  101. package/docs/internals/source-map.md +1 -1
  102. package/docs/running-pipelines.md +2 -2
  103. package/package.json +1 -1
  104. package/server/dist/core-compat.js +7 -3
  105. package/server/dist/mcp/guide.js +4 -3
  106. package/server/dist/modules/agent-runtime/runtime/agent-runtime-bridge.js +7 -3
  107. package/server/dist/modules/agent-runtime/runtime/agent-runtime-settings.js +24 -1
  108. package/server/dist/modules/agents/runtime/profiles-router.js +74 -36
  109. package/server/dist/modules/execution/runtime/queue-manager.js +7 -9
  110. package/server/dist/modules/loops/runtime/loop-agents.js +2 -5
  111. package/server/dist/modules/loops/runtime/loop-command-catalog.js +5 -5
  112. package/server/dist/modules/loops/runtime/loop-definition.js +1 -1
  113. package/server/dist/modules/loops/runtime/loop-executors.js +0 -2
  114. package/server/dist/modules/loops/runtime/loop-implement-recipe.js +5 -4
  115. package/server/dist/modules/loops/runtime/loops-router.js +3 -1
  116. package/server/dist/providers/gemini-agent-ack.js +13 -10
  117. package/server/dist/setup-manager.js +28 -43
  118. package/server/dist/workspace-manager.js +13 -71
  119. package/client/dist/assets/LoopBuilderPage-C4S-rkWp.js +0 -1
  120. package/client/dist/assets/agents-CA5eT1d0.js +0 -1
  121. package/client/dist/assets/agents-CAgy-5uS.js +0 -1
  122. package/client/dist/assets/agents-CNm6Qzlv.js +0 -1
  123. package/client/dist/assets/agents-CTwbx-fb.js +0 -1
  124. package/client/dist/assets/agents-DEGV1Vao.js +0 -1
  125. package/client/dist/assets/agents-HsDF1aQU.js +0 -1
  126. package/client/dist/assets/agents-IQjdA-z9.js +0 -1
  127. package/client/dist/assets/agents-RkGoteXh.js +0 -1
  128. package/client/dist/assets/agentstudio-B2CTtQgZ.js +0 -1
  129. package/client/dist/assets/agentstudio-DtfPcr99.js +0 -1
  130. package/client/dist/assets/agentstudio-X70BKf6u.js +0 -1
  131. package/client/dist/assets/agentstudio-qXKqVnWS.js +0 -1
  132. package/server/dist/modules/loops/runtime/loop-agent-defaults.json +0 -6
@@ -186,7 +186,6 @@ exports.CHECKPOINTS = [
186
186
  { key: 'agent_selection', name: 'Agent selection' },
187
187
  { key: 'codebase_analysis', name: 'Codebase analysis' },
188
188
  { key: 'vpc_discovery', name: 'VPC discovery' },
189
- { key: 'agent_generation', name: 'Agent generation' },
190
189
  { key: 'persona_synthesis', name: 'Persona synthesis' },
191
190
  { key: 'command_generation', name: 'Command generation' },
192
191
  ];
@@ -204,10 +203,7 @@ function checkFilesystem(projectPath, provider = 'claude') {
204
203
  (0, fs_1.existsSync)((0, path_1.join)(projectPath, '.specrails-version'));
205
204
  const hasSetupTemplates = (0, fs_1.existsSync)((0, path_1.join)(projectPath, '.specrails', 'setup-templates')) ||
206
205
  (0, fs_1.existsSync)((0, path_1.join)(projectPath, dir, 'setup-templates'));
207
- const hasRules = (0, fs_1.existsSync)((0, path_1.join)(projectPath, dir, 'rules')) &&
208
- hasFiles((0, path_1.join)(projectPath, dir, 'rules'), /\.md$/);
209
206
  const hasPersonas = artifactState.hasPersonas;
210
- const hasAgents = artifactState.hasAgents;
211
207
  const hasCommands = artifactState.hasCommands;
212
208
  const instructionCandidates = [(0, path_1.join)(projectPath, adapter.instructionsFilename)];
213
209
  // Older Core releases sometimes placed a top-level instructions filename
@@ -227,22 +223,15 @@ function checkFilesystem(projectPath, provider = 'claude') {
227
223
  base_install: hasBaseInstall,
228
224
  // Back-compat filesystem signals from older cores are translated to the
229
225
  // current integration-contract checkpoint keys.
230
- agent_selection: hasInstallConfig || hasAgentConfig || hasBacklogConfig || hasAgents || hasCommands,
226
+ agent_selection: hasInstallConfig || hasAgentConfig || hasBacklogConfig || hasCommands,
231
227
  codebase_analysis: hasBaseInstall && (hasInstructions || hasSetupTemplates),
232
228
  vpc_discovery: hasPersonas,
233
229
  persona_synthesis: hasPersonas,
234
- agent_generation: hasAgents,
235
- command_generation: hasCommands || (hasAgents && hasRules),
230
+ // Role agents are runtime-defined by specrails-core; only the workflow
231
+ // commands (and provider skills) prove a complete installation.
232
+ command_generation: hasCommands,
236
233
  };
237
234
  }
238
- function hasFiles(dir, pattern) {
239
- try {
240
- return (0, fs_1.readdirSync)(dir).some((f) => pattern.test(f));
241
- }
242
- catch {
243
- return false;
244
- }
245
- }
246
235
  // ─── Enrich.md content resolver (shared by start + resume enrich paths) ─────
247
236
  /**
248
237
  * Reads the enrich command's body from the project's specrails dir, falling
@@ -286,9 +275,6 @@ function detectCheckpointFromText(text) {
286
275
  if (/phase\s*3|configuration|agent\s*selection|backlog\s*provider/i.test(text)) {
287
276
  hits.push({ key: 'agent_selection', detail: 'Configuring agents...' });
288
277
  }
289
- if (/generating\s*all\s*files|writing.*agent|sr-architect|sr-developer|sr-reviewer/i.test(text)) {
290
- hits.push({ key: 'agent_generation', detail: 'Generating agents...' });
291
- }
292
278
  if (/command\s*selection|installing.*commands|\.claude\/commands\/(sr|specrails)/i.test(text)) {
293
279
  hits.push({ key: 'command_generation', detail: 'Configuring commands...' });
294
280
  }
@@ -301,7 +287,7 @@ function detectCheckpointFromText(text) {
301
287
  hits.push({ key: 'config_written' });
302
288
  }
303
289
  if (/installing\s*specrails|phase\s*2\s*&\s*3|placing\s*agents/i.test(text)) {
304
- hits.push({ key: 'agent_generation', detail: 'Installing specrails artefacts...' });
290
+ hits.push({ key: 'command_generation', detail: 'Installing specrails artefacts...' });
305
291
  }
306
292
  if (/writing\s*manifest|wrote\s+.*specrails-manifest/i.test(text)) {
307
293
  hits.push({ key: 'command_generation' });
@@ -315,16 +301,8 @@ function detectCheckpointFromText(text) {
315
301
  if (text.includes('/agents/personas/') && text.includes('.md')) {
316
302
  hits.push({ key: 'persona_synthesis', detail: 'Writing personas...' });
317
303
  }
318
- // Claude path: .claude/agents/sr-<name>.md
319
- if (/\/agents\/sr-[^/]+\.md/.test(text)) {
320
- hits.push({ key: 'agent_generation', detail: 'Writing agents...' });
321
- }
322
- // Provider-native rail skills. Kimi's upstream discovery contract scans only
323
- // direct children of `.kimi-code/skills`, so its roles are top-level
324
- // `.kimi-code/skills/sr-*/SKILL.md` entries. Codex may also use `rails/`.
325
- if (/\.(?:codex|kimi-code)\/skills\/(?:rails\/)?sr-[^/]+\/SKILL\.md/.test(text)) {
326
- hits.push({ key: 'agent_generation', detail: 'Writing agent skills...' });
327
- }
304
+ // Role agents (`sr-*`) are no longer installed files: Core defines them in
305
+ // its runtime, so role paths carry no checkpoint signal.
328
306
  if ((text.includes('/commands/sr/') || text.includes('/commands/specrails/')) && text.includes('.md')) {
329
307
  hits.push({ key: 'command_generation', detail: 'Writing commands...' });
330
308
  }
@@ -423,10 +401,11 @@ function computeSummary(projectPath, tier, provider = 'claude') {
423
401
  if (provider === 'codex' || provider === 'kimi') {
424
402
  // Codex/Kimi layout: every artefact ships as a SKILL under the provider's
425
403
  // `skills/` root.
426
- // - agents = rail personas (`skills/rails/sr-*/SKILL.md`) + orchestrator
427
- // skills at the root with an `sr-` prefix. Kimi roles MUST be
428
- // direct children (`skills/sr-*/SKILL.md`) because upstream
429
- // Kimi discovery is intentionally one level deep.
404
+ // - agents = custom roles only: codex `skills/rails/custom-*/SKILL.md`,
405
+ // kimi direct children `skills/custom-*/SKILL.md` (upstream
406
+ // Kimi discovery is intentionally one level deep). Baseline
407
+ // `sr-*` roles are runtime-defined and never counted; stale
408
+ // `sr-*` skills from older Cores are ignored.
430
409
  // - opsxCommands = `skills/openspec-*/SKILL.md`
431
410
  // - specrailsCommands = everything else under `skills/` (ported claude
432
411
  // slash commands like propose-spec, explore-spec, retry, doctor,
@@ -444,7 +423,7 @@ function computeSummary(projectPath, tier, provider = 'claude') {
444
423
  const personasDir = (0, path_1.join)(railsDir, entry);
445
424
  personas = (0, fs_1.readdirSync)(personasDir).filter((persona) => (0, fs_1.existsSync)((0, path_1.join)(personasDir, persona, 'SKILL.md'))).length;
446
425
  }
447
- else if ((0, fs_1.existsSync)((0, path_1.join)(railsDir, entry, 'SKILL.md'))) {
426
+ else if (/^custom-/.test(entry) && (0, fs_1.existsSync)((0, path_1.join)(railsDir, entry, 'SKILL.md'))) {
448
427
  agents++;
449
428
  }
450
429
  }
@@ -456,6 +435,8 @@ function computeSummary(projectPath, tier, provider = 'claude') {
456
435
  if (!(0, fs_1.existsSync)((0, path_1.join)(skillsDir, entry, 'SKILL.md')))
457
436
  continue;
458
437
  if (/^sr-/.test(entry))
438
+ continue;
439
+ else if (/^custom-/.test(entry))
459
440
  agents++;
460
441
  else if (/^openspec-/.test(entry))
461
442
  opsxCommands++;
@@ -473,7 +454,8 @@ function computeSummary(projectPath, tier, provider = 'claude') {
473
454
  }
474
455
  }
475
456
  else {
476
- // Claude / Gemini layout: agents at `<dir>/agents/sr-*.md`, slash commands
457
+ // Claude / Gemini layout: custom roles at `<dir>/agents/custom-*.md`
458
+ // (baseline roles are runtime-defined, stale `sr-*` files are ignored), slash commands
477
459
  // at `<dir>/commands/{specrails,opsx}/*.<ext>`. Gemini installs into
478
460
  // `.gemini/` and its commands are TOML (`.gemini/commands/specrails/*.toml`);
479
461
  // claude installs into `.claude/` with Markdown commands. Without the
@@ -484,7 +466,7 @@ function computeSummary(projectPath, tier, provider = 'claude') {
484
466
  const agentsDir = (0, path_1.join)(projectPath, dir, 'agents');
485
467
  if ((0, fs_1.existsSync)(agentsDir)) {
486
468
  const files = (0, fs_1.readdirSync)(agentsDir);
487
- agents = files.filter((f) => /^sr-.*\.md$/.test(f)).length;
469
+ agents = files.filter((f) => /^custom-.*\.md$/.test(f)).length;
488
470
  const personasDir = (0, path_1.join)(agentsDir, 'personas');
489
471
  if ((0, fs_1.existsSync)(personasDir)) {
490
472
  personas = (0, fs_1.readdirSync)(personasDir).filter((f) => f.endsWith('.md')).length;
@@ -515,6 +497,8 @@ function computeSummary(projectPath, tier, provider = 'claude') {
515
497
  }
516
498
  /**
517
499
  * Resolve completion against the selected provider's real filesystem layout.
500
+ * Completion is decided by the workflow commands Core places; role agents are
501
+ * runtime-defined and never required.
518
502
  * A legacy `.claude` fallback remains intentional only for Codex/Gemini:
519
503
  * older Core releases scaffolded Claude artefacts for those selections.
520
504
  * Kimi never had such a released legacy Core target; accepting a mixed
@@ -529,14 +513,13 @@ function setupArtifactState(projectPath, tier, provider) {
529
513
  : nativeSummary;
530
514
  const nativeHasCommands = nativeSummary.specrailsCommands + nativeSummary.opsxCommands > 0;
531
515
  const legacyHasCommands = legacySummary.specrailsCommands + legacySummary.opsxCommands > 0;
532
- const nativeComplete = nativeSummary.agents > 0 && nativeHasCommands;
533
- const legacyComplete = legacySummary.agents > 0 && legacyHasCommands;
516
+ const nativeComplete = nativeHasCommands;
517
+ const legacyComplete = legacyHasCommands;
534
518
  const selected = nativeComplete || !legacyComplete ? nativeSummary : legacySummary;
535
519
  return {
536
520
  // Preserve the actual selected provider for UI labels even when the
537
521
  // artefacts came from the legacy Claude compatibility tree.
538
522
  summary: { ...selected, provider },
539
- hasAgents: nativeSummary.agents > 0 || legacySummary.agents > 0,
540
523
  hasCommands: nativeHasCommands || legacyHasCommands,
541
524
  hasPersonas: nativeSummary.personas > 0 || legacySummary.personas > 0,
542
525
  complete: nativeComplete || legacyComplete,
@@ -1026,7 +1009,9 @@ class SetupManager {
1026
1009
  const validation = validateInstalledCore(root);
1027
1010
  const selectedProvider = provider ?? this._projectProviders.get(projectId) ?? 'claude';
1028
1011
  const summary = computeSummary(root, 'quick', selectedProvider);
1029
- if (!validation.ok || !installedVersion || summary.agents < 3 || summary.specrailsCommands < 1) {
1012
+ // Role agents are runtime-defined: a Core install is complete when its
1013
+ // workflow commands are in place, regardless of custom role count.
1014
+ if (!validation.ok || !installedVersion || summary.specrailsCommands < 1) {
1030
1015
  this._broadcast({ type: 'setup_error', projectId, error: 'Core 5 uses deterministic installation. Run project installation to repair its framework; enrichment is no longer supported.' });
1031
1016
  return true;
1032
1017
  }
@@ -1315,9 +1300,9 @@ class SetupManager {
1315
1300
  case 'tool-use': {
1316
1301
  this._broadcast({ type: 'setup_log', projectId, line: `[tool] ${ev.name}`, stream: 'stdout' });
1317
1302
  // Tool inputs commonly mention the paths being written — feed the
1318
- // input preview into the checkpoint detector so writes to
1319
- // .claude/agents/sr-*.md or .codex/skills/sr-*/SKILL.md advance
1320
- // the checkpoint state immediately.
1303
+ // input preview into the checkpoint detector so writes to workflow
1304
+ // commands (`commands/specrails/*.md`) or provider command skills
1305
+ // advance the checkpoint state immediately.
1321
1306
  const hits = detectCheckpointFromText(ev.inputPreview);
1322
1307
  for (const hit of hits) {
1323
1308
  this._advanceCheckpoint(projectId, hit.key, hit.detail);
@@ -3,7 +3,6 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.ensureFrameworkAgents = ensureFrameworkAgents;
7
6
  exports.ensureFrameworkCommandSubtrees = ensureFrameworkCommandSubtrees;
8
7
  exports.workspacePathFor = workspacePathFor;
9
8
  exports.ensureWorkspace = ensureWorkspace;
@@ -16,63 +15,6 @@ const framework_manager_1 = require("./framework-manager");
16
15
  const framework_migration_1 = require("./framework-migration");
17
16
  const artifact_registry_1 = require("./artifact-registry");
18
17
  const agent_mcp_config_1 = require("./agent-mcp-config");
19
- /**
20
- * Windows repair: ensure the workspace's `<providerDir>/agents` holds the
21
- * framework's `sr-*` agent definitions, copied from the REAL versioned framework
22
- * dir (`~/.specrails/framework/<version>/<providerDir>/agents`).
23
- *
24
- * Why: on Windows the `framework/current` JUNCTION can be untraversable by Node's
25
- * `fs` ("UNKNOWN: scandir" / "untrusted mount point"); the bundled core's
26
- * `assemble` sources the agents THROUGH `current`, so `linkAgentFiles` reads
27
- * nothing and the workspace ends up with NO `sr-*` agents — the implement
28
- * pipeline then has no sub-agents to delegate to (architect/developer/reviewer)
29
- * and silently runs everything inline. The versioned dir is a real, traversable
30
- * directory, so we read it directly. (The proper fix lives in core's `assemble`;
31
- * this repairs already-broken installs without waiting for a core republish, and
32
- * mirrors exactly what the fixed core does on Windows — copy from the version
33
- * dir.) `assemble` never re-runs on a rail spawn, so a workspace broken at setup
34
- * stays broken; this runs per rail spawn to self-heal it.
35
- *
36
- * NO-OP on POSIX (per-file symlinks already populate the workspace correctly;
37
- * byte-identical). Additive (never touches user `custom-*.md`) + idempotent.
38
- * Returns the number of agents copied.
39
- */
40
- function ensureFrameworkAgents(workspaceDir, providerDir, home) {
41
- (0, core_update_state_1.assertWorkspaceCoreReady)(workspaceDir, home);
42
- if (process.platform !== 'win32')
43
- return 0;
44
- const root = (0, framework_manager_1.frameworkRoot)(home);
45
- const version = (0, framework_manager_1.readCurrentFrameworkVersion)(home);
46
- if (!version)
47
- return 0;
48
- const src = path_1.default.join(root, version, providerDir, 'agents');
49
- let entries;
50
- try {
51
- entries = fs_1.default.readdirSync(src);
52
- }
53
- catch {
54
- return 0; // framework agents not materialized for this provider
55
- }
56
- const dest = path_1.default.join(workspaceDir, providerDir, 'agents');
57
- let copied = 0;
58
- for (const name of entries) {
59
- // Framework agents only; never clobber a user/plugin `custom-*.md`.
60
- if (!name.endsWith('.md') || name.startsWith('custom-'))
61
- continue;
62
- const destFile = path_1.default.join(dest, name);
63
- if (fs_1.default.existsSync(destFile))
64
- continue;
65
- try {
66
- fs_1.default.mkdirSync(dest, { recursive: true });
67
- fs_1.default.copyFileSync(path_1.default.join(src, name), destFile);
68
- copied += 1;
69
- }
70
- catch {
71
- /* best-effort per file — one failure must never abort the rail spawn */
72
- }
73
- }
74
- return copied;
75
- }
76
18
  /** Whole-directory framework links for the legacy provider layouts. */
77
19
  const DIR_LINKED_SUBTREES = ['commands', 'skills', 'rules'];
78
20
  /**
@@ -80,8 +22,9 @@ const DIR_LINKED_SUBTREES = ['commands', 'skills', 'rules'];
80
22
  *
81
23
  * - `rules/` and `specrails/` are whole-directory framework links.
82
24
  * - `skills/` is a real merged directory. Core links only its framework-owned
83
- * `specrails-*` workflow and `sr-*` role children so OpenSpec, custom, and
84
- * other user-owned direct-child skills can coexist.
25
+ * `specrails-*` workflow children (older Cores also linked `sr-*` role
26
+ * skills) so OpenSpec, custom, and other user-owned direct-child skills can
27
+ * coexist.
85
28
  *
86
29
  * The Windows repair must mirror that ownership boundary exactly. Replacing the
87
30
  * Kimi `skills/` root would destroy user state; merely seeing entries in that
@@ -172,21 +115,20 @@ function repairMissingCommands(src, dest) {
172
115
  }
173
116
  }
174
117
  /**
175
- * Windows repair for provider-owned framework links — the sibling of
176
- * `ensureFrameworkAgents`.
118
+ * Windows repair for provider-owned framework links.
177
119
  *
178
- * Why a SEPARATE repair: agents are linked per-file, so a broken `current`
179
- * junction leaves an EMPTY-but-real `agents/` dir that `ensureFrameworkAgents`
180
- * refills file-by-file. `commands`/`skills`/`rules` are instead a single
181
- * dir-symlink INTO `current/<provider>/<subtree>`; when the `current` junction is
182
- * untraversable by the sidecar (the documented Windows failure), that link is
183
- * unreadable and the workspace has NO `/specrails:*` commands at all — the claude
184
- * CLI then reports `Unknown command: /specrails:implement`. This replaces an
120
+ * Why: `commands`/`skills`/`rules` are a single dir-symlink INTO
121
+ * `current/<provider>/<subtree>`; when the `current` junction is untraversable
122
+ * by the sidecar (the documented Windows failure), that link is unreadable and
123
+ * the workspace has NO `/specrails:*` commands at all — the claude CLI then
124
+ * reports `Unknown command: /specrails:implement`. This replaces an
185
125
  * unreadable/missing link with a REAL recursively-copied directory read straight
186
- * from the versioned framework dir (never through `current`).
126
+ * from the versioned framework dir (never through `current`). Role agents need
127
+ * no repair: specrails-core defines them in its runtime, not as workspace files.
128
+ * `assemble` never re-runs on a rail spawn, so this runs per spawn to self-heal.
187
129
  *
188
130
  * Kimi needs an additional per-child repair because its `skills/` root is a real
189
- * merged directory. Only `specrails-*` and `sr-*` children are framework-owned;
131
+ * merged directory. Only `specrails-*` (and legacy `sr-*`) children are framework-owned;
190
132
  * `openspec-*`, `custom-*`, and unknown children are never copied, replaced, or
191
133
  * removed.
192
134
  *
@@ -1 +0,0 @@
1
- import{a as e}from"./rolldown-runtime-CNC7AqOf.js";import{n as t,t as n}from"./jsx-runtime-zu2_FqZY.js";import{d as r,u as i}from"./chunk-KS7C4IRE-DEKu087k.js";import{n as a,t as o}from"./createLucideIcon-Bjbbp_KS.js";import{a as s,r as c,s as l}from"./useDesktop-ChSmmJfc.js";import{r as u}from"./provider-capabilities-lePfeT_Y.js";import{n as d,r as f,t as p}from"./save-OsUqVn99.js";import{t as m}from"./external-link-D6XxC_Cu.js";import{t as h}from"./git-branch-BRM0F5GN.js";import{n as g,t as _}from"./square-Ci-PFcFe.js";import{t as v}from"./plus-CsnjfkmX.js";import{t as y}from"./rotate-ccw-Wh4id13q.js";import{t as b}from"./trash-2-BOU3WdZZ.js";import{t as ee}from"./triangle-alert-H9T4jAmh.js";import{t as te}from"./upload-DYMjAQ6M.js";import{t as ne}from"./x-CBMI9ejn.js";import{a as x,i as re,l as S,o as ie,r as C,t as ae}from"./dialog-CMgps2MY.js";import{t as w}from"./utils-BC4DHlz2.js";import{t as T}from"./button-D1xExSTF.js";import{n as E,t as D}from"./project-repositories-DZKmieH3.js";import{Ft as oe,J as se,K as ce,Mt as le,U as O,Ut as ue,Vt as de,Y as fe,Yt as pe,bt as me,c as k,d as he,f as ge,gt as A,in as _e,it as j,l as M,m as N,ot as P,p as ve,q as ye,rn as be,rt as xe,tn as Se,u as F,xt as I,zt as Ce}from"./index-DVkWHOR3.js";import{a as we,c as Te,d as Ee,f as De,i as L,l as Oe,m as R,n as ke,o as Ae,p as je,r as Me,s as Ne,t as Pe,u as Fe}from"./loop-layout-BF8xMiNv.js";var Ie=o(`grid-3x3`,[[`rect`,{width:`18`,height:`18`,x:`3`,y:`3`,rx:`2`,key:`afitv7`}],[`path`,{d:`M3 9h18`,key:`1pudct`}],[`path`,{d:`M3 15h18`,key:`5xshup`}],[`path`,{d:`M9 3v18`,key:`fh3hqa`}],[`path`,{d:`M15 3v18`,key:`14nvp0`}]]),Le=o(`move-horizontal`,[[`path`,{d:`m18 8 4 4-4 4`,key:`1ak13k`}],[`path`,{d:`M2 12h20`,key:`9i4pu4`}],[`path`,{d:`m6 8-4 4 4 4`,key:`15zrgr`}]]),Re=o(`move-vertical`,[[`path`,{d:`M12 2v20`,key:`t6zp3m`}],[`path`,{d:`m8 18 4 4 4-4`,key:`bh5tu3`}],[`path`,{d:`m8 6 4-4 4 4`,key:`ybng9g`}]]),z=e(t(),1),B=n(),V=`h-9 w-full rounded-md border border-input bg-background px-2 text-sm`;function ze({roles:e={},provider:t,supported:n,onChange:r,renderEngine:i,visibleRoleIds:o,manageRoles:s=!0}){let{t:c}=a(`agentRuntime`),[l,u]=(0,z.useState)(``),[d,f]=(0,z.useState)(!1),p=Object.entries(e).filter(([e])=>!ge.includes(e)&&(!o||o.includes(e)));function m(){if(!k.test(l)||l===`fixer`||ge.includes(l)||Object.prototype.hasOwnProperty.call(e,l)){f(!0);return}r({...e,[l]:{provider:t,access:`read`,artifacts:`none`}}),u(``),f(!1)}return(0,B.jsxs)(`section`,{className:`space-y-3`,"aria-labelledby":`custom-runtime-roles`,children:[s&&(0,B.jsxs)(`div`,{children:[(0,B.jsx)(`h3`,{id:`custom-runtime-roles`,className:`text-sm font-medium`,children:c(`customRoles.title`)}),(0,B.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:c(`customRoles.hint`)})]}),!n&&(0,B.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:c(`customRoles.unsupported`)}),p.map(([t,a])=>{let o=n=>r({...e,[t]:{...a,...n}});return(0,B.jsxs)(`fieldset`,{className:`space-y-3 rounded-lg border p-3`,"aria-label":t,children:[(0,B.jsx)(`legend`,{className:`px-1 font-mono text-sm`,children:t}),s&&(0,B.jsx)(`div`,{className:`flex justify-end`,children:(0,B.jsx)(T,{size:`sm`,variant:`ghost`,onClick:()=>{let n={...e};delete n[t],r(n)},children:c(`customRoles.remove`,{id:t})})}),(0,B.jsxs)(`fieldset`,{disabled:!n,className:`space-y-3`,children:[i(t),(0,B.jsxs)(`div`,{className:`grid gap-3 sm:grid-cols-2`,children:[(0,B.jsxs)(`label`,{className:`space-y-1 text-xs`,children:[c(`customRoles.access`),(0,B.jsxs)(`select`,{className:V,value:a.access,onChange:e=>o({access:e.target.value}),children:[(0,B.jsx)(`option`,{value:`read`,children:c(`customRoles.read`)}),(0,B.jsx)(`option`,{value:`write`,children:c(`customRoles.write`)})]})]}),(0,B.jsxs)(`label`,{className:`space-y-1 text-xs`,children:[c(`customRoles.artifacts`),(0,B.jsxs)(`select`,{className:V,value:a.artifacts,onChange:e=>o({artifacts:e.target.value}),children:[(0,B.jsx)(`option`,{value:`none`,children:c(`customRoles.none`)}),(0,B.jsx)(`option`,{value:`tasks-checkboxes`,children:c(`customRoles.tasks`)}),(0,B.jsx)(`option`,{value:`all`,children:c(`customRoles.all`)})]})]})]}),(0,B.jsxs)(`label`,{className:`block space-y-1 text-xs`,children:[c(`customRoles.skill`),(0,B.jsxs)(`select`,{className:V,value:a.openspecSkill??``,onChange:e=>o({openspecSkill:e.target.value||void 0}),children:[(0,B.jsx)(`option`,{value:``,children:c(`customRoles.noSkill`)}),[`openspec-ff-change`,`openspec-apply-change`,`openspec-verify-change`].map(e=>(0,B.jsx)(`option`,{value:e,children:e},e))]})]}),(0,B.jsxs)(`label`,{className:`block space-y-1 text-xs`,children:[c(`customRoles.prompt`),(0,B.jsx)(`textarea`,{className:`w-full rounded-md border border-input bg-background px-3 py-2 text-sm`,value:a.prompt??``,rows:5,maxLength:2e4,onChange:e=>o({prompt:e.target.value||void 0})})]})]})]},t)}),s&&(0,B.jsxs)(`fieldset`,{disabled:!n||!t,className:`flex items-end gap-2`,children:[(0,B.jsxs)(`label`,{className:`min-w-0 flex-1 space-y-1 text-xs`,children:[c(`customRoles.id`),(0,B.jsx)(O,{value:l,maxLength:64,placeholder:`security-reviewer`,onChange:e=>{u(e.target.value),f(!1)}})]}),(0,B.jsx)(T,{variant:`secondary`,onClick:m,children:c(`customRoles.add`)})]}),d&&(0,B.jsx)(`p`,{role:`alert`,className:`text-xs text-destructive`,children:c(`customRoles.invalidId`)})]})}var Be={architect:ue,developer:oe,host:A};function Ve({projectId:e,catalogUrl:t,guardrails:n,onChange:r}){let{t:i,i18n:o}=a(`agentRuntime`),[s,c]=(0,z.useState)(!0),[l,u]=(0,z.useState)({status:`loading`});(0,z.useEffect)(()=>{let n=!1;return u({status:`loading`}),fetch(t??`${E(e)}/agent-runtime/guardrails`,{cache:`no-store`}).then(async e=>{if(!e.ok)throw Error(`guardrails`);let r=await e.json(),i=t?r.guardrails:r;if(!ve(i))throw Error(`guardrails`);n||u({status:`ready`,supported:i.supported,catalog:i.catalog})}).catch(()=>{n||u({status:`unsupported`})}),()=>{n=!0}},[e,t]);let f=l.status===`ready`?l.catalog:[],p=l.status===`ready`&&l.supported,m=f.filter(e=>n?.[e.id]===!1).length,h=f.length,g=e=>o.exists(`agentRuntime:guardrails.items.${e}.title`),_=`pipeline-guardrails-body`;return(0,B.jsxs)(`fieldset`,{id:`pipeline-guardrails`,"data-testid":`phase-card-guardrails`,className:`scroll-mt-4 rounded-lg border border-border transition-shadow`,children:[(0,B.jsx)(`legend`,{className:`sr-only`,children:i(`guardrails.title`)}),(0,B.jsxs)(`button`,{type:`button`,"aria-expanded":s,"aria-controls":_,"aria-label":`${i(s?`pipeline.collapse`:`pipeline.open`)}: ${i(`guardrails.title`)}`,onClick:()=>c(e=>!e),className:`flex w-full flex-wrap items-center gap-2 rounded-t-lg px-3 py-2 text-left hover:bg-muted/40`,children:[(0,B.jsx)(`span`,{className:`flex h-5 w-5 shrink-0 items-center justify-center rounded-full bg-accent-success/15 text-accent-success`,children:(0,B.jsx)(me,{className:`h-3.5 w-3.5`,"aria-hidden":!0})}),(0,B.jsx)(`span`,{className:`text-xs font-medium`,children:i(`guardrails.title`)}),(0,B.jsxs)(`span`,{className:`ml-auto flex items-center gap-2`,children:[l.status===`ready`&&p&&(0,B.jsx)(`span`,{"data-testid":`guardrails-active`,className:w(`inline-flex items-center rounded-md border px-1.5 py-0.5 text-[11px] leading-4`,m?`border-accent-warning/40 bg-accent-warning/10 text-accent-warning`:`border-accent-success/30 bg-accent-success/10 text-accent-success`),children:i(`guardrails.active`,{on:h-m,total:h})}),(0,B.jsx)(d,{className:`h-3.5 w-3.5 text-muted-foreground transition-transform ${s?``:`-rotate-90`}`,"aria-hidden":!0})]})]}),(0,B.jsxs)(`div`,{id:_,hidden:!s,className:`space-y-3 px-3 pb-3`,children:[(0,B.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:i(`guardrails.intro`)}),l.status===`loading`&&(0,B.jsx)(`p`,{role:`status`,className:`text-xs text-muted-foreground`,children:i(`loading`)}),(l.status===`unsupported`||l.status===`ready`&&!p)&&(0,B.jsx)(`p`,{role:`status`,className:`rounded-md border border-accent-warning/40 p-3 text-xs text-accent-warning`,children:i(`guardrails.unsupported`)}),l.status===`ready`&&(0,B.jsxs)(`fieldset`,{disabled:!p,className:`space-y-3 disabled:opacity-60`,children:[m>0&&(0,B.jsx)(`div`,{className:`flex justify-end`,children:(0,B.jsx)(`button`,{type:`button`,className:`text-[11px] text-accent-primary underline-offset-2 hover:underline`,onClick:()=>r(void 0),children:i(`guardrails.reset`)})}),M.map(e=>{let t=f.filter(t=>t.phase===e);if(!t.length)return null;let a=Be[e];return(0,B.jsxs)(`div`,{className:`space-y-2`,"data-testid":`guardrails-phase-${e}`,children:[(0,B.jsxs)(`p`,{className:`flex items-center gap-1.5 text-[11px] font-medium uppercase tracking-wide text-muted-foreground`,children:[(0,B.jsx)(a,{className:`h-3.5 w-3.5`,"aria-hidden":!0}),i(`guardrails.phases.${e}`)]}),(0,B.jsx)(`ul`,{className:`divide-y divide-border/60 rounded-md border border-border/60`,children:t.map(e=>{let t=n?.[e.id]!==!1,a=g(e.id)?i(`guardrails.items.${e.id}.title`):e.id,o=g(e.id)?i(`guardrails.items.${e.id}.description`):i(`guardrails.unknown`),s=g(e.id)?i(`guardrails.items.${e.id}.why`):null,c=`guardrail-${e.id}-title`;return(0,B.jsxs)(`li`,{className:`flex items-start gap-3 px-3 py-2`,children:[(0,B.jsx)(`button`,{type:`button`,role:`switch`,"aria-checked":t,"aria-labelledby":c,"data-testid":`guardrail-${e.id}`,onClick:()=>r(N(n,e.id,!t)),className:w(`relative mt-0.5 inline-flex h-4 w-7 shrink-0 items-center rounded-full transition-colors`,t?`bg-accent-primary/70`:`bg-muted-foreground/30`),children:(0,B.jsx)(`span`,{className:w(`absolute h-3 w-3 rounded-full bg-background shadow transition-transform`,t?`translate-x-3.5`:`translate-x-0.5`)})}),(0,B.jsxs)(`div`,{className:`min-w-0 flex-1`,children:[(0,B.jsx)(`p`,{id:c,className:w(`text-xs font-medium`,!t&&`text-muted-foreground line-through decoration-muted-foreground/50`),children:a}),(0,B.jsx)(`p`,{className:`mt-0.5 text-[11px] leading-4 text-muted-foreground`,children:o}),s&&(0,B.jsx)(`p`,{className:`mt-0.5 text-[10px] italic leading-4 text-muted-foreground/70`,children:s})]})]},e.id)})})]},e)})]})]})]})}var He=`h-9 w-full rounded-md border border-input bg-background px-2 text-sm`;function Ue({config:e,onChange:t}){let{t:n}=a(`agentRuntime`),r=e.efficiency??{schemaVersion:1};return(0,B.jsxs)(`section`,{className:`space-y-3`,"aria-label":n(`efficiency.title`),children:[(0,B.jsx)(`h3`,{className:`text-sm font-medium`,children:n(`efficiency.title`)}),(0,B.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:n(`efficiency.scope`)}),(0,B.jsx)(`div`,{className:`grid gap-3 sm:grid-cols-3`,children:[`contextMode`,`reviewMode`,`planning`].map(i=>(0,B.jsxs)(`label`,{className:`block space-y-1 text-xs`,children:[n(`efficiency.${i}`),(0,B.jsxs)(`select`,{className:He,value:r[i]??(i===`planning`?`proportional`:`incremental`),onChange:n=>t({...e,efficiency:{...r,[i]:n.target.value}}),children:[(0,B.jsx)(`option`,{value:i===`planning`?`proportional`:`incremental`,children:n(`efficiency.adaptive`)}),(0,B.jsx)(`option`,{value:`full`,children:n(`efficiency.full`)})]})]},i))}),(0,B.jsxs)(`label`,{className:`flex items-center gap-2 text-xs`,children:[(0,B.jsx)(`input`,{type:`checkbox`,checked:r.acceptDeveloperChecks!==!1,onChange:n=>t({...e,efficiency:{...r,acceptDeveloperChecks:n.target.checked}})}),n(`efficiency.developerChecks`)]}),(0,B.jsxs)(`label`,{className:`block space-y-1 text-xs`,children:[n(`efficiency.concurrency`),(0,B.jsx)(O,{type:`number`,min:`1`,max:`4`,step:`1`,value:r.verification?.maxConcurrency??1,onChange:n=>t({...e,efficiency:{...r,verification:{...r.verification,maxConcurrency:Number(n.target.value)}}})})]}),(0,B.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:n(`efficiency.concurrencyHint`)})]})}function We(e){let t=[],n=0;function r(i,a,o){if(!(o.length>=32||t.length>=1e4))for(let s of i.nodes){if(++n>1e4)return;if(s.type!==`core`)continue;let i=a+s.id,c=s.data?.kind,l=H(s.data?.params);(c===`role-turn`||c===`implementation-step`&&l.phase===`reviewer`)&&t.push(i);let u=c===`component`?l.ref:c===`map`?l.body:void 0;typeof u==`string`&&!o.includes(u)&&e.components?.[u]&&r(e.components[u],i+`/`,[...o,u])}}return r(e,``,[]),t.sort()}var H=e=>typeof e==`object`&&e&&!Array.isArray(e)?e:{};function U(e){return typeof e.type==`string`?e.type:e.properties||e.additionalProperties?`object`:e.items?`array`:`string`}function W(e){if(`default`in e)return structuredClone(e.default);if(`const`in e)return structuredClone(e.const);if(Array.isArray(e.enum))return structuredClone(e.enum[0]);let t=e.oneOf??e.anyOf;if(Array.isArray(t)&&!e.properties)return W(H(t[0]));switch(U(e)){case`boolean`:return!1;case`number`:case`integer`:return typeof e.minimum==`number`?e.minimum:0;case`array`:return[];case`object`:{let t=H(e.properties);return Object.fromEntries((Array.isArray(e.required)?e.required:[]).filter(e=>typeof e==`string`).map(e=>[e,W(H(t[e]))]))}default:return``}}function Ge(e){let t=H(W(e.paramsSchema));return e.kind===`prompt`&&(t.text=``,t.engine={provider:`claude`},t.access=`read`),e.kind===`shell`&&(t.argv=[``]),e.kind===`assign`&&(t.set={}),{kind:`core`,coreKind:e.kind,params:t}}function Ke(e,t,n={}){if(!e)return[];let r=e.outcomes;return e.kind===`prompt`&&(r=t.sentinel===`verification`?[`pass`,`fail`,`failed`]:t.sentinel===`blocked`?[`next`,`blocked`,`failed`]:[`next`,`failed`]),e.kind===`role-turn`&&(r=t.structuredOutput?[`next`,`invalid`,`failed`]:[`next`,`failed`]),e.kind===`component`?n[String(t.ref)]?.outputs??[`next`,`failed`]:r.filter(t=>e.outcomes.includes(t))}var qe=e=>[`prompt`,`role-turn`,`decider`,`implementation`,`implementation-step`].includes(e)?`ai`:[`verify`,`shell`].includes(e)?`verification`:e===`artifact-contract`||e.startsWith(`openspec-`)?`openspec`:`control`;function Je(e,t,n){return t===`implementation`?[`architect`,`developer`,`reviewer`,`fixer`]:t===`implementation-step`?[`architect`,`developer`,`reviewer`,`fixer`].includes(String(n.phase))?[String(n.phase)]:[]:t===`prompt`?[e===`fix`?`fixer`:e===`prepare`?`architect`:n.access===`read`?`reviewer`:`developer`]:(t===`role-turn`||t===`decider`)&&typeof n.roleId==`string`?[n.roleId]:[]}function Ye(e){let t=new Set,n=new Set;function r(i){for(let a of i.nodes){if(a.type!==`core`)continue;let i=H(a.data?.params),o=a.data?.kind;Je(a.id,o,i).forEach(e=>t.add(e));let s=o===`component`?i.ref:o===`map`?i.body:void 0;typeof s==`string`&&!n.has(s)&&e.components?.[s]&&(n.add(s),r(e.components[s]))}}return r(e),[...t]}var G=`w-full rounded-md border border-input bg-background px-2 py-1 text-xs`,K=[`architect`,`developer`,`reviewer`,`fixer`];function Xe({value:e,onChange:t,selectedRole:n,graph:r,mode:i=`all`}){let{t:o}=a(`agentRuntime`),{activeProjectId:l}=c(),d=(0,z.useRef)(l);d.current=l;let[f,p]=(0,z.useState)([]),[m,h]=(0,z.useState)({}),[g,_]=(0,z.useState)(),[v,y]=(0,z.useState)(``),[b,ee]=(0,z.useState)(!1),[te,ne]=(0,z.useState)(!1),x=r?Ye(r):[...K,...Object.keys(e?.roles??{})],re=i===`step`?[n??``]:te?void 0:x,S=i!==`workflow`,ie=i!==`step`,C=i===`step`?`loopAgents.stepTitle`:i===`workflow`?`loopAgents.policy`:`loopAgents.title`,ae=[...K,...Object.keys(e?.roles??{})].some(e=>!x.includes(e));(0,z.useEffect)(()=>{let e=new AbortController;return Promise.all([`/api/runtime-providers`,`/api/loop-agent-defaults`].map(t=>fetch(t,{signal:e.signal}).then(async e=>{if(!e.ok)throw Error(o(`loadFailed`));return e.json()}))).then(([t,n])=>{e.signal.aborted||(p(t.providers??[]),_(n.agents),h(Object.fromEntries(Object.entries(t.status??{}).map(([e,t])=>[e,t.models??[]]))))}).catch(()=>{e.signal.aborted||y(o(`loadFailed`))}),()=>e.abort()},[o]);async function w(){let e=l;ee(!0),y(``);try{let n=s(),[r,i]=await Promise.all([fetch(`${n}/agent-runtime/config`),fetch(`${n}/agent-runtime/loop-roles`)]);if(!r.ok||!i.ok)throw Error(o(`loadFailed`));let a=await r.json(),c=await i.json(),{agents:l,fixer:u,roles:f,rolePrompts:p,limits:m,review:h,architect:_,approvalBeforeArchive:v,efficiency:y,guardrails:b}=a.config;if(!e||d.current!==e)return;t({schemaVersion:1,agents:l,fixer:u,roles:{...g?.roles,...Object.fromEntries(Object.entries(f??{}).map(([e,t])=>[e,{...t,prompt:p?.[e]??t.prompt}])),...c.roles?.decider?{"loop-decider":{...g.roles[`loop-decider`],...c.roles.decider}}:{}},rolePrompts:Object.fromEntries(Object.entries({...g?.rolePrompts,...p}).filter(([e])=>K.includes(e))),limits:m,review:h,architect:_,approvalBeforeArchive:v,efficiency:y,guardrails:b})}catch{y(o(`loadFailed`))}finally{ee(!1)}}function E(n){if(!e)return null;let r=K.includes(n),i=n===`fixer`?e.fixer??e.agents.developer:r?e.agents[n]:e.roles?.[n];if(!i)return null;let a=i=>t(n===`fixer`?{...e,fixer:i}:r?{...e,agents:{...e.agents,[n]:i}}:{...e,roles:{...e.roles,[n]:{...e.roles[n],...i}}}),s=f.find(e=>e.id===i.provider),c=s?.kind===`cli`?P(s.cli).map(e=>e.value):m[i.provider]??[];return(0,B.jsxs)(`div`,{className:`space-y-2`,children:[(0,B.jsxs)(`label`,{className:`block text-xs`,children:[o(`agents.provider`),(0,B.jsxs)(`select`,{className:G,value:i.provider,onChange:e=>a({provider:e.target.value,maxTurns:i.maxTurns}),children:[(0,B.jsx)(`option`,{value:`inherit`,children:o(`loopAgents.inheritProvider`)}),!s&&i.provider!==`inherit`&&u(i.provider)&&(0,B.jsx)(`option`,{value:i.provider,children:i.provider}),f.filter(e=>u(e.kind===`cli`?e.cli:e.id)).map(e=>(0,B.jsx)(`option`,{value:e.id,children:e.kind===`openai-compatible`?e.label??e.id:e.id},e.id))]})]}),(0,B.jsxs)(`label`,{className:`block text-xs`,children:[o(`agents.model`),(0,B.jsx)(O,{value:i.model??``,list:`loop-models-${n}`,onChange:e=>a({...i,model:e.target.value||void 0})}),(0,B.jsx)(`datalist`,{id:`loop-models-${n}`,children:c.map(e=>(0,B.jsx)(`option`,{value:e},e))})]}),(0,B.jsxs)(`label`,{className:`block text-xs`,children:[o(`loopAgents.effort`),(0,B.jsx)(O,{value:i.effort??``,onChange:e=>a({...i,effort:e.target.value||void 0})})]}),(0,B.jsxs)(`label`,{className:`block text-xs`,children:[o(`agents.maxTurns`,{turns:100}),(0,B.jsx)(O,{type:`number`,min:1,value:i.maxTurns??``,onChange:e=>a({...i,maxTurns:e.target.value?Number(e.target.value):void 0})})]}),(0,B.jsxs)(`label`,{className:`block text-xs`,children:[o(`agents.thinking`),(0,B.jsxs)(`select`,{className:G,value:i.thinking??``,onChange:e=>a({...i,thinking:e.target.value?e.target.value:void 0}),children:[(0,B.jsx)(`option`,{value:``,children:o(`loopAgents.default`)}),(0,B.jsx)(`option`,{value:`off`,children:o(`agents.thinking_off`)}),(0,B.jsx)(`option`,{value:`on`,children:o(`agents.thinking_on`)})]})]}),(0,B.jsxs)(`label`,{className:`block text-xs`,children:[o(`loopAgents.escalationModel`),(0,B.jsx)(O,{value:i.escalation?.model??``,onChange:e=>a({...i,escalation:e.target.value?{...i.escalation,model:e.target.value}:void 0})})]}),i.escalation&&(0,B.jsxs)(`label`,{className:`block text-xs`,children:[o(`loopAgents.escalationEffort`),(0,B.jsx)(O,{value:i.escalation.effort??``,onChange:e=>a({...i,escalation:{model:i.escalation.model,effort:e.target.value||void 0}})})]})]})}let D=e?{...e,enabled:!0,providers:f,verification:[]}:void 0;return(0,B.jsxs)(`section`,{className:`space-y-3 border-b border-border pb-4`,"aria-label":o(C),children:[(0,B.jsx)(`h3`,{className:`text-sm font-medium`,children:o(C)}),S&&(0,B.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:o(i===`step`?`loopAgents.stepHint`:`loopAgents.hint`)}),v&&(0,B.jsx)(`p`,{role:`alert`,className:`text-xs text-destructive`,children:v}),!e&&(0,B.jsxs)(B.Fragment,{children:[(0,B.jsx)(`p`,{className:`text-xs text-accent-warning`,children:o(`loopAgents.legacy`)}),(0,B.jsx)(T,{size:`sm`,disabled:!g,onClick:()=>g&&t(structuredClone(g)),children:o(`loopAgents.enable`)})]}),i!==`step`&&(0,B.jsx)(T,{size:`sm`,variant:`secondary`,disabled:!l||!g||b,onClick:()=>void w(),children:o(`loopAgents.import`)}),e&&(0,B.jsxs)(B.Fragment,{children:[i===`all`&&ae&&(0,B.jsxs)(`label`,{className:`flex gap-2 text-xs`,children:[(0,B.jsx)(`input`,{type:`checkbox`,checked:te,onChange:e=>ne(e.target.checked)}),o(`loopAgents.showUnused`)]}),S&&K.filter(e=>!re||re.includes(e)).map(r=>(0,B.jsxs)(`details`,{open:n===r,className:`rounded-md border border-border p-2`,children:[(0,B.jsx)(`summary`,{className:`cursor-pointer text-sm font-medium`,children:r}),(0,B.jsxs)(`div`,{className:`mt-3 space-y-3`,children:[E(r),(0,B.jsxs)(`label`,{className:`block text-xs`,children:[o(`customRoles.prompt`),(0,B.jsx)(`textarea`,{className:G,rows:10,maxLength:2e4,value:e.rolePrompts?.[r]??``,onChange:n=>t({...e,rolePrompts:{...e.rolePrompts,[r]:n.target.value}})})]}),(0,B.jsx)(T,{size:`sm`,variant:`ghost`,disabled:!g,onClick:()=>t({...e,rolePrompts:{...e.rolePrompts,[r]:g?.rolePrompts?.[r]??``}}),children:o(`loopAgents.restoreDefinition`)})]})]},r)),i===`step`&&n&&![...K,`archive`,`verify`].includes(n)&&!e.roles?.[n]&&(0,B.jsx)(T,{size:`sm`,disabled:!f.length,onClick:()=>t({...e,roles:{...e.roles,[n]:{provider:`inherit`,access:`read`,artifacts:`none`}}}),children:o(`customRoles.add`)}),(S||i===`workflow`)&&(0,B.jsx)(ze,{manageRoles:i!==`step`,visibleRoleIds:i===`workflow`?[]:re,roles:e.roles,provider:`inherit`,supported:!0,onChange:n=>{Object.keys(n).some(t=>!e.roles?.[t])&&ne(!0),t({...e,roles:n,rolePrompts:Object.fromEntries(Object.entries(e.rolePrompts??{}).filter(([e])=>K.includes(e)))})},renderEngine:E}),(0,B.jsxs)(`div`,{className:`space-y-3`,children:[ie&&(0,B.jsxs)(`details`,{className:`rounded-md border border-border p-2`,children:[(0,B.jsx)(`summary`,{className:`cursor-pointer text-sm`,children:o(`loopAgents.policy`)}),(0,B.jsxs)(`div`,{className:`mt-3 space-y-3`,children:[[`maxAttempts`,`maxTokens`,`maxCostUsd`,`timeoutMs`].map(n=>(0,B.jsxs)(`label`,{className:`block text-xs`,children:[o(`loopAgents.${n}`),(0,B.jsx)(O,{type:`number`,min:1,value:e.limits?.[n]??``,onChange:r=>t({...e,limits:{...e.limits,[n]:r.target.value?Number(r.target.value):void 0}})})]},n)),(0,B.jsx)(Ve,{catalogUrl:`/api/loop-agent-defaults`,guardrails:e.guardrails,onChange:n=>t({...e,guardrails:n})}),D&&(0,B.jsx)(Ue,{config:D,onChange:n=>t({...e,efficiency:n.efficiency})})]})]}),(i===`all`||i===`step`&&n===`reviewer`)&&(0,B.jsxs)(B.Fragment,{children:[(0,B.jsxs)(`label`,{className:`block text-xs`,children:[o(`review.minScore`,{score:70}),(0,B.jsx)(O,{type:`number`,min:70,max:100,value:e.review?.minScore??``,onChange:n=>t({...e,review:{...e.review,minScore:n.target.value?Number(n.target.value):void 0}})})]}),F.map(n=>(0,B.jsxs)(`label`,{className:`block text-xs`,children:[o(`review.aspects.${n}`,{score:he.aspects[n]}),(0,B.jsx)(O,{type:`number`,min:he.aspects[n],max:100,value:e.review?.aspects?.[n]??``,onChange:r=>t({...e,review:{...e.review,aspects:{...e.review?.aspects,[n]:r.target.value?Number(r.target.value):void 0}}})})]},n))]}),(i===`all`||i===`step`&&n===`architect`)&&(0,B.jsxs)(`label`,{className:`block text-xs`,children:[o(`architect.onLowConfidence`),(0,B.jsxs)(`select`,{className:G,value:e.architect?.onLowConfidence??`ask`,onChange:n=>t({...e,architect:{onLowConfidence:n.target.value}}),children:[(0,B.jsx)(`option`,{value:`ask`,children:o(`architect.ask`)}),(0,B.jsx)(`option`,{value:`proceed`,children:o(`architect.proceed`)})]})]}),(i===`all`||i===`step`&&n===`archive`)&&(0,B.jsxs)(`label`,{className:`flex gap-2 text-xs`,children:[(0,B.jsx)(`input`,{type:`checkbox`,checked:e.approvalBeforeArchive??!1,onChange:n=>t({...e,approvalBeforeArchive:n.target.checked})}),o(`approvalBeforeArchive`)]})]})]})]})}var q=`w-full min-w-0 rounded border border-border bg-background px-2 py-1.5 text-xs text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent-primary`;function J({schema:e,value:t,onChange:n,path:r=`params`,choices:i={},depth:o=0}){let{t:s}=a(`loops`),c=(0,z.useId)(),[l,u]=(0,z.useState)(``);if(o>24)return(0,B.jsx)(`p`,{role:`alert`,className:`text-xs text-destructive`,children:s(`builder.core.tooDeep`)});let d=typeof e.title==`string`?e.title:r.split(`.`).slice(-1)[0],f=(e,n,a,s)=>(0,B.jsx)(J,{schema:n,value:a,onChange:s,path:`${r}.${e}`,choices:{...i,selectedProvider:typeof H(t).provider==`string`?String(H(t).provider):i.selectedProvider},depth:o+1},e),p=e.oneOf??e.anyOf;if(Array.isArray(p)&&!e.properties){let e=p.map(H),r=Math.max(0,e.findIndex(e=>`const`in e?t===e.const:Array.isArray(e.enum)?e.enum.includes(t):U(e)===(Array.isArray(t)?`array`:typeof t)));return(0,B.jsxs)(`fieldset`,{className:`space-y-2`,children:[(0,B.jsx)(`legend`,{className:`text-xs font-medium`,children:d}),(0,B.jsx)(`label`,{className:`sr-only`,htmlFor:c,children:s(`builder.core.variant`,{name:d})}),(0,B.jsx)(`select`,{id:c,className:q,value:r,onChange:t=>n(W(e[Number(t.target.value)])),children:e.map((e,t)=>(0,B.jsx)(`option`,{value:t,children:String(e.title??e.const??(Array.isArray(e.enum)?e.enum.join(` / `):U(e)))},t))}),f(`value`,e[r],t,n)]})}if(`const`in e)return(0,B.jsxs)(`p`,{className:`text-xs`,children:[(0,B.jsxs)(`span`,{className:`text-muted-foreground`,children:[d,`: `]}),String(e.const)]});if(Array.isArray(e.enum))return(0,B.jsxs)(`label`,{className:`block space-y-1 text-xs`,children:[d,(0,B.jsxs)(`select`,{className:q,value:JSON.stringify(t),onChange:e=>n(JSON.parse(e.target.value)),children:[!e.enum.includes(t)&&(0,B.jsx)(`option`,{value:JSON.stringify(t)??``,children:s(`builder.core.select`)}),e.enum.map((e,t)=>(0,B.jsx)(`option`,{value:JSON.stringify(e),children:String(e)},t))]})]});let m=U(e);if(m===`object`){let r=H(t),i=H(e.properties),a=new Set(Array.isArray(e.required)?e.required:[]),o=[...Object.keys(i),...Object.keys(r).filter(e=>!(e in i))],c=(e,t)=>{let a={...r};e===`provider`&&t!==r.provider&&i.model&&(delete a.model,delete a.effort),t===void 0?delete a[e]:Object.defineProperty(a,e,{value:t,enumerable:!0,configurable:!0,writable:!0}),n(a)},m=Array.isArray(p)?p.map(e=>H(e).required).filter(e=>Array.isArray(e)&&e.every(e=>typeof e==`string`)):[],h=t=>{let a={...r};if(m.some(e=>e.includes(t)))for(let e of m)for(let n of e)n!==t&&delete a[n];Object.defineProperty(a,t,{value:W(H(i[t]??e.additionalProperties)),enumerable:!0,configurable:!0,writable:!0}),n(a)};return(0,B.jsxs)(`fieldset`,{className:`space-y-2 min-w-0`,children:[(0,B.jsx)(`legend`,{className:`text-xs font-semibold text-foreground mb-1`,children:d}),o.map(t=>{let n=Object.prototype.hasOwnProperty.call(r,t),o=a.has(t);return!n&&!o?(0,B.jsxs)(`button`,{type:`button`,className:`inline-flex items-center gap-1 text-xs rounded border border-border px-2 py-1 mr-1 hover:bg-muted`,onClick:()=>h(t),"aria-label":s(`builder.core.addField`,{name:t}),children:[(0,B.jsx)(v,{className:`h-3 w-3`}),t]},t):(0,B.jsxs)(`div`,{className:`relative border-l border-border pl-2 space-y-1`,children:[!o&&(0,B.jsx)(`button`,{type:`button`,className:`float-right text-muted-foreground hover:text-destructive`,onClick:()=>c(t,void 0),"aria-label":s(`builder.core.removeField`,{name:t}),children:(0,B.jsx)(ne,{className:`h-3.5 w-3.5`})}),f(t,H(i[t]??e.additionalProperties),r[t],e=>c(t,e))]},t)}),e.additionalProperties!==!1&&(0,B.jsxs)(`div`,{className:`flex items-center gap-1`,children:[(0,B.jsx)(`input`,{className:q,value:l,placeholder:s(`builder.core.fieldName`),"aria-label":s(`builder.core.fieldName`),onChange:e=>u(e.target.value)}),(0,B.jsx)(`button`,{type:`button`,className:`p-1.5 text-accent-primary disabled:opacity-40`,disabled:!l.trim()||Object.prototype.hasOwnProperty.call(r,l.trim())||[`__proto__`,`constructor`,`prototype`].includes(l.trim()),onClick:()=>{h(l.trim()),u(``)},"aria-label":s(`builder.core.addField`,{name:l}),children:(0,B.jsx)(v,{className:`h-4 w-4`})})]})]})}if(m===`array`){let r=Array.isArray(t)?t:[],i=H(e.items);return(0,B.jsxs)(`fieldset`,{className:`space-y-2`,children:[(0,B.jsx)(`legend`,{className:`text-xs font-semibold`,children:d}),r.map((e,t)=>(0,B.jsxs)(`div`,{className:`border-l border-border pl-2`,children:[(0,B.jsx)(`button`,{type:`button`,className:`float-right text-muted-foreground hover:text-destructive`,onClick:()=>n(r.filter((e,n)=>n!==t)),"aria-label":s(`builder.core.removeField`,{name:`${d} ${t+1}`}),children:(0,B.jsx)(ne,{className:`h-3.5 w-3.5`})}),f(String(t+1),i,e,e=>n(r.map((n,r)=>r===t?e:n)))]},t)),(0,B.jsxs)(`button`,{type:`button`,className:`inline-flex items-center gap-1 text-xs text-accent-primary`,disabled:typeof e.maxItems==`number`&&r.length>=e.maxItems,onClick:()=>n([...r,W(i)]),children:[(0,B.jsx)(v,{className:`h-3 w-3`}),s(`builder.core.addItem`)]})]})}if(!Object.keys(e).length){let e=t===null?`null`:Array.isArray(t)?`array`:typeof t,r=[`object`,`array`,`boolean`,`number`,`null`].includes(e)?e:`string`;return(0,B.jsxs)(`div`,{className:`space-y-1`,children:[(0,B.jsxs)(`label`,{className:`text-xs`,children:[s(`builder.core.valueType`),(0,B.jsx)(`select`,{className:q,value:r,onChange:e=>n(e.target.value===`null`?null:W({type:e.target.value})),children:[`string`,`number`,`boolean`,`object`,`array`,`null`].map(e=>(0,B.jsx)(`option`,{children:e},e))})]}),r===`null`?(0,B.jsx)(`span`,{className:`text-xs`,children:`null`}):f(`value`,{type:r},t,n)]})}if(m===`boolean`)return(0,B.jsxs)(`label`,{className:`flex items-center gap-2 text-xs`,children:[(0,B.jsx)(`input`,{type:`checkbox`,checked:t===!0,onChange:e=>n(e.target.checked),className:`accent-accent-primary`}),d]});if(m===`number`||m===`integer`)return(0,B.jsxs)(`label`,{className:`block space-y-1 text-xs`,children:[d,(0,B.jsx)(`input`,{type:`number`,className:q,value:typeof t==`number`?t:``,min:typeof e.minimum==`number`?e.minimum:void 0,max:typeof e.maximum==`number`?e.maximum:void 0,step:m===`integer`?1:`any`,onChange:e=>n(e.target.value===``?void 0:Number(e.target.value))})]});let h=d===`provider`?i.providers:d===`roleId`?i.roles:[`ref`,`body`].includes(d)?i.components:void 0,g=d===`model`?i.models?.[i.selectedProvider??``]:void 0,_=[`text`,`prompt`,`question`,`message`,`goal`,`expr`,`commandLine`,`reason`].includes(d);return(0,B.jsxs)(`label`,{className:`block space-y-1 text-xs`,children:[d,h?.length&&d!==`roleId`?(0,B.jsxs)(`select`,{className:q,value:typeof t==`string`?t:``,onChange:e=>n(e.target.value),children:[(0,B.jsx)(`option`,{value:``,children:s(`builder.core.select`)}),t&&!h.includes(String(t))?(0,B.jsx)(`option`,{value:String(t),children:String(t)}):null,h.map(e=>(0,B.jsx)(`option`,{children:e},e))]}):_?(0,B.jsx)(`textarea`,{className:`${q} min-h-24 resize-y font-mono`,value:typeof t==`string`?t:``,maxLength:typeof e.maxLength==`number`?e.maxLength:void 0,onChange:e=>n(e.target.value)}):(0,B.jsx)(`input`,{list:g?.length||d===`roleId`&&h?.length?c:void 0,className:q,value:typeof t==`string`?t:``,maxLength:typeof e.maxLength==`number`?e.maxLength:void 0,onChange:e=>n(e.target.value)}),g?.length||d===`roleId`&&h?.length?(0,B.jsx)(`datalist`,{id:c,children:(g??h??[]).map(e=>(0,B.jsx)(`option`,{value:e},e))}):null,typeof e.description==`string`&&(0,B.jsx)(`span`,{className:`text-[10px] text-muted-foreground`,children:e.description})]})}var Y=`w-full min-w-0 rounded border border-border bg-background px-2 py-1 text-xs`,Ze=[`journal`,`change`,`maxTokens`,`maxTransitions`,`policies`];function Qe({graph:e,canvas:t,schema:n,onChange:r,onOpenCanvas:i}){let{t:o}=a(`loops`),[s,c]=(0,z.useState)(``),l=H(n.properties),u={type:`object`,additionalProperties:!1,properties:{...Object.fromEntries(Ze.filter(e=>l[e]).map(e=>[e,l[e]])),...H(H(l.budget).properties).maxTokens?{maxTokens:H(H(l.budget).properties).maxTokens}:{}}},d=Object.fromEntries(Object.entries(e.config).filter(([e])=>Ze.includes(e))),f=t?e.components?.[t]:void 0,p=t?[]:We(e);return(0,B.jsxs)(B.Fragment,{children:[!t&&(0,B.jsxs)(`label`,{className:`block space-y-1 text-xs`,children:[(0,B.jsx)(`span`,{children:o(`builder.core.reviewerStep`)}),(0,B.jsxs)(`select`,{className:Y,value:e.config.reviewerStepId??``,onChange:t=>r({...e,config:{...e.config,reviewerStepId:t.target.value||void 0}}),children:[(0,B.jsx)(`option`,{value:``,children:o(`builder.core.reviewerAutomatic`)}),e.config.reviewerStepId&&!p.includes(e.config.reviewerStepId)&&(0,B.jsx)(`option`,{value:e.config.reviewerStepId,children:e.config.reviewerStepId}),p.map(e=>(0,B.jsx)(`option`,{value:e,children:e},e))]}),(0,B.jsx)(`span`,{className:`block text-muted-foreground`,children:o(`builder.core.reviewerHint`)})]}),(0,B.jsx)(J,{schema:u,value:d,path:o(`builder.core.options`),onChange:t=>{let n=Object.fromEntries(Object.entries(e.config).filter(([e])=>!Ze.includes(e)));r({...e,config:{...n,...t}})}}),(0,B.jsxs)(`section`,{className:`space-y-2`,children:[(0,B.jsx)(`p`,{className:`text-xs font-semibold`,children:o(`builder.core.components`)}),(0,B.jsx)(`div`,{className:`flex flex-wrap gap-1`,children:Object.keys(e.components??{}).map(e=>(0,B.jsx)(`button`,{type:`button`,onClick:()=>i(e),className:`text-xs rounded border border-border px-2 py-1 hover:bg-muted`,children:e},e))}),(0,B.jsxs)(`div`,{className:`flex gap-1`,children:[(0,B.jsx)(`input`,{className:Y,value:s,"aria-label":o(`builder.core.componentName`),placeholder:o(`builder.core.componentName`),onChange:e=>c(e.target.value)}),(0,B.jsx)(`button`,{type:`button`,disabled:!/^[a-z][a-z0-9-]{0,63}$/.test(s)||!!e.components?.[s],onClick:()=>{i(s,!0),c(``)},"aria-label":o(`builder.core.addComponent`),className:`text-accent-primary disabled:opacity-40`,children:(0,B.jsx)(v,{className:`w-4 h-4`})})]}),f&&t&&(0,B.jsx)(J,{schema:{type:`object`,additionalProperties:!1,required:[`inputs`,`outputs`],properties:{inputs:{type:`array`,items:{type:`string`}},outputs:{type:`array`,items:{type:`string`}}}},value:{inputs:f.inputs??[],outputs:f.outputs??[`next`,`failed`]},path:t,onChange:n=>{r({...e,components:{...e.components,[t]:{...f,...n}}})}})]})]})}function $e({nodeId:e,data:t,piece:n,choices:r,schema:i,onChange:o,onDelete:s,onOpenCanvas:c}){let{t:l}=a(`loops`),u=t.params?.ref??t.params?.body,d=H(H(i.$defs).retry),f=n?.paramsSchema??{},p=t.coreKind===`assign`?{set:l(`builder.core.assignment.set`),increment:l(`builder.core.assignment.increment`)}:t.coreKind===`decider`?{continueWhen:l(`builder.core.requiredContinue`)}:{},m=Object.keys(p).length?{...f,properties:Object.fromEntries(Object.entries(H(f.properties)).map(([e,t])=>[e,p[e]?{...H(t),title:p[e]}:t]))}:f;return(0,B.jsxs)(`div`,{className:`space-y-3`,children:[(0,B.jsxs)(`div`,{className:`flex items-center justify-between`,children:[(0,B.jsx)(`h3`,{className:`text-sm font-semibold`,children:l(`builder.core.pieces.${t.coreKind}`)}),(0,B.jsx)(`button`,{type:`button`,onClick:s,"aria-label":l(`common:actions.delete`),className:`text-muted-foreground hover:text-destructive`,children:(0,B.jsx)(b,{className:`h-4 w-4`})})]}),(0,B.jsxs)(`label`,{className:`block text-xs`,children:[l(`builder.inspector.label`),(0,B.jsx)(`input`,{className:Y,value:String(t.label??``),onChange:e=>o({label:e.target.value})})]}),[`implementation`,`implementation-step`].includes(t.coreKind??``)&&(0,B.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:l(`builder.core.legacyImplementation`)}),n?(0,B.jsx)(J,{schema:m,value:t.params??{},onChange:e=>o({params:e}),choices:r},e):(0,B.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:l(`builder.core.unavailable`)}),[`component`,`map`].includes(t.coreKind)&&typeof u==`string`&&(0,B.jsx)(`button`,{type:`button`,className:`text-xs text-accent-primary`,onClick:()=>c(u),children:l(`builder.core.openComponent`)}),Object.keys(d).length>0&&(0,B.jsx)(J,{schema:d,value:t.retry??{},path:`retry`,onChange:e=>o({retry:e})})]})}function et(e){return e===`continue`||e===`stop`?e:void 0}function tt(e){switch(e){case`core`:return{kind:e,coreKind:`prompt`,params:{text:``,access:`write`,sessionContinuity:`run`}};case`ai-step`:return{kind:e,prompt:``,provider:`claude`,model:``,effort:`medium`,maxTurns:0};case`shell`:return{kind:e,command:``};case`decider`:return{kind:e,goal:``};case`condition`:return{kind:e,join:`AND`};case`end`:return{kind:e,outcome:`success`};default:return{kind:e}}}function nt(){return globalThis.crypto?.randomUUID?.()??`n-${Date.now()}-${Math.floor(Math.random()*1e9)}`}function rt(e,t){return{id:nt(),type:`loop`,position:t,data:tt(e)}}function it(e){let t=(e.nodes??[]).map(e=>({id:e.id,type:`loop`,position:e.position??{x:0,y:0},data:{...e.data??{},...e.type===`core`?{coreKind:e.data?.kind}:{},kind:e.type}})),n=new Map((e.nodes??[]).map(e=>[e.id,e.type]));return{nodes:t,edges:(e.edges??[]).map(e=>{let t=e.branch??(n.get(e.source)===`decider`?n.get(e.target)===`end`?`stop`:`continue`:void 0);return{id:e.id,source:e.source,target:e.target,sourceHandle:e.label??t??void 0,type:`smoothstep`,markerEnd:{type:je.ArrowClosed,width:16,height:16},label:e.label??e.join,data:{...e.join?{join:e.join}:{},...t?{branch:t}:{},...e.label?{label:e.label}:{}},...t?{style:{stroke:t===`stop`?`var(--color-accent-success)`:`var(--color-accent-highlight)`}}:{}}})}}function at(e,t,n,r){let i={...n};return i.legacyDeciderRole&&!e.some(e=>e.data.coreKind===`decider`&&e.data.params?.roleId===i.legacyDeciderRole)&&delete i.legacyDeciderRole,{nodes:e.map(e=>{let{kind:t,coreKind:n,...r}=e.data,i={id:e.id,type:t,position:e.position};return(Object.keys(r).length>0||n)&&(i.data={...r,...t===`core`?{kind:n}:{}}),i}),edges:t.map(t=>{let n=t.data?.join;if(e.find(e=>e.id===t.source)?.data.kind===`core`){let e=t.sourceHandle??t.data?.label;return{id:t.id,source:t.source,target:t.target,...e?{label:e}:{}}}let r=et(t.sourceHandle)??et(t.data?.branch);return{id:t.id,source:t.source,target:t.target,...n?{join:n}:{},...r?{branch:r}:{}}}),config:i,...r?{components:r}:{}}}var ot=`specrailsNodes`;function st(e,t){let n=e.filter(e=>e.selected);if(n.length===0)return null;let r=new Set(n.map(e=>e.id));return{specrailsNodes:1,nodes:n,edges:t.filter(e=>r.has(e.source)&&r.has(e.target))}}function ct(e){if(!e)return null;let t;try{t=JSON.parse(e)}catch{return null}let n=t;return!n||n[ot]==null||!Array.isArray(n.nodes)?null:{nodes:n.nodes,edges:Array.isArray(n.edges)?n.edges:[]}}function lt(e,t){let n=t.offset??{x:40,y:40},r=new Set(t.excludeKinds??[]),i=new Map;return{nodes:e.nodes.filter(e=>!r.has(String(e.data?.kind))).map(e=>{let r=t.mintId();return i.set(e.id,r),{...e,id:r,position:{x:e.position.x+n.x,y:e.position.y+n.y},selected:!0}}),edges:e.edges.filter(e=>i.has(e.source)&&i.has(e.target)).map(e=>({...e,id:t.mintId(),source:i.get(e.source),target:i.get(e.target),selected:!1}))}}function ut(e){return typeof e!=`string`||e.trim().length===0}function dt(e,t){let n=e.find(e=>e.data.kind===`start`),r=new Set;if(!n)return r;let i=new Map;for(let e of t)(i.get(e.source)??i.set(e.source,[]).get(e.source)).push(e.target);let a=[n.id];for(;a.length;){let e=a.shift();if(!r.has(e)){r.add(e);for(let t of i.get(e)??[])r.has(t)||a.push(t)}}return r}function ft(e,t){let n=[],r=e.filter(e=>e.data.kind===`start`);r.length===0&&n.push({severity:`error`,code:`NO_START`});for(let e of r.slice(1))n.push({severity:`error`,code:`MULTIPLE_START`,nodeId:e.id});if(e.some(e=>e.data.kind===`end`||e.data.kind===`core`&&e.data.coreKind===`end`)||n.push({severity:`error`,code:`NO_END`}),e.some(e=>e.data.kind===`core`)&&e.some(e=>![`start`,`core`,`end`].includes(e.data.kind))&&n.push({severity:`error`,code:`MIXED_ENGINES`}),r.length===1){let r=dt(e,t);for(let t of e)r.has(t.id)||n.push({severity:`error`,code:`ORPHAN`,nodeId:t.id})}let i=new Map;for(let e of t)(i.get(e.source)??i.set(e.source,[]).get(e.source)).push(e);for(let t of e){let e=i.get(t.id)??[];switch(t.data.kind){case`core`:{(!t.data.coreKind||!t.data.params||typeof t.data.params!=`object`||Array.isArray(t.data.params))&&n.push({severity:`error`,code:`CORE_PIECE`,nodeId:t.id});let r=e.map(e=>e.sourceHandle??e.data?.label);(t.data.coreKind===`end`?e.length>0:!r.length||r.some(e=>!e||!/^[a-z][a-z0-9-]{0,31}$/.test(e))||new Set(r).size!==r.length)&&n.push({severity:`error`,code:`CORE_OUTCOMES`,nodeId:t.id});break}case`decider`:{let r=new Set(e.map(e=>e.sourceHandle??e.data?.branch));(!r.has(`continue`)||!r.has(`stop`))&&n.push({severity:`error`,code:`DECIDER_BRANCHES`,nodeId:t.id}),ut(t.data.goal)&&n.push({severity:`warning`,code:`EMPTY_GOAL`,nodeId:t.id});break}case`ai-step`:ut(t.data.prompt)&&n.push({severity:`warning`,code:`EMPTY_PROMPT`,nodeId:t.id}),e.length===0&&n.push({severity:`warning`,code:`DEAD_END`,nodeId:t.id});break;case`shell`:ut(t.data.command)&&n.push({severity:`warning`,code:`EMPTY_COMMAND`,nodeId:t.id}),e.length===0&&n.push({severity:`warning`,code:`DEAD_END`,nodeId:t.id});break;case`start`:e.length===0&&n.push({severity:`warning`,code:`DEAD_END`,nodeId:t.id});break;default:break}}return n}function pt(e){let t=new Map;for(let n of e)n.nodeId&&(n.severity===`error`||!t.has(n.nodeId))&&t.set(n.nodeId,n.severity);return t}var mt=(0,z.createContext)(new Map),ht=(0,z.createContext)({pieces:[]}),gt=[`start`,`ai-step`,`shell`,`decider`,`end`],_t={core:pe,start:g,"ai-step":pe,shell:A,decider:h,condition:h,end:Ce},vt={core:`border-accent-primary/60`,start:`border-accent-success/60`,"ai-step":`border-accent-primary/60`,shell:`border-accent-warning/60`,decider:`border-accent-highlight/60`,condition:`border-accent-info/60`,end:`border-accent-secondary/60`};function yt({id:e,data:t,selected:n}){let{t:r}=a(`loops`),i=t.kind,o=_t[i]??_,s=String(t.label??``).trim(),c=(0,z.useContext)(mt).get(e),l=(0,z.useContext)(ht),u=Ke(l.pieces.find(e=>e.kind===t.coreKind),t.params??{},l.components),d=i===`core`?String(t.params?.roleId??t.params?.ref??t.params?.body??t.params?.text??t.params?.expr??``):i===`ai-step`?String(t.model||t.provider||``):i===`shell`?String(t.command||``):i===`decider`?String(t.goal||``):i===`condition`?String(t.join||`AND`):i===`end`?String(t.outcome||`success`):``;return(0,B.jsxs)(`div`,{className:w(`rounded-md border-2 bg-card px-3 py-2 min-w-[140px] shadow-sm`,vt[i],c===`error`?`ring-2 ring-destructive`:n?`ring-2 ring-accent-primary`:c===`warning`?`ring-2 ring-accent-warning`:``),children:[i!==`start`&&(0,B.jsx)(L,{type:`target`,position:R.Top}),(0,B.jsxs)(`div`,{className:`flex items-center gap-1.5`,children:[(0,B.jsx)(o,{className:`w-3.5 h-3.5 text-foreground flex-shrink-0`}),(0,B.jsx)(`span`,{className:`text-xs font-semibold text-foreground truncate max-w-[150px]`,children:s||r(i===`core`?`builder.core.pieces.${t.coreKind}`:`builder.nodes.${i}`)}),s&&(0,B.jsx)(`span`,{className:`text-[9px] text-muted-foreground/70 flex-shrink-0`,children:r(i===`core`?`builder.core.pieces.${t.coreKind}`:`builder.nodes.${i}`)})]}),d&&(0,B.jsx)(`p`,{className:`text-[10px] text-muted-foreground mt-1 truncate max-w-[160px]`,children:d}),i===`core`?(0,B.jsxs)(B.Fragment,{children:[(0,B.jsx)(`div`,{className:`flex justify-around gap-2 mt-2 text-[9px] text-accent-primary`,children:u.map(e=>(0,B.jsx)(`span`,{children:e},e))}),u.map((e,t)=>(0,B.jsx)(L,{id:e,type:`source`,position:R.Bottom,style:{left:`${(t+1)*100/(u.length+1)}%`},"aria-label":e},e))]}):i===`decider`?(0,B.jsxs)(B.Fragment,{children:[(0,B.jsxs)(`div`,{className:`mt-1.5 flex items-center justify-between gap-2 text-[9px] font-medium`,children:[(0,B.jsx)(`span`,{className:`text-accent-highlight`,children:r(`builder.branch.continue`)}),(0,B.jsx)(`span`,{className:`text-accent-success`,children:r(`builder.branch.stop`)})]}),(0,B.jsx)(L,{id:`continue`,type:`source`,position:R.Bottom,style:{left:`30%`},className:`!bg-accent-highlight`}),(0,B.jsx)(L,{id:`stop`,type:`source`,position:R.Bottom,style:{left:`70%`},className:`!bg-accent-success`})]}):i===`end`?null:(0,B.jsx)(L,{type:`source`,position:R.Bottom})]})}function bt({loopId:e,onExit:t,onWindowOpened:n}){let{t:o}=a(`loops`),u=i(),{id:d}=r(),h=e??d,g=(0,z.useCallback)(()=>{t?t():u(`/loops`)},[t,u]),_=Se(),{fitView:b,screenToFlowPosition:ne}=De(),{activeProjectId:E}=c(),[D,oe]=(0,z.useState)([]),[O,ue]=(0,z.useState)({}),[pe,me]=(0,z.useState)(!1),[k,he]=(0,z.useState)({}),[ge,A]=(0,z.useState)([]),[M,N]=(0,z.useState)(null),[P,ve]=(0,z.useState)(null);(0,z.useEffect)(()=>{let e=!1;return j.catalog().then(t=>{e||(oe(t.nodeKinds),ue(t.definitionSchema??{}),me(!1))}).catch(()=>{e||me(!0)}),()=>{e=!0}},[]),(0,z.useEffect)(()=>{let e=new AbortController;he({});let t=t=>fetch(t,{signal:e.signal}).then(e=>e.ok?e.json():null).catch(()=>null);return Promise.all([E&&M&&!M.config.agents?t(`${s()}/agent-runtime/config`):Promise.resolve(null),t(`/api/runtime-providers`)]).then(([t,n])=>{e.signal.aborted||he({providers:(t?.config?.providers??n?.providers??[]).map(e=>e.id),roles:[...new Set([...Object.keys(t?.config?.agents??{}),...Object.keys(t?.config?.roles??{}),...Object.keys(t?.workflowRoleDefaults??{})])],models:Object.fromEntries(Object.entries(n?.status??{}).map(([e,t])=>[e,t.models??[]]))})}),()=>e.abort()},[E,!!M,!!M?.config.agents]);let[F,I,Ce]=Ee([]),[L,R,Ne]=Fe([]),[V,ze]=(0,z.useState)(``),[Be,Ve]=(0,z.useState)(!1),[He,Ue]=(0,z.useState)(!1),[We,H]=(0,z.useState)(10),[U,W]=(0,z.useState)(30),[Ye,G]=(0,z.useState)(null),[K,q]=(0,z.useState)(null),[J,Y]=(0,z.useState)(!1);(0,z.useEffect)(()=>Y(!1),[h]);let[Ze,et]=(0,z.useState)(!0),[tt,ot]=(0,z.useState)(!1),[ut,dt]=(0,z.useState)(!1),[vt,bt]=(0,z.useState)(null),[xt,St]=(0,z.useState)(!1),X=(0,z.useMemo)(()=>[...ft(F,L),...ge.map(e=>({severity:`error`,code:`CORE_VALIDATION`,nodeId:e.nodeId,message:e.message}))],[F,L,ge]),Ct=(0,z.useMemo)(()=>pt(X),[X]),wt=X.filter(e=>e.severity===`error`).length,[Ot,kt]=(0,z.useState)(`manual`),At=(0,z.useRef)(new Map),[jt,Mt]=(0,z.useState)([]),[Nt,Pt]=(0,z.useState)(!1),Ft=(0,z.useCallback)(async()=>{try{Mt(await j.loopConstants())}catch{}},[]);(0,z.useEffect)(()=>{Ft()},[Ft]);let It=(0,z.useMemo)(()=>({loop:yt}),[]),Lt=(0,z.useCallback)(e=>{N(e.graph),ve(null);let{nodes:t,edges:n}=it(e.graph);At.current=new Map(t.map(e=>[e.id,{...e.position}]));let r=e.graph.config?.layout,i=r===`vertical`||r===`horizontal`||r===`grid`?r:`manual`;kt(i),I(i===`manual`?t:Pe(t,n,i)),R(n),ze(e.name),H(e.graph.config?.maxIterations??10),W(e.graph.config?.timeoutMinutes??30),G(typeof e.graph.config?.maxCostUsd==`number`?e.graph.config.maxCostUsd:null),Ve(!!e.builtinId)},[I,R]);(0,z.useEffect)(()=>{if(!h)return;let e=!1;return j.get(h).then(t=>{e||Lt(t)}).catch(()=>l.error(o(`errors.load`))).finally(()=>{e||et(!1)}),()=>{e=!0}},[h,Lt,o]);let Rt=(0,z.useCallback)(async()=>{if(h){Ue(!1);try{Lt(await j.restoreBuiltin(h)),A([]),l.success(o(`builder.builtin.restored`))}catch(e){l.error(e instanceof Error&&e.message?e.message:o(`errors.save`))}}},[h,Lt,o]),zt=(0,z.useCallback)(e=>{if(A([]),F.find(t=>t.id===e.source)?.data.kind===`core`){R(t=>Te({...e,label:e.sourceHandle,data:{label:e.sourceHandle}},t));return}let t=e.sourceHandle===`continue`||e.sourceHandle===`stop`?e.sourceHandle:void 0,n=t?{...e,data:{branch:t},style:{stroke:t===`stop`?`var(--color-accent-success)`:`var(--color-accent-highlight)`}}:e;R(e=>Te(n,e))},[R,F]),Bt=(0,z.useCallback)(e=>{if(!e.source||!e.target)return!1;let t=F.find(t=>t.id===e.source)?.data.kind,n=F.find(t=>t.id===e.target)?.data.kind;if(!t||!n||e.source===e.target&&t!==`core`||t===`end`)return!1;if(t===`core`){let t=F.find(t=>t.id===e.source),n=Ke(D.find(e=>e.kind===t.data.coreKind),t.data.params??{},M?.components);if(!e.sourceHandle||!n.includes(e.sourceHandle)||L.some(t=>t.source===e.source&&t.sourceHandle===e.sourceHandle))return!1}return!(t===`start`&&L.some(t=>t.source===e.source)||n===`start`)},[F,L,D,M]),Vt=(0,z.useCallback)(e=>{kt(e==="default"?`manual`:e),I(t=>e==="default"?t.map(e=>{let t=At.current.get(e.id);return t?{...e,position:{...t}}:e}):Pe(t,L,e)),requestAnimationFrame(()=>b({padding:.25,maxZoom:.85,duration:300}))},[I,L,b]),Ht=(0,z.useCallback)(e=>{e.some(e=>e.type===`position`&&e.dragging===!1)&&kt(`manual`),Ce(e)},[Ce]),Ut=(0,z.useRef)(F);Ut.current=F;let Wt=(0,z.useRef)(L);Wt.current=L,(0,z.useEffect)(()=>{let e=()=>{let e=window.document.activeElement;return!!e&&(e.tagName===`INPUT`||e.tagName===`TEXTAREA`||e.isContentEditable)},t=t=>{if(e())return;let n=st(Ut.current,Wt.current);!n||!t.clipboardData||(t.clipboardData.setData(`text/plain`,JSON.stringify(n)),t.preventDefault())},n=t=>{if(e())return;let n=ct(t.clipboardData?.getData(`text/plain`)??``);if(!n)return;t.preventDefault();let r=lt(n,{mintId:nt,offset:{x:40,y:40},excludeKinds:Ut.current.some(e=>e.data.kind===`start`)?[`start`]:[]});r.nodes.length!==0&&(I(e=>[...e.map(e=>({...e,selected:!1})),...r.nodes]),R(e=>[...e,...r.edges]),kt(`manual`),l.success(o(`builder.paste.done`,{count:r.nodes.length})))};return window.addEventListener(`copy`,t),window.addEventListener(`paste`,n),()=>{window.removeEventListener(`copy`,t),window.removeEventListener(`paste`,n)}},[I,R,o]);let Gt=(0,z.useCallback)(e=>{let t=rt(e,{x:120+Math.random()*120,y:80+Math.random()*240});I(e=>[...e,t]),Y(!1),q(t.id)},[I]),Kt=(0,z.useCallback)(e=>{A([]),I(t=>t.map(t=>t.id===K?{...t,data:{...t.data,...e}}:t))},[K,I]),qt=(0,z.useCallback)(()=>{K&&(I(e=>e.filter(e=>e.id!==K)),R(e=>e.filter(e=>e.source!==K&&e.target!==K)),q(null))},[K,I,R]),Z=!!M&&!F.some(e=>![`start`,`core`,`end`].includes(e.data.kind)),Q=(0,z.useCallback)(()=>{let e={...M?.config,maxIterations:We,timeoutMinutes:U,maxCostUsd:Ye??void 0,layout:Ot},t=P?M?.components?.[P]:M,n={...t,...at(F,L,P?t?.config??e:e)};return P?{...M,config:e,components:{...M?.components,[P]:n}}:{...n,components:M?.components}},[M,P,F,L,We,U,Ye,Ot]),Jt=(0,z.useCallback)((e,t=!1)=>{let n=Q();e&&t&&!n.components?.[e]&&(n.components={...n.components,[e]:{nodes:[{id:nt(),type:`start`,position:{x:160,y:40}},{id:nt(),type:`core`,position:{x:160,y:220},data:{kind:`end`,params:{outcome:`success`}}}],edges:[],config:{maxIterations:10,timeoutMinutes:0},inputs:[],outputs:[`next`,`failed`]}});let r=e?n.components?.[e]:n;if(!r)return;let i=it(r);N(n),ve(e),I(i.nodes),R(i.edges),q(null),A([]),requestAnimationFrame(()=>b({padding:.25}))},[Q,I,R,b]),Yt=(0,z.useCallback)((e,t)=>{let n={id:nt(),type:`loop`,position:t??{x:160+F.length*20,y:100+F.length*30},data:Ge(e)};if(e.kind===`role-turn`&&M){let e=k.providers?.[0]??`claude`,t=(`agent-`+n.id.replace(/[^a-z0-9-]/g,`-`)).slice(0,64),r=M.config.agents??{schemaVersion:1,agents:{architect:{provider:e},developer:{provider:e},reviewer:{provider:e}}};n.data.params={roleId:t,prompt:o(`builder.core.agentTaskDefault`)},N({...M,config:{...M.config,agents:{...r,roles:{...r.roles,[t]:{provider:e,access:`write`,artifacts:`none`,prompt:``}}}}})}e.kind===`prompt`&&k.providers?.length&&(n.data.params.engine={provider:k.providers[0]}),I(e=>[...e,n]),Y(!1),q(n.id)},[F.length,I,k.providers,M,o]),Xt=(0,z.useCallback)(async()=>{St(!0);try{let e=Q(),{steps:t}=await j.previewLoop(e);bt(t)}catch{l.error(o(`builder.preview.error`))}finally{St(!1)}},[Q,o]),Zt=(0,z.useCallback)(async()=>{if(!h)return!1;ot(!0);try{let e=Q();return await j.update(h,{name:V,graph:e}),!0}catch(e){return l.error(e instanceof Error&&e.message?e.message:o(`errors.save`)),!1}finally{ot(!1)}},[h,Q,V,o]),Qt=(0,z.useCallback)(async()=>{if(h&&await Zt())try{await j.publish(h),l.success(o(`builder.published`)),g()}catch(e){e instanceof xe?(A(e.errors),dt(!0),l.error(o(`errors.publishInvalid`))):l.error(e instanceof Error&&e.message?e.message:o(`errors.save`))}},[h,Zt,g,o]),$=F.find(e=>e.id===K)??null;return(0,B.jsx)(mt.Provider,{value:Ct,children:(0,B.jsx)(ht.Provider,{value:{pieces:D,components:M?.components},children:(0,B.jsxs)(`div`,{className:`h-full flex flex-col`,children:[(0,B.jsxs)(`div`,{className:`flex items-center justify-between gap-3 px-4 h-12 border-b border-border flex-shrink-0`,children:[(0,B.jsxs)(`div`,{className:`flex items-center gap-2 min-w-0`,children:[(0,B.jsx)(`button`,{type:`button`,onClick:g,className:`text-muted-foreground hover:text-foreground`,"aria-label":o(`builder.back`),children:(0,B.jsx)(f,{className:`w-4 h-4`})}),(0,B.jsx)(`input`,{value:V,onChange:e=>ze(e.target.value),className:`text-sm font-semibold bg-transparent text-foreground border-b border-transparent focus:border-border focus:outline-none min-w-0`,"aria-label":`name`})]}),(0,B.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,B.jsxs)(se,{delayDuration:150,children:[(0,B.jsxs)(`label`,{className:`text-[10px] text-muted-foreground flex items-center gap-1`,children:[o(`builder.config.maxIterations`),(0,B.jsxs)(ce,{children:[(0,B.jsx)(fe,{asChild:!0,children:(0,B.jsx)(`button`,{type:`button`,onClick:e=>e.preventDefault(),className:`text-muted-foreground/60 hover:text-foreground`,"aria-label":o(`builder.config.maxIterations`),children:(0,B.jsx)(le,{className:`w-3 h-3`})})}),(0,B.jsx)(ye,{className:`max-w-xs leading-relaxed`,children:o(`builder.config.maxIterationsHint`)})]}),(0,B.jsx)(`input`,{type:`number`,min:1,value:We,onChange:e=>H(Math.max(1,Number(e.target.value)||1)),className:`w-14 h-6 text-xs rounded border border-border bg-transparent px-1 text-foreground`})]}),(0,B.jsxs)(`label`,{className:`text-[10px] text-muted-foreground flex items-center gap-1`,children:[o(`builder.config.timeout`),(0,B.jsxs)(ce,{children:[(0,B.jsx)(fe,{asChild:!0,children:(0,B.jsx)(`button`,{type:`button`,onClick:e=>e.preventDefault(),className:`text-muted-foreground/60 hover:text-foreground`,"aria-label":o(`builder.config.timeout`),children:(0,B.jsx)(le,{className:`w-3 h-3`})})}),(0,B.jsx)(ye,{className:`max-w-xs leading-relaxed`,children:o(`builder.config.timeoutHint`)})]}),(0,B.jsx)(`input`,{type:`number`,min:0,"aria-label":o(`builder.config.timeout`),value:U,onChange:e=>W(Math.max(0,Number(e.target.value)||0)),className:`w-14 h-6 text-xs rounded border border-border bg-transparent px-1 text-foreground`})]}),(0,B.jsxs)(`label`,{className:`text-[10px] text-muted-foreground flex items-center gap-1`,children:[o(`builder.config.maxCost`),(0,B.jsxs)(ce,{children:[(0,B.jsx)(fe,{asChild:!0,children:(0,B.jsx)(`button`,{type:`button`,onClick:e=>e.preventDefault(),className:`text-muted-foreground/60 hover:text-foreground`,"aria-label":o(`builder.config.maxCost`),children:(0,B.jsx)(le,{className:`w-3 h-3`})})}),(0,B.jsx)(ye,{className:`max-w-xs leading-relaxed`,children:o(`builder.config.maxCostHint`)})]}),(0,B.jsx)(`input`,{type:`number`,min:0,step:.5,placeholder:`∞`,value:Ye??``,onChange:e=>{let t=Number(e.target.value);G(e.target.value===``||!(t>0)?null:t)},className:`w-16 h-6 text-xs rounded border border-border bg-transparent px-1 text-foreground`})]})]}),Z&&(0,B.jsx)(`button`,{type:`button`,"aria-pressed":J,onClick:()=>Y(e=>!e),className:`inline-flex items-center gap-1.5 h-7 px-2.5 rounded-md text-xs border border-border hover:bg-muted text-foreground`,children:o(`builder.loopSettings`)}),Be&&(0,B.jsxs)(`button`,{type:`button`,onClick:()=>Ue(!0),disabled:tt,"data-testid":`builder-restore-builtin`,className:`inline-flex items-center gap-1.5 h-7 px-2.5 rounded-md text-xs border border-border hover:bg-muted text-foreground disabled:opacity-50`,children:[(0,B.jsx)(y,{className:`w-3 h-3`}),` `,o(`actions.restoreBuiltin`)]}),(0,B.jsxs)(`button`,{type:`button`,onClick:()=>void Xt(),disabled:xt,className:`inline-flex items-center gap-1.5 h-7 px-2.5 rounded-md text-xs border border-border hover:bg-muted text-foreground disabled:opacity-50`,children:[(0,B.jsx)(de,{className:`w-3 h-3`}),` `,o(`builder.preview.label`)]}),!be()&&(0,B.jsxs)(`button`,{type:`button`,disabled:tt,onClick:()=>void Zt().then(async e=>{if(!(!e||!h))try{await _e(E,h),n?n():g()}catch(e){l.error(String(e))}}),className:`inline-flex items-center gap-1.5 h-7 px-2.5 rounded-md text-xs border border-border hover:bg-muted disabled:opacity-50`,children:[(0,B.jsx)(m,{className:`w-3 h-3`}),o(`window.open`)]}),(0,B.jsxs)(`button`,{type:`button`,onClick:()=>void Zt().then(e=>e&&l.success(o(`builder.saved`))),disabled:tt,className:`inline-flex items-center gap-1.5 h-7 px-2.5 rounded-md text-xs border border-border hover:bg-muted text-foreground disabled:opacity-50`,children:[(0,B.jsx)(p,{className:`w-3 h-3`}),` `,o(`builder.save`)]}),(0,B.jsxs)(`button`,{type:`button`,onClick:()=>void Qt(),disabled:tt,className:`inline-flex items-center gap-1.5 h-7 px-2.5 rounded-md text-xs bg-accent-primary text-white hover:bg-accent-primary/90 disabled:opacity-50`,children:[(0,B.jsx)(te,{className:`w-3 h-3`}),` `,o(`builder.publish`)]})]})]}),Be&&(0,B.jsx)(`div`,{role:`note`,"data-testid":`builder-builtin-note`,className:`px-4 py-1.5 border-b border-border bg-accent-info/10 text-[11px] text-accent-info flex-shrink-0`,children:o(`builder.builtin.note`)}),(0,B.jsx)(ae,{open:He,onOpenChange:e=>{e||Ue(!1)},children:(0,B.jsxs)(C,{className:`max-w-sm`,children:[(0,B.jsxs)(ie,{children:[(0,B.jsx)(S,{children:o(`builder.builtin.confirmTitle`)}),(0,B.jsx)(re,{children:o(`builder.builtin.confirmBody`)})]}),(0,B.jsxs)(x,{children:[(0,B.jsx)(T,{variant:`ghost`,onClick:()=>Ue(!1),children:o(`common:actions.cancel`)}),(0,B.jsx)(T,{"data-testid":`builder-restore-confirm`,onClick:()=>void Rt(),children:o(`actions.restoreBuiltin`)})]})]})}),(0,B.jsxs)(`div`,{className:`flex-1 flex min-h-0`,children:[(0,B.jsxs)(`div`,{className:`w-44 border-r border-border p-2 space-y-1 flex-shrink-0 overflow-y-auto`,children:[(0,B.jsx)(`p`,{className:`text-[10px] font-semibold uppercase tracking-wide text-muted-foreground px-1 mb-1`,children:o(`builder.addNode`)}),Z&&pe&&(0,B.jsx)(`p`,{role:`status`,className:`text-xs text-muted-foreground px-1`,children:o(`builder.core.unavailable`)}),Z&&D.length>0&&[`ai`,`verification`,`openspec`,`control`].map(e=>(0,B.jsxs)(`div`,{className:`pt-2`,children:[(0,B.jsx)(`p`,{className:`text-[10px] uppercase text-muted-foreground px-1`,children:o(`builder.core.groups.${e}`)}),D.filter(t=>![`implementation`,`implementation-step`].includes(t.kind)&&qe(t.kind)===e).map(e=>(0,B.jsxs)(`button`,{type:`button`,draggable:!0,onDragStart:t=>{t.dataTransfer.setData(`application/specrails-core-piece`,e.kind),t.dataTransfer.effectAllowed=`copy`},onClick:()=>Yt(e),className:`flex items-center gap-2 w-full min-h-8 px-2 rounded text-left text-xs hover:bg-muted focus-visible:ring-2 focus-visible:ring-accent-primary`,children:[(0,B.jsx)(v,{className:`h-3 w-3 flex-shrink-0`}),o(`builder.core.pieces.${e.kind}`)]},e.kind))]},e)),(Z?[`start`]:gt).map(e=>{let t=_t[e];return(0,B.jsxs)(`button`,{type:`button`,onClick:()=>Gt(e),disabled:e===`start`&&F.some(e=>e.data.kind===`start`),className:`flex items-center gap-2 w-full h-8 px-2 rounded-md text-xs text-muted-foreground hover:text-foreground hover:bg-muted/50`,children:[(0,B.jsx)(t,{className:`w-3.5 h-3.5 flex-shrink-0`}),(0,B.jsx)(`span`,{className:`truncate`,children:o(`builder.nodes.${e}`)}),(0,B.jsx)(v,{className:`w-3 h-3 ml-auto opacity-50`})]},e)})]}),(0,B.jsx)(`div`,{className:`flex-1 min-w-0 relative`,onDragOver:e=>{e.dataTransfer.types.includes(`application/specrails-core-piece`)&&(e.preventDefault(),e.dataTransfer.dropEffect=`copy`)},onDrop:e=>{let t=D.find(t=>t.kind===e.dataTransfer.getData(`application/specrails-core-piece`));!t||!Z||(e.preventDefault(),Yt(t,ne({x:e.clientX,y:e.clientY})))},children:Ze?(0,B.jsx)(`div`,{className:`flex items-center justify-center h-full`,children:(0,B.jsx)(`p`,{className:`text-sm text-muted-foreground`,children:`…`})}):(0,B.jsxs)(Oe,{nodes:F,edges:L,onNodesChange:Ht,onEdgesChange:Ne,onConnect:zt,isValidConnection:Bt,onNodeClick:(e,t)=>{Y(!1),q(t.id)},onPaneClick:()=>{Y(!1),q(null)},nodeTypes:It,colorMode:_.scheme===`dark`?`dark`:`light`,fitView:!0,fitViewOptions:{padding:.25,maxZoom:.85},minZoom:.2,defaultEdgeOptions:{type:`smoothstep`,markerEnd:{type:je.ArrowClosed,width:16,height:16}},proOptions:{hideAttribution:!0},children:[Z&&(0,B.jsx)(Ae,{position:`top-center`,children:(0,B.jsxs)(`nav`,{className:`flex items-center gap-1 rounded border border-border bg-card/95 p-1 text-xs`,"aria-label":o(`builder.core.breadcrumbs`),children:[(0,B.jsx)(`button`,{type:`button`,onClick:()=>Jt(null),className:`px-2 py-1 hover:bg-muted`,children:V||o(`builder.core.root`)}),P&&(0,B.jsxs)(`span`,{"aria-current":`page`,children:[`/ `,P]})]})}),(0,B.jsx)(ke,{}),(0,B.jsx)(Me,{}),(0,B.jsx)(we,{pannable:!0,zoomable:!0}),(0,B.jsx)(Ae,{position:`top-left`,children:(0,B.jsx)(`div`,{className:`flex items-center gap-0.5 rounded-md border border-border bg-card/90 backdrop-blur p-0.5`,role:`group`,"aria-label":o(`builder.arrange.label`),children:[[`vertical`,Re],[`horizontal`,Le],[`grid`,Ie],[`default`,y]].map(([e,t])=>{let n=e==="default"?`reset`:e,r=e==="default"?Ot===`manual`:Ot===e;return(0,B.jsx)(`button`,{type:`button`,title:o(`builder.arrange.${n}`),"aria-label":o(`builder.arrange.${n}`),"aria-pressed":r,onClick:()=>Vt(e),className:w(`inline-flex items-center justify-center w-7 h-7 rounded hover:bg-muted`,r?`bg-muted text-accent-primary`:`text-muted-foreground hover:text-foreground`),children:(0,B.jsx)(t,{className:`w-3.5 h-3.5`})},e)})})}),(0,B.jsx)(Ae,{position:`top-right`,children:(0,B.jsx)(se,{delayDuration:150,children:(0,B.jsxs)(ce,{children:[(0,B.jsx)(fe,{asChild:!0,children:(0,B.jsxs)(`button`,{type:`button`,className:`inline-flex items-center gap-1 h-6 px-2 rounded-md text-[10px] border border-border bg-card/90 text-muted-foreground hover:text-foreground backdrop-blur`,children:[(0,B.jsx)(le,{className:`w-3 h-3`}),o(`builder.edgesHelp.label`)]})}),(0,B.jsx)(ye,{className:`max-w-xs leading-relaxed`,children:o(`builder.edgesHelp.body`)})]})})}),X.length>0&&(0,B.jsx)(Ae,{position:`bottom-center`,children:(0,B.jsxs)(`div`,{className:`rounded-md border border-border bg-card/95 backdrop-blur text-xs overflow-hidden max-w-md mb-2`,children:[(0,B.jsxs)(`button`,{type:`button`,onClick:()=>dt(e=>!e),className:w(`flex items-center gap-1.5 w-full px-2.5 py-1.5 font-medium`,wt>0?`text-destructive`:`text-accent-warning`),children:[(0,B.jsx)(ee,{className:`w-3.5 h-3.5`}),o(`builder.problems.count`,{count:X.length})]}),ut&&(0,B.jsx)(`ul`,{className:`border-t border-border max-h-40 overflow-y-auto py-1`,children:X.map((e,t)=>(0,B.jsx)(`li`,{children:(0,B.jsxs)(`button`,{type:`button`,disabled:!e.nodeId,onClick:()=>{e.nodeId&&(Y(!1),q(e.nodeId))},className:`flex items-start gap-1.5 w-full text-left px-2.5 py-1 hover:bg-muted disabled:cursor-default`,children:[(0,B.jsx)(`span`,{className:w(`mt-1 w-1.5 h-1.5 rounded-full flex-shrink-0`,e.severity===`error`?`bg-destructive`:`bg-accent-warning`)}),(0,B.jsx)(`span`,{className:`text-foreground`,children:`message`in e?String(e.message):o(`builder.problems.${e.code}`)})]})},`${e.code}-${e.nodeId??t}`))})]})})]})}),(0,B.jsxs)(`div`,{className:`w-80 border-l border-border p-3 flex-shrink-0 overflow-y-auto space-y-4`,children:[!J&&($?$.data.kind===`core`?(0,B.jsx)($e,{nodeId:$.id,data:$.data,piece:D.find(e=>e.kind===$.data.coreKind),choices:{...k,roles:M?.config.agents?[...Object.keys(M.config.agents.agents),...Object.keys(M.config.agents.roles??{})]:k.roles,components:Object.keys(M?.components??{})},schema:O,onChange:Kt,onDelete:qt,onOpenCanvas:Jt}):(0,B.jsx)(Dt,{data:$.data,onChange:Kt,onDelete:qt,constants:jt,onManageConstants:()=>Pt(!0)}):(0,B.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:o(`builder.inspector.selectNode`)})),!J&&Z&&M&&$&&(Je($.id,$.data.coreKind,$.data.params??{}).length>0||$.data.coreKind===`implementation-step`&&$.data.params?.phase===`archive`)&&(0,B.jsx)(Xe,{mode:$.data.coreKind===`implementation`?`all`:`step`,graph:Q(),value:M.config.agents,selectedRole:String($.data.params?.phase??Je($.id,$.data.coreKind,$.data.params??{})[0]??``),onChange:e=>N({...M,config:{...M.config,agents:e}})},`${h}:${$.id}`),J&&Z&&M&&(0,B.jsx)(Xe,{mode:`workflow`,graph:Q(),value:M.config.agents,selectedRole:$?Je($.id,$.data.coreKind,$.data.params??{})[0]:void 0,onChange:e=>N({...M,config:{...M.config,agents:e}})},h),J&&Z&&M&&(0,B.jsx)(Qe,{graph:M,canvas:P,schema:O,onChange:N,onOpenCanvas:Jt})]})]}),(0,B.jsx)(Tt,{open:Nt,onClose:()=>Pt(!1),constants:jt,onChanged:Ft,t:o}),(0,B.jsx)(Et,{steps:vt,onClose:()=>bt(null),t:o})]})})})}var xt=[{labelKey:`builder.inspector.tokensSpec`,tokens:[{token:`{{spec.title}}`,label:`spec.title`},{token:`{{spec.description}}`,label:`spec.description`},{token:`{{spec.id}}`,label:`spec.id`},{token:`{{spec.status}}`,label:`spec.status`},{token:`{{spec.priority}}`,label:`spec.priority`},{token:`{{spec.labels}}`,label:`spec.labels`}]},{labelKey:`builder.inspector.tokensJira`,tokens:[{token:`{{spec.jira_key}}`,label:`spec.jira_key`},{token:`{{spec.jira_url}}`,label:`spec.jira_url`}]}];function St({token:e,label:t,description:n,onInsert:r}){return(0,B.jsx)(`button`,{type:`button`,draggable:!0,onDragStart:t=>t.dataTransfer.setData(`text/plain`,e),onClick:()=>r(e),title:n?`${e} — ${n}`:e,className:`px-1.5 py-0.5 rounded border border-border bg-surface/40 text-[10px] font-mono text-accent-primary hover:bg-accent-primary/10 cursor-grab active:cursor-grabbing`,children:t})}function X({t:e,onInsert:t}){let[n,r]=(0,z.useState)([]);return(0,z.useEffect)(()=>{let e=!1;return j.loopCommands().then(t=>{e||r(t)}).catch(()=>{}),()=>{e=!0}},[]),(0,B.jsxs)(`div`,{className:`mb-2 space-y-1.5`,children:[xt.map(n=>(0,B.jsxs)(`div`,{children:[(0,B.jsx)(`span`,{className:`block text-[9px] uppercase tracking-wide text-muted-foreground/70 mb-0.5`,children:e(n.labelKey)}),(0,B.jsx)(`div`,{className:`flex flex-wrap gap-1`,children:n.tokens.map(e=>(0,B.jsx)(St,{token:e.token,label:e.label,onInsert:t},e.token))})]},n.labelKey)),n.length>0&&(0,B.jsxs)(`div`,{children:[(0,B.jsx)(`span`,{className:`block text-[9px] uppercase tracking-wide text-muted-foreground/70 mb-0.5`,children:e(`builder.inspector.tokensCommands`)}),(0,B.jsx)(`div`,{className:`flex flex-wrap gap-1`,children:n.map(e=>(0,B.jsx)(St,{token:`{{cmd:${e.name}}}`,label:`⚡ ${e.label}`,description:e.description,onInsert:t},e.name))})]})]})}function Ct({t:e,constants:t,onInsert:n,onManage:r}){return(0,B.jsxs)(`div`,{className:`mb-2`,children:[(0,B.jsxs)(`div`,{className:`flex items-center justify-between mb-0.5`,children:[(0,B.jsx)(`span`,{className:`text-[9px] uppercase tracking-wide text-muted-foreground/70`,children:e(`builder.constants.label`)}),(0,B.jsx)(`button`,{type:`button`,onClick:r,title:e(`builder.constants.manage`),"aria-label":e(`builder.constants.manage`),className:`text-muted-foreground hover:text-foreground`,children:(0,B.jsx)(I,{className:`w-3 h-3`})})]}),(0,B.jsx)(`div`,{className:`flex flex-wrap gap-1`,children:t.map(e=>(0,B.jsx)(St,{token:`{{const:${e.name}}}`,label:e.builtin?`🔒 ${e.name}`:e.name,description:e.value,onInsert:n},e.id))})]})}function wt({c:e,onSave:t,onDelete:n}){let[r,i]=(0,z.useState)(e.value);return(0,B.jsxs)(`div`,{className:`flex items-center gap-1.5`,children:[(0,B.jsx)(`code`,{className:`text-[10px] font-mono text-accent-primary w-28 truncate`,title:e.name,children:e.name}),(0,B.jsx)(`input`,{className:`flex-1 text-xs rounded border border-border bg-transparent px-2 py-1 text-foreground`,value:r,onChange:e=>i(e.target.value)}),(0,B.jsx)(`button`,{type:`button`,disabled:r===e.value||!r,onClick:()=>t(r),className:`text-muted-foreground hover:text-foreground disabled:opacity-40`,"aria-label":`save`,children:(0,B.jsx)(p,{className:`w-3.5 h-3.5`})}),(0,B.jsx)(`button`,{type:`button`,onClick:n,className:`text-muted-foreground hover:text-destructive`,"aria-label":`delete`,children:(0,B.jsx)(b,{className:`w-3.5 h-3.5`})})]})}function Tt({open:e,onClose:t,constants:n,onChanged:r,t:i}){let[a,o]=(0,z.useState)(``),[s,c]=(0,z.useState)(``),[l,u]=(0,z.useState)(null),[d,f]=(0,z.useState)(!1),p=n.filter(e=>e.builtin),m=n.filter(e=>!e.builtin),h=async()=>{f(!0),u(null);try{await j.createConstant(a.trim(),s),o(``),c(``),await r()}catch(e){u(e instanceof Error?e.message:`error`)}finally{f(!1)}},g=`text-xs rounded border border-border bg-transparent px-2 py-1 text-foreground focus:outline-none focus:ring-1 focus:ring-accent-primary/40`;return(0,B.jsx)(ae,{open:e,onOpenChange:e=>{e||t()},children:(0,B.jsxs)(C,{className:`max-w-md`,children:[(0,B.jsx)(ie,{children:(0,B.jsx)(S,{children:i(`builder.constants.title`)})}),(0,B.jsxs)(`div`,{className:`space-y-3`,children:[(0,B.jsxs)(`div`,{className:`space-y-1.5`,children:[m.length===0&&(0,B.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:i(`builder.constants.empty`)}),m.map(e=>(0,B.jsx)(wt,{c:e,onSave:t=>void j.updateConstant(e.id,t).then(r),onDelete:()=>void j.deleteConstant(e.id).then(r)},e.id))]}),(0,B.jsxs)(`div`,{className:`flex items-center gap-1.5 border-t border-border pt-2`,children:[(0,B.jsx)(`input`,{className:`${g} w-28`,placeholder:i(`builder.constants.name`),value:a,onChange:e=>o(e.target.value)}),(0,B.jsx)(`input`,{className:`${g} flex-1`,placeholder:i(`builder.constants.value`),value:s,onChange:e=>c(e.target.value)}),(0,B.jsx)(T,{size:`sm`,disabled:d||!a.trim()||!s,onClick:()=>void h(),children:i(`builder.constants.add`)})]}),l&&(0,B.jsx)(`p`,{className:`text-[10px] text-destructive`,children:l}),p.length>0&&(0,B.jsxs)(`div`,{className:`border-t border-border pt-2 space-y-1`,children:[(0,B.jsx)(`span`,{className:`text-[9px] uppercase tracking-wide text-muted-foreground/70`,children:i(`builder.constants.builtinBadge`)}),p.map(e=>(0,B.jsxs)(`div`,{className:`flex items-center gap-1.5 text-[10px]`,children:[(0,B.jsx)(`code`,{className:`font-mono text-accent-primary w-28 truncate`,title:e.name,children:e.name}),(0,B.jsx)(`span`,{className:`text-muted-foreground truncate`,children:e.value})]},e.id))]})]}),(0,B.jsx)(x,{children:(0,B.jsx)(T,{variant:`ghost`,onClick:t,children:i(`common:actions.close`)})})]})})}function Et({steps:e,onClose:t,t:n}){return(0,B.jsx)(ae,{open:e!==null,onOpenChange:e=>{e||t()},children:(0,B.jsxs)(C,{className:`max-w-2xl`,children:[(0,B.jsx)(ie,{children:(0,B.jsx)(S,{children:n(`builder.preview.title`)})}),(0,B.jsx)(`p`,{className:`text-[11px] text-muted-foreground`,children:n(`builder.preview.sampleNote`)}),(0,B.jsxs)(`div`,{className:`space-y-2 max-h-[60vh] overflow-y-auto`,children:[e&&e.length===0&&(0,B.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:n(`builder.preview.empty`)}),e?.map((e,t)=>(0,B.jsxs)(`div`,{className:`rounded-md border border-border`,children:[(0,B.jsxs)(`div`,{className:`px-2.5 py-1 text-[10px] border-b border-border flex items-center gap-1.5`,children:[(0,B.jsx)(`span`,{className:`font-medium text-foreground`,children:e.label||n([`start`,`end`,`ai-step`,`shell`,`decider`,`condition`].includes(e.kind)?`builder.nodes.${e.kind}`:`builder.core.pieces.${e.kind}`)}),(0,B.jsxs)(`span`,{className:`text-muted-foreground`,children:[`· `,n([`start`,`end`,`ai-step`,`shell`,`decider`,`condition`].includes(e.kind)?`builder.nodes.${e.kind}`:`builder.core.pieces.${e.kind}`)]})]}),(0,B.jsx)(`pre`,{className:`px-2.5 py-2 text-[11px] text-foreground whitespace-pre-wrap break-words font-mono`,children:e.text||`—`})]},`${e.nodeId}-${t}`))]}),(0,B.jsx)(x,{children:(0,B.jsx)(T,{variant:`ghost`,onClick:t,children:n(`common:actions.close`)})})]})})}function Dt({data:e,onChange:t,onDelete:n,constants:r,onManageConstants:i}){let{t:o}=a(`loops`),{activeProjectId:s,projects:l}=c(),u=D(l.find(e=>e.id===s)),d=e.kind,f=`block text-[10px] font-medium text-muted-foreground mb-1`,p=`w-full text-xs rounded border border-border bg-transparent px-2 py-1 text-foreground focus:outline-none focus:ring-1 focus:ring-accent-primary/40`,m=(0,z.useRef)(null),h=(0,z.useRef)(null),g=(n,r,i)=>{let a=n.current,o=String(e[r]??``);if(!a){t({[r]:o+i});return}let s=a.selectionStart??o.length,c=a.selectionEnd??o.length;t({[r]:o.slice(0,s)+i+o.slice(c)}),requestAnimationFrame(()=>{a.focus();let e=s+i.length;a.setSelectionRange(e,e)})},_=e=>g(m,`prompt`,e);return(0,B.jsxs)(`div`,{className:`space-y-3`,children:[(0,B.jsxs)(`div`,{className:`flex items-center justify-between`,children:[(0,B.jsx)(`span`,{className:`text-xs font-semibold text-foreground`,children:o(`builder.nodes.${d}`)}),(0,B.jsx)(`button`,{type:`button`,onClick:n,"aria-label":o(`builder.deleteNode`),className:`text-muted-foreground hover:text-destructive`,children:(0,B.jsx)(b,{className:`w-3.5 h-3.5`})})]}),(0,B.jsxs)(`div`,{children:[(0,B.jsx)(`label`,{className:f,children:o(`builder.inspector.label`)}),(0,B.jsx)(`input`,{className:p,value:String(e.label??``),onChange:e=>t({label:e.target.value}),placeholder:o(`builder.nodes.${d}`)})]}),d===`ai-step`&&(0,B.jsxs)(`div`,{children:[(0,B.jsx)(`label`,{className:f,children:o(`builder.inspector.prompt`)}),(0,B.jsx)(X,{t:o,onInsert:_}),(0,B.jsx)(Ct,{t:o,constants:r,onInsert:_,onManage:i}),(0,B.jsx)(`textarea`,{ref:m,rows:7,className:p,value:String(e.prompt??``),onChange:e=>t({prompt:e.target.value})}),(0,B.jsx)(`p`,{className:`text-[10px] text-muted-foreground mt-1`,children:o(`builder.inspector.promptHint`)})]}),d===`shell`&&(0,B.jsxs)(`div`,{children:[(0,B.jsx)(`label`,{className:f,children:o(`builder.inspector.command`)}),(0,B.jsx)(`input`,{className:p,value:String(e.command??``),onChange:e=>t({command:e.target.value}),placeholder:`npm test`}),(0,B.jsxs)(`label`,{className:`${f} mt-3`,children:[o(`common:repositories.shellTarget`),(0,B.jsxs)(`select`,{className:p,value:String(e.repositoryId??``),onChange:e=>t({repositoryId:e.target.value||void 0}),children:[(0,B.jsx)(`option`,{value:``,children:o(`common:repositories.shellDefault`)}),u.filter(e=>e.kind===`git`).map(e=>(0,B.jsx)(`option`,{value:e.id,children:e.name},e.id)),!!e.repositoryId&&!u.some(t=>t.id===e.repositoryId)&&(0,B.jsx)(`option`,{value:String(e.repositoryId),children:String(e.repositoryId)})]})]}),(0,B.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:o(`common:repositories.shellHint`)})]}),d===`decider`&&(0,B.jsxs)(`div`,{children:[(0,B.jsx)(`label`,{className:f,children:o(`builder.inspector.goal`)}),(0,B.jsx)(Ct,{t:o,constants:r,onInsert:e=>g(h,`goal`,e),onManage:i}),(0,B.jsx)(`textarea`,{ref:h,rows:4,className:p,value:String(e.goal??``),onChange:e=>t({goal:e.target.value})})]}),d===`condition`&&(0,B.jsxs)(`div`,{children:[(0,B.jsx)(`label`,{className:f,children:o(`builder.inspector.join`)}),(0,B.jsxs)(`select`,{className:p,value:String(e.join??`AND`),onChange:e=>t({join:e.target.value}),children:[(0,B.jsx)(`option`,{value:`AND`,children:`AND`}),(0,B.jsx)(`option`,{value:`OR`,children:`OR`})]})]}),d===`end`&&(0,B.jsxs)(`div`,{children:[(0,B.jsx)(`label`,{className:f,children:o(`builder.inspector.outcome`)}),(0,B.jsxs)(`select`,{className:p,value:String(e.outcome??`success`),onChange:e=>t({outcome:e.target.value}),children:[(0,B.jsx)(`option`,{value:`success`,children:`success`}),(0,B.jsx)(`option`,{value:`failure`,children:`failure`})]})]}),d===`start`&&(0,B.jsx)(`p`,{className:`text-[10px] text-muted-foreground`,children:o(`builder.inspector.startNote`)})]})}function Ot({loopId:e,onExit:t,onWindowOpened:n}={}){return(0,B.jsx)(Ne,{children:(0,B.jsx)(bt,{loopId:e,onExit:t,onWindowOpened:n})})}export{Ot as default};
@@ -1 +0,0 @@
1
- var e={title:`Agents`,subtitle:`Agent-Profile und den Katalog (Upstream + Custom) für dieses Projekt verwalten.`,tabs:{profiles:`Profile`,usage:`Nutzung`,catalog:`Katalog`},banner:{title:`Profilgestützte Pipeline erfordert specrails-core {{required}}+`,body:`Dieses Projekt hat <code>{{version}}</code>. Führe <code>{{command}}</code> im Projekt aus, um den Profilmodus freizuschalten. Hier erstellte Profile werden trotzdem gespeichert; sie wirken sich nur erst nach dem Core-Update auf die Pipeline aus.`,unknownVersion:`unbekannt`}},t={loading:`Katalog wird geladen…`,aiEditChipLabel:`AI Edit · {{agentId}}`,errors:{loadFailed:`Katalog konnte nicht geladen werden: {{status}}`,bodyLoadFailed:`Agent-Inhalt konnte nicht geladen werden: {{status}}`,generateFailed:`Generierung fehlgeschlagen: {{status}}`,agentLoadFailed:`Laden fehlgeschlagen: {{status}}`},templates:{title:`Agent-Vorlagenbibliothek`,countOf:`{{shown}} von {{total}}`,description:`Starte mit einer kuratierten Vorlage aus Engineering, Produkt, Wissenschaft, Gesundheit, Recht und mehr. Wähle eine aus und öffne sie im Studio, um sie vor dem Speichern zu prüfen und zu bearbeiten.`,searchPlaceholder:`Nach Name, Beschreibung, Tag oder Kategorie suchen…`,allCategories:`Alle`,tagFilter:`Tag-Filter:`,noMatch:`Keine Vorlagen entsprechen deinen Filtern.`,clearFilters:`Filter zurücksetzen`,openInStudio:`Im Studio öffnen →`,tip:`Tipp: Klicke auf einen Tag-Chip auf einer Karte, um nach diesem Tag zu filtern.`},generate:{title:`Custom-Agent generieren`,agentIdLabel:`Agent-ID`,agentIdHint:`Muss mit <code>custom-</code> beginnen.`,descriptionLabel:`Beschreibe, was dieser Agent tun soll`,descriptionPlaceholder:`z. B. Terraform-/IaC-Änderungen reviewen und Sicherheits-Fehlkonfigurationen, übermäßige IAM-Berechtigungen und öffentliche S3-Buckets vor dem Merge markieren. Konservativ und knapp.`,note:`Claude entwirft einen vollständigen <code>.md</code>-Inhalt. Du prüfst ihn im Studio und kannst ihn vor dem Speichern bearbeiten. Dabei wird ein einmaliger claude-Aufruf gestartet, der bis zu 90 Sekunden dauern kann.`,generating:`Wird generiert…`,generateButton:`Generieren`},empty:{title:`Keine Agents installiert`,body:`Führe <code>{{command}}</code> in diesem Projekt aus, um die Upstream-Agents zu installieren, oder erstelle jetzt einen Custom-Agent.`},actions:{template:`Vorlage`,templateTitle:`Mit einer Vorlage starten`,generate:`Generieren`,generateWithClaude:`Mit Claude generieren`,generateWithAi:`Mit KI generieren`,blank:`Leer`,blankTitle:`Mit einer leeren Vorlage starten`},sidebar:{title:`Katalog`,createLabel:`Custom-Agent erstellen:`},sections:{upstream:`Upstream ({{count}})`,upstreamDescription:`Wird von specrails-core mitgeliefert; schreibgeschützt.`,custom:`Custom ({{count}})`,customDescription:`Die custom-*.md-Dateien deines Projekts. Nutze Vorlage / Generieren / Leer oben, um einen zu erstellen.`,noCustomAgents:`Noch keine Custom-Agents.`},detail:{defaultModel:`Standardmodell: {{model}}`,aiEdit:`AI Edit`,aiEditTitle:`Diesen Agent iterativ mit KI verfeinern`,readOnly:`schreibgeschützt`,editableHint:`bearbeitbar – nutze Bearbeiten oben`},kind:{upstream:`upstream`,custom:`custom`}},n={providerLabel:`Profilanbieter`,loading:`Profile werden geladen…`,selectPrompt:`Wähle ein Profil zum Bearbeiten`,errors:{listFailed:`Auflisten fehlgeschlagen: {{status}}`,loadFailed:`Laden fehlgeschlagen: {{status}}`,migrationFailed:`Migration fehlgeschlagen: {{status}}`,createFailed:`Erstellen fehlgeschlagen: {{status}}`,duplicateFailed:`Duplizieren fehlgeschlagen: {{status}}`,deleteFailed:`Löschen fehlgeschlagen: {{status}}`,saveFailed:`Speichern fehlgeschlagen: {{status}}`},toasts:{migrated:`Profil migriert`,migratedDescription:`default-Profil aus deinen aktuellen Agents erstellt`,migrationFailed:`Migration fehlgeschlagen`,created:`Profil erstellt`,createFailed:`Profil konnte nicht erstellt werden`,duplicated:`Profil dupliziert`,duplicatedDescription:`{{from}} → {{to}}`,duplicateFailed:`Profil konnte nicht dupliziert werden`,deleted:`Profil gelöscht`,deleteFailed:`Profil konnte nicht gelöscht werden`,saved:`Profil gespeichert`,saveFailed:`Profil konnte nicht gespeichert werden`,savedWithUntargeted:`Profil mit nicht angesteuerten Agents gespeichert`,savedWithUntargetedDescription:`Keine Routing-Regel zeigt auf: {{agents}}. Füge eine Tag-Regel hinzu oder ändere das Ziel der Default-Regel, wenn sie laufen sollen.`},createDialog:{title:`Neues Profil`,description:`Wähle einen Namen in Kleinbuchstaben im kebab-case (Buchstaben, Ziffern und Bindestriche).`,confirmLabel:`Erstellen`,invalidHint:`Muss mit einem Buchstaben oder einer Ziffer beginnen und darf nur Kleinbuchstaben, Ziffern und Bindestriche enthalten.`},duplicateDialog:{title:`„{{name}}“ duplizieren`,description:`Name für das neue Profil.`,invalidHint:`Nur Kleinbuchstaben im kebab-case.`},deleteDialog:{title:`Profil „{{name}}“ löschen?`,description:`Dies kann nicht rückgängig gemacht werden. Bereits mit diesem Profil gestartete Jobs behalten ihren Snapshot; künftige Starts fallen auf die Auflösungsreihenfolge zurück.`},empty:{title:`Noch keine Profile`,body:`Mit Profilen speicherst du Kombinationen aus Orchestrator + Agents + Routing und wählst pro Rail eines aus.`,migrateButton:`Aus aktuellen Agents migrieren`,blankButton:`Leeres Profil`,migrateExplainer:`„Migrieren“ liest die Frontmatter-Modelle deiner bestehenden <code>.claude/agents/</code>-Dateien und erstellt ein <code>default</code>-Profil, das das heutige Verhalten verlustfrei abbildet.`},sidebar:{title:`Profile`,teamDefault:`(Team-Standard)`},editorFooter:{fixValidationIssues:`Behebe Validierungsprobleme vor dem Speichern`,issuesToResolve_one:`{{count}} Problem zu beheben`,issuesToResolve_other:`{{count}} Probleme zu beheben`}},r={title:`Profilnutzung`,windowLabel:`{{days}}d`,subtitleEmpty:`Gestartete Jobs pro Profil im gewählten Zeitraum.`,subtitle:`Gestartete Jobs pro Profil in den letzten {{count}} Tagen.`,empty:`Noch keine profilgebundenen Jobs.`,jobsTooltip:`Jobs`,jobsLabel_one:`Job`,jobsLabel_other:`Jobs`,successRateTooltip:`Erfolgsquote`,okSuffix:`ok`,avgDurationTooltip:`Ø Dauer`,avgTokensTooltip:`Ø Tokens`,tokensSuffix:`tok`},i={addTitle:`Routing-Regel hinzufügen`,editTitle:`Routing-Regel bearbeiten`,addDescription:`Füge eine Tag-basierte Routing-Regel mit kebab-case-Tags in Kleinbuchstaben hinzu.`,editDescription:`Aktualisiere die Tags oder den Ziel-Agent dieser Regel.`,tagsLabel:`Tags`,tagsHint:`Kommagetrennt. Verwende kebab-case in Kleinbuchstaben wie <code>frontend</code> oder <code>api-design</code>.`,invalidTags_one:`Ungültiger Tag: {{tags}}. Tags dürfen nur Kleinbuchstaben, Ziffern und Bindestriche enthalten.`,invalidTags_other:`Ungültige Tags: {{tags}}. Tags dürfen nur Kleinbuchstaben, Ziffern und Bindestriche enthalten.`,routeToLabel:`Weiterleiten an`,routeToHint:`Nur Agents in der Kette dieses Profils können Routing-Ziele sein.`,addRule:`Regel hinzufügen`,saveChanges:`Änderungen speichern`},a={profileTitle:`Agent-Profil für diese Rail`,noProfile:`Kein Profil`,modelTitle:`Modell für diese Freestyle-Rail`,loopModelTitle:`Modell für diesen Loop`,engineTitle:`KI-Anbieter für alle Rollen dieses Starts: Architekt, Entwickler und Reviewer`,localEngine:`Lokale Engine`,rolesEngine:`Rollen`,rolesEngineTitle:`Hybride Engines pro Rolle: Architect, Developer und Reviewer nutzen die Runtime-Konfiguration; Verifier und Decider nutzen die Loop-Rollen (Einstellungen ▸ Specrails-Agenten)`,rolesChip:`Engines pro Rolle`,rolesChipTitle:`Engines pro Rolle konfiguriert in Einstellungen ▸ Specrails-Agenten: Architect, Developer und Reviewer aus der Runtime-Konfiguration; Verifier und Decider aus den Loop-Rollen. Modell, Aufwand und Profil werden hier nicht gewählt.`},o={page:e,catalog:t,profiles:n,usage:r,routingRule:i,railSelectors:a};export{t as catalog,o as default,e as page,n as profiles,a as railSelectors,i as routingRule,r as usage};
@@ -1 +0,0 @@
1
- var e={title:`Agents`,subtitle:`管理此项目的 Agent Profile 和目录(上游 + 自定义)。`,tabs:{profiles:`Profile`,usage:`用量`,catalog:`目录`},banner:{title:`Profile 感知流水线需要 specrails-core {{required}}+`,body:`此项目当前为 <code>{{version}}</code>。在项目内运行 <code>{{command}}</code> 以解锁 Profile 模式。在此创建的 Profile 仍会保存,只是在 core 更新前不会影响流水线。`,unknownVersion:`未知`}},t={loading:`正在加载目录…`,aiEditChipLabel:`AI 编辑 · {{agentId}}`,errors:{loadFailed:`目录加载失败:{{status}}`,bodyLoadFailed:`Agent 正文加载失败:{{status}}`,generateFailed:`生成失败:{{status}}`,agentLoadFailed:`加载失败:{{status}}`},templates:{title:`Agent 模板库`,countOf:`{{shown}} / {{total}}`,description:`从精选模板开始,覆盖工程、产品、科学、健康、法律等领域。挑选一个并在 Studio 中打开,审阅和编辑后再保存。`,searchPlaceholder:`按名称、描述、标签或分类搜索…`,allCategories:`全部`,tagFilter:`标签筛选:`,noMatch:`没有符合筛选条件的模板。`,clearFilters:`清除筛选`,openInStudio:`在 Studio 中打开 →`,tip:`提示:点击任意卡片上的标签即可按该标签筛选。`},generate:{title:`生成自定义 Agent`,agentIdLabel:`Agent ID`,agentIdHint:`必须以 <code>custom-</code> 开头。`,descriptionLabel:`描述此 Agent 的职责`,descriptionPlaceholder:`例如:审查 Terraform/IaC 变更,在合并前标记安全配置错误、过度的 IAM 权限和公开的 S3 存储桶。风格保守、简洁。`,note:`Claude 会起草完整的 <code>.md</code> 正文。你将在 Studio 中审阅,并可在保存前编辑。此操作会启动一次性的 claude 调用,最长可能需要 90 秒。`,generating:`正在生成…`,generateButton:`生成`},empty:{title:`尚未安装任何 Agent`,body:`在此项目中运行 <code>{{command}}</code> 安装上游 Agent,或立即创建一个自定义 Agent。`},actions:{template:`模板`,templateTitle:`从模板开始`,generate:`生成`,generateWithClaude:`用 Claude 生成`,generateWithAi:`用 AI 生成`,blank:`空白`,blankTitle:`从空白模板开始`},sidebar:{title:`目录`,createLabel:`创建自定义 Agent:`},sections:{upstream:`上游({{count}})`,upstreamDescription:`由 specrails-core 提供;只读。`,custom:`自定义({{count}})`,customDescription:`项目中的 custom-*.md 文件。使用上方的模板 / 生成 / 空白来创建。`,noCustomAgents:`暂无自定义 Agent。`},detail:{defaultModel:`默认模型:{{model}}`,aiEdit:`AI 编辑`,aiEditTitle:`用 AI 迭代优化此 Agent`,readOnly:`只读`,editableHint:`可编辑——使用上方的“编辑”`},kind:{upstream:`上游`,custom:`自定义`}},n={providerLabel:`Profile 提供方`,loading:`正在加载 Profile…`,selectPrompt:`选择要编辑的 Profile`,errors:{listFailed:`列表加载失败:{{status}}`,loadFailed:`加载失败:{{status}}`,migrationFailed:`迁移失败:{{status}}`,createFailed:`创建失败:{{status}}`,duplicateFailed:`复制失败:{{status}}`,deleteFailed:`删除失败:{{status}}`,saveFailed:`保存失败:{{status}}`},toasts:{migrated:`Profile 已迁移`,migratedDescription:`已根据当前 Agent 创建 default Profile`,migrationFailed:`迁移失败`,created:`Profile 已创建`,createFailed:`创建 Profile 失败`,duplicated:`Profile 已复制`,duplicatedDescription:`{{from}} → {{to}}`,duplicateFailed:`复制 Profile 失败`,deleted:`Profile 已删除`,deleteFailed:`删除 Profile 失败`,saved:`Profile 已保存`,saveFailed:`保存 Profile 失败`,savedWithUntargeted:`Profile 已保存,但存在未被路由的 Agent`,savedWithUntargetedDescription:`没有路由规则指向:{{agents}}。如需让它们运行,请添加标签规则或调整默认规则的目标。`},createDialog:{title:`新建 Profile`,description:`请使用小写 kebab-case 名称(字母、数字和连字符)。`,confirmLabel:`创建`,invalidHint:`必须以字母或数字开头,且只能包含小写字母、数字和连字符。`},duplicateDialog:{title:`复制“{{name}}”`,description:`新 Profile 的名称。`,invalidHint:`仅限小写 kebab-case。`},deleteDialog:{title:`删除 Profile“{{name}}”?`,description:`此操作无法撤销。已使用此 Profile 启动的任务会保留其快照;之后的启动将回退到解析顺序。`},empty:{title:`暂无 Profile`,body:`Profile 可保存编排器 + Agent + 路由的组合,并为每条 rail 单独选用。`,migrateButton:`从当前 Agent 迁移`,blankButton:`空白 Profile`,migrateExplainer:`“迁移”会读取现有 <code>.claude/agents/</code> frontmatter 中的模型,并创建一个 <code>default</code> Profile,完整复刻当前行为——零损失。`},sidebar:{title:`Profile`,teamDefault:`(团队默认)`},editorFooter:{fixValidationIssues:`保存前请先修复校验问题`,issuesToResolve_one:`{{count}} 个待解决问题`,issuesToResolve_other:`{{count}} 个待解决问题`}},r={title:`Profile 用量`,windowLabel:`{{days}}天`,subtitleEmpty:`所选时间窗口内各 Profile 启动的任务数。`,subtitle:`最近 {{count}} 天内各 Profile 启动的任务数。`,empty:`暂无使用 Profile 的任务。`,jobsTooltip:`任务`,jobsLabel_one:`个任务`,jobsLabel_other:`个任务`,successRateTooltip:`成功率`,okSuffix:`成功`,avgDurationTooltip:`平均时长`,avgTokensTooltip:`平均 token 数`,tokensSuffix:`tok`},i={addTitle:`添加路由规则`,editTitle:`编辑路由规则`,addDescription:`添加按标签匹配的路由规则,标签使用小写 kebab-case。`,editDescription:`更新此规则的标签或目标 Agent。`,tagsLabel:`标签`,tagsHint:`以逗号分隔。使用小写 kebab-case,如 <code>frontend</code> 或 <code>api-design</code>。`,invalidTags_one:`无效标签:{{tags}}。标签只能使用小写字母、数字和连字符。`,invalidTags_other:`无效标签:{{tags}}。标签只能使用小写字母、数字和连字符。`,routeToLabel:`路由到`,routeToHint:`只有此 Profile 链中的 Agent 才能作为路由目标。`,addRule:`添加规则`,saveChanges:`保存更改`},a={profileTitle:`此 rail 使用的 Agent Profile`,noProfile:`无 Profile`,modelTitle:`此 Freestyle rail 使用的模型`,loopModelTitle:`此 Loop 使用的模型`,engineTitle:`本次运行所有角色使用的 AI 提供商:架构师、开发者和审查者`,localEngine:`本地引擎`,rolesEngine:`按角色`,rolesEngineTitle:`按角色的混合引擎:architect、developer 和 reviewer 使用运行时配置;verifier 和 decider 使用循环角色(设置 ▸ Specrails 代理)`,rolesChip:`按角色引擎`,rolesChipTitle:`引擎已在“设置 ▸ Specrails 代理”中按角色配置:architect、developer 和 reviewer 来自运行时配置;verifier 和 decider 来自循环角色。此处不选择模型、推理强度或配置文件。`},o={page:e,catalog:t,profiles:n,usage:r,routingRule:i,railSelectors:a};export{t as catalog,o as default,e as page,n as profiles,a as railSelectors,i as routingRule,r as usage};
@@ -1 +0,0 @@
1
- var e={title:`エージェント`,subtitle:`このプロジェクトのエージェントプロファイルとカタログ(アップストリーム + カスタム)を管理します。`,tabs:{profiles:`プロファイル`,usage:`使用状況`,catalog:`カタログ`},banner:{title:`プロファイル対応パイプラインには specrails-core {{required}}+ が必要です`,body:`このプロジェクトのバージョンは <code>{{version}}</code> です。プロジェクト内で <code>{{command}}</code> を実行するとプロファイルモードが有効になります。ここで作成したプロファイルは保存されますが、core を更新するまでパイプラインには影響しません。`,unknownVersion:`不明`}},t={loading:`カタログを読み込み中…`,aiEditChipLabel:`AI編集 · {{agentId}}`,errors:{loadFailed:`カタログの読み込みに失敗しました: {{status}}`,bodyLoadFailed:`エージェント本文の読み込みに失敗しました: {{status}}`,generateFailed:`生成に失敗しました: {{status}}`,agentLoadFailed:`読み込みに失敗しました: {{status}}`},templates:{title:`エージェントテンプレートライブラリ`,countOf:`{{shown}} / {{total}}`,description:`エンジニアリング、プロダクト、科学、医療、法務など、厳選されたテンプレートから始められます。1つ選んで Studio で開き、確認・編集してから保存してください。`,searchPlaceholder:`名前、説明、タグ、カテゴリで検索…`,allCategories:`すべて`,tagFilter:`タグフィルター:`,noMatch:`フィルターに一致するテンプレートはありません。`,clearFilters:`フィルターをクリア`,openInStudio:`Studio で開く →`,tip:`ヒント: カードのタグをクリックすると、そのタグで絞り込めます。`},generate:{title:`カスタムエージェントを生成`,agentIdLabel:`エージェント ID`,agentIdHint:`<code>custom-</code> で始まる必要があります。`,descriptionLabel:`このエージェントの役割を記述してください`,descriptionPlaceholder:`例: Terraform/IaC の変更をレビューし、マージ前にセキュリティ設定ミス、過剰な IAM 権限、公開 S3 バケットを指摘する。保守的かつ簡潔に。`,note:`Claude が完全な <code>.md</code> 本文をドラフトします。Studio で確認し、保存前に編集できます。ワンショットの claude 呼び出しが起動され、最大 90 秒かかることがあります。`,generating:`生成中…`,generateButton:`生成`},empty:{title:`エージェントがインストールされていません`,body:`このプロジェクトで <code>{{command}}</code> を実行してアップストリームのエージェントをインストールするか、今すぐカスタムエージェントを作成してください。`},actions:{template:`テンプレート`,templateTitle:`テンプレートから始める`,generate:`生成`,generateWithClaude:`Claude で生成`,generateWithAi:`AI で生成`,blank:`ブランク`,blankTitle:`空のテンプレートから始める`},sidebar:{title:`カタログ`,createLabel:`カスタムエージェントを作成:`},sections:{upstream:`アップストリーム ({{count}})`,upstreamDescription:`specrails-core 付属。読み取り専用です。`,custom:`カスタム ({{count}})`,customDescription:`このプロジェクトの custom-*.md ファイルです。上のテンプレート / 生成 / ブランクから作成できます。`,noCustomAgents:`カスタムエージェントはまだありません。`},detail:{defaultModel:`デフォルトモデル: {{model}}`,aiEdit:`AI編集`,aiEditTitle:`AI でこのエージェントを反復的に改良`,readOnly:`読み取り専用`,editableHint:`編集可能 — 上の「編集」を使用`},kind:{upstream:`アップストリーム`,custom:`カスタム`}},n={providerLabel:`プロファイルのプロバイダー`,loading:`プロファイルを読み込み中…`,selectPrompt:`編集するプロファイルを選択してください`,errors:{listFailed:`一覧の取得に失敗しました: {{status}}`,loadFailed:`読み込みに失敗しました: {{status}}`,migrationFailed:`移行に失敗しました: {{status}}`,createFailed:`作成に失敗しました: {{status}}`,duplicateFailed:`複製に失敗しました: {{status}}`,deleteFailed:`削除に失敗しました: {{status}}`,saveFailed:`保存に失敗しました: {{status}}`},toasts:{migrated:`プロファイルを移行しました`,migratedDescription:`現在のエージェントから default プロファイルを作成しました`,migrationFailed:`移行に失敗しました`,created:`プロファイルを作成しました`,createFailed:`プロファイルの作成に失敗しました`,duplicated:`プロファイルを複製しました`,duplicatedDescription:`{{from}} → {{to}}`,duplicateFailed:`プロファイルの複製に失敗しました`,deleted:`プロファイルを削除しました`,deleteFailed:`プロファイルの削除に失敗しました`,saved:`プロファイルを保存しました`,saveFailed:`プロファイルの保存に失敗しました`,savedWithUntargeted:`未ターゲットのエージェントを含むプロファイルを保存しました`,savedWithUntargetedDescription:`ルーティングルールが次のエージェントを指していません: {{agents}}。実行させたい場合は、タグルールを追加するか default ルールのターゲットを変更してください。`},createDialog:{title:`新規プロファイル`,description:`小文字のケバブケース名(英小文字、数字、ハイフン)を指定してください。`,confirmLabel:`作成`,invalidHint:`先頭は英小文字または数字で、英小文字・数字・ハイフンのみ使用できます。`},duplicateDialog:{title:`「{{name}}」を複製`,description:`新しいプロファイルの名前。`,invalidHint:`小文字のケバブケースのみ。`},deleteDialog:{title:`プロファイル「{{name}}」を削除しますか?`,description:`この操作は元に戻せません。このプロファイルで起動済みのジョブはスナップショットを保持します。今後の起動は解決順序にフォールバックします。`},empty:{title:`プロファイルはまだありません`,body:`プロファイルを使うと、オーケストレーター + エージェント + ルーティングの組み合わせを保存し、レールごとに選択できます。`,migrateButton:`現在のエージェントから移行`,blankButton:`空のプロファイル`,migrateExplainer:`「移行」は既存の <code>.claude/agents/</code> フロントマターのモデルを読み取り、現在の動作をそのまま再現する <code>default</code> プロファイルを作成します — 損失ゼロです。`},sidebar:{title:`プロファイル`,teamDefault:`(チームデフォルト)`},editorFooter:{fixValidationIssues:`保存する前に検証エラーを修正してください`,issuesToResolve_one:`未解決の問題が {{count}} 件`,issuesToResolve_other:`未解決の問題が {{count}} 件`}},r={title:`プロファイル使用状況`,windowLabel:`{{days}}日`,subtitleEmpty:`選択した期間にプロファイルごとに起動されたジョブ数。`,subtitle:`過去 {{count}} 日間にプロファイルごとに起動されたジョブ数。`,empty:`プロファイル指定のジョブはまだありません。`,jobsTooltip:`ジョブ`,jobsLabel_one:`ジョブ`,jobsLabel_other:`ジョブ`,successRateTooltip:`成功率`,okSuffix:`ok`,avgDurationTooltip:`平均実行時間`,avgTokensTooltip:`平均トークン数`,tokensSuffix:`tok`},i={addTitle:`ルーティングルールを追加`,editTitle:`ルーティングルールを編集`,addDescription:`小文字ケバブケースのタグでマッチするルーティングルールを追加します。`,editDescription:`このルールのタグまたはターゲットエージェントを更新します。`,tagsLabel:`タグ`,tagsHint:`カンマ区切り。<code>frontend</code> や <code>api-design</code> のような小文字ケバブケースを使用してください。`,invalidTags_one:`無効なタグ: {{tags}}。タグには英小文字・数字・ハイフンのみ使用できます。`,invalidTags_other:`無効なタグ: {{tags}}。タグには英小文字・数字・ハイフンのみ使用できます。`,routeToLabel:`ルーティング先`,routeToHint:`このプロファイルのチェーンに含まれるエージェントのみルーティング先に指定できます。`,addRule:`ルールを追加`,saveChanges:`変更を保存`},a={profileTitle:`このレールのエージェントプロファイル`,noProfile:`プロファイルなし`,modelTitle:`この Freestyle レールのモデル`,loopModelTitle:`このループのモデル`,engineTitle:`この実行のすべてのロール(設計、開発、レビュー)で使う AI プロバイダー`,localEngine:`ローカルエンジン`,rolesEngine:`ロール別`,rolesEngineTitle:`ロール別のハイブリッドエンジン:architect・developer・reviewer はランタイム設定を、verifier・decider はループロールを使用します(設定 ▸ Specrails エージェント)`,rolesChip:`ロール別エンジン`,rolesChipTitle:`エンジンは「設定 ▸ Specrails エージェント」でロールごとに設定済みです:architect・developer・reviewer はランタイム設定から、verifier・decider はループロールから。モデル・推論の深さ・プロファイルはここでは選びません。`},o={page:e,catalog:t,profiles:n,usage:r,routingRule:i,railSelectors:a};export{t as catalog,o as default,e as page,n as profiles,a as railSelectors,i as routingRule,r as usage};
@@ -1 +0,0 @@
1
- import{r as e}from"./rolldown-runtime-CNC7AqOf.js";var t=e({catalog:()=>r,default:()=>c,page:()=>n,profiles:()=>i,railSelectors:()=>s,routingRule:()=>o,usage:()=>a}),n={title:`Agents`,subtitle:`Manage agent profiles and the catalog (upstream + custom) for this project.`,tabs:{profiles:`Profiles`,usage:`Usage`,catalog:`Catalog`},banner:{title:`Profile-aware pipeline requires specrails-core {{required}}+`,body:`This project has <code>{{version}}</code>. Run <code>{{command}}</code> inside the project to unlock profile mode. Profiles you create here will still save; they just won't affect the pipeline until core is updated.`,unknownVersion:`unknown`}},r={loading:`Loading catalog…`,aiEditChipLabel:`AI Edit · {{agentId}}`,errors:{loadFailed:`Catalog load failed: {{status}}`,bodyLoadFailed:`Agent body load failed: {{status}}`,generateFailed:`Generate failed: {{status}}`,agentLoadFailed:`Load failed: {{status}}`},templates:{title:`Agent template library`,countOf:`{{shown}} of {{total}}`,description:`Start from a curated template across engineering, product, science, health, legal, and more. Pick one and open it in the Studio for review and editing before saving.`,searchPlaceholder:`Search by name, description, tag, or category…`,allCategories:`All`,tagFilter:`Tag filter:`,noMatch:`No templates match your filters.`,clearFilters:`Clear filters`,openInStudio:`Open in Studio →`,tip:`Tip: click a tag pill on any card to filter by that tag.`},generate:{title:`Generate a custom agent`,agentIdLabel:`Agent id`,agentIdHint:`Must start with <code>custom-</code>.`,descriptionLabel:`Describe what this agent should do`,descriptionPlaceholder:`e.g. Review Terraform/IaC changes and flag security misconfigurations, excessive IAM permissions, and public S3 buckets before merging. Conservative and terse.`,note:`Claude will draft a full <code>.md</code> body. You'll review it in the Studio and can edit before saving. This spawns a one-shot claude invocation and can take up to 90 seconds.`,generating:`Generating…`,generateButton:`Generate`},empty:{title:`No agents installed`,body:`Run <code>{{command}}</code> in this project to install the upstream agents, or create a custom agent now.`},actions:{template:`Template`,templateTitle:`Start from a template`,generate:`Generate`,generateWithClaude:`Generate with Claude`,generateWithAi:`Generate with AI`,blank:`Blank`,blankTitle:`Start from a blank template`},sidebar:{title:`Catalog`,createLabel:`Create a custom agent:`},sections:{upstream:`Upstream ({{count}})`,upstreamDescription:`Shipped by specrails-core; read-only.`,custom:`Custom ({{count}})`,customDescription:`Your project's custom-*.md files. Use Template / Generate / Blank above to create one.`,noCustomAgents:`No custom agents yet.`},detail:{defaultModel:`default model: {{model}}`,aiEdit:`AI Edit`,aiEditTitle:`Iteratively refine this agent with AI`,readOnly:`read-only`,editableHint:`editable — use Edit above`},kind:{upstream:`upstream`,custom:`custom`}},i={providerLabel:`Profile provider`,loading:`Loading profiles…`,selectPrompt:`Select a profile to edit`,errors:{listFailed:`List failed: {{status}}`,loadFailed:`Load failed: {{status}}`,migrationFailed:`Migration failed: {{status}}`,createFailed:`Create failed: {{status}}`,duplicateFailed:`Duplicate failed: {{status}}`,deleteFailed:`Delete failed: {{status}}`,saveFailed:`Save failed: {{status}}`},toasts:{migrated:`Profile migrated`,migratedDescription:`default profile created from your current agents`,migrationFailed:`Migration failed`,created:`Profile created`,createFailed:`Failed to create profile`,duplicated:`Profile duplicated`,duplicatedDescription:`{{from}} → {{to}}`,duplicateFailed:`Failed to duplicate profile`,deleted:`Profile deleted`,deleteFailed:`Failed to delete profile`,saved:`Profile saved`,saveFailed:`Failed to save profile`,savedWithUntargeted:`Profile saved with untargeted agents`,savedWithUntargetedDescription:`No routing rule points to: {{agents}}. Add a tag rule or retarget the default rule if you want them to run.`},createDialog:{title:`New profile`,description:`Pick a lowercase kebab-case name (letters, digits, and hyphens).`,confirmLabel:`Create`,invalidHint:`Must start with a letter or digit and contain only lowercase letters, digits, and hyphens.`},duplicateDialog:{title:`Duplicate "{{name}}"`,description:`Name for the new profile.`,invalidHint:`Lowercase kebab-case only.`},deleteDialog:{title:`Delete profile "{{name}}"?`,description:`This cannot be undone. Jobs already launched with this profile keep their snapshot; future launches will fall back to the resolution order.`},empty:{title:`No profiles yet`,body:`Profiles let you save orchestrator + agent + routing combinations and pick one per rail.`,migrateButton:`Migrate from current agents`,blankButton:`Blank profile`,migrateExplainer:`"Migrate" reads your existing <code>.claude/agents/</code> frontmatter models and creates a <code>default</code> profile mirroring today's behavior — zero-loss.`},sidebar:{title:`Profiles`,teamDefault:`(team default)`},editorFooter:{fixValidationIssues:`Fix validation issues before saving`,issuesToResolve_one:`{{count}} issue to resolve`,issuesToResolve_other:`{{count}} issues to resolve`}},a={title:`Profile usage`,windowLabel:`{{days}}d`,subtitleEmpty:`Jobs launched per profile in the selected window.`,subtitle:`Jobs launched per profile in the last {{count}} days.`,empty:`No profile-scoped jobs yet.`,jobsTooltip:`jobs`,jobsLabel_one:`job`,jobsLabel_other:`jobs`,successRateTooltip:`success rate`,okSuffix:`ok`,avgDurationTooltip:`avg duration`,avgTokensTooltip:`avg tokens`,tokensSuffix:`tok`},o={addTitle:`Add routing rule`,editTitle:`Edit routing rule`,addDescription:`Add a tag-matched routing rule using lowercase kebab-case tags.`,editDescription:`Update the tags or target agent for this rule.`,tagsLabel:`Tags`,tagsHint:`Comma-separated. Use lowercase kebab-case like <code>frontend</code> or <code>api-design</code>.`,invalidTags_one:`Invalid tag: {{tags}}. Tags must use lowercase letters, digits, and hyphens only.`,invalidTags_other:`Invalid tags: {{tags}}. Tags must use lowercase letters, digits, and hyphens only.`,routeToLabel:`Route to`,routeToHint:`Only agents in this profile's chain can be routing targets.`,addRule:`Add rule`,saveChanges:`Save changes`},s={profileTitle:`Agent profile for this rail`,noProfile:`No profile`,modelTitle:`Model for this Freestyle rail`,loopModelTitle:`Model for this loop`,engineTitle:`AI provider for all roles in this launch: architect, developer and reviewer`,localEngine:`Local engine`,rolesEngine:`Roles`,rolesEngineTitle:`Hybrid engines per role: architect, developer and reviewer use the runtime configuration; verifier and decider use the loop roles (Settings ▸ AI providers)`,rolesChip:`Per-role engines`,rolesChipTitle:`Engines configured per role in Settings ▸ AI providers: architect, developer and reviewer from the runtime configuration; verifier and decider from the loop roles. Model, effort and profile are not chosen here.`},c={page:n,catalog:r,profiles:i,usage:a,routingRule:o,railSelectors:s};export{t};
@@ -1 +0,0 @@
1
- var e={title:`Agenti`,subtitle:`Gestisci i profili agente e il catalogo (upstream + custom) di questo progetto.`,tabs:{profiles:`Profili`,usage:`Utilizzo`,catalog:`Catalogo`},banner:{title:`La pipeline con profili richiede specrails-core {{required}}+`,body:`Questo progetto ha <code>{{version}}</code>. Esegui <code>{{command}}</code> nel progetto per sbloccare la modalità profili. I profili creati qui verranno comunque salvati; semplicemente non influiranno sulla pipeline finché core non viene aggiornato.`,unknownVersion:`sconosciuta`}},t={loading:`Caricamento del catalogo…`,aiEditChipLabel:`Modifica AI · {{agentId}}`,errors:{loadFailed:`Caricamento del catalogo non riuscito: {{status}}`,bodyLoadFailed:`Caricamento del corpo dell'agente non riuscito: {{status}}`,generateFailed:`Generazione non riuscita: {{status}}`,agentLoadFailed:`Caricamento non riuscito: {{status}}`},templates:{title:`Libreria di template agente`,countOf:`{{shown}} di {{total}}`,description:`Parti da un template curato tra engineering, prodotto, scienza, salute, legale e altro. Scegline uno e aprilo nello Studio per revisionarlo e modificarlo prima di salvare.`,searchPlaceholder:`Cerca per nome, descrizione, tag o categoria…`,allCategories:`Tutte`,tagFilter:`Filtro tag:`,noMatch:`Nessun template corrisponde ai filtri.`,clearFilters:`Cancella filtri`,openInStudio:`Apri nello Studio →`,tip:`Suggerimento: clicca un tag su una card per filtrare per quel tag.`},generate:{title:`Genera un agente custom`,agentIdLabel:`ID agente`,agentIdHint:`Deve iniziare con <code>custom-</code>.`,descriptionLabel:`Descrivi cosa deve fare questo agente`,descriptionPlaceholder:`es. Revisiona le modifiche Terraform/IaC e segnala configurazioni di sicurezza errate, permessi IAM eccessivi e bucket S3 pubblici prima del merge. Conservativo e conciso.`,note:`Claude redigerà un corpo <code>.md</code> completo. Lo revisionerai nello Studio e potrai modificarlo prima di salvare. Questo avvia un'invocazione claude one-shot e può richiedere fino a 90 secondi.`,generating:`Generazione…`,generateButton:`Genera`},empty:{title:`Nessun agente installato`,body:`Esegui <code>{{command}}</code> in questo progetto per installare gli agenti upstream, oppure crea subito un agente custom.`},actions:{template:`Template`,templateTitle:`Parti da un template`,generate:`Genera`,generateWithClaude:`Genera con Claude`,generateWithAi:`Genera con IA`,blank:`Vuoto`,blankTitle:`Parti da un template vuoto`},sidebar:{title:`Catalogo`,createLabel:`Crea un agente custom:`},sections:{upstream:`Upstream ({{count}})`,upstreamDescription:`Forniti da specrails-core; sola lettura.`,custom:`Custom ({{count}})`,customDescription:`I file custom-*.md del tuo progetto. Usa Template / Genera / Vuoto qui sopra per crearne uno.`,noCustomAgents:`Ancora nessun agente custom.`},detail:{defaultModel:`modello predefinito: {{model}}`,aiEdit:`Modifica AI`,aiEditTitle:`Raffina iterativamente questo agente con l'AI`,readOnly:`sola lettura`,editableHint:`modificabile — usa Modifica qui sopra`},kind:{upstream:`upstream`,custom:`custom`}},n={providerLabel:`Provider del profilo`,loading:`Caricamento dei profili…`,selectPrompt:`Seleziona un profilo da modificare`,errors:{listFailed:`Caricamento dell'elenco non riuscito: {{status}}`,loadFailed:`Caricamento non riuscito: {{status}}`,migrationFailed:`Migrazione non riuscita: {{status}}`,createFailed:`Creazione non riuscita: {{status}}`,duplicateFailed:`Duplicazione non riuscita: {{status}}`,deleteFailed:`Eliminazione non riuscita: {{status}}`,saveFailed:`Salvataggio non riuscito: {{status}}`},toasts:{migrated:`Profilo migrato`,migratedDescription:`profilo default creato dagli agenti attuali`,migrationFailed:`Migrazione non riuscita`,created:`Profilo creato`,createFailed:`Impossibile creare il profilo`,duplicated:`Profilo duplicato`,duplicatedDescription:`{{from}} → {{to}}`,duplicateFailed:`Impossibile duplicare il profilo`,deleted:`Profilo eliminato`,deleteFailed:`Impossibile eliminare il profilo`,saved:`Profilo salvato`,saveFailed:`Impossibile salvare il profilo`,savedWithUntargeted:`Profilo salvato con agenti senza routing`,savedWithUntargetedDescription:`Nessuna regola di routing punta a: {{agents}}. Aggiungi una regola per tag o ridefinisci la regola default se vuoi che vengano eseguiti.`},createDialog:{title:`Nuovo profilo`,description:`Scegli un nome in kebab-case minuscolo (lettere, cifre e trattini).`,confirmLabel:`Crea`,invalidHint:`Deve iniziare con una lettera o una cifra e contenere solo lettere minuscole, cifre e trattini.`},duplicateDialog:{title:`Duplica "{{name}}"`,description:`Nome del nuovo profilo.`,invalidHint:`Solo kebab-case minuscolo.`},deleteDialog:{title:`Eliminare il profilo "{{name}}"?`,description:`Questa azione è irreversibile. I job già avviati con questo profilo mantengono il loro snapshot; i prossimi avvii ricadranno sull'ordine di risoluzione.`},empty:{title:`Ancora nessun profilo`,body:`I profili permettono di salvare combinazioni di orchestratore + agenti + routing e sceglierne una per rail.`,migrateButton:`Migra dagli agenti attuali`,blankButton:`Profilo vuoto`,migrateExplainer:`"Migra" legge i modelli dal frontmatter dei tuoi <code>.claude/agents/</code> esistenti e crea un profilo <code>default</code> che rispecchia il comportamento attuale — senza perdite.`},sidebar:{title:`Profili`,teamDefault:`(default del team)`},editorFooter:{fixValidationIssues:`Correggi i problemi di validazione prima di salvare`,issuesToResolve_one:`{{count}} problema da risolvere`,issuesToResolve_other:`{{count}} problemi da risolvere`}},r={title:`Utilizzo dei profili`,windowLabel:`{{days}}d`,subtitleEmpty:`Job avviati per profilo nella finestra selezionata.`,subtitle:`Job avviati per profilo negli ultimi {{count}} giorni.`,empty:`Ancora nessun job con profilo.`,jobsTooltip:`job`,jobsLabel_one:`job`,jobsLabel_other:`job`,successRateTooltip:`tasso di successo`,okSuffix:`ok`,avgDurationTooltip:`durata media`,avgTokensTooltip:`token medi`,tokensSuffix:`tok`},i={addTitle:`Aggiungi regola di routing`,editTitle:`Modifica regola di routing`,addDescription:`Aggiungi una regola di routing per tag usando tag in kebab-case minuscolo.`,editDescription:`Aggiorna i tag o l'agente di destinazione per questa regola.`,tagsLabel:`Tag`,tagsHint:`Separati da virgola. Usa kebab-case minuscolo come <code>frontend</code> o <code>api-design</code>.`,invalidTags_one:`Tag non valido: {{tags}}. I tag possono contenere solo lettere minuscole, cifre e trattini.`,invalidTags_other:`Tag non validi: {{tags}}. I tag possono contenere solo lettere minuscole, cifre e trattini.`,routeToLabel:`Instrada verso`,routeToHint:`Solo gli agenti nella catena di questo profilo possono essere destinazioni di routing.`,addRule:`Aggiungi regola`,saveChanges:`Salva modifiche`},a={profileTitle:`Profilo agente per questo rail`,noProfile:`Nessun profilo`,modelTitle:`Modello per questo rail Freestyle`,loopModelTitle:`Modello per questo loop`,engineTitle:`Provider IA per tutti i ruoli di questo avvio: architetto, sviluppatore e revisore`,localEngine:`Motore locale`,rolesEngine:`Ruoli`,rolesEngineTitle:`Motori ibridi per ruolo: architect, developer e reviewer usano la configurazione del runtime; verifier e decider usano i ruoli del loop (Impostazioni ▸ Agenti Specrails)`,rolesChip:`Motori per ruolo`,rolesChipTitle:`Motori configurati per ruolo in Impostazioni ▸ Agenti Specrails: architect, developer e reviewer dalla configurazione del runtime; verifier e decider dai ruoli del loop. Modello, sforzo e profilo non si scelgono qui.`},o={page:e,catalog:t,profiles:n,usage:r,routingRule:i,railSelectors:a};export{t as catalog,o as default,e as page,n as profiles,a as railSelectors,i as routingRule,r as usage};
@@ -1 +0,0 @@
1
- var e={title:`Agentes`,subtitle:`Gestiona los perfiles de agentes y el catálogo (upstream + personalizados) de este proyecto.`,tabs:{profiles:`Perfiles`,usage:`Uso`,catalog:`Catálogo`},banner:{title:`El pipeline con perfiles requiere specrails-core {{required}}+`,body:`Este proyecto tiene <code>{{version}}</code>. Ejecuta <code>{{command}}</code> dentro del proyecto para activar el modo perfiles. Los perfiles que crees aquí se guardarán igualmente; simplemente no afectarán al pipeline hasta que actualices core.`,unknownVersion:`desconocida`}},t={loading:`Cargando catálogo…`,aiEditChipLabel:`Edición IA · {{agentId}}`,errors:{loadFailed:`Error al cargar el catálogo: {{status}}`,bodyLoadFailed:`Error al cargar el cuerpo del agente: {{status}}`,generateFailed:`Error al generar: {{status}}`,agentLoadFailed:`Error al cargar: {{status}}`},templates:{title:`Biblioteca de plantillas de agentes`,countOf:`{{shown}} de {{total}}`,description:`Empieza desde una plantilla seleccionada de ingeniería, producto, ciencia, salud, legal y más. Elige una y ábrela en el Studio para revisarla y editarla antes de guardar.`,searchPlaceholder:`Buscar por nombre, descripción, etiqueta o categoría…`,allCategories:`Todas`,tagFilter:`Filtro de etiquetas:`,noMatch:`Ninguna plantilla coincide con tus filtros.`,clearFilters:`Limpiar filtros`,openInStudio:`Abrir en el Studio →`,tip:`Consejo: haz clic en una etiqueta de cualquier tarjeta para filtrar por ella.`},generate:{title:`Generar un agente personalizado`,agentIdLabel:`Id del agente`,agentIdHint:`Debe empezar por <code>custom-</code>.`,descriptionLabel:`Describe qué debe hacer este agente`,descriptionPlaceholder:`p. ej. Revisar cambios de Terraform/IaC y señalar errores de configuración de seguridad, permisos IAM excesivos y buckets S3 públicos antes del merge. Conservador y conciso.`,note:`Claude redactará un cuerpo <code>.md</code> completo. Lo revisarás en el Studio y podrás editarlo antes de guardar. Esto lanza una invocación puntual de claude y puede tardar hasta 90 segundos.`,generating:`Generando…`,generateButton:`Generar`},empty:{title:`No hay agentes instalados`,body:`Ejecuta <code>{{command}}</code> en este proyecto para instalar los agentes upstream, o crea ahora un agente personalizado.`},actions:{template:`Plantilla`,templateTitle:`Empezar desde una plantilla`,generate:`Generar`,generateWithClaude:`Generar con Claude`,generateWithAi:`Generar con IA`,blank:`En blanco`,blankTitle:`Empezar desde una plantilla en blanco`},sidebar:{title:`Catálogo`,createLabel:`Crear un agente personalizado:`},sections:{upstream:`Upstream ({{count}})`,upstreamDescription:`Incluidos con specrails-core; solo lectura.`,custom:`Personalizados ({{count}})`,customDescription:`Los archivos custom-*.md de tu proyecto. Usa Plantilla / Generar / En blanco arriba para crear uno.`,noCustomAgents:`Aún no hay agentes personalizados.`},detail:{defaultModel:`modelo por defecto: {{model}}`,aiEdit:`Edición IA`,aiEditTitle:`Refina este agente iterativamente con IA`,readOnly:`solo lectura`,editableHint:`editable — usa Editar arriba`},kind:{upstream:`upstream`,custom:`personalizado`}},n={providerLabel:`Proveedor del perfil`,loading:`Cargando perfiles…`,selectPrompt:`Selecciona un perfil para editarlo`,errors:{listFailed:`Error al listar: {{status}}`,loadFailed:`Error al cargar: {{status}}`,migrationFailed:`Error en la migración: {{status}}`,createFailed:`Error al crear: {{status}}`,duplicateFailed:`Error al duplicar: {{status}}`,deleteFailed:`Error al eliminar: {{status}}`,saveFailed:`Error al guardar: {{status}}`},toasts:{migrated:`Perfil migrado`,migratedDescription:`perfil default creado a partir de tus agentes actuales`,migrationFailed:`Error en la migración`,created:`Perfil creado`,createFailed:`No se pudo crear el perfil`,duplicated:`Perfil duplicado`,duplicatedDescription:`{{from}} → {{to}}`,duplicateFailed:`No se pudo duplicar el perfil`,deleted:`Perfil eliminado`,deleteFailed:`No se pudo eliminar el perfil`,saved:`Perfil guardado`,saveFailed:`No se pudo guardar el perfil`,savedWithUntargeted:`Perfil guardado con agentes sin asignar`,savedWithUntargetedDescription:`Ninguna regla de enrutado apunta a: {{agents}}. Añade una regla por etiquetas o reorienta la regla por defecto si quieres que se ejecuten.`},createDialog:{title:`Nuevo perfil`,description:`Elige un nombre en minúsculas y kebab-case (letras, dígitos y guiones).`,confirmLabel:`Crear`,invalidHint:`Debe empezar por una letra o un dígito y contener solo letras minúsculas, dígitos y guiones.`},duplicateDialog:{title:`Duplicar «{{name}}»`,description:`Nombre para el nuevo perfil.`,invalidHint:`Solo minúsculas en kebab-case.`},deleteDialog:{title:`¿Eliminar el perfil «{{name}}»?`,description:`Esta acción no se puede deshacer. Los jobs ya lanzados con este perfil conservan su snapshot; los próximos lanzamientos usarán el orden de resolución.`},empty:{title:`Aún no hay perfiles`,body:`Los perfiles te permiten guardar combinaciones de orquestador + agentes + enrutado y elegir una por rail.`,migrateButton:`Migrar desde los agentes actuales`,blankButton:`Perfil en blanco`,migrateExplainer:`«Migrar» lee los modelos del frontmatter de tu <code>.claude/agents/</code> actual y crea un perfil <code>default</code> que replica el comportamiento de hoy — sin pérdidas.`},sidebar:{title:`Perfiles`,teamDefault:`(por defecto del equipo)`},editorFooter:{fixValidationIssues:`Corrige los problemas de validación antes de guardar`,issuesToResolve_one:`{{count}} problema por resolver`,issuesToResolve_other:`{{count}} problemas por resolver`}},r={title:`Uso de perfiles`,windowLabel:`{{days}}d`,subtitleEmpty:`Jobs lanzados por perfil en la ventana seleccionada.`,subtitle:`Jobs lanzados por perfil en los últimos {{count}} días.`,empty:`Aún no hay jobs con perfil.`,jobsTooltip:`jobs`,jobsLabel_one:`job`,jobsLabel_other:`jobs`,successRateTooltip:`tasa de éxito`,okSuffix:`ok`,avgDurationTooltip:`duración media`,avgTokensTooltip:`media de tokens`,tokensSuffix:`tok`},i={addTitle:`Añadir regla de enrutado`,editTitle:`Editar regla de enrutado`,addDescription:`Añade una regla de enrutado por etiquetas usando etiquetas en minúsculas y kebab-case.`,editDescription:`Actualiza las etiquetas o el agente de destino de esta regla.`,tagsLabel:`Etiquetas`,tagsHint:`Separadas por comas. Usa minúsculas en kebab-case, como <code>frontend</code> o <code>api-design</code>.`,invalidTags_one:`Etiqueta no válida: {{tags}}. Las etiquetas solo pueden contener letras minúsculas, dígitos y guiones.`,invalidTags_other:`Etiquetas no válidas: {{tags}}. Las etiquetas solo pueden contener letras minúsculas, dígitos y guiones.`,routeToLabel:`Enrutar a`,routeToHint:`Solo los agentes de la cadena de este perfil pueden ser destinos de enrutado.`,addRule:`Añadir regla`,saveChanges:`Guardar cambios`},a={profileTitle:`Perfil de agentes para este rail`,noProfile:`Sin perfil`,modelTitle:`Modelo para este rail Freestyle`,loopModelTitle:`Modelo para este loop`,engineTitle:`Proveedor de IA para todos los roles de este lanzamiento: arquitecto, desarrollador y revisor`,localEngine:`Motor local`,rolesEngine:`Roles`,rolesEngineTitle:`Motores híbridos por rol: architect, developer y reviewer usan la configuración del runtime; verifier y decider usan los roles del loop (Ajustes ▸ Agentes Specrails)`,rolesChip:`Motores por rol`,rolesChipTitle:`Motores configurados por rol en Ajustes ▸ Agentes Specrails: architect, developer y reviewer desde la configuración del runtime; verifier y decider desde los roles del loop. Aquí no se elige modelo, esfuerzo ni perfil.`},o={page:e,catalog:t,profiles:n,usage:r,routingRule:i,railSelectors:a};export{t as catalog,o as default,e as page,n as profiles,a as railSelectors,i as routingRule,r as usage};