open-multi-agent-kit 0.92.0 → 0.94.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 (173) hide show
  1. package/CHANGELOG.md +38 -1
  2. package/README.md +2 -2
  3. package/dist/core/agent-session.d.ts +36 -14
  4. package/dist/core/agent-session.d.ts.map +1 -1
  5. package/dist/core/agent-session.js +155 -357
  6. package/dist/core/agent-session.js.map +1 -1
  7. package/dist/core/compaction/branch-summarization.d.ts +5 -1
  8. package/dist/core/compaction/branch-summarization.d.ts.map +1 -1
  9. package/dist/core/compaction/branch-summarization.js +5 -7
  10. package/dist/core/compaction/branch-summarization.js.map +1 -1
  11. package/dist/core/compaction/compaction.d.ts +12 -3
  12. package/dist/core/compaction/compaction.d.ts.map +1 -1
  13. package/dist/core/compaction/compaction.js +28 -15
  14. package/dist/core/compaction/compaction.js.map +1 -1
  15. package/dist/core/extensions/builtin/command-safety-gate.d.ts +8 -0
  16. package/dist/core/extensions/builtin/command-safety-gate.d.ts.map +1 -1
  17. package/dist/core/extensions/builtin/command-safety-gate.js +23 -0
  18. package/dist/core/extensions/builtin/command-safety-gate.js.map +1 -1
  19. package/dist/core/extensions/runner.d.ts.map +1 -1
  20. package/dist/core/extensions/runner.js +4 -0
  21. package/dist/core/extensions/runner.js.map +1 -1
  22. package/dist/core/extensions/types.d.ts +2 -0
  23. package/dist/core/extensions/types.d.ts.map +1 -1
  24. package/dist/core/extensions/types.js.map +1 -1
  25. package/dist/core/keybindings.d.ts +5 -0
  26. package/dist/core/keybindings.d.ts.map +1 -1
  27. package/dist/core/keybindings.js +5 -0
  28. package/dist/core/keybindings.js.map +1 -1
  29. package/dist/core/model-resolver.d.ts +41 -3
  30. package/dist/core/model-resolver.d.ts.map +1 -1
  31. package/dist/core/model-resolver.js +17 -9
  32. package/dist/core/model-resolver.js.map +1 -1
  33. package/dist/core/package-manager.d.ts.map +1 -1
  34. package/dist/core/package-manager.js +11 -1
  35. package/dist/core/package-manager.js.map +1 -1
  36. package/dist/core/provider-resilience.d.ts.map +1 -1
  37. package/dist/core/provider-resilience.js +3 -1
  38. package/dist/core/provider-resilience.js.map +1 -1
  39. package/dist/core/reasoning-router-v4-weights.d.ts.map +1 -1
  40. package/dist/core/reasoning-router-v4-weights.js +9 -3
  41. package/dist/core/reasoning-router-v4-weights.js.map +1 -1
  42. package/dist/core/reasoning-router-v4.d.ts.map +1 -1
  43. package/dist/core/reasoning-router-v4.js +94 -24
  44. package/dist/core/reasoning-router-v4.js.map +1 -1
  45. package/dist/core/resource-loader.d.ts.map +1 -1
  46. package/dist/core/resource-loader.js +11 -5
  47. package/dist/core/resource-loader.js.map +1 -1
  48. package/dist/core/sandbox/default-policy.d.ts +14 -0
  49. package/dist/core/sandbox/default-policy.d.ts.map +1 -0
  50. package/dist/core/sandbox/default-policy.js +58 -0
  51. package/dist/core/sandbox/default-policy.js.map +1 -0
  52. package/dist/core/sdk.d.ts.map +1 -1
  53. package/dist/core/sdk.js +1 -1
  54. package/dist/core/sdk.js.map +1 -1
  55. package/dist/core/session-bash-runtime.d.ts +62 -0
  56. package/dist/core/session-bash-runtime.d.ts.map +1 -0
  57. package/dist/core/session-bash-runtime.js +167 -0
  58. package/dist/core/session-bash-runtime.js.map +1 -0
  59. package/dist/core/session-bash-service.d.ts +61 -0
  60. package/dist/core/session-bash-service.d.ts.map +1 -0
  61. package/dist/core/session-bash-service.js +155 -0
  62. package/dist/core/session-bash-service.js.map +1 -0
  63. package/dist/core/session-compaction-service.d.ts +48 -0
  64. package/dist/core/session-compaction-service.d.ts.map +1 -0
  65. package/dist/core/session-compaction-service.js +250 -0
  66. package/dist/core/session-compaction-service.js.map +1 -0
  67. package/dist/core/session-file-compaction.d.ts.map +1 -1
  68. package/dist/core/session-file-compaction.js +39 -5
  69. package/dist/core/session-file-compaction.js.map +1 -1
  70. package/dist/core/session-termination.d.ts.map +1 -1
  71. package/dist/core/session-termination.js +1 -1
  72. package/dist/core/session-termination.js.map +1 -1
  73. package/dist/core/settings-manager.d.ts +3 -0
  74. package/dist/core/settings-manager.d.ts.map +1 -1
  75. package/dist/core/settings-manager.js +8 -0
  76. package/dist/core/settings-manager.js.map +1 -1
  77. package/dist/core/skills-catalog-cache.d.ts +25 -0
  78. package/dist/core/skills-catalog-cache.d.ts.map +1 -0
  79. package/dist/core/skills-catalog-cache.js +123 -0
  80. package/dist/core/skills-catalog-cache.js.map +1 -0
  81. package/dist/core/skills.d.ts +6 -0
  82. package/dist/core/skills.d.ts.map +1 -1
  83. package/dist/core/skills.js +25 -4
  84. package/dist/core/skills.js.map +1 -1
  85. package/dist/core/system-prompt.d.ts.map +1 -1
  86. package/dist/core/system-prompt.js +2 -2
  87. package/dist/core/system-prompt.js.map +1 -1
  88. package/dist/core/tools/bash.d.ts +5 -0
  89. package/dist/core/tools/bash.d.ts.map +1 -1
  90. package/dist/core/tools/bash.js +41 -13
  91. package/dist/core/tools/bash.js.map +1 -1
  92. package/dist/core/tools/diagnostics.d.ts +29 -0
  93. package/dist/core/tools/diagnostics.d.ts.map +1 -0
  94. package/dist/core/tools/diagnostics.js +325 -0
  95. package/dist/core/tools/diagnostics.js.map +1 -0
  96. package/dist/core/tools/index.d.ts +2 -1
  97. package/dist/core/tools/index.d.ts.map +1 -1
  98. package/dist/core/tools/index.js +18 -1
  99. package/dist/core/tools/index.js.map +1 -1
  100. package/dist/core/verified-bash-adapter.d.ts +18 -1
  101. package/dist/core/verified-bash-adapter.d.ts.map +1 -1
  102. package/dist/core/verified-bash-adapter.js +38 -1
  103. package/dist/core/verified-bash-adapter.js.map +1 -1
  104. package/dist/core/verified-bash-runtime.d.ts +13 -0
  105. package/dist/core/verified-bash-runtime.d.ts.map +1 -0
  106. package/dist/core/verified-bash-runtime.js +81 -0
  107. package/dist/core/verified-bash-runtime.js.map +1 -0
  108. package/dist/index.d.ts +4 -2
  109. package/dist/index.d.ts.map +1 -1
  110. package/dist/index.js +4 -2
  111. package/dist/index.js.map +1 -1
  112. package/dist/modes/interactive/components/control-panel-box.d.ts +27 -0
  113. package/dist/modes/interactive/components/control-panel-box.d.ts.map +1 -1
  114. package/dist/modes/interactive/components/control-panel-box.js +60 -8
  115. package/dist/modes/interactive/components/control-panel-box.js.map +1 -1
  116. package/dist/modes/interactive/components/control-panel-layout.d.ts.map +1 -1
  117. package/dist/modes/interactive/components/control-panel-layout.js +100 -45
  118. package/dist/modes/interactive/components/control-panel-layout.js.map +1 -1
  119. package/dist/modes/interactive/components/control-panel-runtime-status.d.ts +9 -0
  120. package/dist/modes/interactive/components/control-panel-runtime-status.d.ts.map +1 -1
  121. package/dist/modes/interactive/components/control-panel-runtime-status.js +10 -8
  122. package/dist/modes/interactive/components/control-panel-runtime-status.js.map +1 -1
  123. package/dist/modes/interactive/components/control-panel-sparkles.d.ts +5 -0
  124. package/dist/modes/interactive/components/control-panel-sparkles.d.ts.map +1 -1
  125. package/dist/modes/interactive/components/control-panel-sparkles.js +14 -9
  126. package/dist/modes/interactive/components/control-panel-sparkles.js.map +1 -1
  127. package/dist/modes/interactive/components/footer.d.ts +10 -0
  128. package/dist/modes/interactive/components/footer.d.ts.map +1 -1
  129. package/dist/modes/interactive/components/footer.js +3 -3
  130. package/dist/modes/interactive/components/footer.js.map +1 -1
  131. package/dist/modes/interactive/components/status-sidebar.d.ts +49 -0
  132. package/dist/modes/interactive/components/status-sidebar.d.ts.map +1 -0
  133. package/dist/modes/interactive/components/status-sidebar.js +253 -0
  134. package/dist/modes/interactive/components/status-sidebar.js.map +1 -0
  135. package/dist/modes/interactive/interactive-mode.d.ts +9 -0
  136. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  137. package/dist/modes/interactive/interactive-mode.js +94 -20
  138. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  139. package/dist/modes/interactive/theme/omk-neon-control.json +13 -13
  140. package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  141. package/dist/modes/rpc/rpc-mode.js +1 -0
  142. package/dist/modes/rpc/rpc-mode.js.map +1 -1
  143. package/dist/types/evidence.d.ts +1 -1
  144. package/dist/types/evidence.d.ts.map +1 -1
  145. package/dist/types/evidence.js.map +1 -1
  146. package/dist/utils/clipboard.d.ts.map +1 -1
  147. package/dist/utils/clipboard.js +19 -8
  148. package/dist/utils/clipboard.js.map +1 -1
  149. package/dist/utils/frontmatter.d.ts.map +1 -1
  150. package/dist/utils/frontmatter.js +31 -5
  151. package/dist/utils/frontmatter.js.map +1 -1
  152. package/docs/compaction.md +7 -0
  153. package/docs/docs.json +4 -0
  154. package/docs/environment-variables.md +94 -0
  155. package/docs/index.md +1 -0
  156. package/docs/rpc.md +5 -2
  157. package/docs/sdk.md +10 -4
  158. package/docs/settings.md +1 -0
  159. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  160. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  161. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  162. package/examples/extensions/gondolin/package-lock.json +2 -2
  163. package/examples/extensions/gondolin/package.json +1 -1
  164. package/examples/extensions/sandbox/package-lock.json +2 -2
  165. package/examples/extensions/sandbox/package.json +1 -1
  166. package/examples/extensions/subagent/agents.test.ts +86 -0
  167. package/examples/extensions/subagent/agents.ts +18 -4
  168. package/examples/extensions/subagent/capabilities.ts +15 -1
  169. package/examples/extensions/subagent/domain-profiles.ts +272 -0
  170. package/examples/extensions/with-deps/package-lock.json +2 -2
  171. package/examples/extensions/with-deps/package.json +1 -1
  172. package/npm-shrinkwrap.json +15 -15
  173. package/package.json +10 -7
