synabun 1.3.0 → 2.0.0-beta

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 (1153) hide show
  1. package/CHANGELOG.md +197 -662
  2. package/LICENSE-COMMERCIAL.md +33 -0
  3. package/NOTICE +17 -0
  4. package/README.md +175 -853
  5. package/THIRD-PARTY-LICENSES.md +131 -0
  6. package/benchmarks/browser-live-results.json +79 -0
  7. package/benchmarks/browser-v2-results.json +258 -0
  8. package/benchmarks/fixtures/browser/README.md +57 -0
  9. package/benchmarks/fixtures/browser/page-state.json +132 -0
  10. package/benchmarks/fixtures/browser/social.json +92 -0
  11. package/benchmarks/fixtures/browser/target.json +319 -0
  12. package/benchmarks/fixtures/desktop/README.md +58 -0
  13. package/benchmarks/fixtures/desktop/abstention.json +59 -0
  14. package/benchmarks/fixtures/desktop/adversarial.json +22 -0
  15. package/benchmarks/fixtures/desktop/forbidden.json +93 -0
  16. package/benchmarks/fixtures/desktop/generate.mjs +1023 -0
  17. package/benchmarks/fixtures/desktop/target.json +136 -0
  18. package/bin/synabun.js +30 -0
  19. package/docs/browser-v2.md +109 -0
  20. package/docs/hook-integrity.md +89 -0
  21. package/docs/judgments.md +182 -0
  22. package/docs/style-guide.md +246 -0
  23. package/docs/whatsapp.md +325 -0
  24. package/hooks/claude-code/post-plan.mjs +613 -391
  25. package/hooks/claude-code/post-remember.mjs +246 -122
  26. package/hooks/claude-code/pre-compact.mjs +171 -110
  27. package/hooks/claude-code/pre-task.mjs +133 -0
  28. package/hooks/claude-code/pre-websearch.mjs +15 -4
  29. package/hooks/claude-code/prompt-origin.mjs +94 -0
  30. package/hooks/claude-code/prompt-submit.mjs +1244 -861
  31. package/hooks/claude-code/session-start.mjs +114 -156
  32. package/hooks/claude-code/shared.mjs +1228 -368
  33. package/hooks/claude-code/state.mjs +167 -0
  34. package/hooks/claude-code/stop.mjs +515 -140
  35. package/hooks/claude-code/subagent-start.mjs +154 -0
  36. package/hooks/claude-code/subagent-stop.mjs +102 -0
  37. package/hooks/claude-code/task-gate.mjs +150 -0
  38. package/lib/claude-hooks.js +84 -0
  39. package/lib/claude-usage-audit.js +141 -0
  40. package/lib/client-config-repair.js +144 -0
  41. package/lib/data-home-migration.js +498 -0
  42. package/lib/first-launch-protection.js +240 -0
  43. package/lib/paths.d.ts +21 -0
  44. package/lib/paths.js +103 -0
  45. package/mcp-server/dist/config.d.ts +22 -0
  46. package/mcp-server/dist/config.d.ts.map +1 -0
  47. package/mcp-server/dist/config.js +109 -0
  48. package/mcp-server/dist/config.js.map +1 -0
  49. package/mcp-server/dist/http.d.ts +30 -0
  50. package/mcp-server/dist/http.d.ts.map +1 -0
  51. package/mcp-server/dist/http.js +276 -0
  52. package/mcp-server/dist/http.js.map +1 -0
  53. package/mcp-server/dist/index.d.ts +48 -0
  54. package/mcp-server/dist/index.d.ts.map +1 -0
  55. package/mcp-server/dist/index.js +538 -0
  56. package/mcp-server/dist/index.js.map +1 -0
  57. package/mcp-server/dist/preload-http.d.ts +3 -0
  58. package/mcp-server/dist/preload-http.d.ts.map +1 -0
  59. package/mcp-server/dist/preload-http.js +28 -0
  60. package/mcp-server/dist/preload-http.js.map +1 -0
  61. package/mcp-server/dist/preload.d.ts +3 -0
  62. package/mcp-server/dist/preload.d.ts.map +1 -0
  63. package/mcp-server/dist/preload.js +32 -0
  64. package/mcp-server/dist/preload.js.map +1 -0
  65. package/mcp-server/dist/scripts/migrate-qdrant-to-sqlite.d.ts +19 -0
  66. package/mcp-server/dist/scripts/migrate-qdrant-to-sqlite.d.ts.map +1 -0
  67. package/mcp-server/dist/scripts/migrate-qdrant-to-sqlite.js +403 -0
  68. package/mcp-server/dist/scripts/migrate-qdrant-to-sqlite.js.map +1 -0
  69. package/mcp-server/dist/scripts/setup-embeddings.d.ts +3 -0
  70. package/mcp-server/dist/scripts/setup-embeddings.d.ts.map +1 -0
  71. package/mcp-server/dist/scripts/setup-embeddings.js +15 -0
  72. package/mcp-server/dist/scripts/setup-embeddings.js.map +1 -0
  73. package/mcp-server/dist/services/assistant-judgments.d.ts +79 -0
  74. package/mcp-server/dist/services/assistant-judgments.d.ts.map +1 -0
  75. package/mcp-server/dist/services/assistant-judgments.js +128 -0
  76. package/mcp-server/dist/services/assistant-judgments.js.map +1 -0
  77. package/mcp-server/dist/services/browser-assist-gate.d.ts +314 -0
  78. package/mcp-server/dist/services/browser-assist-gate.d.ts.map +1 -0
  79. package/mcp-server/dist/services/browser-assist-gate.js +344 -0
  80. package/mcp-server/dist/services/browser-assist-gate.js.map +1 -0
  81. package/mcp-server/dist/services/browser-assist.d.ts +104 -0
  82. package/mcp-server/dist/services/browser-assist.d.ts.map +1 -0
  83. package/mcp-server/dist/services/browser-assist.js +282 -0
  84. package/mcp-server/dist/services/browser-assist.js.map +1 -0
  85. package/mcp-server/dist/services/browser-bench.d.ts +772 -0
  86. package/mcp-server/dist/services/browser-bench.d.ts.map +1 -0
  87. package/mcp-server/dist/services/browser-bench.js +424 -0
  88. package/mcp-server/dist/services/browser-bench.js.map +1 -0
  89. package/mcp-server/dist/services/browser-judgments.d.ts +196 -0
  90. package/mcp-server/dist/services/browser-judgments.d.ts.map +1 -0
  91. package/mcp-server/dist/services/browser-judgments.js +363 -0
  92. package/mcp-server/dist/services/browser-judgments.js.map +1 -0
  93. package/mcp-server/dist/services/browser-risk.d.ts +166 -0
  94. package/mcp-server/dist/services/browser-risk.d.ts.map +1 -0
  95. package/mcp-server/dist/services/browser-risk.js +458 -0
  96. package/mcp-server/dist/services/browser-risk.js.map +1 -0
  97. package/mcp-server/dist/services/categories.d.ts +61 -0
  98. package/mcp-server/dist/services/categories.d.ts.map +1 -0
  99. package/mcp-server/dist/services/categories.js +377 -0
  100. package/mcp-server/dist/services/categories.js.map +1 -0
  101. package/mcp-server/dist/services/codex-config-heal.d.ts +49 -0
  102. package/mcp-server/dist/services/codex-config-heal.d.ts.map +1 -0
  103. package/mcp-server/dist/services/codex-config-heal.js +346 -0
  104. package/mcp-server/dist/services/codex-config-heal.js.map +1 -0
  105. package/mcp-server/dist/services/desktop-assist-gate.d.ts +198 -0
  106. package/mcp-server/dist/services/desktop-assist-gate.d.ts.map +1 -0
  107. package/mcp-server/dist/services/desktop-assist-gate.js +202 -0
  108. package/mcp-server/dist/services/desktop-assist-gate.js.map +1 -0
  109. package/mcp-server/dist/services/desktop-assist.d.ts +104 -0
  110. package/mcp-server/dist/services/desktop-assist.d.ts.map +1 -0
  111. package/mcp-server/dist/services/desktop-assist.js +266 -0
  112. package/mcp-server/dist/services/desktop-assist.js.map +1 -0
  113. package/mcp-server/dist/services/desktop-bench.d.ts +553 -0
  114. package/mcp-server/dist/services/desktop-bench.d.ts.map +1 -0
  115. package/mcp-server/dist/services/desktop-bench.js +311 -0
  116. package/mcp-server/dist/services/desktop-bench.js.map +1 -0
  117. package/mcp-server/dist/services/desktop-client.d.ts +23 -0
  118. package/mcp-server/dist/services/desktop-client.d.ts.map +1 -0
  119. package/mcp-server/dist/services/desktop-client.js +79 -0
  120. package/mcp-server/dist/services/desktop-client.js.map +1 -0
  121. package/mcp-server/dist/services/desktop-judgments.d.ts +125 -0
  122. package/mcp-server/dist/services/desktop-judgments.d.ts.map +1 -0
  123. package/mcp-server/dist/services/desktop-judgments.js +177 -0
  124. package/mcp-server/dist/services/desktop-judgments.js.map +1 -0
  125. package/mcp-server/dist/services/desktop-risk.d.ts +283 -0
  126. package/mcp-server/dist/services/desktop-risk.d.ts.map +1 -0
  127. package/mcp-server/dist/services/desktop-risk.js +605 -0
  128. package/mcp-server/dist/services/desktop-risk.js.map +1 -0
  129. package/mcp-server/dist/services/discord.d.ts +112 -0
  130. package/mcp-server/dist/services/discord.d.ts.map +1 -0
  131. package/mcp-server/dist/services/discord.js +477 -0
  132. package/mcp-server/dist/services/discord.js.map +1 -0
  133. package/mcp-server/dist/services/edit-stale.d.ts +81 -0
  134. package/mcp-server/dist/services/edit-stale.d.ts.map +1 -0
  135. package/mcp-server/dist/services/edit-stale.js +358 -0
  136. package/mcp-server/dist/services/edit-stale.js.map +1 -0
  137. package/mcp-server/dist/services/embedding-service.d.ts +16 -0
  138. package/mcp-server/dist/services/embedding-service.d.ts.map +1 -0
  139. package/mcp-server/dist/services/embedding-service.js +126 -0
  140. package/mcp-server/dist/services/embedding-service.js.map +1 -0
  141. package/mcp-server/dist/services/embedding-worker.d.ts +2 -0
  142. package/mcp-server/dist/services/embedding-worker.d.ts.map +1 -0
  143. package/mcp-server/dist/services/embedding-worker.js +52 -0
  144. package/mcp-server/dist/services/embedding-worker.js.map +1 -0
  145. package/mcp-server/dist/services/fb-regions.d.ts +71 -0
  146. package/mcp-server/dist/services/fb-regions.d.ts.map +1 -0
  147. package/mcp-server/dist/services/fb-regions.js +211 -0
  148. package/mcp-server/dist/services/fb-regions.js.map +1 -0
  149. package/mcp-server/dist/services/file-checksums.d.ts +22 -0
  150. package/mcp-server/dist/services/file-checksums.d.ts.map +1 -0
  151. package/mcp-server/dist/services/file-checksums.js +55 -0
  152. package/mcp-server/dist/services/file-checksums.js.map +1 -0
  153. package/mcp-server/dist/services/file-excerpt.d.ts +24 -0
  154. package/mcp-server/dist/services/file-excerpt.d.ts.map +1 -0
  155. package/mcp-server/dist/services/file-excerpt.js +65 -0
  156. package/mcp-server/dist/services/file-excerpt.js.map +1 -0
  157. package/mcp-server/dist/services/identity.d.ts +124 -0
  158. package/mcp-server/dist/services/identity.d.ts.map +1 -0
  159. package/mcp-server/dist/services/identity.js +241 -0
  160. package/mcp-server/dist/services/identity.js.map +1 -0
  161. package/mcp-server/dist/services/local-embeddings.d.ts +2 -0
  162. package/mcp-server/dist/services/local-embeddings.d.ts.map +1 -0
  163. package/mcp-server/dist/services/local-embeddings.js +3 -0
  164. package/mcp-server/dist/services/local-embeddings.js.map +1 -0
  165. package/mcp-server/dist/services/memory-client.d.ts +4 -0
  166. package/mcp-server/dist/services/memory-client.d.ts.map +1 -0
  167. package/mcp-server/dist/services/memory-client.js +27 -0
  168. package/mcp-server/dist/services/memory-client.js.map +1 -0
  169. package/mcp-server/dist/services/memory-judge-backfill.d.ts +135 -0
  170. package/mcp-server/dist/services/memory-judge-backfill.d.ts.map +1 -0
  171. package/mcp-server/dist/services/memory-judge-backfill.js +510 -0
  172. package/mcp-server/dist/services/memory-judge-backfill.js.map +1 -0
  173. package/mcp-server/dist/services/memory-judgments.d.ts +362 -0
  174. package/mcp-server/dist/services/memory-judgments.d.ts.map +1 -0
  175. package/mcp-server/dist/services/memory-judgments.js +674 -0
  176. package/mcp-server/dist/services/memory-judgments.js.map +1 -0
  177. package/mcp-server/dist/services/memory-maintenance.d.ts +108 -0
  178. package/mcp-server/dist/services/memory-maintenance.d.ts.map +1 -0
  179. package/mcp-server/dist/services/memory-maintenance.js +403 -0
  180. package/mcp-server/dist/services/memory-maintenance.js.map +1 -0
  181. package/mcp-server/dist/services/memory-retrieval.d.ts +66 -0
  182. package/mcp-server/dist/services/memory-retrieval.d.ts.map +1 -0
  183. package/mcp-server/dist/services/memory-retrieval.js +412 -0
  184. package/mcp-server/dist/services/memory-retrieval.js.map +1 -0
  185. package/mcp-server/dist/services/memory-schema.d.ts +16 -0
  186. package/mcp-server/dist/services/memory-schema.d.ts.map +1 -0
  187. package/mcp-server/dist/services/memory-schema.js +282 -0
  188. package/mcp-server/dist/services/memory-schema.js.map +1 -0
  189. package/mcp-server/dist/services/memory-sessions.d.ts +24 -0
  190. package/mcp-server/dist/services/memory-sessions.d.ts.map +1 -0
  191. package/mcp-server/dist/services/memory-sessions.js +110 -0
  192. package/mcp-server/dist/services/memory-sessions.js.map +1 -0
  193. package/mcp-server/dist/services/memory-triage.d.ts +60 -0
  194. package/mcp-server/dist/services/memory-triage.d.ts.map +1 -0
  195. package/mcp-server/dist/services/memory-triage.js +189 -0
  196. package/mcp-server/dist/services/memory-triage.js.map +1 -0
  197. package/mcp-server/dist/services/memory-verification.d.ts +24 -0
  198. package/mcp-server/dist/services/memory-verification.d.ts.map +1 -0
  199. package/mcp-server/dist/services/memory-verification.js +92 -0
  200. package/mcp-server/dist/services/memory-verification.js.map +1 -0
  201. package/mcp-server/dist/services/memory-writer.d.ts +26 -0
  202. package/mcp-server/dist/services/memory-writer.d.ts.map +1 -0
  203. package/mcp-server/dist/services/memory-writer.js +126 -0
  204. package/mcp-server/dist/services/memory-writer.js.map +1 -0
  205. package/mcp-server/dist/services/neural-interface.d.ts +439 -0
  206. package/mcp-server/dist/services/neural-interface.d.ts.map +1 -0
  207. package/mcp-server/dist/services/neural-interface.js +1135 -0
  208. package/mcp-server/dist/services/neural-interface.js.map +1 -0
  209. package/mcp-server/dist/services/profiles.d.ts +120 -0
  210. package/mcp-server/dist/services/profiles.d.ts.map +1 -0
  211. package/mcp-server/dist/services/profiles.js +387 -0
  212. package/mcp-server/dist/services/profiles.js.map +1 -0
  213. package/mcp-server/dist/services/secret-gate.d.ts +29 -0
  214. package/mcp-server/dist/services/secret-gate.d.ts.map +1 -0
  215. package/mcp-server/dist/services/secret-gate.js +43 -0
  216. package/mcp-server/dist/services/secret-gate.js.map +1 -0
  217. package/mcp-server/dist/services/server-instructions.d.ts +10 -0
  218. package/mcp-server/dist/services/server-instructions.d.ts.map +1 -0
  219. package/mcp-server/dist/services/server-instructions.js +101 -0
  220. package/mcp-server/dist/services/server-instructions.js.map +1 -0
  221. package/mcp-server/dist/services/sqlite.d.ts +235 -0
  222. package/mcp-server/dist/services/sqlite.d.ts.map +1 -0
  223. package/mcp-server/dist/services/sqlite.js +1185 -0
  224. package/mcp-server/dist/services/sqlite.js.map +1 -0
  225. package/mcp-server/dist/services/typesafe-bench.d.ts +99 -0
  226. package/mcp-server/dist/services/typesafe-bench.d.ts.map +1 -0
  227. package/mcp-server/dist/services/typesafe-bench.js +218 -0
  228. package/mcp-server/dist/services/typesafe-bench.js.map +1 -0
  229. package/mcp-server/dist/services/typesafe-config.d.ts +342 -0
  230. package/mcp-server/dist/services/typesafe-config.d.ts.map +1 -0
  231. package/mcp-server/dist/services/typesafe-config.js +746 -0
  232. package/mcp-server/dist/services/typesafe-config.js.map +1 -0
  233. package/mcp-server/dist/services/typesafe.d.ts +213 -0
  234. package/mcp-server/dist/services/typesafe.d.ts.map +1 -0
  235. package/mcp-server/dist/services/typesafe.js +330 -0
  236. package/mcp-server/dist/services/typesafe.js.map +1 -0
  237. package/mcp-server/dist/services/vector-cache.d.ts +68 -0
  238. package/mcp-server/dist/services/vector-cache.d.ts.map +1 -0
  239. package/mcp-server/dist/services/vector-cache.js +271 -0
  240. package/mcp-server/dist/services/vector-cache.js.map +1 -0
  241. package/mcp-server/dist/services/whiteboard-geometry.d.ts +305 -0
  242. package/mcp-server/dist/services/whiteboard-geometry.d.ts.map +1 -0
  243. package/mcp-server/dist/services/whiteboard-geometry.js +666 -0
  244. package/mcp-server/dist/services/whiteboard-geometry.js.map +1 -0
  245. package/mcp-server/dist/tools/agents.d.ts +212 -0
  246. package/mcp-server/dist/tools/agents.d.ts.map +1 -0
  247. package/mcp-server/dist/tools/agents.js +407 -0
  248. package/mcp-server/dist/tools/agents.js.map +1 -0
  249. package/mcp-server/dist/tools/bluesky.d.ts +39 -0
  250. package/mcp-server/dist/tools/bluesky.d.ts.map +1 -0
  251. package/mcp-server/dist/tools/bluesky.js +1144 -0
  252. package/mcp-server/dist/tools/bluesky.js.map +1 -0
  253. package/mcp-server/dist/tools/browser-advanced.d.ts +58 -0
  254. package/mcp-server/dist/tools/browser-advanced.d.ts.map +1 -0
  255. package/mcp-server/dist/tools/browser-advanced.js +106 -0
  256. package/mcp-server/dist/tools/browser-advanced.js.map +1 -0
  257. package/mcp-server/dist/tools/browser-batch.d.ts +99 -0
  258. package/mcp-server/dist/tools/browser-batch.d.ts.map +1 -0
  259. package/mcp-server/dist/tools/browser-batch.js +187 -0
  260. package/mcp-server/dist/tools/browser-batch.js.map +1 -0
  261. package/mcp-server/dist/tools/browser-cheatsheet.d.ts +21 -0
  262. package/mcp-server/dist/tools/browser-cheatsheet.d.ts.map +1 -0
  263. package/mcp-server/dist/tools/browser-cheatsheet.js +144 -0
  264. package/mcp-server/dist/tools/browser-cheatsheet.js.map +1 -0
  265. package/mcp-server/dist/tools/browser-interact.d.ts +239 -0
  266. package/mcp-server/dist/tools/browser-interact.d.ts.map +1 -0
  267. package/mcp-server/dist/tools/browser-interact.js +300 -0
  268. package/mcp-server/dist/tools/browser-interact.js.map +1 -0
  269. package/mcp-server/dist/tools/browser-navigate.d.ts +90 -0
  270. package/mcp-server/dist/tools/browser-navigate.d.ts.map +1 -0
  271. package/mcp-server/dist/tools/browser-navigate.js +142 -0
  272. package/mcp-server/dist/tools/browser-navigate.js.map +1 -0
  273. package/mcp-server/dist/tools/browser-observe.d.ts +561 -0
  274. package/mcp-server/dist/tools/browser-observe.d.ts.map +1 -0
  275. package/mcp-server/dist/tools/browser-observe.js +2009 -0
  276. package/mcp-server/dist/tools/browser-observe.js.map +1 -0
  277. package/mcp-server/dist/tools/browser.d.ts +34 -0
  278. package/mcp-server/dist/tools/browser.d.ts.map +1 -0
  279. package/mcp-server/dist/tools/browser.js +112 -0
  280. package/mcp-server/dist/tools/browser.js.map +1 -0
  281. package/mcp-server/dist/tools/card-tools.d.ts +82 -0
  282. package/mcp-server/dist/tools/card-tools.d.ts.map +1 -0
  283. package/mcp-server/dist/tools/card-tools.js +137 -0
  284. package/mcp-server/dist/tools/card-tools.js.map +1 -0
  285. package/mcp-server/dist/tools/card.d.ts +8 -0
  286. package/mcp-server/dist/tools/card.d.ts.map +1 -0
  287. package/mcp-server/dist/tools/card.js +16 -0
  288. package/mcp-server/dist/tools/card.js.map +1 -0
  289. package/mcp-server/dist/tools/category.d.ts +32 -0
  290. package/mcp-server/dist/tools/category.d.ts.map +1 -0
  291. package/mcp-server/dist/tools/category.js +290 -0
  292. package/mcp-server/dist/tools/category.js.map +1 -0
  293. package/mcp-server/dist/tools/choice.d.ts +160 -0
  294. package/mcp-server/dist/tools/choice.d.ts.map +1 -0
  295. package/mcp-server/dist/tools/choice.js +80 -0
  296. package/mcp-server/dist/tools/choice.js.map +1 -0
  297. package/mcp-server/dist/tools/computer.d.ts +71 -0
  298. package/mcp-server/dist/tools/computer.d.ts.map +1 -0
  299. package/mcp-server/dist/tools/computer.js +174 -0
  300. package/mcp-server/dist/tools/computer.js.map +1 -0
  301. package/mcp-server/dist/tools/discord-channel.d.ts +44 -0
  302. package/mcp-server/dist/tools/discord-channel.d.ts.map +1 -0
  303. package/mcp-server/dist/tools/discord-channel.js +236 -0
  304. package/mcp-server/dist/tools/discord-channel.js.map +1 -0
  305. package/mcp-server/dist/tools/discord-guild.d.ts +20 -0
  306. package/mcp-server/dist/tools/discord-guild.d.ts.map +1 -0
  307. package/mcp-server/dist/tools/discord-guild.js +138 -0
  308. package/mcp-server/dist/tools/discord-guild.js.map +1 -0
  309. package/mcp-server/dist/tools/discord-member.d.ts +26 -0
  310. package/mcp-server/dist/tools/discord-member.d.ts.map +1 -0
  311. package/mcp-server/dist/tools/discord-member.js +122 -0
  312. package/mcp-server/dist/tools/discord-member.js.map +1 -0
  313. package/mcp-server/dist/tools/discord-message.d.ts +36 -0
  314. package/mcp-server/dist/tools/discord-message.d.ts.map +1 -0
  315. package/mcp-server/dist/tools/discord-message.js +184 -0
  316. package/mcp-server/dist/tools/discord-message.js.map +1 -0
  317. package/mcp-server/dist/tools/discord-onboarding.d.ts +32 -0
  318. package/mcp-server/dist/tools/discord-onboarding.d.ts.map +1 -0
  319. package/mcp-server/dist/tools/discord-onboarding.js +179 -0
  320. package/mcp-server/dist/tools/discord-onboarding.js.map +1 -0
  321. package/mcp-server/dist/tools/discord-role.d.ts +34 -0
  322. package/mcp-server/dist/tools/discord-role.d.ts.map +1 -0
  323. package/mcp-server/dist/tools/discord-role.js +178 -0
  324. package/mcp-server/dist/tools/discord-role.js.map +1 -0
  325. package/mcp-server/dist/tools/discord-thread.d.ts +28 -0
  326. package/mcp-server/dist/tools/discord-thread.d.ts.map +1 -0
  327. package/mcp-server/dist/tools/discord-thread.js +88 -0
  328. package/mcp-server/dist/tools/discord-thread.js.map +1 -0
  329. package/mcp-server/dist/tools/discord-webhook.d.ts +32 -0
  330. package/mcp-server/dist/tools/discord-webhook.d.ts.map +1 -0
  331. package/mcp-server/dist/tools/discord-webhook.js +154 -0
  332. package/mcp-server/dist/tools/discord-webhook.js.map +1 -0
  333. package/mcp-server/dist/tools/discord.d.ts +7 -0
  334. package/mcp-server/dist/tools/discord.d.ts.map +1 -0
  335. package/mcp-server/dist/tools/discord.js +25 -0
  336. package/mcp-server/dist/tools/discord.js.map +1 -0
  337. package/mcp-server/dist/tools/fb-groups.d.ts +98 -0
  338. package/mcp-server/dist/tools/fb-groups.d.ts.map +1 -0
  339. package/mcp-server/dist/tools/fb-groups.js +369 -0
  340. package/mcp-server/dist/tools/fb-groups.js.map +1 -0
  341. package/mcp-server/dist/tools/forget.d.ts +14 -0
  342. package/mcp-server/dist/tools/forget.d.ts.map +1 -0
  343. package/mcp-server/dist/tools/forget.js +26 -0
  344. package/mcp-server/dist/tools/forget.js.map +1 -0
  345. package/mcp-server/dist/tools/git-tools.d.ts +24 -0
  346. package/mcp-server/dist/tools/git-tools.d.ts.map +1 -0
  347. package/mcp-server/dist/tools/git-tools.js +107 -0
  348. package/mcp-server/dist/tools/git-tools.js.map +1 -0
  349. package/mcp-server/dist/tools/git.d.ts +7 -0
  350. package/mcp-server/dist/tools/git.d.ts.map +1 -0
  351. package/mcp-server/dist/tools/git.js +11 -0
  352. package/mcp-server/dist/tools/git.js.map +1 -0
  353. package/mcp-server/dist/tools/gsc/experience.d.ts +135 -0
  354. package/mcp-server/dist/tools/gsc/experience.d.ts.map +1 -0
  355. package/mcp-server/dist/tools/gsc/experience.js +351 -0
  356. package/mcp-server/dist/tools/gsc/experience.js.map +1 -0
  357. package/mcp-server/dist/tools/gsc/helpers.d.ts +78 -0
  358. package/mcp-server/dist/tools/gsc/helpers.d.ts.map +1 -0
  359. package/mcp-server/dist/tools/gsc/helpers.js +258 -0
  360. package/mcp-server/dist/tools/gsc/helpers.js.map +1 -0
  361. package/mcp-server/dist/tools/gsc/indexing.d.ts +121 -0
  362. package/mcp-server/dist/tools/gsc/indexing.d.ts.map +1 -0
  363. package/mcp-server/dist/tools/gsc/indexing.js +357 -0
  364. package/mcp-server/dist/tools/gsc/indexing.js.map +1 -0
  365. package/mcp-server/dist/tools/gsc/inspect.d.ts +78 -0
  366. package/mcp-server/dist/tools/gsc/inspect.d.ts.map +1 -0
  367. package/mcp-server/dist/tools/gsc/inspect.js +321 -0
  368. package/mcp-server/dist/tools/gsc/inspect.js.map +1 -0
  369. package/mcp-server/dist/tools/gsc/navigate.d.ts +44 -0
  370. package/mcp-server/dist/tools/gsc/navigate.d.ts.map +1 -0
  371. package/mcp-server/dist/tools/gsc/navigate.js +197 -0
  372. package/mcp-server/dist/tools/gsc/navigate.js.map +1 -0
  373. package/mcp-server/dist/tools/gsc/performance.d.ts +84 -0
  374. package/mcp-server/dist/tools/gsc/performance.d.ts.map +1 -0
  375. package/mcp-server/dist/tools/gsc/performance.js +274 -0
  376. package/mcp-server/dist/tools/gsc/performance.js.map +1 -0
  377. package/mcp-server/dist/tools/gsc/settings.d.ts +153 -0
  378. package/mcp-server/dist/tools/gsc/settings.d.ts.map +1 -0
  379. package/mcp-server/dist/tools/gsc/settings.js +425 -0
  380. package/mcp-server/dist/tools/gsc/settings.js.map +1 -0
  381. package/mcp-server/dist/tools/gsc.d.ts +7 -0
  382. package/mcp-server/dist/tools/gsc.d.ts.map +1 -0
  383. package/mcp-server/dist/tools/gsc.js +51 -0
  384. package/mcp-server/dist/tools/gsc.js.map +1 -0
  385. package/mcp-server/dist/tools/image-tools.d.ts +24 -0
  386. package/mcp-server/dist/tools/image-tools.d.ts.map +1 -0
  387. package/mcp-server/dist/tools/image-tools.js +80 -0
  388. package/mcp-server/dist/tools/image-tools.js.map +1 -0
  389. package/mcp-server/dist/tools/image.d.ts +10 -0
  390. package/mcp-server/dist/tools/image.d.ts.map +1 -0
  391. package/mcp-server/dist/tools/image.js +14 -0
  392. package/mcp-server/dist/tools/image.js.map +1 -0
  393. package/mcp-server/dist/tools/leonardo-browser-tools.d.ts +97 -0
  394. package/mcp-server/dist/tools/leonardo-browser-tools.d.ts.map +1 -0
  395. package/mcp-server/dist/tools/leonardo-browser-tools.js +228 -0
  396. package/mcp-server/dist/tools/leonardo-browser-tools.js.map +1 -0
  397. package/mcp-server/dist/tools/leonardo.d.ts +13 -0
  398. package/mcp-server/dist/tools/leonardo.d.ts.map +1 -0
  399. package/mcp-server/dist/tools/leonardo.js +21 -0
  400. package/mcp-server/dist/tools/leonardo.js.map +1 -0
  401. package/mcp-server/dist/tools/loop.d.ts +30 -0
  402. package/mcp-server/dist/tools/loop.d.ts.map +1 -0
  403. package/mcp-server/dist/tools/loop.js +401 -0
  404. package/mcp-server/dist/tools/loop.js.map +1 -0
  405. package/mcp-server/dist/tools/memories.d.ts +56 -0
  406. package/mcp-server/dist/tools/memories.d.ts.map +1 -0
  407. package/mcp-server/dist/tools/memories.js +171 -0
  408. package/mcp-server/dist/tools/memories.js.map +1 -0
  409. package/mcp-server/dist/tools/morelogin.d.ts +24 -0
  410. package/mcp-server/dist/tools/morelogin.d.ts.map +1 -0
  411. package/mcp-server/dist/tools/morelogin.js +79 -0
  412. package/mcp-server/dist/tools/morelogin.js.map +1 -0
  413. package/mcp-server/dist/tools/profile.d.ts +17 -0
  414. package/mcp-server/dist/tools/profile.d.ts.map +1 -0
  415. package/mcp-server/dist/tools/profile.js +114 -0
  416. package/mcp-server/dist/tools/profile.js.map +1 -0
  417. package/mcp-server/dist/tools/recall.d.ts +71 -0
  418. package/mcp-server/dist/tools/recall.d.ts.map +1 -0
  419. package/mcp-server/dist/tools/recall.js +147 -0
  420. package/mcp-server/dist/tools/recall.js.map +1 -0
  421. package/mcp-server/dist/tools/reflect.d.ts +56 -0
  422. package/mcp-server/dist/tools/reflect.d.ts.map +1 -0
  423. package/mcp-server/dist/tools/reflect.js +157 -0
  424. package/mcp-server/dist/tools/reflect.js.map +1 -0
  425. package/mcp-server/dist/tools/remember.d.ts +62 -0
  426. package/mcp-server/dist/tools/remember.d.ts.map +1 -0
  427. package/mcp-server/dist/tools/remember.js +201 -0
  428. package/mcp-server/dist/tools/remember.js.map +1 -0
  429. package/mcp-server/dist/tools/response.d.ts +23 -0
  430. package/mcp-server/dist/tools/response.d.ts.map +1 -0
  431. package/mcp-server/dist/tools/response.js +24 -0
  432. package/mcp-server/dist/tools/response.js.map +1 -0
  433. package/mcp-server/dist/tools/restore.d.ts +14 -0
  434. package/mcp-server/dist/tools/restore.d.ts.map +1 -0
  435. package/mcp-server/dist/tools/restore.js +23 -0
  436. package/mcp-server/dist/tools/restore.js.map +1 -0
  437. package/mcp-server/dist/tools/style-guide-tools.d.ts +51 -0
  438. package/mcp-server/dist/tools/style-guide-tools.d.ts.map +1 -0
  439. package/mcp-server/dist/tools/style-guide-tools.js +231 -0
  440. package/mcp-server/dist/tools/style-guide-tools.js.map +1 -0
  441. package/mcp-server/dist/tools/style-guide.d.ts +8 -0
  442. package/mcp-server/dist/tools/style-guide.d.ts.map +1 -0
  443. package/mcp-server/dist/tools/style-guide.js +12 -0
  444. package/mcp-server/dist/tools/style-guide.js.map +1 -0
  445. package/mcp-server/dist/tools/sync.d.ts +20 -0
  446. package/mcp-server/dist/tools/sync.d.ts.map +1 -0
  447. package/mcp-server/dist/tools/sync.js +156 -0
  448. package/mcp-server/dist/tools/sync.js.map +1 -0
  449. package/mcp-server/dist/tools/tictactoe-tools.d.ts +18 -0
  450. package/mcp-server/dist/tools/tictactoe-tools.d.ts.map +1 -0
  451. package/mcp-server/dist/tools/tictactoe-tools.js +78 -0
  452. package/mcp-server/dist/tools/tictactoe-tools.js.map +1 -0
  453. package/mcp-server/dist/tools/tictactoe.d.ts +7 -0
  454. package/mcp-server/dist/tools/tictactoe.d.ts.map +1 -0
  455. package/mcp-server/dist/tools/tictactoe.js +11 -0
  456. package/mcp-server/dist/tools/tictactoe.js.map +1 -0
  457. package/mcp-server/dist/tools/utils.d.ts +19 -0
  458. package/mcp-server/dist/tools/utils.d.ts.map +1 -0
  459. package/mcp-server/dist/tools/utils.js +54 -0
  460. package/mcp-server/dist/tools/utils.js.map +1 -0
  461. package/mcp-server/dist/tools/whiteboard-format.d.ts +88 -0
  462. package/mcp-server/dist/tools/whiteboard-format.d.ts.map +1 -0
  463. package/mcp-server/dist/tools/whiteboard-format.js +337 -0
  464. package/mcp-server/dist/tools/whiteboard-format.js.map +1 -0
  465. package/mcp-server/dist/tools/whiteboard-tools.d.ts +326 -0
  466. package/mcp-server/dist/tools/whiteboard-tools.d.ts.map +1 -0
  467. package/mcp-server/dist/tools/whiteboard-tools.js +222 -0
  468. package/mcp-server/dist/tools/whiteboard-tools.js.map +1 -0
  469. package/mcp-server/dist/tools/whiteboard.d.ts +8 -0
  470. package/mcp-server/dist/tools/whiteboard.d.ts.map +1 -0
  471. package/mcp-server/dist/tools/whiteboard.js +16 -0
  472. package/mcp-server/dist/tools/whiteboard.js.map +1 -0
  473. package/mcp-server/dist/tools/youtube/analytics.d.ts +46 -0
  474. package/mcp-server/dist/tools/youtube/analytics.d.ts.map +1 -0
  475. package/mcp-server/dist/tools/youtube/analytics.js +83 -0
  476. package/mcp-server/dist/tools/youtube/analytics.js.map +1 -0
  477. package/mcp-server/dist/tools/youtube/dedup.d.ts +35 -0
  478. package/mcp-server/dist/tools/youtube/dedup.d.ts.map +1 -0
  479. package/mcp-server/dist/tools/youtube/dedup.js +56 -0
  480. package/mcp-server/dist/tools/youtube/dedup.js.map +1 -0
  481. package/mcp-server/dist/tools/youtube/download.d.ts +31 -0
  482. package/mcp-server/dist/tools/youtube/download.d.ts.map +1 -0
  483. package/mcp-server/dist/tools/youtube/download.js +30 -0
  484. package/mcp-server/dist/tools/youtube/download.js.map +1 -0
  485. package/mcp-server/dist/tools/youtube/helpers.d.ts +66 -0
  486. package/mcp-server/dist/tools/youtube/helpers.d.ts.map +1 -0
  487. package/mcp-server/dist/tools/youtube/helpers.js +143 -0
  488. package/mcp-server/dist/tools/youtube/helpers.js.map +1 -0
  489. package/mcp-server/dist/tools/youtube/media.d.ts +43 -0
  490. package/mcp-server/dist/tools/youtube/media.d.ts.map +1 -0
  491. package/mcp-server/dist/tools/youtube/media.js +97 -0
  492. package/mcp-server/dist/tools/youtube/media.js.map +1 -0
  493. package/mcp-server/dist/tools/youtube/metadata.d.ts +33 -0
  494. package/mcp-server/dist/tools/youtube/metadata.d.ts.map +1 -0
  495. package/mcp-server/dist/tools/youtube/metadata.js +106 -0
  496. package/mcp-server/dist/tools/youtube/metadata.js.map +1 -0
  497. package/mcp-server/dist/tools/youtube/navigate.d.ts +30 -0
  498. package/mcp-server/dist/tools/youtube/navigate.d.ts.map +1 -0
  499. package/mcp-server/dist/tools/youtube/navigate.js +71 -0
  500. package/mcp-server/dist/tools/youtube/navigate.js.map +1 -0
  501. package/mcp-server/dist/tools/youtube/playlist.d.ts +29 -0
  502. package/mcp-server/dist/tools/youtube/playlist.d.ts.map +1 -0
  503. package/mcp-server/dist/tools/youtube/playlist.js +128 -0
  504. package/mcp-server/dist/tools/youtube/playlist.js.map +1 -0
  505. package/mcp-server/dist/tools/youtube/schedule.d.ts +31 -0
  506. package/mcp-server/dist/tools/youtube/schedule.d.ts.map +1 -0
  507. package/mcp-server/dist/tools/youtube/schedule.js +147 -0
  508. package/mcp-server/dist/tools/youtube/schedule.js.map +1 -0
  509. package/mcp-server/dist/tools/youtube/source.d.ts +36 -0
  510. package/mcp-server/dist/tools/youtube/source.d.ts.map +1 -0
  511. package/mcp-server/dist/tools/youtube/source.js +85 -0
  512. package/mcp-server/dist/tools/youtube/source.js.map +1 -0
  513. package/mcp-server/dist/tools/youtube/upload.d.ts +53 -0
  514. package/mcp-server/dist/tools/youtube/upload.d.ts.map +1 -0
  515. package/mcp-server/dist/tools/youtube/upload.js +255 -0
  516. package/mcp-server/dist/tools/youtube/upload.js.map +1 -0
  517. package/mcp-server/dist/tools/youtube.d.ts +12 -0
  518. package/mcp-server/dist/tools/youtube.d.ts.map +1 -0
  519. package/mcp-server/dist/tools/youtube.js +38 -0
  520. package/mcp-server/dist/tools/youtube.js.map +1 -0
  521. package/mcp-server/dist/tui.d.ts +3 -0
  522. package/mcp-server/dist/tui.d.ts.map +1 -0
  523. package/mcp-server/dist/tui.js +806 -0
  524. package/mcp-server/dist/tui.js.map +1 -0
  525. package/mcp-server/dist/types.d.ts +77 -0
  526. package/mcp-server/dist/types.d.ts.map +1 -0
  527. package/mcp-server/dist/types.js +2 -0
  528. package/mcp-server/dist/types.js.map +1 -0
  529. package/mcp-server/package-lock.json +4798 -0
  530. package/mcp-server/package.json +55 -38
  531. package/mcp-server/run.mjs +12 -2
  532. package/mcp-server/src/config.ts +48 -3
  533. package/mcp-server/src/http.ts +296 -93
  534. package/mcp-server/src/index.ts +546 -203
  535. package/mcp-server/src/preload-http.ts +19 -18
  536. package/mcp-server/src/preload.ts +19 -18
  537. package/mcp-server/src/scripts/setup-embeddings.ts +9 -0
  538. package/mcp-server/src/services/assistant-judgments.ts +157 -0
  539. package/mcp-server/src/services/browser-assist-gate.ts +383 -0
  540. package/mcp-server/src/services/browser-assist.ts +267 -0
  541. package/mcp-server/src/services/browser-bench.ts +477 -0
  542. package/mcp-server/src/services/browser-judgments.ts +414 -0
  543. package/mcp-server/src/services/browser-risk.ts +484 -0
  544. package/mcp-server/src/services/categories.ts +36 -19
  545. package/mcp-server/src/services/codex-config-heal.ts +403 -0
  546. package/mcp-server/src/services/desktop-assist-gate.ts +251 -0
  547. package/mcp-server/src/services/desktop-assist.ts +308 -0
  548. package/mcp-server/src/services/desktop-bench.ts +372 -0
  549. package/mcp-server/src/services/desktop-client.ts +76 -0
  550. package/mcp-server/src/services/desktop-judgments.ts +218 -0
  551. package/mcp-server/src/services/desktop-risk.ts +743 -0
  552. package/mcp-server/src/services/edit-stale.ts +299 -0
  553. package/mcp-server/src/services/embedding-service.ts +108 -0
  554. package/mcp-server/src/services/embedding-worker.ts +46 -0
  555. package/mcp-server/src/services/fb-regions.ts +221 -0
  556. package/mcp-server/src/services/file-checksums.ts +26 -9
  557. package/mcp-server/src/services/file-excerpt.ts +59 -0
  558. package/mcp-server/src/services/identity.ts +291 -0
  559. package/mcp-server/src/services/local-embeddings.ts +2 -77
  560. package/mcp-server/src/services/memory-client.ts +23 -0
  561. package/mcp-server/src/services/memory-judge-backfill.ts +462 -0
  562. package/mcp-server/src/services/memory-judgments.ts +901 -0
  563. package/mcp-server/src/services/memory-maintenance.ts +360 -0
  564. package/mcp-server/src/services/memory-retrieval.ts +349 -0
  565. package/mcp-server/src/services/memory-schema.ts +280 -0
  566. package/mcp-server/src/services/memory-sessions.ts +87 -0
  567. package/mcp-server/src/services/memory-triage.ts +182 -0
  568. package/mcp-server/src/services/memory-verification.ts +68 -0
  569. package/mcp-server/src/services/memory-writer.ts +125 -0
  570. package/mcp-server/src/services/neural-interface.ts +1217 -73
  571. package/mcp-server/src/services/profiles.ts +428 -0
  572. package/mcp-server/src/services/secret-gate.ts +52 -0
  573. package/mcp-server/src/services/server-instructions.ts +122 -0
  574. package/mcp-server/src/services/sqlite.ts +1456 -823
  575. package/mcp-server/src/services/typesafe-bench.ts +247 -0
  576. package/mcp-server/src/services/typesafe-config.ts +790 -0
  577. package/mcp-server/src/services/typesafe.ts +390 -0
  578. package/mcp-server/src/services/vector-cache.ts +255 -0
  579. package/mcp-server/src/services/whiteboard-geometry.ts +711 -0
  580. package/mcp-server/src/tools/agents.ts +539 -0
  581. package/mcp-server/src/tools/bluesky.ts +1186 -0
  582. package/mcp-server/src/tools/browser-advanced.ts +15 -6
  583. package/mcp-server/src/tools/browser-batch.ts +178 -0
  584. package/mcp-server/src/tools/browser-cheatsheet.ts +155 -0
  585. package/mcp-server/src/tools/browser-interact.ts +362 -255
  586. package/mcp-server/src/tools/browser-navigate.ts +164 -77
  587. package/mcp-server/src/tools/browser-observe.ts +2222 -1330
  588. package/mcp-server/src/tools/browser.ts +181 -107
  589. package/mcp-server/src/tools/card.ts +7 -5
  590. package/mcp-server/src/tools/choice.ts +103 -0
  591. package/mcp-server/src/tools/computer.ts +190 -0
  592. package/mcp-server/src/tools/discord.ts +10 -23
  593. package/mcp-server/src/tools/fb-groups.ts +387 -0
  594. package/mcp-server/src/tools/forget.ts +1 -1
  595. package/mcp-server/src/tools/git.ts +3 -1
  596. package/mcp-server/src/tools/gsc/experience.ts +440 -0
  597. package/mcp-server/src/tools/gsc/helpers.ts +288 -0
  598. package/mcp-server/src/tools/gsc/indexing.ts +495 -0
  599. package/mcp-server/src/tools/gsc/inspect.ts +391 -0
  600. package/mcp-server/src/tools/gsc/navigate.ts +236 -0
  601. package/mcp-server/src/tools/gsc/performance.ts +352 -0
  602. package/mcp-server/src/tools/gsc/settings.ts +564 -0
  603. package/mcp-server/src/tools/gsc.ts +95 -0
  604. package/mcp-server/src/tools/image.ts +3 -1
  605. package/mcp-server/src/tools/leonardo-browser-tools.ts +47 -37
  606. package/mcp-server/src/tools/leonardo.ts +7 -5
  607. package/mcp-server/src/tools/loop.ts +118 -25
  608. package/mcp-server/src/tools/memories.ts +65 -5
  609. package/mcp-server/src/tools/morelogin.ts +81 -0
  610. package/mcp-server/src/tools/profile.ts +122 -0
  611. package/mcp-server/src/tools/recall.ts +105 -261
  612. package/mcp-server/src/tools/reflect.ts +171 -145
  613. package/mcp-server/src/tools/remember.ts +223 -115
  614. package/mcp-server/src/tools/style-guide-tools.ts +250 -0
  615. package/mcp-server/src/tools/style-guide.ts +16 -0
  616. package/mcp-server/src/tools/sync.ts +66 -9
  617. package/mcp-server/src/tools/tictactoe.ts +3 -1
  618. package/mcp-server/src/tools/utils.ts +22 -0
  619. package/mcp-server/src/tools/whiteboard-format.ts +394 -0
  620. package/mcp-server/src/tools/whiteboard-tools.ts +191 -183
  621. package/mcp-server/src/tools/whiteboard.ts +7 -5
  622. package/mcp-server/src/tools/youtube/analytics.ts +106 -0
  623. package/mcp-server/src/tools/youtube/dedup.ts +57 -0
  624. package/mcp-server/src/tools/youtube/download.ts +41 -0
  625. package/mcp-server/src/tools/youtube/helpers.ts +183 -0
  626. package/mcp-server/src/tools/youtube/media.ts +109 -0
  627. package/mcp-server/src/tools/youtube/metadata.ts +112 -0
  628. package/mcp-server/src/tools/youtube/navigate.ts +81 -0
  629. package/mcp-server/src/tools/youtube/playlist.ts +134 -0
  630. package/mcp-server/src/tools/youtube/schedule.ts +158 -0
  631. package/mcp-server/src/tools/youtube/source.ts +101 -0
  632. package/mcp-server/src/tools/youtube/upload.ts +296 -0
  633. package/mcp-server/src/tools/youtube.ts +47 -0
  634. package/mcp-server/src/tui.ts +8 -9
  635. package/neural-interface/games/TicTacToe/1.svg +1 -0
  636. package/neural-interface/games/TicTacToe/2.svg +1 -0
  637. package/neural-interface/games/TicTacToe/3.svg +1 -0
  638. package/neural-interface/games/TicTacToe/4.svg +1 -0
  639. package/neural-interface/games/TicTacToe/5.svg +1 -0
  640. package/neural-interface/games/TicTacToe/6.svg +1 -0
  641. package/neural-interface/games/TicTacToe/7.svg +1 -0
  642. package/neural-interface/games/TicTacToe/8.svg +1 -0
  643. package/neural-interface/games/TicTacToe/9.svg +1 -0
  644. package/neural-interface/games/TicTacToe/Board.svg +1 -0
  645. package/neural-interface/games/TicTacToe/Circle.svg +1 -0
  646. package/neural-interface/games/TicTacToe/Cross.svg +1 -0
  647. package/neural-interface/i18n/en.json +6983 -0
  648. package/neural-interface/i18n/pt-BR.json +6987 -0
  649. package/neural-interface/lib/assistant-api.js +1005 -0
  650. package/neural-interface/lib/assistant-attachments.js +121 -0
  651. package/neural-interface/lib/assistant-brains/claude.js +207 -0
  652. package/neural-interface/lib/assistant-brains/codex-browser-policy-hook.mjs +43 -0
  653. package/neural-interface/lib/assistant-brains/codex-route-gate-hook.mjs +56 -0
  654. package/neural-interface/lib/assistant-brains/codex.js +213 -0
  655. package/neural-interface/lib/assistant-brains/opencode-browser-policy.js +47 -0
  656. package/neural-interface/lib/assistant-brains/opencode-route-gate.js +62 -0
  657. package/neural-interface/lib/assistant-brains/opencode.js +320 -0
  658. package/neural-interface/lib/assistant-budget.js +318 -0
  659. package/neural-interface/lib/assistant-catalog.js +731 -0
  660. package/neural-interface/lib/assistant-clarify.js +664 -0
  661. package/neural-interface/lib/assistant-config.js +232 -0
  662. package/neural-interface/lib/assistant-dispatch.js +2744 -0
  663. package/neural-interface/lib/assistant-envelope.js +579 -0
  664. package/neural-interface/lib/assistant-evidence.js +236 -0
  665. package/neural-interface/lib/assistant-hidden-models.js +272 -0
  666. package/neural-interface/lib/assistant-jev.js +117 -0
  667. package/neural-interface/lib/assistant-judgments.js +111 -0
  668. package/neural-interface/lib/assistant-media.js +335 -0
  669. package/neural-interface/lib/assistant-memory.js +398 -0
  670. package/neural-interface/lib/assistant-persona.js +444 -0
  671. package/neural-interface/lib/assistant-plan-permissions.js +448 -0
  672. package/neural-interface/lib/assistant-playbooks/design.md +87 -0
  673. package/neural-interface/lib/assistant-playbooks.js +72 -0
  674. package/neural-interface/lib/assistant-pricing.js +159 -0
  675. package/neural-interface/lib/assistant-route-gate-codex.js +163 -0
  676. package/neural-interface/lib/assistant-route-gate.js +212 -0
  677. package/neural-interface/lib/assistant-router.js +1324 -0
  678. package/neural-interface/lib/assistant-runtime.js +3337 -0
  679. package/neural-interface/lib/assistant-task-prompt.js +472 -0
  680. package/neural-interface/lib/assistant-usage.js +1688 -0
  681. package/neural-interface/lib/augmented-path.js +50 -0
  682. package/neural-interface/lib/automation-storage-migration.js +54 -0
  683. package/neural-interface/lib/backup-service.js +851 -0
  684. package/neural-interface/lib/backup-zip-reader.js +262 -0
  685. package/neural-interface/lib/browser-assist-api.js +41 -0
  686. package/neural-interface/lib/browser-console.js +176 -0
  687. package/neural-interface/lib/browser-execution.js +241 -0
  688. package/neural-interface/lib/browser-extraction.js +191 -0
  689. package/neural-interface/lib/browser-screenshot.js +399 -0
  690. package/neural-interface/lib/browser-semantic-context.js +639 -0
  691. package/neural-interface/lib/browser-snapshots.js +192 -0
  692. package/neural-interface/lib/browser-tab-recovery.js +119 -0
  693. package/neural-interface/lib/browser-targets.js +70 -0
  694. package/neural-interface/lib/browser-tool-policy.js +926 -0
  695. package/neural-interface/lib/claude-accounts.js +230 -0
  696. package/neural-interface/lib/claude-agent-bridge.js +3296 -0
  697. package/neural-interface/lib/claude-bypass-policy.js +99 -0
  698. package/neural-interface/lib/claude-history.js +429 -0
  699. package/neural-interface/lib/claude-model-catalog.js +483 -0
  700. package/neural-interface/lib/claude-panel-requests.js +165 -0
  701. package/neural-interface/lib/claude-panel-session.js +272 -0
  702. package/neural-interface/lib/claude-permission-rules.js +153 -0
  703. package/neural-interface/lib/claude-session-cleanup.js +71 -0
  704. package/neural-interface/lib/claude-session-list.js +82 -0
  705. package/neural-interface/lib/claude-session-ops.js +140 -0
  706. package/neural-interface/lib/claude-settings-view.js +51 -0
  707. package/neural-interface/lib/claude-skin-connect.js +79 -0
  708. package/neural-interface/lib/claude-stall-policy.js +7 -0
  709. package/neural-interface/lib/claude-temporary.js +435 -0
  710. package/neural-interface/lib/cli-update-planner.js +312 -0
  711. package/neural-interface/lib/codex-capabilities.d.ts +41 -0
  712. package/neural-interface/lib/codex-capabilities.js +148 -0
  713. package/neural-interface/lib/codex-collaboration-mode.js +17 -0
  714. package/neural-interface/lib/codex-compat-rpc.js +241 -0
  715. package/neural-interface/lib/codex-mcp-approvals.js +56 -0
  716. package/neural-interface/lib/codex-mcp-apps.js +47 -0
  717. package/neural-interface/lib/codex-model-context.js +202 -0
  718. package/neural-interface/lib/codex-plan-store.js +71 -0
  719. package/neural-interface/lib/codex-request-journal.js +242 -0
  720. package/neural-interface/lib/codex-runtime-path.js +213 -0
  721. package/neural-interface/lib/codex-session-catalog.js +231 -0
  722. package/neural-interface/lib/codex-session-settings.js +46 -0
  723. package/neural-interface/lib/codex-sidepanel-permissions.js +110 -0
  724. package/neural-interface/lib/codex-thread-history.js +165 -0
  725. package/neural-interface/lib/codex-user-verification.js +34 -0
  726. package/neural-interface/lib/codex-writer-lifecycle.js +152 -0
  727. package/neural-interface/lib/confined-fs.js +256 -0
  728. package/neural-interface/lib/db.js +922 -0
  729. package/neural-interface/lib/design-md.js +9 -0
  730. package/neural-interface/lib/desktop/api.js +92 -0
  731. package/neural-interface/lib/desktop/audit.js +62 -0
  732. package/neural-interface/lib/desktop/build.js +423 -0
  733. package/neural-interface/lib/desktop/config.js +606 -0
  734. package/neural-interface/lib/desktop/coords.js +76 -0
  735. package/neural-interface/lib/desktop/fake-helper.js +1192 -0
  736. package/neural-interface/lib/desktop/frames.js +77 -0
  737. package/neural-interface/lib/desktop/grants.js +84 -0
  738. package/neural-interface/lib/desktop/guards.js +170 -0
  739. package/neural-interface/lib/desktop/helper/SynabunDesktop.swift +3056 -0
  740. package/neural-interface/lib/desktop/lease.js +51 -0
  741. package/neural-interface/lib/desktop/manager.js +545 -0
  742. package/neural-interface/lib/desktop/press-contexts.js +103 -0
  743. package/neural-interface/lib/desktop/protocol.js +495 -0
  744. package/neural-interface/lib/desktop/service.js +1202 -0
  745. package/neural-interface/lib/effort-levels.js +148 -0
  746. package/neural-interface/lib/event-loop-monitor.js +67 -0
  747. package/neural-interface/lib/exec-loop-command.js +209 -0
  748. package/neural-interface/lib/folder-picker.ps1 +77 -0
  749. package/neural-interface/lib/http-guards.js +287 -0
  750. package/neural-interface/lib/jsonl-lines.js +94 -0
  751. package/neural-interface/lib/loop-logger.js +127 -0
  752. package/neural-interface/lib/mcp-client-config.js +133 -0
  753. package/neural-interface/lib/mcp-installer.js +487 -0
  754. package/neural-interface/lib/mcp-profile-refresh-coordinator.js +78 -0
  755. package/neural-interface/lib/mcp-profile-servers.js +120 -0
  756. package/neural-interface/lib/memo-cache.js +84 -0
  757. package/neural-interface/lib/memory-api.js +758 -0
  758. package/neural-interface/lib/memory-map-api.js +1150 -0
  759. package/neural-interface/lib/memory-map-layout.js +872 -0
  760. package/neural-interface/lib/memory-map-worker.js +165 -0
  761. package/neural-interface/lib/memory-session-capture.js +81 -0
  762. package/neural-interface/lib/memory-timers.js +62 -0
  763. package/neural-interface/lib/morelogin.js +301 -0
  764. package/neural-interface/lib/native-binary-runtime.js +650 -0
  765. package/neural-interface/lib/native-loop-goal.js +33 -0
  766. package/neural-interface/lib/native-loop-providers.js +1016 -0
  767. package/neural-interface/lib/native-loop-runtime.js +747 -0
  768. package/neural-interface/lib/opencode-hidden-models.js +113 -0
  769. package/neural-interface/lib/opencode-history.js +253 -0
  770. package/neural-interface/lib/opencode-runtime-config.js +58 -0
  771. package/neural-interface/lib/opencode-v2-client.js +486 -0
  772. package/neural-interface/lib/opencode-v2-ws-requests.js +955 -0
  773. package/neural-interface/lib/path-confine.js +213 -0
  774. package/neural-interface/lib/plugin-installer.js +264 -0
  775. package/neural-interface/lib/project-storage.js +766 -0
  776. package/neural-interface/lib/pty-host/core.js +603 -0
  777. package/neural-interface/lib/pty-host/flow.js +43 -0
  778. package/neural-interface/lib/pty-host/host.js +47 -0
  779. package/neural-interface/lib/pty-host/manager.js +360 -0
  780. package/neural-interface/lib/pty-host/protocol.js +81 -0
  781. package/neural-interface/lib/pty-host/snapshot.js +133 -0
  782. package/neural-interface/lib/remote-policy.js +582 -0
  783. package/neural-interface/lib/rulesets/api.js +175 -0
  784. package/neural-interface/lib/rulesets/fs-safe.js +245 -0
  785. package/neural-interface/lib/rulesets/installer.js +1453 -0
  786. package/neural-interface/lib/rulesets/json-edit.js +186 -0
  787. package/neural-interface/lib/rulesets/lock.js +170 -0
  788. package/neural-interface/lib/rulesets/managed-text.js +314 -0
  789. package/neural-interface/lib/rulesets/normalise.js +24 -0
  790. package/neural-interface/lib/rulesets/render.js +84 -0
  791. package/neural-interface/lib/schedule-launch-intent.js +40 -0
  792. package/neural-interface/lib/session-cache-builder.js +524 -0
  793. package/neural-interface/lib/session-chunker.js +344 -0
  794. package/neural-interface/lib/session-indexer.js +327 -0
  795. package/neural-interface/lib/session-title-generator.js +227 -0
  796. package/neural-interface/lib/skill-prompt-bridge.js +11 -0
  797. package/neural-interface/lib/style-guide/api.js +375 -0
  798. package/neural-interface/lib/style-guide/color.js +352 -0
  799. package/neural-interface/lib/style-guide/export-css.js +99 -0
  800. package/neural-interface/lib/style-guide/export-dtcg.js +209 -0
  801. package/neural-interface/lib/style-guide/export-tailwind.js +102 -0
  802. package/neural-interface/lib/style-guide/fonts.json +227 -0
  803. package/neural-interface/lib/style-guide/import.js +1268 -0
  804. package/neural-interface/lib/style-guide/pointers.js +103 -0
  805. package/neural-interface/lib/style-guide/presets.js +232 -0
  806. package/neural-interface/lib/style-guide/render-design-md.js +319 -0
  807. package/neural-interface/lib/style-guide/schema.js +848 -0
  808. package/neural-interface/lib/style-guide/security.js +43 -0
  809. package/neural-interface/lib/style-guide/store.js +491 -0
  810. package/neural-interface/lib/style-guide/summary.js +106 -0
  811. package/neural-interface/lib/style-guide/tokens.js +170 -0
  812. package/neural-interface/lib/synabun-update-plan.js +305 -0
  813. package/neural-interface/lib/synabun-version.js +179 -0
  814. package/neural-interface/lib/system-restore.js +99 -0
  815. package/neural-interface/lib/terminal-env.js +86 -0
  816. package/neural-interface/lib/ui-blob-store.js +106 -0
  817. package/neural-interface/lib/vector-cache.js +2 -0
  818. package/neural-interface/lib/virtual-socket.js +60 -0
  819. package/neural-interface/lib/whatsapp/api.js +146 -0
  820. package/neural-interface/lib/whatsapp/auth-store.js +389 -0
  821. package/neural-interface/lib/whatsapp/baileys-adapter.js +457 -0
  822. package/neural-interface/lib/whatsapp/brain.js +128 -0
  823. package/neural-interface/lib/whatsapp/bridge.js +1499 -0
  824. package/neural-interface/lib/whatsapp/cards.js +519 -0
  825. package/neural-interface/lib/whatsapp/commands.js +92 -0
  826. package/neural-interface/lib/whatsapp/config.js +291 -0
  827. package/neural-interface/lib/whatsapp/connector/entry.mjs +25 -0
  828. package/neural-interface/lib/whatsapp/connector/manifest.json +6 -0
  829. package/neural-interface/lib/whatsapp/connector/npm-shrinkwrap.json +717 -0
  830. package/neural-interface/lib/whatsapp/connector/package.json +8 -0
  831. package/neural-interface/lib/whatsapp/fake-baileys.js +444 -0
  832. package/neural-interface/lib/whatsapp/format.js +552 -0
  833. package/neural-interface/lib/whatsapp/host-core.js +1225 -0
  834. package/neural-interface/lib/whatsapp/host.js +119 -0
  835. package/neural-interface/lib/whatsapp/identity.js +288 -0
  836. package/neural-interface/lib/whatsapp/inbound.js +149 -0
  837. package/neural-interface/lib/whatsapp/installer.js +562 -0
  838. package/neural-interface/lib/whatsapp/manager.js +638 -0
  839. package/neural-interface/lib/whatsapp/paths.js +81 -0
  840. package/neural-interface/lib/whatsapp/protocol.js +327 -0
  841. package/neural-interface/lib/whatsapp/qr-svg.js +57 -0
  842. package/neural-interface/lib/whatsapp/redact.js +130 -0
  843. package/neural-interface/lib/whatsapp/service.js +1305 -0
  844. package/neural-interface/lib/whatsapp/vendor/qrcodegen.js +848 -0
  845. package/neural-interface/package-lock.json +4682 -0
  846. package/neural-interface/package.json +58 -27
  847. package/neural-interface/public/apple-touch-icon.png +0 -0
  848. package/neural-interface/public/category-logos/synabun.png +0 -0
  849. package/neural-interface/public/claude.svg +1 -0
  850. package/neural-interface/public/favicon-16x16.png +0 -0
  851. package/neural-interface/public/favicon-32x32.png +0 -0
  852. package/neural-interface/public/icon-192.png +0 -0
  853. package/neural-interface/public/icon-512.png +0 -0
  854. package/neural-interface/public/index.html +32 -182
  855. package/neural-interface/public/index2d.html +2 -2
  856. package/neural-interface/public/logo-synabun.png +0 -0
  857. package/neural-interface/public/logoHD.png +0 -0
  858. package/neural-interface/public/mcp.svg +4 -0
  859. package/neural-interface/public/offline.html +335 -299
  860. package/neural-interface/public/onboarding.html +692 -155
  861. package/neural-interface/public/opencode-logo-dark-square.svg +1 -0
  862. package/neural-interface/public/shared/agent-runtime-options.js +596 -0
  863. package/neural-interface/public/shared/api.js +339 -28
  864. package/neural-interface/public/shared/assistant/asst-accounts.js +318 -0
  865. package/neural-interface/public/shared/assistant/asst-agents-dock.js +296 -0
  866. package/neural-interface/public/shared/assistant/asst-api.js +270 -0
  867. package/neural-interface/public/shared/assistant/asst-brain-picker.js +744 -0
  868. package/neural-interface/public/shared/assistant/asst-budget.js +333 -0
  869. package/neural-interface/public/shared/assistant/asst-composer.js +656 -0
  870. package/neural-interface/public/shared/assistant/asst-computer.js +803 -0
  871. package/neural-interface/public/shared/assistant/asst-control.js +1018 -0
  872. package/neural-interface/public/shared/assistant/asst-hosts.js +262 -0
  873. package/neural-interface/public/shared/assistant/asst-mascot.js +311 -0
  874. package/neural-interface/public/shared/assistant/asst-menu.js +375 -0
  875. package/neural-interface/public/shared/assistant/asst-panel.js +1845 -0
  876. package/neural-interface/public/shared/assistant/asst-rack-styles.js +589 -0
  877. package/neural-interface/public/shared/assistant/asst-render.js +3296 -0
  878. package/neural-interface/public/shared/assistant/asst-route.js +1653 -0
  879. package/neural-interface/public/shared/assistant/asst-roving.js +75 -0
  880. package/neural-interface/public/shared/assistant/asst-sanitize.js +117 -0
  881. package/neural-interface/public/shared/assistant/asst-sidepanel-styles.js +488 -0
  882. package/neural-interface/public/shared/assistant/asst-sidepanel.js +675 -0
  883. package/neural-interface/public/shared/assistant/asst-slash.js +258 -0
  884. package/neural-interface/public/shared/assistant/asst-state.js +727 -0
  885. package/neural-interface/public/shared/assistant/asst-styles.js +1684 -0
  886. package/neural-interface/public/shared/assistant/asst-tool-kinds.js +1017 -0
  887. package/neural-interface/public/shared/assistant/asst-usage.js +444 -0
  888. package/neural-interface/public/shared/assistant/asst-ws.js +175 -0
  889. package/neural-interface/public/shared/automation-context.js +75 -0
  890. package/neural-interface/public/shared/blob-store.js +99 -0
  891. package/neural-interface/public/shared/cdx/cdx-capabilities.js +118 -0
  892. package/neural-interface/public/shared/cdx/cdx-cards.js +37 -0
  893. package/neural-interface/public/shared/cdx/cdx-commands.js +171 -0
  894. package/neural-interface/public/shared/cdx/cdx-context-menu.js +402 -0
  895. package/neural-interface/public/shared/cdx/cdx-context-model.js +220 -0
  896. package/neural-interface/public/shared/cdx/cdx-features.js +408 -0
  897. package/neural-interface/public/shared/cdx/cdx-icons.js +89 -0
  898. package/neural-interface/public/shared/cdx/cdx-mcp-app-host.js +414 -0
  899. package/neural-interface/public/shared/cdx/cdx-mcp-app-proxy.html +6 -0
  900. package/neural-interface/public/shared/cdx/cdx-mcp-app-proxy.js +56 -0
  901. package/neural-interface/public/shared/cdx/cdx-mcp-app.js +178 -0
  902. package/neural-interface/public/shared/cdx/cdx-model-catalog.js +120 -0
  903. package/neural-interface/public/shared/cdx/cdx-output-model.js +261 -0
  904. package/neural-interface/public/shared/cdx/cdx-output.js +382 -0
  905. package/neural-interface/public/shared/cdx/cdx-panel.js +1372 -0
  906. package/neural-interface/public/shared/cdx/cdx-plan.js +266 -0
  907. package/neural-interface/public/shared/cdx/cdx-protocol.js +682 -0
  908. package/neural-interface/public/shared/cdx/cdx-render.js +3381 -0
  909. package/neural-interface/public/shared/cdx/cdx-requests.js +1136 -0
  910. package/neural-interface/public/shared/cdx/cdx-styles.js +3251 -0
  911. package/neural-interface/public/shared/cdx/cdx-tabs.js +7992 -0
  912. package/neural-interface/public/shared/cdx/cdx-ws.js +363 -0
  913. package/neural-interface/public/shared/cli-status.js +169 -0
  914. package/neural-interface/public/shared/constants.js +22 -5
  915. package/neural-interface/public/shared/cp/cp-agents.js +186 -0
  916. package/neural-interface/public/shared/cp/cp-bash.js +252 -0
  917. package/neural-interface/public/shared/cp/cp-compose.js +159 -0
  918. package/neural-interface/public/shared/cp/cp-context-menu.js +309 -0
  919. package/neural-interface/public/shared/cp/cp-context-model.js +157 -0
  920. package/neural-interface/public/shared/cp/cp-context-window.js +80 -0
  921. package/neural-interface/public/shared/cp/cp-ctx.js +11 -0
  922. package/neural-interface/public/shared/cp/cp-diff.js +255 -0
  923. package/neural-interface/public/shared/cp/cp-event-rows.js +637 -0
  924. package/neural-interface/public/shared/cp/cp-events.js +846 -0
  925. package/neural-interface/public/shared/cp/cp-markdown.js +104 -0
  926. package/neural-interface/public/shared/cp/cp-permission-model.js +905 -0
  927. package/neural-interface/public/shared/cp/cp-permissions.js +626 -0
  928. package/neural-interface/public/shared/cp/cp-rehydrate.js +113 -0
  929. package/neural-interface/public/shared/cp/cp-restore.js +224 -0
  930. package/neural-interface/public/shared/cp/cp-session-model.js +338 -0
  931. package/neural-interface/public/shared/cp/cp-session-settings.js +254 -0
  932. package/neural-interface/public/shared/cp/cp-sessions.js +227 -0
  933. package/neural-interface/public/shared/cp/cp-statusline.js +153 -0
  934. package/neural-interface/public/shared/cp/cp-styles.js +349 -0
  935. package/neural-interface/public/shared/cp/cp-tasks-model.js +282 -0
  936. package/neural-interface/public/shared/cp/cp-tasks.js +107 -0
  937. package/neural-interface/public/shared/cp/cp-temporary-view.js +56 -0
  938. package/neural-interface/public/shared/cp/cp-temporary.js +231 -0
  939. package/neural-interface/public/shared/cp/cp-tool-cards.js +326 -0
  940. package/neural-interface/public/shared/cp/cp-tool-results.js +618 -0
  941. package/neural-interface/public/shared/cp/cp-usage-model.js +124 -0
  942. package/neural-interface/public/shared/graph-activity.js +68 -0
  943. package/neural-interface/public/shared/html-shell.js +107 -12
  944. package/neural-interface/public/shared/i18n.js +132 -34
  945. package/neural-interface/public/shared/node-positions-store.js +44 -0
  946. package/neural-interface/public/shared/ocp-hidden-models.js +116 -0
  947. package/neural-interface/public/shared/ocp-v2/ocp-v2-approvals.js +355 -0
  948. package/neural-interface/public/shared/ocp-v2/ocp-v2-autoaccept-button.js +35 -0
  949. package/neural-interface/public/shared/ocp-v2/ocp-v2-automation-ownership.js +72 -0
  950. package/neural-interface/public/shared/ocp-v2/ocp-v2-binding.js +280 -0
  951. package/neural-interface/public/shared/ocp-v2/ocp-v2-caps.js +67 -0
  952. package/neural-interface/public/shared/ocp-v2/ocp-v2-changes-logic.js +179 -0
  953. package/neural-interface/public/shared/ocp-v2/ocp-v2-changes.js +164 -0
  954. package/neural-interface/public/shared/ocp-v2/ocp-v2-childpanel.js +725 -0
  955. package/neural-interface/public/shared/ocp-v2/ocp-v2-compact-button.js +75 -0
  956. package/neural-interface/public/shared/ocp-v2/ocp-v2-composer-logic.js +1204 -0
  957. package/neural-interface/public/shared/ocp-v2/ocp-v2-confirm-logic.js +117 -0
  958. package/neural-interface/public/shared/ocp-v2/ocp-v2-confirm.js +59 -0
  959. package/neural-interface/public/shared/ocp-v2/ocp-v2-context-gauge.js +252 -0
  960. package/neural-interface/public/shared/ocp-v2/ocp-v2-context-menu.js +478 -0
  961. package/neural-interface/public/shared/ocp-v2/ocp-v2-context-model.js +179 -0
  962. package/neural-interface/public/shared/ocp-v2/ocp-v2-events.js +233 -0
  963. package/neural-interface/public/shared/ocp-v2/ocp-v2-icons.js +30 -0
  964. package/neural-interface/public/shared/ocp-v2/ocp-v2-manager.js +1065 -0
  965. package/neural-interface/public/shared/ocp-v2/ocp-v2-mention-hints.js +182 -0
  966. package/neural-interface/public/shared/ocp-v2/ocp-v2-modelpicker.js +655 -0
  967. package/neural-interface/public/shared/ocp-v2/ocp-v2-panel.js +2636 -0
  968. package/neural-interface/public/shared/ocp-v2/ocp-v2-plan.js +601 -0
  969. package/neural-interface/public/shared/ocp-v2/ocp-v2-profile-inheritance.js +78 -0
  970. package/neural-interface/public/shared/ocp-v2/ocp-v2-projectbar.js +649 -0
  971. package/neural-interface/public/shared/ocp-v2/ocp-v2-providers.js +35 -0
  972. package/neural-interface/public/shared/ocp-v2/ocp-v2-rehydrate.js +357 -0
  973. package/neural-interface/public/shared/ocp-v2/ocp-v2-render-logic.js +189 -0
  974. package/neural-interface/public/shared/ocp-v2/ocp-v2-render.js +1869 -0
  975. package/neural-interface/public/shared/ocp-v2/ocp-v2-select.js +42 -0
  976. package/neural-interface/public/shared/ocp-v2/ocp-v2-send-logic.js +117 -0
  977. package/neural-interface/public/shared/ocp-v2/ocp-v2-send.js +1714 -0
  978. package/neural-interface/public/shared/ocp-v2/ocp-v2-session-actions.js +468 -0
  979. package/neural-interface/public/shared/ocp-v2/ocp-v2-session-widgets.js +63 -0
  980. package/neural-interface/public/shared/ocp-v2/ocp-v2-sessions-logic.js +366 -0
  981. package/neural-interface/public/shared/ocp-v2/ocp-v2-settings-link.js +19 -0
  982. package/neural-interface/public/shared/ocp-v2/ocp-v2-slash-hints.js +343 -0
  983. package/neural-interface/public/shared/ocp-v2/ocp-v2-state.js +746 -0
  984. package/neural-interface/public/shared/ocp-v2/ocp-v2-status-logic.js +347 -0
  985. package/neural-interface/public/shared/ocp-v2/ocp-v2-status.js +338 -0
  986. package/neural-interface/public/shared/ocp-v2/ocp-v2-styles.js +3543 -0
  987. package/neural-interface/public/shared/ocp-v2/ocp-v2-subagents-logic.js +482 -0
  988. package/neural-interface/public/shared/ocp-v2/ocp-v2-tools-logic.js +351 -0
  989. package/neural-interface/public/shared/ocp-v2/ocp-v2-tools.js +168 -0
  990. package/neural-interface/public/shared/ocp-v2/ocp-v2-variantpicker.js +315 -0
  991. package/neural-interface/public/shared/ocp-v2/ocp-v2-ws.js +545 -0
  992. package/neural-interface/public/shared/provider-icons.js +30 -0
  993. package/neural-interface/public/shared/session-title.js +100 -0
  994. package/neural-interface/public/shared/settings/settings-ia.js +389 -0
  995. package/neural-interface/public/shared/settings/settings-kit.js +234 -0
  996. package/neural-interface/public/shared/settings/settings-search.js +463 -0
  997. package/neural-interface/public/shared/settings/settings-shell.js +570 -0
  998. package/neural-interface/public/shared/state.js +5 -0
  999. package/neural-interface/public/shared/storage.js +50 -7
  1000. package/neural-interface/public/shared/styleguide/sg-agents.js +42 -0
  1001. package/neural-interface/public/shared/styleguide/sg-brand.js +4 -0
  1002. package/neural-interface/public/shared/styleguide/sg-color-client.js +388 -0
  1003. package/neural-interface/public/shared/styleguide/sg-colors.js +148 -0
  1004. package/neural-interface/public/shared/styleguide/sg-components.js +35 -0
  1005. package/neural-interface/public/shared/styleguide/sg-history.js +41 -0
  1006. package/neural-interface/public/shared/styleguide/sg-icons-logo.js +38 -0
  1007. package/neural-interface/public/shared/styleguide/sg-imagery.js +4 -0
  1008. package/neural-interface/public/shared/styleguide/sg-import-export.js +47 -0
  1009. package/neural-interface/public/shared/styleguide/sg-kit.js +281 -0
  1010. package/neural-interface/public/shared/styleguide/sg-labels.js +318 -0
  1011. package/neural-interface/public/shared/styleguide/sg-layout.js +4 -0
  1012. package/neural-interface/public/shared/styleguide/sg-motion.js +5 -0
  1013. package/neural-interface/public/shared/styleguide/sg-panel.js +229 -0
  1014. package/neural-interface/public/shared/styleguide/sg-preview.js +138 -0
  1015. package/neural-interface/public/shared/styleguide/sg-rules.js +9 -0
  1016. package/neural-interface/public/shared/styleguide/sg-shape.js +24 -0
  1017. package/neural-interface/public/shared/styleguide/sg-state.js +132 -0
  1018. package/neural-interface/public/shared/styleguide/sg-typography.js +124 -0
  1019. package/neural-interface/public/shared/styles.css +7883 -1155
  1020. package/neural-interface/public/shared/synabun-mascot.js +1625 -0
  1021. package/neural-interface/public/shared/synabun-ticker.js +376 -0
  1022. package/neural-interface/public/shared/term-renderer.js +343 -0
  1023. package/neural-interface/public/shared/ui-assistant-panel.js +10 -0
  1024. package/neural-interface/public/shared/ui-assistant.js +77 -0
  1025. package/neural-interface/public/shared/ui-automation-studio.js +5105 -3573
  1026. package/neural-interface/public/shared/ui-claude-panel.js +11685 -6333
  1027. package/neural-interface/public/shared/ui-codex-panel.js +12 -0
  1028. package/neural-interface/public/shared/ui-cost-widget.js +55 -34
  1029. package/neural-interface/public/shared/ui-detail.js +77 -14
  1030. package/neural-interface/public/shared/ui-explorer.js +360 -181
  1031. package/neural-interface/public/shared/ui-file-explorer.js +485 -107
  1032. package/neural-interface/public/shared/ui-help.js +2 -2
  1033. package/neural-interface/public/shared/ui-image-gallery.js +45 -21
  1034. package/neural-interface/public/shared/ui-judgments.js +1346 -0
  1035. package/neural-interface/public/shared/ui-keybinds.js +3 -2
  1036. package/neural-interface/public/shared/ui-link.js +105 -51
  1037. package/neural-interface/public/shared/ui-loading.js +4 -4
  1038. package/neural-interface/public/shared/ui-memory-maintenance.js +111 -0
  1039. package/neural-interface/public/shared/ui-menubar.js +89 -4
  1040. package/neural-interface/public/shared/ui-native-loop-router-state.js +94 -0
  1041. package/neural-interface/public/shared/ui-native-loop-router.js +493 -0
  1042. package/neural-interface/public/shared/ui-native-window-id.js +7 -0
  1043. package/neural-interface/public/shared/ui-navbar.js +357 -222
  1044. package/neural-interface/public/shared/ui-notifications.js +58 -12
  1045. package/neural-interface/public/shared/ui-opencode-panel-v2.js +17 -0
  1046. package/neural-interface/public/shared/ui-panels.js +15 -7
  1047. package/neural-interface/public/shared/ui-resume.js +823 -653
  1048. package/neural-interface/public/shared/ui-schedule-queue.js +172 -0
  1049. package/neural-interface/public/shared/ui-schedules-studio.js +1882 -0
  1050. package/neural-interface/public/shared/ui-scroll-follow.js +194 -0
  1051. package/neural-interface/public/shared/ui-sessions.js +789 -34
  1052. package/neural-interface/public/shared/ui-settings.js +5793 -2190
  1053. package/neural-interface/public/shared/ui-sidepanel-layout.js +109 -0
  1054. package/neural-interface/public/shared/ui-sidepanel-runtime.js +19 -0
  1055. package/neural-interface/public/shared/ui-sidepanel-session-entry.js +40 -0
  1056. package/neural-interface/public/shared/ui-sidepanel-sessions.js +221 -0
  1057. package/neural-interface/public/shared/ui-sidepanel-state.js +131 -0
  1058. package/neural-interface/public/shared/ui-sidepanel-tray.js +547 -0
  1059. package/neural-interface/public/shared/ui-sidepanel-windows.js +387 -0
  1060. package/neural-interface/public/shared/ui-skills.js +18 -32
  1061. package/neural-interface/public/shared/ui-styleguide.js +35 -0
  1062. package/neural-interface/public/shared/ui-sync.js +87 -0
  1063. package/neural-interface/public/shared/ui-terminal.js +7877 -6385
  1064. package/neural-interface/public/shared/ui-tool-updates.js +292 -0
  1065. package/neural-interface/public/shared/ui-tooltip.js +156 -15
  1066. package/neural-interface/public/shared/ui-tutorial-draw.js +119 -683
  1067. package/neural-interface/public/shared/ui-tutorial-layout.js +135 -0
  1068. package/neural-interface/public/shared/ui-tutorial-steps.js +59 -2209
  1069. package/neural-interface/public/shared/ui-tutorial.css +102 -0
  1070. package/neural-interface/public/shared/ui-tutorial.js +557 -1076
  1071. package/neural-interface/public/shared/ui-update.js +420 -68
  1072. package/neural-interface/public/shared/ui-whatsapp.js +941 -0
  1073. package/neural-interface/public/shared/ui-whiteboard.js +1076 -233
  1074. package/neural-interface/public/shared/ui-workspaces.js +2 -1
  1075. package/neural-interface/public/shared/utils.js +58 -0
  1076. package/neural-interface/public/shared/vterm-buffer.js +15 -5
  1077. package/neural-interface/public/shared/whatsapp/wa-phone.js +65 -0
  1078. package/neural-interface/public/shared/whatsapp/wa-view.js +411 -0
  1079. package/neural-interface/public/sidepanel-session.html +18 -0
  1080. package/neural-interface/public/sw.js +8 -2
  1081. package/neural-interface/public/synabun.png +0 -0
  1082. package/neural-interface/public/variant/2d/graph.js +1707 -1635
  1083. package/neural-interface/public/variant/2d/lasso.js +2 -1
  1084. package/neural-interface/public/variant/2d/layout.js +595 -594
  1085. package/neural-interface/public/variant/2d/main.js +556 -521
  1086. package/neural-interface/public/variant/2d/settings-gfx.js +18 -24
  1087. package/neural-interface/public/variant/3d/main.js +516 -500
  1088. package/neural-interface/public/variant/3d/map-controls.js +144 -0
  1089. package/neural-interface/public/variant/3d/map-data.js +251 -0
  1090. package/neural-interface/public/variant/3d/map-labels.js +241 -0
  1091. package/neural-interface/public/variant/3d/map-pick.js +90 -0
  1092. package/neural-interface/public/variant/3d/map-renderer.js +521 -0
  1093. package/neural-interface/public/variant/3d/map-shaders.js +158 -0
  1094. package/neural-interface/public/variant/3d/map-view.js +618 -0
  1095. package/neural-interface/public/vendor/three/manifest.json +3 -0
  1096. package/neural-interface/public/vendor/three/three-0.169.0.min.js +3844 -0
  1097. package/neural-interface/public/vendor/xterm/manifest.json +3 -0
  1098. package/neural-interface/public/vendor/xterm/xterm-6.0.0.css +285 -0
  1099. package/neural-interface/public/vendor/xterm/xterm-6.0.0.min.js +192 -0
  1100. package/neural-interface/scripts/build-vendor.mjs +64 -0
  1101. package/neural-interface/scripts/codex-protocol-fixture.mjs +83 -0
  1102. package/neural-interface/scripts/rebuild-pty.js +37 -23
  1103. package/neural-interface/scripts/vendor-three-entry.js +24 -0
  1104. package/neural-interface/scripts/vendor-xterm-entry.js +8 -0
  1105. package/neural-interface/server.js +33948 -15000
  1106. package/neural-interface/skins/default/skin.css +90 -0
  1107. package/neural-interface/skins/default/skin.json +8 -0
  1108. package/neural-interface/templates/rulesets/README.md +9 -0
  1109. package/neural-interface/templates/rulesets/claude.md +3 -0
  1110. package/neural-interface/templates/rulesets/codex.md +2 -0
  1111. package/neural-interface/templates/rulesets/coexistence.md +6 -0
  1112. package/neural-interface/templates/rulesets/core.md +26 -0
  1113. package/neural-interface/templates/rulesets/cursor.md +2 -0
  1114. package/neural-interface/templates/rulesets/gemini.md +2 -0
  1115. package/neural-interface/templates/rulesets/legacy-hashes.json +227 -0
  1116. package/neural-interface/templates/rulesets/manifest.json +12 -0
  1117. package/neural-interface/templates/rulesets/opencode.md +2 -0
  1118. package/package.json +119 -53
  1119. package/postinstall.js +125 -26
  1120. package/preuninstall.js +187 -0
  1121. package/scripts/audit-claude-hook-usage.mjs +12 -0
  1122. package/scripts/audit-memory-duplicates.mjs +44 -0
  1123. package/scripts/measure-claude-hook-overhead.mjs +77 -0
  1124. package/scripts/recover-user-config.mjs +254 -0
  1125. package/scripts/restore-data-home-from-backup.mjs +239 -0
  1126. package/setup.js +804 -260
  1127. package/skills/leonardo/SKILL.md +19 -10
  1128. package/skills/leonardo/modules/image-prompter.md +18 -12
  1129. package/skills/leonardo/modules/video-prompter.md +19 -13
  1130. package/skills/synabun/SKILL.md +209 -185
  1131. package/skills/synabun/icon.png +0 -0
  1132. package/skills/synabun/modules/audit.md +380 -374
  1133. package/skills/synabun/modules/changelog.md +15 -6
  1134. package/skills/synabun/modules/idea.md +148 -144
  1135. package/skills/synabun/modules/memorize.md +13 -4
  1136. package/skills/synabun/modules/schedule.md +198 -0
  1137. package/skills/synabun/synabunicon.png +0 -0
  1138. package/updater.cmd +31 -0
  1139. package/updater.mjs +382 -0
  1140. package/updater.sh +29 -0
  1141. package/hooks/claude-code/test-user-learning.mjs +0 -531
  1142. package/neural-interface/public/claude-chat.css +0 -878
  1143. package/neural-interface/public/claude-chat.html +0 -92
  1144. package/neural-interface/public/claude-chat.js +0 -1168
  1145. package/neural-interface/public/index-legacy.html +0 -14677
  1146. package/neural-interface/public/index2d-legacy.html +0 -8193
  1147. package/neural-interface/public/shared/html-term-renderer.js +0 -1022
  1148. package/neural-interface/public/variant/3d/background.js +0 -884
  1149. package/neural-interface/public/variant/3d/camera.js +0 -661
  1150. package/neural-interface/public/variant/3d/gfx.js +0 -116
  1151. package/neural-interface/public/variant/3d/graph.js +0 -2399
  1152. package/neural-interface/public/variant/3d/settings-gfx.js +0 -228
  1153. package/neural-interface/templates/CLAUDE-template.md +0 -211
