@gokulvenkatareddy/cortex 0.1.7

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 (299) hide show
  1. package/README.md +1295 -0
  2. package/apps/octogent/.github/workflows/ci.yml +40 -0
  3. package/apps/octogent/.shims/claude +4 -0
  4. package/apps/octogent/AGENTS.md +71 -0
  5. package/apps/octogent/CONTRIBUTING.md +72 -0
  6. package/apps/octogent/LICENSE +21 -0
  7. package/apps/octogent/README.md +184 -0
  8. package/apps/octogent/apps/api/AGENTS.md +32 -0
  9. package/apps/octogent/apps/api/package.json +19 -0
  10. package/apps/octogent/apps/api/src/agentStateDetection.ts +181 -0
  11. package/apps/octogent/apps/api/src/claudeSessionScanner.ts +235 -0
  12. package/apps/octogent/apps/api/src/claudeSkills.ts +182 -0
  13. package/apps/octogent/apps/api/src/claudeUsage.ts +922 -0
  14. package/apps/octogent/apps/api/src/cli.ts +595 -0
  15. package/apps/octogent/apps/api/src/codeIntelStore.ts +46 -0
  16. package/apps/octogent/apps/api/src/codexUsage.ts +278 -0
  17. package/apps/octogent/apps/api/src/createApiServer/codeIntelRoutes.ts +60 -0
  18. package/apps/octogent/apps/api/src/createApiServer/conversationRoutes.ts +128 -0
  19. package/apps/octogent/apps/api/src/createApiServer/deckRoutes.ts +873 -0
  20. package/apps/octogent/apps/api/src/createApiServer/gitParsers.ts +140 -0
  21. package/apps/octogent/apps/api/src/createApiServer/gitRoutes.ts +214 -0
  22. package/apps/octogent/apps/api/src/createApiServer/miscRoutes.ts +316 -0
  23. package/apps/octogent/apps/api/src/createApiServer/monitorParsers.ts +137 -0
  24. package/apps/octogent/apps/api/src/createApiServer/monitorRoutes.ts +95 -0
  25. package/apps/octogent/apps/api/src/createApiServer/requestHandler.ts +311 -0
  26. package/apps/octogent/apps/api/src/createApiServer/requestParsers.ts +25 -0
  27. package/apps/octogent/apps/api/src/createApiServer/routeHelpers.ts +97 -0
  28. package/apps/octogent/apps/api/src/createApiServer/security.ts +70 -0
  29. package/apps/octogent/apps/api/src/createApiServer/terminalParsers.ts +167 -0
  30. package/apps/octogent/apps/api/src/createApiServer/terminalRoutes.ts +315 -0
  31. package/apps/octogent/apps/api/src/createApiServer/types.ts +24 -0
  32. package/apps/octogent/apps/api/src/createApiServer/uiStateParsers.ts +255 -0
  33. package/apps/octogent/apps/api/src/createApiServer/upgradeHandler.ts +38 -0
  34. package/apps/octogent/apps/api/src/createApiServer/usageRoutes.ts +84 -0
  35. package/apps/octogent/apps/api/src/createApiServer.ts +176 -0
  36. package/apps/octogent/apps/api/src/deck/readDeckTentacles.ts +595 -0
  37. package/apps/octogent/apps/api/src/githubRepoSummary.ts +397 -0
  38. package/apps/octogent/apps/api/src/logging.ts +9 -0
  39. package/apps/octogent/apps/api/src/monitor/defaults.ts +3 -0
  40. package/apps/octogent/apps/api/src/monitor/index.ts +8 -0
  41. package/apps/octogent/apps/api/src/monitor/repository.ts +303 -0
  42. package/apps/octogent/apps/api/src/monitor/service.ts +349 -0
  43. package/apps/octogent/apps/api/src/monitor/types.ts +120 -0
  44. package/apps/octogent/apps/api/src/monitor/xProvider.ts +587 -0
  45. package/apps/octogent/apps/api/src/projectPersistence.ts +377 -0
  46. package/apps/octogent/apps/api/src/prompts/index.ts +10 -0
  47. package/apps/octogent/apps/api/src/prompts/promptResolver.ts +145 -0
  48. package/apps/octogent/apps/api/src/runtimeMetadata.ts +69 -0
  49. package/apps/octogent/apps/api/src/server.ts +80 -0
  50. package/apps/octogent/apps/api/src/setupState.ts +80 -0
  51. package/apps/octogent/apps/api/src/setupStatus.ts +174 -0
  52. package/apps/octogent/apps/api/src/startupPrerequisites.ts +146 -0
  53. package/apps/octogent/apps/api/src/terminalRuntime/channelMessaging.ts +87 -0
  54. package/apps/octogent/apps/api/src/terminalRuntime/claudeTranscript.ts +279 -0
  55. package/apps/octogent/apps/api/src/terminalRuntime/constants.ts +15 -0
  56. package/apps/octogent/apps/api/src/terminalRuntime/conversations.ts +492 -0
  57. package/apps/octogent/apps/api/src/terminalRuntime/gitOperations.ts +341 -0
  58. package/apps/octogent/apps/api/src/terminalRuntime/hookProcessor.ts +405 -0
  59. package/apps/octogent/apps/api/src/terminalRuntime/protocol.ts +46 -0
  60. package/apps/octogent/apps/api/src/terminalRuntime/ptyEnvironment.ts +50 -0
  61. package/apps/octogent/apps/api/src/terminalRuntime/registry.ts +423 -0
  62. package/apps/octogent/apps/api/src/terminalRuntime/sessionRuntime.ts +671 -0
  63. package/apps/octogent/apps/api/src/terminalRuntime/systemClients.ts +432 -0
  64. package/apps/octogent/apps/api/src/terminalRuntime/types.ts +157 -0
  65. package/apps/octogent/apps/api/src/terminalRuntime/worktreeManager.ts +135 -0
  66. package/apps/octogent/apps/api/src/terminalRuntime.ts +567 -0
  67. package/apps/octogent/apps/api/src/usageUtils.ts +16 -0
  68. package/apps/octogent/apps/api/src/ws-shim.d.ts +28 -0
  69. package/apps/octogent/apps/api/tests/agentStateDetection.test.ts +67 -0
  70. package/apps/octogent/apps/api/tests/claudeUsage.test.ts +583 -0
  71. package/apps/octogent/apps/api/tests/codexUsage.test.ts +107 -0
  72. package/apps/octogent/apps/api/tests/createApiServer.test.ts +3207 -0
  73. package/apps/octogent/apps/api/tests/githubRepoSummary.test.ts +100 -0
  74. package/apps/octogent/apps/api/tests/logging.test.ts +33 -0
  75. package/apps/octogent/apps/api/tests/monitorApi.test.ts +467 -0
  76. package/apps/octogent/apps/api/tests/monitorCore.test.ts +104 -0
  77. package/apps/octogent/apps/api/tests/promptResolver.test.ts +109 -0
  78. package/apps/octogent/apps/api/tests/protocol.test.ts +14 -0
  79. package/apps/octogent/apps/api/tests/sessionRuntime.test.ts +608 -0
  80. package/apps/octogent/apps/api/tests/startupPrerequisites.test.ts +70 -0
  81. package/apps/octogent/apps/api/tests/upgradeHandler.test.ts +40 -0
  82. package/apps/octogent/apps/api/tests/xMonitorProvider.test.ts +109 -0
  83. package/apps/octogent/apps/api/tsconfig.json +7 -0
  84. package/apps/octogent/apps/api/vitest.config.ts +7 -0
  85. package/apps/octogent/apps/web/AGENTS.md +38 -0
  86. package/apps/octogent/apps/web/index.html +13 -0
  87. package/apps/octogent/apps/web/package.json +32 -0
  88. package/apps/octogent/apps/web/public/octopus-favicon.svg +26 -0
  89. package/apps/octogent/apps/web/src/App.tsx +646 -0
  90. package/apps/octogent/apps/web/src/app/canvas/types.ts +34 -0
  91. package/apps/octogent/apps/web/src/app/codeIntelAggregation.ts +278 -0
  92. package/apps/octogent/apps/web/src/app/constants.ts +28 -0
  93. package/apps/octogent/apps/web/src/app/conversationNormalizers.ts +135 -0
  94. package/apps/octogent/apps/web/src/app/formatTimestamp.ts +18 -0
  95. package/apps/octogent/apps/web/src/app/githubMetrics.ts +76 -0
  96. package/apps/octogent/apps/web/src/app/githubNormalizers.ts +91 -0
  97. package/apps/octogent/apps/web/src/app/hooks/useAgentRuntimeStates.ts +18 -0
  98. package/apps/octogent/apps/web/src/app/hooks/useBackendLivenessPolling.ts +53 -0
  99. package/apps/octogent/apps/web/src/app/hooks/useCanvasGraphData.ts +449 -0
  100. package/apps/octogent/apps/web/src/app/hooks/useCanvasTransform.ts +260 -0
  101. package/apps/octogent/apps/web/src/app/hooks/useClaudeUsagePolling.ts +40 -0
  102. package/apps/octogent/apps/web/src/app/hooks/useClickOutside.ts +30 -0
  103. package/apps/octogent/apps/web/src/app/hooks/useCodeIntelRuntime.ts +83 -0
  104. package/apps/octogent/apps/web/src/app/hooks/useCodexUsagePolling.ts +35 -0
  105. package/apps/octogent/apps/web/src/app/hooks/useConsoleKeyboardShortcuts.ts +31 -0
  106. package/apps/octogent/apps/web/src/app/hooks/useConversationsRuntime.ts +377 -0
  107. package/apps/octogent/apps/web/src/app/hooks/useForceSimulation.ts +319 -0
  108. package/apps/octogent/apps/web/src/app/hooks/useGitHubPrimaryViewModel.ts +143 -0
  109. package/apps/octogent/apps/web/src/app/hooks/useGithubSummaryPolling.ts +28 -0
  110. package/apps/octogent/apps/web/src/app/hooks/useInitialColumnsHydration.ts +64 -0
  111. package/apps/octogent/apps/web/src/app/hooks/useMonitorRuntime.ts +220 -0
  112. package/apps/octogent/apps/web/src/app/hooks/usePersistedUiState.ts +536 -0
  113. package/apps/octogent/apps/web/src/app/hooks/usePollingData.ts +79 -0
  114. package/apps/octogent/apps/web/src/app/hooks/usePromptLibrary.ts +185 -0
  115. package/apps/octogent/apps/web/src/app/hooks/useTentacleGitLifecycle.ts +530 -0
  116. package/apps/octogent/apps/web/src/app/hooks/useTerminalCompletionNotification.ts +94 -0
  117. package/apps/octogent/apps/web/src/app/hooks/useTerminalMutations.ts +266 -0
  118. package/apps/octogent/apps/web/src/app/hooks/useTerminalStateReconciliation.ts +23 -0
  119. package/apps/octogent/apps/web/src/app/hooks/useUsageHeatmapPolling.ts +43 -0
  120. package/apps/octogent/apps/web/src/app/hooks/useWorkspaceSetup.ts +80 -0
  121. package/apps/octogent/apps/web/src/app/hotkeys.ts +31 -0
  122. package/apps/octogent/apps/web/src/app/monitorNormalizers.ts +145 -0
  123. package/apps/octogent/apps/web/src/app/notificationSounds.ts +164 -0
  124. package/apps/octogent/apps/web/src/app/terminalRuntimeStateStore.ts +261 -0
  125. package/apps/octogent/apps/web/src/app/terminalState.ts +21 -0
  126. package/apps/octogent/apps/web/src/app/types.ts +42 -0
  127. package/apps/octogent/apps/web/src/app/uiStateNormalizers.ts +113 -0
  128. package/apps/octogent/apps/web/src/app/usageNormalizers.ts +58 -0
  129. package/apps/octogent/apps/web/src/components/ActiveAgentsSidebar.tsx +60 -0
  130. package/apps/octogent/apps/web/src/components/ActivityPrimaryView.tsx +21 -0
  131. package/apps/octogent/apps/web/src/components/AgentStateBadge.tsx +47 -0
  132. package/apps/octogent/apps/web/src/components/CanvasPrimaryView.tsx +1532 -0
  133. package/apps/octogent/apps/web/src/components/ClearAllConversationsDialog.tsx +33 -0
  134. package/apps/octogent/apps/web/src/components/CodeIntelArcDiagram.tsx +245 -0
  135. package/apps/octogent/apps/web/src/components/CodeIntelPrimaryView.tsx +104 -0
  136. package/apps/octogent/apps/web/src/components/CodeIntelTreemap.tsx +138 -0
  137. package/apps/octogent/apps/web/src/components/ConsolePrimaryNav.tsx +31 -0
  138. package/apps/octogent/apps/web/src/components/ConversationsPrimaryView.tsx +243 -0
  139. package/apps/octogent/apps/web/src/components/DeckPrimaryView.tsx +613 -0
  140. package/apps/octogent/apps/web/src/components/DeleteTentacleDialog.tsx +91 -0
  141. package/apps/octogent/apps/web/src/components/EmptyOctopus.tsx +715 -0
  142. package/apps/octogent/apps/web/src/components/GitHubPrimaryView.tsx +494 -0
  143. package/apps/octogent/apps/web/src/components/MonitorPrimaryView.tsx +475 -0
  144. package/apps/octogent/apps/web/src/components/PrimaryViewRouter.tsx +99 -0
  145. package/apps/octogent/apps/web/src/components/PromptsPrimaryView.tsx +243 -0
  146. package/apps/octogent/apps/web/src/components/RuntimeStatusStrip.tsx +273 -0
  147. package/apps/octogent/apps/web/src/components/SettingsPrimaryView.tsx +92 -0
  148. package/apps/octogent/apps/web/src/components/SidebarActionPanel.tsx +124 -0
  149. package/apps/octogent/apps/web/src/components/SidebarConversationsList.tsx +279 -0
  150. package/apps/octogent/apps/web/src/components/SidebarPromptsList.tsx +116 -0
  151. package/apps/octogent/apps/web/src/components/TelemetryTape.tsx +106 -0
  152. package/apps/octogent/apps/web/src/components/TentacleGitActionsDialog.tsx +341 -0
  153. package/apps/octogent/apps/web/src/components/Terminal.tsx +524 -0
  154. package/apps/octogent/apps/web/src/components/TerminalPromptPicker.tsx +140 -0
  155. package/apps/octogent/apps/web/src/components/UsageHeatmap.tsx +702 -0
  156. package/apps/octogent/apps/web/src/components/canvas/CanvasTentaclePanel.tsx +485 -0
  157. package/apps/octogent/apps/web/src/components/canvas/CanvasTerminalColumn.tsx +89 -0
  158. package/apps/octogent/apps/web/src/components/canvas/DeleteAllTerminalsDialog.tsx +221 -0
  159. package/apps/octogent/apps/web/src/components/canvas/OctopusNode.tsx +307 -0
  160. package/apps/octogent/apps/web/src/components/canvas/SessionNode.tsx +185 -0
  161. package/apps/octogent/apps/web/src/components/deck/ActionCards.tsx +118 -0
  162. package/apps/octogent/apps/web/src/components/deck/AddTentacleForm.tsx +269 -0
  163. package/apps/octogent/apps/web/src/components/deck/DeckBottomActions.tsx +56 -0
  164. package/apps/octogent/apps/web/src/components/deck/TentaclePod.tsx +334 -0
  165. package/apps/octogent/apps/web/src/components/deck/WorkspaceSetupCard.tsx +105 -0
  166. package/apps/octogent/apps/web/src/components/deck/octopusVisuals.ts +72 -0
  167. package/apps/octogent/apps/web/src/components/terminalReplay.ts +62 -0
  168. package/apps/octogent/apps/web/src/components/terminalWheel.ts +54 -0
  169. package/apps/octogent/apps/web/src/components/ui/ActionButton.tsx +34 -0
  170. package/apps/octogent/apps/web/src/components/ui/ConfirmationDialog.tsx +86 -0
  171. package/apps/octogent/apps/web/src/components/ui/MarkdownContent.tsx +43 -0
  172. package/apps/octogent/apps/web/src/components/ui/SettingsToggle.tsx +34 -0
  173. package/apps/octogent/apps/web/src/components/ui/StatusBadge.tsx +24 -0
  174. package/apps/octogent/apps/web/src/main.tsx +17 -0
  175. package/apps/octogent/apps/web/src/runtime/HttpTerminalSnapshotReader.ts +87 -0
  176. package/apps/octogent/apps/web/src/runtime/runtimeEndpoints.ts +412 -0
  177. package/apps/octogent/apps/web/src/styles/chrome-and-buttons.css +272 -0
  178. package/apps/octogent/apps/web/src/styles/console-canvas-activity.css +358 -0
  179. package/apps/octogent/apps/web/src/styles/console-canvas-canvas.css +1843 -0
  180. package/apps/octogent/apps/web/src/styles/console-canvas-code-intel.css +227 -0
  181. package/apps/octogent/apps/web/src/styles/console-canvas-conversations.css +705 -0
  182. package/apps/octogent/apps/web/src/styles/console-canvas-deck.css +1524 -0
  183. package/apps/octogent/apps/web/src/styles/console-canvas-github.css +541 -0
  184. package/apps/octogent/apps/web/src/styles/console-canvas-monitor.css +595 -0
  185. package/apps/octogent/apps/web/src/styles/console-canvas-pixpack.css +81 -0
  186. package/apps/octogent/apps/web/src/styles/console-canvas-prompts.css +474 -0
  187. package/apps/octogent/apps/web/src/styles/console-canvas-settings.css +207 -0
  188. package/apps/octogent/apps/web/src/styles/console-chrome-status-nav.css +441 -0
  189. package/apps/octogent/apps/web/src/styles/console-overrides-telemetry.css +320 -0
  190. package/apps/octogent/apps/web/src/styles/console-theme-tokens.css +25 -0
  191. package/apps/octogent/apps/web/src/styles/cortex-theme.css +412 -0
  192. package/apps/octogent/apps/web/src/styles/foundation.css +100 -0
  193. package/apps/octogent/apps/web/src/styles/sidebar-and-scrollbars.css +447 -0
  194. package/apps/octogent/apps/web/src/styles/terminal-and-status.css +356 -0
  195. package/apps/octogent/apps/web/src/styles.css +25 -0
  196. package/apps/octogent/apps/web/src/types/ws.d.ts +23 -0
  197. package/apps/octogent/apps/web/tests/CanvasPrimaryView.test.tsx +347 -0
  198. package/apps/octogent/apps/web/tests/HttpTerminalSnapshotReader.test.tsx +54 -0
  199. package/apps/octogent/apps/web/tests/RuntimeStatusStrip.test.tsx +70 -0
  200. package/apps/octogent/apps/web/tests/Terminal.test.tsx +87 -0
  201. package/apps/octogent/apps/web/tests/add-tentacle-form.test.tsx +48 -0
  202. package/apps/octogent/apps/web/tests/app-github-runtime.test.tsx +162 -0
  203. package/apps/octogent/apps/web/tests/app-monitor-runtime.test.tsx +657 -0
  204. package/apps/octogent/apps/web/tests/app-shell-navigation.test.tsx +109 -0
  205. package/apps/octogent/apps/web/tests/app-swarm-refresh.test.tsx +268 -0
  206. package/apps/octogent/apps/web/tests/app-ui-state-persistence.test.tsx +116 -0
  207. package/apps/octogent/apps/web/tests/app-workspace-setup.test.tsx +217 -0
  208. package/apps/octogent/apps/web/tests/canvas-tentacle-panel.test.tsx +195 -0
  209. package/apps/octogent/apps/web/tests/delete-all-terminals-dialog.test.tsx +76 -0
  210. package/apps/octogent/apps/web/tests/githubMetrics.test.tsx +52 -0
  211. package/apps/octogent/apps/web/tests/hotkeys.test.tsx +44 -0
  212. package/apps/octogent/apps/web/tests/runtimeEndpoints.test.tsx +240 -0
  213. package/apps/octogent/apps/web/tests/setup.ts +39 -0
  214. package/apps/octogent/apps/web/tests/tentacle-pod.test.tsx +62 -0
  215. package/apps/octogent/apps/web/tests/terminalReplay.test.ts +71 -0
  216. package/apps/octogent/apps/web/tests/terminalState.test.tsx +49 -0
  217. package/apps/octogent/apps/web/tests/terminalWheel.test.tsx +51 -0
  218. package/apps/octogent/apps/web/tests/test-utils/appTestHarness.ts +48 -0
  219. package/apps/octogent/apps/web/tests/uiPrimitives.test.tsx +31 -0
  220. package/apps/octogent/apps/web/tests/useAgentRuntimeStates.test.tsx +47 -0
  221. package/apps/octogent/apps/web/tsconfig.json +8 -0
  222. package/apps/octogent/apps/web/vite.api.bundle.config.mts +32 -0
  223. package/apps/octogent/apps/web/vite.config.ts +22 -0
  224. package/apps/octogent/bin/octogent +3 -0
  225. package/apps/octogent/biome.json +21 -0
  226. package/apps/octogent/docs/concepts/mental-model.md +79 -0
  227. package/apps/octogent/docs/concepts/runtime-and-api.md +60 -0
  228. package/apps/octogent/docs/concepts/tentacles.md +85 -0
  229. package/apps/octogent/docs/getting-started/installation.md +54 -0
  230. package/apps/octogent/docs/getting-started/quickstart.md +79 -0
  231. package/apps/octogent/docs/guides/inter-agent-messaging.md +43 -0
  232. package/apps/octogent/docs/guides/orchestrating-child-agents.md +49 -0
  233. package/apps/octogent/docs/guides/working-with-todos.md +56 -0
  234. package/apps/octogent/docs/index.md +40 -0
  235. package/apps/octogent/docs/reference/api.md +103 -0
  236. package/apps/octogent/docs/reference/cli.md +71 -0
  237. package/apps/octogent/docs/reference/experimental-features.md +28 -0
  238. package/apps/octogent/docs/reference/filesystem-layout.md +62 -0
  239. package/apps/octogent/docs/reference/troubleshooting.md +49 -0
  240. package/apps/octogent/package.json +35 -0
  241. package/apps/octogent/packages/core/AGENTS.md +31 -0
  242. package/apps/octogent/packages/core/package.json +12 -0
  243. package/apps/octogent/packages/core/src/adapters/InMemoryTerminalSnapshotReader.ts +10 -0
  244. package/apps/octogent/packages/core/src/application/buildTerminalList.ts +13 -0
  245. package/apps/octogent/packages/core/src/domain/agentRuntime.ts +18 -0
  246. package/apps/octogent/packages/core/src/domain/channel.ts +8 -0
  247. package/apps/octogent/packages/core/src/domain/completionSound.ts +14 -0
  248. package/apps/octogent/packages/core/src/domain/conversation.ts +48 -0
  249. package/apps/octogent/packages/core/src/domain/deck.ts +33 -0
  250. package/apps/octogent/packages/core/src/domain/git.ts +32 -0
  251. package/apps/octogent/packages/core/src/domain/monitor.ts +62 -0
  252. package/apps/octogent/packages/core/src/domain/setup.ts +27 -0
  253. package/apps/octogent/packages/core/src/domain/terminal.ts +17 -0
  254. package/apps/octogent/packages/core/src/domain/uiState.ts +22 -0
  255. package/apps/octogent/packages/core/src/domain/usage.ts +60 -0
  256. package/apps/octogent/packages/core/src/index.ts +15 -0
  257. package/apps/octogent/packages/core/src/ports/TerminalSnapshotReader.ts +5 -0
  258. package/apps/octogent/packages/core/src/util/typeCoercion.ts +20 -0
  259. package/apps/octogent/packages/core/tests/buildTerminalList.test.ts +75 -0
  260. package/apps/octogent/packages/core/tsconfig.json +7 -0
  261. package/apps/octogent/packages/core/tsconfig.tsbuildinfo +1 -0
  262. package/apps/octogent/packages/core/vitest.config.ts +7 -0
  263. package/apps/octogent/pnpm-lock.yaml +3212 -0
  264. package/apps/octogent/pnpm-workspace.yaml +3 -0
  265. package/apps/octogent/prompts/meta-prompt-generator.md +223 -0
  266. package/apps/octogent/prompts/octoboss-clean-contexts.md +30 -0
  267. package/apps/octogent/prompts/octoboss-reorganize-tentacles.md +29 -0
  268. package/apps/octogent/prompts/octoboss-reorganize-todos.md +27 -0
  269. package/apps/octogent/prompts/sandbox-init.md +3 -0
  270. package/apps/octogent/prompts/swarm-parent.md +83 -0
  271. package/apps/octogent/prompts/swarm-worker.md +50 -0
  272. package/apps/octogent/prompts/tentacle-context-init.md +1 -0
  273. package/apps/octogent/prompts/tentacle-planner.md +110 -0
  274. package/apps/octogent/prompts/tentacle-reorganize-todos.md +20 -0
  275. package/apps/octogent/prompts/tentacle-update-tentacle.md +18 -0
  276. package/apps/octogent/scripts/build-package.mjs +23 -0
  277. package/apps/octogent/scripts/dev.mjs +158 -0
  278. package/apps/octogent/scripts/smoke-public-install.mjs +271 -0
  279. package/apps/octogent/static/images/octogent-header.png +0 -0
  280. package/apps/octogent/static/images/preview_1.jpg +0 -0
  281. package/apps/octogent/static/images/preview_2.jpg +0 -0
  282. package/apps/octogent/static/images/preview_3.jpg +0 -0
  283. package/apps/octogent/static/images/preview_4.jpg +0 -0
  284. package/apps/octogent/static/images/preview_5.jpg +0 -0
  285. package/apps/octogent/static/images/preview_6.jpg +0 -0
  286. package/apps/octogent/tsconfig.base.json +16 -0
  287. package/bin/AGI +3 -0
  288. package/bin/AGI-install-app +71 -0
  289. package/bin/AGI-ui +16 -0
  290. package/bin/AGI-voice +15 -0
  291. package/bin/AGI-web +16 -0
  292. package/bin/cortex +109 -0
  293. package/bin/cortex-octogent +99 -0
  294. package/bin/import-specifier.mjs +13 -0
  295. package/bin/import-specifier.test.mjs +13 -0
  296. package/bin/octo +150 -0
  297. package/dist/cli.mjs +555650 -0
  298. package/package.json +157 -0
  299. package/scripts/setup-wizard.ts +390 -0
