@jinion/core 0.3.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (377) hide show
  1. package/dist/agent/claude/backend.d.ts +4 -0
  2. package/dist/agent/claude/backend.d.ts.map +1 -1
  3. package/dist/agent/claude/backend.js.map +1 -1
  4. package/dist/agent/claude/events.js +1 -1
  5. package/dist/agent/claude/events.js.map +1 -1
  6. package/dist/agent/claude/guard.d.ts.map +1 -1
  7. package/dist/agent/claude/guard.js +2 -1
  8. package/dist/agent/claude/guard.js.map +1 -1
  9. package/dist/agent/claude/jinion-tools.d.ts +9 -1
  10. package/dist/agent/claude/jinion-tools.d.ts.map +1 -1
  11. package/dist/agent/claude/jinion-tools.js +14 -2
  12. package/dist/agent/claude/jinion-tools.js.map +1 -1
  13. package/dist/agent/claude/mcp.d.ts.map +1 -1
  14. package/dist/agent/claude/mcp.js +21 -1
  15. package/dist/agent/claude/mcp.js.map +1 -1
  16. package/dist/agent/claude/options.d.ts +9 -1
  17. package/dist/agent/claude/options.d.ts.map +1 -1
  18. package/dist/agent/claude/options.js +5 -3
  19. package/dist/agent/claude/options.js.map +1 -1
  20. package/dist/agent/claude/paths.d.ts +0 -3
  21. package/dist/agent/claude/paths.d.ts.map +1 -1
  22. package/dist/agent/claude/paths.js +1 -7
  23. package/dist/agent/claude/paths.js.map +1 -1
  24. package/dist/agent/claude/permissions.js +1 -1
  25. package/dist/agent/claude/permissions.js.map +1 -1
  26. package/dist/agent/claude/prompt.d.ts +2 -1
  27. package/dist/agent/claude/prompt.d.ts.map +1 -1
  28. package/dist/agent/claude/prompt.js +10 -5
  29. package/dist/agent/claude/prompt.js.map +1 -1
  30. package/dist/agent/claude/review.d.ts +4 -1
  31. package/dist/agent/claude/review.d.ts.map +1 -1
  32. package/dist/agent/claude/review.js +5 -2
  33. package/dist/agent/claude/review.js.map +1 -1
  34. package/dist/agent/claude/session.d.ts +7 -0
  35. package/dist/agent/claude/session.d.ts.map +1 -1
  36. package/dist/agent/claude/session.js +6 -1
  37. package/dist/agent/claude/session.js.map +1 -1
  38. package/dist/agent/claude/tool-calls.d.ts.map +1 -1
  39. package/dist/agent/claude/tool-calls.js +11 -2
  40. package/dist/agent/claude/tool-calls.js.map +1 -1
  41. package/dist/agent/codex/backend.d.ts +4 -0
  42. package/dist/agent/codex/backend.d.ts.map +1 -1
  43. package/dist/agent/codex/backend.js.map +1 -1
  44. package/dist/agent/codex/events.d.ts.map +1 -1
  45. package/dist/agent/codex/events.js +15 -1
  46. package/dist/agent/codex/events.js.map +1 -1
  47. package/dist/agent/codex/jinion-tools.d.ts +38 -4
  48. package/dist/agent/codex/jinion-tools.d.ts.map +1 -1
  49. package/dist/agent/codex/jinion-tools.js +57 -10
  50. package/dist/agent/codex/jinion-tools.js.map +1 -1
  51. package/dist/agent/codex/mcp.d.ts.map +1 -1
  52. package/dist/agent/codex/mcp.js +4 -0
  53. package/dist/agent/codex/mcp.js.map +1 -1
  54. package/dist/agent/codex/rewind.js +1 -47
  55. package/dist/agent/codex/rewind.js.map +1 -1
  56. package/dist/agent/codex/session.d.ts +9 -2
  57. package/dist/agent/codex/session.d.ts.map +1 -1
  58. package/dist/agent/codex/session.js +21 -7
  59. package/dist/agent/codex/session.js.map +1 -1
  60. package/dist/agent/demo/mcp.d.ts +2 -0
  61. package/dist/agent/demo/mcp.d.ts.map +1 -1
  62. package/dist/agent/demo/mcp.js +14 -0
  63. package/dist/agent/demo/mcp.js.map +1 -1
  64. package/dist/agent/demo/scenarios/pricing-card.d.ts +3 -0
  65. package/dist/agent/demo/scenarios/pricing-card.d.ts.map +1 -0
  66. package/dist/agent/demo/scenarios/pricing-card.js +43 -0
  67. package/dist/agent/demo/scenarios/pricing-card.js.map +1 -0
  68. package/dist/agent/demo/script.d.ts +6 -0
  69. package/dist/agent/demo/script.d.ts.map +1 -1
  70. package/dist/agent/demo/tasks.d.ts +3 -0
  71. package/dist/agent/demo/tasks.d.ts.map +1 -1
  72. package/dist/agent/events.d.ts +3 -0
  73. package/dist/agent/events.d.ts.map +1 -1
  74. package/dist/agent/events.js +2 -0
  75. package/dist/agent/events.js.map +1 -1
  76. package/dist/agent/mcp.d.ts +5 -0
  77. package/dist/agent/mcp.d.ts.map +1 -1
  78. package/dist/agent/mcp.js +2 -0
  79. package/dist/agent/mcp.js.map +1 -1
  80. package/dist/agent/patches.d.ts +5 -0
  81. package/dist/agent/patches.d.ts.map +1 -1
  82. package/dist/agent/patches.js +49 -0
  83. package/dist/agent/patches.js.map +1 -1
  84. package/dist/agent/review-tools.d.ts +15 -0
  85. package/dist/agent/review-tools.d.ts.map +1 -0
  86. package/dist/agent/review-tools.js +13 -0
  87. package/dist/agent/review-tools.js.map +1 -0
  88. package/dist/agent/review.d.ts +18 -6
  89. package/dist/agent/review.d.ts.map +1 -1
  90. package/dist/agent/review.js +52 -17
  91. package/dist/agent/review.js.map +1 -1
  92. package/dist/api/client.d.ts +15 -1
  93. package/dist/api/client.d.ts.map +1 -1
  94. package/dist/api/client.js +14 -3
  95. package/dist/api/client.js.map +1 -1
  96. package/dist/api/connection.d.ts +5 -0
  97. package/dist/api/connection.d.ts.map +1 -1
  98. package/dist/api/connection.js +6 -0
  99. package/dist/api/connection.js.map +1 -1
  100. package/dist/api/fields.d.ts +3 -1
  101. package/dist/api/fields.d.ts.map +1 -1
  102. package/dist/api/fields.js +3 -2
  103. package/dist/api/fields.js.map +1 -1
  104. package/dist/api/json-schema.d.ts +592 -89
  105. package/dist/api/json-schema.d.ts.map +1 -1
  106. package/dist/api/json-schema.js +2 -1
  107. package/dist/api/json-schema.js.map +1 -1
  108. package/dist/api/methods/accounts.d.ts.map +1 -1
  109. package/dist/api/methods/accounts.js +1 -2
  110. package/dist/api/methods/accounts.js.map +1 -1
  111. package/dist/api/methods/app.d.ts.map +1 -1
  112. package/dist/api/methods/app.js +9 -5
  113. package/dist/api/methods/app.js.map +1 -1
  114. package/dist/api/methods/files.d.ts +3 -1
  115. package/dist/api/methods/files.d.ts.map +1 -1
  116. package/dist/api/methods/files.js +75 -2
  117. package/dist/api/methods/files.js.map +1 -1
  118. package/dist/api/methods/git.d.ts.map +1 -1
  119. package/dist/api/methods/git.js +54 -6
  120. package/dist/api/methods/git.js.map +1 -1
  121. package/dist/api/methods/lsp.d.ts +7 -0
  122. package/dist/api/methods/lsp.d.ts.map +1 -0
  123. package/dist/api/methods/lsp.js +68 -0
  124. package/dist/api/methods/lsp.js.map +1 -0
  125. package/dist/api/methods/preview.d.ts +4 -1
  126. package/dist/api/methods/preview.d.ts.map +1 -1
  127. package/dist/api/methods/preview.js +19 -3
  128. package/dist/api/methods/preview.js.map +1 -1
  129. package/dist/api/methods/terminals.d.ts.map +1 -1
  130. package/dist/api/methods/terminals.js +7 -1
  131. package/dist/api/methods/terminals.js.map +1 -1
  132. package/dist/api/protocol.d.ts +762 -7
  133. package/dist/api/protocol.d.ts.map +1 -1
  134. package/dist/api/protocol.js +126 -8
  135. package/dist/api/protocol.js.map +1 -1
  136. package/dist/api/schemas.d.ts +7 -0
  137. package/dist/api/schemas.d.ts.map +1 -1
  138. package/dist/api/schemas.js +4 -0
  139. package/dist/api/schemas.js.map +1 -1
  140. package/dist/api/screen.d.ts +2 -0
  141. package/dist/api/screen.d.ts.map +1 -1
  142. package/dist/api/screen.js +3 -0
  143. package/dist/api/screen.js.map +1 -1
  144. package/dist/api/server.d.ts +2 -0
  145. package/dist/api/server.d.ts.map +1 -1
  146. package/dist/api/server.js +13 -0
  147. package/dist/api/server.js.map +1 -1
  148. package/dist/commands/builtin.d.ts.map +1 -1
  149. package/dist/commands/builtin.js +2 -0
  150. package/dist/commands/builtin.js.map +1 -1
  151. package/dist/commands/conversation.d.ts.map +1 -1
  152. package/dist/commands/conversation.js +2 -0
  153. package/dist/commands/conversation.js.map +1 -1
  154. package/dist/commands/feedback.d.ts.map +1 -1
  155. package/dist/commands/feedback.js +1 -0
  156. package/dist/commands/feedback.js.map +1 -1
  157. package/dist/commands/notifications.d.ts.map +1 -1
  158. package/dist/commands/notifications.js +5 -3
  159. package/dist/commands/notifications.js.map +1 -1
  160. package/dist/commands/registry.d.ts +3 -0
  161. package/dist/commands/registry.d.ts.map +1 -1
  162. package/dist/commands/registry.js +14 -0
  163. package/dist/commands/registry.js.map +1 -1
  164. package/dist/commands/skill.d.ts +5 -0
  165. package/dist/commands/skill.d.ts.map +1 -0
  166. package/dist/commands/skill.js +30 -0
  167. package/dist/commands/skill.js.map +1 -0
  168. package/dist/commands/views.d.ts.map +1 -1
  169. package/dist/commands/views.js +5 -1
  170. package/dist/commands/views.js.map +1 -1
  171. package/dist/controllers/accounts.d.ts +5 -2
  172. package/dist/controllers/accounts.d.ts.map +1 -1
  173. package/dist/controllers/accounts.js +11 -8
  174. package/dist/controllers/accounts.js.map +1 -1
  175. package/dist/controllers/context.d.ts +2 -0
  176. package/dist/controllers/context.d.ts.map +1 -1
  177. package/dist/controllers/context.js.map +1 -1
  178. package/dist/controllers/feedback.d.ts +1 -1
  179. package/dist/controllers/feedback.d.ts.map +1 -1
  180. package/dist/controllers/feedback.js +4 -1
  181. package/dist/controllers/feedback.js.map +1 -1
  182. package/dist/controllers/input.d.ts.map +1 -1
  183. package/dist/controllers/input.js +2 -0
  184. package/dist/controllers/input.js.map +1 -1
  185. package/dist/controllers/jinion.d.ts +7 -0
  186. package/dist/controllers/jinion.d.ts.map +1 -1
  187. package/dist/controllers/jinion.js +7 -0
  188. package/dist/controllers/jinion.js.map +1 -1
  189. package/dist/controllers/mcp.d.ts +7 -2
  190. package/dist/controllers/mcp.d.ts.map +1 -1
  191. package/dist/controllers/mcp.js +23 -7
  192. package/dist/controllers/mcp.js.map +1 -1
  193. package/dist/controllers/session.d.ts.map +1 -1
  194. package/dist/controllers/session.js +4 -0
  195. package/dist/controllers/session.js.map +1 -1
  196. package/dist/conversation/activity.d.ts +5 -0
  197. package/dist/conversation/activity.d.ts.map +1 -0
  198. package/dist/conversation/activity.js +41 -0
  199. package/dist/conversation/activity.js.map +1 -0
  200. package/dist/conversation/apply-event.d.ts.map +1 -1
  201. package/dist/conversation/apply-event.js +2 -1
  202. package/dist/conversation/apply-event.js.map +1 -1
  203. package/dist/conversation/edits.d.ts +5 -0
  204. package/dist/conversation/edits.d.ts.map +1 -1
  205. package/dist/conversation/edits.js +10 -0
  206. package/dist/conversation/edits.js.map +1 -1
  207. package/dist/conversation/reducer.d.ts +9 -0
  208. package/dist/conversation/reducer.d.ts.map +1 -1
  209. package/dist/design/guides.d.ts +78 -5
  210. package/dist/design/guides.d.ts.map +1 -1
  211. package/dist/design/guides.js +78 -5
  212. package/dist/design/guides.js.map +1 -1
  213. package/dist/design/prompt.d.ts +1 -1
  214. package/dist/design/prompt.d.ts.map +1 -1
  215. package/dist/design/prompt.js +2 -2
  216. package/dist/design/prompt.js.map +1 -1
  217. package/dist/design/tools.d.ts +2 -0
  218. package/dist/design/tools.d.ts.map +1 -1
  219. package/dist/design/tools.js +6 -2
  220. package/dist/design/tools.js.map +1 -1
  221. package/dist/directions/directions.d.ts +42 -0
  222. package/dist/directions/directions.d.ts.map +1 -0
  223. package/dist/directions/directions.js +120 -0
  224. package/dist/directions/directions.js.map +1 -0
  225. package/dist/directions/store.d.ts +34 -0
  226. package/dist/directions/store.d.ts.map +1 -0
  227. package/dist/directions/store.js +61 -0
  228. package/dist/directions/store.js.map +1 -0
  229. package/dist/directions/tools.d.ts +29 -0
  230. package/dist/directions/tools.d.ts.map +1 -0
  231. package/dist/directions/tools.js +57 -0
  232. package/dist/directions/tools.js.map +1 -0
  233. package/dist/directions/viewer.d.ts +6 -0
  234. package/dist/directions/viewer.d.ts.map +1 -0
  235. package/dist/directions/viewer.js +266 -0
  236. package/dist/directions/viewer.js.map +1 -0
  237. package/dist/files/names.d.ts +6 -0
  238. package/dist/files/names.d.ts.map +1 -0
  239. package/dist/files/names.js +18 -0
  240. package/dist/files/names.js.map +1 -0
  241. package/dist/files/operations.d.ts +54 -0
  242. package/dist/files/operations.d.ts.map +1 -0
  243. package/dist/files/operations.js +173 -0
  244. package/dist/files/operations.js.map +1 -0
  245. package/dist/files/search.d.ts +11 -0
  246. package/dist/files/search.d.ts.map +1 -0
  247. package/dist/files/search.js +112 -0
  248. package/dist/files/search.js.map +1 -0
  249. package/dist/files/trash.d.ts +11 -0
  250. package/dist/files/trash.d.ts.map +1 -0
  251. package/dist/files/trash.js +64 -0
  252. package/dist/files/trash.js.map +1 -0
  253. package/dist/files/types.d.ts +112 -0
  254. package/dist/files/types.d.ts.map +1 -0
  255. package/dist/files/types.js +47 -0
  256. package/dist/files/types.js.map +1 -0
  257. package/dist/files/watch.d.ts +26 -0
  258. package/dist/files/watch.d.ts.map +1 -0
  259. package/dist/files/watch.js +107 -0
  260. package/dist/files/watch.js.map +1 -0
  261. package/dist/git/blame.d.ts +10 -0
  262. package/dist/git/blame.d.ts.map +1 -0
  263. package/dist/git/blame.js +91 -0
  264. package/dist/git/blame.js.map +1 -0
  265. package/dist/git/repos.d.ts +5 -0
  266. package/dist/git/repos.d.ts.map +1 -1
  267. package/dist/git/repos.js +13 -0
  268. package/dist/git/repos.js.map +1 -1
  269. package/dist/git/staging.d.ts +10 -1
  270. package/dist/git/staging.d.ts.map +1 -1
  271. package/dist/git/staging.js +21 -0
  272. package/dist/git/staging.js.map +1 -1
  273. package/dist/git/types.d.ts +48 -0
  274. package/dist/git/types.d.ts.map +1 -1
  275. package/dist/git/types.js +25 -0
  276. package/dist/git/types.js.map +1 -1
  277. package/dist/host.d.ts +2 -0
  278. package/dist/host.d.ts.map +1 -1
  279. package/dist/host.js +8 -1
  280. package/dist/host.js.map +1 -1
  281. package/dist/lib/glob.d.ts +6 -0
  282. package/dist/lib/glob.d.ts.map +1 -0
  283. package/dist/lib/glob.js +49 -0
  284. package/dist/lib/glob.js.map +1 -0
  285. package/dist/lib/paths.d.ts +3 -0
  286. package/dist/lib/paths.d.ts.map +1 -1
  287. package/dist/lib/paths.js +9 -1
  288. package/dist/lib/paths.js.map +1 -1
  289. package/dist/look/tools.d.ts +7 -1
  290. package/dist/look/tools.d.ts.map +1 -1
  291. package/dist/look/tools.js +19 -4
  292. package/dist/look/tools.js.map +1 -1
  293. package/dist/lsp/code-intelligence.d.ts +87 -0
  294. package/dist/lsp/code-intelligence.d.ts.map +1 -0
  295. package/dist/lsp/code-intelligence.js +343 -0
  296. package/dist/lsp/code-intelligence.js.map +1 -0
  297. package/dist/lsp/edits.d.ts +4 -0
  298. package/dist/lsp/edits.d.ts.map +1 -0
  299. package/dist/lsp/edits.js +14 -0
  300. package/dist/lsp/edits.js.map +1 -0
  301. package/dist/lsp/project-check.d.ts +8 -0
  302. package/dist/lsp/project-check.d.ts.map +1 -0
  303. package/dist/lsp/project-check.js +71 -0
  304. package/dist/lsp/project-check.js.map +1 -0
  305. package/dist/lsp/results.d.ts +95 -0
  306. package/dist/lsp/results.d.ts.map +1 -0
  307. package/dist/lsp/results.js +116 -0
  308. package/dist/lsp/results.js.map +1 -0
  309. package/dist/lsp/server.d.ts +22 -0
  310. package/dist/lsp/server.d.ts.map +1 -0
  311. package/dist/lsp/server.js +123 -0
  312. package/dist/lsp/server.js.map +1 -0
  313. package/dist/lsp/servers.d.ts +21 -0
  314. package/dist/lsp/servers.d.ts.map +1 -0
  315. package/dist/lsp/servers.js +57 -0
  316. package/dist/lsp/servers.js.map +1 -0
  317. package/dist/lsp/transport.d.ts +9 -0
  318. package/dist/lsp/transport.d.ts.map +1 -0
  319. package/dist/lsp/transport.js +64 -0
  320. package/dist/lsp/transport.js.map +1 -0
  321. package/dist/lsp/types.d.ts +262 -0
  322. package/dist/lsp/types.d.ts.map +1 -0
  323. package/dist/lsp/types.js +64 -0
  324. package/dist/lsp/types.js.map +1 -0
  325. package/dist/map/prompt.d.ts.map +1 -1
  326. package/dist/map/prompt.js +2 -1
  327. package/dist/map/prompt.js.map +1 -1
  328. package/dist/map/review.d.ts +29 -9
  329. package/dist/map/review.d.ts.map +1 -1
  330. package/dist/map/review.js +105 -25
  331. package/dist/map/review.js.map +1 -1
  332. package/dist/mcp/login.d.ts +2 -0
  333. package/dist/mcp/login.d.ts.map +1 -1
  334. package/dist/mcp/login.js +5 -0
  335. package/dist/mcp/login.js.map +1 -1
  336. package/dist/preview/pages.d.ts +17 -0
  337. package/dist/preview/pages.d.ts.map +1 -0
  338. package/dist/preview/pages.js +92 -0
  339. package/dist/preview/pages.js.map +1 -0
  340. package/dist/preview/previews.d.ts +22 -0
  341. package/dist/preview/previews.d.ts.map +1 -0
  342. package/dist/preview/previews.js +28 -0
  343. package/dist/preview/previews.js.map +1 -0
  344. package/dist/preview/prompt.d.ts +3 -0
  345. package/dist/preview/prompt.d.ts.map +1 -0
  346. package/dist/preview/prompt.js +5 -0
  347. package/dist/preview/prompt.js.map +1 -0
  348. package/dist/preview/tools.d.ts +21 -0
  349. package/dist/preview/tools.d.ts.map +1 -0
  350. package/dist/preview/tools.js +34 -0
  351. package/dist/preview/tools.js.map +1 -0
  352. package/dist/preview/types.d.ts +7 -0
  353. package/dist/preview/types.d.ts.map +1 -1
  354. package/dist/preview/types.js +2 -0
  355. package/dist/preview/types.js.map +1 -1
  356. package/dist/prompt/files.d.ts +4 -1
  357. package/dist/prompt/files.d.ts.map +1 -1
  358. package/dist/prompt/files.js +23 -8
  359. package/dist/prompt/files.js.map +1 -1
  360. package/dist/skills/tools.d.ts +26 -0
  361. package/dist/skills/tools.d.ts.map +1 -0
  362. package/dist/skills/tools.js +34 -0
  363. package/dist/skills/tools.js.map +1 -0
  364. package/dist/state/session.d.ts +4 -0
  365. package/dist/state/session.d.ts.map +1 -1
  366. package/dist/state/session.js +1 -0
  367. package/dist/state/session.js.map +1 -1
  368. package/package.json +3 -1
  369. package/schema/api.json +3016 -45
  370. package/vendor/darwin-arm64/build.json +62 -0
  371. package/vendor/darwin-arm64/ffmpeg +0 -0
  372. package/vendor/darwin-arm64/ffprobe +0 -0
  373. package/vendor/darwin-arm64/licenses/README.md +13 -0
  374. package/vendor/darwin-arm64/licenses/ffmpeg-LGPL-2.1.txt +502 -0
  375. package/vendor/darwin-arm64/licenses/whisper.cpp-MIT.txt +21 -0
  376. package/vendor/darwin-arm64/voices.bin +0 -0
  377. package/vendor/darwin-arm64/whisper-cli +0 -0
