@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,491 @@
1
+ /**
2
+ * CLI Backend — executes agent steps by spawning CLI tools headless.
3
+ *
4
+ * Supports subscription accounts (no API key needed).
5
+ * Each step = one `claude -p "..."` call.
6
+ * Multi-step context via --resume (Claude) or prompt injection (others).
7
+ */
8
+
9
+ import { spawn, type ChildProcess } from 'node:child_process';
10
+ import { createRequire } from 'node:module';
11
+ import { getAgent } from '../../agents';
12
+ import type { AgentBackend, AgentStep, StepExecutionParams, StepExecutionResult, Artifact } from '../types';
13
+ import type { TaskLogEntry } from '../../../src/types';
14
+
15
+ const esmRequire = createRequire(import.meta.url);
16
+
17
+ // ─── Stream-JSON parser (reused from task-manager pattern) ──
18
+
19
+ function parseStreamJson(parsed: any): TaskLogEntry[] {
20
+ const entries: TaskLogEntry[] = [];
21
+ const ts = new Date().toISOString();
22
+
23
+ if (parsed.type === 'system' && parsed.subtype === 'init') {
24
+ entries.push({ type: 'system', subtype: 'init', content: `Model: ${parsed.model || 'unknown'}`, timestamp: ts });
25
+ return entries;
26
+ }
27
+
28
+ if (parsed.type === 'assistant' && parsed.message?.content) {
29
+ for (const block of parsed.message.content) {
30
+ if (block.type === 'text' && block.text) {
31
+ entries.push({ type: 'assistant', subtype: 'text', content: block.text, timestamp: ts });
32
+ } else if (block.type === 'tool_use') {
33
+ entries.push({
34
+ type: 'assistant',
35
+ subtype: 'tool_use',
36
+ content: typeof block.input === 'string' ? block.input : JSON.stringify(block.input || {}),
37
+ tool: block.name,
38
+ timestamp: ts,
39
+ });
40
+ } else if (block.type === 'tool_result') {
41
+ entries.push({
42
+ type: 'assistant',
43
+ subtype: 'tool_result',
44
+ content: typeof block.content === 'string' ? block.content : JSON.stringify(block.content || ''),
45
+ timestamp: ts,
46
+ });
47
+ }
48
+ }
49
+ return entries;
50
+ }
51
+
52
+ if (parsed.type === 'result') {
53
+ entries.push({
54
+ type: 'result',
55
+ subtype: parsed.subtype || 'success',
56
+ content: typeof parsed.result === 'string' ? parsed.result : JSON.stringify(parsed.result || ''),
57
+ timestamp: ts,
58
+ });
59
+ return entries;
60
+ }
61
+
62
+ // Ignore rate limit events
63
+ if (parsed.type === 'rate_limit_event') return entries;
64
+
65
+ // Unknown type — log raw
66
+ entries.push({ type: 'assistant', subtype: parsed.type || 'unknown', content: JSON.stringify(parsed), timestamp: ts });
67
+ return entries;
68
+ }
69
+
70
+ // ─── Artifact detection from tool_use events ─────────────
71
+
72
+ const WRITE_TOOL_NAMES = new Set(['Write', 'write_to_file', 'Edit', 'create_file', 'write_file']);
73
+
74
+ function detectArtifacts(parsed: any): Artifact[] {
75
+ const artifacts: Artifact[] = [];
76
+ if (parsed.type !== 'assistant' || !parsed.message?.content) return artifacts;
77
+
78
+ for (const block of parsed.message.content) {
79
+ if (block.type === 'tool_use' && WRITE_TOOL_NAMES.has(block.name)) {
80
+ const path = block.input?.file_path || block.input?.path || block.input?.filename;
81
+ if (path) {
82
+ artifacts.push({ type: 'file', path, summary: `Written by ${block.name}` });
83
+ }
84
+ }
85
+ }
86
+ return artifacts;
87
+ }
88
+
89
+ // ─── CLI Backend class ───────────────────────────────────
90
+
91
+ export class CliBackend implements AgentBackend {
92
+ private child: ChildProcess | null = null;
93
+ private sessionId: string | undefined;
94
+ headlessSessionId: string | undefined; // exposed for session file monitoring
95
+ /** Callback to persist sessionId back to agent state */
96
+ onSessionId?: (id: string) => void;
97
+
98
+ constructor(initialSessionId?: string) {
99
+ this.sessionId = initialSessionId;
100
+ }
101
+
102
+ async executeStep(params: StepExecutionParams): Promise<StepExecutionResult> {
103
+ const { config, step, history, projectPath, upstreamContext, onLog, abortSignal, workspaceId } = params;
104
+ const agentId = config.agentId || 'claude';
105
+
106
+ let adapter;
107
+ try {
108
+ adapter = getAgent(agentId);
109
+ } catch {
110
+ throw new Error(`Agent "${agentId}" not found or not installed`);
111
+ }
112
+
113
+ // Build prompt with context
114
+ const prompt = this.buildStepPrompt(step, history, upstreamContext);
115
+
116
+ // Use adapter to build spawn command (same as task-manager)
117
+ // Model priority: workspace config > profile config > adapter default
118
+ const effectiveModel = config.model || (adapter.config as any).model;
119
+ // Note: if no sessionId, each execution starts a new session (no resume).
120
+ // To maintain context, user can enable persistent terminal session per agent.
121
+
122
+ // Generate a session ID for headless execution so we can monitor the .jsonl file
123
+ const isClaude = adapter.config.type === 'claude-code';
124
+ if (isClaude && !this.sessionId) {
125
+ this.headlessSessionId = crypto.randomUUID();
126
+ }
127
+
128
+ const spawnOpts = adapter.buildTaskSpawn({
129
+ projectPath,
130
+ prompt,
131
+ model: effectiveModel,
132
+ conversationId: this.sessionId,
133
+ skipPermissions: true,
134
+ outputFormat: adapter.config.capabilities?.supportsStreamJson ? 'stream-json' : undefined,
135
+ extraFlags: this.headlessSessionId && !this.sessionId ? ['--session-id', this.headlessSessionId] : undefined,
136
+ });
137
+
138
+ onLog?.({
139
+ type: 'system',
140
+ subtype: 'init',
141
+ content: `Step "${step.label}" — ${agentId}${config.model ? `/${config.model}` : ''}${this.sessionId ? ' (resume)' : ''}`,
142
+ timestamp: new Date().toISOString(),
143
+ });
144
+
145
+ return new Promise<StepExecutionResult>((resolve, reject) => {
146
+ // Merge env: process env → adapter spawn env → profile env → workspace context
147
+ const profileEnv = (adapter.config as any).env || {};
148
+ const env = {
149
+ ...process.env,
150
+ ...(spawnOpts.env || {}),
151
+ ...profileEnv,
152
+ // Inject workspace context so forge skills can use them
153
+ FORGE_AGENT_ID: config.id,
154
+ FORGE_WORKSPACE_ID: workspaceId || '',
155
+ FORGE_PORT: String(process.env.PORT || 8403),
156
+ };
157
+ delete env.CLAUDECODE;
158
+
159
+ // Check if agent needs TTY — use cliType not agentId
160
+ const cliType = (adapter.config as any).cliType || adapter.config.type;
161
+ const needsTTY = adapter.config.capabilities?.requiresTTY
162
+ || cliType === 'codex';
163
+
164
+ if (needsTTY) {
165
+ this.executePTY(spawnOpts, projectPath, env, onLog, abortSignal, resolve, reject);
166
+ return;
167
+ }
168
+
169
+ this.child = spawn(spawnOpts.cmd, spawnOpts.args, {
170
+ cwd: projectPath,
171
+ env,
172
+ stdio: ['pipe', 'pipe', 'pipe'],
173
+ });
174
+ this.child.stdin?.end();
175
+
176
+ let buffer = '';
177
+ let resultText = '';
178
+ let sessionId = '';
179
+ const artifacts: Artifact[] = [];
180
+ let inputTokens = 0;
181
+ let outputTokens = 0;
182
+
183
+ // Handle abort signal
184
+ const onAbort = () => {
185
+ this.child?.kill('SIGTERM');
186
+ };
187
+ abortSignal?.addEventListener('abort', onAbort, { once: true });
188
+
189
+ // Fatal error detection pattern — only used for stderr (stdout is structured JSON)
190
+ const FATAL_PATTERN = /usage limit|rate limit|hit your.*limit|upgrade to (plus|pro|max)|exceeded.*monthly|you've been rate limited|api key.*invalid|insufficient.*quota|billing.*not.*active/i;
191
+ let fatalDetected = false;
192
+
193
+ this.child.stdout?.on('data', (data: Buffer) => {
194
+ const raw = data.toString();
195
+ // Fatal detection on stdout — only on non-JSON lines (skip tool results, user messages)
196
+ // JSON lines start with { and contain structured data from claude CLI
197
+ if (!fatalDetected && FATAL_PATTERN.test(raw)) {
198
+ // Check each line individually — only flag if it's NOT inside a JSON payload
199
+ const nonJsonLines = raw.split('\n').filter(l => {
200
+ const trimmed = l.trim();
201
+ return trimmed && !trimmed.startsWith('{') && !trimmed.startsWith('"') && !trimmed.includes('tool_use_id');
202
+ });
203
+ const fatalLine = nonJsonLines.find(l => FATAL_PATTERN.test(l));
204
+ if (fatalLine) {
205
+ fatalDetected = true;
206
+ console.log(`[cli-backend] Fatal error detected: ${fatalLine.trim().slice(0, 100)}`);
207
+ onLog?.({ type: 'system', subtype: 'error', content: fatalLine.trim().slice(0, 200), timestamp: new Date().toISOString() });
208
+ this.child?.kill('SIGTERM');
209
+ return;
210
+ }
211
+ }
212
+ buffer += raw;
213
+ const lines = buffer.split('\n');
214
+ buffer = lines.pop() || '';
215
+
216
+ for (const line of lines) {
217
+ if (!line.trim()) continue;
218
+ try {
219
+ const parsed = JSON.parse(line);
220
+
221
+ // Emit log entries
222
+ const entries = parseStreamJson(parsed);
223
+ for (const entry of entries) {
224
+ onLog?.(entry);
225
+ }
226
+
227
+ // Track session ID for multi-step resume
228
+ if (parsed.session_id) sessionId = parsed.session_id;
229
+
230
+ // Track result
231
+ if (parsed.type === 'result') {
232
+ resultText = typeof parsed.result === 'string'
233
+ ? parsed.result
234
+ : JSON.stringify(parsed.result || '');
235
+ if (parsed.total_cost_usd) {
236
+ // Cost tracking if available
237
+ }
238
+ }
239
+
240
+ // Track usage
241
+ if (parsed.usage) {
242
+ inputTokens += parsed.usage.input_tokens || 0;
243
+ outputTokens += parsed.usage.output_tokens || 0;
244
+ }
245
+
246
+ // Detect file write artifacts
247
+ artifacts.push(...detectArtifacts(parsed));
248
+
249
+ } catch {
250
+ // Non-JSON line — emit as raw text log
251
+ if (line.trim()) {
252
+ onLog?.({
253
+ type: 'assistant',
254
+ subtype: 'text',
255
+ content: line,
256
+ timestamp: new Date().toISOString(),
257
+ });
258
+ }
259
+ }
260
+ }
261
+ });
262
+
263
+ this.child.stderr?.on('data', (data: Buffer) => {
264
+ const text = data.toString().trim();
265
+ // Also check stderr for fatal errors
266
+ if (!fatalDetected && FATAL_PATTERN.test(text)) {
267
+ fatalDetected = true;
268
+ console.log(`[cli-backend] Fatal error in stderr: ${text.slice(0, 100)}`);
269
+ this.child?.kill('SIGTERM');
270
+ }
271
+ if (text) {
272
+ onLog?.({
273
+ type: 'system',
274
+ subtype: 'error',
275
+ content: text,
276
+ timestamp: new Date().toISOString(),
277
+ });
278
+ }
279
+ });
280
+
281
+ this.child.on('error', (err) => {
282
+ abortSignal?.removeEventListener('abort', onAbort);
283
+ this.child = null;
284
+ reject(err);
285
+ });
286
+
287
+ this.child.on('exit', (code) => {
288
+ abortSignal?.removeEventListener('abort', onAbort);
289
+
290
+ // Flush remaining buffer
291
+ if (buffer.trim()) {
292
+ try {
293
+ const parsed = JSON.parse(buffer);
294
+ const entries = parseStreamJson(parsed);
295
+ for (const entry of entries) onLog?.(entry);
296
+ if (parsed.type === 'result') {
297
+ resultText = typeof parsed.result === 'string' ? parsed.result : JSON.stringify(parsed.result || '');
298
+ }
299
+ if (parsed.session_id) sessionId = parsed.session_id;
300
+ artifacts.push(...detectArtifacts(parsed));
301
+ } catch {
302
+ if (buffer.trim()) {
303
+ onLog?.({ type: 'assistant', subtype: 'text', content: buffer.trim(), timestamp: new Date().toISOString() });
304
+ }
305
+ }
306
+ }
307
+
308
+ // Persist session ID for multi-step resume
309
+ this.sessionId = sessionId || this.sessionId;
310
+ if (this.sessionId && this.onSessionId) this.onSessionId(this.sessionId);
311
+ this.child = null;
312
+
313
+ // Check for error patterns even if exit code is 0
314
+ const KNOWN_ERRORS = /usage limit|rate limit|upgrade to|authentication failed|api key.*invalid/i;
315
+ const errorInOutput = resultText.split('\n').find(l => KNOWN_ERRORS.test(l))?.trim();
316
+
317
+ if (errorInOutput) {
318
+ reject(new Error(errorInOutput.slice(0, 200)));
319
+ } else if (code === 0 || code === null) {
320
+ resolve({
321
+ response: resultText,
322
+ artifacts,
323
+ sessionId: this.sessionId,
324
+ inputTokens,
325
+ outputTokens,
326
+ });
327
+ } else if (abortSignal?.aborted || code === 143 || code === 130) {
328
+ // 143=SIGTERM, 130=SIGINT — normal shutdown, not an error
329
+ reject(new Error('Aborted'));
330
+ } else {
331
+ reject(new Error(`CLI exited with code ${code}`));
332
+ }
333
+ });
334
+ });
335
+ }
336
+
337
+ abort(): void {
338
+ this.child?.kill('SIGTERM');
339
+ }
340
+
341
+ /**
342
+ * Build the prompt for a step, injecting history context.
343
+ * If resuming (sessionId exists), the CLI already has conversation context.
344
+ * Otherwise, prepend a summary of prior steps.
345
+ */
346
+ /** Execute step using node-pty for agents that require a TTY (e.g., codex) */
347
+ private executePTY(
348
+ spawnOpts: { cmd: string; args: string[] },
349
+ projectPath: string,
350
+ env: Record<string, string | undefined>,
351
+ onLog: StepExecutionParams['onLog'],
352
+ abortSignal: AbortSignal | undefined,
353
+ resolve: (r: StepExecutionResult) => void,
354
+ reject: (e: Error) => void,
355
+ ): void {
356
+ try {
357
+ const pty = esmRequire('node-pty');
358
+ const stripAnsi = (s: string) => s
359
+ .replace(/\x1b\[[0-9;?]*[a-zA-Z]/g, '')
360
+ .replace(/\x1b\][^\x07\x1b]*(?:\x07|\x1b\\)/g, '')
361
+ .replace(/\x1b[()][0-9A-B]/g, '')
362
+ .replace(/\x1b[=>]/g, '')
363
+ .replace(/\r/g, '')
364
+ .replace(/\x07/g, '');
365
+
366
+ const ptyProcess = pty.spawn(spawnOpts.cmd, spawnOpts.args, {
367
+ name: 'xterm-256color',
368
+ cols: 120, rows: 40,
369
+ cwd: projectPath,
370
+ env,
371
+ });
372
+
373
+ let resultText = '';
374
+ let ptyBytes = 0;
375
+ let idleTimer: any = null;
376
+ const PTY_IDLE_MS = 15000;
377
+
378
+ const onAbort = () => { try { ptyProcess.kill(); } catch {} };
379
+ abortSignal?.addEventListener('abort', onAbort, { once: true });
380
+
381
+ // Noise filter: skip spinner fragments, partial redraws, and short garbage
382
+ const NOISE_PATTERNS = /^(W|Wo|Wor|Work|Worki|Workin|Working|orking|rking|king|ing|ng|g|•|[0-9]+s?|[0-9]+m [0-9]+s|›.*|─+|╭.*|│.*|╰.*|\[K|\[0m|;[0-9;m]+|\s*)$/;
383
+ const isNoise = (line: string) => {
384
+ const t = line.trim();
385
+ return !t || t.length < 3 || NOISE_PATTERNS.test(t) || /^[•\s]*$/.test(t);
386
+ };
387
+
388
+ let lineBuf = '';
389
+
390
+ ptyProcess.onData((data: string) => {
391
+ const clean = stripAnsi(data);
392
+ ptyBytes += clean.length;
393
+ resultText += clean;
394
+ if (resultText.length > 50000) resultText = resultText.slice(-25000);
395
+
396
+ // Buffer lines and only emit meaningful content
397
+ lineBuf += clean;
398
+ const lines = lineBuf.split('\n');
399
+ lineBuf = lines.pop() || '';
400
+
401
+ for (const line of lines) {
402
+ if (!isNoise(line)) {
403
+ onLog?.({ type: 'assistant', subtype: 'text', content: line.trim(), timestamp: new Date().toISOString() });
404
+ }
405
+ }
406
+
407
+ // Detect fatal errors in real-time — kill immediately instead of waiting for idle
408
+ if (/usage limit|rate limit|hit your.*limit|upgrade to (plus|pro)/i.test(clean)) {
409
+ console.log(`[cli-backend] Detected usage limit — killing PTY immediately`);
410
+ onLog?.({ type: 'system', subtype: 'error', content: 'Agent hit usage limit', timestamp: new Date().toISOString() });
411
+ if (idleTimer) clearTimeout(idleTimer);
412
+ try { ptyProcess.kill(); } catch {}
413
+ return;
414
+ }
415
+
416
+ // Idle timer: kill after 15s of silence (interactive agents don't exit on their own)
417
+ if (idleTimer) clearTimeout(idleTimer);
418
+ if (ptyBytes > 500) {
419
+ idleTimer = setTimeout(() => { try { ptyProcess.kill(); } catch {} }, PTY_IDLE_MS);
420
+ }
421
+ });
422
+
423
+ ptyProcess.onExit(({ exitCode }: { exitCode: number }) => {
424
+ if (idleTimer) clearTimeout(idleTimer);
425
+ abortSignal?.removeEventListener('abort', onAbort);
426
+
427
+ // Flush remaining buffer
428
+ if (lineBuf.trim() && !isNoise(lineBuf)) {
429
+ onLog?.({ type: 'assistant', subtype: 'text', content: lineBuf.trim(), timestamp: new Date().toISOString() });
430
+ }
431
+
432
+ // Detect error patterns in output (rate limit, auth failure, etc.)
433
+ const ERROR_PATTERNS = [
434
+ /usage limit/i,
435
+ /rate limit/i,
436
+ /upgrade to/i,
437
+ /authentication failed/i,
438
+ /api key/i,
439
+ /permission denied/i,
440
+ /error:.*fatal/i,
441
+ ];
442
+ const errorMatch = ERROR_PATTERNS.find(p => p.test(resultText));
443
+ if (errorMatch) {
444
+ // Extract the error line
445
+ const errorLine = resultText.split('\n').find(l => errorMatch.test(l))?.trim() || 'Agent execution failed';
446
+ reject(new Error(errorLine.slice(0, 200)));
447
+ return;
448
+ }
449
+
450
+ const meaningful = resultText.split('\n').filter(l => !isNoise(l)).join('\n');
451
+ resolve({
452
+ response: meaningful.slice(-2000) || resultText.slice(-500),
453
+ artifacts: [],
454
+ inputTokens: 0,
455
+ outputTokens: 0,
456
+ });
457
+ });
458
+ } catch (err: any) {
459
+ reject(new Error(`PTY spawn failed: ${err.message}`));
460
+ }
461
+ }
462
+
463
+ private buildStepPrompt(step: AgentStep, history: TaskLogEntry[], upstreamContext?: string): string {
464
+ let prompt = step.prompt;
465
+
466
+ // If resuming with session, Claude already has conversation context — skip history injection
467
+ if (!this.sessionId && history.length > 0) {
468
+ // Only inject last 3 step results (not full history) to save tokens
469
+ const MAX_HISTORY_STEPS = 3;
470
+ const stepResults = history
471
+ .filter(m => m.type === 'result' && m.subtype === 'step_complete')
472
+ .slice(-MAX_HISTORY_STEPS);
473
+
474
+ if (stepResults.length > 0) {
475
+ const contextSummary = stepResults
476
+ .map((m, i) => `Step ${i + 1}: ${m.content.slice(0, 500)}${m.content.length > 500 ? '...' : ''}`)
477
+ .join('\n\n');
478
+ prompt = `## Context from previous steps (last ${stepResults.length}):\n${contextSummary}\n\n---\n\n## Current task:\n${prompt}`;
479
+ }
480
+ }
481
+
482
+ if (upstreamContext) {
483
+ prompt = `## Upstream agent output:\n${upstreamContext}\n\n---\n\n${prompt}`;
484
+ }
485
+
486
+ // Note: [SEND:] bus markers disabled. Agent communication now uses forge skills (/forge-send, /forge-inbox).
487
+ // Phase 2 will add ticket system + causedBy protocol for structured agent-to-agent feedback.
488
+
489
+ return prompt;
490
+ }
491
+ }
@@ -0,0 +1,84 @@
1
+ /**
2
+ * Workspace Agent System — public API.
3
+ */
4
+
5
+ // Types
6
+ export type {
7
+ WorkspaceAgentConfig,
8
+ AgentBackendType,
9
+ AgentStep,
10
+ AgentStatus,
11
+ AgentState,
12
+ Artifact,
13
+ BusMessage,
14
+ WorkspaceState,
15
+ AgentBackend,
16
+ StepExecutionParams,
17
+ StepExecutionResult,
18
+ WorkerEvent,
19
+ } from './types';
20
+
21
+ // Core
22
+ export { AgentWorker, type AgentWorkerOptions } from './agent-worker';
23
+ export { AgentBus } from './agent-bus';
24
+ export { WorkspaceOrchestrator, type OrchestratorEvent } from './orchestrator';
25
+
26
+ // Backends
27
+ export { ApiBackend } from './backends/api-backend';
28
+ export { CliBackend } from './backends/cli-backend';
29
+
30
+ // Presets
31
+ export { AGENT_PRESETS, createDeliveryPipeline, createFromPreset } from './presets';
32
+
33
+ // Manager (singleton orchestrator cache + SSE)
34
+ export {
35
+ getOrchestrator,
36
+ createOrchestratorFromState,
37
+ getOrchestratorByProject,
38
+ subscribeSSE,
39
+ shutdownOrchestrator,
40
+ shutdownAll,
41
+ } from './manager';
42
+
43
+ // Persistence
44
+ // NOTE: saveWorkspace is intentionally NOT exported here.
45
+ // The workspace daemon is the exclusive writer of state.json.
46
+ // All mutations must go through the daemon's HTTP API to prevent race conditions.
47
+ export {
48
+ loadWorkspace,
49
+ listWorkspaces,
50
+ findWorkspaceByProject,
51
+ deleteWorkspace,
52
+ readAgentLog,
53
+ readAgentLogTail,
54
+ appendAgentLog,
55
+ startAutoSave,
56
+ stopAutoSave,
57
+ type WorkspaceSummary,
58
+ } from './persistence';
59
+
60
+ // Smith Memory
61
+ export {
62
+ loadMemory,
63
+ saveMemory,
64
+ createMemory,
65
+ addObservation,
66
+ addSessionSummary,
67
+ formatMemoryForPrompt,
68
+ formatMemoryForDisplay,
69
+ getMemoryStats,
70
+ parseStepToObservations,
71
+ buildSessionSummary,
72
+ type SmithMemory,
73
+ type Observation,
74
+ type ObservationType,
75
+ type SessionSummary,
76
+ type MemoryDisplayEntry,
77
+ } from './smith-memory';
78
+
79
+ // Skill installer
80
+ export {
81
+ installForgeSkills,
82
+ hasForgeSkills,
83
+ removeForgeSkills,
84
+ } from './skill-installer';