@@ -0,0 +1,595 @@
1
+ import { spawn } from "node:child_process";
2
+ import { existsSync } from "node:fs";
3
+ import { createServer } from "node:net";
4
+ import { basename, join, resolve } from "node:path";
5
+
6
+ import {
7
+ ensureOctogentGitignoreEntry,
8
+ ensureProjectScaffold,
9
+ loadProjectConfig,
10
+ loadProjectsRegistry,
11
+ migrateStateToGlobal,
12
+ registerProject,
13
+ resolveEphemeralProjectStateDir,
14
+ resolveProjectStateDir,
15
+ } from "./projectPersistence";
16
+ import { clearRuntimeMetadata, readRuntimeMetadata, writeRuntimeMetadata } from "./runtimeMetadata";
17
+ import {
18
+ collectStartupPrerequisiteReport,
19
+ formatStartupPrerequisiteReport,
20
+ } from "./startupPrerequisites";
21
+
22
+ const args = process.argv.slice(2);
23
+ const command = args[0];
24
+
25
+ const resolvePackageRoot = () => {
26
+ const envRoot = process.env.OCTOGENT_PACKAGE_ROOT?.trim();
27
+ if (envRoot) {
28
+ return resolve(envRoot);
29
+ }
30
+
31
+ const candidates = [
32
+ resolve(import.meta.dirname ?? ".", "../.."),
33
+ resolve(import.meta.dirname ?? ".", "../../.."),
34
+ process.cwd(),
35
+ ];
36
+
37
+ for (const candidate of candidates) {
38
+ if (existsSync(join(candidate, "package.json"))) {
39
+ return candidate;
40
+ }
41
+ }
42
+
43
+ return candidates[0] ?? process.cwd();
44
+ };
45
+
46
+ const PACKAGE_ROOT = resolvePackageRoot();
47
+
48
+ const resolveRuntimeAssetPath = (...relativePathCandidates: [string[], ...string[][]]) => {
49
+ for (const relativePath of relativePathCandidates) {
50
+ const candidate = join(PACKAGE_ROOT, ...relativePath);
51
+ if (existsSync(candidate)) {
52
+ return candidate;
53
+ }
54
+ }
55
+
56
+ return join(PACKAGE_ROOT, ...relativePathCandidates[0]);
57
+ };
58
+
59
+ const DEFAULT_START_PORT = 8787;
60
+ const MAX_PORT_ATTEMPTS = 200;
61
+
62
+ const initializeProject = (workspaceCwd: string, preferredName?: string) => {
63
+ const projectName = preferredName?.trim() || basename(workspaceCwd) || "octogent-project";
64
+ const hadConfig = loadProjectConfig(workspaceCwd) !== null;
65
+ const projectConfig = ensureProjectScaffold(workspaceCwd, projectName);
66
+ ensureOctogentGitignoreEntry(workspaceCwd);
67
+ registerProject(workspaceCwd, projectConfig.displayName);
68
+ const projectStateDir = resolveProjectStateDir(workspaceCwd, projectConfig.displayName);
69
+ migrateStateToGlobal(workspaceCwd, projectStateDir);
70
+ return {
71
+ created: !hadConfig,
72
+ projectConfig,
73
+ projectStateDir,
74
+ };
75
+ };
76
+
77
+ const resolveStartupProjectContext = (workspaceCwd: string) => {
78
+ const existingConfig = loadProjectConfig(workspaceCwd);
79
+ if (existingConfig) {
80
+ registerProject(workspaceCwd, existingConfig.displayName);
81
+ const projectStateDir = resolveProjectStateDir(workspaceCwd, existingConfig.displayName);
82
+ migrateStateToGlobal(workspaceCwd, projectStateDir);
83
+ return {
84
+ isInitialized: true,
85
+ projectDisplayName: existingConfig.displayName,
86
+ projectStateDir,
87
+ };
88
+ }
89
+
90
+ const projectDisplayName = basename(workspaceCwd) || "octogent-project";
91
+ const projectStateDir = resolveEphemeralProjectStateDir(workspaceCwd);
92
+ return {
93
+ isInitialized: false,
94
+ projectDisplayName,
95
+ projectStateDir,
96
+ };
97
+ };
98
+
99
+ const initProject = (name?: string) => {
100
+ const projectPath = process.cwd();
101
+ const { created, projectConfig, projectStateDir } = initializeProject(projectPath, name);
102
+
103
+ console.log(
104
+ `${created ? "Initialized" : "Updated"} Octogent project "${projectConfig.displayName}" at ${projectPath}`,
105
+ );
106
+ console.log(" .octogent/ directory ready (project metadata, tentacles, worktrees)");
107
+ console.log(` Global state: ${projectStateDir}`);
108
+ console.log(" .gitignore updated");
109
+ console.log("\nRun `octogent` to start the dashboard.");
110
+ };
111
+
112
+ const canListenOnPort = (port: number): Promise<boolean> =>
113
+ new Promise((resolvePort) => {
114
+ const server = createServer();
115
+ server.once("error", () => resolvePort(false));
116
+ server.once("listening", () => {
117
+ server.close(() => resolvePort(true));
118
+ });
119
+ server.listen(port, "127.0.0.1");
120
+ });
121
+
122
+ const findOpenPort = async (startPort: number): Promise<number> => {
123
+ for (let offset = 0; offset < MAX_PORT_ATTEMPTS; offset += 1) {
124
+ const port = startPort + offset;
125
+ if (port > 65535) {
126
+ break;
127
+ }
128
+
129
+ // eslint-disable-next-line no-await-in-loop
130
+ if (await canListenOnPort(port)) {
131
+ return port;
132
+ }
133
+ }
134
+
135
+ throw new Error(`Unable to find an open port starting from ${startPort}`);
136
+ };
137
+
138
+ const readPreferredStartPort = () => {
139
+ const rawPort = process.env.OCTOGENT_API_PORT ?? process.env.PORT;
140
+ if (!rawPort) {
141
+ return DEFAULT_START_PORT;
142
+ }
143
+
144
+ const parsed = Number.parseInt(rawPort, 10);
145
+ if (!Number.isFinite(parsed) || parsed < 1 || parsed > 65535) {
146
+ return DEFAULT_START_PORT;
147
+ }
148
+
149
+ return parsed;
150
+ };
151
+
152
+ const resolveRuntimeApiBase = () => {
153
+ const explicitBase =
154
+ process.env.OCTOGENT_API_ORIGIN?.trim() || process.env.OCTOGENT_API_BASE?.trim();
155
+ if (explicitBase) {
156
+ return explicitBase;
157
+ }
158
+
159
+ const projectConfig = loadProjectConfig(process.cwd());
160
+ if (projectConfig) {
161
+ const projectStateDir = resolveProjectStateDir(process.cwd(), projectConfig.displayName);
162
+ const runtimeMetadata = readRuntimeMetadata(projectStateDir);
163
+ if (runtimeMetadata) {
164
+ return runtimeMetadata.apiBaseUrl;
165
+ }
166
+ }
167
+
168
+ return `http://127.0.0.1:${readPreferredStartPort()}`;
169
+ };
170
+
171
+ const apiError = () => {
172
+ console.error(
173
+ `Error: Could not reach API at ${resolveRuntimeApiBase()}. Start Octogent in this project first.`,
174
+ );
175
+ process.exit(1);
176
+ };
177
+
178
+ const maybeOpenBrowser = (url: string) => {
179
+ if (process.env.OCTOGENT_NO_OPEN === "1" || process.env.CI === "1") {
180
+ return;
181
+ }
182
+
183
+ const command =
184
+ process.platform === "darwin"
185
+ ? { file: "open", args: [url] }
186
+ : process.platform === "win32"
187
+ ? { file: "cmd", args: ["/c", "start", "", url] }
188
+ : { file: "xdg-open", args: [url] };
189
+
190
+ try {
191
+ const child = spawn(command.file, command.args, {
192
+ stdio: "ignore",
193
+ detached: true,
194
+ });
195
+ child.unref();
196
+ } catch {
197
+ // Best-effort browser open.
198
+ }
199
+ };
200
+
201
+ const startServer = async () => {
202
+ const startupPrerequisiteReport = collectStartupPrerequisiteReport();
203
+ const startupPrerequisiteLines = formatStartupPrerequisiteReport(startupPrerequisiteReport);
204
+ if (startupPrerequisiteLines.length > 0) {
205
+ for (const line of startupPrerequisiteLines) {
206
+ if (startupPrerequisiteReport.errors.length > 0) {
207
+ console.error(line);
208
+ } else {
209
+ console.warn(line);
210
+ }
211
+ }
212
+ if (startupPrerequisiteReport.errors.length > 0) {
213
+ process.exit(1);
214
+ }
215
+ console.warn("");
216
+ }
217
+
218
+ const workspaceCwd = process.cwd();
219
+ const { isInitialized, projectDisplayName, projectStateDir } =
220
+ resolveStartupProjectContext(workspaceCwd);
221
+ const promptsDir = resolveRuntimeAssetPath(["dist", "prompts"], ["prompts"]);
222
+ const webDistDir = resolveRuntimeAssetPath(["dist", "web"], ["apps", "web", "dist"]);
223
+ const port = await findOpenPort(readPreferredStartPort());
224
+ const { createApiServer } = await import("./createApiServer");
225
+
226
+ const apiServer = createApiServer({
227
+ workspaceCwd,
228
+ projectStateDir,
229
+ promptsDir,
230
+ webDistDir: existsSync(webDistDir) ? webDistDir : undefined,
231
+ allowRemoteAccess: process.env.OCTOGENT_ALLOW_REMOTE_ACCESS === "1",
232
+ });
233
+
234
+ const shutdown = async () => {
235
+ clearRuntimeMetadata(projectStateDir);
236
+ await apiServer.stop();
237
+ process.exit(0);
238
+ };
239
+
240
+ process.on("SIGINT", () => void shutdown());
241
+ process.on("SIGTERM", () => void shutdown());
242
+
243
+ const { host, port: activePort } = await apiServer.start(port, "127.0.0.1");
244
+ const apiBaseUrl = `http://${host}:${activePort}`;
245
+ writeRuntimeMetadata(projectStateDir, {
246
+ apiBaseUrl,
247
+ host,
248
+ port: activePort,
249
+ pid: process.pid,
250
+ startedAt: new Date().toISOString(),
251
+ workspaceCwd,
252
+ });
253
+
254
+ const hasWebDist = existsSync(webDistDir);
255
+ if (hasWebDist) {
256
+ maybeOpenBrowser(apiBaseUrl);
257
+ }
258
+
259
+ console.log();
260
+ console.log(" Octogent is running");
261
+ console.log(` Project: ${workspaceCwd}`);
262
+ console.log(` Name: ${projectDisplayName}`);
263
+ console.log(` API: ${apiBaseUrl}`);
264
+ if (hasWebDist) {
265
+ console.log(` UI: ${apiBaseUrl}`);
266
+ } else {
267
+ console.log(" UI: bundled web assets are missing from this install");
268
+ }
269
+ if (!isInitialized) {
270
+ console.log(" Setup: workspace is not initialized yet; use the in-app setup flow");
271
+ }
272
+ console.log();
273
+ };
274
+
275
+ const COLORS = [
276
+ "#ff6b2b",
277
+ "#ff2d6b",
278
+ "#00ffaa",
279
+ "#bf5fff",
280
+ "#00c8ff",
281
+ "#ffee00",
282
+ "#39ff14",
283
+ "#ff4df0",
284
+ "#00fff7",
285
+ "#ff9500",
286
+ ];
287
+ const ANIMATIONS = ["sway", "walk", "jog", "bounce", "float", "swim-up"];
288
+ const EXPRESSIONS = ["normal", "happy", "angry", "surprised"];
289
+ const ACCESSORIES = ["none", "none", "long", "mohawk", "side-sweep", "curly"];
290
+ const HAIR_COLORS = [
291
+ "#4a2c0a",
292
+ "#1a1a1a",
293
+ "#c8a04a",
294
+ "#e04020",
295
+ "#f5f5f5",
296
+ "#6b3fa0",
297
+ "#2a6e3f",
298
+ "#1e90ff",
299
+ ];
300
+
301
+ const pick = <T>(items: T[]): T => items[Math.floor(Math.random() * items.length)] as T;
302
+
303
+ const randomAppearance = () => ({
304
+ color: pick(COLORS),
305
+ octopus: {
306
+ animation: pick(ANIMATIONS),
307
+ expression: pick(EXPRESSIONS),
308
+ accessory: pick(ACCESSORIES),
309
+ hairColor: pick(HAIR_COLORS),
310
+ },
311
+ });
312
+
313
+ const parseFlag = (flag: string): string | undefined => {
314
+ const index = args.indexOf(flag);
315
+ if (index === -1 || index + 1 >= args.length) {
316
+ return undefined;
317
+ }
318
+ return args[index + 1];
319
+ };
320
+
321
+ const parseJsonFlag = (flag: string): Record<string, string> | undefined => {
322
+ const raw = parseFlag(flag);
323
+ if (!raw) {
324
+ return undefined;
325
+ }
326
+
327
+ try {
328
+ const parsed = JSON.parse(raw) as unknown;
329
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
330
+ console.error(`Error: ${flag} must be a JSON object.`);
331
+ process.exit(1);
332
+ }
333
+
334
+ const entries = Object.entries(parsed).filter(([, value]) => typeof value === "string");
335
+ return Object.fromEntries(entries);
336
+ } catch {
337
+ console.error(`Error: ${flag} must be valid JSON.`);
338
+ process.exit(1);
339
+ }
340
+ };
341
+
342
+ const tentacleCreate = async () => {
343
+ const name = args[2];
344
+ if (!name || name.startsWith("-")) {
345
+ console.error("Error: tentacle name is required.");
346
+ process.exit(1);
347
+ }
348
+
349
+ const description = parseFlag("--description") ?? parseFlag("-d") ?? "";
350
+ const { color, octopus } = randomAppearance();
351
+ const apiBase = resolveRuntimeApiBase();
352
+
353
+ try {
354
+ const response = await fetch(`${apiBase}/api/deck/tentacles`, {
355
+ method: "POST",
356
+ headers: { "Content-Type": "application/json" },
357
+ body: JSON.stringify({ name, description, color, octopus }),
358
+ });
359
+ const data = (await response.json()) as Record<string, unknown>;
360
+ if (!response.ok) {
361
+ console.error(`Error: ${data.error ?? "Failed"}`);
362
+ process.exit(1);
363
+ }
364
+ console.log(`Created tentacle "${data.tentacleId}"`);
365
+ } catch {
366
+ apiError();
367
+ }
368
+ };
369
+
370
+ const tentacleList = async () => {
371
+ const apiBase = resolveRuntimeApiBase();
372
+
373
+ try {
374
+ const response = await fetch(`${apiBase}/api/deck/tentacles`);
375
+ if (!response.ok) {
376
+ console.error("Error: failed to fetch tentacles.");
377
+ process.exit(1);
378
+ }
379
+
380
+ const tentacles = (await response.json()) as Array<Record<string, unknown>>;
381
+ if (tentacles.length === 0) {
382
+ console.log("No tentacles found.");
383
+ return;
384
+ }
385
+
386
+ for (const tentacle of tentacles) {
387
+ const description = tentacle.description ? ` — ${tentacle.description}` : "";
388
+ console.log(` ${tentacle.tentacleId}${description}`);
389
+ }
390
+ } catch {
391
+ apiError();
392
+ }
393
+ };
394
+
395
+ const terminalCreate = async () => {
396
+ const name = parseFlag("--name") ?? parseFlag("-n");
397
+ const initialPrompt = parseFlag("--initial-prompt") ?? parseFlag("-p");
398
+ const workspaceMode = parseFlag("--workspace-mode") ?? parseFlag("-w") ?? "shared";
399
+ const terminalId = parseFlag("--terminal-id");
400
+ const tentacleId = parseFlag("--tentacle-id");
401
+ const worktreeId = parseFlag("--worktree-id");
402
+ const parentTerminalId = parseFlag("--parent-terminal-id");
403
+ const nameOrigin = parseFlag("--name-origin");
404
+ const autoRenamePromptContext = parseFlag("--auto-rename-prompt-context");
405
+ const promptTemplate = parseFlag("--prompt-template");
406
+ const promptVariables = parseJsonFlag("--prompt-variables");
407
+ const apiBase = resolveRuntimeApiBase();
408
+
409
+ const body: Record<string, unknown> = {};
410
+ if (name) body.name = name;
411
+ if (initialPrompt) body.initialPrompt = initialPrompt;
412
+ if (workspaceMode) body.workspaceMode = workspaceMode;
413
+ if (terminalId) body.terminalId = terminalId;
414
+ if (tentacleId) body.tentacleId = tentacleId;
415
+ if (worktreeId) body.worktreeId = worktreeId;
416
+ if (parentTerminalId) body.parentTerminalId = parentTerminalId;
417
+ if (nameOrigin) body.nameOrigin = nameOrigin;
418
+ if (autoRenamePromptContext) body.autoRenamePromptContext = autoRenamePromptContext;
419
+ if (promptTemplate) body.promptTemplate = promptTemplate;
420
+ if (promptVariables) body.promptVariables = promptVariables;
421
+
422
+ try {
423
+ const response = await fetch(`${apiBase}/api/terminals`, {
424
+ method: "POST",
425
+ headers: { "Content-Type": "application/json" },
426
+ body: JSON.stringify(body),
427
+ });
428
+ const data = (await response.json()) as Record<string, unknown>;
429
+ if (!response.ok) {
430
+ console.error(`Error: ${data.error ?? "Failed"}`);
431
+ process.exit(1);
432
+ }
433
+ console.log(`Created terminal "${data.terminalId}"`);
434
+ } catch {
435
+ apiError();
436
+ }
437
+ };
438
+
439
+ const channelSend = async () => {
440
+ const terminalId = args[2];
441
+ if (!terminalId || terminalId.startsWith("-")) {
442
+ console.error("Error: target terminalId is required.");
443
+ process.exit(1);
444
+ }
445
+
446
+ const fromTerminalId = parseFlag("--from") ?? process.env.OCTOGENT_SESSION_ID ?? "";
447
+ const fromIndex = args.indexOf("--from");
448
+ const message =
449
+ fromIndex !== -1
450
+ ? args
451
+ .slice(3)
452
+ .filter((_, index) => {
453
+ const absoluteIndex = index + 3;
454
+ return absoluteIndex !== fromIndex && absoluteIndex !== fromIndex + 1;
455
+ })
456
+ .join(" ")
457
+ .trim()
458
+ : args
459
+ .slice(3)
460
+ .filter((value) => !value.startsWith("--from"))
461
+ .join(" ")
462
+ .trim();
463
+
464
+ if (!message) {
465
+ console.error("Error: message content is required.");
466
+ process.exit(1);
467
+ }
468
+
469
+ const apiBase = resolveRuntimeApiBase();
470
+ try {
471
+ const response = await fetch(
472
+ `${apiBase}/api/channels/${encodeURIComponent(terminalId)}/messages`,
473
+ {
474
+ method: "POST",
475
+ headers: { "Content-Type": "application/json" },
476
+ body: JSON.stringify({ fromTerminalId, content: message }),
477
+ },
478
+ );
479
+ const data = (await response.json()) as Record<string, unknown>;
480
+ if (!response.ok) {
481
+ console.error(`Error: ${data.error ?? "Failed"}`);
482
+ process.exit(1);
483
+ }
484
+ console.log(`Message sent (${data.messageId}) to ${terminalId}`);
485
+ } catch {
486
+ apiError();
487
+ }
488
+ };
489
+
490
+ const channelList = async () => {
491
+ const terminalId = args[2];
492
+ if (!terminalId || terminalId.startsWith("-")) {
493
+ console.error("Error: terminalId is required.");
494
+ process.exit(1);
495
+ }
496
+
497
+ const apiBase = resolveRuntimeApiBase();
498
+ try {
499
+ const response = await fetch(
500
+ `${apiBase}/api/channels/${encodeURIComponent(terminalId)}/messages`,
501
+ );
502
+ const data = (await response.json()) as Record<string, unknown>;
503
+ if (!response.ok) {
504
+ console.error(`Error: ${data.error ?? "Failed"}`);
505
+ process.exit(1);
506
+ }
507
+
508
+ const messages = (data.messages ?? []) as Array<Record<string, unknown>>;
509
+ if (messages.length === 0) {
510
+ console.log(`No messages for ${terminalId}.`);
511
+ return;
512
+ }
513
+
514
+ for (const message of messages) {
515
+ const status = message.delivered ? "delivered" : "pending";
516
+ console.log(
517
+ ` [${message.messageId}] from=${message.fromTerminalId || "(unknown)"} status=${status}: ${message.content}`,
518
+ );
519
+ }
520
+ } catch {
521
+ apiError();
522
+ }
523
+ };
524
+
525
+ const main = async () => {
526
+ if (!command || command === "start") {
527
+ return startServer();
528
+ }
529
+
530
+ if (command === "init") {
531
+ return initProject(args[1]);
532
+ }
533
+
534
+ if (command === "projects" || command === "project") {
535
+ const projects = loadProjectsRegistry().projects;
536
+ if (projects.length === 0) {
537
+ console.log(
538
+ "No projects registered yet. Run `octogent` or `octogent init` in a project directory.",
539
+ );
540
+ return;
541
+ }
542
+
543
+ for (const project of projects) {
544
+ console.log(` ${project.name} ${project.id} ${project.path}`);
545
+ }
546
+ return;
547
+ }
548
+
549
+ if (command === "tentacle" || command === "tentacles") {
550
+ if (args[1] === "create") {
551
+ return tentacleCreate();
552
+ }
553
+ if (args[1] === "list" || args[1] === "ls") {
554
+ return tentacleList();
555
+ }
556
+ }
557
+
558
+ if (command === "terminal" || command === "terminals") {
559
+ if (args[1] === "create") {
560
+ return terminalCreate();
561
+ }
562
+ }
563
+
564
+ if (command === "channel") {
565
+ if (args[1] === "send") {
566
+ return channelSend();
567
+ }
568
+ if (args[1] === "list" || args[1] === "ls") {
569
+ return channelList();
570
+ }
571
+ }
572
+
573
+ console.log(`Usage:
574
+ octogent Start the dashboard in the current project
575
+ octogent init [project-name] Initialize the current directory explicitly
576
+ octogent projects List registered projects
577
+
578
+ octogent tentacle create <name> Create a tentacle (Octogent must be running)
579
+ octogent tentacle list List tentacles
580
+ octogent terminal create [options] Create a terminal
581
+ --name, -n Terminal display name
582
+ --workspace-mode, -w shared | worktree
583
+ --initial-prompt, -p Raw initial prompt text
584
+ --terminal-id Explicit terminal ID
585
+ --tentacle-id Existing tentacle ID to attach to
586
+ --worktree-id Explicit worktree ID
587
+ --parent-terminal-id Parent terminal ID for child terminals
588
+ --prompt-template Prompt template name
589
+ --prompt-variables JSON object of prompt template variables
590
+ octogent channel send <id> <msg> Send a channel message
591
+ octogent channel list <id> List channel messages`);
592
+ process.exit(1);
593
+ };
594
+
595
+ main();
@@ -0,0 +1,46 @@
1
+ import { appendFile, mkdir, readFile } from "node:fs/promises";
2
+ import { join } from "node:path";
3
+
4
+ export type CodeIntelEvent = {
5
+ ts: string;
6
+ sessionId: string;
7
+ tool: string;
8
+ file: string;
9
+ };
10
+
11
+ export type CodeIntelStore = {
12
+ append: (event: CodeIntelEvent) => Promise<void>;
13
+ readAll: () => Promise<CodeIntelEvent[]>;
14
+ };
15
+
16
+ export const createCodeIntelStore = (projectStateDir: string): CodeIntelStore => {
17
+ const filePath = join(projectStateDir, "state", "code-intel-events.jsonl");
18
+
19
+ return {
20
+ async append(event) {
21
+ const dir = join(projectStateDir, "state");
22
+ await mkdir(dir, { recursive: true });
23
+ await appendFile(filePath, `${JSON.stringify(event)}\n`, "utf-8");
24
+ },
25
+
26
+ async readAll() {
27
+ let raw: string;
28
+ try {
29
+ raw = await readFile(filePath, "utf-8");
30
+ } catch {
31
+ return [];
32
+ }
33
+
34
+ const events: CodeIntelEvent[] = [];
35
+ for (const line of raw.split("\n")) {
36
+ if (line.trim().length === 0) continue;
37
+ try {
38
+ events.push(JSON.parse(line) as CodeIntelEvent);
39
+ } catch {
40
+ // skip malformed lines
41
+ }
42
+ }
43
+ return events;
44
+ },
45
+ };
46
+ };