@@ -1 +1 @@
1
- {"version":3,"file":"control-panel-layout.js","sourceRoot":"","sources":["../../../../src/modes/interactive/components/control-panel-layout.ts"],"names":[],"mappings":"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","sourcesContent":["import { truncateToWidth, visibleWidth } from \"omk-tui\";\nimport type { PiPackageIntakeSummary } from \"../../../core/pi-package-intake.ts\";\nimport { nextActiveTodo, type TodoState, summary as todoSummary } from \"../../../core/todo-state.ts\";\nimport { type ThemeColor, theme } from \"../theme/theme.ts\";\nimport {\n\tboxBottom,\n\tboxCenteredLine,\n\tboxTextLine,\n\tboxTop,\n\tcenterLine,\n\tcomposeColumns,\n\tdivider,\n\tfitLine,\n\tsidebarRule,\n\ttextLine,\n} from \"./control-panel-box.ts\";\nimport { SPARKLE_ROW_BOTTOM, SPARKLE_ROW_TOP, sparkleRow } from \"./control-panel-sparkles.ts\";\n\nexport const CONTROL_PANEL_ASCII_ART = [\n\t\" ███████ ██ ██ ██ ██\",\n\t\"██ ██ ███ ███ ██ ██ \",\n\t\"██ ██ ████ ████ ██ ██ \",\n\t\"██ ██ ██ ██ ██ ██ █████ \",\n\t\"██ ██ ██ ███ ██ ██ ██ \",\n\t\"██ ██ ██ █ ██ ██ ██ \",\n\t\" ███████ ██ ██ ██ ██\",\n];\nconst META_WIDTH = 31;\nexport const CONTROL_PANEL_OVERLAY_MIN_WIDTH = 112;\nexport const CONTROL_PANEL_DECK_MIN_WIDTH = CONTROL_PANEL_OVERLAY_MIN_WIDTH + 1;\nexport const CONTROL_PANEL_SIDEBAR_WIDTH = 38;\nexport const CONTROL_PANEL_GAP_WIDTH = 2;\nconst CONTEXT_METER_CELLS = 12;\nconst SPARKLINE_WIDTH = 16;\nconst SPARKLINE_GLYPHS = \"▁▂▃▄▅▆▇█\";\n\nexport interface ControlPanelContent {\n\tappName: string;\n\tversion: string;\n\tcompactInstructions: () => string;\n\texpandedInstructions: () => string;\n\tcompactOnboarding: () => string;\n\tonboarding: () => string;\n\tstatusSnapshot?: () => ControlPanelStatusSnapshot;\n}\n\nexport interface ControlPanelStatusSnapshot {\n\treadonly modelId?: string;\n\treadonly modelProvider?: string;\n\treadonly thinkingLevel?: string;\n\treadonly contextPercent?: number | null;\n\treadonly contextWindowTokens?: number;\n\treadonly contextTokens?: number | null;\n\treadonly headroomStatus?: string;\n\treadonly optimizerPolicy?: string;\n\treadonly skillCount?: number;\n\treadonly mcpCount?: number;\n\treadonly packageIntake?: PiPackageIntakeSummary;\n\treadonly cwdLabel?: string;\n\treadonly gitBranch?: string | null;\n\treadonly todoState?: TodoState;\n\treadonly runtimeState?: string;\n\treadonly routeState?: string;\n\treadonly evidenceState?: string;\n\treadonly controlState?: string;\n\treadonly dagOrchestrationState?: string;\n\treadonly ansiColorState?: string;\n\treadonly startupState?: string;\n\treadonly linkState?: string;\n\treadonly sidebarState?: string;\n}\n\nexport function renderControlPanelLayout(\n\tcontent: ControlPanelContent,\n\texpanded: boolean,\n\twidth: number,\n\tbannerFrame?: string[],\n\tsparkleMs = 0,\n): string[] {\n\tif (width <= 0) return [];\n\treturn expanded\n\t\t? renderExpanded(content, width, bannerFrame, sparkleMs)\n\t\t: renderCompact(content, width, bannerFrame, sparkleMs);\n}\n\nexport function renderControlPanelRightPane(content: ControlPanelContent, width: number): string[] {\n\tif (width <= 0) return [];\n\treturn sidebarPanel(content, width);\n}\n\nfunction renderCompact(content: ControlPanelContent, width: number, bannerFrame?: string[], sparkleMs = 0): string[] {\n\tif (width >= CONTROL_PANEL_DECK_MIN_WIDTH) {\n\t\tconst deck = renderDeck(content, width, bannerFrame, sparkleMs);\n\t\tif (deck.length > 0) return deck;\n\t}\n\treturn [\n\t\tdivider(width, \"OMK//CONTROL PANEL\", \"accent\"),\n\t\tstatusLine(content, width),\n\t\ttextLine(width, content.compactInstructions()),\n\t\ttextLine(width, content.compactOnboarding(), \"dim\"),\n\t];\n}\n\nfunction renderDeck(content: ControlPanelContent, width: number, bannerFrame?: string[], sparkleMs = 0): string[] {\n\tconst { leftWidth, sidebarWidth } = deckWidths(width);\n\tif (leftWidth < 72) return [];\n\tconst lines = composeColumns(\n\t\theroPanel(content, leftWidth, bannerFrame, sparkleMs),\n\t\tleftWidth,\n\t\tsidebarPanel(content, sidebarWidth),\n\t\tsidebarWidth,\n\t\tCONTROL_PANEL_GAP_WIDTH,\n\t\twidth,\n\t);\n\tlines.push(controlStripLine(content, width));\n\tlines.push(centerLine(width, content.compactOnboarding(), \"dim\"));\n\treturn lines;\n}\n\nfunction deckWidths(width: number): { leftWidth: number; sidebarWidth: number } {\n\tconst sidebarWidth = Math.min(CONTROL_PANEL_SIDEBAR_WIDTH, Math.max(34, Math.floor(width * 0.28)));\n\treturn { leftWidth: width - CONTROL_PANEL_GAP_WIDTH - sidebarWidth, sidebarWidth };\n}\n\nfunction heroPanel(content: ControlPanelContent, width: number, bannerFrame?: string[], sparkleMs = 0): string[] {\n\tconst snapshot = statusSnapshot(content);\n\tconst innerWidth = Math.max(0, width - 4);\n\treturn [\n\t\tboxTop(width, `omk v${content.version} · OMK://CONTROL`),\n\t\tboxCenteredLine(width, theme.bold(theme.fg(\"accent\", \"OMK\"))),\n\t\tboxCenteredLine(width, theme.fg(\"muted\", \"route · verify · loop · control\")),\n\t\tboxTextLine(width, sparkleRow(innerWidth, SPARKLE_ROW_TOP, sparkleMs)),\n\t\t...(bannerFrame ?? CONTROL_PANEL_ASCII_ART).map((line, index) => {\n\t\t\tif (bannerFrame) return boxCenteredLine(width, line);\n\t\t\tconst color: ThemeColor = index < 2 ? \"mdCode\" : index < 4 ? \"accent\" : index < 6 ? \"success\" : \"warning\";\n\t\t\treturn boxCenteredLine(width, theme.fg(color, line));\n\t\t}),\n\t\tboxTextLine(width, sparkleRow(innerWidth, SPARKLE_ROW_BOTTOM, sparkleMs)),\n\t\tboxCenteredLine(\n\t\t\twidth,\n\t\t\t`${theme.fg(\"warning\", \"●\")} ${theme.bold(\"OMK\")} / ${theme.fg(\"success\", heroModelLabel(snapshot))}`,\n\t\t),\n\t\tboxCenteredLine(\n\t\t\twidth,\n\t\t\t`${theme.fg(\"mdCode\", \"◇\")} omk-control · ${theme.fg(\"accent\", \"route\")} · ${theme.fg(\"warning\", \"verify\")} · ${theme.fg(\"success\", \"loop\")} · ${theme.fg(\"mdCode\", \"control\")}`,\n\t\t),\n\t\tboxBottom(width),\n\t];\n}\n\nfunction heroModelLabel(snapshot: ControlPanelStatusSnapshot): string {\n\tif (!snapshot.modelId) return \"no-model\";\n\tconst think = snapshot.thinkingLevel;\n\treturn think && think !== \"off\" ? `${snapshot.modelId}:${think}` : snapshot.modelId;\n}\n\nfunction sidebarPanel(content: ControlPanelContent, width: number): string[] {\n\tconst snapshot = statusSnapshot(content);\n\tconst headroomLabel = snapshot.headroomStatus ?? snapshot.optimizerPolicy ?? \"unknown\";\n\tconst mcpCount = snapshot.mcpCount;\n\tconst skillCount = snapshot.skillCount;\n\tconst packageIntakeLabel = packageIntakeStatusLabel(snapshot.packageIntake);\n\tconst contextMeter = contextMeterLabel(snapshot);\n\tconst activitySparkline = activitySparklineLabel(snapshot);\n\treturn [\n\t\tsidebarTabs(width),\n\t\tboxCenteredLine(width, theme.bold(theme.fg(\"accent\", \"OMK://CONTROL\"))),\n\t\tboxCenteredLine(width, theme.bold(theme.fg(\"warning\", \"CYBERPUNK OPS CORE\"))),\n\t\tboxCenteredLine(width, `${theme.fg(\"mdCode\", \"MATRIX RAIN\")} // ${theme.fg(\"success\", \"NEON GRID ONLINE\")}`),\n\t\tboxCenteredLine(width, theme.fg(\"text\", \"NIGHT-CITY-MATRIX-V3\")),\n\t\tsidebarRule(width, \"STATUS\", \"accent\"),\n\t\tboxTextLine(width, `${theme.fg(\"muted\", \"state:\")} ${coloredStatus(snapshot.runtimeState ?? \"unknown\")}`),\n\t\tboxTextLine(width, `${theme.fg(\"muted\", \"route:\")} ${coloredStatus(snapshot.routeState ?? \"unknown\")}`),\n\t\tboxTextLine(width, `${theme.fg(\"muted\", \"evidence:\")} ${coloredStatus(snapshot.evidenceState ?? \"unknown\")}`),\n\t\tsidebarRule(width, \"TODO\", \"accent\"),\n\t\t...todoSidebarLines(snapshot.todoState, width),\n\t\tsidebarRule(width, \"SESSION\", \"accent\"),\n\t\tsemanticBoxTextLine(width, \"cwd\", snapshot.cwdLabel ?? \"?\", \"end\"),\n\t\tsemanticBoxTextLine(width, \"git\", snapshot.gitBranch ?? \"?\", \"start\"),\n\t\tsidebarRule(width, \"MODEL / CTX\", \"accent\"),\n\t\tsemanticBoxTextLine(width, \"model\", modelStatusLabel(snapshot), \"end\"),\n\t\tsemanticBoxTextLine(width, \"think\", snapshot.thinkingLevel ?? \"off\", \"start\"),\n\t\tboxTextLine(\n\t\t\twidth,\n\t\t\t`${theme.fg(\"muted\", \"ctx:\")} ${theme.fg(statusColor(snapshot.contextPercent === undefined || snapshot.contextPercent === null ? \"unknown\" : \"ready\"), contextStatusLabel(snapshot))}`,\n\t\t),\n\t\tboxTextLine(width, `${theme.fg(\"muted\", \"meter:\")} ${contextMeter}`),\n\t\tboxTextLine(width, `${theme.fg(\"muted\", \"pulse:\")} ${activitySparkline}`),\n\t\tsidebarRule(width, \"RUNTIME / MCP / SKILLS\", \"accent\"),\n\t\tsemanticBoxTextLine(width, \"headroom\", headroomLabel, \"end\"),\n\t\tsemanticBoxTextLine(width, \"omk\", snapshot.dagOrchestrationState ?? \"unknown\", \"end\"),\n\t\tsemanticBoxTextLine(width, \"sidebar\", snapshot.sidebarState ?? \"unknown\", \"start\"),\n\t\tboxTextLine(width, `${theme.fg(\"muted\", \"res:\")} MCP:${mcpCount ?? \"?\"} skills:${skillCount ?? \"?\"}`),\n\t\tsemanticBoxTextLine(width, \"pkg\", packageIntakeLabel, \"end\"),\n\t\tsidebarRule(width, \"CONTROL\", \"accent\"),\n\t\tboxTextLine(width, `${theme.fg(\"muted\", \"route:\")} ${coloredStatus(snapshot.routeState ?? \"unknown\")}`),\n\t\tboxTextLine(width, `${theme.fg(\"muted\", \"verify:\")} ${coloredStatus(snapshot.evidenceState ?? \"unknown\")}`),\n\t\tboxTextLine(width, `${theme.fg(\"muted\", \"control:\")} ${coloredStatus(snapshot.controlState ?? \"unknown\")}`),\n\t\tboxBottom(width, \"accent\"),\n\t];\n}\n\nfunction semanticBoxTextLine(\n\twidth: number,\n\tlabel: string,\n\tvalue: string,\n\tpreserve: \"start\" | \"middle\" | \"end\",\n): string {\n\tconst prefix = `${theme.fg(\"muted\", `${label}:`)} `;\n\tconst availableWidth = Math.max(0, width - 4 - visibleWidth(prefix));\n\treturn boxTextLine(width, `${prefix}${semanticTruncate(value, availableWidth, preserve)}`);\n}\n\nfunction semanticTruncate(value: string, maxWidth: number, preserve: \"start\" | \"middle\" | \"end\"): string {\n\tif (visibleWidth(value) <= maxWidth) return value;\n\tif (maxWidth <= 0) return \"\";\n\tif (preserve === \"start\") return truncateToWidth(value, maxWidth, \"…\");\n\tconst ellipsis = \"…\";\n\tconst targetWidth = maxWidth - visibleWidth(ellipsis);\n\tif (targetWidth <= 0) return truncateToWidth(ellipsis, maxWidth, \"\");\n\tif (preserve === \"middle\") {\n\t\tconst headWidth = Math.max(1, Math.floor(targetWidth / 2));\n\t\tconst tailWidth = Math.max(1, targetWidth - headWidth);\n\t\treturn `${takeStart(value, headWidth)}${ellipsis}${takeEnd(value, tailWidth)}`;\n\t}\n\treturn `${ellipsis}${takeEnd(value, targetWidth)}`;\n}\n\nfunction takeStart(value: string, maxWidth: number): string {\n\tlet prefix = \"\";\n\tfor (const char of Array.from(value)) {\n\t\tif (visibleWidth(prefix + char) > maxWidth) break;\n\t\tprefix += char;\n\t}\n\treturn prefix;\n}\n\nfunction takeEnd(value: string, maxWidth: number): string {\n\tlet suffix = \"\";\n\tfor (const char of Array.from(value).reverse()) {\n\t\tif (visibleWidth(char + suffix) > maxWidth) break;\n\t\tsuffix = char + suffix;\n\t}\n\treturn suffix;\n}\n\nfunction statusToken(label: string, value: string | undefined): string {\n\tconst state = value ?? \"unknown\";\n\treturn theme.fg(statusColor(state), `${label}:${state.toUpperCase()}`);\n}\n\nfunction coloredStatus(value: string): string {\n\treturn theme.fg(statusColor(value), value);\n}\n\nfunction statusColor(value: string): ThemeColor {\n\tconst normalized = value.toLowerCase();\n\tif ([\"ready\", \"on\", \"active\", \"available\", \"linked\", \"tracking\", \"pinned\"].includes(normalized)) return \"success\";\n\tif ([\"degraded\", \"limited\", \"blocked\", \"off\"].includes(normalized)) return \"warning\";\n\treturn \"muted\";\n}\n\nfunction todoSidebarLines(state: TodoState | undefined, width: number): string[] {\n\tif (!state || state.items.length === 0) {\n\t\treturn [\n\t\t\tboxTextLine(width, `${theme.fg(\"muted\", \"todo:\")} empty`),\n\t\t\tboxTextLine(width, `${theme.fg(\"muted\", \"next:\")} no active todos`),\n\t\t];\n\t}\n\tconst counts = todoSummary(state);\n\tconst next = nextActiveTodo(state);\n\treturn [\n\t\tboxTextLine(width, `${theme.fg(\"muted\", \"todo:\")} ${counts.done}/${counts.total} done`),\n\t\tsemanticBoxTextLine(width, \"next\", next?.label ?? \"complete\", \"middle\"),\n\t];\n}\n\nfunction packageIntakeStatusLabel(summary: PiPackageIntakeSummary | undefined): string {\n\tif (!summary) return \"ports:pending\";\n\tconst ready =\n\t\tsummary.acceptedNative + summary.acceptedReference + summary.acceptedMeasurement + summary.acceptedAdvisory;\n\tconst review = summary.deferred + summary.reject;\n\treturn `ports:${ready}/${summary.total} review:${review} block:${summary.hardForkBlocked}`;\n}\n\nfunction renderExpanded(content: ControlPanelContent, width: number, bannerFrame?: string[], sparkleMs = 0): string[] {\n\tif (width >= CONTROL_PANEL_DECK_MIN_WIDTH) {\n\t\tconst { leftWidth, sidebarWidth } = deckWidths(width);\n\t\tconst resourceLines = [\"\", ...content.onboarding().split(\"\\n\")];\n\t\tconst rightRail = blankSidebarRail(sidebarWidth, resourceLines.length);\n\t\tconst lines = [...renderDeck(content, width, bannerFrame, sparkleMs)];\n\t\tlines.push(...composeColumns(resourceLines, leftWidth, rightRail, sidebarWidth, CONTROL_PANEL_GAP_WIDTH, width));\n\t\treturn lines;\n\t}\n\n\tconst lines = [divider(width, \"OMK//CONTROL PANEL\", \"accent\"), statusLine(content, width)];\n\tif (width >= 32) lines.push(...brandLines(content, width, bannerFrame));\n\tlines.push(divider(width, \"SYSTEM MAP\", \"mdHeading\"));\n\tfor (const instruction of content.expandedInstructions().split(\"\\n\")) lines.push(textLine(width, instruction));\n\tlines.push(divider(width, \"STARTUP LINK\", \"success\"));\n\tfor (const onboardingLine of content.onboarding().split(\"\\n\")) lines.push(textLine(width, onboardingLine, \"dim\"));\n\tlines.push(divider(width, \"END\", \"borderMuted\"));\n\treturn lines;\n}\n\nfunction blankSidebarRail(width: number, lineCount: number): string[] {\n\treturn Array.from({ length: lineCount }, () => boxTextLine(width, \"\"));\n}\n\nfunction statusSnapshot(content: ControlPanelContent): ControlPanelStatusSnapshot {\n\treturn content.statusSnapshot?.() ?? {};\n}\n\nfunction modelStatusLabel(snapshot: ControlPanelStatusSnapshot): string {\n\tif (!snapshot.modelId) return \"no-model\";\n\treturn snapshot.modelProvider ? `${snapshot.modelProvider}/${snapshot.modelId}` : snapshot.modelId;\n}\n\nfunction contextStatusLabel(snapshot: ControlPanelStatusSnapshot): string {\n\tconst windowTokens = snapshot.contextWindowTokens ?? 0;\n\tconst windowLabel = windowTokens > 0 ? formatTokens(windowTokens) : \"?\";\n\treturn snapshot.contextPercent === null || snapshot.contextPercent === undefined\n\t\t? `?/${windowLabel}`\n\t\t: `${snapshot.contextPercent.toFixed(1)}%/${windowLabel}`;\n}\n\nfunction contextMeterLabel(snapshot: ControlPanelStatusSnapshot): string {\n\tconst percent = normalizePercent(snapshot.contextPercent);\n\tif (percent === undefined) {\n\t\treturn `${theme.fg(\"borderMuted\", \"░\".repeat(CONTEXT_METER_CELLS))} ${theme.fg(\"muted\", \"??%\")}`;\n\t}\n\tconst filled = Math.max(0, Math.min(CONTEXT_METER_CELLS, Math.round((percent / 100) * CONTEXT_METER_CELLS)));\n\tconst color: ThemeColor = percent >= 85 ? \"warning\" : percent >= 65 ? \"mdCode\" : \"success\";\n\treturn `${theme.fg(color, \"█\".repeat(filled))}${theme.fg(\"borderMuted\", \"░\".repeat(CONTEXT_METER_CELLS - filled))} ${theme.fg(color, `${Math.round(percent)}%`)}`;\n}\n\nfunction activitySparklineLabel(snapshot: ControlPanelStatusSnapshot): string {\n\tconst seed = hashSnapshot(snapshot);\n\tconst glyphs = Array.from(SPARKLINE_GLYPHS);\n\tconst parts: string[] = [];\n\tfor (let index = 0; index < SPARKLINE_WIDTH; index++) {\n\t\tconst glyph = glyphs[(seed + index * 5 + index * index) % glyphs.length] ?? \"▁\";\n\t\tconst color: ThemeColor = index % 5 === 0 ? \"accent\" : index % 3 === 0 ? \"warning\" : \"success\";\n\t\tparts.push(theme.fg(color, glyph));\n\t}\n\treturn parts.join(\"\");\n}\n\nfunction normalizePercent(value: number | null | undefined): number | undefined {\n\tif (value === null || value === undefined || !Number.isFinite(value)) return undefined;\n\tif (value < 0) return 0;\n\tif (value > 100) return 100;\n\treturn value;\n}\n\nfunction hashSnapshot(snapshot: ControlPanelStatusSnapshot): number {\n\tconst source = [\n\t\tsnapshot.modelProvider,\n\t\tsnapshot.modelId,\n\t\tsnapshot.contextPercent?.toFixed(1),\n\t\tsnapshot.contextTokens,\n\t\tsnapshot.contextWindowTokens,\n\t\tsnapshot.cwdLabel,\n\t\tsnapshot.gitBranch,\n\t].join(\"|\");\n\tlet hash = 2166136261;\n\tfor (let index = 0; index < source.length; index++) {\n\t\thash ^= source.charCodeAt(index);\n\t\thash = Math.imul(hash, 16777619);\n\t}\n\treturn hash >>> 0;\n}\n\nfunction formatTokens(count: number): string {\n\tif (count < 1000) return count.toString();\n\tif (count < 10000) return `${(count / 1000).toFixed(1)}k`;\n\tif (count < 1000000) return `${Math.round(count / 1000)}k`;\n\tif (count < 10000000) return `${(count / 1000000).toFixed(1)}M`;\n\treturn `${Math.round(count / 1000000)}M`;\n}\n\nfunction sidebarTabs(width: number): string {\n\treturn boxTextLine(\n\t\twidth,\n\t\tfitLine(\n\t\t\t`${theme.bold(theme.fg(\"accent\", \"1:CONTROL\"))} ${theme.fg(\"muted\", \"2:HISTORY\")}`,\n\t\t\tMath.max(0, width - 4),\n\t\t),\n\t);\n}\n\nfunction controlStripLine(content: ControlPanelContent, width: number): string {\n\treturn centerLine(\n\t\twidth,\n\t\t`${theme.bold(theme.fg(\"accent\", \"OMK://CONTROL READ\"))} ${theme.fg(\"accent\", \"route/verify/loop/control\")} · ${content.compactInstructions()}`,\n\t);\n}\n\nfunction brandLines(content: ControlPanelContent, width: number, bannerFrame?: string[]): string[] {\n\tconst art = bannerFrame ?? CONTROL_PANEL_ASCII_ART;\n\tif (bannerFrame) return art.map((line) => textLine(width, line));\n\tconst leftWidth = Math.max(...art.map((line) => visibleWidth(line)));\n\tconst minWideWidth = visibleWidth(\"| \") + leftWidth + visibleWidth(\" | \") + META_WIDTH;\n\tif (width < minWideWidth) return art.map((line) => textLine(width, theme.fg(\"accent\", line)));\n\tconst snapshot = statusSnapshot(content);\n\treturn art.map((line, index) =>\n\t\ttextLine(\n\t\t\twidth,\n\t\t\t`${fitLine(theme.fg(\"accent\", line), leftWidth)}${theme.fg(\"borderMuted\", \" | \")}${metadataLines(snapshot)[index] ?? \"\"}`,\n\t\t),\n\t);\n}\n\nfunction metadataLines(snapshot: ControlPanelStatusSnapshot): string[] {\n\tconst rawThemeName = theme.name ?? \"live\";\n\tconst themeName = (rawThemeName.startsWith(\"omk-\") ? rawThemeName.slice(4) : rawThemeName).toUpperCase();\n\treturn [\n\t\t`${theme.fg(\"mdCode\", \"PANEL\")} ${coloredStatus(snapshot.runtimeState ?? \"unknown\")}`,\n\t\t`${theme.fg(\"mdCode\", \"THEME\")} ${theme.fg(\"accent\", themeName)}`,\n\t\t`${theme.fg(\"mdCode\", \"STARTUP\")} ${coloredStatus(snapshot.startupState ?? \"unknown\")}`,\n\t\t`${theme.fg(\"mdCode\", \"LINK\")} ${coloredStatus(snapshot.linkState ?? \"unknown\")}`,\n\t];\n}\n\nfunction statusLine(content: ControlPanelContent, width: number): string {\n\tconst snapshot = statusSnapshot(content);\n\tconst segments = [\n\t\ttheme.bold(theme.fg(\"accent\", `${content.appName.toUpperCase()} v${content.version}`)),\n\t\tstatusToken(\"CORE\", snapshot.runtimeState),\n\t\tstatusToken(\"ANSI\", snapshot.ansiColorState),\n\t\tstatusToken(\"STARTUP\", snapshot.startupState),\n\t\tstatusToken(\"LINK\", snapshot.linkState),\n\t\ttheme.fg(\"muted\", \"THEME:LIVE\"),\n\t];\n\treturn textLine(width, segments.join(theme.fg(\"borderMuted\", \" | \")));\n}\n"]}
1
+ {"version":3,"file":"control-panel-layout.js","sourceRoot":"","sources":["../../../../src/modes/interactive/components/control-panel-layout.ts"],"names":[],"mappings":"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","sourcesContent":["import { truncateToWidth, visibleWidth } from \"omk-tui\";\nimport type { PiPackageIntakeSummary } from \"../../../core/pi-package-intake.ts\";\nimport { nextActiveTodo, type TodoState, summary as todoSummary } from \"../../../core/todo-state.ts\";\nimport { type ThemeColor, theme } from \"../theme/theme.ts\";\nimport {\n\tboxBottom,\n\tboxCenteredLine,\n\tboxRuleLine,\n\tboxTextLine,\n\tboxTop,\n\tcenterLine,\n\tcomposeColumns,\n\tdivider,\n\tfitLine,\n\tlabelCell,\n\tpadBoxColumn,\n\tsidebarRule,\n\ttextLine,\n} from \"./control-panel-box.ts\";\nimport { SPARKLE_ROW_BOTTOM, SPARKLE_ROW_TOP, sparkleRow } from \"./control-panel-sparkles.ts\";\n\nexport const CONTROL_PANEL_ASCII_ART = [\n\t\" ███████ ██ ██ ██ ██\",\n\t\"██ ██ ███ ███ ██ ██ \",\n\t\"██ ██ ████ ████ ██ ██ \",\n\t\"██ ██ ██ ██ ██ ██ █████ \",\n\t\"██ ██ ██ ███ ██ ██ ██ \",\n\t\"██ ██ ██ █ ██ ██ ██ \",\n\t\" ███████ ██ ██ ██ ██\",\n];\nconst META_WIDTH = 31;\nexport const CONTROL_PANEL_OVERLAY_MIN_WIDTH = 112;\nexport const CONTROL_PANEL_DECK_MIN_WIDTH = CONTROL_PANEL_OVERLAY_MIN_WIDTH + 1;\nexport const CONTROL_PANEL_SIDEBAR_WIDTH = 38;\nexport const CONTROL_PANEL_GAP_WIDTH = 2;\nconst CONTEXT_METER_CELLS = 12;\nconst SPARKLINE_WIDTH = 16;\nconst SPARKLINE_GLYPHS = \"▁▂▃▄▅▆▇█\";\n\nexport interface ControlPanelContent {\n\tappName: string;\n\tversion: string;\n\tcompactInstructions: () => string;\n\texpandedInstructions: () => string;\n\tcompactOnboarding: () => string;\n\tonboarding: () => string;\n\tstatusSnapshot?: () => ControlPanelStatusSnapshot;\n}\n\nexport interface ControlPanelStatusSnapshot {\n\treadonly modelId?: string;\n\treadonly modelProvider?: string;\n\treadonly thinkingLevel?: string;\n\treadonly contextPercent?: number | null;\n\treadonly contextWindowTokens?: number;\n\treadonly contextTokens?: number | null;\n\treadonly headroomStatus?: string;\n\treadonly optimizerPolicy?: string;\n\treadonly skillCount?: number;\n\treadonly mcpCount?: number;\n\treadonly packageIntake?: PiPackageIntakeSummary;\n\treadonly cwdLabel?: string;\n\treadonly gitBranch?: string | null;\n\treadonly todoState?: TodoState;\n\treadonly runtimeState?: string;\n\treadonly routeState?: string;\n\treadonly evidenceState?: string;\n\treadonly controlState?: string;\n\treadonly dagOrchestrationState?: string;\n\treadonly ansiColorState?: string;\n\treadonly startupState?: string;\n\treadonly linkState?: string;\n\treadonly sidebarState?: string;\n}\n\nexport function renderControlPanelLayout(\n\tcontent: ControlPanelContent,\n\texpanded: boolean,\n\twidth: number,\n\tbannerFrame?: string[],\n\tsparkleMs = 0,\n): string[] {\n\tif (width <= 0) return [];\n\treturn expanded\n\t\t? renderExpanded(content, width, bannerFrame, sparkleMs)\n\t\t: renderCompact(content, width, bannerFrame, sparkleMs);\n}\n\nexport function renderControlPanelRightPane(content: ControlPanelContent, width: number): string[] {\n\tif (width <= 0) return [];\n\treturn sidebarPanel(content, width);\n}\n\nfunction renderCompact(content: ControlPanelContent, width: number, bannerFrame?: string[], sparkleMs = 0): string[] {\n\tif (width >= CONTROL_PANEL_DECK_MIN_WIDTH) {\n\t\tconst deck = renderDeck(content, width, bannerFrame, sparkleMs);\n\t\tif (deck.length > 0) return deck;\n\t}\n\treturn [\n\t\tdivider(width, \"OMK//CONTROL PANEL\", \"accent\"),\n\t\tstatusLine(content, width),\n\t\ttextLine(width, content.compactInstructions()),\n\t\ttextLine(width, content.compactOnboarding(), \"dim\"),\n\t];\n}\n\nfunction renderDeck(content: ControlPanelContent, width: number, bannerFrame?: string[], sparkleMs = 0): string[] {\n\tconst { leftWidth, sidebarWidth } = deckWidths(width);\n\tif (leftWidth < 72) return [];\n\tconst hero = heroPanel(content, leftWidth, bannerFrame, sparkleMs);\n\tconst rail = sidebarPanel(content, sidebarWidth);\n\t// Both framed columns close on the same row so the deck reads as one block\n\t// instead of a short hero beside a long ragged rail.\n\tconst deckHeight = Math.max(hero.length, rail.length);\n\tconst lines = composeColumns(\n\t\tpadBoxColumn(hero, deckHeight, leftWidth, \"center\"),\n\t\tleftWidth,\n\t\tpadBoxColumn(rail, deckHeight, sidebarWidth),\n\t\tsidebarWidth,\n\t\tCONTROL_PANEL_GAP_WIDTH,\n\t\twidth,\n\t);\n\tlines.push(controlStripLine(content, width));\n\tlines.push(centerLine(width, content.compactOnboarding(), \"dim\"));\n\treturn lines;\n}\n\nfunction deckWidths(width: number): { leftWidth: number; sidebarWidth: number } {\n\tconst sidebarWidth = Math.min(CONTROL_PANEL_SIDEBAR_WIDTH, Math.max(34, Math.floor(width * 0.28)));\n\treturn { leftWidth: width - CONTROL_PANEL_GAP_WIDTH - sidebarWidth, sidebarWidth };\n}\n\nfunction heroPanel(content: ControlPanelContent, width: number, bannerFrame?: string[], sparkleMs = 0): string[] {\n\tconst snapshot = statusSnapshot(content);\n\tconst innerWidth = Math.max(0, width - 4);\n\treturn [\n\t\t// One wordmark only: the framed title chip carries the product name, so the\n\t\t// hero body is the block mark plus live state, not a second text logotype.\n\t\tboxTop(width, `omk v${content.version} · OMK://CONTROL`),\n\t\tboxTextLine(width, sparkleRow(innerWidth, SPARKLE_ROW_TOP, sparkleMs)),\n\t\t...(bannerFrame ?? CONTROL_PANEL_ASCII_ART).map((line, index, rows) => {\n\t\t\tif (bannerFrame) return boxCenteredLine(width, line);\n\t\t\t// Single-tone wordmark: the top and bottom scanlines fall back to the\n\t\t\t// dim ink so the mark reads as one lit object rather than a four-colour\n\t\t\t// stack. Accent stays the only hue in the hero.\n\t\t\tconst isEdge = index === 0 || index === rows.length - 1;\n\t\t\tconst isCore = index === Math.floor(rows.length / 2);\n\t\t\tconst painted = theme.fg(isEdge ? \"dim\" : \"accent\", line);\n\t\t\treturn boxCenteredLine(width, isCore ? theme.bold(painted) : painted);\n\t\t}),\n\t\tboxTextLine(width, sparkleRow(innerWidth, SPARKLE_ROW_BOTTOM, sparkleMs)),\n\t\tboxCenteredLine(\n\t\t\twidth,\n\t\t\t`${theme.fg(\"success\", \"●\")} ${theme.fg(\"muted\", \"MODEL\")} ${theme.fg(\"text\", heroModelLabel(snapshot))}`,\n\t\t),\n\t\tboxCenteredLine(\n\t\t\twidth,\n\t\t\t[\"route\", \"verify\", \"loop\", \"control\"]\n\t\t\t\t.map((stage) => theme.fg(\"dim\", stage))\n\t\t\t\t.join(theme.fg(\"borderMuted\", \" · \")),\n\t\t),\n\t\tboxTextLine(width, \"\"),\n\t\tboxRuleLine(width, Math.max(4, Math.floor(innerWidth * 0.18))),\n\t\tboxCenteredLine(width, heroMetaStrip(snapshot)),\n\t\tboxBottom(width),\n\t];\n}\n\n/**\n * Compact meta strip under the wordmark: the same signals the narrow layout\n * shows beside the banner, rendered as one centred row so the hero carries\n * real state instead of empty deck height.\n */\nfunction heroMetaStrip(snapshot: ControlPanelStatusSnapshot): string {\n\tconst rawThemeName = theme.name ?? \"live\";\n\tconst themeName = (rawThemeName.startsWith(\"omk-\") ? rawThemeName.slice(4) : rawThemeName).toUpperCase();\n\tconst cells: Array<[string, string]> = [\n\t\t[\"PANEL\", snapshot.runtimeState ?? \"unknown\"],\n\t\t[\"THEME\", themeName],\n\t\t[\"STARTUP\", snapshot.startupState ?? \"unknown\"],\n\t\t[\"LINK\", snapshot.linkState ?? \"unknown\"],\n\t];\n\treturn cells\n\t\t.map(([label, value]) => `${theme.fg(\"muted\", label)} ${coloredStatus(value)}`)\n\t\t.join(theme.fg(\"borderMuted\", \" · \"));\n}\n\nfunction heroModelLabel(snapshot: ControlPanelStatusSnapshot): string {\n\tif (!snapshot.modelId) return \"no-model\";\n\tconst think = snapshot.thinkingLevel;\n\treturn think && think !== \"off\" ? `${snapshot.modelId}:${think}` : snapshot.modelId;\n}\n\n/**\n * Label gutters are aligned per section rather than across the whole rail: a\n * global gutter would indent short labels so far that long values (todo text,\n * model ids) lose characters at rail widths of 34-38 columns.\n */\nconst RAIL_COLUMNS = {\n\tstatus: 8,\n\ttodo: 4,\n\tsession: 3,\n\tmodel: 5,\n\truntime: 8,\n\tcontrol: 7,\n} as const;\n\nfunction sidebarPanel(content: ControlPanelContent, width: number): string[] {\n\tconst snapshot = statusSnapshot(content);\n\tconst headroomLabel = snapshot.headroomStatus ?? snapshot.optimizerPolicy ?? \"unknown\";\n\tconst mcpCount = snapshot.mcpCount;\n\tconst skillCount = snapshot.skillCount;\n\tconst packageIntakeLabel = packageIntakeStatusLabel(snapshot.packageIntake);\n\tconst contextMeter = contextMeterLabel(snapshot);\n\tconst activitySparkline = activitySparklineLabel(snapshot);\n\treturn [\n\t\tsidebarTabs(width),\n\t\tboxCenteredLine(width, theme.bold(theme.fg(\"accent\", \"OMK://CONTROL\"))),\n\t\tboxCenteredLine(width, theme.fg(\"dim\", \"CYBERPUNK OPS CORE\")),\n\t\tboxCenteredLine(\n\t\t\twidth,\n\t\t\t`${theme.fg(\"muted\", \"MATRIX RAIN\")}${theme.fg(\"borderMuted\", \" // \")}${theme.fg(\"muted\", \"NEON GRID ONLINE\")}`,\n\t\t),\n\t\tboxCenteredLine(width, theme.fg(\"dim\", \"NIGHT-CITY-MATRIX-V3\")),\n\t\tsidebarRule(width, \"STATUS\"),\n\t\tboxTextLine(\n\t\t\twidth,\n\t\t\t`${labelCell(\"state\", RAIL_COLUMNS.status)} ${coloredStatus(snapshot.runtimeState ?? \"unknown\")}`,\n\t\t),\n\t\tboxTextLine(\n\t\t\twidth,\n\t\t\t`${labelCell(\"route\", RAIL_COLUMNS.status)} ${coloredStatus(snapshot.routeState ?? \"unknown\")}`,\n\t\t),\n\t\tboxTextLine(\n\t\t\twidth,\n\t\t\t`${labelCell(\"evidence\", RAIL_COLUMNS.status)} ${coloredStatus(snapshot.evidenceState ?? \"unknown\")}`,\n\t\t),\n\t\tsidebarRule(width, \"TODO\"),\n\t\t...todoSidebarLines(snapshot.todoState, width),\n\t\tsidebarRule(width, \"SESSION\"),\n\t\tsemanticBoxTextLine(width, \"cwd\", snapshot.cwdLabel ?? \"?\", \"end\", RAIL_COLUMNS.session),\n\t\tsemanticBoxTextLine(width, \"git\", snapshot.gitBranch ?? \"?\", \"start\", RAIL_COLUMNS.session),\n\t\tsidebarRule(width, \"MODEL / CTX\"),\n\t\tsemanticBoxTextLine(width, \"model\", modelStatusLabel(snapshot), \"end\", RAIL_COLUMNS.model),\n\t\tsemanticBoxTextLine(width, \"think\", snapshot.thinkingLevel ?? \"off\", \"start\", RAIL_COLUMNS.model),\n\t\tboxTextLine(\n\t\t\twidth,\n\t\t\t`${labelCell(\"ctx\", RAIL_COLUMNS.model)} ${theme.fg(statusColor(snapshot.contextPercent === undefined || snapshot.contextPercent === null ? \"unknown\" : \"ready\"), contextStatusLabel(snapshot))}`,\n\t\t),\n\t\tboxTextLine(width, `${labelCell(\"meter\", RAIL_COLUMNS.model)} ${contextMeter}`),\n\t\tboxTextLine(width, `${labelCell(\"pulse\", RAIL_COLUMNS.model)} ${activitySparkline}`),\n\t\tsidebarRule(width, \"RUNTIME / MCP / SKILLS\"),\n\t\tsemanticBoxTextLine(width, \"headroom\", headroomLabel, \"end\", RAIL_COLUMNS.runtime),\n\t\tsemanticBoxTextLine(width, \"omk\", snapshot.dagOrchestrationState ?? \"unknown\", \"end\", RAIL_COLUMNS.runtime),\n\t\tsemanticBoxTextLine(width, \"sidebar\", snapshot.sidebarState ?? \"unknown\", \"start\", RAIL_COLUMNS.runtime),\n\t\tboxTextLine(\n\t\t\twidth,\n\t\t\t`${labelCell(\"res\", RAIL_COLUMNS.runtime)} MCP:${mcpCount ?? \"?\"} skills:${skillCount ?? \"?\"}`,\n\t\t),\n\t\tsemanticBoxTextLine(width, \"pkg\", packageIntakeLabel, \"end\", RAIL_COLUMNS.runtime),\n\t\t// CONTROL previously repeated STATUS's route row verbatim; the rail now\n\t\t// carries each signal exactly once.\n\t\tsidebarRule(width, \"CONTROL\"),\n\t\tboxTextLine(\n\t\t\twidth,\n\t\t\t`${labelCell(\"verify\", RAIL_COLUMNS.control)} ${coloredStatus(snapshot.evidenceState ?? \"unknown\")}`,\n\t\t),\n\t\tboxTextLine(\n\t\t\twidth,\n\t\t\t`${labelCell(\"control\", RAIL_COLUMNS.control)} ${coloredStatus(snapshot.controlState ?? \"unknown\")}`,\n\t\t),\n\t\tboxBottom(width),\n\t];\n}\n\nfunction semanticBoxTextLine(\n\twidth: number,\n\tlabel: string,\n\tvalue: string,\n\tpreserve: \"start\" | \"middle\" | \"end\",\n\tcolumn?: number,\n): string {\n\t// Alignment is a courtesy, not a cost: if the gutter indent would truncate the\n\t// value, this row drops back to a flush label so the data survives intact.\n\tconst aligned = `${labelCell(label, column)} `;\n\tconst flush = `${labelCell(label, label.length)} `;\n\tconst alignedRoom = Math.max(0, width - 4 - visibleWidth(aligned));\n\tconst prefix = visibleWidth(value) <= alignedRoom ? aligned : flush;\n\tconst availableWidth = Math.max(0, width - 4 - visibleWidth(prefix));\n\treturn boxTextLine(width, `${prefix}${semanticTruncate(value, availableWidth, preserve)}`);\n}\n\nfunction semanticTruncate(value: string, maxWidth: number, preserve: \"start\" | \"middle\" | \"end\"): string {\n\tif (visibleWidth(value) <= maxWidth) return value;\n\tif (maxWidth <= 0) return \"\";\n\tif (preserve === \"start\") return truncateToWidth(value, maxWidth, \"…\");\n\tconst ellipsis = \"…\";\n\tconst targetWidth = maxWidth - visibleWidth(ellipsis);\n\tif (targetWidth <= 0) return truncateToWidth(ellipsis, maxWidth, \"\");\n\tif (preserve === \"middle\") {\n\t\tconst headWidth = Math.max(1, Math.floor(targetWidth / 2));\n\t\tconst tailWidth = Math.max(1, targetWidth - headWidth);\n\t\treturn `${takeStart(value, headWidth)}${ellipsis}${takeEnd(value, tailWidth)}`;\n\t}\n\treturn `${ellipsis}${takeEnd(value, targetWidth)}`;\n}\n\nfunction takeStart(value: string, maxWidth: number): string {\n\tlet prefix = \"\";\n\tfor (const char of Array.from(value)) {\n\t\tif (visibleWidth(prefix + char) > maxWidth) break;\n\t\tprefix += char;\n\t}\n\treturn prefix;\n}\n\nfunction takeEnd(value: string, maxWidth: number): string {\n\tlet suffix = \"\";\n\tfor (const char of Array.from(value).reverse()) {\n\t\tif (visibleWidth(char + suffix) > maxWidth) break;\n\t\tsuffix = char + suffix;\n\t}\n\treturn suffix;\n}\n\nfunction statusToken(label: string, value: string | undefined): string {\n\tconst state = value ?? \"unknown\";\n\treturn theme.fg(statusColor(state), `${label}:${state.toUpperCase()}`);\n}\n\nfunction coloredStatus(value: string): string {\n\treturn theme.fg(statusColor(value), value);\n}\n\nfunction statusColor(value: string): ThemeColor {\n\tconst normalized = value.toLowerCase();\n\tif ([\"ready\", \"on\", \"active\", \"available\", \"linked\", \"tracking\", \"pinned\"].includes(normalized)) return \"success\";\n\tif ([\"degraded\", \"limited\", \"blocked\", \"off\"].includes(normalized)) return \"warning\";\n\treturn \"muted\";\n}\n\nfunction todoSidebarLines(state: TodoState | undefined, width: number): string[] {\n\tif (!state || state.items.length === 0) {\n\t\treturn [\n\t\t\tboxTextLine(width, `${labelCell(\"todo\", RAIL_COLUMNS.todo)} ${theme.fg(\"dim\", \"empty\")}`),\n\t\t\tboxTextLine(width, `${labelCell(\"next\", RAIL_COLUMNS.todo)} ${theme.fg(\"dim\", \"no active todos\")}`),\n\t\t];\n\t}\n\tconst counts = todoSummary(state);\n\tconst next = nextActiveTodo(state);\n\treturn [\n\t\tboxTextLine(width, `${labelCell(\"todo\", RAIL_COLUMNS.todo)} ${counts.done}/${counts.total} done`),\n\t\tsemanticBoxTextLine(width, \"next\", next?.label ?? \"complete\", \"middle\", RAIL_COLUMNS.todo),\n\t];\n}\n\nfunction packageIntakeStatusLabel(summary: PiPackageIntakeSummary | undefined): string {\n\tif (!summary) return \"ports:pending\";\n\tconst ready =\n\t\tsummary.acceptedNative + summary.acceptedReference + summary.acceptedMeasurement + summary.acceptedAdvisory;\n\tconst review = summary.deferred + summary.reject;\n\treturn `ports:${ready}/${summary.total} review:${review} block:${summary.hardForkBlocked}`;\n}\n\nfunction renderExpanded(content: ControlPanelContent, width: number, bannerFrame?: string[], sparkleMs = 0): string[] {\n\tif (width >= CONTROL_PANEL_DECK_MIN_WIDTH) {\n\t\tconst { leftWidth, sidebarWidth } = deckWidths(width);\n\t\tconst resourceLines = [\"\", ...content.onboarding().split(\"\\n\")];\n\t\tconst rightRail = blankSidebarRail(sidebarWidth, resourceLines.length);\n\t\tconst lines = [...renderDeck(content, width, bannerFrame, sparkleMs)];\n\t\tlines.push(...composeColumns(resourceLines, leftWidth, rightRail, sidebarWidth, CONTROL_PANEL_GAP_WIDTH, width));\n\t\treturn lines;\n\t}\n\n\tconst lines = [divider(width, \"OMK//CONTROL PANEL\", \"accent\"), statusLine(content, width)];\n\tif (width >= 32) lines.push(...brandLines(content, width, bannerFrame));\n\tlines.push(divider(width, \"SYSTEM MAP\", \"mdHeading\"));\n\tfor (const instruction of content.expandedInstructions().split(\"\\n\")) lines.push(textLine(width, instruction));\n\tlines.push(divider(width, \"STARTUP LINK\", \"success\"));\n\tfor (const onboardingLine of content.onboarding().split(\"\\n\")) lines.push(textLine(width, onboardingLine, \"dim\"));\n\tlines.push(divider(width, \"END\", \"borderMuted\"));\n\treturn lines;\n}\n\nfunction blankSidebarRail(width: number, lineCount: number): string[] {\n\treturn Array.from({ length: lineCount }, () => boxTextLine(width, \"\"));\n}\n\nfunction statusSnapshot(content: ControlPanelContent): ControlPanelStatusSnapshot {\n\treturn content.statusSnapshot?.() ?? {};\n}\n\nfunction modelStatusLabel(snapshot: ControlPanelStatusSnapshot): string {\n\tif (!snapshot.modelId) return \"no-model\";\n\treturn snapshot.modelProvider ? `${snapshot.modelProvider}/${snapshot.modelId}` : snapshot.modelId;\n}\n\nfunction contextStatusLabel(snapshot: ControlPanelStatusSnapshot): string {\n\tconst windowTokens = snapshot.contextWindowTokens ?? 0;\n\tconst windowLabel = windowTokens > 0 ? formatTokens(windowTokens) : \"?\";\n\treturn snapshot.contextPercent === null || snapshot.contextPercent === undefined\n\t\t? `?/${windowLabel}`\n\t\t: `${snapshot.contextPercent.toFixed(1)}%/${windowLabel}`;\n}\n\nfunction contextMeterLabel(snapshot: ControlPanelStatusSnapshot): string {\n\tconst percent = normalizePercent(snapshot.contextPercent);\n\tif (percent === undefined) {\n\t\treturn `${theme.fg(\"borderMuted\", \"░\".repeat(CONTEXT_METER_CELLS))} ${theme.fg(\"muted\", \"??%\")}`;\n\t}\n\tconst filled = Math.max(0, Math.min(CONTEXT_METER_CELLS, Math.round((percent / 100) * CONTEXT_METER_CELLS)));\n\tconst color: ThemeColor = percent >= 85 ? \"warning\" : percent >= 65 ? \"mdCode\" : \"success\";\n\treturn `${theme.fg(color, \"█\".repeat(filled))}${theme.fg(\"borderMuted\", \"░\".repeat(CONTEXT_METER_CELLS - filled))} ${theme.fg(color, `${Math.round(percent)}%`)}`;\n}\n\nfunction activitySparklineLabel(snapshot: ControlPanelStatusSnapshot): string {\n\tconst seed = hashSnapshot(snapshot);\n\tconst glyphs = Array.from(SPARKLINE_GLYPHS);\n\tconst parts: string[] = [];\n\tfor (let index = 0; index < SPARKLINE_WIDTH; index++) {\n\t\tconst level = (seed + index * 5 + index * index) % glyphs.length;\n\t\tconst glyph = glyphs[level] ?? \"▁\";\n\t\t// Colour follows amplitude instead of column index, so the pulse reads as\n\t\t// one signal in the accent hue rather than a rotating three-colour pattern.\n\t\tconst color: ThemeColor = level >= glyphs.length - 2 ? \"accent\" : level >= 3 ? \"muted\" : \"dim\";\n\t\tparts.push(theme.fg(color, glyph));\n\t}\n\treturn parts.join(\"\");\n}\n\nfunction normalizePercent(value: number | null | undefined): number | undefined {\n\tif (value === null || value === undefined || !Number.isFinite(value)) return undefined;\n\tif (value < 0) return 0;\n\tif (value > 100) return 100;\n\treturn value;\n}\n\nfunction hashSnapshot(snapshot: ControlPanelStatusSnapshot): number {\n\tconst source = [\n\t\tsnapshot.modelProvider,\n\t\tsnapshot.modelId,\n\t\tsnapshot.contextPercent?.toFixed(1),\n\t\tsnapshot.contextTokens,\n\t\tsnapshot.contextWindowTokens,\n\t\tsnapshot.cwdLabel,\n\t\tsnapshot.gitBranch,\n\t].join(\"|\");\n\tlet hash = 2166136261;\n\tfor (let index = 0; index < source.length; index++) {\n\t\thash ^= source.charCodeAt(index);\n\t\thash = Math.imul(hash, 16777619);\n\t}\n\treturn hash >>> 0;\n}\n\nfunction formatTokens(count: number): string {\n\tif (count < 1000) return count.toString();\n\tif (count < 10000) return `${(count / 1000).toFixed(1)}k`;\n\tif (count < 1000000) return `${Math.round(count / 1000)}k`;\n\tif (count < 10000000) return `${(count / 1000000).toFixed(1)}M`;\n\treturn `${Math.round(count / 1000000)}M`;\n}\n\nfunction sidebarTabs(width: number): string {\n\treturn boxTextLine(\n\t\twidth,\n\t\tfitLine(\n\t\t\t`${theme.bold(theme.fg(\"accent\", \"1:CONTROL\"))} ${theme.fg(\"muted\", \"2:HISTORY\")}`,\n\t\t\tMath.max(0, width - 4),\n\t\t),\n\t);\n}\n\nfunction controlStripLine(content: ControlPanelContent, width: number): string {\n\treturn centerLine(\n\t\twidth,\n\t\t`${theme.bold(theme.fg(\"accent\", \"OMK://CONTROL READ\"))} ${theme.fg(\"accent\", \"route/verify/loop/control\")} · ${content.compactInstructions()}`,\n\t);\n}\n\nfunction brandLines(content: ControlPanelContent, width: number, bannerFrame?: string[]): string[] {\n\tconst art = bannerFrame ?? CONTROL_PANEL_ASCII_ART;\n\tif (bannerFrame) return art.map((line) => textLine(width, line));\n\tconst leftWidth = Math.max(...art.map((line) => visibleWidth(line)));\n\tconst minWideWidth = visibleWidth(\"| \") + leftWidth + visibleWidth(\" | \") + META_WIDTH;\n\tif (width < minWideWidth) return art.map((line) => textLine(width, theme.fg(\"accent\", line)));\n\tconst snapshot = statusSnapshot(content);\n\treturn art.map((line, index) =>\n\t\ttextLine(\n\t\t\twidth,\n\t\t\t`${fitLine(theme.fg(\"accent\", line), leftWidth)}${theme.fg(\"borderMuted\", \" | \")}${metadataLines(snapshot)[index] ?? \"\"}`,\n\t\t),\n\t);\n}\n\nfunction metadataLines(snapshot: ControlPanelStatusSnapshot): string[] {\n\tconst rawThemeName = theme.name ?? \"live\";\n\tconst themeName = (rawThemeName.startsWith(\"omk-\") ? rawThemeName.slice(4) : rawThemeName).toUpperCase();\n\treturn [\n\t\t`${theme.fg(\"mdCode\", \"PANEL\")} ${coloredStatus(snapshot.runtimeState ?? \"unknown\")}`,\n\t\t`${theme.fg(\"mdCode\", \"THEME\")} ${theme.fg(\"accent\", themeName)}`,\n\t\t`${theme.fg(\"mdCode\", \"STARTUP\")} ${coloredStatus(snapshot.startupState ?? \"unknown\")}`,\n\t\t`${theme.fg(\"mdCode\", \"LINK\")} ${coloredStatus(snapshot.linkState ?? \"unknown\")}`,\n\t];\n}\n\nfunction statusLine(content: ControlPanelContent, width: number): string {\n\tconst snapshot = statusSnapshot(content);\n\tconst segments = [\n\t\ttheme.bold(theme.fg(\"accent\", `${content.appName.toUpperCase()} v${content.version}`)),\n\t\tstatusToken(\"CORE\", snapshot.runtimeState),\n\t\tstatusToken(\"ANSI\", snapshot.ansiColorState),\n\t\tstatusToken(\"STARTUP\", snapshot.startupState),\n\t\tstatusToken(\"LINK\", snapshot.linkState),\n\t\ttheme.fg(\"muted\", \"THEME:LIVE\"),\n\t];\n\treturn textLine(width, segments.join(theme.fg(\"borderMuted\", \" | \")));\n}\n"]}
@@ -15,6 +15,15 @@ export declare function countRoutableNonHubSkills(skills: readonly {
15
15
  readonly name: string;
16
16
  }[]): number;
