@aion0/forge 0.5.26 → 0.5.28

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 (255) hide show
  1. package/.forge/worktrees/pipeline-4dd8dc2d/CLAUDE.md +86 -0
  2. package/.forge/worktrees/pipeline-4dd8dc2d/README.md +136 -0
  3. package/.forge/worktrees/pipeline-4dd8dc2d/RELEASE_NOTES.md +36 -0
  4. package/.forge/worktrees/pipeline-4dd8dc2d/app/api/agents/route.ts +17 -0
  5. package/.forge/worktrees/pipeline-4dd8dc2d/app/api/auth/[...nextauth]/route.ts +3 -0
  6. package/.forge/worktrees/pipeline-4dd8dc2d/app/api/auth/verify/route.ts +46 -0
  7. package/.forge/worktrees/pipeline-4dd8dc2d/app/api/claude/[id]/route.ts +31 -0
  8. package/.forge/worktrees/pipeline-4dd8dc2d/app/api/claude/[id]/stream/route.ts +63 -0
  9. package/.forge/worktrees/pipeline-4dd8dc2d/app/api/claude/route.ts +28 -0
  10. package/.forge/worktrees/pipeline-4dd8dc2d/app/api/claude-sessions/[projectName]/entries/route.ts +23 -0
  11. package/.forge/worktrees/pipeline-4dd8dc2d/app/api/claude-sessions/[projectName]/live/route.ts +72 -0
  12. package/.forge/worktrees/pipeline-4dd8dc2d/app/api/claude-sessions/[projectName]/route.ts +37 -0
  13. package/.forge/worktrees/pipeline-4dd8dc2d/app/api/claude-sessions/sync/route.ts +17 -0
  14. package/.forge/worktrees/pipeline-4dd8dc2d/app/api/claude-templates/route.ts +145 -0
  15. package/.forge/worktrees/pipeline-4dd8dc2d/app/api/code/route.ts +299 -0
  16. package/.forge/worktrees/pipeline-4dd8dc2d/app/api/delivery/[id]/route.ts +62 -0
  17. package/.forge/worktrees/pipeline-4dd8dc2d/app/api/delivery/route.ts +40 -0
  18. package/.forge/worktrees/pipeline-4dd8dc2d/app/api/detect-cli/route.ts +46 -0
  19. package/.forge/worktrees/pipeline-4dd8dc2d/app/api/docs/route.ts +176 -0
  20. package/.forge/worktrees/pipeline-4dd8dc2d/app/api/docs/sessions/route.ts +54 -0
  21. package/.forge/worktrees/pipeline-4dd8dc2d/app/api/favorites/route.ts +26 -0
  22. package/.forge/worktrees/pipeline-4dd8dc2d/app/api/flows/route.ts +6 -0
  23. package/.forge/worktrees/pipeline-4dd8dc2d/app/api/flows/run/route.ts +19 -0
  24. package/.forge/worktrees/pipeline-4dd8dc2d/app/api/git/route.ts +149 -0
  25. package/.forge/worktrees/pipeline-4dd8dc2d/app/api/help/route.ts +84 -0
  26. package/.forge/worktrees/pipeline-4dd8dc2d/app/api/issue-scanner/route.ts +116 -0
  27. package/.forge/worktrees/pipeline-4dd8dc2d/app/api/logs/route.ts +100 -0
  28. package/.forge/worktrees/pipeline-4dd8dc2d/app/api/mobile-chat/route.ts +115 -0
  29. package/.forge/worktrees/pipeline-4dd8dc2d/app/api/monitor/route.ts +74 -0
  30. package/.forge/worktrees/pipeline-4dd8dc2d/app/api/notifications/route.ts +42 -0
  31. package/.forge/worktrees/pipeline-4dd8dc2d/app/api/notify/test/route.ts +33 -0
  32. package/.forge/worktrees/pipeline-4dd8dc2d/app/api/online/route.ts +40 -0
  33. package/.forge/worktrees/pipeline-4dd8dc2d/app/api/pipelines/[id]/route.ts +41 -0
  34. package/.forge/worktrees/pipeline-4dd8dc2d/app/api/pipelines/route.ts +90 -0
  35. package/.forge/worktrees/pipeline-4dd8dc2d/app/api/plugins/route.ts +75 -0
  36. package/.forge/worktrees/pipeline-4dd8dc2d/app/api/preview/[...path]/route.ts +64 -0
  37. package/.forge/worktrees/pipeline-4dd8dc2d/app/api/preview/route.ts +156 -0
  38. package/.forge/worktrees/pipeline-4dd8dc2d/app/api/project-pipelines/route.ts +91 -0
  39. package/.forge/worktrees/pipeline-4dd8dc2d/app/api/project-sessions/route.ts +61 -0
  40. package/.forge/worktrees/pipeline-4dd8dc2d/app/api/projects/route.ts +26 -0
  41. package/.forge/worktrees/pipeline-4dd8dc2d/app/api/sessions/[id]/chat/route.ts +64 -0
  42. package/.forge/worktrees/pipeline-4dd8dc2d/app/api/sessions/[id]/messages/route.ts +9 -0
  43. package/.forge/worktrees/pipeline-4dd8dc2d/app/api/sessions/[id]/route.ts +17 -0
  44. package/.forge/worktrees/pipeline-4dd8dc2d/app/api/sessions/route.ts +20 -0
  45. package/.forge/worktrees/pipeline-4dd8dc2d/app/api/settings/route.ts +64 -0
  46. package/.forge/worktrees/pipeline-4dd8dc2d/app/api/skills/local/route.ts +228 -0
  47. package/.forge/worktrees/pipeline-4dd8dc2d/app/api/skills/route.ts +182 -0
  48. package/.forge/worktrees/pipeline-4dd8dc2d/app/api/smith-templates/route.ts +81 -0
  49. package/.forge/worktrees/pipeline-4dd8dc2d/app/api/status/route.ts +12 -0
  50. package/.forge/worktrees/pipeline-4dd8dc2d/app/api/tabs/route.ts +25 -0
  51. package/.forge/worktrees/pipeline-4dd8dc2d/app/api/tasks/[id]/route.ts +51 -0
  52. package/.forge/worktrees/pipeline-4dd8dc2d/app/api/tasks/[id]/stream/route.ts +77 -0
  53. package/.forge/worktrees/pipeline-4dd8dc2d/app/api/tasks/link/route.ts +37 -0
  54. package/.forge/worktrees/pipeline-4dd8dc2d/app/api/tasks/route.ts +44 -0
  55. package/.forge/worktrees/pipeline-4dd8dc2d/app/api/tasks/session/route.ts +14 -0
  56. package/.forge/worktrees/pipeline-4dd8dc2d/app/api/telegram/route.ts +23 -0
  57. package/.forge/worktrees/pipeline-4dd8dc2d/app/api/templates/route.ts +6 -0
  58. package/.forge/worktrees/pipeline-4dd8dc2d/app/api/terminal-bell/route.ts +39 -0
  59. package/.forge/worktrees/pipeline-4dd8dc2d/app/api/terminal-cwd/route.ts +19 -0
  60. package/.forge/worktrees/pipeline-4dd8dc2d/app/api/terminal-state/route.ts +15 -0
  61. package/.forge/worktrees/pipeline-4dd8dc2d/app/api/tunnel/route.ts +26 -0
  62. package/.forge/worktrees/pipeline-4dd8dc2d/app/api/upgrade/route.ts +43 -0
  63. package/.forge/worktrees/pipeline-4dd8dc2d/app/api/usage/route.ts +20 -0
  64. package/.forge/worktrees/pipeline-4dd8dc2d/app/api/version/route.ts +78 -0
  65. package/.forge/worktrees/pipeline-4dd8dc2d/app/api/watchers/route.ts +33 -0
  66. package/.forge/worktrees/pipeline-4dd8dc2d/app/api/workspace/[id]/agents/route.ts +35 -0
  67. package/.forge/worktrees/pipeline-4dd8dc2d/app/api/workspace/[id]/memory/route.ts +23 -0
  68. package/.forge/worktrees/pipeline-4dd8dc2d/app/api/workspace/[id]/smith/route.ts +22 -0
  69. package/.forge/worktrees/pipeline-4dd8dc2d/app/api/workspace/[id]/stream/route.ts +31 -0
  70. package/.forge/worktrees/pipeline-4dd8dc2d/app/api/workspace/route.ts +79 -0
  71. package/.forge/worktrees/pipeline-4dd8dc2d/app/global-error.tsx +21 -0
  72. package/.forge/worktrees/pipeline-4dd8dc2d/app/globals.css +52 -0
  73. package/.forge/worktrees/pipeline-4dd8dc2d/app/icon.ico +0 -0
  74. package/.forge/worktrees/pipeline-4dd8dc2d/app/icon.png +0 -0
  75. package/.forge/worktrees/pipeline-4dd8dc2d/app/icon.svg +106 -0
  76. package/.forge/worktrees/pipeline-4dd8dc2d/app/layout.tsx +17 -0
  77. package/.forge/worktrees/pipeline-4dd8dc2d/app/login/LoginForm.tsx +96 -0
  78. package/.forge/worktrees/pipeline-4dd8dc2d/app/login/page.tsx +10 -0
  79. package/.forge/worktrees/pipeline-4dd8dc2d/app/mobile/page.tsx +10 -0
  80. package/.forge/worktrees/pipeline-4dd8dc2d/app/page.tsx +22 -0
  81. package/.forge/worktrees/pipeline-4dd8dc2d/bin/forge-server.mjs +484 -0
  82. package/.forge/worktrees/pipeline-4dd8dc2d/check-forge-status.sh +71 -0
  83. package/.forge/worktrees/pipeline-4dd8dc2d/cli/mw.ts +579 -0
  84. package/.forge/worktrees/pipeline-4dd8dc2d/components/BrowserPanel.tsx +175 -0
  85. package/.forge/worktrees/pipeline-4dd8dc2d/components/ChatPanel.tsx +191 -0
  86. package/.forge/worktrees/pipeline-4dd8dc2d/components/ClaudeTerminal.tsx +267 -0
  87. package/.forge/worktrees/pipeline-4dd8dc2d/components/CodeViewer.tsx +787 -0
  88. package/.forge/worktrees/pipeline-4dd8dc2d/components/ConversationEditor.tsx +411 -0
  89. package/.forge/worktrees/pipeline-4dd8dc2d/components/ConversationGraphView.tsx +347 -0
  90. package/.forge/worktrees/pipeline-4dd8dc2d/components/ConversationTerminalView.tsx +303 -0
  91. package/.forge/worktrees/pipeline-4dd8dc2d/components/Dashboard.tsx +807 -0
  92. package/.forge/worktrees/pipeline-4dd8dc2d/components/DashboardWrapper.tsx +9 -0
  93. package/.forge/worktrees/pipeline-4dd8dc2d/components/DeliveryFlowEditor.tsx +491 -0
  94. package/.forge/worktrees/pipeline-4dd8dc2d/components/DeliveryList.tsx +230 -0
  95. package/.forge/worktrees/pipeline-4dd8dc2d/components/DeliveryWorkspace.tsx +589 -0
  96. package/.forge/worktrees/pipeline-4dd8dc2d/components/DocTerminal.tsx +187 -0
  97. package/.forge/worktrees/pipeline-4dd8dc2d/components/DocsViewer.tsx +574 -0
  98. package/.forge/worktrees/pipeline-4dd8dc2d/components/HelpDialog.tsx +169 -0
  99. package/.forge/worktrees/pipeline-4dd8dc2d/components/HelpTerminal.tsx +141 -0
  100. package/.forge/worktrees/pipeline-4dd8dc2d/components/InlinePipelineView.tsx +111 -0
  101. package/.forge/worktrees/pipeline-4dd8dc2d/components/LogViewer.tsx +194 -0
  102. package/.forge/worktrees/pipeline-4dd8dc2d/components/MarkdownContent.tsx +73 -0
  103. package/.forge/worktrees/pipeline-4dd8dc2d/components/MobileView.tsx +385 -0
  104. package/.forge/worktrees/pipeline-4dd8dc2d/components/MonitorPanel.tsx +122 -0
  105. package/.forge/worktrees/pipeline-4dd8dc2d/components/NewSessionModal.tsx +93 -0
  106. package/.forge/worktrees/pipeline-4dd8dc2d/components/NewTaskModal.tsx +492 -0
  107. package/.forge/worktrees/pipeline-4dd8dc2d/components/PipelineEditor.tsx +570 -0
  108. package/.forge/worktrees/pipeline-4dd8dc2d/components/PipelineView.tsx +1018 -0
  109. package/.forge/worktrees/pipeline-4dd8dc2d/components/PluginsPanel.tsx +472 -0
  110. package/.forge/worktrees/pipeline-4dd8dc2d/components/ProjectDetail.tsx +1618 -0
  111. package/.forge/worktrees/pipeline-4dd8dc2d/components/ProjectList.tsx +108 -0
  112. package/.forge/worktrees/pipeline-4dd8dc2d/components/ProjectManager.tsx +401 -0
  113. package/.forge/worktrees/pipeline-4dd8dc2d/components/SessionList.tsx +74 -0
  114. package/.forge/worktrees/pipeline-4dd8dc2d/components/SessionView.tsx +726 -0
  115. package/.forge/worktrees/pipeline-4dd8dc2d/components/SettingsModal.tsx +1647 -0
  116. package/.forge/worktrees/pipeline-4dd8dc2d/components/SkillsPanel.tsx +969 -0
  117. package/.forge/worktrees/pipeline-4dd8dc2d/components/StatusBar.tsx +99 -0
  118. package/.forge/worktrees/pipeline-4dd8dc2d/components/TabBar.tsx +46 -0
  119. package/.forge/worktrees/pipeline-4dd8dc2d/components/TaskBoard.tsx +113 -0
  120. package/.forge/worktrees/pipeline-4dd8dc2d/components/TaskDetail.tsx +372 -0
  121. package/.forge/worktrees/pipeline-4dd8dc2d/components/TerminalLauncher.tsx +398 -0
  122. package/.forge/worktrees/pipeline-4dd8dc2d/components/TunnelToggle.tsx +206 -0
  123. package/.forge/worktrees/pipeline-4dd8dc2d/components/UsagePanel.tsx +207 -0
  124. package/.forge/worktrees/pipeline-4dd8dc2d/components/WebTerminal.tsx +1743 -0
  125. package/.forge/worktrees/pipeline-4dd8dc2d/components/WorkspaceTree.tsx +221 -0
  126. package/.forge/worktrees/pipeline-4dd8dc2d/components/WorkspaceView.tsx +4048 -0
  127. package/.forge/worktrees/pipeline-4dd8dc2d/dev-test.sh +5 -0
  128. package/.forge/worktrees/pipeline-4dd8dc2d/docs/Forge_Memory_Layer_Design.docx +0 -0
  129. package/.forge/worktrees/pipeline-4dd8dc2d/docs/Forge_Strategy_Research_2026.docx +0 -0
  130. package/.forge/worktrees/pipeline-4dd8dc2d/docs/LOCAL-DEPLOY.md +144 -0
  131. package/.forge/worktrees/pipeline-4dd8dc2d/docs/roadmap-multi-agent-workflow.md +330 -0
  132. package/.forge/worktrees/pipeline-4dd8dc2d/forge-logo.png +0 -0
  133. package/.forge/worktrees/pipeline-4dd8dc2d/forge-logo.svg +106 -0
  134. package/.forge/worktrees/pipeline-4dd8dc2d/hooks/useSidebarResize.ts +52 -0
  135. package/.forge/worktrees/pipeline-4dd8dc2d/install.sh +29 -0
  136. package/.forge/worktrees/pipeline-4dd8dc2d/instrumentation.ts +35 -0
  137. package/.forge/worktrees/pipeline-4dd8dc2d/lib/agents/claude-adapter.ts +104 -0
  138. package/.forge/worktrees/pipeline-4dd8dc2d/lib/agents/generic-adapter.ts +64 -0
  139. package/.forge/worktrees/pipeline-4dd8dc2d/lib/agents/index.ts +245 -0
  140. package/.forge/worktrees/pipeline-4dd8dc2d/lib/agents/types.ts +70 -0
  141. package/.forge/worktrees/pipeline-4dd8dc2d/lib/artifacts.ts +106 -0
  142. package/.forge/worktrees/pipeline-4dd8dc2d/lib/auth.ts +62 -0
  143. package/.forge/worktrees/pipeline-4dd8dc2d/lib/builtin-plugins/docker.yaml +70 -0
  144. package/.forge/worktrees/pipeline-4dd8dc2d/lib/builtin-plugins/http.yaml +66 -0
  145. package/.forge/worktrees/pipeline-4dd8dc2d/lib/builtin-plugins/jenkins.yaml +92 -0
  146. package/.forge/worktrees/pipeline-4dd8dc2d/lib/builtin-plugins/llm-vision.yaml +85 -0
  147. package/.forge/worktrees/pipeline-4dd8dc2d/lib/builtin-plugins/playwright.yaml +111 -0
  148. package/.forge/worktrees/pipeline-4dd8dc2d/lib/builtin-plugins/shell-command.yaml +60 -0
  149. package/.forge/worktrees/pipeline-4dd8dc2d/lib/builtin-plugins/slack.yaml +48 -0
  150. package/.forge/worktrees/pipeline-4dd8dc2d/lib/builtin-plugins/webhook.yaml +56 -0
  151. package/.forge/worktrees/pipeline-4dd8dc2d/lib/claude-process.ts +361 -0
  152. package/.forge/worktrees/pipeline-4dd8dc2d/lib/claude-sessions.ts +266 -0
  153. package/.forge/worktrees/pipeline-4dd8dc2d/lib/claude-templates.ts +227 -0
  154. package/.forge/worktrees/pipeline-4dd8dc2d/lib/cloudflared.ts +424 -0
  155. package/.forge/worktrees/pipeline-4dd8dc2d/lib/crypto.ts +67 -0
  156. package/.forge/worktrees/pipeline-4dd8dc2d/lib/delivery.ts +787 -0
  157. package/.forge/worktrees/pipeline-4dd8dc2d/lib/dirs.ts +99 -0
  158. package/.forge/worktrees/pipeline-4dd8dc2d/lib/flows.ts +86 -0
  159. package/.forge/worktrees/pipeline-4dd8dc2d/lib/forge-mcp-server.ts +732 -0
  160. package/.forge/worktrees/pipeline-4dd8dc2d/lib/forge-skills/forge-inbox.md +38 -0
  161. package/.forge/worktrees/pipeline-4dd8dc2d/lib/forge-skills/forge-send.md +47 -0
  162. package/.forge/worktrees/pipeline-4dd8dc2d/lib/forge-skills/forge-status.md +32 -0
  163. package/.forge/worktrees/pipeline-4dd8dc2d/lib/forge-skills/forge-workspace-sync.md +37 -0
  164. package/.forge/worktrees/pipeline-4dd8dc2d/lib/help-docs/00-overview.md +40 -0
  165. package/.forge/worktrees/pipeline-4dd8dc2d/lib/help-docs/01-settings.md +194 -0
  166. package/.forge/worktrees/pipeline-4dd8dc2d/lib/help-docs/02-telegram.md +41 -0
  167. package/.forge/worktrees/pipeline-4dd8dc2d/lib/help-docs/03-tunnel.md +31 -0
  168. package/.forge/worktrees/pipeline-4dd8dc2d/lib/help-docs/04-tasks.md +52 -0
  169. package/.forge/worktrees/pipeline-4dd8dc2d/lib/help-docs/05-pipelines.md +460 -0
  170. package/.forge/worktrees/pipeline-4dd8dc2d/lib/help-docs/06-skills.md +43 -0
  171. package/.forge/worktrees/pipeline-4dd8dc2d/lib/help-docs/07-projects.md +73 -0
  172. package/.forge/worktrees/pipeline-4dd8dc2d/lib/help-docs/08-rules.md +53 -0
  173. package/.forge/worktrees/pipeline-4dd8dc2d/lib/help-docs/09-issue-autofix.md +55 -0
  174. package/.forge/worktrees/pipeline-4dd8dc2d/lib/help-docs/10-troubleshooting.md +89 -0
  175. package/.forge/worktrees/pipeline-4dd8dc2d/lib/help-docs/11-workspace.md +810 -0
  176. package/.forge/worktrees/pipeline-4dd8dc2d/lib/help-docs/CLAUDE.md +62 -0
  177. package/.forge/worktrees/pipeline-4dd8dc2d/lib/init.ts +266 -0
  178. package/.forge/worktrees/pipeline-4dd8dc2d/lib/issue-scanner.ts +298 -0
  179. package/.forge/worktrees/pipeline-4dd8dc2d/lib/logger.ts +79 -0
  180. package/.forge/worktrees/pipeline-4dd8dc2d/lib/notifications.ts +75 -0
  181. package/.forge/worktrees/pipeline-4dd8dc2d/lib/notify.ts +108 -0
  182. package/.forge/worktrees/pipeline-4dd8dc2d/lib/password.ts +97 -0
  183. package/.forge/worktrees/pipeline-4dd8dc2d/lib/pipeline-scheduler.ts +373 -0
  184. package/.forge/worktrees/pipeline-4dd8dc2d/lib/pipeline.ts +1565 -0
  185. package/.forge/worktrees/pipeline-4dd8dc2d/lib/plugins/executor.ts +347 -0
  186. package/.forge/worktrees/pipeline-4dd8dc2d/lib/plugins/registry.ts +228 -0
  187. package/.forge/worktrees/pipeline-4dd8dc2d/lib/plugins/types.ts +103 -0
  188. package/.forge/worktrees/pipeline-4dd8dc2d/lib/project-sessions.ts +53 -0
  189. package/.forge/worktrees/pipeline-4dd8dc2d/lib/projects.ts +86 -0
  190. package/.forge/worktrees/pipeline-4dd8dc2d/lib/session-manager.ts +156 -0
  191. package/.forge/worktrees/pipeline-4dd8dc2d/lib/session-utils.ts +53 -0
  192. package/.forge/worktrees/pipeline-4dd8dc2d/lib/session-watcher.ts +345 -0
  193. package/.forge/worktrees/pipeline-4dd8dc2d/lib/settings.ts +195 -0
  194. package/.forge/worktrees/pipeline-4dd8dc2d/lib/skills.ts +458 -0
  195. package/.forge/worktrees/pipeline-4dd8dc2d/lib/task-manager.ts +951 -0
  196. package/.forge/worktrees/pipeline-4dd8dc2d/lib/telegram-bot.ts +1477 -0
  197. package/.forge/worktrees/pipeline-4dd8dc2d/lib/telegram-standalone.ts +83 -0
  198. package/.forge/worktrees/pipeline-4dd8dc2d/lib/terminal-server.ts +70 -0
  199. package/.forge/worktrees/pipeline-4dd8dc2d/lib/terminal-standalone.ts +438 -0
  200. package/.forge/worktrees/pipeline-4dd8dc2d/lib/usage-scanner.ts +249 -0
  201. package/.forge/worktrees/pipeline-4dd8dc2d/lib/workspace/__tests__/state-machine.test.ts +388 -0
  202. package/.forge/worktrees/pipeline-4dd8dc2d/lib/workspace/__tests__/workspace.test.ts +311 -0
  203. package/.forge/worktrees/pipeline-4dd8dc2d/lib/workspace/agent-bus.ts +416 -0
  204. package/.forge/worktrees/pipeline-4dd8dc2d/lib/workspace/agent-worker.ts +655 -0
  205. package/.forge/worktrees/pipeline-4dd8dc2d/lib/workspace/backends/api-backend.ts +262 -0
  206. package/.forge/worktrees/pipeline-4dd8dc2d/lib/workspace/backends/cli-backend.ts +491 -0
  207. package/.forge/worktrees/pipeline-4dd8dc2d/lib/workspace/index.ts +84 -0
  208. package/.forge/worktrees/pipeline-4dd8dc2d/lib/workspace/manager.ts +136 -0
  209. package/.forge/worktrees/pipeline-4dd8dc2d/lib/workspace/orchestrator.ts +3415 -0
  210. package/.forge/worktrees/pipeline-4dd8dc2d/lib/workspace/persistence.ts +309 -0
  211. package/.forge/worktrees/pipeline-4dd8dc2d/lib/workspace/presets.ts +649 -0
  212. package/.forge/worktrees/pipeline-4dd8dc2d/lib/workspace/requests.ts +287 -0
  213. package/.forge/worktrees/pipeline-4dd8dc2d/lib/workspace/session-monitor.ts +240 -0
  214. package/.forge/worktrees/pipeline-4dd8dc2d/lib/workspace/skill-installer.ts +275 -0
  215. package/.forge/worktrees/pipeline-4dd8dc2d/lib/workspace/smith-memory.ts +498 -0
  216. package/.forge/worktrees/pipeline-4dd8dc2d/lib/workspace/types.ts +241 -0
  217. package/.forge/worktrees/pipeline-4dd8dc2d/lib/workspace/watch-manager.ts +560 -0
  218. package/.forge/worktrees/pipeline-4dd8dc2d/lib/workspace-standalone.ts +978 -0
  219. package/.forge/worktrees/pipeline-4dd8dc2d/middleware.ts +51 -0
  220. package/.forge/worktrees/pipeline-4dd8dc2d/next.config.ts +26 -0
  221. package/.forge/worktrees/pipeline-4dd8dc2d/package.json +74 -0
  222. package/.forge/worktrees/pipeline-4dd8dc2d/pnpm-lock.yaml +3719 -0
  223. package/.forge/worktrees/pipeline-4dd8dc2d/pnpm-workspace.yaml +1 -0
  224. package/.forge/worktrees/pipeline-4dd8dc2d/postcss.config.mjs +7 -0
  225. package/.forge/worktrees/pipeline-4dd8dc2d/publish.sh +133 -0
  226. package/.forge/worktrees/pipeline-4dd8dc2d/scripts/bench/README.md +66 -0
  227. package/.forge/worktrees/pipeline-4dd8dc2d/scripts/bench/results/.gitignore +2 -0
  228. package/.forge/worktrees/pipeline-4dd8dc2d/scripts/bench/run.ts +635 -0
  229. package/.forge/worktrees/pipeline-4dd8dc2d/scripts/bench/tasks/01-text-utils/task.md +26 -0
  230. package/.forge/worktrees/pipeline-4dd8dc2d/scripts/bench/tasks/01-text-utils/validator.sh +46 -0
  231. package/.forge/worktrees/pipeline-4dd8dc2d/scripts/bench/tasks/02-pagination/setup.sh +19 -0
  232. package/.forge/worktrees/pipeline-4dd8dc2d/scripts/bench/tasks/02-pagination/task.md +48 -0
  233. package/.forge/worktrees/pipeline-4dd8dc2d/scripts/bench/tasks/02-pagination/validator.sh +69 -0
  234. package/.forge/worktrees/pipeline-4dd8dc2d/scripts/bench/tasks/03-bug-fix/setup.sh +82 -0
  235. package/.forge/worktrees/pipeline-4dd8dc2d/scripts/bench/tasks/03-bug-fix/task.md +30 -0
  236. package/.forge/worktrees/pipeline-4dd8dc2d/scripts/bench/tasks/03-bug-fix/validator.sh +29 -0
  237. package/.forge/worktrees/pipeline-4dd8dc2d/scripts/verify-usage.ts +178 -0
  238. package/.forge/worktrees/pipeline-4dd8dc2d/src/config/index.ts +129 -0
  239. package/.forge/worktrees/pipeline-4dd8dc2d/src/core/db/database.ts +259 -0
  240. package/.forge/worktrees/pipeline-4dd8dc2d/src/core/memory/strategy.ts +32 -0
  241. package/.forge/worktrees/pipeline-4dd8dc2d/src/core/providers/chat.ts +65 -0
  242. package/.forge/worktrees/pipeline-4dd8dc2d/src/core/providers/registry.ts +60 -0
  243. package/.forge/worktrees/pipeline-4dd8dc2d/src/core/session/manager.ts +190 -0
  244. package/.forge/worktrees/pipeline-4dd8dc2d/src/types/index.ts +129 -0
  245. package/.forge/worktrees/pipeline-4dd8dc2d/start.sh +32 -0
  246. package/.forge/worktrees/pipeline-4dd8dc2d/templates/smith-lead.json +45 -0
  247. package/.forge/worktrees/pipeline-4dd8dc2d/tsconfig.json +42 -0
  248. package/RELEASE_NOTES.md +10 -29
  249. package/app/api/terminal-bell/route.ts +6 -2
  250. package/app/api/terminal-cwd/route.ts +7 -4
  251. package/components/CodeViewer.tsx +3 -31
  252. package/components/Dashboard.tsx +34 -20
  253. package/components/WebTerminal.tsx +36 -2
  254. package/lib/terminal-standalone.ts +19 -2
  255. package/package.json +1 -1