@@ -6,7 +6,7 @@ export const GUIDES = {
6
6
  interface: `# Building interface in this project
7
7
 
8
8
  ## Before you write
9
- 1. If the project has no interface yet, it has no look to follow, and the framework's defaults are not one. Don't settle on a look and describe it: read the \`variations\` guide and offer directions first. The rest of this guide is for building the one picked.
9
+ 1. If the project has no interface yet, it has no look to follow, and the framework's defaults are not one. Don't settle on a look and describe it: read the \`variations\` guide and offer directions first, drawn with the \`taste\` guide. The rest of this guide is for building the one picked.
10
10
  2. Sort the request into what is the user's and what is yours. The layout of a screen, a new visual idea, a color, a size, the tone of the copy: theirs. Consistency, spacing, states, alignment: yours, unasked.
11
11
  3. Find the closest relatives: the one or two existing screens or pieces most like what is asked. The project map in your instructions shows where pieces live, and \`find_existing\` finds one by what it does. Read them whole: the structure, what styles each part, how each state is done.
12
12
  4. List what you will build it from: existing components, tokens and classes. What isn't on that list is new. If the new thing is a look (a kind of surface, an accent, a control the project doesn't have), stop and offer options; read the \`variations\` guide for how.
@@ -33,6 +33,71 @@ Each of these, taken without being asked for, says nobody decided it: an accent
33
33
  - Hold it against its closest relative: the same row heights, corners, steps of type and gaps.
34
34
  - Say what you couldn't look at.
35
35
  - Tell the user what is new to the project in what you built, a line each: every new token, class, component or pattern.`,
36
+ research: `# Research before a new look
37
+
38
+ Do it when the project has no look of its own yet, when a kind of screen comes up that it has nothing like, and when the user asks for options: before you draw, look at how strong products do it, as a designer would. Not inside a screen that exists: there the project's own language is the reference.
39
+
40
+ ## Find the references
41
+ 1. The user's own come first: the products, screens or sites they named, and what they said about them. When they named none in a new project, ask for two or three, and research meanwhile.
42
+ 2. Find three to five more that are known for being well made, in the same domain or of the same kind of screen: their own pages, not template galleries or collections of shots. Search the web for them. If you can't search the web here, say so and ask the user for references instead of naming products from memory as if you had looked.
43
+ 3. Look at each with \`look\`, at the address of the screen most like the one asked and at the width it is used at. Where the real screen is behind a sign-in, take its public pages or the pictures of it in its own docs, and say which.
44
+
45
+ ## Write the brief
46
+ Before you draw, a short brief to the user, a line per aspect, of what the references share and where they differ:
47
+ - Type: the families, how many steps the scale has, how much weight carries.
48
+ - Density: how much is on a screen, rows or cards, how much air.
49
+ - Color: the neutrals, the accent, how much the color carries.
50
+ - Surfaces: told apart by space, lines or fills; corners; what has a shadow.
51
+ - What each does best, in a few words.
52
+
53
+ Then say what each direction takes from them: each one a position the brief makes clear, such as the density of one with the type of another. Draw them with the \`taste\` guide.
54
+
55
+ ## What a reference gives
56
+ - The visual language, not a layout, a brand or content to copy: no one else's logo, pictures, copy or exact palette.
57
+ - When the user picks, the note you save names the references that shaped the pick, so the next piece is drawn from the same ones.`,
58
+ taste: `# Taste, where the project hasn't spoken
59
+
60
+ The project's own language always comes first. This guide is for where it has none: a new project, the first piece of a kind, the pages of a round of directions. Start each new look from references (the \`research\` guide), then make the decisions below on purpose, each for a reason you could say. Where they leave a choice open, the user's references settle it.
61
+
62
+ ## Decide the job first
63
+ - Say what the screen is for and how it is used before you draw it, since that sets its density. A tool used all day is dense: small type, rows over cards, little chrome, much on one screen. A product used now and then has more air, larger targets and one task a screen. A page meant to be read or to persuade is generous: larger type, a clear order, one idea at a time.
64
+ - Find the one thing the screen is for and give it the weight; everything else is quieter.
65
+
66
+ ## Type
67
+ - One family for the interface. A second only with a job: a monospace for code and figures that line up, a serif or a display face for an editorial voice.
68
+ - A scale of few steps, each clearly apart from the next: in an application about 12, 13 or 14 for the body, 16, 20 and one display size; on a page to be read, a body of 16 to 18 and larger steps between headings. Inside an application, sizes rarely change.
69
+ - Hierarchy comes from size and color first (an ink, a muted and a faint text), then from weight, in two or three steps at most: regular, medium, semibold.
70
+ - Body text at a line height of about 1.4 to 1.6 and 45 to 75 characters a line; large headings tighter, at 1.1 to 1.25, their letters a little closer.
71
+ - Figures that change or line up in columns are tabular. Small uppercase labels are rare and a little more widely spaced.
72
+
73
+ ## Space
74
+ - One base and a few steps from it, such as 4, 8, 12, 16, 24, 32, 48 and 64. Small steps inside a control, larger between groups; the space between two groups is at least twice the space inside one.
75
+ - One content width and one grid a screen: edges line up from section to section.
76
+ - Controls share a height: 28 to 32 in a dense tool, 36 to 40 elsewhere, 44 for a finger.
77
+
78
+ ## Color
79
+ - Neutrals carry most of the screen: a background, a raised surface, an edge, and the three inks. Leaning them slightly warm or cool, after the accent, reads as decided; pure gray rarely does.
80
+ - One accent, for the primary action, the selection and links. Success, warning and danger only where there is that state.
81
+ - Body text at a contrast of at least 4.5 to 1, large text and the edges of controls at 3 to 1.
82
+ - A dark scheme is drawn, not inverted: surfaces get lighter as they rise, the accent less saturated, the text not pure white.
83
+
84
+ ## Surfaces and depth
85
+ - Separate with space first, then a hairline, then a fill. Elevation only for what floats over the rest.
86
+ - One family of corners: a small radius for controls, one step larger for what holds them, concentric when nested. Sharp, slight or round is a choice of the whole look, not of each piece.
87
+
88
+ ## Real content
89
+ - Draw with content that could be true: real names, figures of a real length, the longest likely one beside a short one, and the empty case. The content decides the layout; placeholder text hides where it breaks.
90
+ - Copy is part of the design: short, plain, in the product's voice, saying what each thing is and what each button does.
91
+
92
+ ## Every state
93
+ - Empty, with what to do from there; loading; failed, with what can be done; one item and many; very long content; disabled. A control has its hover, focus and pressed states, and a focus that shows.
94
+
95
+ ## Motion
96
+ - Short, between 150 and 250 milliseconds, easing out, for what appears, moves or changes size. Nothing moves for its own sake, and nothing at all for someone who asked for reduced motion.
97
+
98
+ ## Restraint
99
+ - Each element, size, color and line earns its place; when in doubt, take one away. A look made of few decisions applied everywhere reads as designed; many small ones read as assembled.
100
+ - None of what the \`interface\` guide lists as giving a generated look away, unless the user asks for it.`,
36
101
  variations: `# Offering variations
37
102
 
38
103
  Offer them when you are about to decide something the project hasn't: the first screen of a new project, the first piece of a kind, a look nothing existing carries. Offer them too whenever the user asks. Don't offer them for what the project or your notes already settle: apply that.
@@ -43,15 +108,23 @@ Offer them when you are about to decide something the project hasn't: the first
43
108
  - Each is built from the project's language where there is one: the same components and tokens, put together another way. An option that needs something new says so.
44
109
  - When the look as it is now is one of the options, it comes first and is marked as the current one.
45
110
  - In a new project, before you draw anything, ask what the user finds well made, two or three products or screens, and what about them. A reference gives the visual language, not a layout to copy.
111
+ - For a look the project doesn't have yet, research first and draw from the brief: read the \`research\` guide.
46
112
 
47
113
  ## How to show them, by the size of the decision
48
114
  - A piece inside a screen, such as a card, a row or a menu: describe the options in words, from the patterns already on that screen, and ask the user to pick. Build the one picked.
49
- - A screen, or a piece many screens will repeat: build the options for real, side by side, with the real screen and data that could be true, never placeholders. Use the project's playground or Storybook when it has one. When it has none, say in a line that you will keep the options on a playground page, where it goes and that it isn't shipped, and that they can say no. If they say no, save that with \`remember\` and don't offer one in this project again: describe options in words instead.
50
- - A whole new project: one real screen per direction, the screen the product is used on the most, not a landing page.
51
- - Never leave the options built into the real screen.
115
+ - A screen, a piece many screens will repeat, or a look the project doesn't have: these are directions. Build each as a real page and show them with \`show_directions\`, never described in words alone. Jinion's viewer shows them side by side, outside the project, and the user picks there.
116
+ - A whole new project: one page per direction, of the screen the product is used on the most, not a landing page.
117
+
118
+ ## How a direction's page is made
119
+ - One whole HTML document: its CSS and any script inline, pictures as data URLs or from the web. Nothing from the project's files or its dev server, which the viewer can't reach.
120
+ - In the project's language where it has one: the values of its tokens, its type, its spacing steps, its corners. In a project built with components, such as React, the page is drawn in its tokens, not with its components: enough to pick from, and the same in every stack.
121
+ - Real content, as the \`taste\` guide says: names and figures that could be true, the long case and the empty one. Never placeholder text.
122
+ - Only what tells the directions apart needs care; the rest is the same in each, so the difference shows.
123
+ - Look at each page with \`look\`, at the address \`show_directions\` gives it, before you tell the user they are there. If one needs fixing, show the round again.
52
124
 
53
125
  ## After the pick
54
- - Only the one picked goes into the product. Take the others out of the code; in the playground keep at most the one picked, as the reference.
126
+ - The pick comes as the user's next message. Until it does, nothing goes into the project.
127
+ - Build the one picked in the project, with its components and tokens, as the \`interface\` guide says. The page was for picking, not code to copy.
55
128
  - Save the decision with \`remember\`, in the project's scope and as a decision: what was decided, in terms the next piece can be built from (sizes, tokens, what goes where), and each option turned down in a few words with the reason the user gave. What was turned down is as useful as the pick: it is what not to offer again.
56
129
  - When the pick replaces an earlier decision, update that note rather than adding one beside it.
57
130
  - From then on apply it without asking. When a later request seems to go against it, say so and ask which holds.`,
@@ -1 +1 @@
1
- {"version":3,"file":"guides.js","sourceRoot":"","sources":["../../src/design/guides.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,CAAC,MAAM,MAAM,GAAG;IACpB,SAAS,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;yHA6B4G;IAEvH,UAAU,EAAE;;;;;;;;;;;;;;;;;;;;;iHAqBmG;CACvG,CAAC;AAIX,MAAM,CAAC,MAAM,YAAY,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,CAAkC,CAAC"}
1
+ {"version":3,"file":"guides.js","sourceRoot":"","sources":["../../src/design/guides.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,CAAC,MAAM,MAAM,GAAG;IACpB,SAAS,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;yHA6B4G;IAEvH,QAAQ,EAAE;;;;;;;;;;;;;;;;;;;;;mIAqBuH;IAEjI,KAAK,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2GA0CkG;IAEzG,UAAU,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iHA6BmG;CACvG,CAAC;AAIX,MAAM,CAAC,MAAM,YAAY,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,CAAkC,CAAC"}
@@ -3,5 +3,5 @@
3
3
  * is what, and the project's language before the agent's habits. The craft in depth is in the guides, read when there
4
4
  * is interface to build, so a turn that fixes a query doesn't carry it.
5
5
  */
6
- export declare const DESIGN = "# Interface work\nOn an interface you work as a design engineer. How it looks is the user's to decide; the craft is yours, done without being asked.\n- The project's own language comes first, before your habits and before any general rule: its components, its design tokens, its steps of spacing and type, its classes, as the project map shows them. Where the project uses a library's card, a card is that card. Before you write a piece, open the one or two existing pieces most like it and build yours the same way: the same structure, sizes, surfaces and states.\n- A new piece gets no new idiom: no chip, tile, stepper, meter or icon style the screen doesn't already have, because a piece with a look of its own reads as made by someone else. When what exists can't carry it, that is a design decision, and the user's.\n- Before you build a screen, or a piece big enough to be wrong, say in two or three sentences what you understood: what goes where, what comes first, which existing pieces it is built from. For a new screen or a new visual direction, wait for the user's yes; inside a screen that exists, say it and go on.\n- Where the project hasn't spoken, as in a new project or for the first piece of its kind, don't pick a look and build it. Offer two or three directions that differ in a principle, such as density, how surfaces are told apart or what the type is like, each with a name and a sentence on what it stands for, and let the user pick. Offer them too whenever the user asks for options.\n- A pick is a decision: save it with `remember`, with what was turned down and why. A decision in your notes is applied to the next piece, not offered again; when the code and a note disagree, ask which holds rather than following either.\n- What the user points at as a reference gives the visual language, not a layout to copy, unless they say so. Feedback changes exactly what it names: everything else stays as it was, the neighbours you would have tidied included.\n- A build doesn't check an interface. Look at what you made with `look`, which shows you a picture of a page or of the simulator's screen, and say plainly when you couldn't.\n- The craft itself is in Jinion's guides. Read `design_guide` for `interface` before you design or build more than a line of interface, and for `variations` before you offer options; once in a conversation is enough.";
6
+ export declare const DESIGN = "# Interface work\nOn an interface you work as a design engineer. How it looks is the user's to decide; the craft is yours, done without being asked.\n- The project's own language comes first, before your habits and before any general rule: its components, its design tokens, its steps of spacing and type, its classes, as the project map shows them. Where the project uses a library's card, a card is that card. Before you write a piece, open the one or two existing pieces most like it and build yours the same way: the same structure, sizes, surfaces and states.\n- A new piece gets no new idiom: no chip, tile, stepper, meter or icon style the screen doesn't already have, because a piece with a look of its own reads as made by someone else. When what exists can't carry it, that is a design decision, and the user's.\n- Before you build a screen, or a piece big enough to be wrong, say in two or three sentences what you understood: what goes where, what comes first, which existing pieces it is built from. For a new screen or a new visual direction, wait for the user's yes; inside a screen that exists, say it and go on.\n- Where the project hasn't spoken, as in a new project or for the first piece of its kind, don't pick a look and build it. Look first at how strong products do it, then offer two or three directions that differ in a principle, such as density, how surfaces are told apart or what the type is like, each with a name and a sentence on what it stands for. Build each as a real page and show them with `show_directions`, never described in words alone, and let the user pick there. Offer them too whenever the user asks for options.\n- A pick is a decision: save it with `remember`, with what was turned down and why. A decision in your notes is applied to the next piece, not offered again; when the code and a note disagree, ask which holds rather than following either.\n- What the user points at as a reference gives the visual language, not a layout to copy, unless they say so. Feedback changes exactly what it names: everything else stays as it was, the neighbours you would have tidied included.\n- A build doesn't check an interface. Look at what you made with `look`, which shows you a picture of a page or of the simulator's screen, and say plainly when you couldn't.\n- The craft itself is in Jinion's guides. Read `design_guide` for `interface` before you design or build more than a line of interface, for `variations` before you offer options, and for `research` and `taste` before you draw a look the project doesn't have yet; once in a conversation is enough.";
7
7
  //# sourceMappingURL=prompt.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"prompt.d.ts","sourceRoot":"","sources":["../../src/design/prompt.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,eAAO,MAAM,MAAM,20EAS4M,CAAC"}
1
+ {"version":3,"file":"prompt.d.ts","sourceRoot":"","sources":["../../src/design/prompt.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,eAAO,MAAM,MAAM,+iFASgS,CAAC"}
@@ -8,9 +8,9 @@ On an interface you work as a design engineer. How it looks is the user's to dec
8
8
  - The project's own language comes first, before your habits and before any general rule: its components, its design tokens, its steps of spacing and type, its classes, as the project map shows them. Where the project uses a library's card, a card is that card. Before you write a piece, open the one or two existing pieces most like it and build yours the same way: the same structure, sizes, surfaces and states.
9
9
  - A new piece gets no new idiom: no chip, tile, stepper, meter or icon style the screen doesn't already have, because a piece with a look of its own reads as made by someone else. When what exists can't carry it, that is a design decision, and the user's.
10
10
  - Before you build a screen, or a piece big enough to be wrong, say in two or three sentences what you understood: what goes where, what comes first, which existing pieces it is built from. For a new screen or a new visual direction, wait for the user's yes; inside a screen that exists, say it and go on.
11
- - Where the project hasn't spoken, as in a new project or for the first piece of its kind, don't pick a look and build it. Offer two or three directions that differ in a principle, such as density, how surfaces are told apart or what the type is like, each with a name and a sentence on what it stands for, and let the user pick. Offer them too whenever the user asks for options.
11
+ - Where the project hasn't spoken, as in a new project or for the first piece of its kind, don't pick a look and build it. Look first at how strong products do it, then offer two or three directions that differ in a principle, such as density, how surfaces are told apart or what the type is like, each with a name and a sentence on what it stands for. Build each as a real page and show them with \`show_directions\`, never described in words alone, and let the user pick there. Offer them too whenever the user asks for options.
12
12
  - A pick is a decision: save it with \`remember\`, with what was turned down and why. A decision in your notes is applied to the next piece, not offered again; when the code and a note disagree, ask which holds rather than following either.
13
13
  - What the user points at as a reference gives the visual language, not a layout to copy, unless they say so. Feedback changes exactly what it names: everything else stays as it was, the neighbours you would have tidied included.
14
14
  - A build doesn't check an interface. Look at what you made with \`look\`, which shows you a picture of a page or of the simulator's screen, and say plainly when you couldn't.
15
- - The craft itself is in Jinion's guides. Read \`design_guide\` for \`interface\` before you design or build more than a line of interface, and for \`variations\` before you offer options; once in a conversation is enough.`;
15
+ - The craft itself is in Jinion's guides. Read \`design_guide\` for \`interface\` before you design or build more than a line of interface, for \`variations\` before you offer options, and for \`research\` and \`taste\` before you draw a look the project doesn't have yet; once in a conversation is enough.`;
16
16
  //# sourceMappingURL=prompt.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"prompt.js","sourceRoot":"","sources":["../../src/design/prompt.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,CAAC,MAAM,MAAM,GAAG;;;;;;;;;+NASyM,CAAC"}
1
+ {"version":3,"file":"prompt.js","sourceRoot":"","sources":["../../src/design/prompt.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,CAAC,MAAM,MAAM,GAAG;;;;;;;;;mTAS6R,CAAC"}
@@ -10,6 +10,8 @@ export declare function designTools(): {
10
10
  design_guide: DesignTool<{
11
11
  topic: z.ZodEnum<{
12
12
  interface: "interface";
13
+ research: "research";
14
+ taste: "taste";
13
15
  variations: "variations";
14
16
  }>;
15
17
  }>;
@@ -1 +1 @@
1
- {"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../../src/design/tools.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAGlD,8FAA8F;AAC9F,MAAM,WAAW,UAAU,CAAC,CAAC,SAAS,CAAC,CAAC,WAAW,GAAG,CAAC,CAAC,WAAW;IACjE,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,CAAC,CAAC;IACT,GAAG,CAAC,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;CACtD;AAID,wBAAgB,WAAW;IAEvB,YAAY;;;;;;EAOf;AAED,MAAM,MAAM,WAAW,GAAG,UAAU,CAAC,OAAO,WAAW,CAAC,CAAC;AAEzD,MAAM,MAAM,YAAY,GAAG,MAAM,WAAW,CAAC;AAE7C,eAAO,MAAM,cAAc,aAA6D,CAAC;AAEzF,+FAA+F;AAC/F,wBAAgB,UAAU,CAAC,KAAK,EAAE,OAAO,GAAG,QAAQ,CAInD"}
1
+ {"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../../src/design/tools.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAGlD,8FAA8F;AAC9F,MAAM,WAAW,UAAU,CAAC,CAAC,SAAS,CAAC,CAAC,WAAW,GAAG,CAAC,CAAC,WAAW;IACjE,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,CAAC,CAAC;IACT,GAAG,CAAC,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;CACtD;AAID,wBAAgB,WAAW;IAEvB,YAAY;;;;;;;;EAaf;AAED,MAAM,MAAM,WAAW,GAAG,UAAU,CAAC,OAAO,WAAW,CAAC,CAAC;AAEzD,MAAM,MAAM,YAAY,GAAG,MAAM,WAAW,CAAC;AAE7C,eAAO,MAAM,cAAc,aAA6D,CAAC;AAEzF,+FAA+F;AAC/F,wBAAgB,UAAU,CAAC,KAAK,EAAE,OAAO,GAAG,QAAQ,CAInD"}
@@ -4,8 +4,12 @@ const define = (tool) => tool;
4
4
  export function designTools() {
5
5
  return {
6
6
  design_guide: define({
7
- description: "Reads Jinion's guide to a kind of interface work: `interface` before designing or building any interface, `variations` before offering the user options to pick from. Read it once in a conversation, before the work it is about.",
8
- input: { topic: z.enum(GUIDE_TOPICS).describe('`interface`: how interface is built here. `variations`: how options are offered, shown and recorded.') },
7
+ description: "Reads Jinion's guide to a kind of interface work: `interface` before designing or building any interface, `variations` before offering the user options to pick from, `research` and `taste` before drawing a look the project doesn't have yet. Read it once in a conversation, before the work it is about.",
8
+ input: {
9
+ topic: z
10
+ .enum(GUIDE_TOPICS)
11
+ .describe("`interface`: how interface is built here. `variations`: how options are offered, shown and recorded. `research`: how good products are looked at before a new look. `taste`: what well made means where the project has no language of its own."),
12
+ },
9
13
  run: async ({ topic }) => GUIDES[topic],
10
14
  }),
11
15
  };
@@ -1 +1 @@
1
- {"version":3,"file":"tools.js","sourceRoot":"","sources":["../../src/design/tools.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AASnD,MAAM,MAAM,GAAG,CAA0B,IAAmB,EAAE,EAAE,CAAC,IAAI,CAAC;AAEtE,MAAM,UAAU,WAAW;IACzB,OAAO;QACL,YAAY,EAAE,MAAM,CAAC;YACnB,WAAW,EACT,oOAAoO;YACtO,KAAK,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,QAAQ,CAAC,sGAAsG,CAAC,EAAE;YACvJ,GAAG,EAAE,KAAK,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC;SACxC,CAAC;KACH,CAAC;AACJ,CAAC;AAMD,MAAM,CAAC,MAAM,cAAc,GAAG,IAAI,GAAG,CAAS,CAAC,cAAc,CAA0B,CAAC,CAAC;AAEzF,+FAA+F;AAC/F,MAAM,UAAU,UAAU,CAAC,KAAc;IACvC,MAAM,EAAE,KAAK,EAAE,GAAG,CAAC,KAAK,IAAI,EAAE,CAAwB,CAAC;IAEvD,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,KAAK,EAAE,uBAAuB,EAAE,MAAM,EAAE,MAAM,CAAC,KAAK,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC;AACnG,CAAC"}
1
+ {"version":3,"file":"tools.js","sourceRoot":"","sources":["../../src/design/tools.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AASnD,MAAM,MAAM,GAAG,CAA0B,IAAmB,EAAE,EAAE,CAAC,IAAI,CAAC;AAEtE,MAAM,UAAU,WAAW;IACzB,OAAO;QACL,YAAY,EAAE,MAAM,CAAC;YACnB,WAAW,EACT,+SAA+S;YACjT,KAAK,EAAE;gBACL,KAAK,EAAE,CAAC;qBACL,IAAI,CAAC,YAAY,CAAC;qBAClB,QAAQ,CACP,iPAAiP,CAClP;aACJ;YACD,GAAG,EAAE,KAAK,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC;SACxC,CAAC;KACH,CAAC;AACJ,CAAC;AAMD,MAAM,CAAC,MAAM,cAAc,GAAG,IAAI,GAAG,CAAS,CAAC,cAAc,CAA0B,CAAC,CAAC;AAEzF,+FAA+F;AAC/F,MAAM,UAAU,UAAU,CAAC,KAAc;IACvC,MAAM,EAAE,KAAK,EAAE,GAAG,CAAC,KAAK,IAAI,EAAE,CAAwB,CAAC;IAEvD,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,KAAK,EAAE,uBAAuB,EAAE,MAAM,EAAE,MAAM,CAAC,KAAK,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC;AACnG,CAAC"}
@@ -0,0 +1,42 @@
1
+ import { DirectionsStore, type Offered, type Round } from './store.js';
2
+ export interface Picked {
3
+ round: Round;
4
+ direction: string;
5
+ }
6
+ /** What a viewer is told after a pick: the round as it is now, and whether a conversation took the pick. */
7
+ export interface PickAnswer {
8
+ round: Round;
9
+ sent: boolean;
10
+ }
11
+ /** The viewer as a Preview beside the thread shows it, which has no room for the rounds. */
12
+ export declare const SIDEBAR_CLOSED = "#sidebar-closed";
13
+ /**
14
+ * Jinion's own place to show directions, the same for every project and client: the rounds kept under the project's
15
+ * folder in `~/.jinion`, served to a viewer on 127.0.0.1 behind a token. Nothing listens before a round is shown.
16
+ */
17
+ export declare class Directions {
18
+ private readonly cwd;
19
+ readonly store: DirectionsStore;
20
+ private readonly token;
21
+ /** The conversation each round was shown in, while it is open; a pick on any other is only kept. */
22
+ private readonly listeners;
23
+ private server?;
24
+ private port?;
25
+ constructor(cwd: string);
26
+ show(offered: Offered, onPick: (picked: Picked) => void): Promise<{
27
+ round: Round;
28
+ address: string;
29
+ /** Each direction's page alone, for the agent to look at. */
30
+ pages: string[];
31
+ /** Each direction in the viewer without its sidebar, as a Preview shows the round. */
32
+ shown: string[];
33
+ }>;
34
+ /** The viewer, at the newest round. */
35
+ address(): Promise<string>;
36
+ pick(id: string, direction: string): PickAnswer | undefined;
37
+ close(): void;
38
+ private listen;
39
+ private receive;
40
+ private receivePick;
41
+ }
42
+ //# sourceMappingURL=directions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"directions.d.ts","sourceRoot":"","sources":["../../src/directions/directions.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,eAAe,EAAE,KAAK,OAAO,EAAE,KAAK,KAAK,EAAE,MAAM,YAAY,CAAC;AAGvE,MAAM,WAAW,MAAM;IACrB,KAAK,EAAE,KAAK,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,4GAA4G;AAC5G,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,KAAK,CAAC;IACb,IAAI,EAAE,OAAO,CAAC;CACf;AAID,4FAA4F;AAC5F,eAAO,MAAM,cAAc,oBAAoB,CAAC;AAEhD;;;GAGG;AACH,qBAAa,UAAU;IAQT,OAAO,CAAC,QAAQ,CAAC,GAAG;IAPhC,QAAQ,CAAC,KAAK,EAAE,eAAe,CAAC;IAChC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAmC;IACzD,oGAAoG;IACpG,OAAO,CAAC,QAAQ,CAAC,SAAS,CAA+C;IACzE,OAAO,CAAC,MAAM,CAAC,CAAS;IACxB,OAAO,CAAC,IAAI,CAAC,CAAkB;IAE/B,YAA6B,GAAG,EAAE,MAAM,EAEvC;IAEK,IAAI,CAAC,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI;;;QAUzD,6DAA6D;;QAE7D,sFAAsF;;OAGzF;IAED,uCAAuC;IACjC,OAAO,oBAIZ;IAED,IAAI,CAAC,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,UAAU,GAAG,SAAS,CAS1D;IAED,KAAK,SAIJ;IAED,OAAO,CAAC,MAAM;IAad,OAAO,CAAC,OAAO;IA8Bf,OAAO,CAAC,WAAW;CAkBpB"}
@@ -0,0 +1,120 @@
1
+ import { randomBytes } from 'node:crypto';
2
+ import { createServer } from 'node:http';
3
+ import { basename } from 'node:path';
4
+ import { DirectionsStore } from './store.js';
5
+ import { viewerPage } from './viewer.js';
6
+ const MAX_PICK_BYTES = 4 * 1024;
7
+ /** The viewer as a Preview beside the thread shows it, which has no room for the rounds. */
8
+ export const SIDEBAR_CLOSED = '#sidebar-closed';
9
+ /**
10
+ * Jinion's own place to show directions, the same for every project and client: the rounds kept under the project's
11
+ * folder in `~/.jinion`, served to a viewer on 127.0.0.1 behind a token. Nothing listens before a round is shown.
12
+ */
13
+ export class Directions {
14
+ cwd;
15
+ store;
16
+ token = randomBytes(16).toString('hex');
17
+ /** The conversation each round was shown in, while it is open; a pick on any other is only kept. */
18
+ listeners = new Map();
19
+ server;
20
+ port;
21
+ constructor(cwd) {
22
+ this.cwd = cwd;
23
+ this.store = new DirectionsStore(cwd);
24
+ }
25
+ async show(offered, onPick) {
26
+ const round = this.store.add(offered);
27
+ this.listeners.set(round.id, onPick);
28
+ const viewer = await this.address();
29
+ return {
30
+ round,
31
+ address: `${viewer}?round=${round.id}`,
32
+ /** Each direction's page alone, for the agent to look at. */
33
+ pages: round.directions.map((_, index) => `${viewer}rounds/${round.id}/${index + 1}`),
34
+ /** Each direction in the viewer without its sidebar, as a Preview shows the round. */
35
+ shown: round.directions.map((_, index) => `${viewer}?round=${round.id}&direction=${index + 1}${SIDEBAR_CLOSED}`),
36
+ };
37
+ }
38
+ /** The viewer, at the newest round. */
39
+ async address() {
40
+ this.port ??= this.listen();
41
+ return `http://127.0.0.1:${await this.port}/${this.token}/`;
42
+ }
43
+ pick(id, direction) {
44
+ const round = this.store.pick(id, direction);
45
+ if (!round)
46
+ return undefined;
47
+ const listener = this.listeners.get(id);
48
+ listener?.({ round, direction });
49
+ return { round, sent: listener !== undefined };
50
+ }
51
+ close() {
52
+ this.server?.close();
53
+ this.server = undefined;
54
+ this.port = undefined;
55
+ }
56
+ listen() {
57
+ const server = createServer((request, response) => this.receive(request, response));
58
+ this.server = server;
59
+ // The app quits whether or not a browser still holds a connection open.
60
+ server.unref();
61
+ return new Promise((resolve, reject) => {
62
+ server.once('error', reject);
63
+ server.listen(0, '127.0.0.1', () => resolve(server.address().port));
64
+ });
65
+ }
66
+ receive(request, response) {
67
+ const { pathname } = new URL(request.url ?? '/', 'http://127.0.0.1');
68
+ const [token, ...rest] = pathname.split('/').slice(1);
69
+ const path = rest.join('/');
70
+ response.setHeader('Cache-Control', 'no-store');
71
+ if (token !== this.token)
72
+ return void response.writeHead(404).end();
73
+ if (request.method === 'GET' && path === '')
74
+ return send(response, 'text/html', viewerPage(basename(this.cwd)));
75
+ if (request.method === 'GET' && path === 'rounds')
76
+ return send(response, 'application/json', JSON.stringify(this.store.list()));
77
+ const page = /^rounds\/([^/]+)\/(\d+)$/.exec(path);
78
+ if (request.method === 'GET' && page) {
79
+ const html = this.store.page(page[1], Number(page[2]) - 1);
80
+ if (html === undefined)
81
+ return void response.writeHead(404).end();
82
+ // A page of its own origin, so what the agent wrote can't reach the viewer, its token or the picks.
83
+ response.setHeader('Content-Security-Policy', 'sandbox allow-scripts allow-forms allow-popups');
84
+ return send(response, 'text/html', html);
85
+ }
86
+ const pick = /^rounds\/([^/]+)\/pick$/.exec(path);
87
+ if (request.method === 'POST' && pick)
88
+ return this.receivePick(request, response, pick[1]);
89
+ response.writeHead(404).end();
90
+ }
91
+ receivePick(request, response, id) {
92
+ const chunks = [];
93
+ let size = 0;
94
+ request.on('data', (chunk) => {
95
+ size += chunk.length;
96
+ if (size <= MAX_PICK_BYTES)
97
+ chunks.push(chunk);
98
+ });
99
+ request.on('end', () => {
100
+ const direction = size <= MAX_PICK_BYTES ? directionOf(Buffer.concat(chunks).toString('utf8')) : undefined;
101
+ const answer = direction === undefined ? undefined : this.pick(id, direction);
102
+ if (!answer)
103
+ return void response.writeHead(400).end();
104
+ send(response, 'application/json', JSON.stringify(answer));
105
+ });
106
+ }
107
+ }
108
+ function send(response, type, body) {
109
+ response.writeHead(200, { 'Content-Type': `${type}; charset=utf-8` }).end(body);
110
+ }
111
+ function directionOf(body) {
112
+ try {
113
+ const { direction } = JSON.parse(body);
114
+ return typeof direction === 'string' ? direction : undefined;
115
+ }
116
+ catch {
117
+ return undefined;
118
+ }
119
+ }
120
+ //# sourceMappingURL=directions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"directions.js","sourceRoot":"","sources":["../../src/directions/directions.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,34 @@
1
+ export interface Direction {
2
+ name: string;
3
+ idea: string;
4
+ }
5
+ /** A round as the agent hands it over: each direction with its page. */
6
+ export interface Offered {
7
+ title: string;
8
+ directions: (Direction & {
9
+ html: string;
10
+ })[];
11
+ }
12
+ export interface Round {
13
+ id: string;
14
+ title: string;
15
+ /** When it was shown, in milliseconds. */
16
+ at: number;
17
+ directions: Direction[];
18
+ picked?: string;
19
+ }
20
+ /** The project's rounds of directions, a folder each, out of the project and of git. */
21
+ export declare class DirectionsStore {
22
+ private readonly cwd;
23
+ constructor(cwd: string);
24
+ get dir(): string;
25
+ add({ title, directions }: Offered): Round;
26
+ /** The newest first. */
27
+ list(): Round[];
28
+ get(id: string): Round | undefined;
29
+ /** The page of a round's direction, by its place in the round. */
30
+ page(id: string, index: number): string | undefined;
31
+ pick(id: string, name: string): Round | undefined;
32
+ private save;
33
+ }
34
+ //# sourceMappingURL=store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../src/directions/store.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd;AAED,wEAAwE;AACxE,MAAM,WAAW,OAAO;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,CAAC,SAAS,GAAG;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,EAAE,CAAC;CAC9C;AAED,MAAM,WAAW,KAAK;IACpB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,0CAA0C;IAC1C,EAAE,EAAE,MAAM,CAAC;IACX,UAAU,EAAE,SAAS,EAAE,CAAC;IACxB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,wFAAwF;AACxF,qBAAa,eAAe;IACd,OAAO,CAAC,QAAQ,CAAC,GAAG;IAAhC,YAA6B,GAAG,EAAE,MAAM,EAAI;IAE5C,IAAI,GAAG,WAEN;IAED,GAAG,CAAC,EAAE,KAAK,EAAE,UAAU,EAAE,EAAE,OAAO,GAAG,KAAK,CASzC;IAED,wBAAwB;IACxB,IAAI,IAAI,KAAK,EAAE,CAMd;IAED,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,KAAK,GAAG,SAAS,CAMjC;IAED,kEAAkE;IAClE,IAAI,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,sBAK7B;IAED,IAAI,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,KAAK,GAAG,SAAS,CAShD;IAED,OAAO,CAAC,IAAI;CAGb"}
@@ -0,0 +1,61 @@
1
+ import { randomUUID } from 'node:crypto';
2
+ import { existsSync, mkdirSync, readdirSync, readFileSync, writeFileSync } from 'node:fs';
3
+ import { join } from 'node:path';
4
+ import { projectDir } from '../lib/paths.js';
5
+ /** The project's rounds of directions, a folder each, out of the project and of git. */
6
+ export class DirectionsStore {
7
+ cwd;
8
+ constructor(cwd) {
9
+ this.cwd = cwd;
10
+ }
11
+ get dir() {
12
+ return join(projectDir(this.cwd), 'directions');
13
+ }
14
+ add({ title, directions }) {
15
+ const round = { id: randomUUID().slice(0, 8), title, at: Date.now(), directions: directions.map(({ name, idea }) => ({ name, idea })) };
16
+ const folder = join(this.dir, round.id);
17
+ mkdirSync(folder, { recursive: true });
18
+ for (const [index, { html }] of directions.entries())
19
+ writeFileSync(join(folder, pageName(index)), html);
20
+ this.save(round);
21
+ return round;
22
+ }
23
+ /** The newest first. */
24
+ list() {
25
+ if (!existsSync(this.dir))
26
+ return [];
27
+ return readdirSync(this.dir)
28
+ .flatMap((id) => this.get(id) ?? [])
29
+ .sort((a, b) => b.at - a.at);
30
+ }
31
+ get(id) {
32
+ if (!ROUND_ID.test(id))
33
+ return undefined;
34
+ const file = join(this.dir, id, 'round.json');
35
+ return existsSync(file) ? JSON.parse(readFileSync(file, 'utf8')) : undefined;
36
+ }
37
+ /** The page of a round's direction, by its place in the round. */
38
+ page(id, index) {
39
+ const round = this.get(id);
40
+ if (!round || !Number.isInteger(index) || index < 0 || index >= round.directions.length)
41
+ return undefined;
42
+ return readFileSync(join(this.dir, id, pageName(index)), 'utf8');
43
+ }
44
+ pick(id, name) {
45
+ const round = this.get(id);
46
+ if (!round?.directions.some((direction) => direction.name === name))
47
+ return undefined;
48
+ const picked = { ...round, picked: name };
49
+ this.save(picked);
50
+ return picked;
51
+ }
52
+ save(round) {
53
+ writeFileSync(join(this.dir, round.id, 'round.json'), `${JSON.stringify(round, null, 2)}\n`);
54
+ }
55
+ }
56
+ // Ids come back in addresses, so only one of ours ever names a folder.
57
+ const ROUND_ID = /^[0-9a-f]{8}$/;
58
+ function pageName(index) {
59
+ return `${index + 1}.html`;
60
+ }
61
+ //# sourceMappingURL=store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store.js","sourceRoot":"","sources":["../../src/directions/store.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,WAAW,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC1F,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAsB7C,wFAAwF;AACxF,MAAM,OAAO,eAAe;IACG,GAAG;IAAhC,YAA6B,GAAW;mBAAX,GAAG;IAAW,CAAC;IAE5C,IAAI,GAAG;QACL,OAAO,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,YAAY,CAAC,CAAC;IAClD,CAAC;IAED,GAAG,CAAC,EAAE,KAAK,EAAE,UAAU,EAAW;QAChC,MAAM,KAAK,GAAU,EAAE,EAAE,EAAE,UAAU,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,UAAU,EAAE,UAAU,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC;QAC/I,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,CAAC,CAAC;QAExC,SAAS,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACvC,KAAK,MAAM,CAAC,KAAK,EAAE,EAAE,IAAI,EAAE,CAAC,IAAI,UAAU,CAAC,OAAO,EAAE;YAAE,aAAa,CAAC,IAAI,CAAC,MAAM,EAAE,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;QACzG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAEjB,OAAO,KAAK,CAAC;IACf,CAAC;IAED,wBAAwB;IACxB,IAAI;QACF,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC;YAAE,OAAO,EAAE,CAAC;QAErC,OAAO,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC;aACzB,OAAO,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC;aACnC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC;IACjC,CAAC;IAED,GAAG,CAAC,EAAU;QACZ,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;YAAE,OAAO,SAAS,CAAC;QAEzC,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,EAAE,EAAE,YAAY,CAAC,CAAC;QAE9C,OAAO,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAE,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAW,CAAC,CAAC,CAAC,SAAS,CAAC;IAC1F,CAAC;IAED,kEAAkE;IAClE,IAAI,CAAC,EAAU,EAAE,KAAa;QAC5B,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAC3B,IAAI,CAAC,KAAK,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,CAAC,IAAI,KAAK,IAAI,KAAK,CAAC,UAAU,CAAC,MAAM;YAAE,OAAO,SAAS,CAAC;QAE1G,OAAO,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,EAAE,EAAE,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;IACnE,CAAC;IAED,IAAI,CAAC,EAAU,EAAE,IAAY;QAC3B,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAC3B,IAAI,CAAC,KAAK,EAAE,UAAU,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,IAAI,KAAK,IAAI,CAAC;YAAE,OAAO,SAAS,CAAC;QAEtF,MAAM,MAAM,GAAG,EAAE,GAAG,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;QAE1C,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAElB,OAAO,MAAM,CAAC;IAChB,CAAC;IAEO,IAAI,CAAC,KAAY;QACvB,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,EAAE,YAAY,CAAC,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;IAC/F,CAAC;CACF;AAED,uEAAuE;AACvE,MAAM,QAAQ,GAAG,eAAe,CAAC;AAEjC,SAAS,QAAQ,CAAC,KAAa;IAC7B,OAAO,GAAG,KAAK,GAAG,CAAC,OAAO,CAAC;AAC7B,CAAC"}
@@ -0,0 +1,29 @@
1
+ import { z } from 'zod';
2
+ import type { ToolCall } from '../agent/tools.js';
3
+ import type { Previews } from '../preview/previews.js';
4
+ import { type Directions, type Picked } from './directions.js';
5
+ /** A tool the agent shows directions with; each backend offers it its own way. */
6
+ export interface DirectionsTool<S extends z.ZodRawShape = z.ZodRawShape> {
7
+ description: string;
8
+ input: S;
9
+ run(input: z.infer<z.ZodObject<S>>): Promise<string>;
10
+ }
11
+ /** `onPick` is told of a pick on a round this conversation showed; `previews` opens the round beside the thread where the app has a Preview. */
12
+ export declare function directionsTools(directions: Directions, onPick: (picked: Picked) => void, previews?: Previews): {
13
+ show_directions: DirectionsTool<{
14
+ title: z.ZodString;
15
+ directions: z.ZodArray<z.ZodObject<{
16
+ name: z.ZodString;
17
+ idea: z.ZodString;
18
+ html: z.ZodString;
19
+ }, z.core.$strip>>;
20
+ }>;
21
+ };
22
+ export type DirectionsTools = ReturnType<typeof directionsTools>;
23
+ export type DirectionsAction = keyof DirectionsTools;
24
+ export declare const DIRECTIONS_ACTIONS: Set<string>;
25
+ /** A call of the tool as the conversation shows it, worded alike whichever backend made it. */
26
+ export declare function directionsCall(input: unknown): ToolCall;
27
+ /** What the user's pick says to the agent, as their own message. */
28
+ export declare function pickMessage({ round, direction }: Picked): string;
29
+ //# sourceMappingURL=tools.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../../src/directions/tools.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAElD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AACvD,OAAO,EAAE,KAAK,UAAU,EAAE,KAAK,MAAM,EAAkB,MAAM,iBAAiB,CAAC;AAE/E,kFAAkF;AAClF,MAAM,WAAW,cAAc,CAAC,CAAC,SAAS,CAAC,CAAC,WAAW,GAAG,CAAC,CAAC,WAAW;IACrE,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,CAAC,CAAC;IACT,GAAG,CAAC,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;CACtD;AAMD,gJAAgJ;AAChJ,wBAAgB,eAAe,CAAC,UAAU,EAAE,UAAU,EAAE,MAAM,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,EAAE,QAAQ,CAAC,EAAE,QAAQ;IAEzG,eAAe;;;;;;;;EA4ClB;AAED,MAAM,MAAM,eAAe,GAAG,UAAU,CAAC,OAAO,eAAe,CAAC,CAAC;AAEjE,MAAM,MAAM,gBAAgB,GAAG,MAAM,eAAe,CAAC;AAErD,eAAO,MAAM,kBAAkB,aAAoE,CAAC;AAEpG,+FAA+F;AAC/F,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG,QAAQ,CAIvD;AAED,oEAAoE;AACpE,wBAAgB,WAAW,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,EAAE,MAAM,UAEvD"}
@@ -0,0 +1,57 @@
1
+ import { z } from 'zod';
2
+ import { errorMessage } from '../lib/errors.js';
3
+ import { SIDEBAR_CLOSED } from './directions.js';
4
+ const MAX_PAGE_BYTES = 2 * 1024 * 1024;
5
+ const define = (tool) => tool;
6
+ /** `onPick` is told of a pick on a round this conversation showed; `previews` opens the round beside the thread where the app has a Preview. */
7
+ export function directionsTools(directions, onPick, previews) {
8
+ return {
9
+ show_directions: define({
10
+ description: "Shows the user a round of directions to pick from, in Jinion's own viewer outside the project: each direction's name, its idea in a sentence and its page. Use it whenever you offer directions, rather than describing them in words or writing their pages into the project. Nothing is written in the project and nothing is asked. The user's pick comes back as their next message.",
11
+ input: {
12
+ title: z.string().describe('What the round decides, in a few words, such as "The today screen".'),
13
+ directions: z
14
+ .array(z.object({
15
+ name: z.string().describe('A word or two the user can call it by.'),
16
+ idea: z.string().describe('What it stands for and what it gives up, in a sentence.'),
17
+ html: z
18
+ .string()
19
+ .describe("Its page: one whole HTML document, its CSS and any script inline, pictures as data: URLs or from the web. Nothing from the project's files or its dev server, which the viewer can't reach."),
20
+ }))
21
+ .min(2)
22
+ .max(4),
23
+ },
24
+ run: async ({ title, directions: offered }) => {
25
+ const names = offered.map(({ name }) => name.trim());
26
+ if (new Set(names).size < names.length)
27
+ return 'Two directions have the same name. Give each its own, so the user can tell them apart.';
28
+ const large = offered.find(({ html }) => Buffer.byteLength(html) > MAX_PAGE_BYTES);
29
+ if (large)
30
+ return `The page of ${large.name} is over 2 MB. Leave large pictures out, or take them from the web.`;
31
+ const { address, pages, shown } = await directions.show({ title, directions: offered.map((direction, index) => ({ ...direction, name: names[index] })) }, onPick);
32
+ const preview = previews?.client;
33
+ const opened = preview && !(await preview.open(`${address}${SIDEBAR_CLOSED}`).catch((error) => ({ error: errorMessage(error) }))).error;
34
+ return [
35
+ opened
36
+ ? 'The directions are open in the Preview beside the conversation, where the user sees them now.'
37
+ : `The directions are shown. Give the user this address to open in their browser: ${address}`,
38
+ 'They pick there, and the pick comes back as their next message; they may also answer in words. Until they pick, build none of the directions in the project.',
39
+ 'Before you tell them, look at each page with `look`; if one needs fixing, show the round again:',
40
+ // In the Preview each is looked at in the viewer, so the round stays where the user sees it.
41
+ ...(opened ? shown : pages).map((page, index) => `- ${names[index]}: ${page}`),
42
+ ].join('\n');
43
+ },
44
+ }),
45
+ };
46
+ }
47
+ export const DIRECTIONS_ACTIONS = new Set(['show_directions']);
48
+ /** A call of the tool as the conversation shows it, worded alike whichever backend made it. */
49
+ export function directionsCall(input) {
50
+ const { title } = (input ?? {});
51
+ return { name: 'other', input: { title: 'Show directions', detail: String(title ?? '') } };
52
+ }
53
+ /** What the user's pick says to the agent, as their own message. */
54
+ export function pickMessage({ round, direction }) {
55
+ return `I pick ${direction}, of the directions for ${round.title}.`;
56
+ }
57
+ //# sourceMappingURL=tools.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tools.js","sourceRoot":"","sources":["../../src/directions/tools.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * The viewer the core serves, as drawn in @jinion/ui's playground (`pages/directions`): one page that reads the rounds
3
+ * from beside it. The core draws no React, so it is written out here, with @jinion/ui's tokens by the same names.
4
+ */
5
+ export declare function viewerPage(project: string): string;
6
+ //# sourceMappingURL=viewer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"viewer.d.ts","sourceRoot":"","sources":["../../src/directions/viewer.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,UAezC"}