@netnodeag/kraftwerk 0.38.0 → 0.39.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (258) hide show
  1. package/dist/cli/init.js +1 -0
  2. package/dist/cli/kraftwerk.js +2 -0
  3. package/dist/cli/vibeables.d.ts +2 -0
  4. package/dist/cli/vibeables.js +89 -0
  5. package/dist/config.d.ts +20 -0
  6. package/dist/config.js +29 -10
  7. package/dist/inspector/chat/sessions.d.ts +11 -0
  8. package/dist/inspector/chat/sessions.js +86 -10
  9. package/dist/inspector/chat/types.d.ts +2 -0
  10. package/dist/inspector/git.js +5 -3
  11. package/dist/inspector/mtime.d.ts +3 -0
  12. package/dist/inspector/mtime.js +31 -0
  13. package/dist/inspector/repos.d.ts +2 -0
  14. package/dist/inspector/repos.js +5 -1
  15. package/dist/inspector/server.js +90 -1
  16. package/dist/inspector/settings.d.ts +3 -1
  17. package/dist/inspector/settings.js +19 -8
  18. package/dist/inspector/vibeables.d.ts +152 -0
  19. package/dist/inspector/vibeables.js +509 -0
  20. package/inspector/dist/assets/apl-gfMMiTNf.js +1 -0
  21. package/inspector/dist/assets/asciiarmor-C_eisQCp.js +1 -0
  22. package/inspector/dist/assets/asn1-DCl_8MCW.js +1 -0
  23. package/inspector/dist/assets/asterisk-BEn0Cwpx.js +1 -0
  24. package/inspector/dist/assets/brainfuck-D5EjA2JK.js +1 -0
  25. package/inspector/dist/assets/clike-D_6L3tnO.js +1 -0
  26. package/inspector/dist/assets/clojure-BflJGmDX.js +1 -0
  27. package/inspector/dist/assets/cmake-84nbDH0I.js +1 -0
  28. package/inspector/dist/assets/cobol-DHLQUbN7.js +1 -0
  29. package/inspector/dist/assets/coffeescript-De_zI4J0.js +1 -0
  30. package/inspector/dist/assets/commonlisp-DgAKBe0r.js +1 -0
  31. package/inspector/dist/assets/crystal-Bsdphhtm.js +1 -0
  32. package/inspector/dist/assets/css-CnaYoQib.js +1 -0
  33. package/inspector/dist/assets/cypher-p9eYesGn.js +1 -0
  34. package/inspector/dist/assets/d-DWkQyNnU.js +1 -0
  35. package/inspector/dist/assets/diff-ChtP43wD.js +1 -0
  36. package/inspector/dist/assets/dist-3Nzkrylv.js +1 -0
  37. package/inspector/dist/assets/dist-5wk4daHl.js +1 -0
  38. package/inspector/dist/assets/dist-BCM6ehYa.js +1 -0
  39. package/inspector/dist/assets/dist-BECiZEqH.js +1 -0
  40. package/inspector/dist/assets/dist-BbhR2mEU.js +1 -0
  41. package/inspector/dist/assets/dist-CF7An11X.js +1 -0
  42. package/inspector/dist/assets/dist-CI-2-8Tz.js +23 -0
  43. package/inspector/dist/assets/dist-CPlSMtdY.js +1 -0
  44. package/inspector/dist/assets/dist-CXS6W3P9.js +9 -0
  45. package/inspector/dist/assets/dist-Ceimhh7q.js +1 -0
  46. package/inspector/dist/assets/dist-D3tgdU3w.js +1 -0
  47. package/inspector/dist/assets/dist-D8nmL5S9.js +1 -0
  48. package/inspector/dist/assets/dist-DNBDudvB.js +1 -0
  49. package/inspector/dist/assets/dist-DTW4FhJ_.js +1 -0
  50. package/inspector/dist/assets/dist-DXIk6Ebu.js +1 -0
  51. package/inspector/dist/assets/dist-DaG9QYNU.js +1 -0
  52. package/inspector/dist/assets/dist-Dd-u7fXY.js +1 -0
  53. package/inspector/dist/assets/dist-DwyxsFyN.js +1 -0
  54. package/inspector/dist/assets/dist-H3rerbMg.js +13 -0
  55. package/inspector/dist/assets/dist-ZMc9InB9.js +1 -0
  56. package/inspector/dist/assets/dist-nc_mc1w0.js +1 -0
  57. package/inspector/dist/assets/dist-rE2oRtJp.js +11 -0
  58. package/inspector/dist/assets/dist-yFKhRrHN.js +2 -0
  59. package/inspector/dist/assets/dockerfile-DJkHQgkl.js +1 -0
  60. package/inspector/dist/assets/dtd-DTF72YNO.js +1 -0
  61. package/inspector/dist/assets/dylan-BCDoL_-p.js +1 -0
  62. package/inspector/dist/assets/ebnf-D4c0_ac3.js +1 -0
  63. package/inspector/dist/assets/ecl-BVIeWmwY.js +1 -0
  64. package/inspector/dist/assets/editor-6yCJBeDg.js +120 -0
  65. package/inspector/dist/assets/editor-B1Jq9YIq.css +1 -0
  66. package/inspector/dist/assets/eiffel-BEjRio4Q.js +1 -0
  67. package/inspector/dist/assets/elm-Cshzl8qu.js +1 -0
  68. package/inspector/dist/assets/erlang-BV0c4Hdn.js +1 -0
  69. package/inspector/dist/assets/factor-LKH5gN8L.js +1 -0
  70. package/inspector/dist/assets/fcl-ClOhbFR7.js +1 -0
  71. package/inspector/dist/assets/forth-D6RzAl64.js +1 -0
  72. package/inspector/dist/assets/fortran-Bt6PBEDR.js +1 -0
  73. package/inspector/dist/assets/gas-BHEdbvp9.js +1 -0
  74. package/inspector/dist/assets/gherkin-oBAE_ms0.js +1 -0
  75. package/inspector/dist/assets/groovy-CUpZ7dEl.js +1 -0
  76. package/inspector/dist/assets/haskell-BRsoo5mP.js +1 -0
  77. package/inspector/dist/assets/haxe-DjVOVvNP.js +1 -0
  78. package/inspector/dist/assets/http-CLVgA2GD.js +1 -0
  79. package/inspector/dist/assets/idl-BUZw3wgd.js +1 -0
  80. package/inspector/dist/assets/index-Dom87GNV.css +1 -0
  81. package/inspector/dist/assets/index-DurTvcNI.js +218 -0
  82. package/inspector/dist/assets/javascript-Bu8mWwtz.js +1 -0
  83. package/inspector/dist/assets/julia-CQfgDRfP.js +1 -0
  84. package/inspector/dist/assets/livescript-BXxG0Yva.js +1 -0
  85. package/inspector/dist/assets/lua-DPCEkfD_.js +1 -0
  86. package/inspector/dist/assets/material-symbols-rounded-DzDTtRam.woff2 +0 -0
  87. package/inspector/dist/assets/mathematica-u8YMmbU0.js +1 -0
  88. package/inspector/dist/assets/mbox-BEMVcqjs.js +1 -0
  89. package/inspector/dist/assets/{mirc-CjQqDB4T.js → mirc-C9zpzAZU.js} +1 -1
  90. package/inspector/dist/assets/mllike-B45xgp2S.js +1 -0
  91. package/inspector/dist/assets/modelica-CqHI_q-D.js +1 -0
  92. package/inspector/dist/assets/mscgen-qgSLujhx.js +1 -0
  93. package/inspector/dist/assets/mumps-BSzj6Xyz.js +1 -0
  94. package/inspector/dist/assets/{nginx-DdIZxoE0.js → nginx-8H7HVH4w.js} +1 -1
  95. package/inspector/dist/assets/nsis-viPvXFiq.js +1 -0
  96. package/inspector/dist/assets/ntriples-B9h1VB_g.js +1 -0
  97. package/inspector/dist/assets/octave-D2Q8cUp1.js +1 -0
  98. package/inspector/dist/assets/oz-BwTct_5T.js +1 -0
  99. package/inspector/dist/assets/pascal-Dp_KdFgX.js +1 -0
  100. package/inspector/dist/assets/perl-BkSkiI9m.js +1 -0
  101. package/inspector/dist/assets/pig-AF4Hwhju.js +1 -0
  102. package/inspector/dist/assets/powershell-BcIto6Sf.js +1 -0
  103. package/inspector/dist/assets/properties-C357ku5U.js +1 -0
  104. package/inspector/dist/assets/protobuf-D1ij_kNL.js +1 -0
  105. package/inspector/dist/assets/pug-3K-JMW4g.js +1 -0
  106. package/inspector/dist/assets/puppet-BZyAS7I4.js +1 -0
  107. package/inspector/dist/assets/python-B_1Jd8HM.js +1 -0
  108. package/inspector/dist/assets/q-B9NhS7L_.js +1 -0
  109. package/inspector/dist/assets/r-CxDmU1I4.js +1 -0
  110. package/inspector/dist/assets/rpm-gpDK5sbt.js +1 -0
  111. package/inspector/dist/assets/ruby-ChfNwlCY.js +1 -0
  112. package/inspector/dist/assets/{sas-B4kiWyti.js → sas-C2OyD2Y6.js} +1 -1
  113. package/inspector/dist/assets/scheme-D9qYN0V5.js +1 -0
  114. package/inspector/dist/assets/shell-DwuoZtxw.js +1 -0
  115. package/inspector/dist/assets/sieve-tLWDfEkZ.js +1 -0
  116. package/inspector/dist/assets/simple-mode-DXiLM1-G.js +1 -0
  117. package/inspector/dist/assets/smalltalk-BLp5-jwC.js +1 -0
  118. package/inspector/dist/assets/solr-B78wSQJQ.js +1 -0
  119. package/inspector/dist/assets/sparql-Dz-mlCAC.js +1 -0
  120. package/inspector/dist/assets/spreadsheet-CTIncYxj.js +1 -0
  121. package/inspector/dist/assets/sql-DuQMFDvy.js +1 -0
  122. package/inspector/dist/assets/stex-DNzd62Q_.js +1 -0
  123. package/inspector/dist/assets/stylus-BOVgKnng.js +1 -0
  124. package/inspector/dist/assets/swift-DKB6_1j6.js +1 -0
  125. package/inspector/dist/assets/tcl-BGfruO1u.js +1 -0
  126. package/inspector/dist/assets/textile-C4jVoHG1.js +1 -0
  127. package/inspector/dist/assets/tiddlywiki-VlUiK86J.js +1 -0
  128. package/inspector/dist/assets/tiki-AK6FwT8q.js +1 -0
  129. package/inspector/dist/assets/toml-BPTmHmyx.js +1 -0
  130. package/inspector/dist/assets/troff-C2dAgh7P.js +1 -0
  131. package/inspector/dist/assets/ttcn-PPSTk1ow.js +1 -0
  132. package/inspector/dist/assets/ttcn-cfg-2b4Gb5sE.js +1 -0
  133. package/inspector/dist/assets/turtle-Cx3rYX2g.js +1 -0
  134. package/inspector/dist/assets/vb-BthdM_4N.js +1 -0
  135. package/inspector/dist/assets/vbscript-D9f6rSsU.js +1 -0
  136. package/inspector/dist/assets/velocity-CqftRsjg.js +1 -0
  137. package/inspector/dist/assets/verilog-CjI9Y6RI.js +1 -0
  138. package/inspector/dist/assets/vhdl-kS471soi.js +1 -0
  139. package/inspector/dist/assets/webidl-D5jiJvOU.js +1 -0
  140. package/inspector/dist/assets/xquery-BKJx4mf9.js +1 -0
  141. package/inspector/dist/assets/yacas-CXXgtw0p.js +1 -0
  142. package/inspector/dist/assets/z80-Co3PbHdE.js +1 -0
  143. package/inspector/dist/index.html +2 -2
  144. package/package.json +6 -6
  145. package/inspector/dist/assets/apl-B4CMkyY2.js +0 -1
  146. package/inspector/dist/assets/asciiarmor-Df11BRmG.js +0 -1
  147. package/inspector/dist/assets/asn1-EdZsLKOL.js +0 -1
  148. package/inspector/dist/assets/asterisk-B-8jnY81.js +0 -1
  149. package/inspector/dist/assets/brainfuck-C4LP7Hcl.js +0 -1
  150. package/inspector/dist/assets/clike-B9uivgTg.js +0 -1
  151. package/inspector/dist/assets/clojure-BMjYHr_A.js +0 -1
  152. package/inspector/dist/assets/cmake-BQqOBYOt.js +0 -1
  153. package/inspector/dist/assets/cobol-CWcv1MsR.js +0 -1
  154. package/inspector/dist/assets/coffeescript-S37ZYGWr.js +0 -1
  155. package/inspector/dist/assets/commonlisp-DBKNyK5s.js +0 -1
  156. package/inspector/dist/assets/crystal-SjHAIU92.js +0 -1
  157. package/inspector/dist/assets/css-BnMrqG3P.js +0 -1
  158. package/inspector/dist/assets/cypher-C_CwsFkJ.js +0 -1
  159. package/inspector/dist/assets/d-pRatUO7H.js +0 -1
  160. package/inspector/dist/assets/diff-DbItnlRl.js +0 -1
  161. package/inspector/dist/assets/dockerfile-BKs6k2Af.js +0 -1
  162. package/inspector/dist/assets/dtd-DF_7sFjM.js +0 -1
  163. package/inspector/dist/assets/dylan-DwRh75JA.js +0 -1
  164. package/inspector/dist/assets/ebnf-CDyGwa7X.js +0 -1
  165. package/inspector/dist/assets/ecl-Cabwm37j.js +0 -1
  166. package/inspector/dist/assets/editor-9rr2cQaW.css +0 -1
  167. package/inspector/dist/assets/editor-BnDJd3j4.js +0 -144
  168. package/inspector/dist/assets/eiffel-CnydiIhH.js +0 -1
  169. package/inspector/dist/assets/elm-vLlmbW-K.js +0 -1
  170. package/inspector/dist/assets/erlang-BNw1qcRV.js +0 -1
  171. package/inspector/dist/assets/factor-kuTfRLto.js +0 -1
  172. package/inspector/dist/assets/fcl-Kvtd6kyn.js +0 -1
  173. package/inspector/dist/assets/forth-Ffai-XNe.js +0 -1
  174. package/inspector/dist/assets/fortran-DYz_wnZ1.js +0 -1
  175. package/inspector/dist/assets/gas-Bneqetm1.js +0 -1
  176. package/inspector/dist/assets/gherkin-heZmZLOM.js +0 -1
  177. package/inspector/dist/assets/groovy-D9Dt4D0W.js +0 -1
  178. package/inspector/dist/assets/haskell-Cw1EW3IL.js +0 -1
  179. package/inspector/dist/assets/haxe-H-WmDvRZ.js +0 -1
  180. package/inspector/dist/assets/http-DBlCnlav.js +0 -1
  181. package/inspector/dist/assets/idl-BEugSyMb.js +0 -1
  182. package/inspector/dist/assets/index-1K-YGe-R.js +0 -1
  183. package/inspector/dist/assets/index-5n-x53jb.js +0 -1
  184. package/inspector/dist/assets/index-B6zeZ-I9.js +0 -2
  185. package/inspector/dist/assets/index-BCwvYdEE.js +0 -1
  186. package/inspector/dist/assets/index-BDHHRQvJ.js +0 -7
  187. package/inspector/dist/assets/index-BFmXikOX.js +0 -1
  188. package/inspector/dist/assets/index-C2kxy-K_.js +0 -1
  189. package/inspector/dist/assets/index-CTECF5uX.js +0 -1
  190. package/inspector/dist/assets/index-CtnGrZvu.js +0 -217
  191. package/inspector/dist/assets/index-DBHgQG4M.js +0 -1
  192. package/inspector/dist/assets/index-DfqhDHp9.js +0 -1
  193. package/inspector/dist/assets/index-DjMx3a5H.css +0 -1
  194. package/inspector/dist/assets/index-DmY7gYaR.js +0 -1
  195. package/inspector/dist/assets/index-Dq3QrDLb.js +0 -1
  196. package/inspector/dist/assets/index-Fd3s8yys.js +0 -1
  197. package/inspector/dist/assets/index-Rmy9pam8.js +0 -1
  198. package/inspector/dist/assets/index-VxlzgVIX.js +0 -1
  199. package/inspector/dist/assets/index-o4xPJnqZ.js +0 -1
  200. package/inspector/dist/assets/index-sSEE6ykA.js +0 -3
  201. package/inspector/dist/assets/javascript-iXu5QeM3.js +0 -1
  202. package/inspector/dist/assets/julia-DuME0IfC.js +0 -1
  203. package/inspector/dist/assets/livescript-BwQOo05w.js +0 -1
  204. package/inspector/dist/assets/lua-VAEuO923.js +0 -1
  205. package/inspector/dist/assets/material-symbols-rounded-DxXFL64Y.woff2 +0 -0
  206. package/inspector/dist/assets/mathematica-DTrFuWx2.js +0 -1
  207. package/inspector/dist/assets/mbox-CNhZ1qSd.js +0 -1
  208. package/inspector/dist/assets/mllike-CXdrOF99.js +0 -1
  209. package/inspector/dist/assets/modelica-Dc1JOy9r.js +0 -1
  210. package/inspector/dist/assets/mscgen-BA5vi2Kp.js +0 -1
  211. package/inspector/dist/assets/mumps-BT43cFF4.js +0 -1
  212. package/inspector/dist/assets/nsis-LY0VT_u5.js +0 -1
  213. package/inspector/dist/assets/ntriples-BfvgReVJ.js +0 -1
  214. package/inspector/dist/assets/octave-Ck1zUtKM.js +0 -1
  215. package/inspector/dist/assets/oz-BzwKVEFT.js +0 -1
  216. package/inspector/dist/assets/pascal--L3eBynH.js +0 -1
  217. package/inspector/dist/assets/perl-CdXCOZ3F.js +0 -1
  218. package/inspector/dist/assets/pig-CevX1Tat.js +0 -1
  219. package/inspector/dist/assets/powershell-CFHJl5sT.js +0 -1
  220. package/inspector/dist/assets/properties-C78fOPTZ.js +0 -1
  221. package/inspector/dist/assets/protobuf-ChK-085T.js +0 -1
  222. package/inspector/dist/assets/pug-DeIclll2.js +0 -1
  223. package/inspector/dist/assets/puppet-DMA9R1ak.js +0 -1
  224. package/inspector/dist/assets/python-BuPzkPfP.js +0 -1
  225. package/inspector/dist/assets/q-pXgVlZs6.js +0 -1
  226. package/inspector/dist/assets/r-B6wPVr8A.js +0 -1
  227. package/inspector/dist/assets/rpm-CTu-6PCP.js +0 -1
  228. package/inspector/dist/assets/ruby-BK5aLJev.js +0 -1
  229. package/inspector/dist/assets/scheme-C41bIUwD.js +0 -1
  230. package/inspector/dist/assets/shell-CjFT_Tl9.js +0 -1
  231. package/inspector/dist/assets/sieve-C3Gn_uJK.js +0 -1
  232. package/inspector/dist/assets/simple-mode-GW_nhZxv.js +0 -1
  233. package/inspector/dist/assets/smalltalk-CnHTOXQT.js +0 -1
  234. package/inspector/dist/assets/solr-DehyRSwq.js +0 -1
  235. package/inspector/dist/assets/sparql-DkYu6x3z.js +0 -1
  236. package/inspector/dist/assets/spreadsheet-BCZA_wO0.js +0 -1
  237. package/inspector/dist/assets/sql-D0XecflT.js +0 -1
  238. package/inspector/dist/assets/stex-C3f8Ysf7.js +0 -1
  239. package/inspector/dist/assets/stylus-B533Al4x.js +0 -1
  240. package/inspector/dist/assets/swift-BzpIVaGY.js +0 -1
  241. package/inspector/dist/assets/tcl-DVfN8rqt.js +0 -1
  242. package/inspector/dist/assets/textile-CnDTJFAw.js +0 -1
  243. package/inspector/dist/assets/tiddlywiki-DO-Gjzrf.js +0 -1
  244. package/inspector/dist/assets/tiki-DGYXhP31.js +0 -1
  245. package/inspector/dist/assets/toml-Bm5Em-hy.js +0 -1
  246. package/inspector/dist/assets/troff-wAsdV37c.js +0 -1
  247. package/inspector/dist/assets/ttcn-CfJYG6tj.js +0 -1
  248. package/inspector/dist/assets/ttcn-cfg-B9xdYoR4.js +0 -1
  249. package/inspector/dist/assets/turtle-B1tBg_DP.js +0 -1
  250. package/inspector/dist/assets/vb-CmGdzxic.js +0 -1
  251. package/inspector/dist/assets/vbscript-BuJXcnF6.js +0 -1
  252. package/inspector/dist/assets/velocity-D8B20fx6.js +0 -1
  253. package/inspector/dist/assets/verilog-C6RDOZhf.js +0 -1
  254. package/inspector/dist/assets/vhdl-lSbBsy5d.js +0 -1
  255. package/inspector/dist/assets/webidl-ZXfAyPTL.js +0 -1
  256. package/inspector/dist/assets/xquery-DzFWVndE.js +0 -1
  257. package/inspector/dist/assets/yacas-BJ4BC0dw.js +0 -1
  258. package/inspector/dist/assets/z80-Hz9HOZM7.js +0 -1