17
17
  export declare function countStableMcpServers(entries: readonly McpStabilityInput[]): number;
18
+ /**
19
+ * Classify a single MCP server entry for status display.
20
+ *
21
+ * - `stable`: configured, healthy, and safe to surface as an active server.
22
+ * - `overridden`: a higher-precedence source replaced this entry.
23
+ * - `unstable`: malformed, privileged, or blocked by an auth/network policy.
24
+ */
25
+ export type McpStability = "stable" | "overridden" | "unstable";
26
+ export declare function classifyMcpStability(entry: McpStabilityInput): McpStability;
18
27
  export declare function parseHeadroomVersionOutput(output: string): string | null;
19
28
  export declare function createControlPanelStatusSnapshot(session: AgentSession, sessionManager: SessionManager, footerData?: ReadonlyFooterDataProvider): ControlPanelStatusSnapshot;
20
29
  export {};
@@ -1 +1 @@
1
- {"version":3,"file":"control-panel-runtime-status.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/control-panel-runtime-status.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gCAAgC,CAAC;AAEnE,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,uCAAuC,CAAC;AACxF,OAAO,EAAoB,KAAK,cAAc,EAAE,MAAM,gCAAgC,CAAC;AAEvF,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kCAAkC,CAAC;AAEvE,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,2BAA2B,CAAC;AA0B5E,UAAU,iBAAiB;IAC1B,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,eAAe,EAAE,IAAI,CAAC,cAAc,CAAC,iBAAiB,CAAC,EAAE,MAAM,CAAC,CAAC;IAC1E,QAAQ,CAAC,kBAAkB,EAAE,IAAI,CAAC,cAAc,CAAC,oBAAoB,CAAC,EAAE,WAAW,GAAG,qBAAqB,CAAC,CAAC;IAC7G,QAAQ,CAAC,YAAY,EAAE,IAAI,CAAC,cAAc,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC,CAAC;CACpE;AAED,wBAAgB,yBAAyB,IAAI,MAAM,CAGlD;AAED,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,SAAS;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAAE,EAAE,GAAG,MAAM,CAE9F;AAED,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,SAAS,iBAAiB,EAAE,GAAG,MAAM,CAEnF;AAiDD,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAGxE;AAED,wBAAgB,gCAAgC,CAC/C,OAAO,EAAE,YAAY,EACrB,cAAc,EAAE,cAAc,EAC9B,UAAU,CAAC,EAAE,0BAA0B,GACrC,0BAA0B,CAiC5B","sourcesContent":["import { spawnSync } from \"node:child_process\";\nimport type { AgentSession } from \"../../../core/agent-session.ts\";\nimport { getHeadroomRuntimeStatus } from \"../../../core/context-budget-headroom.ts\";\nimport type { ReadonlyFooterDataProvider } from \"../../../core/footer-data-provider.ts\";\nimport { loadMcpInventory, type McpServerEntry } from \"../../../core/mcp-inventory.ts\";\nimport { evaluatePiPackageIntake } from \"../../../core/pi-package-intake.ts\";\nimport type { SessionManager } from \"../../../core/session-manager.ts\";\nimport { getCurrentTodoState } from \"../../../core/todo-runtime-state.ts\";\nimport type { ControlPanelStatusSnapshot } from \"./control-panel-layout.ts\";\nimport { formatCwdForFooter } from \"./footer.ts\";\n\nconst OMK_HUB_SKILL_NAMES = new Set([\n\t\"omk-skills\",\n\t\"omk-engineering\",\n\t\"omk-backend-data\",\n\t\"omk-security\",\n\t\"omk-devops-release\",\n\t\"omk-research-docs\",\n\t\"omk-design-media\",\n\t\"omk-agent-ops\",\n\t\"omk-product-ops\",\n\t\"omk-workspace-ops\",\n\t\"omk-frontend\",\n\t\"omk-loop\",\n\t\"omk-plan\",\n]);\n\nconst INVALID_MCP_NETWORK_RULES = new Set([\"mcp.network.invalid_mode\", \"mcp.network.empty_allowlist\"]);\nconst PRIVILEGED_MCP_COMMANDS = new Set([\"sudo\", \"su\"]);\nconst VERSION_COMMAND_TIMEOUT_MS = 750;\nconst HEADROOM_PYTHON_DISTRIBUTIONS = [\"headroom\", \"headroom-ai\"] as const;\n\nlet cachedHeadroomVersion: string | null | undefined;\n\ninterface McpStabilityInput {\n\treadonly commandSummary: string;\n\treadonly overriddenBy?: string;\n\treadonly networkDecision: Pick<McpServerEntry[\"networkDecision\"], \"rule\">;\n\treadonly capabilityDecision: Pick<McpServerEntry[\"capabilityDecision\"], \"malformed\" | \"unknownCapabilities\">;\n\treadonly authDecision: Pick<McpServerEntry[\"authDecision\"], \"rule\">;\n}\n\nexport function formatHeadroomStatusLabel(): string {\n\tconst version = getInstalledHeadroomVersion();\n\treturn version ? `headroom:${version}` : getHeadroomRuntimeStatus().policyId;\n}\n\nexport function countRoutableNonHubSkills(skills: readonly { readonly name: string }[]): number {\n\treturn skills.filter((skill) => !OMK_HUB_SKILL_NAMES.has(skill.name)).length;\n}\n\nexport function countStableMcpServers(entries: readonly McpStabilityInput[]): number {\n\treturn entries.filter(isStableMcpEntry).length;\n}\n\nfunction isStableMcpEntry(entry: McpStabilityInput): boolean {\n\tif (entry.overriddenBy) return false;\n\tif (entry.commandSummary === \"<unknown>\") return false;\n\tif (entry.authDecision.rule === \"mcp.auth.invalid\") return false;\n\tif (INVALID_MCP_NETWORK_RULES.has(entry.networkDecision.rule)) return false;\n\tif (entry.capabilityDecision.malformed || entry.capabilityDecision.unknownCapabilities.length > 0) return false;\n\tconst command = entry.commandSummary.split(/\\s+/, 1)[0] ?? \"\";\n\treturn !PRIVILEGED_MCP_COMMANDS.has(command);\n}\n\nfunction getInstalledHeadroomVersion(): string | null {\n\tif (cachedHeadroomVersion !== undefined) return cachedHeadroomVersion;\n\tcachedHeadroomVersion = readVersionFromCommand(\"headroom\", [\"--version\"]);\n\tif (cachedHeadroomVersion) return cachedHeadroomVersion;\n\tcachedHeadroomVersion = readVersionFromCommand(\"headroom\", [\"version\"]);\n\tif (cachedHeadroomVersion) return cachedHeadroomVersion;\n\tfor (const distribution of HEADROOM_PYTHON_DISTRIBUTIONS) {\n\t\tcachedHeadroomVersion = readPythonDistributionVersion(distribution);\n\t\tif (cachedHeadroomVersion) return cachedHeadroomVersion;\n\t}\n\tcachedHeadroomVersion = null;\n\treturn cachedHeadroomVersion;\n}\n\nfunction readPythonDistributionVersion(distribution: (typeof HEADROOM_PYTHON_DISTRIBUTIONS)[number]): string | null {\n\treturn readVersionFromCommand(\"python3\", [\n\t\t\"-c\",\n\t\t`import importlib.metadata as m; print(m.version('${distribution}'))`,\n\t]);\n}\n\nfunction readVersionFromCommand(command: string, args: readonly string[]): string | null {\n\ttry {\n\t\tconst result = spawnSync(command, [...args], {\n\t\t\tencoding: \"utf8\",\n\t\t\ttimeout: VERSION_COMMAND_TIMEOUT_MS,\n\t\t\tshell: false,\n\t\t\twindowsHide: true,\n\t\t\tenv: { PATH: process.env.PATH ?? \"\" },\n\t\t});\n\t\tif (result.error || result.status !== 0) return null;\n\t\treturn parseHeadroomVersionOutput(`${result.stdout}\\n${result.stderr}`);\n\t} catch {\n\t\treturn null;\n\t}\n}\n\nexport function parseHeadroomVersionOutput(output: string): string | null {\n\tconst match = /\\bv?(\\d+\\.\\d+(?:\\.\\d+)?(?:[-+][0-9A-Za-z.-]+)?)\\b/.exec(output);\n\treturn match?.[1] ?? null;\n}\n\nexport function createControlPanelStatusSnapshot(\n\tsession: AgentSession,\n\tsessionManager: SessionManager,\n\tfooterData?: ReadonlyFooterDataProvider,\n): ControlPanelStatusSnapshot {\n\tconst contextUsage = session.getContextUsage();\n\tconst contextWindow = contextUsage?.contextWindow ?? session.state.model?.contextWindow ?? 0;\n\tconst mcpInventory = loadMcpInventory(sessionManager.getCwd());\n\tconst loadedSkills = session.resourceLoader.getSkills().skills;\n\tconst packageIntake = evaluatePiPackageIntake().summary;\n\tconst ansiColorState = process.env.NO_COLOR ? \"off\" : \"on\";\n\tconst cwdLabel = formatCwdForFooter(sessionManager.getCwd(), process.env.HOME || process.env.USERPROFILE);\n\treturn {\n\t\tmodelId: session.state.model?.id,\n\t\tmodelProvider: session.state.model?.provider,\n\t\tthinkingLevel: session.state.thinkingLevel ?? \"off\",\n\t\tcontextPercent: contextUsage?.percent ?? null,\n\t\tcontextWindowTokens: contextWindow,\n\t\tcontextTokens: contextUsage?.tokens ?? null,\n\t\theadroomStatus: formatHeadroomStatusLabel(),\n\t\toptimizerPolicy: getHeadroomRuntimeStatus().selector,\n\t\tmcpCount: countStableMcpServers(mcpInventory.entries),\n\t\tskillCount: countRoutableNonHubSkills(loadedSkills),\n\t\tpackageIntake,\n\t\tcwdLabel,\n\t\tgitBranch: footerData?.getGitBranch(),\n\t\ttodoState: getCurrentTodoState(),\n\t\truntimeState: \"ready\",\n\t\trouteState: \"active\",\n\t\tevidenceState: \"tracking\",\n\t\tcontrolState: \"ready\",\n\t\tdagOrchestrationState: \"DAG:omk-parallel-orchestrator\",\n\t\tansiColorState,\n\t\tstartupState: \"linked\",\n\t\tlinkState: \"ready\",\n\t\tsidebarState: \"pinned\",\n\t};\n}\n"]}
1
+ {"version":3,"file":"control-panel-runtime-status.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/control-panel-runtime-status.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gCAAgC,CAAC;AAEnE,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,uCAAuC,CAAC;AACxF,OAAO,EAAoB,KAAK,cAAc,EAAE,MAAM,gCAAgC,CAAC;AAEvF,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kCAAkC,CAAC;AAEvE,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,2BAA2B,CAAC;AA0B5E,UAAU,iBAAiB;IAC1B,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,eAAe,EAAE,IAAI,CAAC,cAAc,CAAC,iBAAiB,CAAC,EAAE,MAAM,CAAC,CAAC;IAC1E,QAAQ,CAAC,kBAAkB,EAAE,IAAI,CAAC,cAAc,CAAC,oBAAoB,CAAC,EAAE,WAAW,GAAG,qBAAqB,CAAC,CAAC;IAC7G,QAAQ,CAAC,YAAY,EAAE,IAAI,CAAC,cAAc,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC,CAAC;CACpE;AAED,wBAAgB,yBAAyB,IAAI,MAAM,CAGlD;AAED,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,SAAS;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAAE,EAAE,GAAG,MAAM,CAE9F;AAED,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,SAAS,iBAAiB,EAAE,GAAG,MAAM,CAEnF;AAED;;;;;;GAMG;AACH,MAAM,MAAM,YAAY,GAAG,QAAQ,GAAG,YAAY,GAAG,UAAU,CAAC;AAEhE,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,iBAAiB,GAAG,YAAY,CAS3E;AAuCD,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAGxE;AAED,wBAAgB,gCAAgC,CAC/C,OAAO,EAAE,YAAY,EACrB,cAAc,EAAE,cAAc,EAC9B,UAAU,CAAC,EAAE,0BAA0B,GACrC,0BAA0B,CAiC5B","sourcesContent":["import { spawnSync } from \"node:child_process\";\nimport type { AgentSession } from \"../../../core/agent-session.ts\";\nimport { getHeadroomRuntimeStatus } from \"../../../core/context-budget-headroom.ts\";\nimport type { ReadonlyFooterDataProvider } from \"../../../core/footer-data-provider.ts\";\nimport { loadMcpInventory, type McpServerEntry } from \"../../../core/mcp-inventory.ts\";\nimport { evaluatePiPackageIntake } from \"../../../core/pi-package-intake.ts\";\nimport type { SessionManager } from \"../../../core/session-manager.ts\";\nimport { getCurrentTodoState } from \"../../../core/todo-runtime-state.ts\";\nimport type { ControlPanelStatusSnapshot } from \"./control-panel-layout.ts\";\nimport { formatCwdForFooter } from \"./footer.ts\";\n\nconst OMK_HUB_SKILL_NAMES = new Set([\n\t\"omk-skills\",\n\t\"omk-engineering\",\n\t\"omk-backend-data\",\n\t\"omk-security\",\n\t\"omk-devops-release\",\n\t\"omk-research-docs\",\n\t\"omk-design-media\",\n\t\"omk-agent-ops\",\n\t\"omk-product-ops\",\n\t\"omk-workspace-ops\",\n\t\"omk-frontend\",\n\t\"omk-loop\",\n\t\"omk-plan\",\n]);\n\nconst INVALID_MCP_NETWORK_RULES = new Set([\"mcp.network.invalid_mode\", \"mcp.network.empty_allowlist\"]);\nconst PRIVILEGED_MCP_COMMANDS = new Set([\"sudo\", \"su\"]);\nconst VERSION_COMMAND_TIMEOUT_MS = 750;\nconst HEADROOM_PYTHON_DISTRIBUTIONS = [\"headroom\", \"headroom-ai\"] as const;\n\nlet cachedHeadroomVersion: string | null | undefined;\n\ninterface McpStabilityInput {\n\treadonly commandSummary: string;\n\treadonly overriddenBy?: string;\n\treadonly networkDecision: Pick<McpServerEntry[\"networkDecision\"], \"rule\">;\n\treadonly capabilityDecision: Pick<McpServerEntry[\"capabilityDecision\"], \"malformed\" | \"unknownCapabilities\">;\n\treadonly authDecision: Pick<McpServerEntry[\"authDecision\"], \"rule\">;\n}\n\nexport function formatHeadroomStatusLabel(): string {\n\tconst version = getInstalledHeadroomVersion();\n\treturn version ? `headroom:${version}` : getHeadroomRuntimeStatus().policyId;\n}\n\nexport function countRoutableNonHubSkills(skills: readonly { readonly name: string }[]): number {\n\treturn skills.filter((skill) => !OMK_HUB_SKILL_NAMES.has(skill.name)).length;\n}\n\nexport function countStableMcpServers(entries: readonly McpStabilityInput[]): number {\n\treturn entries.filter((entry) => classifyMcpStability(entry) === \"stable\").length;\n}\n\n/**\n * Classify a single MCP server entry for status display.\n *\n * - `stable`: configured, healthy, and safe to surface as an active server.\n * - `overridden`: a higher-precedence source replaced this entry.\n * - `unstable`: malformed, privileged, or blocked by an auth/network policy.\n */\nexport type McpStability = \"stable\" | \"overridden\" | \"unstable\";\n\nexport function classifyMcpStability(entry: McpStabilityInput): McpStability {\n\tif (entry.overriddenBy) return \"overridden\";\n\tif (entry.commandSummary === \"<unknown>\") return \"unstable\";\n\tif (entry.authDecision.rule === \"mcp.auth.invalid\") return \"unstable\";\n\tif (INVALID_MCP_NETWORK_RULES.has(entry.networkDecision.rule)) return \"unstable\";\n\tif (entry.capabilityDecision.malformed || entry.capabilityDecision.unknownCapabilities.length > 0) return \"unstable\";\n\tconst command = entry.commandSummary.split(/\\s+/, 1)[0] ?? \"\";\n\tif (PRIVILEGED_MCP_COMMANDS.has(command)) return \"unstable\";\n\treturn \"stable\";\n}\n\nfunction getInstalledHeadroomVersion(): string | null {\n\tif (cachedHeadroomVersion !== undefined) return cachedHeadroomVersion;\n\tcachedHeadroomVersion = readVersionFromCommand(\"headroom\", [\"--version\"]);\n\tif (cachedHeadroomVersion) return cachedHeadroomVersion;\n\tcachedHeadroomVersion = readVersionFromCommand(\"headroom\", [\"version\"]);\n\tif (cachedHeadroomVersion) return cachedHeadroomVersion;\n\tfor (const distribution of HEADROOM_PYTHON_DISTRIBUTIONS) {\n\t\tcachedHeadroomVersion = readPythonDistributionVersion(distribution);\n\t\tif (cachedHeadroomVersion) return cachedHeadroomVersion;\n\t}\n\tcachedHeadroomVersion = null;\n\treturn cachedHeadroomVersion;\n}\n\nfunction readPythonDistributionVersion(distribution: (typeof HEADROOM_PYTHON_DISTRIBUTIONS)[number]): string | null {\n\treturn readVersionFromCommand(\"python3\", [\n\t\t\"-c\",\n\t\t`import importlib.metadata as m; print(m.version('${distribution}'))`,\n\t]);\n}\n\nfunction readVersionFromCommand(command: string, args: readonly string[]): string | null {\n\ttry {\n\t\tconst result = spawnSync(command, [...args], {\n\t\t\tencoding: \"utf8\",\n\t\t\ttimeout: VERSION_COMMAND_TIMEOUT_MS,\n\t\t\tshell: false,\n\t\t\twindowsHide: true,\n\t\t\tenv: { PATH: process.env.PATH ?? \"\" },\n\t\t});\n\t\tif (result.error || result.status !== 0) return null;\n\t\treturn parseHeadroomVersionOutput(`${result.stdout}\\n${result.stderr}`);\n\t} catch {\n\t\treturn null;\n\t}\n}\n\nexport function parseHeadroomVersionOutput(output: string): string | null {\n\tconst match = /\\bv?(\\d+\\.\\d+(?:\\.\\d+)?(?:[-+][0-9A-Za-z.-]+)?)\\b/.exec(output);\n\treturn match?.[1] ?? null;\n}\n\nexport function createControlPanelStatusSnapshot(\n\tsession: AgentSession,\n\tsessionManager: SessionManager,\n\tfooterData?: ReadonlyFooterDataProvider,\n): ControlPanelStatusSnapshot {\n\tconst contextUsage = session.getContextUsage();\n\tconst contextWindow = contextUsage?.contextWindow ?? session.state.model?.contextWindow ?? 0;\n\tconst mcpInventory = loadMcpInventory(sessionManager.getCwd());\n\tconst loadedSkills = session.resourceLoader.getSkills().skills;\n\tconst packageIntake = evaluatePiPackageIntake().summary;\n\tconst ansiColorState = process.env.NO_COLOR ? \"off\" : \"on\";\n\tconst cwdLabel = formatCwdForFooter(sessionManager.getCwd(), process.env.HOME || process.env.USERPROFILE);\n\treturn {\n\t\tmodelId: session.state.model?.id,\n\t\tmodelProvider: session.state.model?.provider,\n\t\tthinkingLevel: session.state.thinkingLevel ?? \"off\",\n\t\tcontextPercent: contextUsage?.percent ?? null,\n\t\tcontextWindowTokens: contextWindow,\n\t\tcontextTokens: contextUsage?.tokens ?? null,\n\t\theadroomStatus: formatHeadroomStatusLabel(),\n\t\toptimizerPolicy: getHeadroomRuntimeStatus().selector,\n\t\tmcpCount: countStableMcpServers(mcpInventory.entries),\n\t\tskillCount: countRoutableNonHubSkills(loadedSkills),\n\t\tpackageIntake,\n\t\tcwdLabel,\n\t\tgitBranch: footerData?.getGitBranch(),\n\t\ttodoState: getCurrentTodoState(),\n\t\truntimeState: \"ready\",\n\t\trouteState: \"active\",\n\t\tevidenceState: \"tracking\",\n\t\tcontrolState: \"ready\",\n\t\tdagOrchestrationState: \"DAG:omk-parallel-orchestrator\",\n\t\tansiColorState,\n\t\tstartupState: \"linked\",\n\t\tlinkState: \"ready\",\n\t\tsidebarState: \"pinned\",\n\t};\n}\n"]}
@@ -32,21 +32,23 @@ export function countRoutableNonHubSkills(skills) {
32
32
  return skills.filter((skill) => !OMK_HUB_SKILL_NAMES.has(skill.name)).length;
33
33
  }