@@ -0,0 +1,484 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * forge-server — Start the Forge web platform.
4
+ *
5
+ * Usage:
6
+ * forge-server Start in foreground (production)
7
+ * forge-server --dev Start in foreground (development)
8
+ * forge-server --background Start in background
9
+ * forge-server --stop Stop background server
10
+ * forge-server --restart Stop + start (safe for remote)
11
+ * forge-server --rebuild Force rebuild
12
+ * forge-server --port 4000 Custom web port (default: 8403)
13
+ * forge-server --terminal-port 4001 Custom terminal port (default: 8404)
14
+ * forge-server --dir ~/.forge-test Custom data directory (default: ~/.forge)
15
+ * forge-server --reset-terminal Kill terminal server before start (loses tmux sessions)
16
+ *
17
+ * Examples:
18
+ * forge-server --background --port 4000 --terminal-port 4001 --dir ~/.forge-staging
19
+ * forge-server --restart
20
+ */
21
+
22
+ import { execSync, spawn } from 'node:child_process';
23
+ import { existsSync, mkdirSync, readFileSync, writeFileSync, unlinkSync, openSync } from 'node:fs';
24
+ import { join, dirname } from 'node:path';
25
+ import { fileURLToPath } from 'node:url';
26
+ import { homedir } from 'node:os';
27
+
28
+ const __dirname = dirname(fileURLToPath(import.meta.url));
29
+ const ROOT = join(__dirname, '..');
30
+
31
+ /** Build Next.js — install devDependencies first if missing */
32
+ function buildNext() {
33
+ // Check if devDependencies are installed (e.g. @tailwindcss/postcss)
34
+ if (!existsSync(join(ROOT, 'node_modules', '@tailwindcss', 'postcss'))) {
35
+ console.log('[forge] Installing dependencies...');
36
+ execSync('npm install --include=dev', { cwd: ROOT, stdio: 'inherit' });
37
+ }
38
+ execSync('npx next build', { cwd: ROOT, stdio: 'inherit', env: { ...process.env } });
39
+ }
40
+
41
+ // ── Parse arguments ──
42
+
43
+ function getArg(name) {
44
+ const idx = process.argv.indexOf(name);
45
+ if (idx === -1 || idx + 1 >= process.argv.length) return null;
46
+ return process.argv[idx + 1];
47
+ }
48
+
49
+ // ── Version ──
50
+ if (process.argv.includes('--version') || process.argv.includes('-v')) {
51
+ const pkg = JSON.parse(readFileSync(join(ROOT, 'package.json'), 'utf-8'));
52
+ console.log(`@aion0/forge v${pkg.version}`);
53
+ process.exit(0);
54
+ }
55
+
56
+ const isDev = process.argv.includes('--dev');
57
+ const isForeground = process.argv.includes('--foreground');
58
+ const isBackground = !isForeground && !isDev; // default background unless --foreground or --dev
59
+ const isStop = process.argv.includes('--stop');
60
+ const isRestart = process.argv.includes('--restart');
61
+ const isRebuild = process.argv.includes('--rebuild');
62
+ const resetTerminal = process.argv.includes('--reset-terminal');
63
+ const resetPassword = process.argv.includes('--reset-password');
64
+
65
+ const webPort = parseInt(getArg('--port')) || 8403;
66
+ const terminalPort = parseInt(getArg('--terminal-port')) || (webPort + 1);
67
+ const workspacePort = parseInt(getArg('--workspace-port')) || (webPort + 2);
68
+ const DATA_DIR = getArg('--dir')?.replace(/^~/, homedir()) || join(homedir(), '.forge', 'data');
69
+
70
+ const PID_FILE = join(DATA_DIR, 'forge.pid');
71
+ const PIDS_FILE = join(DATA_DIR, 'forge.pids'); // all child process PIDs
72
+ const LOG_FILE = join(DATA_DIR, 'forge.log');
73
+
74
+ process.chdir(ROOT);
75
+
76
+ // ── Migrate old layout (~/.forge/*) to new (~/.forge/data/*) ──
77
+ if (!getArg('--dir')) {
78
+ const oldSettings = join(homedir(), '.forge', 'settings.yaml');
79
+ const newSettings = join(DATA_DIR, 'settings.yaml');
80
+ if (existsSync(oldSettings) && !existsSync(newSettings)) {
81
+ console.log('[forge] Migrating data from ~/.forge/ to ~/.forge/data/...');
82
+ mkdirSync(DATA_DIR, { recursive: true });
83
+ const migrateFiles = ['settings.yaml', '.encrypt-key', '.env.local', 'session-code.json', 'terminal-state.json', 'tunnel-state.json', 'preview.json', 'forge.pid', 'forge.log'];
84
+ for (const f of migrateFiles) {
85
+ const src = join(homedir(), '.forge', f);
86
+ const dest = join(DATA_DIR, f);
87
+ if (existsSync(src) && !existsSync(dest)) {
88
+ try { const { copyFileSync } = await import('node:fs'); copyFileSync(src, dest); console.log(` ${f}`); } catch {}
89
+ }
90
+ }
91
+ // data.db → workflow.db
92
+ const oldDb = join(homedir(), '.forge', 'data.db');
93
+ const newDb = join(DATA_DIR, 'workflow.db');
94
+ if (existsSync(oldDb) && !existsSync(newDb)) {
95
+ try { const { copyFileSync } = await import('node:fs'); copyFileSync(oldDb, newDb); console.log(' data.db → workflow.db'); } catch {}
96
+ }
97
+ // Migrate directories
98
+ for (const d of ['flows', 'pipelines']) {
99
+ const src = join(homedir(), '.forge', d);
100
+ const dest = join(DATA_DIR, d);
101
+ if (existsSync(src) && !existsSync(dest)) {
102
+ try { const { renameSync } = await import('node:fs'); renameSync(src, dest); console.log(` ${d}/`); } catch {}
103
+ }
104
+ }
105
+ console.log('[forge] Migration complete.');
106
+ }
107
+ }
108
+
109
+ mkdirSync(DATA_DIR, { recursive: true });
110
+
111
+ // ── Load <data-dir>/.env.local ──
112
+ const envFile = join(DATA_DIR, '.env.local');
113
+ if (existsSync(envFile)) {
114
+ for (const line of readFileSync(envFile, 'utf-8').split('\n')) {
115
+ const trimmed = line.trim();
116
+ if (!trimmed || trimmed.startsWith('#')) continue;
117
+ const eq = trimmed.indexOf('=');
118
+ if (eq === -1) continue;
119
+ const key = trimmed.slice(0, eq).trim();
120
+ const val = trimmed.slice(eq + 1).trim();
121
+ if (!process.env[key]) process.env[key] = val;
122
+ }
123
+ }
124
+
125
+ // Set env vars for Next.js and terminal server
126
+ process.env.PORT = String(webPort);
127
+ process.env.TERMINAL_PORT = String(terminalPort);
128
+ process.env.WORKSPACE_PORT = String(workspacePort);
129
+ process.env.FORGE_DATA_DIR = DATA_DIR;
130
+
131
+ // ── Password setup (first run or --reset-password) ──
132
+ if (!isStop) {
133
+ const YAML = await import('yaml');
134
+ const settingsFile = join(DATA_DIR, 'settings.yaml');
135
+ let settings = {};
136
+ try { settings = YAML.parse(readFileSync(settingsFile, 'utf-8')) || {}; } catch {}
137
+
138
+ const hasPassword = !!settings.telegramTunnelPassword;
139
+
140
+ if (resetPassword || !hasPassword) {
141
+ if (resetPassword) {
142
+ console.log('[forge] Password reset requested');
143
+ } else {
144
+ console.log('[forge] First run — please set an admin password');
145
+ }
146
+
147
+ const readline = await import('node:readline');
148
+ const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
149
+ const ask = (q) => new Promise((resolve, reject) => {
150
+ rl.question(q, resolve);
151
+ rl.once('close', () => reject(new Error('cancelled')));
152
+ });
153
+
154
+ let pw = '';
155
+ try {
156
+ while (true) {
157
+ pw = await ask(' Enter admin password: ');
158
+ if (!pw || pw.length < 4) {
159
+ console.log(' Password must be at least 4 characters');
160
+ continue;
161
+ }
162
+ const confirm = await ask(' Confirm password: ');
163
+ if (pw !== confirm) {
164
+ console.log(' Passwords do not match, try again');
165
+ continue;
166
+ }
167
+ break;
168
+ }
169
+ } catch {
170
+ console.log('\n[forge] Cancelled');
171
+ process.exit(0);
172
+ }
173
+ rl.close();
174
+
175
+ // Encrypt and save
176
+ const crypto = await import('node:crypto');
177
+ const KEY_FILE = join(DATA_DIR, '.encrypt-key');
178
+ let encKey;
179
+ if (existsSync(KEY_FILE)) {
180
+ encKey = Buffer.from(readFileSync(KEY_FILE, 'utf-8').trim(), 'hex');
181
+ } else {
182
+ encKey = crypto.randomBytes(32);
183
+ writeFileSync(KEY_FILE, encKey.toString('hex'), { mode: 0o600 });
184
+ }
185
+ const iv = crypto.randomBytes(12);
186
+ const cipher = crypto.createCipheriv('aes-256-gcm', encKey, iv);
187
+ const encrypted = Buffer.concat([cipher.update(pw, 'utf-8'), cipher.final()]);
188
+ const tag = cipher.getAuthTag();
189
+ settings.telegramTunnelPassword = `enc:${iv.toString('base64')}.${tag.toString('base64')}.${encrypted.toString('base64')}`;
190
+ if (!existsSync(dirname(settingsFile))) mkdirSync(dirname(settingsFile), { recursive: true });
191
+ writeFileSync(settingsFile, YAML.stringify(settings), 'utf-8');
192
+ console.log('[forge] Admin password saved');
193
+
194
+ if (resetPassword) {
195
+ process.exit(0);
196
+ }
197
+ }
198
+ }
199
+
200
+ // ── Reset terminal server (kill port + tmux sessions) ──
201
+ if (resetTerminal) {
202
+ console.log(`[forge] Resetting terminal server (port ${terminalPort})...`);
203
+ try {
204
+ const pids = execSync(`lsof -ti:${terminalPort}`, { encoding: 'utf-8' }).trim();
205
+ for (const pid of pids.split('\n').filter(Boolean)) {
206
+ try { execSync(`kill ${pid.trim()}`); } catch {}
207
+ }
208
+ console.log(`[forge] Killed terminal server on port ${terminalPort}`);
209
+ } catch {
210
+ console.log(`[forge] No process on port ${terminalPort}`);
211
+ }
212
+ }
213
+
214
+ // ── PID tracking for clean shutdown ──
215
+
216
+ function savePids(pids) {
217
+ writeFileSync(PIDS_FILE, JSON.stringify(pids), 'utf-8');
218
+ }
219
+
220
+ function loadPids() {
221
+ try { return JSON.parse(readFileSync(PIDS_FILE, 'utf-8')); } catch { return []; }
222
+ }
223
+
224
+ function killTrackedPids() {
225
+ const pids = loadPids();
226
+ for (const pid of pids) {
227
+ try { process.kill(pid, 'SIGTERM'); } catch {}
228
+ }
229
+ // Give them a moment, then force kill
230
+ if (pids.length > 0) {
231
+ setTimeout(() => {
232
+ for (const pid of pids) {
233
+ try { process.kill(pid, 'SIGKILL'); } catch {}
234
+ }
235
+ }, 2000);
236
+ }
237
+ try { unlinkSync(PIDS_FILE); } catch {}
238
+ }
239
+
240
+ // ── Kill orphan standalone processes ──
241
+ const protectedPids = new Set();
242
+
243
+ function cleanupOrphans() {
244
+ const myPid = String(process.pid);
245
+ const instanceTag = `--forge-port=${webPort}`;
246
+ try {
247
+ // Kill processes on our ports
248
+ for (const port of [webPort, terminalPort]) {
249
+ try {
250
+ const pids = execSync(`lsof -ti:${port}`, { encoding: 'utf-8', timeout: 5000, stdio: ['pipe', 'pipe', 'pipe'] }).trim();
251
+ for (const pid of pids.split('\n').filter(Boolean)) {
252
+ const p = pid.trim();
253
+ if (p === myPid || protectedPids.has(p)) continue;
254
+ try { process.kill(parseInt(p), 'SIGTERM'); } catch {}
255
+ }
256
+ } catch {}
257
+ }
258
+ // Kill standalone processes: our instance's + orphans without any tag
259
+ try {
260
+ const out = execSync(`ps aux | grep -E 'telegram-standalone|terminal-standalone|workspace-standalone' | grep -v grep`, {
261
+ encoding: 'utf-8', timeout: 5000, stdio: ['pipe', 'pipe', 'pipe'],
262
+ }).trim();
263
+ for (const line of out.split('\n').filter(Boolean)) {
264
+ const isOurs = line.includes(instanceTag);
265
+ const isOrphan = !line.includes('--forge-port='); // no tag = legacy orphan
266
+ if (!isOurs && !isOrphan) continue; // belongs to another instance, skip
267
+ const pid = line.trim().split(/\s+/)[1];
268
+ if (pid === myPid || protectedPids.has(pid)) continue;
269
+ try { process.kill(parseInt(pid), 'SIGTERM'); } catch {}
270
+ }
271
+ } catch {}
272
+ } catch {}
273
+ }
274
+
275
+ // ── Start standalone services (single instance each) ──
276
+ const services = [];
277
+
278
+ function startServices() {
279
+ cleanupOrphans();
280
+
281
+ const instanceTag = `--forge-port=${webPort}`;
282
+
283
+ // Terminal server
284
+ const termScript = join(ROOT, 'lib', 'terminal-standalone.ts');
285
+ const termChild = spawn('npx', ['tsx', termScript, instanceTag], {
286
+ cwd: ROOT,
287
+ stdio: ['ignore', 'inherit', 'inherit'],
288
+ env: { ...process.env },
289
+ });
290
+ services.push(termChild);
291
+ console.log(`[forge] Terminal server started (pid: ${termChild.pid})`);
292
+
293
+ // Telegram bot
294
+ const telegramScript = join(ROOT, 'lib', 'telegram-standalone.ts');
295
+ const telegramChild = spawn('npx', ['tsx', telegramScript, instanceTag], {
296
+ cwd: ROOT,
297
+ stdio: ['ignore', 'inherit', 'inherit'],
298
+ env: { ...process.env },
299
+ });
300
+ services.push(telegramChild);
301
+ console.log(`[forge] Telegram bot started (pid: ${telegramChild.pid})`);
302
+
303
+ // Workspace daemon
304
+ const workspaceScript = join(ROOT, 'lib', 'workspace-standalone.ts');
305
+ const workspaceChild = spawn('npx', ['tsx', workspaceScript, instanceTag], {
306
+ cwd: ROOT,
307
+ stdio: ['ignore', 'inherit', 'inherit'],
308
+ env: { ...process.env },
309
+ });
310
+ services.push(workspaceChild);
311
+ console.log(`[forge] Workspace daemon started (pid: ${workspaceChild.pid})`);
312
+
313
+ // Track all child PIDs for clean shutdown
314
+ const childPids = services.map(c => c.pid).filter(Boolean);
315
+ savePids(childPids);
316
+ }
317
+
318
+ function stopServices() {
319
+ for (const child of services) {
320
+ try { child.kill('SIGTERM'); } catch {}
321
+ }
322
+ services.length = 0;
323
+ cleanupOrphans();
324
+ }
325
+
326
+ // ── Helper: stop running instance ──
327
+ async function stopServer() {
328
+ stopServices();
329
+ try { unlinkSync(join(DATA_DIR, 'tunnel-state.json')); } catch {}
330
+
331
+ // Kill all tracked child PIDs first
332
+ killTrackedPids();
333
+
334
+ let stopped = false;
335
+
336
+ // Try PID file first
337
+ try {
338
+ const pid = parseInt(readFileSync(PID_FILE, 'utf-8').trim());
339
+ process.kill(pid, 'SIGTERM');
340
+ console.log(`[forge] Stopped (pid ${pid})`);
341
+ stopped = true;
342
+ } catch {}
343
+ try { unlinkSync(PID_FILE); } catch {}
344
+
345
+ // Also kill by port (in case PID file is stale)
346
+ const portPids = [];
347
+ try {
348
+ const pids = execSync(`lsof -ti:${webPort}`, { encoding: 'utf-8', timeout: 3000 }).trim();
349
+ for (const p of pids.split('\n').filter(Boolean)) {
350
+ const pid = parseInt(p.trim());
351
+ try { process.kill(pid, 'SIGTERM'); stopped = true; portPids.push(pid); } catch {}
352
+ }
353
+ if (pids) console.log(`[forge] Killed processes on port ${webPort}`);
354
+ } catch {}
355
+
356
+ // Force kill after 2 seconds if SIGTERM didn't work
357
+ if (portPids.length > 0) {
358
+ await new Promise(r => setTimeout(r, 2000));
359
+ for (const pid of portPids) {
360
+ try { process.kill(pid, 'SIGKILL'); } catch {}
361
+ }
362
+ }
363
+
364
+ if (!stopped) {
365
+ console.log('[forge] No running server found');
366
+ }
367
+ return stopped;
368
+ }
369
+
370
+ // ── Helper: start background server ──
371
+ function startBackground() {
372
+ if (!existsSync(join(ROOT, '.next', 'BUILD_ID'))) {
373
+ console.log('[forge] Building...');
374
+ buildNext();
375
+ }
376
+
377
+ const logFd = openSync(LOG_FILE, 'a');
378
+ const nextBin = join(ROOT, 'node_modules', '.bin', 'next');
379
+ const child = spawn(nextBin, ['start', '-p', String(webPort)], {
380
+ cwd: ROOT,
381
+ stdio: ['ignore', logFd, logFd],
382
+ env: { ...process.env, FORGE_EXTERNAL_SERVICES: '1' },
383
+ detached: true,
384
+ });
385
+
386
+ writeFileSync(PID_FILE, String(child.pid));
387
+ protectedPids.add(String(child.pid));
388
+ child.unref();
389
+
390
+ // Start services in background too (cleanupOrphans will skip protectedPids)
391
+ startServices();
392
+
393
+ console.log(`[forge] Started in background (pid ${child.pid})`);
394
+ if (!getArg('--port')) {
395
+ console.log(`[forge] ⚠️ Default port changed: 3000 → ${webPort}`);
396
+ console.log(`[forge] ⚠️ Default port changed: 3000 → ${webPort}`);
397
+ console.log(`[forge] ⚠️ Default port changed: 3000 → ${webPort}`);
398
+ console.log(`[forge] ⚠️ Default port changed: 3000 → ${webPort}`);
399
+ console.log(`[forge] ⚠️ Default port changed: 3000 → ${webPort}`);
400
+ }
401
+ console.log(`[forge] Web: http://localhost:${webPort}`);
402
+ console.log(`[forge] Terminal: ws://localhost:${terminalPort}`);
403
+ console.log(`[forge] Data: ${DATA_DIR}`);
404
+ console.log(`[forge] Log: ${LOG_FILE}`);
405
+ console.log(`[forge] Stop: forge server stop`);
406
+ }
407
+
408
+ // ── Stop ──
409
+ if (isStop) {
410
+ await stopServer();
411
+ process.exit(0);
412
+ }
413
+
414
+ // ── Restart ──
415
+ if (isRestart) {
416
+ await stopServer();
417
+ // Wait for port to fully release
418
+ const net = await import('node:net');
419
+ for (let i = 0; i < 20; i++) {
420
+ await new Promise(r => setTimeout(r, 500));
421
+ const free = await new Promise(resolve => {
422
+ const s = net.createServer();
423
+ s.once('error', () => resolve(false));
424
+ s.once('listening', () => { s.close(); resolve(true); });
425
+ s.listen(webPort);
426
+ });
427
+ if (free) break;
428
+ }
429
+ startBackground();
430
+ process.exit(0);
431
+ }
432
+
433
+ // ── Rebuild ──
434
+ if (isRebuild || existsSync(join(ROOT, '.next', 'BUILD_ID'))) {
435
+ const pkgVersion = JSON.parse(readFileSync(join(ROOT, 'package.json'), 'utf-8')).version;
436
+ const versionFile = join(ROOT, '.next', '.forge-version');
437
+ const lastBuiltVersion = existsSync(versionFile) ? readFileSync(versionFile, 'utf-8').trim() : '';
438
+ if (isRebuild || lastBuiltVersion !== pkgVersion) {
439
+ console.log(`[forge] Rebuilding (v${pkgVersion})...`);
440
+ execSync('rm -rf .next', { cwd: ROOT });
441
+ buildNext();
442
+ writeFileSync(versionFile, pkgVersion);
443
+ if (isRebuild) {
444
+ console.log('[forge] Rebuild complete');
445
+ process.exit(0);
446
+ }
447
+ }
448
+ }
449
+
450
+ // ── Background ──
451
+ if (isBackground) {
452
+ startBackground();
453
+ process.exit(0);
454
+ }
455
+
456
+ // ── Foreground ──
457
+
458
+ // Clean up services on exit
459
+ process.on('SIGINT', () => { stopServices(); process.exit(0); });
460
+ process.on('SIGTERM', () => { stopServices(); process.exit(0); });
461
+
462
+ if (isDev) {
463
+ console.log(`[forge] Starting dev mode (port ${webPort}, terminal ${terminalPort}, data ${DATA_DIR})`);
464
+ startServices();
465
+ const child = spawn('npx', ['next', 'dev', '--turbopack', '-p', String(webPort)], {
466
+ cwd: ROOT,
467
+ stdio: 'inherit',
468
+ env: { ...process.env, FORGE_EXTERNAL_SERVICES: '1' },
469
+ });
470
+ child.on('exit', (code) => { stopServices(); process.exit(code || 0); });
471
+ } else {
472
+ if (!existsSync(join(ROOT, '.next', 'BUILD_ID'))) {
473
+ console.log('[forge] Building...');
474
+ buildNext();
475
+ }
476
+ console.log(`[forge] Starting server (port ${webPort}, terminal ${terminalPort}, data ${DATA_DIR})`);
477
+ startServices();
478
+ const child = spawn('npx', ['next', 'start', '-p', String(webPort)], {
479
+ cwd: ROOT,
480
+ stdio: 'inherit',
481
+ env: { ...process.env, FORGE_EXTERNAL_SERVICES: '1' },
482
+ });
483
+ child.on('exit', (code) => { stopServices(); process.exit(code || 0); });
484
+ }
@@ -0,0 +1,71 @@
1
+ #!/bin/bash
2
+ # check-forge-status.sh — Show Forge process status
3
+
4
+ echo "══════════════════════════════════"
5
+ echo " Forge Process Status"
6
+ echo "══════════════════════════════════"
7
+
8
+ # Next.js
9
+ count=$(ps aux | grep 'next-server' | grep -v grep | wc -l | tr -d ' ')
10
+ pid=$(ps aux | grep 'next-server' | grep -v grep | awk '{print $2}' | head -1)
11
+ if [ "$count" -gt 0 ]; then
12
+ echo " ● Next.js running (pid: $pid)"
13
+ else
14
+ echo " ○ Next.js stopped"
15
+ fi
16
+
17
+ # Terminal
18
+ count=$(ps aux | grep 'terminal-standalone' | grep -v grep | grep -v 'npm exec' | grep -v 'cli.mjs' | wc -l | tr -d ' ')
19
+ pid=$(ps aux | grep 'terminal-standalone' | grep -v grep | grep -v 'npm exec' | grep -v 'cli.mjs' | awk '{print $2}' | head -1)
20
+ if [ "$count" -gt 0 ]; then
21
+ echo " ● Terminal running (pid: $pid)"
22
+ else
23
+ echo " ○ Terminal stopped"
24
+ fi
25
+
26
+ # Telegram
27
+ count=$(ps aux | grep 'telegram-standalone' | grep -v grep | grep -v 'npm exec' | grep -v 'cli.mjs' | wc -l | tr -d ' ')
28
+ pid=$(ps aux | grep 'telegram-standalone' | grep -v grep | grep -v 'npm exec' | grep -v 'cli.mjs' | awk '{print $2}' | head -1)
29
+ if [ "$count" -gt 0 ]; then
30
+ echo " ● Telegram running (pid: $pid)"
31
+ else
32
+ echo " ○ Telegram stopped"
33
+ fi
34
+
35
+ # Workspace Daemon
36
+ count=$(ps aux | grep 'workspace-standalone' | grep -v grep | grep -v 'npm exec' | grep -v 'cli.mjs' | wc -l | tr -d ' ')
37
+ pid=$(ps aux | grep 'workspace-standalone' | grep -v grep | grep -v 'npm exec' | grep -v 'cli.mjs' | awk '{print $2}' | head -1)
38
+ if [ "$count" -gt 0 ]; then
39
+ echo " ● Workspace running (pid: $pid)"
40
+ else
41
+ echo " ○ Workspace stopped"
42
+ fi
43
+
44
+ # MCP Server (runs inside workspace-standalone)
45
+ mcp_status=$(curl -s http://localhost:8406/health 2>/dev/null)
46
+ if echo "$mcp_status" | grep -q '"ok":true'; then
47
+ sessions=$(echo "$mcp_status" | python3 -c "import sys,json; print(json.load(sys.stdin).get('sessions',0))" 2>/dev/null)
48
+ echo " ● MCP Server running (port: 8406, sessions: $sessions)"
49
+ else
50
+ echo " ○ MCP Server stopped"
51
+ fi
52
+
53
+ # Cloudflare Tunnel
54
+ count=$(ps aux | grep 'cloudflared tunnel' | grep -v grep | wc -l | tr -d ' ')
55
+ pid=$(ps aux | grep 'cloudflared tunnel' | grep -v grep | awk '{print $2}' | head -1)
56
+ url=$(cat ~/.forge/tunnel-state.json 2>/dev/null | python3 -c "import sys,json; d=json.load(sys.stdin); print(d.get('url',''))" 2>/dev/null)
57
+ if [ "$count" -gt 0 ]; then
58
+ echo " ● Tunnel running (pid: $pid) ${url}"
59
+ else
60
+ echo " ○ Tunnel stopped"
61
+ fi
62
+
63
+ # tmux sessions
64
+ tmux_count=$(tmux list-sessions 2>/dev/null | grep '^mw-' | wc -l | tr -d ' ')
65
+ echo ""
66
+ echo " Terminal sessions: $tmux_count"
67
+ tmux list-sessions 2>/dev/null | grep '^mw-' | while read line; do
68
+ echo " $line"
69
+ done
70
+
71
+ echo "══════════════════════════════════"