@@ -1,89 +1,5 @@
1
- // ═══════════════════════════════════════════
2
- // TUTORIAL STEP DEFINITIONS
3
- // ═══════════════════════════════════════════
4
- //
5
- // Each step describes what to show and how.
6
- // Steps with whiteboardMode: true render directly on the whiteboard
7
- // using a render() function. Others use the legacy overlay+card mode.
8
-
9
- import {
10
- handwrittenLabel,
11
- createDoodle,
12
- createHandDrawnUnderline,
13
- createAnimatedArrow,
14
- createWobblyCircle,
15
- createHighlightCircle,
16
- } from './ui-tutorial-draw.js';
17
- import { emit } from './state.js';
18
- import { storage, flushStorage } from './storage.js';
19
- import { KEYS } from './constants.js';
20
- import { createTerminalSession } from './api.js';
21
- import { toggleExplorer } from './ui-explorer.js';
22
- import { toggleFileExplorer } from './ui-file-explorer.js';
23
- import { toggleClaudePanel, isClaudePanelOpen } from './ui-claude-panel.js';
24
-
25
-
26
- // ── Settings hint (shown when user declines explore) ──────────
27
- function _showSettingsHint(svg, dom, cx, cy, goToStep) {
28
- svg.innerHTML = '';
29
- dom.innerHTML = '';
30
-
31
- handwrittenLabel(svg, 'You can do this at any time from Project Settings', {
32
- x: cx,
33
- y: cy,
34
- color: 'rgba(255, 255, 255, 0.5)',
35
- fontSize: 28,
36
- textAnchor: 'middle',
37
- duration: 400,
38
- });
39
-
40
- createDoodle(svg, 'star', {
41
- x: cx + 280,
42
- y: cy - 30,
43
- scale: 0.9,
44
- color: 'rgba(255, 255, 255, 0.25)',
45
- duration: 400,
46
- });
47
-
48
- createDoodle(svg, 'sparkle', {
49
- x: cx - 290,
50
- y: cy - 20,
51
- scale: 0.8,
52
- color: 'rgba(255, 255, 255, 0.2)',
53
- duration: 350,
54
- });
55
-
56
- // Continue button — user clicks to advance (no auto-timer)
57
- const contEl = document.createElement('div');
58
- contEl.className = 'wb-tutorial-btn';
59
- contEl.textContent = 'Continue';
60
- contEl.style.cssText = `
61
- position: absolute; left: ${cx}px; top: ${cy + 60}px;
62
- transform: translate(-50%, 0);
63
- font-family: 'Caveat', cursive; font-size: 22px;
64
- color: rgba(255, 255, 255, 0.35);
65
- pointer-events: auto; opacity: 0;
66
- transition: opacity 0.4s ease 0.8s;
67
- `;
68
- dom.appendChild(contEl);
69
- requestAnimationFrame(() => { contEl.style.opacity = '1'; });
70
- contEl.addEventListener('mouseenter', () => {
71
- contEl.style.color = 'rgba(255, 255, 255, 0.7)';
72
- contEl.style.transform = 'translate(-50%, 0) scale(1.08)';
73
- });
74
- contEl.addEventListener('mouseleave', () => {
75
- contEl.style.color = 'rgba(255, 255, 255, 0.35)';
76
- contEl.style.transform = 'translate(-50%, 0) scale(1)';
77
- });
78
- contEl.addEventListener('click', () => {
79
- goToStep(6);
80
- });
81
- }
82
-
83
-
84
- // ── Exploration prompt (injected into CLI on launch) ────────
85
- // This prompt MUST be forceful and explicit — weaker models (Haiku, Flash, o4-mini)
86
- // will only follow instructions that are direct and structured as mandatory steps.
1
+ // The storyboard is shared by 2D and 3D. Copy lives in the `tutorial` namespace
2
+ // of i18n/<locale>.json; this file only says what each step points at.
87
3
  export function buildExplorePrompt(projectSlug) {
88
4
  const cat = projectSlug || 'project';
89
5
  const catProject = `${cat}-project`;
@@ -145,2132 +61,66 @@ export function buildExplorePrompt(projectSlug) {
145
61
  ].join(' ');
146
62
  }