34
34
  export function countStableMcpServers(entries) {
35
- return entries.filter(isStableMcpEntry).length;
35
+ return entries.filter((entry) => classifyMcpStability(entry) === "stable").length;
36
36
  }
37
- function isStableMcpEntry(entry) {
37
+ export function classifyMcpStability(entry) {
38
38
  if (entry.overriddenBy)
39
- return false;
39
+ return "overridden";
40
40
  if (entry.commandSummary === "<unknown>")
41
- return false;
41
+ return "unstable";
42
42
  if (entry.authDecision.rule === "mcp.auth.invalid")
43
- return false;
43
+ return "unstable";
44
44
  if (INVALID_MCP_NETWORK_RULES.has(entry.networkDecision.rule))
45
- return false;
45
+ return "unstable";
46
46
  if (entry.capabilityDecision.malformed || entry.capabilityDecision.unknownCapabilities.length > 0)
47
- return false;
47
+ return "unstable";
48
48
  const command = entry.commandSummary.split(/\s+/, 1)[0] ?? "";
49
- return !PRIVILEGED_MCP_COMMANDS.has(command);
49
+ if (PRIVILEGED_MCP_COMMANDS.has(command))
50
+ return "unstable";
51
+ return "stable";
50
52
  }
51
53
  function getInstalledHeadroomVersion() {
52
54
  if (cachedHeadroomVersion !== undefined)
@@ -1 +1 @@
1
- {"version":3,"file":"control-panel-runtime-status.js","sourceRoot":"","sources":["../../../../src/modes/interactive/components/control-panel-runtime-status.ts"],"names":[],"mappings":"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","sourcesContent":["import { spawnSync } from \"node:child_process\";\nimport type { AgentSession } from \"../../../core/agent-session.ts\";\nimport { getHeadroomRuntimeStatus } from \"../../../core/context-budget-headroom.ts\";\nimport type { ReadonlyFooterDataProvider } from \"../../../core/footer-data-provider.ts\";\nimport { loadMcpInventory, type McpServerEntry } from \"../../../core/mcp-inventory.ts\";\nimport { evaluatePiPackageIntake } from \"../../../core/pi-package-intake.ts\";\nimport type { SessionManager } from \"../../../core/session-manager.ts\";\nimport { getCurrentTodoState } from \"../../../core/todo-runtime-state.ts\";\nimport type { ControlPanelStatusSnapshot } from \"./control-panel-layout.ts\";\nimport { formatCwdForFooter } from \"./footer.ts\";\n\nconst OMK_HUB_SKILL_NAMES = new Set([\n\t\"omk-skills\",\n\t\"omk-engineering\",\n\t\"omk-backend-data\",\n\t\"omk-security\",\n\t\"omk-devops-release\",\n\t\"omk-research-docs\",\n\t\"omk-design-media\",\n\t\"omk-agent-ops\",\n\t\"omk-product-ops\",\n\t\"omk-workspace-ops\",\n\t\"omk-frontend\",\n\t\"omk-loop\",\n\t\"omk-plan\",\n]);\n\nconst INVALID_MCP_NETWORK_RULES = new Set([\"mcp.network.invalid_mode\", \"mcp.network.empty_allowlist\"]);\nconst PRIVILEGED_MCP_COMMANDS = new Set([\"sudo\", \"su\"]);\nconst VERSION_COMMAND_TIMEOUT_MS = 750;\nconst HEADROOM_PYTHON_DISTRIBUTIONS = [\"headroom\", \"headroom-ai\"] as const;\n\nlet cachedHeadroomVersion: string | null | undefined;\n\ninterface McpStabilityInput {\n\treadonly commandSummary: string;\n\treadonly overriddenBy?: string;\n\treadonly networkDecision: Pick<McpServerEntry[\"networkDecision\"], \"rule\">;\n\treadonly capabilityDecision: Pick<McpServerEntry[\"capabilityDecision\"], \"malformed\" | \"unknownCapabilities\">;\n\treadonly authDecision: Pick<McpServerEntry[\"authDecision\"], \"rule\">;\n}\n\nexport function formatHeadroomStatusLabel(): string {\n\tconst version = getInstalledHeadroomVersion();\n\treturn version ? `headroom:${version}` : getHeadroomRuntimeStatus().policyId;\n}\n\nexport function countRoutableNonHubSkills(skills: readonly { readonly name: string }[]): number {\n\treturn skills.filter((skill) => !OMK_HUB_SKILL_NAMES.has(skill.name)).length;\n}\n\nexport function countStableMcpServers(entries: readonly McpStabilityInput[]): number {\n\treturn entries.filter(isStableMcpEntry).length;\n}\n\nfunction isStableMcpEntry(entry: McpStabilityInput): boolean {\n\tif (entry.overriddenBy) return false;\n\tif (entry.commandSummary === \"<unknown>\") return false;\n\tif (entry.authDecision.rule === \"mcp.auth.invalid\") return false;\n\tif (INVALID_MCP_NETWORK_RULES.has(entry.networkDecision.rule)) return false;\n\tif (entry.capabilityDecision.malformed || entry.capabilityDecision.unknownCapabilities.length > 0) return false;\n\tconst command = entry.commandSummary.split(/\\s+/, 1)[0] ?? \"\";\n\treturn !PRIVILEGED_MCP_COMMANDS.has(command);\n}\n\nfunction getInstalledHeadroomVersion(): string | null {\n\tif (cachedHeadroomVersion !== undefined) return cachedHeadroomVersion;\n\tcachedHeadroomVersion = readVersionFromCommand(\"headroom\", [\"--version\"]);\n\tif (cachedHeadroomVersion) return cachedHeadroomVersion;\n\tcachedHeadroomVersion = readVersionFromCommand(\"headroom\", [\"version\"]);\n\tif (cachedHeadroomVersion) return cachedHeadroomVersion;\n\tfor (const distribution of HEADROOM_PYTHON_DISTRIBUTIONS) {\n\t\tcachedHeadroomVersion = readPythonDistributionVersion(distribution);\n\t\tif (cachedHeadroomVersion) return cachedHeadroomVersion;\n\t}\n\tcachedHeadroomVersion = null;\n\treturn cachedHeadroomVersion;\n}\n\nfunction readPythonDistributionVersion(distribution: (typeof HEADROOM_PYTHON_DISTRIBUTIONS)[number]): string | null {\n\treturn readVersionFromCommand(\"python3\", [\n\t\t\"-c\",\n\t\t`import importlib.metadata as m; print(m.version('${distribution}'))`,\n\t]);\n}\n\nfunction readVersionFromCommand(command: string, args: readonly string[]): string | null {\n\ttry {\n\t\tconst result = spawnSync(command, [...args], {\n\t\t\tencoding: \"utf8\",\n\t\t\ttimeout: VERSION_COMMAND_TIMEOUT_MS,\n\t\t\tshell: false,\n\t\t\twindowsHide: true,\n\t\t\tenv: { PATH: process.env.PATH ?? \"\" },\n\t\t});\n\t\tif (result.error || result.status !== 0) return null;\n\t\treturn parseHeadroomVersionOutput(`${result.stdout}\\n${result.stderr}`);\n\t} catch {\n\t\treturn null;\n\t}\n}\n\nexport function parseHeadroomVersionOutput(output: string): string | null {\n\tconst match = /\\bv?(\\d+\\.\\d+(?:\\.\\d+)?(?:[-+][0-9A-Za-z.-]+)?)\\b/.exec(output);\n\treturn match?.[1] ?? null;\n}\n\nexport function createControlPanelStatusSnapshot(\n\tsession: AgentSession,\n\tsessionManager: SessionManager,\n\tfooterData?: ReadonlyFooterDataProvider,\n): ControlPanelStatusSnapshot {\n\tconst contextUsage = session.getContextUsage();\n\tconst contextWindow = contextUsage?.contextWindow ?? session.state.model?.contextWindow ?? 0;\n\tconst mcpInventory = loadMcpInventory(sessionManager.getCwd());\n\tconst loadedSkills = session.resourceLoader.getSkills().skills;\n\tconst packageIntake = evaluatePiPackageIntake().summary;\n\tconst ansiColorState = process.env.NO_COLOR ? \"off\" : \"on\";\n\tconst cwdLabel = formatCwdForFooter(sessionManager.getCwd(), process.env.HOME || process.env.USERPROFILE);\n\treturn {\n\t\tmodelId: session.state.model?.id,\n\t\tmodelProvider: session.state.model?.provider,\n\t\tthinkingLevel: session.state.thinkingLevel ?? \"off\",\n\t\tcontextPercent: contextUsage?.percent ?? null,\n\t\tcontextWindowTokens: contextWindow,\n\t\tcontextTokens: contextUsage?.tokens ?? null,\n\t\theadroomStatus: formatHeadroomStatusLabel(),\n\t\toptimizerPolicy: getHeadroomRuntimeStatus().selector,\n\t\tmcpCount: countStableMcpServers(mcpInventory.entries),\n\t\tskillCount: countRoutableNonHubSkills(loadedSkills),\n\t\tpackageIntake,\n\t\tcwdLabel,\n\t\tgitBranch: footerData?.getGitBranch(),\n\t\ttodoState: getCurrentTodoState(),\n\t\truntimeState: \"ready\",\n\t\trouteState: \"active\",\n\t\tevidenceState: \"tracking\",\n\t\tcontrolState: \"ready\",\n\t\tdagOrchestrationState: \"DAG:omk-parallel-orchestrator\",\n\t\tansiColorState,\n\t\tstartupState: \"linked\",\n\t\tlinkState: \"ready\",\n\t\tsidebarState: \"pinned\",\n\t};\n}\n"]}
1
+ {"version":3,"file":"control-panel-runtime-status.js","sourceRoot":"","sources":["../../../../src/modes/interactive/components/control-panel-runtime-status.ts"],"names":[],"mappings":"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","sourcesContent":["import { spawnSync } from \"node:child_process\";\nimport type { AgentSession } from \"../../../core/agent-session.ts\";\nimport { getHeadroomRuntimeStatus } from \"../../../core/context-budget-headroom.ts\";\nimport type { ReadonlyFooterDataProvider } from \"../../../core/footer-data-provider.ts\";\nimport { loadMcpInventory, type McpServerEntry } from \"../../../core/mcp-inventory.ts\";\nimport { evaluatePiPackageIntake } from \"../../../core/pi-package-intake.ts\";\nimport type { SessionManager } from \"../../../core/session-manager.ts\";\nimport { getCurrentTodoState } from \"../../../core/todo-runtime-state.ts\";\nimport type { ControlPanelStatusSnapshot } from \"./control-panel-layout.ts\";\nimport { formatCwdForFooter } from \"./footer.ts\";\n\nconst OMK_HUB_SKILL_NAMES = new Set([\n\t\"omk-skills\",\n\t\"omk-engineering\",\n\t\"omk-backend-data\",\n\t\"omk-security\",\n\t\"omk-devops-release\",\n\t\"omk-research-docs\",\n\t\"omk-design-media\",\n\t\"omk-agent-ops\",\n\t\"omk-product-ops\",\n\t\"omk-workspace-ops\",\n\t\"omk-frontend\",\n\t\"omk-loop\",\n\t\"omk-plan\",\n]);\n\nconst INVALID_MCP_NETWORK_RULES = new Set([\"mcp.network.invalid_mode\", \"mcp.network.empty_allowlist\"]);\nconst PRIVILEGED_MCP_COMMANDS = new Set([\"sudo\", \"su\"]);\nconst VERSION_COMMAND_TIMEOUT_MS = 750;\nconst HEADROOM_PYTHON_DISTRIBUTIONS = [\"headroom\", \"headroom-ai\"] as const;\n\nlet cachedHeadroomVersion: string | null | undefined;\n\ninterface McpStabilityInput {\n\treadonly commandSummary: string;\n\treadonly overriddenBy?: string;\n\treadonly networkDecision: Pick<McpServerEntry[\"networkDecision\"], \"rule\">;\n\treadonly capabilityDecision: Pick<McpServerEntry[\"capabilityDecision\"], \"malformed\" | \"unknownCapabilities\">;\n\treadonly authDecision: Pick<McpServerEntry[\"authDecision\"], \"rule\">;\n}\n\nexport function formatHeadroomStatusLabel(): string {\n\tconst version = getInstalledHeadroomVersion();\n\treturn version ? `headroom:${version}` : getHeadroomRuntimeStatus().policyId;\n}\n\nexport function countRoutableNonHubSkills(skills: readonly { readonly name: string }[]): number {\n\treturn skills.filter((skill) => !OMK_HUB_SKILL_NAMES.has(skill.name)).length;\n}\n\nexport function countStableMcpServers(entries: readonly McpStabilityInput[]): number {\n\treturn entries.filter((entry) => classifyMcpStability(entry) === \"stable\").length;\n}\n\n/**\n * Classify a single MCP server entry for status display.\n *\n * - `stable`: configured, healthy, and safe to surface as an active server.\n * - `overridden`: a higher-precedence source replaced this entry.\n * - `unstable`: malformed, privileged, or blocked by an auth/network policy.\n */\nexport type McpStability = \"stable\" | \"overridden\" | \"unstable\";\n\nexport function classifyMcpStability(entry: McpStabilityInput): McpStability {\n\tif (entry.overriddenBy) return \"overridden\";\n\tif (entry.commandSummary === \"<unknown>\") return \"unstable\";\n\tif (entry.authDecision.rule === \"mcp.auth.invalid\") return \"unstable\";\n\tif (INVALID_MCP_NETWORK_RULES.has(entry.networkDecision.rule)) return \"unstable\";\n\tif (entry.capabilityDecision.malformed || entry.capabilityDecision.unknownCapabilities.length > 0) return \"unstable\";\n\tconst command = entry.commandSummary.split(/\\s+/, 1)[0] ?? \"\";\n\tif (PRIVILEGED_MCP_COMMANDS.has(command)) return \"unstable\";\n\treturn \"stable\";\n}\n\nfunction getInstalledHeadroomVersion(): string | null {\n\tif (cachedHeadroomVersion !== undefined) return cachedHeadroomVersion;\n\tcachedHeadroomVersion = readVersionFromCommand(\"headroom\", [\"--version\"]);\n\tif (cachedHeadroomVersion) return cachedHeadroomVersion;\n\tcachedHeadroomVersion = readVersionFromCommand(\"headroom\", [\"version\"]);\n\tif (cachedHeadroomVersion) return cachedHeadroomVersion;\n\tfor (const distribution of HEADROOM_PYTHON_DISTRIBUTIONS) {\n\t\tcachedHeadroomVersion = readPythonDistributionVersion(distribution);\n\t\tif (cachedHeadroomVersion) return cachedHeadroomVersion;\n\t}\n\tcachedHeadroomVersion = null;\n\treturn cachedHeadroomVersion;\n}\n\nfunction readPythonDistributionVersion(distribution: (typeof HEADROOM_PYTHON_DISTRIBUTIONS)[number]): string | null {\n\treturn readVersionFromCommand(\"python3\", [\n\t\t\"-c\",\n\t\t`import importlib.metadata as m; print(m.version('${distribution}'))`,\n\t]);\n}\n\nfunction readVersionFromCommand(command: string, args: readonly string[]): string | null {\n\ttry {\n\t\tconst result = spawnSync(command, [...args], {\n\t\t\tencoding: \"utf8\",\n\t\t\ttimeout: VERSION_COMMAND_TIMEOUT_MS,\n\t\t\tshell: false,\n\t\t\twindowsHide: true,\n\t\t\tenv: { PATH: process.env.PATH ?? \"\" },\n\t\t});\n\t\tif (result.error || result.status !== 0) return null;\n\t\treturn parseHeadroomVersionOutput(`${result.stdout}\\n${result.stderr}`);\n\t} catch {\n\t\treturn null;\n\t}\n}\n\nexport function parseHeadroomVersionOutput(output: string): string | null {\n\tconst match = /\\bv?(\\d+\\.\\d+(?:\\.\\d+)?(?:[-+][0-9A-Za-z.-]+)?)\\b/.exec(output);\n\treturn match?.[1] ?? null;\n}\n\nexport function createControlPanelStatusSnapshot(\n\tsession: AgentSession,\n\tsessionManager: SessionManager,\n\tfooterData?: ReadonlyFooterDataProvider,\n): ControlPanelStatusSnapshot {\n\tconst contextUsage = session.getContextUsage();\n\tconst contextWindow = contextUsage?.contextWindow ?? session.state.model?.contextWindow ?? 0;\n\tconst mcpInventory = loadMcpInventory(sessionManager.getCwd());\n\tconst loadedSkills = session.resourceLoader.getSkills().skills;\n\tconst packageIntake = evaluatePiPackageIntake().summary;\n\tconst ansiColorState = process.env.NO_COLOR ? \"off\" : \"on\";\n\tconst cwdLabel = formatCwdForFooter(sessionManager.getCwd(), process.env.HOME || process.env.USERPROFILE);\n\treturn {\n\t\tmodelId: session.state.model?.id,\n\t\tmodelProvider: session.state.model?.provider,\n\t\tthinkingLevel: session.state.thinkingLevel ?? \"off\",\n\t\tcontextPercent: contextUsage?.percent ?? null,\n\t\tcontextWindowTokens: contextWindow,\n\t\tcontextTokens: contextUsage?.tokens ?? null,\n\t\theadroomStatus: formatHeadroomStatusLabel(),\n\t\toptimizerPolicy: getHeadroomRuntimeStatus().selector,\n\t\tmcpCount: countStableMcpServers(mcpInventory.entries),\n\t\tskillCount: countRoutableNonHubSkills(loadedSkills),\n\t\tpackageIntake,\n\t\tcwdLabel,\n\t\tgitBranch: footerData?.getGitBranch(),\n\t\ttodoState: getCurrentTodoState(),\n\t\truntimeState: \"ready\",\n\t\trouteState: \"active\",\n\t\tevidenceState: \"tracking\",\n\t\tcontrolState: \"ready\",\n\t\tdagOrchestrationState: \"DAG:omk-parallel-orchestrator\",\n\t\tansiColorState,\n\t\tstartupState: \"linked\",\n\t\tlinkState: \"ready\",\n\t\tsidebarState: \"pinned\",\n\t};\n}\n"]}
@@ -22,6 +22,11 @@ export interface SparkleAnchor {
22
22
  * stable `visibleWidth` of `innerWidth` regardless of motion frame.
23
23
  */
24
24
  export declare function sparkleRow(innerWidth: number, anchors: readonly SparkleAnchor[], frameMs: number): string;
25
+ /**
26
+ * The starfield is deliberately monochrome: `dim` and `muted` ink with a single
27
+ * accent star per row. Multi-hue confetti competed with the wordmark once the
28
+ * frames were reduced to hairlines.
29
+ */
25
30
  export declare const SPARKLE_ROW_TOP: readonly SparkleAnchor[];
26
31
  export declare const SPARKLE_ROW_BOTTOM: readonly SparkleAnchor[];
27
32
  //# sourceMappingURL=control-panel-sparkles.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"control-panel-sparkles.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/control-panel-sparkles.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,UAAU,EAAS,MAAM,mBAAmB,CAAC;AAE3D;;;;;;;;GAQG;AAEH,MAAM,WAAW,aAAa;IAC7B,+DAA+D;IAC/D,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,KAAK,EAAE,UAAU,CAAC;IAC3B,kEAAkE;IAClE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACvB;AAYD;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,SAAS,aAAa,EAAE,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAUzG;AAED,eAAO,MAAM,eAAe,EAAE,SAAS,aAAa,EAKnD,CAAC;AAEF,eAAO,MAAM,kBAAkB,EAAE,SAAS,aAAa,EAMtD,CAAC","sourcesContent":["import { type ThemeColor, theme } from \"../theme/theme.ts\";\n\n/**\n * Neon sparkle starfield for the OMK hero banner.\n *\n * The twinkle cadence is adapted from bokub/chalk-animation's `neon` effect\n * (https://github.com/bokub/chalk-animation), which alternates a glyph between\n * a dim and a bold neon color every ~500ms frame. Here it is extended to a\n * three-state flicker (bold / lit / faint) with a per-sparkle phase offset so\n * the field shimmers out of sync instead of strobing in lockstep.\n */\n\nexport interface SparkleAnchor {\n\t/** Horizontal position across the inner banner width, 0..1. */\n\treadonly frac: number;\n\treadonly glyph: string;\n\treadonly color: ThemeColor;\n\t/** Phase offset (in frames) so sparkles twinkle independently. */\n\treadonly phase: number;\n}\n\nconst SPARKLE_PERIOD_MS = 520;\n\nfunction twinkle(glyph: string, color: ThemeColor, phase: number, frameMs: number): string {\n\tconst frame = Math.floor(frameMs / SPARKLE_PERIOD_MS) + phase;\n\tconst state = ((frame % 3) + 3) % 3;\n\tif (state === 0) return theme.bold(theme.fg(color, glyph));\n\tif (state === 1) return theme.fg(color, glyph);\n\treturn theme.fg(\"dim\", glyph);\n}\n\n/**\n * Render a full-inner-width row with sparkles stamped at their fractional\n * columns. Every non-sparkle cell stays a literal space, so the row keeps a\n * stable `visibleWidth` of `innerWidth` regardless of motion frame.\n */\nexport function sparkleRow(innerWidth: number, anchors: readonly SparkleAnchor[], frameMs: number): string {\n\tif (innerWidth <= 0) return \"\";\n\tconst cells: string[] = new Array(innerWidth).fill(\" \");\n\tfor (const anchor of anchors) {\n\t\tconst col = Math.round(anchor.frac * (innerWidth - 1));\n\t\tif (col >= 0 && col < innerWidth) {\n\t\t\tcells[col] = twinkle(anchor.glyph, anchor.color, anchor.phase, frameMs);\n\t\t}\n\t}\n\treturn cells.join(\"\");\n}\n\nexport const SPARKLE_ROW_TOP: readonly SparkleAnchor[] = [\n\t{ frac: 0.1, glyph: \"·\", color: \"muted\", phase: 0 },\n\t{ frac: 0.28, glyph: \"•\", color: \"warning\", phase: 1 },\n\t{ frac: 0.73, glyph: \"✦\", color: \"mdCode\", phase: 2 },\n\t{ frac: 0.9, glyph: \"◆\", color: \"mdCode\", phase: 0 },\n];\n\nexport const SPARKLE_ROW_BOTTOM: readonly SparkleAnchor[] = [\n\t{ frac: 0.06, glyph: \"·\", color: \"muted\", phase: 2 },\n\t{ frac: 0.21, glyph: \"◆\", color: \"mdCode\", phase: 1 },\n\t{ frac: 0.55, glyph: \"·\", color: \"success\", phase: 0 },\n\t{ frac: 0.82, glyph: \"✦\", color: \"warning\", phase: 1 },\n\t{ frac: 0.96, glyph: \"◆\", color: \"accent\", phase: 2 },\n];\n"]}
1
+ {"version":3,"file":"control-panel-sparkles.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/control-panel-sparkles.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,UAAU,EAAS,MAAM,mBAAmB,CAAC;AAE3D;;;;;;;;GAQG;AAEH,MAAM,WAAW,aAAa;IAC7B,+DAA+D;IAC/D,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,KAAK,EAAE,UAAU,CAAC;IAC3B,kEAAkE;IAClE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACvB;AAYD;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,SAAS,aAAa,EAAE,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAUzG;AAED;;;;GAIG;AACH,eAAO,MAAM,eAAe,EAAE,SAAS,aAAa,EAKnD,CAAC;AAEF,eAAO,MAAM,kBAAkB,EAAE,SAAS,aAAa,EAMtD,CAAC","sourcesContent":["import { type ThemeColor, theme } from \"../theme/theme.ts\";\n\n/**\n * Neon sparkle starfield for the OMK hero banner.\n *\n * The twinkle cadence is adapted from bokub/chalk-animation's `neon` effect\n * (https://github.com/bokub/chalk-animation), which alternates a glyph between\n * a dim and a bold neon color every ~500ms frame. Here it is extended to a\n * three-state flicker (bold / lit / faint) with a per-sparkle phase offset so\n * the field shimmers out of sync instead of strobing in lockstep.\n */\n\nexport interface SparkleAnchor {\n\t/** Horizontal position across the inner banner width, 0..1. */\n\treadonly frac: number;\n\treadonly glyph: string;\n\treadonly color: ThemeColor;\n\t/** Phase offset (in frames) so sparkles twinkle independently. */\n\treadonly phase: number;\n}\n\nconst SPARKLE_PERIOD_MS = 520;\n\nfunction twinkle(glyph: string, color: ThemeColor, phase: number, frameMs: number): string {\n\tconst frame = Math.floor(frameMs / SPARKLE_PERIOD_MS) + phase;\n\tconst state = ((frame % 3) + 3) % 3;\n\tif (state === 0) return theme.bold(theme.fg(color, glyph));\n\tif (state === 1) return theme.fg(color, glyph);\n\treturn theme.fg(\"dim\", glyph);\n}\n\n/**\n * Render a full-inner-width row with sparkles stamped at their fractional\n * columns. Every non-sparkle cell stays a literal space, so the row keeps a\n * stable `visibleWidth` of `innerWidth` regardless of motion frame.\n */\nexport function sparkleRow(innerWidth: number, anchors: readonly SparkleAnchor[], frameMs: number): string {\n\tif (innerWidth <= 0) return \"\";\n\tconst cells: string[] = new Array(innerWidth).fill(\" \");\n\tfor (const anchor of anchors) {\n\t\tconst col = Math.round(anchor.frac * (innerWidth - 1));\n\t\tif (col >= 0 && col < innerWidth) {\n\t\t\tcells[col] = twinkle(anchor.glyph, anchor.color, anchor.phase, frameMs);\n\t\t}\n\t}\n\treturn cells.join(\"\");\n}\n\n/**\n * The starfield is deliberately monochrome: `dim` and `muted` ink with a single\n * accent star per row. Multi-hue confetti competed with the wordmark once the\n * frames were reduced to hairlines.\n */\nexport const SPARKLE_ROW_TOP: readonly SparkleAnchor[] = [\n\t{ frac: 0.1, glyph: \"·\", color: \"dim\", phase: 0 },\n\t{ frac: 0.28, glyph: \"·\", color: \"muted\", phase: 1 },\n\t{ frac: 0.73, glyph: \"✦\", color: \"dim\", phase: 2 },\n\t{ frac: 0.9, glyph: \"·\", color: \"accent\", phase: 0 },\n];\n\nexport const SPARKLE_ROW_BOTTOM: readonly SparkleAnchor[] = [\n\t{ frac: 0.06, glyph: \"·\", color: \"dim\", phase: 2 },\n\t{ frac: 0.21, glyph: \"·\", color: \"muted\", phase: 1 },\n\t{ frac: 0.55, glyph: \"✦\", color: \"dim\", phase: 0 },\n\t{ frac: 0.82, glyph: \"·\", color: \"muted\", phase: 1 },\n\t{ frac: 0.96, glyph: \"·\", color: \"accent\", phase: 2 },\n];\n"]}
@@ -26,17 +26,22 @@ export function sparkleRow(innerWidth, anchors, frameMs) {
26
26
  }
27
27
  return cells.join("");
28
28
  }
29
+ /**
30
+ * The starfield is deliberately monochrome: `dim` and `muted` ink with a single
31
+ * accent star per row. Multi-hue confetti competed with the wordmark once the
32
+ * frames were reduced to hairlines.
33
+ */
29
34
  export const SPARKLE_ROW_TOP = [
30
- { frac: 0.1, glyph: "·", color: "muted", phase: 0 },
31
- { frac: 0.28, glyph: "", color: "warning", phase: 1 },
32
- { frac: 0.73, glyph: "✦", color: "mdCode", phase: 2 },
33
- { frac: 0.9, glyph: "", color: "mdCode", phase: 0 },
35
+ { frac: 0.1, glyph: "·", color: "dim", phase: 0 },
36
+ { frac: 0.28, glyph: "·", color: "muted", phase: 1 },
37
+ { frac: 0.73, glyph: "✦", color: "dim", phase: 2 },
38
+ { frac: 0.9, glyph: "·", color: "accent", phase: 0 },
34
39
  ];
35
40
  export const SPARKLE_ROW_BOTTOM = [
36
- { frac: 0.06, glyph: "·", color: "muted", phase: 2 },
37
- { frac: 0.21, glyph: "", color: "mdCode", phase: 1 },
38
- { frac: 0.55, glyph: "·", color: "success", phase: 0 },
39
- { frac: 0.82, glyph: "", color: "warning", phase: 1 },
40
- { frac: 0.96, glyph: "", color: "accent", phase: 2 },
41
+ { frac: 0.06, glyph: "·", color: "dim", phase: 2 },
42
+ { frac: 0.21, glyph: "·", color: "muted", phase: 1 },
43
+ { frac: 0.55, glyph: "", color: "dim", phase: 0 },
44
+ { frac: 0.82, glyph: "·", color: "muted", phase: 1 },
45
+ { frac: 0.96, glyph: "·", color: "accent", phase: 2 },
41
46
  ];
42
47
  //# sourceMappingURL=control-panel-sparkles.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"control-panel-sparkles.js","sourceRoot":"","sources":["../../../../src/modes/interactive/components/control-panel-sparkles.ts"],"names":[],"mappings":"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","sourcesContent":["import { type ThemeColor, theme } from \"../theme/theme.ts\";\n\n/**\n * Neon sparkle starfield for the OMK hero banner.\n *\n * The twinkle cadence is adapted from bokub/chalk-animation's `neon` effect\n * (https://github.com/bokub/chalk-animation), which alternates a glyph between\n * a dim and a bold neon color every ~500ms frame. Here it is extended to a\n * three-state flicker (bold / lit / faint) with a per-sparkle phase offset so\n * the field shimmers out of sync instead of strobing in lockstep.\n */\n\nexport interface SparkleAnchor {\n\t/** Horizontal position across the inner banner width, 0..1. */\n\treadonly frac: number;\n\treadonly glyph: string;\n\treadonly color: ThemeColor;\n\t/** Phase offset (in frames) so sparkles twinkle independently. */\n\treadonly phase: number;\n}\n\nconst SPARKLE_PERIOD_MS = 520;\n\nfunction twinkle(glyph: string, color: ThemeColor, phase: number, frameMs: number): string {\n\tconst frame = Math.floor(frameMs / SPARKLE_PERIOD_MS) + phase;\n\tconst state = ((frame % 3) + 3) % 3;\n\tif (state === 0) return theme.bold(theme.fg(color, glyph));\n\tif (state === 1) return theme.fg(color, glyph);\n\treturn theme.fg(\"dim\", glyph);\n}\n\n/**\n * Render a full-inner-width row with sparkles stamped at their fractional\n * columns. Every non-sparkle cell stays a literal space, so the row keeps a\n * stable `visibleWidth` of `innerWidth` regardless of motion frame.\n */\nexport function sparkleRow(innerWidth: number, anchors: readonly SparkleAnchor[], frameMs: number): string {\n\tif (innerWidth <= 0) return \"\";\n\tconst cells: string[] = new Array(innerWidth).fill(\" \");\n\tfor (const anchor of anchors) {\n\t\tconst col = Math.round(anchor.frac * (innerWidth - 1));\n\t\tif (col >= 0 && col < innerWidth) {\n\t\t\tcells[col] = twinkle(anchor.glyph, anchor.color, anchor.phase, frameMs);\n\t\t}\n\t}\n\treturn cells.join(\"\");\n}\n\nexport const SPARKLE_ROW_TOP: readonly SparkleAnchor[] = [\n\t{ frac: 0.1, glyph: \"·\", color: \"muted\", phase: 0 },\n\t{ frac: 0.28, glyph: \"•\", color: \"warning\", phase: 1 },\n\t{ frac: 0.73, glyph: \"✦\", color: \"mdCode\", phase: 2 },\n\t{ frac: 0.9, glyph: \"◆\", color: \"mdCode\", phase: 0 },\n];\n\nexport const SPARKLE_ROW_BOTTOM: readonly SparkleAnchor[] = [\n\t{ frac: 0.06, glyph: \"·\", color: \"muted\", phase: 2 },\n\t{ frac: 0.21, glyph: \"◆\", color: \"mdCode\", phase: 1 },\n\t{ frac: 0.55, glyph: \"·\", color: \"success\", phase: 0 },\n\t{ frac: 0.82, glyph: \"✦\", color: \"warning\", phase: 1 },\n\t{ frac: 0.96, glyph: \"◆\", color: \"accent\", phase: 2 },\n];\n"]}
1
+ {"version":3,"file":"control-panel-sparkles.js","sourceRoot":"","sources":["../../../../src/modes/interactive/components/control-panel-sparkles.ts"],"names":[],"mappings":"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","sourcesContent":["import { type ThemeColor, theme } from \"../theme/theme.ts\";\n\n/**\n * Neon sparkle starfield for the OMK hero banner.\n *\n * The twinkle cadence is adapted from bokub/chalk-animation's `neon` effect\n * (https://github.com/bokub/chalk-animation), which alternates a glyph between\n * a dim and a bold neon color every ~500ms frame. Here it is extended to a\n * three-state flicker (bold / lit / faint) with a per-sparkle phase offset so\n * the field shimmers out of sync instead of strobing in lockstep.\n */\n\nexport interface SparkleAnchor {\n\t/** Horizontal position across the inner banner width, 0..1. */\n\treadonly frac: number;\n\treadonly glyph: string;\n\treadonly color: ThemeColor;\n\t/** Phase offset (in frames) so sparkles twinkle independently. */\n\treadonly phase: number;\n}\n\nconst SPARKLE_PERIOD_MS = 520;\n\nfunction twinkle(glyph: string, color: ThemeColor, phase: number, frameMs: number): string {\n\tconst frame = Math.floor(frameMs / SPARKLE_PERIOD_MS) + phase;\n\tconst state = ((frame % 3) + 3) % 3;\n\tif (state === 0) return theme.bold(theme.fg(color, glyph));\n\tif (state === 1) return theme.fg(color, glyph);\n\treturn theme.fg(\"dim\", glyph);\n}\n\n/**\n * Render a full-inner-width row with sparkles stamped at their fractional\n * columns. Every non-sparkle cell stays a literal space, so the row keeps a\n * stable `visibleWidth` of `innerWidth` regardless of motion frame.\n */\nexport function sparkleRow(innerWidth: number, anchors: readonly SparkleAnchor[], frameMs: number): string {\n\tif (innerWidth <= 0) return \"\";\n\tconst cells: string[] = new Array(innerWidth).fill(\" \");\n\tfor (const anchor of anchors) {\n\t\tconst col = Math.round(anchor.frac * (innerWidth - 1));\n\t\tif (col >= 0 && col < innerWidth) {\n\t\t\tcells[col] = twinkle(anchor.glyph, anchor.color, anchor.phase, frameMs);\n\t\t}\n\t}\n\treturn cells.join(\"\");\n}\n\n/**\n * The starfield is deliberately monochrome: `dim` and `muted` ink with a single\n * accent star per row. Multi-hue confetti competed with the wordmark once the\n * frames were reduced to hairlines.\n */\nexport const SPARKLE_ROW_TOP: readonly SparkleAnchor[] = [\n\t{ frac: 0.1, glyph: \"·\", color: \"dim\", phase: 0 },\n\t{ frac: 0.28, glyph: \"·\", color: \"muted\", phase: 1 },\n\t{ frac: 0.73, glyph: \"✦\", color: \"dim\", phase: 2 },\n\t{ frac: 0.9, glyph: \"·\", color: \"accent\", phase: 0 },\n];\n\nexport const SPARKLE_ROW_BOTTOM: readonly SparkleAnchor[] = [\n\t{ frac: 0.06, glyph: \"·\", color: \"dim\", phase: 2 },\n\t{ frac: 0.21, glyph: \"·\", color: \"muted\", phase: 1 },\n\t{ frac: 0.55, glyph: \"✦\", color: \"dim\", phase: 0 },\n\t{ frac: 0.82, glyph: \"·\", color: \"muted\", phase: 1 },\n\t{ frac: 0.96, glyph: \"·\", color: \"accent\", phase: 2 },\n];\n"]}
@@ -1,6 +1,16 @@
1
1
  import { type Component } from "omk-tui";
2
2
  import type { AgentSession } from "../../../core/agent-session.ts";
3
3
  import type { ReadonlyFooterDataProvider } from "../../../core/footer-data-provider.ts";
4
+ import type { PiPackageIntakeSummary } from "../../../core/pi-package-intake.ts";
5
+ /**
6
+ * Format token counts for compact footer display.
7
+ */
8
+ export declare function formatTokens(count: number): string;
9
+ /**
10
+ * Format byte counts for compact footer display.
11
+ */
12
+ export declare function formatBytes(bytes: number): string;
13
+ export declare function formatPackageIntake(summary: PiPackageIntakeSummary): string;
4
14
  export declare function formatCwdForFooter(cwd: string, home: string | undefined): string;
5
15
  /**
6
16
  * Footer component that shows pwd, token stats, and context usage.
@@ -1 +1 @@
1
- {"version":3,"file":"footer.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/footer.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,SAAS,EAAiC,MAAM,SAAS,CAAC;AACxE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gCAAgC,CAAC;AACnE,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,uCAAuC,CAAC;AA4CxF,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAYhF;AAED;;;GAGG;AACH,qBAAa,eAAgB,YAAW,SAAS;IAChD,OAAO,CAAC,kBAAkB,CAAQ;IAClC,OAAO,CAAC,OAAO,CAAe;IAC9B,OAAO,CAAC,UAAU,CAA6B;IAE/C,YAAY,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,0BAA0B,EAGxE;IAED,UAAU,CAAC,OAAO,EAAE,YAAY,GAAG,IAAI,CAEtC;IAED,qBAAqB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAE5C;IAED;;;;OAIG;IACH,OAAO,CAAC,mBAAmB;IA8B3B;;;OAGG;IACH,UAAU,IAAI,IAAI,CAEjB;IAED;;;OAGG;IACH,OAAO,IAAI,IAAI,CAEd;IAED,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CA6J9B;CACD","sourcesContent":["import { isAbsolute, relative, resolve, sep } from \"node:path\";\nimport { type Component, truncateToWidth, visibleWidth } from \"omk-tui\";\nimport type { AgentSession } from \"../../../core/agent-session.ts\";\nimport type { ReadonlyFooterDataProvider } from \"../../../core/footer-data-provider.ts\";\nimport type { PiPackageIntakeSummary } from \"../../../core/pi-package-intake.ts\";\nimport { theme } from \"../theme/theme.ts\";\n\n/**\n * Sanitize text for display in a single-line status.\n * Removes newlines, tabs, carriage returns, and other control characters.\n */\nfunction sanitizeStatusText(text: string): string {\n\t// Replace newlines, tabs, carriage returns with space, then collapse multiple spaces\n\treturn text\n\t\t.replace(/[\\r\\n\\t]/g, \" \")\n\t\t.replace(/ +/g, \" \")\n\t\t.trim();\n}\n\n/**\n * Format token counts for compact footer display.\n */\nfunction formatTokens(count: number): string {\n\tif (count < 1000) return count.toString();\n\tif (count < 10000) return `${(count / 1000).toFixed(1)}k`;\n\tif (count < 1000000) return `${Math.round(count / 1000)}k`;\n\tif (count < 10000000) return `${(count / 1000000).toFixed(1)}M`;\n\treturn `${Math.round(count / 1000000)}M`;\n}\n\n/**\n * Format byte counts for compact footer display.\n */\nfunction formatBytes(bytes: number): string {\n\tif (bytes < 1024) return `${bytes}B`;\n\tif (bytes < 1024 * 1024) return `${Math.round(bytes / 1024)}K`;\n\tif (bytes < 1024 * 1024 * 1024) return `${Math.round(bytes / (1024 * 1024))}M`;\n\treturn `${(bytes / (1024 * 1024 * 1024)).toFixed(1)}G`;\n}\n\nfunction formatPackageIntake(summary: PiPackageIntakeSummary): string {\n\tconst ready =\n\t\tsummary.acceptedNative + summary.acceptedReference + summary.acceptedMeasurement + summary.acceptedAdvisory;\n\tconst review = summary.deferred + summary.reject;\n\treturn `PKG ${ready}/${summary.total} R${review} B${summary.hardForkBlocked}`;\n}\n\nexport function formatCwdForFooter(cwd: string, home: string | undefined): string {\n\tif (!home) return cwd;\n\n\tconst resolvedCwd = resolve(cwd);\n\tconst resolvedHome = resolve(home);\n\tconst relativeToHome = relative(resolvedHome, resolvedCwd);\n\tconst isInsideHome =\n\t\trelativeToHome === \"\" ||\n\t\t(relativeToHome !== \"..\" && !relativeToHome.startsWith(`..${sep}`) && !isAbsolute(relativeToHome));\n\n\tif (!isInsideHome) return cwd;\n\treturn relativeToHome === \"\" ? \"~\" : `~${sep}${relativeToHome}`;\n}\n\n/**\n * Footer component that shows pwd, token stats, and context usage.\n * Computes token/context stats from session, gets git branch and extension statuses from provider.\n */\nexport class FooterComponent implements Component {\n\tprivate autoCompactEnabled = true;\n\tprivate session: AgentSession;\n\tprivate footerData: ReadonlyFooterDataProvider;\n\n\tconstructor(session: AgentSession, footerData: ReadonlyFooterDataProvider) {\n\t\tthis.session = session;\n\t\tthis.footerData = footerData;\n\t}\n\n\tsetSession(session: AgentSession): void {\n\t\tthis.session = session;\n\t}\n\n\tsetAutoCompactEnabled(enabled: boolean): void {\n\t\tthis.autoCompactEnabled = enabled;\n\t}\n\n\t/**\n\t * Build a compact system-wide CPU/memory metrics segment for the footer.\n\t * Degrades gracefully to shorter forms (or is omitted entirely) when the\n\t * terminal is very narrow so the rest of the footer can still render.\n\t */\n\tprivate buildMetricsSegment(width: number): string | undefined {\n\t\tconst cpu = this.footerData.getSystemCpuPercent();\n\t\tconst memUsed = this.footerData.getSystemMemoryUsedBytes();\n\t\tconst memTotal = this.footerData.getSystemMemoryTotalBytes();\n\t\tif (cpu === null || memUsed === null || memTotal === null || memTotal <= 0) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\tconst memPercent = (memUsed / memTotal) * 100;\n\t\tconst color: \"error\" | \"warning\" | \"dim\" =\n\t\t\tcpu >= 90 || memPercent >= 95 ? \"error\" : cpu >= 70 || memPercent >= 85 ? \"warning\" : \"dim\";\n\n\t\tconst cpuStr = `${Math.round(cpu)}%`;\n\t\tconst memStr = `${Math.round(memPercent)}%`;\n\n\t\tif (width >= 56) {\n\t\t\treturn theme.fg(color, `CPU ${cpuStr} MEM ${memStr} (${formatBytes(memUsed)}/${formatBytes(memTotal)})`);\n\t\t}\n\t\tif (width >= 48) {\n\t\t\treturn theme.fg(color, `CPU ${cpuStr} MEM ${memStr}`);\n\t\t}\n\t\tif (width >= 30) {\n\t\t\treturn theme.fg(color, `${cpuStr} ${memStr}`);\n\t\t}\n\t\tif (width >= 18) {\n\t\t\treturn theme.fg(color, cpuStr);\n\t\t}\n\t\treturn undefined;\n\t}\n\n\t/**\n\t * No-op: git branch caching now handled by provider.\n\t * Kept for compatibility with existing call sites in interactive-mode.\n\t */\n\tinvalidate(): void {\n\t\t// No-op: git branch is cached/invalidated by provider\n\t}\n\n\t/**\n\t * Clean up resources.\n\t * Git watcher cleanup now handled by provider.\n\t */\n\tdispose(): void {\n\t\t// Git watcher cleanup handled by provider\n\t}\n\n\trender(width: number): string[] {\n\t\tconst state = this.session.state;\n\n\t\t// Calculate cumulative usage from ALL session entries (not just post-compaction messages)\n\t\tlet totalInput = 0;\n\t\tlet totalOutput = 0;\n\t\tlet totalCacheRead = 0;\n\t\tlet totalCacheWrite = 0;\n\t\tlet totalCost = 0;\n\n\t\tfor (const entry of this.session.sessionManager.getEntries()) {\n\t\t\tif (entry.type === \"message\" && entry.message.role === \"assistant\") {\n\t\t\t\ttotalInput += entry.message.usage.input;\n\t\t\t\ttotalOutput += entry.message.usage.output;\n\t\t\t\ttotalCacheRead += entry.message.usage.cacheRead;\n\t\t\t\ttotalCacheWrite += entry.message.usage.cacheWrite;\n\t\t\t\ttotalCost += entry.message.usage.cost.total;\n\t\t\t}\n\t\t}\n\n\t\t// Calculate context usage from session (handles compaction correctly).\n\t\t// After compaction, tokens are unknown until the next LLM response.\n\t\tconst contextUsage = this.session.getContextUsage();\n\t\tconst contextWindow = contextUsage?.contextWindow ?? state.model?.contextWindow ?? 0;\n\t\tconst contextPercentValue = contextUsage?.percent ?? 0;\n\t\tconst contextPercent = contextUsage?.percent !== null ? contextPercentValue.toFixed(1) : \"?\";\n\n\t\t// Replace home directory with ~\n\t\tlet pwd = formatCwdForFooter(this.session.sessionManager.getCwd(), process.env.HOME || process.env.USERPROFILE);\n\n\t\t// Add git branch if available\n\t\tconst branch = this.footerData.getGitBranch();\n\t\tif (branch) {\n\t\t\tpwd = `${pwd} (${branch})`;\n\t\t}\n\n\t\t// Add session name if set\n\t\tconst sessionName = this.session.sessionManager.getSessionName();\n\t\tif (sessionName) {\n\t\t\tpwd = `${pwd} • ${sessionName}`;\n\t\t}\n\n\t\t// Build stats line\n\t\tconst statsParts = [];\n\t\tif (totalInput) statsParts.push(`↑${formatTokens(totalInput)}`);\n\t\tif (totalOutput) statsParts.push(`↓${formatTokens(totalOutput)}`);\n\t\tif (totalCacheRead) statsParts.push(`R${formatTokens(totalCacheRead)}`);\n\t\tif (totalCacheWrite) statsParts.push(`W${formatTokens(totalCacheWrite)}`);\n\n\t\t// Show cost with \"(sub)\" indicator if using OAuth subscription\n\t\tconst usingSubscription = state.model ? this.session.modelRegistry.isUsingOAuth(state.model) : false;\n\t\tif (totalCost || usingSubscription) {\n\t\t\tconst costStr = `$${totalCost.toFixed(3)}${usingSubscription ? \" (sub)\" : \"\"}`;\n\t\t\tstatsParts.push(costStr);\n\t\t}\n\n\t\t// Add CPU/memory metrics; degrade gracefully when horizontal space is tight.\n\t\tconst metricsSegment = this.buildMetricsSegment(width);\n\t\tif (metricsSegment) {\n\t\t\tstatsParts.push(metricsSegment);\n\t\t}\n\t\tstatsParts.push(formatPackageIntake(this.footerData.getPackageIntakeSummary()));\n\n\t\t// Colorize context percentage based on usage\n\t\tlet contextPercentStr: string;\n\t\tconst autoIndicator = this.autoCompactEnabled ? \" (auto)\" : \"\";\n\t\tconst contextPercentDisplay =\n\t\t\tcontextPercent === \"?\"\n\t\t\t\t? `?/${formatTokens(contextWindow)}${autoIndicator}`\n\t\t\t\t: `${contextPercent}%/${formatTokens(contextWindow)}${autoIndicator}`;\n\t\tif (contextPercentValue > 90) {\n\t\t\tcontextPercentStr = theme.fg(\"error\", contextPercentDisplay);\n\t\t} else if (contextPercentValue > 70) {\n\t\t\tcontextPercentStr = theme.fg(\"warning\", contextPercentDisplay);\n\t\t} else {\n\t\t\tcontextPercentStr = contextPercentDisplay;\n\t\t}\n\t\tstatsParts.push(contextPercentStr);\n\n\t\tlet statsLeft = statsParts.join(\" \");\n\n\t\t// Add model name on the right side, plus thinking level if model supports it\n\t\tconst modelName = state.model?.id || \"no-model\";\n\n\t\tlet statsLeftWidth = visibleWidth(statsLeft);\n\n\t\t// If statsLeft is too wide, truncate it\n\t\tif (statsLeftWidth > width) {\n\t\t\tstatsLeft = truncateToWidth(statsLeft, width, \"...\");\n\t\t\tstatsLeftWidth = visibleWidth(statsLeft);\n\t\t}\n\n\t\t// Calculate available space for padding (minimum 2 spaces between stats and model)\n\t\tconst minPadding = 2;\n\n\t\t// Add thinking level indicator if model supports reasoning\n\t\tlet rightSideWithoutProvider = modelName;\n\t\tif (state.model?.reasoning) {\n\t\t\tconst thinkingLevel = state.thinkingLevel || \"off\";\n\t\t\trightSideWithoutProvider =\n\t\t\t\tthinkingLevel === \"off\" ? `${modelName} • thinking off` : `${modelName} • ${thinkingLevel}`;\n\t\t}\n\n\t\t// Prepend the provider in parentheses if there are multiple providers and there's enough room\n\t\tlet rightSide = rightSideWithoutProvider;\n\t\tif (this.footerData.getAvailableProviderCount() > 1 && state.model) {\n\t\t\trightSide = `(${state.model!.provider}) ${rightSideWithoutProvider}`;\n\t\t\tif (statsLeftWidth + minPadding + visibleWidth(rightSide) > width) {\n\t\t\t\t// Too wide, fall back\n\t\t\t\trightSide = rightSideWithoutProvider;\n\t\t\t}\n\t\t}\n\n\t\tconst rightSideWidth = visibleWidth(rightSide);\n\t\tconst totalNeeded = statsLeftWidth + minPadding + rightSideWidth;\n\n\t\tlet statsLine: string;\n\t\tif (totalNeeded <= width) {\n\t\t\t// Both fit - add padding to right-align model\n\t\t\tconst padding = \" \".repeat(width - statsLeftWidth - rightSideWidth);\n\t\t\tstatsLine = statsLeft + padding + rightSide;\n\t\t} else {\n\t\t\t// Need to truncate right side\n\t\t\tconst availableForRight = width - statsLeftWidth - minPadding;\n\t\t\tif (availableForRight > 0) {\n\t\t\t\tconst truncatedRight = truncateToWidth(rightSide, availableForRight, \"\");\n\t\t\t\tconst truncatedRightWidth = visibleWidth(truncatedRight);\n\t\t\t\tconst padding = \" \".repeat(Math.max(0, width - statsLeftWidth - truncatedRightWidth));\n\t\t\t\tstatsLine = statsLeft + padding + truncatedRight;\n\t\t\t} else {\n\t\t\t\t// Not enough space for right side at all\n\t\t\t\tstatsLine = statsLeft;\n\t\t\t}\n\t\t}\n\n\t\t// Apply dim to each part separately. statsLeft may contain color codes (for context %)\n\t\t// that end with a reset, which would clear an outer dim wrapper. So we dim the parts\n\t\t// before and after the colored section independently.\n\t\tconst dimStatsLeft = theme.fg(\"dim\", statsLeft);\n\t\tconst remainder = statsLine.slice(statsLeft.length); // padding + rightSide\n\t\tconst dimRemainder = theme.fg(\"dim\", remainder);\n\n\t\tconst pwdLine = truncateToWidth(theme.fg(\"dim\", pwd), width, theme.fg(\"dim\", \"...\"));\n\t\tconst lines = [pwdLine, dimStatsLeft + dimRemainder];\n\n\t\t// Add extension statuses on a single line, sorted by key alphabetically\n\t\tconst extensionStatuses = this.footerData.getExtensionStatuses();\n\t\tif (extensionStatuses.size > 0) {\n\t\t\tconst sortedStatuses = Array.from(extensionStatuses.entries())\n\t\t\t\t.sort(([a], [b]) => a.localeCompare(b))\n\t\t\t\t.map(([, text]) => sanitizeStatusText(text));\n\t\t\tconst statusLine = sortedStatuses.join(\" \");\n\t\t\t// Truncate to terminal width with dim ellipsis for consistency with footer style\n\t\t\tlines.push(truncateToWidth(statusLine, width, theme.fg(\"dim\", \"...\")));\n\t\t}\n\n\t\treturn lines;\n\t}\n}\n"]}
1
+ {"version":3,"file":"footer.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/footer.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,SAAS,EAAiC,MAAM,SAAS,CAAC;AACxE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gCAAgC,CAAC;AACnE,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,uCAAuC,CAAC;AACxF,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,oCAAoC,CAAC;AAejF;;GAEG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAMlD;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAKjD;AAED,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,sBAAsB,GAAG,MAAM,CAK3E;AAED,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAYhF;AAED;;;GAGG;AACH,qBAAa,eAAgB,YAAW,SAAS;IAChD,OAAO,CAAC,kBAAkB,CAAQ;IAClC,OAAO,CAAC,OAAO,CAAe;IAC9B,OAAO,CAAC,UAAU,CAA6B;IAE/C,YAAY,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,0BAA0B,EAGxE;IAED,UAAU,CAAC,OAAO,EAAE,YAAY,GAAG,IAAI,CAEtC;IAED,qBAAqB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAE5C;IAED;;;;OAIG;IACH,OAAO,CAAC,mBAAmB;IA8B3B;;;OAGG;IACH,UAAU,IAAI,IAAI,CAEjB;IAED;;;OAGG;IACH,OAAO,IAAI,IAAI,CAEd;IAED,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CA6J9B;CACD","sourcesContent":["import { isAbsolute, relative, resolve, sep } from \"node:path\";\nimport { type Component, truncateToWidth, visibleWidth } from \"omk-tui\";\nimport type { AgentSession } from \"../../../core/agent-session.ts\";\nimport type { ReadonlyFooterDataProvider } from \"../../../core/footer-data-provider.ts\";\nimport type { PiPackageIntakeSummary } from \"../../../core/pi-package-intake.ts\";\nimport { theme } from \"../theme/theme.ts\";\n\n/**\n * Sanitize text for display in a single-line status.\n * Removes newlines, tabs, carriage returns, and other control characters.\n */\nfunction sanitizeStatusText(text: string): string {\n\t// Replace newlines, tabs, carriage returns with space, then collapse multiple spaces\n\treturn text\n\t\t.replace(/[\\r\\n\\t]/g, \" \")\n\t\t.replace(/ +/g, \" \")\n\t\t.trim();\n}\n\n/**\n * Format token counts for compact footer display.\n */\nexport function formatTokens(count: number): string {\n\tif (count < 1000) return count.toString();\n\tif (count < 10000) return `${(count / 1000).toFixed(1)}k`;\n\tif (count < 1000000) return `${Math.round(count / 1000)}k`;\n\tif (count < 10000000) return `${(count / 1000000).toFixed(1)}M`;\n\treturn `${Math.round(count / 1000000)}M`;\n}\n\n/**\n * Format byte counts for compact footer display.\n */\nexport function formatBytes(bytes: number): string {\n\tif (bytes < 1024) return `${bytes}B`;\n\tif (bytes < 1024 * 1024) return `${Math.round(bytes / 1024)}K`;\n\tif (bytes < 1024 * 1024 * 1024) return `${Math.round(bytes / (1024 * 1024))}M`;\n\treturn `${(bytes / (1024 * 1024 * 1024)).toFixed(1)}G`;\n}\n\nexport function formatPackageIntake(summary: PiPackageIntakeSummary): string {\n\tconst ready =\n\t\tsummary.acceptedNative + summary.acceptedReference + summary.acceptedMeasurement + summary.acceptedAdvisory;\n\tconst review = summary.deferred + summary.reject;\n\treturn `PKG ${ready}/${summary.total} R${review} B${summary.hardForkBlocked}`;\n}\n\nexport function formatCwdForFooter(cwd: string, home: string | undefined): string {\n\tif (!home) return cwd;\n\n\tconst resolvedCwd = resolve(cwd);\n\tconst resolvedHome = resolve(home);\n\tconst relativeToHome = relative(resolvedHome, resolvedCwd);\n\tconst isInsideHome =\n\t\trelativeToHome === \"\" ||\n\t\t(relativeToHome !== \"..\" && !relativeToHome.startsWith(`..${sep}`) && !isAbsolute(relativeToHome));\n\n\tif (!isInsideHome) return cwd;\n\treturn relativeToHome === \"\" ? \"~\" : `~${sep}${relativeToHome}`;\n}\n\n/**\n * Footer component that shows pwd, token stats, and context usage.\n * Computes token/context stats from session, gets git branch and extension statuses from provider.\n */\nexport class FooterComponent implements Component {\n\tprivate autoCompactEnabled = true;\n\tprivate session: AgentSession;\n\tprivate footerData: ReadonlyFooterDataProvider;\n\n\tconstructor(session: AgentSession, footerData: ReadonlyFooterDataProvider) {\n\t\tthis.session = session;\n\t\tthis.footerData = footerData;\n\t}\n\n\tsetSession(session: AgentSession): void {\n\t\tthis.session = session;\n\t}\n\n\tsetAutoCompactEnabled(enabled: boolean): void {\n\t\tthis.autoCompactEnabled = enabled;\n\t}\n\n\t/**\n\t * Build a compact system-wide CPU/memory metrics segment for the footer.\n\t * Degrades gracefully to shorter forms (or is omitted entirely) when the\n\t * terminal is very narrow so the rest of the footer can still render.\n\t */\n\tprivate buildMetricsSegment(width: number): string | undefined {\n\t\tconst cpu = this.footerData.getSystemCpuPercent();\n\t\tconst memUsed = this.footerData.getSystemMemoryUsedBytes();\n\t\tconst memTotal = this.footerData.getSystemMemoryTotalBytes();\n\t\tif (cpu === null || memUsed === null || memTotal === null || memTotal <= 0) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\tconst memPercent = (memUsed / memTotal) * 100;\n\t\tconst color: \"error\" | \"warning\" | \"dim\" =\n\t\t\tcpu >= 90 || memPercent >= 95 ? \"error\" : cpu >= 70 || memPercent >= 85 ? \"warning\" : \"dim\";\n\n\t\tconst cpuStr = `${Math.round(cpu)}%`;\n\t\tconst memStr = `${Math.round(memPercent)}%`;\n\n\t\tif (width >= 56) {\n\t\t\treturn theme.fg(color, `CPU ${cpuStr} MEM ${memStr} (${formatBytes(memUsed)}/${formatBytes(memTotal)})`);\n\t\t}\n\t\tif (width >= 48) {\n\t\t\treturn theme.fg(color, `CPU ${cpuStr} MEM ${memStr}`);\n\t\t}\n\t\tif (width >= 30) {\n\t\t\treturn theme.fg(color, `${cpuStr} ${memStr}`);\n\t\t}\n\t\tif (width >= 18) {\n\t\t\treturn theme.fg(color, cpuStr);\n\t\t}\n\t\treturn undefined;\n\t}\n\n\t/**\n\t * No-op: git branch caching now handled by provider.\n\t * Kept for compatibility with existing call sites in interactive-mode.\n\t */\n\tinvalidate(): void {\n\t\t// No-op: git branch is cached/invalidated by provider\n\t}\n\n\t/**\n\t * Clean up resources.\n\t * Git watcher cleanup now handled by provider.\n\t */\n\tdispose(): void {\n\t\t// Git watcher cleanup handled by provider\n\t}\n\n\trender(width: number): string[] {\n\t\tconst state = this.session.state;\n\n\t\t// Calculate cumulative usage from ALL session entries (not just post-compaction messages)\n\t\tlet totalInput = 0;\n\t\tlet totalOutput = 0;\n\t\tlet totalCacheRead = 0;\n\t\tlet totalCacheWrite = 0;\n\t\tlet totalCost = 0;\n\n\t\tfor (const entry of this.session.sessionManager.getEntries()) {\n\t\t\tif (entry.type === \"message\" && entry.message.role === \"assistant\") {\n\t\t\t\ttotalInput += entry.message.usage.input;\n\t\t\t\ttotalOutput += entry.message.usage.output;\n\t\t\t\ttotalCacheRead += entry.message.usage.cacheRead;\n\t\t\t\ttotalCacheWrite += entry.message.usage.cacheWrite;\n\t\t\t\ttotalCost += entry.message.usage.cost.total;\n\t\t\t}\n\t\t}\n\n\t\t// Calculate context usage from session (handles compaction correctly).\n\t\t// After compaction, tokens are unknown until the next LLM response.\n\t\tconst contextUsage = this.session.getContextUsage();\n\t\tconst contextWindow = contextUsage?.contextWindow ?? state.model?.contextWindow ?? 0;\n\t\tconst contextPercentValue = contextUsage?.percent ?? 0;\n\t\tconst contextPercent = contextUsage?.percent !== null ? contextPercentValue.toFixed(1) : \"?\";\n\n\t\t// Replace home directory with ~\n\t\tlet pwd = formatCwdForFooter(this.session.sessionManager.getCwd(), process.env.HOME || process.env.USERPROFILE);\n\n\t\t// Add git branch if available\n\t\tconst branch = this.footerData.getGitBranch();\n\t\tif (branch) {\n\t\t\tpwd = `${pwd} (${branch})`;\n\t\t}\n\n\t\t// Add session name if set\n\t\tconst sessionName = this.session.sessionManager.getSessionName();\n\t\tif (sessionName) {\n\t\t\tpwd = `${pwd} • ${sessionName}`;\n\t\t}\n\n\t\t// Build stats line\n\t\tconst statsParts = [];\n\t\tif (totalInput) statsParts.push(`↑${formatTokens(totalInput)}`);\n\t\tif (totalOutput) statsParts.push(`↓${formatTokens(totalOutput)}`);\n\t\tif (totalCacheRead) statsParts.push(`R${formatTokens(totalCacheRead)}`);\n\t\tif (totalCacheWrite) statsParts.push(`W${formatTokens(totalCacheWrite)}`);\n\n\t\t// Show cost with \"(sub)\" indicator if using OAuth subscription\n\t\tconst usingSubscription = state.model ? this.session.modelRegistry.isUsingOAuth(state.model) : false;\n\t\tif (totalCost || usingSubscription) {\n\t\t\tconst costStr = `$${totalCost.toFixed(3)}${usingSubscription ? \" (sub)\" : \"\"}`;\n\t\t\tstatsParts.push(costStr);\n\t\t}\n\n\t\t// Add CPU/memory metrics; degrade gracefully when horizontal space is tight.\n\t\tconst metricsSegment = this.buildMetricsSegment(width);\n\t\tif (metricsSegment) {\n\t\t\tstatsParts.push(metricsSegment);\n\t\t}\n\t\tstatsParts.push(formatPackageIntake(this.footerData.getPackageIntakeSummary()));\n\n\t\t// Colorize context percentage based on usage\n\t\tlet contextPercentStr: string;\n\t\tconst autoIndicator = this.autoCompactEnabled ? \" (auto)\" : \"\";\n\t\tconst contextPercentDisplay =\n\t\t\tcontextPercent === \"?\"\n\t\t\t\t? `?/${formatTokens(contextWindow)}${autoIndicator}`\n\t\t\t\t: `${contextPercent}%/${formatTokens(contextWindow)}${autoIndicator}`;\n\t\tif (contextPercentValue > 90) {\n\t\t\tcontextPercentStr = theme.fg(\"error\", contextPercentDisplay);\n\t\t} else if (contextPercentValue > 70) {\n\t\t\tcontextPercentStr = theme.fg(\"warning\", contextPercentDisplay);\n\t\t} else {\n\t\t\tcontextPercentStr = contextPercentDisplay;\n\t\t}\n\t\tstatsParts.push(contextPercentStr);\n\n\t\tlet statsLeft = statsParts.join(\" \");\n\n\t\t// Add model name on the right side, plus thinking level if model supports it\n\t\tconst modelName = state.model?.id || \"no-model\";\n\n\t\tlet statsLeftWidth = visibleWidth(statsLeft);\n\n\t\t// If statsLeft is too wide, truncate it\n\t\tif (statsLeftWidth > width) {\n\t\t\tstatsLeft = truncateToWidth(statsLeft, width, \"...\");\n\t\t\tstatsLeftWidth = visibleWidth(statsLeft);\n\t\t}\n\n\t\t// Calculate available space for padding (minimum 2 spaces between stats and model)\n\t\tconst minPadding = 2;\n\n\t\t// Add thinking level indicator if model supports reasoning\n\t\tlet rightSideWithoutProvider = modelName;\n\t\tif (state.model?.reasoning) {\n\t\t\tconst thinkingLevel = state.thinkingLevel || \"off\";\n\t\t\trightSideWithoutProvider =\n\t\t\t\tthinkingLevel === \"off\" ? `${modelName} • thinking off` : `${modelName} • ${thinkingLevel}`;\n\t\t}\n\n\t\t// Prepend the provider in parentheses if there are multiple providers and there's enough room\n\t\tlet rightSide = rightSideWithoutProvider;\n\t\tif (this.footerData.getAvailableProviderCount() > 1 && state.model) {\n\t\t\trightSide = `(${state.model!.provider}) ${rightSideWithoutProvider}`;\n\t\t\tif (statsLeftWidth + minPadding + visibleWidth(rightSide) > width) {\n\t\t\t\t// Too wide, fall back\n\t\t\t\trightSide = rightSideWithoutProvider;\n\t\t\t}\n\t\t}\n\n\t\tconst rightSideWidth = visibleWidth(rightSide);\n\t\tconst totalNeeded = statsLeftWidth + minPadding + rightSideWidth;\n\n\t\tlet statsLine: string;\n\t\tif (totalNeeded <= width) {\n\t\t\t// Both fit - add padding to right-align model\n\t\t\tconst padding = \" \".repeat(width - statsLeftWidth - rightSideWidth);\n\t\t\tstatsLine = statsLeft + padding + rightSide;\n\t\t} else {\n\t\t\t// Need to truncate right side\n\t\t\tconst availableForRight = width - statsLeftWidth - minPadding;\n\t\t\tif (availableForRight > 0) {\n\t\t\t\tconst truncatedRight = truncateToWidth(rightSide, availableForRight, \"\");\n\t\t\t\tconst truncatedRightWidth = visibleWidth(truncatedRight);\n\t\t\t\tconst padding = \" \".repeat(Math.max(0, width - statsLeftWidth - truncatedRightWidth));\n\t\t\t\tstatsLine = statsLeft + padding + truncatedRight;\n\t\t\t} else {\n\t\t\t\t// Not enough space for right side at all\n\t\t\t\tstatsLine = statsLeft;\n\t\t\t}\n\t\t}\n\n\t\t// Apply dim to each part separately. statsLeft may contain color codes (for context %)\n\t\t// that end with a reset, which would clear an outer dim wrapper. So we dim the parts\n\t\t// before and after the colored section independently.\n\t\tconst dimStatsLeft = theme.fg(\"dim\", statsLeft);\n\t\tconst remainder = statsLine.slice(statsLeft.length); // padding + rightSide\n\t\tconst dimRemainder = theme.fg(\"dim\", remainder);\n\n\t\tconst pwdLine = truncateToWidth(theme.fg(\"dim\", pwd), width, theme.fg(\"dim\", \"...\"));\n\t\tconst lines = [pwdLine, dimStatsLeft + dimRemainder];\n\n\t\t// Add extension statuses on a single line, sorted by key alphabetically\n\t\tconst extensionStatuses = this.footerData.getExtensionStatuses();\n\t\tif (extensionStatuses.size > 0) {\n\t\t\tconst sortedStatuses = Array.from(extensionStatuses.entries())\n\t\t\t\t.sort(([a], [b]) => a.localeCompare(b))\n\t\t\t\t.map(([, text]) => sanitizeStatusText(text));\n\t\t\tconst statusLine = sortedStatuses.join(\" \");\n\t\t\t// Truncate to terminal width with dim ellipsis for consistency with footer style\n\t\t\tlines.push(truncateToWidth(statusLine, width, theme.fg(\"dim\", \"...\")));\n\t\t}\n\n\t\treturn lines;\n\t}\n}\n"]}
@@ -15,7 +15,7 @@ function sanitizeStatusText(text) {
15
15
  /**
16
16
  * Format token counts for compact footer display.
17
17
  */
18
- function formatTokens(count) {
18
+ export function formatTokens(count) {
19
19
  if (count < 1000)
20
20
  return count.toString();
21
21
  if (count < 10000)
@@ -29,7 +29,7 @@ function formatTokens(count) {
29
29
  /**
30
30
  * Format byte counts for compact footer display.
31
31
  */
32
- function formatBytes(bytes) {
32
+ export function formatBytes(bytes) {
33
33
  if (bytes < 1024)
34
34
  return `${bytes}B`;
35
35
  if (bytes < 1024 * 1024)
@@ -38,7 +38,7 @@ function formatBytes(bytes) {
38
38
  return `${Math.round(bytes / (1024 * 1024))}M`;
39
39
  return `${(bytes / (1024 * 1024 * 1024)).toFixed(1)}G`;
40
40
  }
41
- function formatPackageIntake(summary) {
41
+ export function formatPackageIntake(summary) {
42
42
  const ready = summary.acceptedNative + summary.acceptedReference + summary.acceptedMeasurement + summary.acceptedAdvisory;
43
43
  const review = summary.deferred + summary.reject;
44
44
  return `PKG ${ready}/${summary.total} R${review} B${summary.hardForkBlocked}`;