@@ -6,7 +6,7 @@ import { resolveProject } from "../config.js";
6
6
  import { listRuns, getRun, readRunFile } from "./runs.js";
7
7
  import { listWorkflows, getWorkflow } from "./workflows.js";
8
8
  import { dockerStatus, triggerRun, stopRun } from "./runner.js";
9
- import { cancelChat, createChat, deleteChat, disposeAllBackends, getChat, listChats, postMessage, resolvePermission, subscribeChat, } from "./chat/sessions.js";
9
+ import { cancelChat, createChat, deleteChat, disposeAllBackends, getChat, listChats, postMessage, resolvePermission, setChatVibeable, subscribeChat, } from "./chat/sessions.js";
10
10
  import { bundleDetail, conceptDetail, createBundle, knowledgeIndex, putConcept, verifyFromUi, } from "./knowledge.js";
11
11
  import { deleteAgent, getAgent, listAgents, saveAgent, setAgentArchived, agentsRoot, } from "./agents.js";
12
12
  import { deleteAgentSkill, getSkill, listAgentSkills, listSkills, readSkill, saveAgentSkill, skillsRoot, } from "./skills.js";
@@ -14,6 +14,7 @@ import { discoverWorkspaces, forgetProject, listWorkspacesDetailed, markProjectS
14
14
  import { gitCommit, gitDiff, gitFetch, gitPull, gitPush, gitStatus, startGitSync, } from "./git.js";
15
15
  import { getSettings, saveSettings } from "./settings.js";
16
16
  import { addRepo, listRepos, openRepos, removeRepo, updateRepo } from "./repos.js";
17
+ import { createVibeable, deleteVibeable, disposeAllDevs, listVibeables, openVibeables, resolveVibeable, serveVibeable, startDev, stopDev, subscribeVibeable, vibeableStatus, } from "./vibeables.js";
17
18
  import { searchAgents } from "./search.js";
18
19
  import { deleteRoutine, routineStatuses, runRoutineNow, saveRoutine, startRoutineScheduler, } from "./routines.js";
19
20
  /**
@@ -219,6 +220,7 @@ async function handleApi(req, res, url) {
219
220
  projectRootLabel: tildify(project?.root ?? getProjectRoot()),
220
221
  git: (project?.config.git && project.config.git.enabled !== false) === true,
221
222
  repos: (project?.config.repos && project.config.repos.enabled !== false) === true,
223
+ vibeables: (project?.config.vibeables && project.config.vibeables.enabled !== false) === true,
222
224
  switcher,
223
225
  });
224
226
  }
@@ -273,6 +275,75 @@ async function handleApi(req, res, url) {
273
275
  return json(res, { error: err.message }, 400);
274
276
  }
275
277
  }
278
+ // GET /api/vibeables — every app folder under the vibeables root | POST {name} — create one with the starter
279
+ if (seg.length === 2 && seg[1] === "vibeables") {
280
+ if (method === "GET")
281
+ return json(res, await listVibeables());
282
+ if (method === "POST") {
283
+ if ((await openVibeables()).off)
284
+ return json(res, { error: "vibeables are off" }, 409);
285
+ try {
286
+ const body = JSON.parse(await readBody(req));
287
+ return json(res, await createVibeable(typeof body.name === "string" ? body.name : ""), 201);
288
+ }
289
+ catch (err) {
290
+ return json(res, { error: err.message }, 400);
291
+ }
292
+ }
293
+ }
294
+ const vibeableError = (err) => {
295
+ const msg = err.message;
296
+ return [/^no vibeable/.test(msg) ? 404 : /are off/.test(msg) ? 409 : 400, { error: msg }];
297
+ };
298
+ // GET /api/vibeables/<slug> — how the app previews: mode, static url, dev server state | DELETE — remove the folder
299
+ if (seg.length === 3 && seg[1] === "vibeables") {
300
+ try {
301
+ if (method === "GET")
302
+ return json(res, await vibeableStatus(seg[2]));
303
+ if (method === "DELETE") {
304
+ await deleteVibeable(seg[2]);
305
+ return json(res, { ok: true });
306
+ }
307
+ }
308
+ catch (err) {
309
+ const [status, body] = vibeableError(err);
310
+ return json(res, body, status);
311
+ }
312
+ }
313
+ // GET /api/vibeables/<slug>/events — SSE: file changes (debounced) and dev-server state
314
+ if (seg.length === 4 && seg[1] === "vibeables" && seg[3] === "events" && method === "GET") {
315
+ let dir;
316
+ try {
317
+ dir = (await resolveVibeable(seg[2])).dir;
318
+ }
319
+ catch (err) {
320
+ const [status, body] = vibeableError(err);
321
+ return json(res, body, status);
322
+ }
323
+ res.writeHead(200, { "content-type": "text/event-stream", "cache-control": "no-store", connection: "keep-alive" });
324
+ res.write(":ok\n\n");
325
+ const unsubscribe = subscribeVibeable(seg[2], dir, (ev) => res.write(`data: ${JSON.stringify(ev)}\n\n`));
326
+ const heartbeat = setInterval(() => res.write(":hb\n\n"), 25_000);
327
+ req.on("close", () => {
328
+ clearInterval(heartbeat);
329
+ unsubscribe();
330
+ });
331
+ return;
332
+ }
333
+ // POST /api/vibeables/<slug>/dev/{start,stop} — the app's dev command
334
+ if (seg.length === 5 && seg[1] === "vibeables" && seg[3] === "dev" && method === "POST") {
335
+ try {
336
+ if (seg[4] === "start")
337
+ return json(res, await startDev(seg[2]));
338
+ if (seg[4] === "stop")
339
+ return json(res, await stopDev(seg[2]));
340
+ return json(res, { error: "not found" }, 404);
341
+ }
342
+ catch (err) {
343
+ const [status, body] = vibeableError(err);
344
+ return json(res, body, status);
345
+ }
346
+ }
276
347
  // POST /api/repos/<slug>/update — fetch, fast-forward when clean
277
348
  if (seg.length === 4 && seg[1] === "repos" && seg[3] === "update" && method === "POST") {
278
349
  try {
@@ -380,6 +451,7 @@ async function handleApi(req, res, url) {
380
451
  json(res, { ok: true });
381
452
  setTimeout(() => {
382
453
  disposeAllBackends();
454
+ disposeAllDevs();
383
455
  process.exit(RESTART_EXIT_CODE);
384
456
  }, 150);
385
457
  return;
@@ -770,6 +842,18 @@ async function handleApi(req, res, url) {
770
842
  });
771
843
  return;
772
844
  }
845
+ // POST /api/chats/:id/vibeable {slug | null} — open an app in the chat's preview pane (cwd follows), or close it
846
+ if (seg.length === 4 && seg[1] === "chats" && seg[3] === "vibeable" && method === "POST") {
847
+ try {
848
+ const body = JSON.parse((await readBody(req)) || "{}");
849
+ const slug = body.slug == null || body.slug === "" ? null : String(body.slug);
850
+ const result = await setChatVibeable(seg[2], slug);
851
+ return result.error ? json(res, { error: result.error }, result.status ?? 400) : json(res, result.meta);
852
+ }
853
+ catch (err) {
854
+ return json(res, { error: err.message }, 400);
855
+ }
856
+ }
773
857
  // POST /api/chats/:id/{message,permission,cancel}
774
858
  if (seg.length === 4 && seg[1] === "chats" && method === "POST") {
775
859
  let body = {};
@@ -840,6 +924,7 @@ export function startInspector(opts) {
840
924
  for (const sig of ["SIGINT", "SIGTERM"]) {
841
925
  process.once(sig, () => {
842
926
  disposeAllBackends();
927
+ disposeAllDevs();
843
928
  unregisterInstance();
844
929
  markProjectStopped();
845
930
  process.exit(sig === "SIGINT" ? 130 : 143);
@@ -847,6 +932,7 @@ export function startInspector(opts) {
847
932
  }
848
933
  process.once("exit", (code) => {
849
934
  disposeAllBackends();
935
+ disposeAllDevs();
850
936
  unregisterInstance();
851
937
  // A self-restart (new version) is not a stop — the project stays "running".
852
938
  if (code !== RESTART_EXIT_CODE)
@@ -859,6 +945,9 @@ export function startInspector(opts) {
859
945
  return json(res, { error: "unexpected Host header" }, 421);
860
946
  if (url.pathname.startsWith("/api/"))
861
947
  await handleApi(req, res, url);
948
+ // /vibeables/<slug>/… is an app's own files, served for the preview pane.
949
+ else if (url.pathname === "/vibeables" || url.pathname.startsWith("/vibeables/"))
950
+ await serveVibeable(req, res, url);
862
951
  else
863
952
  await serveStatic(res, opts.staticDir, url.pathname);
864
953
  }
@@ -1,7 +1,7 @@
1
1
  import { type ProjectConfig, type SwitcherEntry } from "../config.js";
2
2
  /**
3
3
  * Workspace settings: read kraftwerk.yml for the UI and write the
4
- * UI-editable subset (name, icon, switcher, git, repos) back. Edits go through the
4
+ * UI-editable subset (name, icon, switcher, git, repos, vibeables) back. Edits go through the
5
5
  * yaml Document API so comments and every other key survive untouched;
6
6
  * a missing kraftwerk.yml is created at the project root on first save.
7
7
  */
@@ -28,6 +28,8 @@ export interface SaveSettingsInput {
28
28
  git?: GitSettingsInput;
29
29
  /** Omitted = untouched. Same rules as git: off with defaults = no block. */
30
30
  repos?: ReposSettingsInput;
31
+ /** Omitted = untouched. Same shape and rules as repos. */
32
+ vibeables?: ReposSettingsInput;
31
33
  }
32
34
  export interface ReposSettingsInput {
33
35
  enabled: boolean;
@@ -1,7 +1,8 @@
1
1
  import { promises as fs } from "node:fs";
2
2
  import path from "node:path";
3
3
  import { parseDocument } from "yaml";
4
- import { ignoreEntryFor, REPOS_DEFAULT_ROOT, resolveProject } from "../config.js";
4
+ import { ignoreEntryFor, REPOS_DEFAULT_ROOT, resolveProject, VIBEABLES_DEFAULT_ROOT } from "../config.js";
5
+ import { ensureVibeablesRoot } from "./vibeables.js";
5
6
  import { getProjectRoot } from "./context.js";
6
7
  import { ensureReposRoot } from "./repos.js";
7
8
  const GIT_DEFAULTS = { remote: "origin", interval: 300, autosync: "pull" };
@@ -70,18 +71,19 @@ function cleanGit(value) {
70
71
  return null;
71
72
  return { enabled: false, ...out };
72
73
  }
73
- /** The repos block to write; null when the feature is off and nothing else is set. */
74
- function cleanRepos(value, projectRoot) {
74
+ /** The repos or vibeables block to write; null when the feature is off and nothing else is set. */
75
+ function cleanRootBlock(block, value, projectRoot) {
75
76
  if (typeof value !== "object" || value === null)
76
- throw new Error("repos must be an object");
77
+ throw new Error(`${block} must be an object`);
77
78
  if (typeof value.enabled !== "boolean")
78
- throw new Error("repos.enabled must be true or false");
79
+ throw new Error(`${block}.enabled must be true or false`);
79
80
  const out = {};
80
81
  const root = typeof value.root === "string" ? value.root.trim().replace(/\/+$/, "") : "";
81
82
  if (root && !ignoreEntryFor(projectRoot, root)) {
82
- throw new Error('repos.root must be a directory inside the project (not ".", ".." or an absolute path outside it)');
83
+ throw new Error(`${block}.root must be a directory inside the project (not ".", ".." or an absolute path outside it)`);
83
84
  }
84
- if (root && root !== REPOS_DEFAULT_ROOT)
85
+ const dflt = block === "repos" ? REPOS_DEFAULT_ROOT : VIBEABLES_DEFAULT_ROOT;
86
+ if (root && root !== dflt)
85
87
  out.root = root;
86
88
  if (value.enabled)
87
89
  return out;
@@ -128,16 +130,25 @@ export async function saveSettings(input) {
128
130
  doc.set("git", git);
129
131
  }
130
132
  if (input.repos !== undefined) {
131
- const repos = cleanRepos(input.repos, project.root);
133
+ const repos = cleanRootBlock("repos", input.repos, project.root);
132
134
  if (repos === null)
133
135
  doc.delete("repos");
134
136
  else
135
137
  doc.set("repos", repos);
136
138
  }
139
+ if (input.vibeables !== undefined) {
140
+ const vibeables = cleanRootBlock("vibeables", input.vibeables, project.root);
141
+ if (vibeables === null)
142
+ doc.delete("vibeables");
143
+ else
144
+ doc.set("vibeables", vibeables);
145
+ }
137
146
  await fs.writeFile(configPath, doc.toString());
138
147
  // Turning repositories on prepares the folder so the first clone and the
139
148
  // workspace git both find it in the right state.
140
149
  if (input.repos?.enabled)
141
150
  await ensureReposRoot().catch(() => { });
151
+ if (input.vibeables?.enabled)
152
+ await ensureVibeablesRoot().catch(() => { });
142
153
  return getSettings();
143
154
  }
@@ -0,0 +1,152 @@
1
+ import http from "node:http";
2
+ import { type Project } from "../config.js";
3
+ /**
4
+ * Vibeables: small applications built live in a chat. The agent edits the
5
+ * folder, the user watches the result in a preview pane next to the thread
6
+ * — lovable-style, but for whatever ad-hoc software the user needs: a
7
+ * dashboard, a slideshow, a tracker with its own backend.
8
+ *
9
+ * A vibeable is one folder under the vibeables root (`vibeables.root` in
10
+ * kraftwerk.yml, default kraftwerk-data/vibeables/). Like agents and knowledge it is part
11
+ * of the workspace: versioned by the workspace git, no repository of its
12
+ * own. The folder is the registry — whatever directory is under the root
13
+ * is a vibeable, whoever created it.
14
+ *
15
+ * Two ways to run one, chosen by the folder itself:
16
+ *
17
+ * - static (default): the inspector serves the folder at /vibeables/<slug>/
18
+ * — index.html in, no build step. A file watcher tells the pane to reload.
19
+ * - dev: `vibeable.yml` names a `dev` command (npm run dev, node server.js).
20
+ * The inspector spawns it with PORT set and the pane embeds that server;
21
+ * anything with a build tool, a backend or a database lives here.
22
+ *
23
+ * Static files go out under a CSP sandbox: the code is what the agent
24
+ * wrote, and it must not act on the inspector API as the user. Nothing here
25
+ * has a shell in the middle except the dev command, which is the user's own
26
+ * choice in their own workspace.
27
+ */
28
+ export interface VibeableConfig {
29
+ /** Command that starts a dev server; gets PORT in its environment. */
30
+ dev?: string;
31
+ /** Port the dev command listens on. Default: a free port, passed as PORT. */
32
+ port?: number;
33
+ /** Folder served in static mode, relative to the vibeable. Default: the vibeable itself. */
34
+ dir?: string;
35
+ }
36
+ export interface VibeableInfo {
37
+ /** Folder name under the root; the id everywhere. */
38
+ slug: string;
39
+ /** Absolute path of the folder. */
40
+ path: string;
41
+ /** index.html exists in the served folder, so the static preview renders something. */
42
+ hasIndex: boolean;
43
+ /** Dev command from vibeable.yml, when declared. */
44
+ dev?: string;
45
+ /** Set when vibeable.yml exists but is unusable. */
46
+ configError?: string;
47
+ /** Newest change inside the folder (node_modules and dot entries excluded). */
48
+ updatedAt?: string;
49
+ }
50
+ export interface VibeablesView {
51
+ enabled: boolean;
52
+ root?: string;
53
+ vibeables: VibeableInfo[];
54
+ /** Set when the feature is off or the root cannot be read. */
55
+ error?: string;
56
+ }
57
+ export interface VibeableDev {
58
+ command: string;
59
+ port: number;
60
+ /** The process is alive. */
61
+ running: boolean;
62
+ /** The server answered HTTP on its port. */
63
+ ready: boolean;
64
+ pid?: number;
65
+ startedAt: string;
66
+ /** Set once the process ended. */
67
+ exitCode?: number | null;
68
+ /** Last lines of stdout + stderr. */
69
+ log: string[];
70
+ }
71
+ export interface VibeableStatus {
72
+ slug: string;
73
+ /** Absolute folder path. */
74
+ path: string;
75
+ /** Absolute folder served in static mode. */
76
+ dir: string;
77
+ /** What the pane shows right now: the dev server once it runs, the static folder otherwise. */
78
+ mode: "static" | "dev";
79
+ /** Static preview url, relative to the inspector. */
80
+ url: string;
81
+ config: VibeableConfig;
82
+ /** Set when vibeable.yml exists but is unusable; static mode still works. */
83
+ configError?: string;
84
+ dev?: VibeableDev;
85
+ }
86
+ export type VibeableEvent = {
87
+ type: "change";
88
+ files: string[];
89
+ } | {
90
+ type: "dev";
91
+ dev: VibeableDev;
92
+ } | {
93
+ type: "error";
94
+ message: string;
95
+ };
96
+ export declare const VIBEABLE_CONFIG_FILE = "vibeable.yml";
97
+ export declare function safeVibeableSlug(slug: string): string;
98
+ /** The files a fresh vibeable starts with: a page that renders, and the config template. */
99
+ export declare function vibeableStarter(name: string): Record<string, string>;
100
+ /** Resolve the project and its vibeables block. `off` when the feature is not on. */
101
+ export declare function openVibeables(): Promise<{
102
+ project?: Project;
103
+ root?: string;
104
+ off?: boolean;
105
+ error?: string;
106
+ }>;
107
+ /** Make sure the root exists; runs when the feature is switched on. */
108
+ export declare function ensureVibeablesRoot(): Promise<void>;
109
+ interface Resolved {
110
+ slug: string;
111
+ dir: string;
112
+ servedDir: string;
113
+ config: VibeableConfig;
114
+ configError?: string;
115
+ }
116
+ /** The folder behind a slug, or throw `no vibeable "<slug>"`. */
117
+ export declare function resolveVibeable(slug: string): Promise<Resolved>;
118
+ /** Every folder under the root, alphabetically. Dot folders and odd names are skipped. */
119
+ export declare function listVibeables(): Promise<VibeablesView>;
120
+ /**
121
+ * Create <root>/<name> with the starter files. The folder is claimed with a
122
+ * plain mkdir first: it fails when anything is there already, so two
123
+ * creates of the same name cannot both win.
124
+ */
125
+ export declare function createVibeable(name: string): Promise<VibeableInfo>;
126
+ /** Delete a vibeable folder. Its history stays in the workspace git. */
127
+ export declare function deleteVibeable(slug: string): Promise<void>;
128
+ export declare function vibeableStatus(slug: string): Promise<VibeableStatus>;
129
+ /**
130
+ * GET /vibeables/<slug>/<file>. Dot segments (.env, .git) are never served;
131
+ * a directory answers with its index.html, and a directory url without the
132
+ * trailing slash redirects so the page's relative links resolve.
133
+ */
134
+ export declare function serveVibeable(req: http.IncomingMessage, res: http.ServerResponse, url: URL): Promise<void>;
135
+ /**
136
+ * Stream a vibeable's events: file changes (debounced, node_modules and
137
+ * the like excluded) and dev-server state. The watcher exists while
138
+ * someone listens. `fs.watch` recursive covers macOS and Linux on Node 20+;
139
+ * where it cannot watch, the pane still has its manual reload.
140
+ */
141
+ export declare function subscribeVibeable(slug: string, dir: string, fn: (ev: VibeableEvent) => void): () => void;
142
+ /**
143
+ * Start the vibeable's dev command. Idempotent while it runs. The child
144
+ * leads its own process group so stopping it also stops what it spawned
145
+ * (npm → vite → esbuild).
146
+ */
147
+ export declare function startDev(slug: string): Promise<VibeableStatus>;
148
+ /** SIGTERM the dev process group, SIGKILL what is still there after 3 s. */
149
+ export declare function stopDev(slug: string): Promise<VibeableStatus>;
150
+ /** Server shutdown: no dev server may outlive the inspector. */
151
+ export declare function disposeAllDevs(): void;
152
+ export {};