147
63
 
148
- // ── Launch exploration CLI session ──────────────────────────
149
- async function _launchExploration(goToStep) {
150
- console.log('[SynaBun] _launchExploration: starting');
151
- const cli = storage.getItem(KEYS.ONBOARDING_CLI) || 'claude-code';
152
- const model = storage.getItem(KEYS.ONBOARDING_MODEL) || null;
153
-
154
- // Use the project chosen in the onboarding project picker (step 4)
155
- let cwd = null;
156
- let projectSlug = null;
157
- try {
158
- const stored = JSON.parse(storage.getItem(KEYS.ONBOARDING_PROJECT) || 'null');
159
- if (stored?.path) {
160
- cwd = stored.path;
161
- const folderName = stored.label || cwd.split(/[\\/]/).filter(Boolean).pop() || 'project';
162
- projectSlug = folderName.toLowerCase().replace(/[^a-z0-9]+/g, '');
163
- }
164
- } catch { /* fallback to null (home dir) */ }
165
-
166
- const prompt = buildExplorePrompt(projectSlug);
167
-
168
- try {
169
- const result = await createTerminalSession(cli, 120, 30, cwd, model ? { model } : {});
170
- console.log('[SynaBun] _launchExploration: session created, id =', result?.sessionId);
171
- if (result?.sessionId) {
172
- emit('terminal:attach-floating', {
173
- terminalSessionId: result.sessionId,
174
- profile: cli,
175
- initialMessage: prompt,
176
- autoSubmit: true,
177
- });
178
- }
179
- } catch (err) {
180
- console.error('[SynaBun] Exploration launch failed:', err);
181
- }
182
-
183
- // Advance to tutorial welcome regardless of launch success
184
- goToStep(6);
185
- }
186
-
187
-
188
- export const TUTORIAL_STEPS = [
189
- // ── Step 0: Explore Your Project? (onboarding pre-step) ───
190
- {
191
- id: 'onboarding-explore',
192
- whiteboardMode: true,
193
-
194
- render({ svg, dom, seq, vw, vh, nextStep, goToStep, createButton }) {
195
- const cx = vw / 2;
196
- const cy = vh / 2 - 40;
197
-
198
- // 1. Hand-drawn question text
199
- seq.add(() => handwrittenLabel(svg, 'Explore your project and create memories?', {
200
- x: cx,
201
- y: cy,
202
- color: 'rgba(255, 255, 255, 0.55)',
203
- fontSize: 34,
204
- textAnchor: 'middle',
205
- duration: 400,
206
- }), 200);
207
-
208
- // 2. Decorative sparkle doodles
209
- seq.add(() => createDoodle(svg, 'sparkle', {
210
- x: cx - 260,
211
- y: cy - 55,
212
- scale: 1.1,
213
- color: 'rgba(255, 255, 255, 0.3)',
214
- duration: 350,
215
- }), 200);
216
-
217
- seq.add(() => createDoodle(svg, 'sparkle', {
218
- x: cx + 230,
219
- y: cy + 15,
220
- scale: 0.85,
221
- color: 'rgba(255, 255, 255, 0.3)',
222
- duration: 350,
223
- }), 200);
224
-
225
- // 3. Yes / No buttons
226
- seq.add(() => {
227
- const btnY = cy + 50;
228
- const gap = 80;
229
-
230
- const yesEl = createButton(dom, 'Yes', {
231
- x: cx - gap,
232
- y: btnY,
233
- color: 'rgba(255, 255, 255, 0.5)',
234
- fontSize: 28,
235
- onClick: () => {
236
- storage.setItem(KEYS.ONBOARDING_EXPLORE, 'yes');
237
- flushStorage();
238
- nextStep();
239
- },
240
- });
241
-
242
- const noEl = createButton(dom, 'No', {
243
- x: cx + gap,
244
- y: btnY,
245
- color: 'rgba(255, 255, 255, 0.5)',
246
- fontSize: 28,
247
- onClick: () => {
248
- storage.setItem(KEYS.ONBOARDING_EXPLORE, 'no');
249
- flushStorage();
250
- _showSettingsHint(svg, dom, cx, cy, goToStep);
251
- },
252
- });
253
-
254
- // Hand-drawn underlines beneath buttons
255
- setTimeout(() => {
256
- const yesRect = yesEl.getBoundingClientRect();
257
- const noRect = noEl.getBoundingClientRect();
258
- createHandDrawnUnderline(svg, yesRect, {
259
- color: 'rgba(255, 255, 255, 0.22)',
260
- wobbleSeed: 'explore-yes-ul', duration: 250, offset: 2,
261
- });
262
- createHandDrawnUnderline(svg, noRect, {
263
- color: 'rgba(255, 255, 255, 0.22)',
264
- wobbleSeed: 'explore-no-ul', duration: 250, offset: 2,
265
- });
266
- }, 100);
267
-
268
- return {
269
- destroy() { yesEl.remove(); noEl.remove(); },
270
- };
271
- }, 200);
272
- },
273
- },
274
-
275
- // ── Step 1: Token Warning (Red Alert) ─────────────────────
276
- {
277
- id: 'onboarding-token-warning',
278
- whiteboardMode: true,
279
-
280
- render({ svg, dom, seq, vw, vh, nextStep, prevStep, goToStep, createButton }) {
281
- const cx = vw / 2;
282
- const cy = vh / 2 - 40;
283
-
284
- // 1. Red-tinted alert heading
285
- seq.add(() => handwrittenLabel(svg, 'Heads up!', {
286
- x: cx,
287
- y: cy - 30,
288
- color: 'rgba(239, 83, 80, 0.65)',
289
- fontSize: 38,
290
- textAnchor: 'middle',
291
- duration: 400,
292
- }), 200);
293
-
294
- // 2. Warning message body (white, not red)
295
- seq.add(() => handwrittenLabel(svg, 'Exploring your project can burn tokens.', {
296
- x: cx,
297
- y: cy + 20,
298
- color: 'rgba(255, 255, 255, 0.45)',
299
- fontSize: 26,
300
- textAnchor: 'middle',
301
- duration: 350,
302
- }), 300);
303
-
304
- seq.add(() => handwrittenLabel(svg, 'Choose your model and provider with caution.', {
305
- x: cx,
306
- y: cy + 55,
307
- color: 'rgba(255, 255, 255, 0.35)',
308
- fontSize: 24,
309
- textAnchor: 'middle',
310
- duration: 350,
311
- }), 200);
312
-
313
- // 3. Alert triangle doodles
314
- seq.add(() => createDoodle(svg, 'alert', {
315
- x: cx - 250,
316
- y: cy - 50,
317
- scale: 1.0,
318
- color: 'rgba(239, 83, 80, 0.3)',
319
- duration: 350,
320
- }), 200);
321
-
322
- seq.add(() => createDoodle(svg, 'alert', {
323
- x: cx + 230,
324
- y: cy + 10,
325
- scale: 0.8,
326
- color: 'rgba(239, 83, 80, 0.25)',
327
- duration: 350,
328
- }), 200);
329
-
330
- // 4. Continue / Back buttons
331
- seq.add(() => {
332
- const btnY = cy + 110;
333
- const gap = 90;
334
-
335
- const backEl = createButton(dom, 'Back', {
336
- x: cx - gap,
337
- y: btnY,
338
- color: 'rgba(255, 255, 255, 0.35)',
339
- fontSize: 24,
340
- onClick: () => prevStep(),
341
- });
342
-
343
- const contEl = createButton(dom, 'Continue', {
344
- x: cx + gap,
345
- y: btnY,
346
- color: 'rgba(255, 255, 255, 0.45)',
347
- fontSize: 24,
348
- onClick: () => nextStep(),
349
- });
350
-
351
- // Subtle underlines
352
- setTimeout(() => {
353
- const backRect = backEl.getBoundingClientRect();
354
- const contRect = contEl.getBoundingClientRect();
355
- createHandDrawnUnderline(svg, backRect, {
356
- color: 'rgba(255, 255, 255, 0.15)',
357
- wobbleSeed: 'warn-back-ul', duration: 250, offset: 2,
358
- });
359
- createHandDrawnUnderline(svg, contRect, {
360
- color: 'rgba(255, 255, 255, 0.15)',
361
- wobbleSeed: 'warn-cont-ul', duration: 250, offset: 2,
362
- });
363
- }, 100);
364
-
365
- return {
366
- destroy() { backEl.remove(); contEl.remove(); },
367
- };
368
- }, 200);
369
- },
370
- },
371
-
372
- // ── Step 2: CLI Picker ─────────────────────────────────────
373
- {
374
- id: 'onboarding-cli-picker',
375
- whiteboardMode: true,
376
-
377
- render({ svg, dom, seq, vw, vh, nextStep, prevStep, goToStep, createButton }) {
378
- const cx = vw / 2;
379
- const cy = vh / 2 - 50;
380
-
381
- // SVG logo paths (same as tic-tac-toe opponent picker)
382
- const ICON_CLAUDE = '<svg viewBox="0 0 24 24" fill="currentColor"><path d="M4.709 15.955l4.72-2.647.08-.23-.08-.128H9.2l-.79-.048-2.698-.073-2.339-.097-2.266-.122-.571-.121L0 11.784l.055-.352.48-.321.686.06 1.52.103 2.278.158 1.652.097 2.449.255h.389l.055-.157-.134-.098-.103-.097-2.358-1.596-2.552-1.688-1.336-.972-.724-.491-.364-.462-.158-1.008.656-.722.881.06.225.061.893.686 1.908 1.476 2.491 1.833.365.304.145-.103.019-.073-.164-.274-1.355-2.446-1.446-2.49-.644-1.032-.17-.619a2.97 2.97 0 01-.104-.729L6.283.134 6.696 0l.996.134.42.364.62 1.414 1.002 2.229 1.555 3.03.456.898.243.832.091.255h.158V9.01l.128-1.706.237-2.095.23-2.695.08-.76.376-.91.747-.492.584.28.48.685-.067.444-.286 1.851-.559 2.903-.364 1.942h.212l.243-.242.985-1.306 1.652-2.064.73-.82.85-.904.547-.431h1.033l.76 1.129-.34 1.166-1.064 1.347-.881 1.142-1.264 1.7-.79 1.36.073.11.188-.02 2.856-.606 1.543-.28 1.841-.315.833.388.091.395-.328.807-1.969.486-2.309.462-3.439.813-.042.03.049.061 1.549.146.662.036h1.622l3.02.225.79.522.474.638-.079.485-1.215.62-1.64-.389-3.829-.91-1.312-.329h-.182v.11l1.093 1.068 2.006 1.81 2.509 2.33.127.578-.322.455-.34-.049-2.205-1.657-.851-.747-1.926-1.62h-.128v.17l.444.649 2.345 3.521.122 1.08-.17.353-.608.213-.668-.122-1.374-1.925-1.415-2.167-1.143-1.943-.14.08-.674 7.254-.316.37-.729.28-.607-.461-.322-.747.322-1.476.389-1.924.315-1.53.286-1.9.17-.632-.012-.042-.14.018-1.434 1.967-2.18 2.945-1.726 1.845-.414.164-.717-.37.067-.662.401-.589 2.388-3.036 1.44-1.882.93-1.086-.006-.158h-.055L4.132 18.56l-1.13.146-.487-.456.061-.746.231-.243 1.908-1.312-.006.006z"/></svg>';
383
- const ICON_OPENAI = '<svg viewBox="0 0 24 24" fill="currentColor"><path d="M9.205 8.658v-2.26c0-.19.072-.333.238-.428l4.543-2.616c.619-.357 1.356-.523 2.117-.523 2.854 0 4.662 2.212 4.662 4.566 0 .167 0 .357-.024.547l-4.71-2.759a.797.797 0 00-.856 0l-5.97 3.473zm10.609 8.8V12.06c0-.333-.143-.57-.429-.737l-5.97-3.473 1.95-1.118a.433.433 0 01.476 0l4.543 2.617c1.309.76 2.189 2.378 2.189 3.948 0 1.808-1.07 3.473-2.76 4.163zM7.802 12.703l-1.95-1.142c-.167-.095-.239-.238-.239-.428V5.899c0-2.545 1.95-4.472 4.591-4.472 1 0 1.927.333 2.712.928L8.23 5.067c-.285.166-.428.404-.428.737v6.898zM12 15.128l-2.795-1.57v-3.33L12 8.658l2.795 1.57v3.33L12 15.128zm1.796 7.23c-1 0-1.927-.332-2.712-.927l4.686-2.712c.285-.166.428-.404.428-.737v-6.898l1.974 1.142c.167.095.238.238.238.428v5.233c0 2.545-1.974 4.472-4.614 4.472zm-5.637-5.303l-4.544-2.617c-1.308-.761-2.188-2.378-2.188-3.948A4.482 4.482 0 014.21 6.327v5.423c0 .333.143.571.428.738l5.947 3.449-1.95 1.118a.432.432 0 01-.476 0zm-.262 3.9c-2.688 0-4.662-2.021-4.662-4.519 0-.19.024-.38.047-.57l4.686 2.71c.286.167.571.167.856 0l5.97-3.448v2.26c0 .19-.07.333-.237.428l-4.543 2.616c-.619.357-1.356.523-2.117.523zm5.899 2.83a5.947 5.947 0 005.827-4.756C22.287 18.339 24 15.84 24 13.296c0-1.665-.713-3.282-1.998-4.448.119-.5.19-.999.19-1.498 0-3.401-2.759-5.947-5.946-5.947-.642 0-1.26.095-1.88.31A5.962 5.962 0 0010.205 0a5.947 5.947 0 00-5.827 4.757C1.713 5.447 0 7.945 0 10.49c0 1.666.713 3.283 1.998 4.448-.119.5-.19 1-.19 1.499 0 3.401 2.759 5.946 5.946 5.946.642 0 1.26-.095 1.88-.309a5.96 5.96 0 004.162 1.713z"/></svg>';
384
- const ICON_GEMINI = '<svg viewBox="0 0 24 24" fill="currentColor"><path d="M20.616 10.835a14.147 14.147 0 01-4.45-3.001 14.111 14.111 0 01-3.678-6.452.503.503 0 00-.975 0 14.134 14.134 0 01-3.679 6.452 14.155 14.155 0 01-4.45 3.001c-.65.28-1.318.505-2.002.678a.502.502 0 000 .975c.684.172 1.35.397 2.002.677a14.147 14.147 0 014.45 3.001 14.112 14.112 0 013.679 6.453.502.502 0 00.975 0c.172-.685.397-1.351.677-2.003a14.145 14.145 0 013.001-4.45 14.113 14.113 0 016.453-3.678.503.503 0 000-.975 13.245 13.245 0 01-2.003-.678z"/></svg>';
385
-
386
- const CLIS = [
387
- { id: 'claude-code', icon: ICON_CLAUDE, label: 'Claude Code', desc: 'Anthropic' },
388
- { id: 'codex', icon: ICON_OPENAI, label: 'Codex CLI', desc: 'OpenAI' },
389
- { id: 'gemini', icon: ICON_GEMINI, label: 'Gemini CLI', desc: 'Google' },
390
- ];
391
-
392
- // 1. Title
393
- seq.add(() => handwrittenLabel(svg, 'Pick your CLI', {
394
- x: cx, y: cy - 20,
395
- color: 'rgba(255, 255, 255, 0.55)',
396
- fontSize: 34, textAnchor: 'middle', duration: 400,
397
- }), 200);
398
-
399
- // 2. CLI cards (DOM elements, same style as ttt-picker)
400
- seq.add(() => {
401
- const cardY = cy + 40;
402
- const gap = 130;
403
- const els = [];
404
-
405
- CLIS.forEach((cli, i) => {
406
- const x = cx + (i - 1) * gap;
407
- const card = document.createElement('div');
408
- card.style.cssText = `
409
- position: absolute; left: ${x}px; top: ${cardY}px;
410
- transform: translate(-50%, 0);
411
- display: flex; flex-direction: column; align-items: center; gap: 8px;
412
- padding: 16px 22px; border: 1px solid rgba(255,255,255,0.06);
413
- border-radius: 12px; background: rgba(255,255,255,0.02);
414
- cursor: pointer; pointer-events: auto;
415
- transition: all 0.2s ease; opacity: 0;
416
- `;
417
- card.innerHTML = `
418
- <div style="width:36px;height:36px;color:rgba(255,255,255,0.4);transition:color 0.2s">${cli.icon}</div>
419
- <div style="font-family:'Caveat',cursive;font-size:18px;color:rgba(255,255,255,0.45);user-select:none;transition:color 0.2s">${cli.label}</div>
420
- <div style="font-size:11px;color:rgba(255,255,255,0.25);user-select:none">${cli.desc}</div>
421
- `;
422
- dom.appendChild(card);
423
- requestAnimationFrame(() => { card.style.opacity = '1'; });
424
-
425
- card.addEventListener('mouseenter', () => {
426
- card.style.background = 'rgba(255,255,255,0.06)';
427
- card.style.borderColor = 'rgba(255,255,255,0.15)';
428
- card.style.transform = 'translate(-50%, 0) translateY(-2px)';
429
- card.querySelector('div').style.color = 'rgba(255,255,255,0.7)';
430
- });
431
- card.addEventListener('mouseleave', () => {
432
- card.style.background = 'rgba(255,255,255,0.02)';
433
- card.style.borderColor = 'rgba(255,255,255,0.06)';
434
- card.style.transform = 'translate(-50%, 0)';
435
- card.querySelector('div').style.color = 'rgba(255,255,255,0.4)';
436
- });
437
- card.addEventListener('click', () => {
438
- storage.setItem(KEYS.ONBOARDING_CLI, cli.id);
439
- flushStorage();
440
- nextStep();
441
- });
442
- els.push(card);
443
- });
444
-
445
- return { destroy() { els.forEach(e => e.remove()); } };
446
- }, 300);
447
-
448
- // 3. Sparkle doodles
449
- seq.add(() => createDoodle(svg, 'sparkle', {
450
- x: cx - 240, y: cy - 50, scale: 0.9,
451
- color: 'rgba(255, 255, 255, 0.25)', duration: 350,
452
- }), 200);
453
- seq.add(() => createDoodle(svg, 'sparkle', {
454
- x: cx + 230, y: cy - 30, scale: 0.7,
455
- color: 'rgba(255, 255, 255, 0.2)', duration: 350,
456
- }), 200);
457
-
458
- // 4. Back button
459
- seq.add(() => {
460
- const backEl = createButton(dom, 'Back', {
461
- x: cx, y: cy + 180, fontSize: 22,
462
- color: 'rgba(255, 255, 255, 0.35)',
463
- onClick: () => prevStep(),
464
- });
465
- return { destroy() { backEl.remove(); } };
466
- }, 200);
467
- },
468
- },
469
-
470
- // ── Step 3: Model Picker ──────────────────────────────────
471
- {
472
- id: 'onboarding-model-picker',
473
- whiteboardMode: true,
474
-
475
- render({ svg, dom, seq, vw, vh, nextStep, prevStep, createButton }) {
476
- const cx = vw / 2;
477
- const cy = vh / 2 - 50;
478
-
479
- const CLI_MODELS = {
480
- 'claude-code': [
481
- { id: 'claude-opus-4-6', label: 'Opus 4.6', desc: 'Most capable', tier: 'top' },
482
- { id: 'claude-sonnet-4-6', label: 'Sonnet 4.6', desc: 'Balanced', tier: 'default' },
483
- { id: 'claude-haiku-4-5', label: 'Haiku 4.5', desc: 'Fastest', tier: 'light' },
484
- ],
485
- 'codex': [
486
- { id: 'o3', label: 'o3', desc: 'Deep reasoning', tier: 'top' },
487
- { id: 'o4-mini', label: 'o4-mini', desc: 'Fast reasoning', tier: 'default' },
488
- ],
489
- 'gemini': [
490
- { id: 'gemini-2.5-pro', label: '2.5 Pro', desc: 'Most capable', tier: 'default' },
491
- { id: 'gemini-2.5-flash', label: '2.5 Flash', desc: 'Lightweight', tier: 'light' },
492
- ],
493
- };
494
-
495
- const CLI_LABELS = {
496
- 'claude-code': 'Claude Code',
497
- 'codex': 'Codex CLI',
498
- 'gemini': 'Gemini CLI',
499
- };
500
-
501
- const chosenCli = storage.getItem(KEYS.ONBOARDING_CLI) || 'claude-code';
502
- const models = CLI_MODELS[chosenCli] || CLI_MODELS['claude-code'];
503
- const cliLabel = CLI_LABELS[chosenCli] || 'Claude Code';
504
-
505
- // 1. Title with CLI name
506
- seq.add(() => handwrittenLabel(svg, `Choose a model for ${cliLabel}`, {
507
- x: cx, y: cy - 20,
508
- color: 'rgba(255, 255, 255, 0.55)',
509
- fontSize: 32, textAnchor: 'middle', duration: 400,
510
- }), 200);
511
-
512
- // 2. Model cards
513
- seq.add(() => {
514
- const cardY = cy + 40;
515
- const gap = 150;
516
- const startX = cx - ((models.length - 1) / 2) * gap;
517
- const els = [];
518
-
519
- models.forEach((model, i) => {
520
- const x = startX + i * gap;
521
- const tierColor = model.tier === 'top'
522
- ? 'rgba(255, 180, 80, 0.5)'
523
- : model.tier === 'light'
524
- ? 'rgba(130, 200, 255, 0.5)'
525
- : 'rgba(255, 255, 255, 0.45)';
526
-
527
- const card = document.createElement('div');
528
- card.style.cssText = `
529
- position: absolute; left: ${x}px; top: ${cardY}px;
530
- transform: translate(-50%, 0);
531
- display: flex; flex-direction: column; align-items: center; gap: 6px;
532
- padding: 18px 26px; border: 1px solid rgba(255,255,255,0.06);
533
- border-radius: 12px; background: rgba(255,255,255,0.02);
534
- cursor: pointer; pointer-events: auto;
535
- transition: all 0.2s ease; opacity: 0;
536
- `;
537
- card.innerHTML = `
538
- <div style="font-family:'Caveat',cursive;font-size:22px;color:${tierColor};user-select:none;transition:color 0.2s">${model.label}</div>
539
- <div style="font-size:11px;color:rgba(255,255,255,0.3);user-select:none">${model.desc}</div>
540
- `;
541
- dom.appendChild(card);
542
- requestAnimationFrame(() => { card.style.opacity = '1'; });
543
-
544
- card.addEventListener('mouseenter', () => {
545
- card.style.background = 'rgba(255,255,255,0.06)';
546
- card.style.borderColor = 'rgba(255,255,255,0.15)';
547
- card.style.transform = 'translate(-50%, 0) translateY(-2px)';
548
- });
549
- card.addEventListener('mouseleave', () => {
550
- card.style.background = 'rgba(255,255,255,0.02)';
551
- card.style.borderColor = 'rgba(255,255,255,0.06)';
552
- card.style.transform = 'translate(-50%, 0)';
553
- });
554
- card.addEventListener('click', () => {
555
- storage.setItem(KEYS.ONBOARDING_MODEL, model.id);
556
- flushStorage();
557
- nextStep();
558
- });
559
- els.push(card);
560
- });
561
-
562
- return { destroy() { els.forEach(e => e.remove()); } };
563
- }, 300);
564
-
565
- // 3. Back button
566
- seq.add(() => {
567
- const backEl = createButton(dom, 'Back', {
568
- x: cx, y: cy + 180, fontSize: 22,
569
- color: 'rgba(255, 255, 255, 0.35)',
570
- onClick: () => prevStep(),
571
- });
572
- return { destroy() { backEl.remove(); } };
573
- }, 200);
574
- },
575
- },
576
-
577
- // ── Step 4: Project Picker ───────────────────────────────────
578
- {
579
- id: 'onboarding-project-picker',
580
- whiteboardMode: true,
581
-
582
- render({ svg, dom, seq, vw, vh, nextStep, prevStep, goToStep, createButton }) {
583
- const cx = vw / 2;
584
- const cy = vh / 2 - 60;
585
-
586
- // 1. Title
587
- seq.add(() => handwrittenLabel(svg, 'Which project should we explore?', {
588
- x: cx, y: cy - 30,
589
- color: 'rgba(255, 255, 255, 0.55)',
590
- fontSize: 32, textAnchor: 'middle', duration: 400,
591
- }), 200);
592
-
593
- // 2. Fetch projects and build cards
594
- seq.add(async () => {
595
- let projects = [];
596
- try {
597
- const res = await fetch('/api/terminal/profiles');
598
- const data = await res.json();
599
- projects = data.projects || [];
600
- } catch { /* empty list fallback */ }
601
-
602
- const els = [];
603
- const cardY = cy + 30;
604
- const maxVisible = 4;
605
- const visible = projects.slice(0, maxVisible);
606
- // +1 for the "Add Project" card
607
- const totalCards = visible.length + 1;
608
- const gap = Math.min(170, (vw - 160) / totalCards);
609
- const startX = cx - ((totalCards - 1) * gap) / 2;
610
-
611
- // Folder icon for project cards
612
- const ICON_FOLDER = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" style="width:28px;height:28px"><path d="M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z"/></svg>';
613
- const ICON_PLUS = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" style="width:28px;height:28px"><line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></svg>';
614
-
615
- function makeCard(x, icon, label, sublabel, color, onClick) {
616
- const card = document.createElement('div');
617
- card.style.cssText = `
618
- position: absolute; left: ${x}px; top: ${cardY}px;
619
- transform: translate(-50%, 0);
620
- display: flex; flex-direction: column; align-items: center; gap: 8px;
621
- padding: 18px 22px; border: 1px solid rgba(255,255,255,0.06);
622
- border-radius: 12px; background: rgba(255,255,255,0.02);
623
- cursor: pointer; pointer-events: auto;
624
- transition: all 0.2s ease; opacity: 0;
625
- min-width: 120px; max-width: 150px;
626
- `;
627
- card.innerHTML = `
628
- <div style="color:${color};opacity:0.7;transition:opacity 0.2s">${icon}</div>
629
- <div style="font-family:'Caveat',cursive;font-size:20px;color:${color};user-select:none;text-align:center;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:130px" title="${label}">${label}</div>
630
- ${sublabel ? `<div style="font-size:10px;color:rgba(255,255,255,0.25);user-select:none;max-width:130px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-family:'JetBrains Mono',monospace" title="${sublabel}">${sublabel}</div>` : ''}
631
- `;
632
- dom.appendChild(card);
633
- requestAnimationFrame(() => { card.style.opacity = '1'; });
634
-
635
- card.addEventListener('mouseenter', () => {
636
- card.style.background = 'rgba(255,255,255,0.06)';
637
- card.style.borderColor = 'rgba(255,255,255,0.15)';
638
- card.style.transform = 'translate(-50%, 0) translateY(-2px)';
639
- });
640
- card.addEventListener('mouseleave', () => {
641
- card.style.background = 'rgba(255,255,255,0.02)';
642
- card.style.borderColor = 'rgba(255,255,255,0.06)';
643
- card.style.transform = 'translate(-50%, 0)';
644
- });
645
- card.addEventListener('click', onClick);
646
- els.push(card);
647
- }
648
-
649
- // Project cards
650
- visible.forEach((proj, i) => {
651
- const x = startX + i * gap;
652
- const folder = proj.label || proj.path.split(/[\\/]/).filter(Boolean).pop();
653
- makeCard(x, ICON_FOLDER, folder, proj.path.replace(/\\/g, '/'), 'rgba(255, 255, 255, 0.45)', () => {
654
- storage.setItem(KEYS.ONBOARDING_PROJECT, JSON.stringify({ path: proj.path, label: proj.label || folder }));
655
- flushStorage();
656
- nextStep();
657
- });
658
- });
659
-
660
- // "Add Project" card (always last)
661
- const addX = startX + visible.length * gap;
662
- makeCard(addX, ICON_PLUS, 'Add Project', null, 'rgba(79, 195, 247, 0.5)', async () => {
663
- // Open Settings on the Projects tab
664
- const { openSettingsModal } = await import('./ui-settings.js');
665
- await openSettingsModal();
666
- const panel = document.getElementById('settings-panel');
667
- if (panel) {
668
- panel.querySelectorAll('.settings-nav-item').forEach(n => n.classList.remove('active'));
669
- panel.querySelectorAll('.settings-tab-body').forEach(b => b.classList.remove('active'));
670
- const nav = panel.querySelector('.settings-nav-item[data-tab="projects"]');
671
- const tab = panel.querySelector('.settings-tab-body[data-tab="projects"]');
672
- if (nav) nav.classList.add('active');
673
- if (tab) tab.classList.add('active');
674
- }
675
- });
676
-
677
- // If no projects exist, show hint
678
- if (projects.length === 0) {
679
- handwrittenLabel(svg, 'No projects registered yet — add one to get started', {
680
- x: cx, y: cardY + 140,
681
- color: 'rgba(255, 255, 255, 0.3)',
682
- fontSize: 19, textAnchor: 'middle', duration: 300,
683
- });
684
- }
685
-
686
- return { destroy() { els.forEach(e => e.remove()); } };
687
- }, 300);
688
-
689
- // 3. Back button
690
- seq.add(() => {
691
- const backEl = createButton(dom, 'Back', {
692
- x: cx, y: cy + 210, fontSize: 22,
693
- color: 'rgba(255, 255, 255, 0.35)',
694
- onClick: () => prevStep(),
695
- });
696
- return { destroy() { backEl.remove(); } };
697
- }, 200);
698
- },
699
- },
700
-
701
- // ── Step 5: Memory Explanation ─────────────────────────────
702
- {
703
- id: 'onboarding-memory-explain',
704
- whiteboardMode: true,
705
-
706
- render({ svg, dom, seq, vw, vh, nextStep, prevStep, goToStep, createButton }) {
707
- const cx = vw / 2;
708
- const cy = vh / 2 - 70;
709
-
710
- // 1. Title
711
- seq.add(() => handwrittenLabel(svg, 'Memories are regenerative', {
712
- x: cx, y: cy,
713
- color: 'rgba(255, 255, 255, 0.55)',
714
- fontSize: 34, textAnchor: 'middle', duration: 400,
715
- }), 200);
716
-
717
- // 2. Explanation lines
718
- seq.add(() => handwrittenLabel(svg, 'A cheaper model can lay the groundwork.', {
719
- x: cx, y: cy + 50,
720
- color: 'rgba(255, 255, 255, 0.4)',
721
- fontSize: 24, textAnchor: 'middle', duration: 350,
722
- }), 300);
723
-
724
- seq.add(() => handwrittenLabel(svg, 'When a stronger model uses those memories later,', {
725
- x: cx, y: cy + 85,
726
- color: 'rgba(255, 255, 255, 0.4)',
727
- fontSize: 24, textAnchor: 'middle', duration: 350,
728
- }), 200);
729
-
730
- seq.add(() => handwrittenLabel(svg, 'it will refine and update them automatically.', {
731
- x: cx, y: cy + 120,
732
- color: 'rgba(255, 255, 255, 0.4)',
733
- fontSize: 24, textAnchor: 'middle', duration: 350,
734
- }), 200);
735
-
736
- // 3. Key takeaway
737
- seq.add(() => handwrittenLabel(svg, 'Starting small is not a compromise -- it is a strategy.', {
738
- x: cx, y: cy + 175,
739
- color: 'rgba(255, 255, 255, 0.5)',
740
- fontSize: 26, textAnchor: 'middle', duration: 400,
741
- }), 400);
742
-
743
- // 4. Sparkle doodles
744
- seq.add(() => createDoodle(svg, 'sparkle', {
745
- x: cx - 300, y: cy + 40, scale: 0.9,
746
- color: 'rgba(255, 255, 255, 0.2)', duration: 350,
747
- }), 200);
748
- seq.add(() => createDoodle(svg, 'star', {
749
- x: cx + 280, y: cy + 100, scale: 0.8,
750
- color: 'rgba(255, 255, 255, 0.2)', duration: 350,
751
- }), 200);
752
-
753
- // 5. Navigation
754
- seq.add(() => {
755
- const navY = cy + 235;
756
- const backEl = createButton(dom, 'Back', {
757
- x: cx - 80, y: navY, fontSize: 22,
758
- color: 'rgba(255, 255, 255, 0.35)',
759
- onClick: () => prevStep(),
760
- });
761
- const contEl = createButton(dom, 'Begin Exploration', {
762
- x: cx + 100, y: navY, fontSize: 22,
763
- color: 'rgba(255, 255, 255, 0.45)',
764
- onClick: () => _launchExploration(goToStep),
765
- });
766
- return { destroy() { backEl.remove(); contEl.remove(); } };
767
- }, 200);
768
- },
769
- },
770
-
771
- // ── Step 6: Welcome (whiteboard mode) ─────────────────────
772
- {
773
- id: 'welcome',
774
- whiteboardMode: true,
775
-
776
- render({ svg, dom, seq, vw, vh, nextStep, onSkipWithArrow, createButton }) {
777
- const cx = vw / 2;
778
- const cy = vh / 2 - 40;
779
-
780
- // 1. Hand-drawn question text (centered, Caveat, large)
781
- seq.add(() => handwrittenLabel(svg, 'Do you want to see the tutorial?', {
782
- x: cx,
783
- y: cy,
784
- color: 'rgba(255, 255, 255, 0.55)',
785
- fontSize: 36,
786
- textAnchor: 'middle',
787
- duration: 400,
788
- }), 200);
789
-
790
- // 2. Decorative sparkle doodles
791
- seq.add(() => createDoodle(svg, 'sparkle', {
792
- x: cx - 240,
793
- y: cy - 60,
794
- scale: 1.2,
795
- color: 'rgba(255, 255, 255, 0.3)',
796
- duration: 350,
797
- }), 200);
798
-
799
- seq.add(() => createDoodle(svg, 'sparkle', {
800
- x: cx + 210,
801
- y: cy + 20,
802
- scale: 0.9,
803
- color: 'rgba(255, 255, 255, 0.3)',
804
- duration: 350,
805
- }), 200);
806
-
807
- // 3. Interactive Yes / No buttons
808
- seq.add(() => {
809
- const btnY = cy + 50;
810
- const gap = 80;
811
-
812
- const yesEl = createButton(dom, 'Yes', {
813
- x: cx - gap,
814
- y: btnY,
815
- color: 'rgba(255, 255, 255, 0.5)',
816
- fontSize: 28,
817
- onClick: () => nextStep(),
818
- });
819
-
820
- const noEl = createButton(dom, 'No', {
821
- x: cx + gap,
822
- y: btnY,
823
- color: 'rgba(255, 255, 255, 0.5)',
824
- fontSize: 28,
825
- onClick: () => onSkipWithArrow(),
826
- });
827
-
828
- // Draw hand-drawn underlines after buttons paint
829
- setTimeout(() => {
830
- const yesRect = yesEl.getBoundingClientRect();
831
- const noRect = noEl.getBoundingClientRect();
832
-
833
- createHandDrawnUnderline(svg, yesRect, {
834
- color: 'rgba(255, 255, 255, 0.22)',
835
- wobbleSeed: 'yes-underline',
836
- duration: 250,
837
- offset: 2,
838
- });
839
- createHandDrawnUnderline(svg, noRect, {
840
- color: 'rgba(255, 255, 255, 0.22)',
841
- wobbleSeed: 'no-underline',
842
- duration: 250,
843
- offset: 2,
844
- });
845
- }, 100);
846
-
847
- return {
848
- destroy() { yesEl.remove(); noEl.remove(); },
849
- };
850
- }, 200);
851
- },
852
- },
853
-
854
- // ── Step 7: Session Monitor ────────────────────────────
855
- {
856
- id: 'explain-sessions',
857
- whiteboardMode: true,
858
-
859
- render({ svg, dom, seq, vw, vh, nextStep, prevStep, skipTutorial, createButton }) {
860
- const btn = document.getElementById('titlebar-sessions-btn');
861
- const rect = btn?.getBoundingClientRect();
862
- if (!rect) return;
863
-
864
- const btnCx = rect.left + rect.width / 2;
865
- const textX = Math.max(220, Math.min(btnCx, vw - 220));
866
- const textY = rect.bottom + 90;
867
-
868
- seq.add(() => createHighlightCircle(svg, rect, {
869
- color: 'rgba(255, 255, 255, 0.25)',
870
- padding: 10, duration: 500, strokeWidth: 1.2,
871
- }), 100);
872
-
873
- seq.add(() => createAnimatedArrow(svg, {
874
- from: { x: textX, y: textY - 18 },
875
- to: { x: btnCx, y: rect.bottom + 24 },
876
- color: 'rgba(255, 255, 255, 0.22)',
877
- wobbleSeed: 'sessions-arrow', duration: 400,
878
- arrowheadSize: 14, strokeWidth: 1.5,
879
- }), 250);
880
-
881
- seq.add(() => handwrittenLabel(svg, 'Session Monitor', {
882
- x: textX, y: textY,
883
- textAnchor: 'middle',
884
- color: 'rgba(255, 255, 255, 0.6)',
885
- fontSize: 28, duration: 350,
886
- }), 400);
887
-
888
- seq.add(() => handwrittenLabel(svg, 'Track active CLI sessions across your terminals', {
889
- x: textX, y: textY + 36,
890
- textAnchor: 'middle',
891
- color: 'rgba(255, 255, 255, 0.32)',
892
- fontSize: 19, duration: 300,
893
- }), 100);
894
-
895
- seq.add(() => {
896
- const navY = textY + 105;
897
- const backEl = createButton(dom, 'Back', {
898
- x: textX - 80, y: navY, fontSize: 22,
899
- color: 'rgba(255, 255, 255, 0.35)', onClick: () => prevStep(),
900
- });
901
- const endEl = createButton(dom, 'End', {
902
- x: textX, y: navY, fontSize: 17,
903
- color: 'rgba(255, 255, 255, 0.25)', onClick: () => skipTutorial(),
904
- });
905
- const nextEl = createButton(dom, 'Next', {
906
- x: textX + 80, y: navY, fontSize: 22,
907
- color: 'rgba(255, 255, 255, 0.35)', onClick: () => nextStep(),
908
- });
909
- return { destroy() { backEl.remove(); endEl.remove(); nextEl.remove(); } };
910
- }, 200);
911
- },
912
- },
913
-
914
- // ── Step 8: Image Gallery ────────────────────────────
915
- {
916
- id: 'explain-gallery',
917
- whiteboardMode: true,
918
-
919
- render({ svg, dom, seq, vw, vh, nextStep, prevStep, skipTutorial, createButton }) {
920
- const btn = document.getElementById('titlebar-gallery-btn');
921
- const rect = btn?.getBoundingClientRect();
922
- if (!rect) return;
923
-
924
- const btnCx = rect.left + rect.width / 2;
925
- const textX = Math.max(220, Math.min(btnCx, vw - 220));
926
- const textY = rect.bottom + 90;
927
-
928
- seq.add(() => createHighlightCircle(svg, rect, {
929
- color: 'rgba(255, 255, 255, 0.25)',
930
- padding: 10, duration: 500, strokeWidth: 1.2,
931
- }), 100);
932
-
933
- seq.add(() => createAnimatedArrow(svg, {
934
- from: { x: textX, y: textY - 18 },
935
- to: { x: btnCx, y: rect.bottom + 24 },
936
- color: 'rgba(255, 255, 255, 0.22)',
937
- wobbleSeed: 'gallery-arrow', duration: 400,
938
- arrowheadSize: 14, strokeWidth: 1.5,
939
- }), 250);
940
-
941
- seq.add(() => handwrittenLabel(svg, 'Image Gallery', {
942
- x: textX, y: textY,
943
- textAnchor: 'middle',
944
- color: 'rgba(255, 255, 255, 0.6)',
945
- fontSize: 28, duration: 350,
946
- }), 400);
947
-
948
- seq.add(() => handwrittenLabel(svg, 'Browse and manage images from your sessions', {
949
- x: textX, y: textY + 36,
950
- textAnchor: 'middle',
951
- color: 'rgba(255, 255, 255, 0.32)',
952
- fontSize: 19, duration: 300,
953
- }), 100);
954
-
955
- seq.add(() => {
956
- const navY = textY + 105;
957
- const backEl = createButton(dom, 'Back', {
958
- x: textX - 80, y: navY, fontSize: 22,
959
- color: 'rgba(255, 255, 255, 0.35)', onClick: () => prevStep(),
960
- });
961
- const endEl = createButton(dom, 'End', {
962
- x: textX, y: navY, fontSize: 17,
963
- color: 'rgba(255, 255, 255, 0.25)', onClick: () => skipTutorial(),
964
- });
965
- const nextEl = createButton(dom, 'Next', {
966
- x: textX + 80, y: navY, fontSize: 22,
967
- color: 'rgba(255, 255, 255, 0.35)', onClick: () => nextStep(),
968
- });
969
- return { destroy() { backEl.remove(); endEl.remove(); nextEl.remove(); } };
970
- }, 200);
971
- },
972
- },
973
-
974
- // ── Step 9: Cost Tracker ─────────────────────────────
975
- {
976
- id: 'explain-cost',
977
- whiteboardMode: true,
978
-
979
- render({ svg, dom, seq, vw, vh, nextStep, prevStep, skipTutorial, createButton }) {
980
- const btn = document.getElementById('titlebar-cost-btn');
981
- const rect = btn?.getBoundingClientRect();
982
- if (!rect) return;
983
-
984
- const btnCx = rect.left + rect.width / 2;
985
- const textX = Math.max(220, Math.min(btnCx, vw - 220));
986
- const textY = rect.bottom + 90;
987
-
988
- seq.add(() => createHighlightCircle(svg, rect, {
989
- color: 'rgba(255, 255, 255, 0.25)',
990
- padding: 10, duration: 500, strokeWidth: 1.2,
991
- }), 100);
992
-
993
- seq.add(() => createAnimatedArrow(svg, {
994
- from: { x: textX, y: textY - 18 },
995
- to: { x: btnCx, y: rect.bottom + 24 },
996
- color: 'rgba(255, 255, 255, 0.22)',
997
- wobbleSeed: 'cost-arrow', duration: 400,
998
- arrowheadSize: 14, strokeWidth: 1.5,
999
- }), 250);
1000
-
1001
- seq.add(() => handwrittenLabel(svg, 'Cost Tracker', {
1002
- x: textX, y: textY,
1003
- textAnchor: 'middle',
1004
- color: 'rgba(255, 255, 255, 0.6)',
1005
- fontSize: 28, duration: 350,
1006
- }), 400);
1007
-
1008
- seq.add(() => handwrittenLabel(svg, 'Watch your token spend in real-time', {
1009
- x: textX, y: textY + 36,
1010
- textAnchor: 'middle',
1011
- color: 'rgba(255, 255, 255, 0.32)',
1012
- fontSize: 19, duration: 300,
1013
- }), 100);
1014
-
1015
- seq.add(() => {
1016
- const navY = textY + 105;
1017
- const backEl = createButton(dom, 'Back', {
1018
- x: textX - 80, y: navY, fontSize: 22,
1019
- color: 'rgba(255, 255, 255, 0.35)', onClick: () => prevStep(),
1020
- });
1021
- const endEl = createButton(dom, 'End', {
1022
- x: textX, y: navY, fontSize: 17,
1023
- color: 'rgba(255, 255, 255, 0.25)', onClick: () => skipTutorial(),
1024
- });
1025
- const nextEl = createButton(dom, 'Next', {
1026
- x: textX + 80, y: navY, fontSize: 22,
1027
- color: 'rgba(255, 255, 255, 0.35)', onClick: () => nextStep(),
1028
- });
1029
- return { destroy() { backEl.remove(); endEl.remove(); nextEl.remove(); } };
1030
- }, 200);
1031
- },
1032
- },
1033
-
1034
- // ── Step 10: Help & Tutorial ─────────────────────────
1035
- {
1036
- id: 'explain-help',
1037
- whiteboardMode: true,
1038
-
1039
- render({ svg, dom, seq, vw, vh, nextStep, prevStep, skipTutorial, createButton }) {
1040
- const btn = document.getElementById('titlebar-tutorial-btn');
1041
- const rect = btn?.getBoundingClientRect();
1042
- if (!rect) return;
1043
-
1044
- const btnCx = rect.left + rect.width / 2;
1045
- const textX = Math.max(220, Math.min(btnCx, vw - 220));
1046
- const textY = rect.bottom + 90;
1047
-
1048
- seq.add(() => createHighlightCircle(svg, rect, {
1049
- color: 'rgba(255, 255, 255, 0.25)',
1050
- padding: 10, duration: 500, strokeWidth: 1.2,
1051
- }), 100);
1052
-
1053
- seq.add(() => createAnimatedArrow(svg, {
1054
- from: { x: textX, y: textY - 18 },
1055
- to: { x: btnCx, y: rect.bottom + 24 },
1056
- color: 'rgba(255, 255, 255, 0.22)',
1057
- wobbleSeed: 'help-arrow', duration: 400,
1058
- arrowheadSize: 14, strokeWidth: 1.5,
1059
- }), 250);
1060
-
1061
- seq.add(() => handwrittenLabel(svg, 'Help & Tutorial', {
1062
- x: textX, y: textY,
1063
- textAnchor: 'middle',
1064
- color: 'rgba(255, 255, 255, 0.6)',
1065
- fontSize: 28, duration: 350,
1066
- }), 400);
1067
-
1068
- seq.add(() => handwrittenLabel(svg, 'Restart this tour anytime from here', {
1069
- x: textX, y: textY + 36,
1070
- textAnchor: 'middle',
1071
- color: 'rgba(255, 255, 255, 0.32)',
1072
- fontSize: 19, duration: 300,
1073
- }), 100);
1074
-
1075
- seq.add(() => {
1076
- const navY = textY + 105;
1077
- const backEl = createButton(dom, 'Back', {
1078
- x: textX - 80, y: navY, fontSize: 22,
1079
- color: 'rgba(255, 255, 255, 0.35)', onClick: () => prevStep(),
1080
- });
1081
- const endEl = createButton(dom, 'End', {
1082
- x: textX, y: navY, fontSize: 17,
1083
- color: 'rgba(255, 255, 255, 0.25)', onClick: () => skipTutorial(),
1084
- });
1085
- const nextEl = createButton(dom, 'Next', {
1086
- x: textX + 80, y: navY, fontSize: 22,
1087
- color: 'rgba(255, 255, 255, 0.35)', onClick: () => nextStep(),
1088
- });
1089
- return { destroy() { backEl.remove(); endEl.remove(); nextEl.remove(); } };
1090
- }, 200);
1091
- },
1092
- },
1093
-
1094
- // ── Step 11: Graph View ──────────────────────────────
1095
- {
1096
- id: 'explain-focus',
1097
- whiteboardMode: true,
1098
-
1099
- render({ svg, dom, seq, vw, vh, nextStep, prevStep, skipTutorial, createButton }) {
1100
- const btn = document.getElementById('titlebar-viz-toggle');
1101
- const rect = btn?.getBoundingClientRect();
1102
- if (!rect) return;
1103
-
1104
- const btnCx = rect.left + rect.width / 2;
1105
- const textX = Math.max(220, Math.min(btnCx, vw - 220));
1106
- const textY = rect.bottom + 90;
1107
-
1108
- seq.add(() => createHighlightCircle(svg, rect, {
1109
- color: 'rgba(255, 255, 255, 0.25)',
1110
- padding: 10, duration: 500, strokeWidth: 1.2,
1111
- }), 100);
1112
-
1113
- seq.add(() => createAnimatedArrow(svg, {
1114
- from: { x: textX, y: textY - 18 },
1115
- to: { x: btnCx, y: rect.bottom + 24 },
1116
- color: 'rgba(255, 255, 255, 0.22)',
1117
- wobbleSeed: 'focus-arrow', duration: 400,
1118
- arrowheadSize: 14, strokeWidth: 1.5,
1119
- }), 250);
1120
-
1121
- seq.add(() => handwrittenLabel(svg, 'Graph View', {
1122
- x: textX, y: textY,
1123
- textAnchor: 'middle',
1124
- color: 'rgba(255, 255, 255, 0.6)',
1125
- fontSize: 28, duration: 350,
1126
- }), 400);
1127
-
1128
- seq.add(() => handwrittenLabel(svg, 'Switch between the memory graph and this whiteboard', {
1129
- x: textX, y: textY + 36,
1130
- textAnchor: 'middle',
1131
- color: 'rgba(255, 255, 255, 0.32)',
1132
- fontSize: 19, duration: 300,
1133
- }), 100);
1134
-
1135
- seq.add(() => {
1136
- const navY = textY + 105;
1137
- const backEl = createButton(dom, 'Back', {
1138
- x: textX - 80, y: navY, fontSize: 22,
1139
- color: 'rgba(255, 255, 255, 0.35)', onClick: () => prevStep(),
1140
- });
1141
- const endEl = createButton(dom, 'End', {
1142
- x: textX, y: navY, fontSize: 17,
1143
- color: 'rgba(255, 255, 255, 0.25)', onClick: () => skipTutorial(),
1144
- });
1145
- const nextEl = createButton(dom, 'Next', {
1146
- x: textX + 80, y: navY, fontSize: 22,
1147
- color: 'rgba(255, 255, 255, 0.35)', onClick: () => nextStep(),
1148
- });
1149
- return { destroy() { backEl.remove(); endEl.remove(); nextEl.remove(); } };
1150
- }, 200);
1151
- },
1152
- },
1153
-
1154
- // ── Step 12: Fullscreen ──────────────────────────────
1155
- {
1156
- id: 'explain-fullscreen',
1157
- whiteboardMode: true,
1158
-
1159
- render({ svg, dom, seq, vw, vh, nextStep, prevStep, skipTutorial, createButton }) {
1160
- const btn = document.getElementById('titlebar-fullscreen-btn');
1161
- const rect = btn?.getBoundingClientRect();
1162
- if (!rect) return;
1163
-
1164
- const btnCx = rect.left + rect.width / 2;
1165
- const textX = Math.max(220, Math.min(btnCx, vw - 220));
1166
- const textY = rect.bottom + 90;
1167
-
1168
- seq.add(() => createHighlightCircle(svg, rect, {
1169
- color: 'rgba(255, 255, 255, 0.25)',
1170
- padding: 10, duration: 500, strokeWidth: 1.2,
1171
- }), 100);
1172
-
1173
- seq.add(() => createAnimatedArrow(svg, {
1174
- from: { x: textX, y: textY - 18 },
1175
- to: { x: btnCx, y: rect.bottom + 24 },
1176
- color: 'rgba(255, 255, 255, 0.22)',
1177
- wobbleSeed: 'fs-arrow', duration: 400,
1178
- arrowheadSize: 14, strokeWidth: 1.5,
1179
- }), 250);
1180
-
1181
- seq.add(() => handwrittenLabel(svg, 'Fullscreen', {
1182
- x: textX, y: textY,
1183
- textAnchor: 'middle',
1184
- color: 'rgba(255, 255, 255, 0.6)',
1185
- fontSize: 28, duration: 350,
1186
- }), 400);
1187
-
1188
- seq.add(() => handwrittenLabel(svg, 'A clean, distraction-free workspace', {
1189
- x: textX, y: textY + 36,
1190
- textAnchor: 'middle',
1191
- color: 'rgba(255, 255, 255, 0.32)',
1192
- fontSize: 19, duration: 300,
1193
- }), 100);
1194
-
1195
- seq.add(() => {
1196
- const navY = textY + 105;
1197
- const backEl = createButton(dom, 'Back', {
1198
- x: textX - 80, y: navY, fontSize: 22,
1199
- color: 'rgba(255, 255, 255, 0.35)', onClick: () => prevStep(),
1200
- });
1201
- const endEl = createButton(dom, 'End', {
1202
- x: textX, y: navY, fontSize: 17,
1203
- color: 'rgba(255, 255, 255, 0.25)', onClick: () => skipTutorial(),
1204
- });
1205
- const nextEl = createButton(dom, 'Next', {
1206
- x: textX + 80, y: navY, fontSize: 22,
1207
- color: 'rgba(255, 255, 255, 0.35)', onClick: () => nextStep(),
1208
- });
1209
- return { destroy() { backEl.remove(); endEl.remove(); nextEl.remove(); } };
1210
- }, 200);
1211
- },
1212
- },
1213
-
1214
- // ── Step 13: Clock ───────────────────────────────────
1215
- {
1216
- id: 'explain-clock',
1217
- whiteboardMode: true,
1218
-
1219
- render({ svg, dom, seq, vw, vh, nextStep, prevStep, skipTutorial, createButton }) {
1220
- // Hide workspace toolbar for the next section reveal
1221
- const topControls = document.getElementById('topright-controls');
1222
- if (topControls) topControls.classList.add('tutorial-hidden');
1223
-
1224
- const clock = document.getElementById('titlebar-clock');
1225
- const rect = clock?.getBoundingClientRect();
1226
- if (!rect) return;
1227
-
1228
- const clockCx = rect.left + rect.width / 2;
1229
- const textX = Math.max(220, Math.min(clockCx, vw - 220));
1230
- const textY = rect.bottom + 90;
1231
-
1232
- seq.add(() => createHighlightCircle(svg, rect, {
1233
- color: 'rgba(255, 255, 255, 0.25)',
1234
- padding: 10, duration: 500, strokeWidth: 1.2,
1235
- }), 100);
1236
-
1237
- seq.add(() => createAnimatedArrow(svg, {
1238
- from: { x: textX, y: textY - 18 },
1239
- to: { x: clockCx, y: rect.bottom + 24 },
1240
- color: 'rgba(255, 255, 255, 0.22)',
1241
- wobbleSeed: 'clock-arrow', duration: 400,
1242
- arrowheadSize: 14, strokeWidth: 1.5,
1243
- }), 250);
1244
-
1245
- seq.add(() => handwrittenLabel(svg, 'Whoa... a clock', {
1246
- x: textX, y: textY,
1247
- textAnchor: 'middle',
1248
- color: 'rgba(255, 255, 255, 0.6)',
1249
- fontSize: 28, duration: 350,
1250
- }), 400);
1251
-
1252
- seq.add(() => {
1253
- const navY = textY + 70;
1254
- const backEl = createButton(dom, 'Back', {
1255
- x: textX - 80, y: navY, fontSize: 22,
1256
- color: 'rgba(255, 255, 255, 0.35)', onClick: () => prevStep(),
1257
- });
1258
- const endEl = createButton(dom, 'End', {
1259
- x: textX, y: navY, fontSize: 17,
1260
- color: 'rgba(255, 255, 255, 0.25)', onClick: () => skipTutorial(),
1261
- });
1262
- const nextEl = createButton(dom, 'Next', {
1263
- x: textX + 80, y: navY, fontSize: 22,
1264
- color: 'rgba(255, 255, 255, 0.35)', onClick: () => nextStep(),
1265
- });
1266
- return { destroy() { backEl.remove(); endEl.remove(); nextEl.remove(); } };
1267
- }, 200);
1268
- },
1269
- },
1270
-
1271
-
1272
- // ── Step 14: Trash (+ reveal workspace toolbar) ──────
1273
- {
1274
- id: 'explain-trash',
1275
- whiteboardMode: true,
1276
-
1277
- render({ svg, dom, seq, vw, vh, nextStep, prevStep, skipTutorial, createButton }) {
1278
- // Slide in the top-right workspace toolbar
1279
- const topControls = document.getElementById('topright-controls');
1280
- if (topControls) {
1281
- topControls.classList.remove('tutorial-hidden');
1282
- topControls.style.transform = 'translateY(-20px)';
1283
- topControls.style.opacity = '0';
1284
- topControls.style.transition = 'transform 0.35s ease, opacity 0.35s ease';
1285
- requestAnimationFrame(() => {
1286
- topControls.style.transform = 'translateY(0)';
1287
- topControls.style.opacity = '1';
1288
- });
1289
- }
1290
-
1291
- const btn = document.getElementById('topright-trash-btn');
1292
- const rect = btn?.getBoundingClientRect();
1293
- if (!rect) return;
1294
-
1295
- const btnCx = rect.left + rect.width / 2;
1296
- const textX = Math.max(220, Math.min(btnCx, vw - 220));
1297
- const textY = rect.bottom + 90;
1298
-
1299
- seq.add(() => createHighlightCircle(svg, rect, {
1300
- color: 'rgba(255, 255, 255, 0.25)',
1301
- padding: 10, duration: 500, strokeWidth: 1.2,
1302
- }), 400);
1303
-
1304
- seq.add(() => createAnimatedArrow(svg, {
1305
- from: { x: textX, y: textY - 18 },
1306
- to: { x: btnCx, y: rect.bottom + 24 },
1307
- color: 'rgba(255, 255, 255, 0.22)',
1308
- wobbleSeed: 'trash-arrow', duration: 400,
1309
- arrowheadSize: 14, strokeWidth: 1.5,
1310
- }), 250);
1311
-
1312
- seq.add(() => handwrittenLabel(svg, 'Trash', {
1313
- x: textX, y: textY,
1314
- textAnchor: 'middle',
1315
- color: 'rgba(255, 255, 255, 0.6)',
1316
- fontSize: 28, duration: 350,
1317
- }), 400);
1318
-
1319
- seq.add(() => handwrittenLabel(svg, 'Recover deleted cards and terminals', {
1320
- x: textX, y: textY + 36,
1321
- textAnchor: 'middle',
1322
- color: 'rgba(255, 255, 255, 0.32)',
1323
- fontSize: 19, duration: 300,
1324
- }), 100);
1325
-
1326
- seq.add(() => {
1327
- const navY = textY + 105;
1328
- const backEl = createButton(dom, 'Back', {
1329
- x: textX - 80, y: navY, fontSize: 22,
1330
- color: 'rgba(255, 255, 255, 0.35)', onClick: () => prevStep(),
1331
- });
1332
- const endEl = createButton(dom, 'End', {
1333
- x: textX, y: navY, fontSize: 17,
1334
- color: 'rgba(255, 255, 255, 0.25)', onClick: () => skipTutorial(),
1335
- });
1336
- const nextEl = createButton(dom, 'Next', {
1337
- x: textX + 80, y: navY, fontSize: 22,
1338
- color: 'rgba(255, 255, 255, 0.35)', onClick: () => nextStep(),
1339
- });
1340
- return { destroy() { backEl.remove(); endEl.remove(); nextEl.remove(); } };
1341
- }, 200);
1342
- },
1343
- },
1344
-
1345
- // ── Step 15: Grid Snap ────────────────────────────────
1346
- {
1347
- id: 'explain-grid',
1348
- whiteboardMode: true,
1349
-
1350
- render({ svg, dom, seq, vw, vh, nextStep, prevStep, skipTutorial, createButton }) {
1351
- const btn = document.getElementById('ws-grid-toggle');
1352
- const rect = btn?.getBoundingClientRect();
1353
- if (!rect) return;
1354
-
1355
- const btnCx = rect.left + rect.width / 2;
1356
- const textX = Math.max(220, Math.min(btnCx, vw - 220));
1357
- const textY = rect.bottom + 90;
1358
-
1359
- seq.add(() => createHighlightCircle(svg, rect, {
1360
- color: 'rgba(255, 255, 255, 0.25)',
1361
- padding: 10, duration: 500, strokeWidth: 1.2,
1362
- }), 100);
1363
-
1364
- seq.add(() => createAnimatedArrow(svg, {
1365
- from: { x: textX, y: textY - 18 },
1366
- to: { x: btnCx, y: rect.bottom + 24 },
1367
- color: 'rgba(255, 255, 255, 0.22)',
1368
- wobbleSeed: 'grid-arrow', duration: 400,
1369
- arrowheadSize: 14, strokeWidth: 1.5,
1370
- }), 250);
1371
-
1372
- seq.add(() => handwrittenLabel(svg, 'Grid Snap', {
1373
- x: textX, y: textY,
1374
- textAnchor: 'middle',
1375
- color: 'rgba(255, 255, 255, 0.6)',
1376
- fontSize: 28, duration: 350,
1377
- }), 400);
1378
-
1379
- seq.add(() => handwrittenLabel(svg, 'Align cards to a grid for tidy layouts', {
1380
- x: textX, y: textY + 36,
1381
- textAnchor: 'middle',
1382
- color: 'rgba(255, 255, 255, 0.32)',
1383
- fontSize: 19, duration: 300,
1384
- }), 100);
1385
-
1386
- seq.add(() => {
1387
- const navY = textY + 105;
1388
- const backEl = createButton(dom, 'Back', {
1389
- x: textX - 80, y: navY, fontSize: 22,
1390
- color: 'rgba(255, 255, 255, 0.35)', onClick: () => prevStep(),
1391
- });
1392
- const endEl = createButton(dom, 'End', {
1393
- x: textX, y: navY, fontSize: 17,
1394
- color: 'rgba(255, 255, 255, 0.25)', onClick: () => skipTutorial(),
1395
- });
1396
- const nextEl = createButton(dom, 'Next', {
1397
- x: textX + 80, y: navY, fontSize: 22,
1398
- color: 'rgba(255, 255, 255, 0.35)', onClick: () => nextStep(),
1399
- });
1400
- return { destroy() { backEl.remove(); endEl.remove(); nextEl.remove(); } };
1401
- }, 200);
1402
- },
1403
- },
1404
-
1405
- // ── Step 16: Tile Terminals ───────────────────────────
1406
- {
1407
- id: 'explain-tile',
1408
- whiteboardMode: true,
1409
-
1410
- render({ svg, dom, seq, vw, vh, nextStep, prevStep, skipTutorial, createButton }) {
1411
- const btn = document.getElementById('ws-tile-btn');
1412
- const rect = btn?.getBoundingClientRect();
1413
- if (!rect) return;
1414
-
1415
- const btnCx = rect.left + rect.width / 2;
1416
- const textX = Math.max(220, Math.min(btnCx, vw - 220));
1417
- const textY = rect.bottom + 90;
1418
-
1419
- seq.add(() => createHighlightCircle(svg, rect, {
1420
- color: 'rgba(255, 255, 255, 0.25)',
1421
- padding: 10, duration: 500, strokeWidth: 1.2,
1422
- }), 100);
1423
-
1424
- seq.add(() => createAnimatedArrow(svg, {
1425
- from: { x: textX, y: textY - 18 },
1426
- to: { x: btnCx, y: rect.bottom + 24 },
1427
- color: 'rgba(255, 255, 255, 0.22)',
1428
- wobbleSeed: 'tile-arrow', duration: 400,
1429
- arrowheadSize: 14, strokeWidth: 1.5,
1430
- }), 250);
1431
-
1432
- seq.add(() => handwrittenLabel(svg, 'Tile Terminals', {
1433
- x: textX, y: textY,
1434
- textAnchor: 'middle',
1435
- color: 'rgba(255, 255, 255, 0.6)',
1436
- fontSize: 28, duration: 350,
1437
- }), 400);
1438
-
1439
- seq.add(() => handwrittenLabel(svg, 'Auto-arrange all terminals into a neat grid', {
1440
- x: textX, y: textY + 36,
1441
- textAnchor: 'middle',
1442
- color: 'rgba(255, 255, 255, 0.32)',
1443
- fontSize: 19, duration: 300,
1444
- }), 100);
1445
-
1446
- seq.add(() => {
1447
- const navY = textY + 105;
1448
- const backEl = createButton(dom, 'Back', {
1449
- x: textX - 80, y: navY, fontSize: 22,
1450
- color: 'rgba(255, 255, 255, 0.35)', onClick: () => prevStep(),
1451
- });
1452
- const endEl = createButton(dom, 'End', {
1453
- x: textX, y: navY, fontSize: 17,
1454
- color: 'rgba(255, 255, 255, 0.25)', onClick: () => skipTutorial(),
1455
- });
1456
- const nextEl = createButton(dom, 'Next', {
1457
- x: textX + 80, y: navY, fontSize: 22,
1458
- color: 'rgba(255, 255, 255, 0.35)', onClick: () => nextStep(),
1459
- });
1460
- return { destroy() { backEl.remove(); endEl.remove(); nextEl.remove(); } };
1461
- }, 200);
1462
- },
1463
- },
1464
-
1465
- // ── Step 17: Keybinds ─────────────────────────────────
1466
- {
1467
- id: 'explain-keybinds',
1468
- whiteboardMode: true,
1469
-
1470
- render({ svg, dom, seq, vw, vh, nextStep, prevStep, skipTutorial, createButton }) {
1471
- const btn = document.getElementById('topright-keybinds-btn');
1472
- const rect = btn?.getBoundingClientRect();
1473
- if (!rect) return;
1474
-
1475
- const btnCx = rect.left + rect.width / 2;
1476
- const textX = Math.max(220, Math.min(btnCx, vw - 220));
1477
- const textY = rect.bottom + 90;
1478
-
1479
- seq.add(() => createHighlightCircle(svg, rect, {
1480
- color: 'rgba(255, 255, 255, 0.25)',
1481
- padding: 10, duration: 500, strokeWidth: 1.2,
1482
- }), 100);
1483
-
1484
- seq.add(() => createAnimatedArrow(svg, {
1485
- from: { x: textX, y: textY - 18 },
1486
- to: { x: btnCx, y: rect.bottom + 24 },
1487
- color: 'rgba(255, 255, 255, 0.22)',
1488
- wobbleSeed: 'keys-arrow', duration: 400,
1489
- arrowheadSize: 14, strokeWidth: 1.5,
1490
- }), 250);
1491
-
1492
- seq.add(() => handwrittenLabel(svg, 'Keybinds', {
1493
- x: textX, y: textY,
1494
- textAnchor: 'middle',
1495
- color: 'rgba(255, 255, 255, 0.6)',
1496
- fontSize: 28, duration: 350,
1497
- }), 400);
1498
-
1499
- seq.add(() => handwrittenLabel(svg, 'View and customize keyboard shortcuts', {
1500
- x: textX, y: textY + 36,
1501
- textAnchor: 'middle',
1502
- color: 'rgba(255, 255, 255, 0.32)',
1503
- fontSize: 19, duration: 300,
1504
- }), 100);
1505
-
1506
- seq.add(() => {
1507
- const navY = textY + 105;
1508
- const backEl = createButton(dom, 'Back', {
1509
- x: textX - 80, y: navY, fontSize: 22,
1510
- color: 'rgba(255, 255, 255, 0.35)', onClick: () => prevStep(),
1511
- });
1512
- const endEl = createButton(dom, 'End', {
1513
- x: textX, y: navY, fontSize: 17,
1514
- color: 'rgba(255, 255, 255, 0.25)', onClick: () => skipTutorial(),
1515
- });
1516
- const nextEl = createButton(dom, 'Next', {
1517
- x: textX + 80, y: navY, fontSize: 22,
1518
- color: 'rgba(255, 255, 255, 0.35)', onClick: () => nextStep(),
1519
- });
1520
- return { destroy() { backEl.remove(); endEl.remove(); nextEl.remove(); } };
1521
- }, 200);
1522
- },
1523
- },
1524
-
1525
- // ── Step 18: Memory Explorer ──────────────────────────
1526
- {
1527
- id: 'explain-memory-explorer',
1528
- whiteboardMode: true,
1529
- _openedExplorer: false,
1530
-
1531
- onEnter() {
1532
- // Slide the memory explorer open so the user sees it
1533
- if (!document.body.classList.contains('explorer-open')) {
1534
- this._openedExplorer = true;
1535
- toggleExplorer();
1536
- }
1537
- },
1538
-
1539
- onExit() {
1540
- // Close it back if we opened it
1541
- if (this._openedExplorer && document.body.classList.contains('explorer-open')) {
1542
- toggleExplorer();
1543
- }
1544
- this._openedExplorer = false;
1545
- },
1546
-
1547
- render({ svg, dom, seq, vw, vh, nextStep, prevStep, skipTutorial, createButton }) {
1548
- const btn = document.getElementById('topright-memory-explorer-btn');
1549
- const rect = btn?.getBoundingClientRect();
1550
- if (!rect) return;
1551
-
1552
- const btnCx = rect.left + rect.width / 2;
1553
- const textX = Math.max(220, Math.min(btnCx, vw - 220));
1554
- const textY = rect.bottom + 90;
1555
-
1556
- seq.add(() => createHighlightCircle(svg, rect, {
1557
- color: 'rgba(255, 255, 255, 0.25)',
1558
- padding: 10, duration: 500, strokeWidth: 1.2,
1559
- }), 100);
1560
-
1561
- seq.add(() => createAnimatedArrow(svg, {
1562
- from: { x: textX, y: textY - 18 },
1563
- to: { x: btnCx, y: rect.bottom + 24 },
1564
- color: 'rgba(255, 255, 255, 0.22)',
1565
- wobbleSeed: 'mem-arrow', duration: 400,
1566
- arrowheadSize: 14, strokeWidth: 1.5,
1567
- }), 250);
1568
-
1569
- seq.add(() => handwrittenLabel(svg, 'Memory Explorer', {
1570
- x: textX, y: textY,
1571
- textAnchor: 'middle',
1572
- color: 'rgba(255, 255, 255, 0.6)',
1573
- fontSize: 28, duration: 350,
1574
- }), 400);
1575
-
1576
- seq.add(() => handwrittenLabel(svg, 'Browse, search, and manage stored memories', {
1577
- x: textX, y: textY + 36,
1578
- textAnchor: 'middle',
1579
- color: 'rgba(255, 255, 255, 0.32)',
1580
- fontSize: 19, duration: 300,
1581
- }), 100);
1582
-
1583
- seq.add(() => {
1584
- const navY = textY + 105;
1585
- const backEl = createButton(dom, 'Back', {
1586
- x: textX - 80, y: navY, fontSize: 22,
1587
- color: 'rgba(255, 255, 255, 0.35)', onClick: () => prevStep(),
1588
- });
1589
- const endEl = createButton(dom, 'End', {
1590
- x: textX, y: navY, fontSize: 17,
1591
- color: 'rgba(255, 255, 255, 0.25)', onClick: () => skipTutorial(),
1592
- });
1593
- const nextEl = createButton(dom, 'Next', {
1594
- x: textX + 80, y: navY, fontSize: 22,
1595
- color: 'rgba(255, 255, 255, 0.35)', onClick: () => nextStep(),
1596
- });
1597
- return { destroy() { backEl.remove(); endEl.remove(); nextEl.remove(); } };
1598
- }, 200);
1599
- },
1600
- },
1601
-
1602
- // ── Step 19: File Explorer ────────────────────────────
1603
- {
1604
- id: 'explain-file-explorer',
1605
- whiteboardMode: true,
1606
- _openedFileExplorer: false,
1607
-
1608
- onEnter() {
1609
- if (!document.body.classList.contains('file-explorer-open')) {
1610
- this._openedFileExplorer = true;
1611
- toggleFileExplorer();
1612
- }
1613
- },
1614
-
1615
- onExit() {
1616
- if (this._openedFileExplorer && document.body.classList.contains('file-explorer-open')) {
1617
- toggleFileExplorer();
1618
- }
1619
- this._openedFileExplorer = false;
1620
- },
1621
-
1622
- render({ svg, dom, seq, vw, vh, nextStep, prevStep, skipTutorial, createButton }) {
1623
- const btn = document.getElementById('topright-file-explorer-btn');
1624
- const rect = btn?.getBoundingClientRect();
1625
- if (!rect) return;
1626
-
1627
- const btnCx = rect.left + rect.width / 2;
1628
- const textX = Math.max(220, Math.min(btnCx, vw - 220));
1629
- const textY = rect.bottom + 90;
1630
-
1631
- seq.add(() => createHighlightCircle(svg, rect, {
1632
- color: 'rgba(255, 255, 255, 0.25)',
1633
- padding: 10, duration: 500, strokeWidth: 1.2,
1634
- }), 100);
1635
-
1636
- seq.add(() => createAnimatedArrow(svg, {
1637
- from: { x: textX, y: textY - 18 },
1638
- to: { x: btnCx, y: rect.bottom + 24 },
1639
- color: 'rgba(255, 255, 255, 0.22)',
1640
- wobbleSeed: 'files-arrow', duration: 400,
1641
- arrowheadSize: 14, strokeWidth: 1.5,
1642
- }), 250);
1643
-
1644
- seq.add(() => handwrittenLabel(svg, 'File Explorer', {
1645
- x: textX, y: textY,
1646
- textAnchor: 'middle',
1647
- color: 'rgba(255, 255, 255, 0.6)',
1648
- fontSize: 28, duration: 350,
1649
- }), 400);
1650
-
1651
- seq.add(() => handwrittenLabel(svg, 'Browse project files right from the whiteboard', {
1652
- x: textX, y: textY + 36,
1653
- textAnchor: 'middle',
1654
- color: 'rgba(255, 255, 255, 0.32)',
1655
- fontSize: 19, duration: 300,
1656
- }), 100);
1657
-
1658
- seq.add(() => {
1659
- const navY = textY + 105;
1660
- const backEl = createButton(dom, 'Back', {
1661
- x: textX - 80, y: navY, fontSize: 22,
1662
- color: 'rgba(255, 255, 255, 0.35)', onClick: () => prevStep(),
1663
- });
1664
- const endEl = createButton(dom, 'End', {
1665
- x: textX, y: navY, fontSize: 17,
1666
- color: 'rgba(255, 255, 255, 0.25)', onClick: () => skipTutorial(),
1667
- });
1668
- const nextEl = createButton(dom, 'Next', {
1669
- x: textX + 80, y: navY, fontSize: 22,
1670
- color: 'rgba(255, 255, 255, 0.35)', onClick: () => nextStep(),
1671
- });
1672
- return { destroy() { backEl.remove(); endEl.remove(); nextEl.remove(); } };
1673
- }, 200);
1674
- },
1675
- },
1676
-
1677
- // ── Step 20: Bookmarks ────────────────────────────────
1678
- {
1679
- id: 'explain-bookmarks',
1680
- whiteboardMode: true,
1681
-
1682
- render({ svg, dom, seq, vw, vh, nextStep, prevStep, skipTutorial, createButton }) {
1683
- const btn = document.getElementById('topright-bookmarks-btn');
1684
- const rect = btn?.getBoundingClientRect();
1685
- if (!rect) return;
1686
-
1687
- const btnCx = rect.left + rect.width / 2;
1688
- const textX = Math.max(220, Math.min(btnCx, vw - 220));
1689
- const textY = rect.bottom + 90;
1690
-
1691
- seq.add(() => createHighlightCircle(svg, rect, {
1692
- color: 'rgba(255, 255, 255, 0.25)',
1693
- padding: 10, duration: 500, strokeWidth: 1.2,
1694
- }), 100);
1695
-
1696
- seq.add(() => createAnimatedArrow(svg, {
1697
- from: { x: textX, y: textY - 18 },
1698
- to: { x: btnCx, y: rect.bottom + 24 },
1699
- color: 'rgba(255, 255, 255, 0.22)',
1700
- wobbleSeed: 'bm-arrow', duration: 400,
1701
- arrowheadSize: 14, strokeWidth: 1.5,
1702
- }), 250);
1703
-
1704
- seq.add(() => handwrittenLabel(svg, 'Bookmarks', {
1705
- x: textX, y: textY,
1706
- textAnchor: 'middle',
1707
- color: 'rgba(255, 255, 255, 0.6)',
1708
- fontSize: 28, duration: 350,
1709
- }), 400);
1710
-
1711
- seq.add(() => handwrittenLabel(svg, 'Pin important memories for quick access', {
1712
- x: textX, y: textY + 36,
1713
- textAnchor: 'middle',
1714
- color: 'rgba(255, 255, 255, 0.32)',
1715
- fontSize: 19, duration: 300,
1716
- }), 100);
1717
-
1718
- seq.add(() => {
1719
- const navY = textY + 105;
1720
- const backEl = createButton(dom, 'Back', {
1721
- x: textX - 80, y: navY, fontSize: 22,
1722
- color: 'rgba(255, 255, 255, 0.35)', onClick: () => prevStep(),
1723
- });
1724
- const endEl = createButton(dom, 'End', {
1725
- x: textX, y: navY, fontSize: 17,
1726
- color: 'rgba(255, 255, 255, 0.25)', onClick: () => skipTutorial(),
1727
- });
1728
- const nextEl = createButton(dom, 'Next', {
1729
- x: textX + 80, y: navY, fontSize: 22,
1730
- color: 'rgba(255, 255, 255, 0.35)', onClick: () => nextStep(),
1731
- });
1732
- return { destroy() { backEl.remove(); endEl.remove(); nextEl.remove(); } };
1733
- }, 200);
1734
- },
1735
- },
1736
-
1737
- // ── Step 21: Share / Invite ───────────────────────────
1738
- {
1739
- id: 'explain-share',
1740
- whiteboardMode: true,
1741
-
1742
- render({ svg, dom, seq, vw, vh, nextStep, prevStep, skipTutorial, createButton }) {
1743
- const btn = document.getElementById('invite-btn');
1744
- const rect = btn?.getBoundingClientRect();
1745
- if (!rect) return;
1746
-
1747
- const btnCx = rect.left + rect.width / 2;
1748
- const textX = Math.max(220, Math.min(btnCx, vw - 220));
1749
- const textY = rect.bottom + 90;
1750
-
1751
- seq.add(() => createHighlightCircle(svg, rect, {
1752
- color: 'rgba(255, 255, 255, 0.25)',
1753
- padding: 10, duration: 500, strokeWidth: 1.2,
1754
- }), 100);
1755
-
1756
- seq.add(() => createAnimatedArrow(svg, {
1757
- from: { x: textX, y: textY - 18 },
1758
- to: { x: btnCx, y: rect.bottom + 24 },
1759
- color: 'rgba(255, 255, 255, 0.22)',
1760
- wobbleSeed: 'share-arrow', duration: 400,
1761
- arrowheadSize: 14, strokeWidth: 1.5,
1762
- }), 250);
1763
-
1764
- seq.add(() => handwrittenLabel(svg, 'Share / Invite', {
1765
- x: textX, y: textY,
1766
- textAnchor: 'middle',
1767
- color: 'rgba(255, 255, 255, 0.6)',
1768
- fontSize: 28, duration: 350,
1769
- }), 400);
1770
-
1771
- seq.add(() => handwrittenLabel(svg, 'Invite others to view your whiteboard live', {
1772
- x: textX, y: textY + 36,
1773
- textAnchor: 'middle',
1774
- color: 'rgba(255, 255, 255, 0.32)',
1775
- fontSize: 19, duration: 300,
1776
- }), 100);
1777
-
1778
- seq.add(() => {
1779
- const navY = textY + 105;
1780
- const backEl = createButton(dom, 'Back', {
1781
- x: textX - 80, y: navY, fontSize: 22,
1782
- color: 'rgba(255, 255, 255, 0.35)', onClick: () => prevStep(),
1783
- });
1784
- const endEl = createButton(dom, 'End', {
1785
- x: textX, y: navY, fontSize: 17,
1786
- color: 'rgba(255, 255, 255, 0.25)', onClick: () => skipTutorial(),
1787
- });
1788
- const nextEl = createButton(dom, 'Next', {
1789
- x: textX + 80, y: navY, fontSize: 22,
1790
- color: 'rgba(255, 255, 255, 0.35)', onClick: () => nextStep(),
1791
- });
1792
- return { destroy() { backEl.remove(); endEl.remove(); nextEl.remove(); } };
1793
- }, 200);
1794
- },
1795
- },
1796
-
1797
- // ── Step 22: Workspaces ───────────────────────────────
1798
- {
1799
- id: 'explain-workspaces',
1800
- whiteboardMode: true,
1801
-
1802
- render({ svg, dom, seq, vw, vh, nextStep, prevStep, skipTutorial, createButton }) {
1803
- const wsEl = document.getElementById('ws-indicator');
1804
- const rect = wsEl?.getBoundingClientRect();
1805
- if (!rect) return;
1806
-
1807
- const wsCx = rect.left + rect.width / 2;
1808
- const textX = Math.max(220, Math.min(wsCx, vw - 220));
1809
- const textY = rect.bottom + 90;
1810
-
1811
- seq.add(() => createHighlightCircle(svg, rect, {
1812
- color: 'rgba(255, 255, 255, 0.25)',
1813
- padding: 10, duration: 500, strokeWidth: 1.2,
1814
- }), 100);
1815
-
1816
- seq.add(() => createAnimatedArrow(svg, {
1817
- from: { x: textX, y: textY - 18 },
1818
- to: { x: wsCx, y: rect.bottom + 24 },
1819
- color: 'rgba(255, 255, 255, 0.22)',
1820
- wobbleSeed: 'ws-arrow', duration: 400,
1821
- arrowheadSize: 14, strokeWidth: 1.5,
1822
- }), 250);
1823
-
1824
- seq.add(() => handwrittenLabel(svg, 'Workspaces', {
1825
- x: textX, y: textY,
1826
- textAnchor: 'middle',
1827
- color: 'rgba(255, 255, 255, 0.6)',
1828
- fontSize: 28, duration: 350,
1829
- }), 400);
1830
-
1831
- seq.add(() => handwrittenLabel(svg, 'Save and load your whiteboard layouts', {
1832
- x: textX, y: textY + 36,
1833
- textAnchor: 'middle',
1834
- color: 'rgba(255, 255, 255, 0.32)',
1835
- fontSize: 19, duration: 300,
1836
- }), 100);
1837
-
1838
- seq.add(() => {
1839
- const navY = textY + 105;
1840
- const backEl = createButton(dom, 'Back', {
1841
- x: textX - 80, y: navY, fontSize: 22,
1842
- color: 'rgba(255, 255, 255, 0.35)', onClick: () => prevStep(),
1843
- });
1844
- const endEl = createButton(dom, 'End', {
1845
- x: textX, y: navY, fontSize: 17,
1846
- color: 'rgba(255, 255, 255, 0.25)', onClick: () => skipTutorial(),
1847
- });
1848
- const nextEl = createButton(dom, 'Next', {
1849
- x: textX + 80, y: navY, fontSize: 22,
1850
- color: 'rgba(255, 255, 255, 0.35)', onClick: () => nextStep(),
1851
- });
1852
- return { destroy() { backEl.remove(); endEl.remove(); nextEl.remove(); } };
1853
- }, 200);
1854
- },
1855
- },
1856
-
1857
- // ── Step 23: Side Panel ───────────────────────────────
1858
- {
1859
- id: 'explain-side-panel',
1860
- whiteboardMode: true,
1861
- _openedClaudePanel: false,
1862
-
1863
- onEnter() {
1864
- if (!isClaudePanelOpen()) {
1865
- this._openedClaudePanel = true;
1866
- toggleClaudePanel();
1867
- }
1868
- },
1869
-
1870
- onExit() {
1871
- if (this._openedClaudePanel && isClaudePanelOpen()) {
1872
- toggleClaudePanel();
1873
- }
1874
- this._openedClaudePanel = false;
1875
- },
1876
-
1877
- render({ svg, dom, seq, vw, vh, nextStep, prevStep, skipTutorial, createButton }) {
1878
- const btn = document.getElementById('topright-claude-panel-btn');
1879
- const rect = btn?.getBoundingClientRect();
1880
- if (!rect) return;
1881
-
1882
- const btnCx = rect.left + rect.width / 2;
1883
- const textX = Math.max(220, Math.min(btnCx, vw - 220));
1884
- const textY = rect.bottom + 90;
1885
-
1886
- seq.add(() => createHighlightCircle(svg, rect, {
1887
- color: 'rgba(255, 255, 255, 0.25)',
1888
- padding: 10, duration: 500, strokeWidth: 1.2,
1889
- }), 100);
1890
-
1891
- seq.add(() => createAnimatedArrow(svg, {
1892
- from: { x: textX, y: textY - 18 },
1893
- to: { x: btnCx, y: rect.bottom + 24 },
1894
- color: 'rgba(255, 255, 255, 0.22)',
1895
- wobbleSeed: 'panel-arrow', duration: 400,
1896
- arrowheadSize: 14, strokeWidth: 1.5,
1897
- }), 250);
1898
-
1899
- seq.add(() => handwrittenLabel(svg, 'Side Panel', {
1900
- x: textX, y: textY,
1901
- textAnchor: 'middle',
1902
- color: 'rgba(255, 255, 255, 0.6)',
1903
- fontSize: 28, duration: 350,
1904
- }), 400);
1905
-
1906
- seq.add(() => handwrittenLabel(svg, 'Chat with Claude Code without leaving the board', {
1907
- x: textX, y: textY + 36,
1908
- textAnchor: 'middle',
1909
- color: 'rgba(255, 255, 255, 0.32)',
1910
- fontSize: 19, duration: 300,
1911
- }), 100);
1912
-
1913
- seq.add(() => {
1914
- const navY = textY + 105;
1915
- const backEl = createButton(dom, 'Back', {
1916
- x: textX - 80, y: navY, fontSize: 22,
1917
- color: 'rgba(255, 255, 255, 0.35)', onClick: () => prevStep(),
1918
- });
1919
- const endEl = createButton(dom, 'End', {
1920
- x: textX, y: navY, fontSize: 17,
1921
- color: 'rgba(255, 255, 255, 0.25)', onClick: () => skipTutorial(),
1922
- });
1923
- const nextEl = createButton(dom, 'Next', {
1924
- x: textX + 80, y: navY, fontSize: 22,
1925
- color: 'rgba(255, 255, 255, 0.35)', onClick: () => nextStep(),
1926
- });
1927
- return { destroy() { backEl.remove(); endEl.remove(); nextEl.remove(); } };
1928
- }, 200);
1929
- },
1930
- },
1931
-
1932
- // ── Step 24: Menubar Tour (animated sweep) ───────────
1933
- {
1934
- id: 'explain-menubar',
1935
- whiteboardMode: true,
1936
-
1937
- onExit() {
1938
- document.querySelectorAll('.menubar-item.open').forEach(m => m.classList.remove('open'));
1939
- },
1940
-
1941
- render({ svg, dom, seq, vw, vh, nextStep, prevStep, skipTutorial, createButton }) {
1942
- document.querySelectorAll('.menubar-item.open').forEach(m => m.classList.remove('open'));
1943
-
1944
- const menubar = document.querySelector('.menubar');
1945
- if (!menubar) return;
1946
- const mbRect = menubar.getBoundingClientRect();
1947
- const cx = vw / 2;
1948
-
1949
- // Menus to sweep — resume stays closed (no dropdown content to show)
1950
- const menus = [
1951
- { menu: 'apps', desc: 'Your AI tools live here', open: true },
1952
- { menu: 'resume', desc: 'Continue where you left off', open: false },
1953
- { menu: 'view', desc: 'Show or hide panels', open: true },
1954
- { menu: 'graph', desc: 'Tune the memory graph', open: true },
1955
- { menu: 'skills', desc: 'Reusable AI skills', open: true },
1956
- { menu: 'automations', desc: 'Workflows on autopilot', open: true },
1957
- { menu: 'games', desc: 'You earned a break', open: true },
1958
- ];
1959
-
1960
- // Sweep state
1961
- let sweepG = null;
1962
- let currentOpenItem = null;
1963
-
1964
- const cleanupSweep = () => {
1965
- if (sweepG) { sweepG.remove(); sweepG = null; }
1966
- if (currentOpenItem) { currentOpenItem.classList.remove('open'); currentOpenItem = null; }
1967
- };
1968
-
1969
- // Sweep through each menu
1970
- menus.forEach((m, i) => {
1971
- seq.add(() => {
1972
- cleanupSweep();
1973
-
1974
- const menuItem = document.querySelector(`.menubar-item[data-menu="${m.menu}"]`);
1975
- if (!menuItem) return;
1976
-
1977
- const label = menuItem.querySelector('.menubar-label');
1978
- const labelRect = label?.getBoundingClientRect();
1979
- if (!labelRect) return;
1980
-
1981
- // SVG group for this menu's annotations
1982
- sweepG = document.createElementNS('http://www.w3.org/2000/svg', 'g');
1983
- svg.appendChild(sweepG);
1984
-
1985
- // Highlight circle around the label
1986
- createHighlightCircle(sweepG, labelRect, {
1987
- color: 'rgba(255, 255, 255, 0.2)',
1988
- padding: 6, duration: 350, strokeWidth: 1,
1989
- });
1990
-
1991
- const labelCx = labelRect.left + labelRect.width / 2;
1992
-
1993
- if (m.open) {
1994
- // Open the dropdown
1995
- menuItem.classList.add('open');
1996
- currentOpenItem = menuItem;
1997
-
1998
- const dropdown = menuItem.querySelector('.menubar-dropdown');
1999
- if (dropdown) dropdown.offsetHeight;
2000
- const ddRect = dropdown?.getBoundingClientRect();
2001
-
2002
- if (ddRect && ddRect.width > 0) {
2003
- const ddCx = ddRect.left + ddRect.width / 2;
2004
- const textX = Math.max(200, Math.min(ddCx, vw - 200));
2005
- const textY = ddRect.bottom + 40;
2006
-
2007
- createAnimatedArrow(sweepG, {
2008
- from: { x: textX, y: textY - 10 },
2009
- to: { x: ddCx, y: ddRect.bottom + 8 },
2010
- color: 'rgba(255, 255, 255, 0.22)',
2011
- wobbleSeed: `${m.menu}-sweep`, duration: 200,
2012
- strokeWidth: 1.2, arrowheadSize: 10,
2013
- });
2014
-
2015
- handwrittenLabel(sweepG, m.desc, {
2016
- x: textX, y: textY,
2017
- textAnchor: 'middle', maxWidth: 400,
2018
- color: 'rgba(255, 255, 255, 0.45)',
2019
- fontSize: 22, duration: 200,
2020
- });
2021
- }
2022
- } else {
2023
- // Closed menu — show description below the label
2024
- const textX = Math.max(200, Math.min(labelCx, vw - 200));
2025
- const textY = labelRect.bottom + 55;
2026
-
2027
- createAnimatedArrow(sweepG, {
2028
- from: { x: textX, y: textY - 10 },
2029
- to: { x: labelCx, y: labelRect.bottom + 10 },
2030
- color: 'rgba(255, 255, 255, 0.22)',
2031
- wobbleSeed: `${m.menu}-sweep`, duration: 200,
2032
- strokeWidth: 1.2, arrowheadSize: 10,
2033
- });
2034
-
2035
- handwrittenLabel(sweepG, m.desc, {
2036
- x: textX, y: textY,
2037
- textAnchor: 'middle', maxWidth: 400,
2038
- color: 'rgba(255, 255, 255, 0.45)',
2039
- fontSize: 22, duration: 200,
2040
- });
2041
- }
2042
-
2043
- return { destroy: cleanupSweep };
2044
- }, i === 0 ? 600 : 3000);
2045
- });
2046
-
2047
- // After sweep — close last menu, show summary + nav
2048
- seq.add(() => {
2049
- cleanupSweep();
2050
-
2051
- handwrittenLabel(svg, 'Explore each menu at your own pace', {
2052
- x: cx, y: mbRect.bottom + 80,
2053
- textAnchor: 'middle',
2054
- color: 'rgba(255, 255, 255, 0.38)',
2055
- fontSize: 22, duration: 300,
2056
- });
2057
-
2058
- createDoodle(svg, 'sparkle', {
2059
- x: cx - 200, y: mbRect.bottom + 60,
2060
- scale: 0.7, color: 'rgba(255, 255, 255, 0.18)', duration: 300,
2061
- });
2062
- createDoodle(svg, 'sparkle', {
2063
- x: cx + 190, y: mbRect.bottom + 70,
2064
- scale: 0.6, color: 'rgba(255, 255, 255, 0.18)', duration: 300,
2065
- });
2066
-
2067
- const navY = mbRect.bottom + 145;
2068
- const backEl = createButton(dom, 'Back', {
2069
- x: cx - 80, y: navY, fontSize: 22,
2070
- color: 'rgba(255, 255, 255, 0.35)', onClick: () => prevStep(),
2071
- });
2072
- const endEl = createButton(dom, 'End', {
2073
- x: cx, y: navY, fontSize: 17,
2074
- color: 'rgba(255, 255, 255, 0.25)', onClick: () => skipTutorial(),
2075
- });
2076
- const nextEl = createButton(dom, 'Next', {
2077
- x: cx + 80, y: navY, fontSize: 22,
2078
- color: 'rgba(255, 255, 255, 0.35)', onClick: () => nextStep(),
2079
- });
2080
- return { destroy() { backEl.remove(); endEl.remove(); nextEl.remove(); } };
2081
- }, 1500);
2082
- },
2083
- },
2084
-
2085
- // ── Step 25: Whiteboard Toolbar ─────────────────────
2086
- {
2087
- id: 'explain-whiteboard-toolbar',
2088
- whiteboardMode: true,
2089
-
2090
- onEnter() {
2091
- const tb = document.getElementById('wb-toolbar');
2092
- if (tb) tb.classList.remove('tutorial-hidden');
2093
- },
2094
-
2095
- onExit() {
2096
- const tb = document.getElementById('wb-toolbar');
2097
- if (tb) tb.classList.add('tutorial-hidden');
2098
- },
2099
-
2100
- render({ svg, dom, seq, vw, vh, nextStep, prevStep, skipTutorial, createButton }) {
2101
- const toolbar = document.getElementById('wb-toolbar');
2102
- if (!toolbar) return;
2103
- toolbar.offsetHeight; // force reflow after unhide
2104
- const tbRect = toolbar.getBoundingClientRect();
2105
- const cx = vw / 2;
2106
-
2107
- // 1. Highlight the toolbar
2108
- seq.add(() => createHighlightCircle(svg, tbRect, {
2109
- color: 'rgba(255, 255, 255, 0.18)',
2110
- padding: 12, duration: 500, strokeWidth: 1,
2111
- }), 100);
2112
-
2113
- // 2. Arrow from description up to toolbar
2114
- const textY = tbRect.bottom + 70;
2115
- seq.add(() => createAnimatedArrow(svg, {
2116
- from: { x: cx, y: textY - 12 },
2117
- to: { x: tbRect.left + tbRect.width / 2, y: tbRect.bottom + 12 },
2118
- color: 'rgba(255, 255, 255, 0.22)',
2119
- wobbleSeed: 'wb-toolbar', duration: 300,
2120
- strokeWidth: 1.2, arrowheadSize: 10,
2121
- }), 200);
2122
-
2123
- // 3. Title
2124
- seq.add(() => handwrittenLabel(svg, 'The Whiteboard', {
2125
- x: cx, y: textY,
2126
- textAnchor: 'middle',
2127
- color: 'rgba(255, 255, 255, 0.55)',
2128
- fontSize: 28, duration: 300,
2129
- }), 200);
2130
-
2131
- // 4. Description lines
2132
- seq.add(() => handwrittenLabel(svg, 'Draw, write, sketch — Claude can see everything here.', {
2133
- x: cx, y: textY + 38,
2134
- textAnchor: 'middle',
2135
- color: 'rgba(255, 255, 255, 0.4)',
2136
- fontSize: 20, duration: 250,
2137
- }), 200);
2138
-
2139
- seq.add(() => handwrittenLabel(svg, 'Just say "look at the whiteboard" and it will.', {
2140
- x: cx, y: textY + 68,
2141
- textAnchor: 'middle',
2142
- color: 'rgba(255, 255, 255, 0.4)',
2143
- fontSize: 20, duration: 250,
2144
- }), 200);
2145
-
2146
- // 5. Nav
2147
- seq.add(() => {
2148
- const navY = textY + 130;
2149
- const backEl = createButton(dom, 'Back', {
2150
- x: cx - 80, y: navY, fontSize: 22,
2151
- color: 'rgba(255, 255, 255, 0.35)', onClick: () => prevStep(),
2152
- });
2153
- const endEl = createButton(dom, 'End', {
2154
- x: cx, y: navY, fontSize: 17,
2155
- color: 'rgba(255, 255, 255, 0.25)', onClick: () => skipTutorial(),
2156
- });
2157
- const nextEl = createButton(dom, 'Next', {
2158
- x: cx + 80, y: navY, fontSize: 22,
2159
- color: 'rgba(255, 255, 255, 0.35)', onClick: () => nextStep(),
2160
- });
2161
- return { destroy() { backEl.remove(); endEl.remove(); nextEl.remove(); } };
2162
- }, 200);
2163
- },
2164
- },
2165
-
2166
- // ── Step 26: Feedback / Social links ──────────────────
2167
- {
2168
- id: 'feedback',
2169
- whiteboardMode: true,
2170
-
2171
- render({ svg, dom, seq, vw, vh, nextStep, prevStep, skipTutorial, createButton }) {
2172
- // Close any previously open dropdowns
2173
- document.querySelectorAll('.menubar-item.open').forEach(m => m.classList.remove('open'));
2174
-
2175
- const cx = vw / 2;
2176
- const cy = vh / 2 - 60;
2177
-
2178
- // 1. "Feedback is always welcome" handwritten text
2179
- seq.add(() => handwrittenLabel(svg, 'Feedback is always welcome', {
2180
- x: cx,
2181
- y: cy,
2182
- color: 'rgba(255, 255, 255, 0.55)',
2183
- fontSize: 34,
2184
- textAnchor: 'middle',
2185
- duration: 400,
2186
- }), 200);
2187
-
2188
- // 2. Decorative sparkles
2189
- seq.add(() => createDoodle(svg, 'sparkle', {
2190
- x: cx - 220, y: cy - 50,
2191
- scale: 1, color: 'rgba(255, 255, 255, 0.25)', duration: 300,
2192
- }), 300);
2193
- seq.add(() => createDoodle(svg, 'sparkle', {
2194
- x: cx + 200, y: cy + 10,
2195
- scale: 0.8, color: 'rgba(255, 255, 255, 0.25)', duration: 300,
2196
- }), 400);
64
+ export const ONBOARDING_STEPS = [
65
+ { id: 'onboarding-explore', kind: 'explore' },
66
+ { id: 'onboarding-token-warning', kind: 'warning' },
67
+ { id: 'onboarding-cli-picker', kind: 'cli' },
68
+ { id: 'onboarding-model-picker', kind: 'model' },
69
+ { id: 'onboarding-project-picker', kind: 'project' },
70
+ { id: 'onboarding-memory-explain', kind: 'launch' },
71
+ ];
2197
72
 
2198
- // 3. Social icons row
2199
- seq.add(() => {
2200
- const iconY = cy + 60;
2201
- const gap = 90;
73
+ // A feature step:
74
+ // targets ordered alternatives, [selector, copyKey = 'body', lastSelector?]. The first one on
75
+ // screen is annotated and its copy shown; `lastSelector` widens the outline to a run
76
+ // of controls. None on screen: the note stays, with the navigation.
77
+ // menu a menubar dropdown opened while the step shows (closed again after).
78
+ // panel 'assistant' shows the Assistant panel for the step when that starts nothing
79
+ // (see assistantPanelPeekable); otherwise the last target, its button, is used.
80
+ // copy per-variant copy key for the first target ({ '2d': 'body2d' }).
81
+ const ASSISTANT_BUTTON = ['#topright-assistant-panel-btn', 'closed'];
82
+ const ACTIVE_TAB = '#assistant-panel.open .asp-viewport.active';
83
+ const ACTIVE_BAR = '#assistant-panel.open .asp-tab-bar.active';
84
+
85
+ export const FEATURE_STEPS = [
86
+ { id: 'explain-memory-explorer', chapter: 'memory', targets: [['#topright-memory-explorer-btn']] },
87
+ { id: 'explain-graph', chapter: 'memory', copy: { '2d': 'body2d' }, targets: [['[data-menu="graph"] > .menubar-label']] },
88
+ { id: 'explain-focus', chapter: 'workspace', targets: [['#wb-toolbar'], ['#titlebar-viz-toggle', 'graph']] },
89
+ { id: 'explain-workspaces', chapter: 'workspace', targets: [['#ws-indicator']] },
90
+ { id: 'explain-terminals', chapter: 'tools', menu: 'apps', targets: [['#menu-terminal-claude', 'body', '#menu-terminal-opencode']] },
91
+ { id: 'explain-browser', chapter: 'tools', menu: 'apps', targets: [['#menu-terminal-browser']] },
92
+ { id: 'explain-side-panel', chapter: 'tools', targets: [['#topright-claude-panel-btn', 'body', '#topright-opencode-panel-btn']] },
93
+ { id: 'explain-automations', chapter: 'automation', menu: 'automations', targets: [['#menu-open-automation-studio']] },
94
+ { id: 'explain-schedules', chapter: 'automation', menu: 'automations', targets: [['#menu-automations-schedules']] },
95
+ { id: 'assistant-start', chapter: 'assistant', panel: 'assistant', targets: [[`${ACTIVE_TAB} .asst-input`], ASSISTANT_BUTTON] },
96
+ { id: 'assistant-tools', chapter: 'assistant', panel: 'assistant', targets: [[`${ACTIVE_BAR} .asst-computer-toggle`], ASSISTANT_BUTTON] },
97
+ { id: 'assistant-route', chapter: 'assistant', panel: 'assistant', targets: [[`${ACTIVE_BAR} .asst-route-chip`], ASSISTANT_BUTTON] },
98
+ { id: 'assistant-track', chapter: 'assistant', panel: 'assistant',
99
+ targets: [[`${ACTIVE_TAB} .asst-usage-strip`], [`${ACTIVE_BAR} .asst-act-more`, 'more'], ASSISTANT_BUTTON] },
100
+ { id: 'explain-help', chapter: 'help', targets: [['#titlebar-tutorial-btn']] },
101
+ ];
2202
102
 
2203
- const socials = [
2204
- {
2205
- label: 'Discord',
2206
- url: 'https://discord.gg/x6yWqE9GZP',
2207
- svg: '<svg width="28" height="28" viewBox="0 0 24 24" fill="currentColor"><path d="M20.317 4.37a19.791 19.791 0 0 0-4.885-1.515.074.074 0 0 0-.079.037c-.21.375-.444.864-.608 1.25a18.27 18.27 0 0 0-5.487 0 12.64 12.64 0 0 0-.617-1.25.077.077 0 0 0-.079-.037A19.736 19.736 0 0 0 3.677 4.37a.07.07 0 0 0-.032.027C.533 9.046-.32 13.58.099 18.057a.082.082 0 0 0 .031.057 19.9 19.9 0 0 0 5.993 3.03.078.078 0 0 0 .084-.028c.462-.63.874-1.295 1.226-1.994a.076.076 0 0 0-.041-.106 13.107 13.107 0 0 1-1.872-.892.077.077 0 0 1-.008-.128 10.2 10.2 0 0 0 .372-.292.074.074 0 0 1 .077-.01c3.928 1.793 8.18 1.793 12.062 0a.074.074 0 0 1 .078.01c.12.098.246.198.373.292a.077.077 0 0 1-.006.127 12.299 12.299 0 0 1-1.873.892.077.077 0 0 0-.041.107c.36.698.772 1.362 1.225 1.993a.076.076 0 0 0 .084.028 19.839 19.839 0 0 0 6.002-3.03.077.077 0 0 0 .032-.054c.5-5.177-.838-9.674-3.549-13.66a.061.061 0 0 0-.031-.03zM8.02 15.33c-1.183 0-2.157-1.085-2.157-2.419 0-1.333.956-2.419 2.157-2.419 1.21 0 2.176 1.095 2.157 2.42 0 1.333-.956 2.418-2.157 2.418zm7.975 0c-1.183 0-2.157-1.085-2.157-2.419 0-1.333.955-2.419 2.157-2.419 1.21 0 2.176 1.095 2.157 2.42 0 1.333-.946 2.418-2.157 2.418z"/></svg>',
2208
- },
2209
- {
2210
- label: 'GitHub',
2211
- url: 'https://github.com/danilokhury/Synabun',
2212
- svg: '<svg width="28" height="28" viewBox="0 0 24 24" fill="currentColor"><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg>',
2213
- },
2214
- {
2215
- label: 'X',
2216
- url: 'https://x.com/SynabunAI',
2217
- svg: '<svg width="28" height="28" viewBox="0 0 24 24" fill="currentColor"><path d="M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231zm-1.161 17.52h1.833L7.084 4.126H5.117z"/></svg>',
2218
- },
2219
- ];
103
+ export const SKIP_HINT = { id: 'skip-hint', chapter: 'help', targets: [['#titlebar-tutorial-btn']] };
2220
104
 
2221
- const els = [];
2222
- socials.forEach((s, i) => {
2223
- const x = cx + (i - 1) * gap;
2224
- const el = document.createElement('a');
2225
- el.href = s.url;
2226
- el.target = '_blank';
2227
- el.rel = 'noopener';
2228
- el.title = s.label;
2229
- el.style.cssText = `
2230
- position: absolute;
2231
- left: ${x}px; top: ${iconY}px;
2232
- transform: translate(-50%, 0);
2233
- display: flex; flex-direction: column; align-items: center; gap: 8px;
2234
- color: rgba(255, 255, 255, 0.4);
2235
- text-decoration: none;
2236
- pointer-events: auto;
2237
- transition: color 0.2s, transform 0.2s;
2238
- opacity: 0;
2239
- font-family: 'Caveat', cursive;
2240
- font-size: 18px;
2241
- cursor: pointer;
2242
- `;
2243
- el.innerHTML = `${s.svg}<span>${s.label}</span>`;
2244
- dom.appendChild(el);
2245
- requestAnimationFrame(() => { el.style.opacity = '1'; });
105
+ export const CHAPTERS = [...new Set(FEATURE_STEPS.map(s => s.chapter))];
2246
106
 
2247
- el.addEventListener('mouseenter', () => {
2248
- el.style.color = 'rgba(255, 255, 255, 0.8)';
2249
- el.style.transform = 'translate(-50%, 0) scale(1.1)';
2250
- });
2251
- el.addEventListener('mouseleave', () => {
2252
- el.style.color = 'rgba(255, 255, 255, 0.4)';
2253
- el.style.transform = 'translate(-50%, 0) scale(1)';
2254
- });
2255
- els.push(el);
2256
- });
107
+ export const TUTORIAL_STEPS = [...ONBOARDING_STEPS, { id: 'welcome', kind: 'welcome' }, ...FEATURE_STEPS];
2257
108
 
2258
- return { destroy() { els.forEach(e => e.remove()); } };
2259
- }, 300);
109
+ const WELCOME = TUTORIAL_STEPS.findIndex(s => s.id === 'welcome');
2260
110
 
2261
- // 4. Navigation buttons
2262
- seq.add(() => {
2263
- const navY = cy + 170;
2264
- const backEl = createButton(dom, 'Back', {
2265
- x: cx - 70, y: navY, fontSize: 22,
2266
- color: 'rgba(255, 255, 255, 0.4)', onClick: () => prevStep(),
2267
- });
2268
- const doneEl = createButton(dom, 'Done', {
2269
- x: cx + 70, y: navY, fontSize: 22,
2270
- color: 'rgba(255, 255, 255, 0.4)', onClick: () => nextStep(),
2271
- });
2272
- return { destroy() { backEl.remove(); doneEl.remove(); } };
2273
- }, 200);
2274
- },
2275
- },
2276
- ];
111
+ // Existing numeric cursors migrate to retained step ids. The old onboarding
112
+ // indices never make a returning user repeat CLI/model/project choices.
113
+ export function resumeIndex(value, includeOnboarding = false) {
114
+ const direct = TUTORIAL_STEPS.findIndex(s => s.id === value);
115
+ if (direct >= 0) return includeOnboarding ? direct : Math.max(WELCOME, direct);
116
+ const legacy = ['onboarding-explore', 'onboarding-token-warning', 'onboarding-cli-picker', 'onboarding-model-picker',
117
+ 'onboarding-project-picker', 'onboarding-memory-explain', 'welcome', 'explain-sessions', 'explain-gallery',
118
+ 'explain-cost', 'explain-help', 'explain-focus', 'explain-fullscreen', 'explain-clock', 'explain-trash', 'explain-grid',
119
+ 'explain-tile', 'explain-keybinds', 'explain-memory-explorer', 'explain-file-explorer', 'explain-bookmarks',
120
+ 'explain-share', 'explain-workspaces', 'explain-side-panel', 'explain-menubar', 'explain-whiteboard-toolbar', 'feedback'];
121
+ if (value != null && /^\d+$/.test(value)) {
122
+ const mapped = TUTORIAL_STEPS.findIndex(s => s.id === legacy[Number(value)]);
123
+ return mapped >= WELCOME ? mapped : WELCOME;
124
+ }
125
+ return includeOnboarding ? 0 : WELCOME;
126
+ }