synthos 0.10.1 → 0.11.1

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 (311) hide show
  1. package/README.md +5 -5
  2. package/default-pages/elevenlabs_effects_studio/chat-history.json +1 -0
  3. package/default-pages/elevenlabs_effects_studio/page.html +1345 -1363
  4. package/default-pages/elevenlabs_effects_studio/page.json +13 -11
  5. package/default-pages/elevenlabs_voice_studio/chat-history.json +1 -0
  6. package/default-pages/elevenlabs_voice_studio/page.html +782 -801
  7. package/default-pages/elevenlabs_voice_studio/page.json +13 -11
  8. package/default-pages/json_tools/chat-history.json +1 -0
  9. package/default-pages/json_tools/page.html +70 -90
  10. package/default-pages/json_tools/page.json +12 -10
  11. package/default-pages/my_notes/chat-history.json +1 -0
  12. package/default-pages/my_notes/page.html +115 -131
  13. package/default-pages/my_notes/page.json +14 -12
  14. package/default-pages/neon_asteroids/chat-history.json +1 -0
  15. package/default-pages/neon_asteroids/page.html +1777 -1803
  16. package/default-pages/neon_asteroids/page.json +14 -12
  17. package/default-pages/oregon_trail/chat-history.json +1 -0
  18. package/default-pages/oregon_trail/page.html +290 -307
  19. package/default-pages/oregon_trail/page.json +14 -12
  20. package/default-pages/solar_explorer/chat-history.json +1 -0
  21. package/default-pages/solar_explorer/page.html +1929 -1951
  22. package/default-pages/solar_explorer/page.json +14 -12
  23. package/default-pages/solar_tutorial/chat-history.json +1 -0
  24. package/default-pages/solar_tutorial/page.html +464 -478
  25. package/default-pages/solar_tutorial/page.json +12 -10
  26. package/default-pages/us_map/chat-history.json +1 -0
  27. package/default-pages/us_map/page.html +170 -193
  28. package/default-pages/us_map/page.json +14 -12
  29. package/default-pages/us_map/page.light.png +0 -0
  30. package/default-pages/us_map_1850/chat-history.json +1 -0
  31. package/default-pages/us_map_1850/page.html +302 -326
  32. package/default-pages/us_map_1850/page.json +14 -12
  33. package/default-pages/western_cities_1850/chat-history.json +1 -0
  34. package/default-pages/western_cities_1850/page.html +503 -527
  35. package/default-pages/western_cities_1850/page.json +14 -12
  36. package/default-themes/aurora-dawn.v3.css +15 -14
  37. package/default-themes/aurora-dusk.v3.css +26 -26
  38. package/default-themes/cosmos-dawn.v3.css +15 -14
  39. package/default-themes/cosmos-dusk.v3.css +26 -26
  40. package/default-themes/elemental-dawn.v3.css +200 -0
  41. package/default-themes/nebula-dawn.v3.css +15 -14
  42. package/default-themes/nebula-dusk.v3.css +24 -24
  43. package/default-themes/solar-flare-dawn.v3.css +15 -14
  44. package/default-themes/solar-flare-dusk.v3.css +26 -26
  45. package/dist/builders/anthropic.d.ts +26 -2
  46. package/dist/builders/anthropic.d.ts.map +1 -1
  47. package/dist/builders/anthropic.js +132 -31
  48. package/dist/builders/anthropic.js.map +1 -1
  49. package/dist/builders/claudecode.d.ts +13 -0
  50. package/dist/builders/claudecode.d.ts.map +1 -0
  51. package/dist/builders/claudecode.js +253 -0
  52. package/dist/builders/claudecode.js.map +1 -0
  53. package/dist/builders/index.d.ts +2 -1
  54. package/dist/builders/index.d.ts.map +1 -1
  55. package/dist/builders/index.js +8 -1
  56. package/dist/builders/index.js.map +1 -1
  57. package/dist/builders/openai.js +2 -1
  58. package/dist/builders/openai.js.map +1 -1
  59. package/dist/builders/types.d.ts +31 -7
  60. package/dist/builders/types.d.ts.map +1 -1
  61. package/dist/builders/types.js +60 -28
  62. package/dist/builders/types.js.map +1 -1
  63. package/dist/connectors/types.d.ts +8 -0
  64. package/dist/connectors/types.d.ts.map +1 -1
  65. package/dist/init.d.ts.map +1 -1
  66. package/dist/init.js +13 -6
  67. package/dist/init.js.map +1 -1
  68. package/dist/migrations.d.ts.map +1 -1
  69. package/dist/migrations.js +161 -14
  70. package/dist/migrations.js.map +1 -1
  71. package/dist/models/anthropic.d.ts +1 -0
  72. package/dist/models/anthropic.d.ts.map +1 -1
  73. package/dist/models/anthropic.js +129 -29
  74. package/dist/models/anthropic.js.map +1 -1
  75. package/dist/models/chainOfThought.d.ts.map +1 -1
  76. package/dist/models/chainOfThought.js +32 -19
  77. package/dist/models/chainOfThought.js.map +1 -1
  78. package/dist/models/index.d.ts +2 -2
  79. package/dist/models/index.d.ts.map +1 -1
  80. package/dist/models/index.js +2 -1
  81. package/dist/models/index.js.map +1 -1
  82. package/dist/models/providers.d.ts +1 -0
  83. package/dist/models/providers.d.ts.map +1 -1
  84. package/dist/models/providers.js +12 -4
  85. package/dist/models/providers.js.map +1 -1
  86. package/dist/models/types.d.ts +15 -1
  87. package/dist/models/types.d.ts.map +1 -1
  88. package/dist/models/types.js.map +1 -1
  89. package/dist/pages.d.ts +57 -8
  90. package/dist/pages.d.ts.map +1 -1
  91. package/dist/pages.js +258 -45
  92. package/dist/pages.js.map +1 -1
  93. package/dist/service/createCompletePrompt.d.ts.map +1 -1
  94. package/dist/service/createCompletePrompt.js +5 -0
  95. package/dist/service/createCompletePrompt.js.map +1 -1
  96. package/dist/service/mediaCache.d.ts +36 -0
  97. package/dist/service/mediaCache.d.ts.map +1 -0
  98. package/dist/service/mediaCache.js +182 -0
  99. package/dist/service/mediaCache.js.map +1 -0
  100. package/dist/service/pageValidator.d.ts +25 -0
  101. package/dist/service/pageValidator.d.ts.map +1 -0
  102. package/dist/service/pageValidator.js +315 -0
  103. package/dist/service/pageValidator.js.map +1 -0
  104. package/dist/service/server.d.ts.map +1 -1
  105. package/dist/service/server.js +4 -0
  106. package/dist/service/server.js.map +1 -1
  107. package/dist/service/sharedTableSchema.d.ts +73 -0
  108. package/dist/service/sharedTableSchema.d.ts.map +1 -0
  109. package/dist/service/sharedTableSchema.js +206 -0
  110. package/dist/service/sharedTableSchema.js.map +1 -0
  111. package/dist/service/transformPage.d.ts +49 -11
  112. package/dist/service/transformPage.d.ts.map +1 -1
  113. package/dist/service/transformPage.js +354 -241
  114. package/dist/service/transformPage.js.map +1 -1
  115. package/dist/service/useApiRoutes.d.ts.map +1 -1
  116. package/dist/service/useApiRoutes.js +285 -34
  117. package/dist/service/useApiRoutes.js.map +1 -1
  118. package/dist/service/useConnectorRoutes.d.ts.map +1 -1
  119. package/dist/service/useConnectorRoutes.js +170 -32
  120. package/dist/service/useConnectorRoutes.js.map +1 -1
  121. package/dist/service/useDataRoutes.d.ts.map +1 -1
  122. package/dist/service/useDataRoutes.js +59 -2
  123. package/dist/service/useDataRoutes.js.map +1 -1
  124. package/dist/service/useExtractRoutes.d.ts +4 -0
  125. package/dist/service/useExtractRoutes.d.ts.map +1 -0
  126. package/dist/service/useExtractRoutes.js +304 -0
  127. package/dist/service/useExtractRoutes.js.map +1 -0
  128. package/dist/service/usePageRoutes.d.ts +17 -0
  129. package/dist/service/usePageRoutes.d.ts.map +1 -1
  130. package/dist/service/usePageRoutes.js +1388 -483
  131. package/dist/service/usePageRoutes.js.map +1 -1
  132. package/dist/service/useSharedDataRoutes.d.ts.map +1 -1
  133. package/dist/service/useSharedDataRoutes.js +54 -2
  134. package/dist/service/useSharedDataRoutes.js.map +1 -1
  135. package/dist/settings.d.ts +27 -0
  136. package/dist/settings.d.ts.map +1 -1
  137. package/dist/settings.js +40 -1
  138. package/dist/settings.js.map +1 -1
  139. package/dist/themes.d.ts +0 -5
  140. package/dist/themes.d.ts.map +1 -1
  141. package/dist/themes.js +3 -95
  142. package/dist/themes.js.map +1 -1
  143. package/migration-rules/v2-to-v3.md +277 -119
  144. package/package.json +5 -1
  145. package/{default-pages/application → required-pages/_shell}/page.html +56 -42
  146. package/required-pages/_shell/page.json +14 -0
  147. package/required-pages/_starters/page.html +534 -0
  148. package/required-pages/_starters/page.json +12 -0
  149. package/required-pages/builder/page.html +353 -43
  150. package/required-pages/builder/page.json +12 -10
  151. package/required-pages/pages/page.html +697 -924
  152. package/required-pages/pages/page.json +12 -10
  153. package/required-pages/settings/page.html +1888 -1753
  154. package/required-pages/settings/page.json +12 -10
  155. package/required-pages/synthos_apis/page.html +834 -845
  156. package/required-pages/synthos_apis/page.json +12 -10
  157. package/required-pages/synthos_scripts/page.html +74 -88
  158. package/required-pages/synthos_scripts/page.json +12 -10
  159. package/scripts/append-instructions.py +90 -0
  160. package/scripts/audit-instructions.py +76 -0
  161. package/scripts/cleanup-shell-markup.mjs +112 -0
  162. package/service-connectors/buffer/connector.json +46 -0
  163. package/service-connectors/canva/connector.json +67 -0
  164. package/service-connectors/elevenlabs/connector.json +1 -1
  165. package/src/builders/anthropic.ts +150 -25
  166. package/src/builders/claudecode.ts +310 -0
  167. package/src/builders/index.ts +7 -1
  168. package/src/builders/openai.ts +2 -1
  169. package/src/builders/types.ts +93 -32
  170. package/src/connectors/types.ts +8 -0
  171. package/src/init.ts +13 -7
  172. package/src/migrations.ts +187 -16
  173. package/src/models/anthropic.ts +140 -30
  174. package/src/models/chainOfThought.ts +33 -18
  175. package/src/models/index.ts +2 -2
  176. package/src/models/providers.ts +10 -1
  177. package/src/models/types.ts +21 -1
  178. package/src/pages.ts +271 -35
  179. package/src/service/createCompletePrompt.ts +6 -0
  180. package/src/service/mediaCache.ts +206 -0
  181. package/src/service/pageValidator.ts +337 -0
  182. package/src/service/server.ts +4 -0
  183. package/src/service/sharedTableSchema.ts +236 -0
  184. package/src/service/transformPage.ts +370 -260
  185. package/src/service/useApiRoutes.ts +283 -32
  186. package/src/service/useConnectorRoutes.ts +189 -34
  187. package/src/service/useDataRoutes.ts +198 -116
  188. package/src/service/useExtractRoutes.ts +331 -0
  189. package/src/service/usePageRoutes.ts +1414 -394
  190. package/src/service/useSharedDataRoutes.ts +184 -109
  191. package/src/settings.ts +65 -0
  192. package/src/themes.ts +78 -180
  193. package/starters/blank_starter/chat-history.json +1 -0
  194. package/starters/blank_starter/page.dark.png +0 -0
  195. package/starters/blank_starter/page.html +47 -0
  196. package/starters/blank_starter/page.json +13 -0
  197. package/starters/blank_starter/page.light.png +0 -0
  198. package/starters/calculator_starter/chat-history.json +1 -0
  199. package/starters/calculator_starter/page.dark.png +0 -0
  200. package/starters/calculator_starter/page.html +232 -0
  201. package/starters/calculator_starter/page.json +13 -0
  202. package/starters/calculator_starter/page.light.png +0 -0
  203. package/starters/calendar_starter/chat-history.json +1 -0
  204. package/starters/calendar_starter/page.dark.png +0 -0
  205. package/starters/calendar_starter/page.html +495 -0
  206. package/starters/calendar_starter/page.json +13 -0
  207. package/starters/calendar_starter/page.light.png +0 -0
  208. package/starters/chat_starter/chat-history.json +1 -0
  209. package/starters/chat_starter/page.dark.png +0 -0
  210. package/starters/chat_starter/page.html +351 -0
  211. package/starters/chat_starter/page.json +13 -0
  212. package/starters/chat_starter/page.light.png +0 -0
  213. package/starters/checklist_starter/chat-history.json +1 -0
  214. package/starters/checklist_starter/page.dark.png +0 -0
  215. package/starters/checklist_starter/page.html +437 -0
  216. package/starters/checklist_starter/page.json +13 -0
  217. package/starters/checklist_starter/page.light.png +0 -0
  218. package/starters/dashboard_starter/chat-history.json +1 -0
  219. package/starters/dashboard_starter/page.dark.png +0 -0
  220. package/starters/dashboard_starter/page.html +195 -0
  221. package/starters/dashboard_starter/page.json +13 -0
  222. package/starters/dashboard_starter/page.light.png +0 -0
  223. package/starters/form_starter/chat-history.json +1 -0
  224. package/starters/form_starter/page.dark.png +0 -0
  225. package/starters/form_starter/page.html +313 -0
  226. package/starters/form_starter/page.json +13 -0
  227. package/starters/form_starter/page.light.png +0 -0
  228. package/starters/gallery_starter/chat-history.json +1 -0
  229. package/starters/gallery_starter/page.dark.png +0 -0
  230. package/starters/gallery_starter/page.html +418 -0
  231. package/starters/gallery_starter/page.json +13 -0
  232. package/starters/gallery_starter/page.light.png +0 -0
  233. package/starters/generator_starter/chat-history.json +1 -0
  234. package/starters/generator_starter/page.dark.png +0 -0
  235. package/starters/generator_starter/page.html +261 -0
  236. package/starters/generator_starter/page.json +13 -0
  237. package/starters/generator_starter/page.light.png +0 -0
  238. package/starters/index.html +538 -0
  239. package/starters/kanban_starter/chat-history.json +1 -0
  240. package/starters/kanban_starter/page.dark.png +0 -0
  241. package/starters/kanban_starter/page.html +432 -0
  242. package/starters/kanban_starter/page.json +13 -0
  243. package/starters/kanban_starter/page.light.png +0 -0
  244. package/starters/presentation_builder/chat-history.json +1 -0
  245. package/starters/presentation_builder/page.dark.png +0 -0
  246. package/starters/presentation_builder/page.html +970 -0
  247. package/starters/presentation_builder/page.json +15 -0
  248. package/starters/presentation_builder/page.light.png +0 -0
  249. package/starters/presentation_builder/presentation_voice/voice_config.json +9 -0
  250. package/starters/pulse_starter/chat-history.json +1 -0
  251. package/starters/pulse_starter/page.dark.png +0 -0
  252. package/starters/pulse_starter/page.html +698 -0
  253. package/starters/pulse_starter/page.json +13 -0
  254. package/starters/pulse_starter/page.light.png +0 -0
  255. package/starters/quiz_starter/chat-history.json +1 -0
  256. package/starters/quiz_starter/page.dark.png +0 -0
  257. package/starters/quiz_starter/page.html +292 -0
  258. package/starters/quiz_starter/page.json +13 -0
  259. package/starters/quiz_starter/page.light.png +0 -0
  260. package/starters/reference_starter/chat-history.json +1 -0
  261. package/starters/reference_starter/page.dark.png +0 -0
  262. package/starters/reference_starter/page.html +250 -0
  263. package/starters/reference_starter/page.json +13 -0
  264. package/starters/reference_starter/page.light.png +0 -0
  265. package/starters/retro_game_starter/chat-history.json +1 -0
  266. package/starters/retro_game_starter/page.dark.png +0 -0
  267. package/{default-pages → starters}/retro_game_starter/page.html +1281 -1308
  268. package/starters/retro_game_starter/page.json +15 -0
  269. package/starters/retro_game_starter/page.light.png +0 -0
  270. package/starters/roster_starter/chat-history.json +1 -0
  271. package/starters/roster_starter/page.dark.png +0 -0
  272. package/starters/roster_starter/page.html +600 -0
  273. package/starters/roster_starter/page.json +13 -0
  274. package/starters/roster_starter/page.light.png +0 -0
  275. package/starters/server.js +182 -0
  276. package/starters/start.cmd +1 -0
  277. package/starters/timeline_starter/chat-history.json +1 -0
  278. package/starters/timeline_starter/page.dark.png +0 -0
  279. package/starters/timeline_starter/page.html +446 -0
  280. package/starters/timeline_starter/page.json +13 -0
  281. package/starters/timeline_starter/page.light.png +0 -0
  282. package/starters/tutorial_starter/chat-history.json +1 -0
  283. package/starters/tutorial_starter/page.dark.png +0 -0
  284. package/starters/tutorial_starter/page.html +283 -0
  285. package/starters/tutorial_starter/page.json +13 -0
  286. package/starters/tutorial_starter/page.light.png +0 -0
  287. package/static-files/agent.v3.js +122 -0
  288. package/static-files/connector.v3.js +48 -0
  289. package/static-files/extract.v3.js +188 -0
  290. package/static-files/helpers.v3.js +50 -6
  291. package/static-files/page-bridge.js +114 -0
  292. package/static-files/page.v3.js +1292 -1290
  293. package/static-files/script.v3.js +32 -0
  294. package/static-files/server.v3.js +89 -0
  295. package/static-files/shell-bridge.v3.js +174 -0
  296. package/static-files/shell-modals.v3.js +521 -0
  297. package/static-files/{shell.css → shell.v3.css} +271 -22
  298. package/static-files/shell.v3.js +1865 -0
  299. package/static-files/storage.v3.js +176 -0
  300. package/tests/anthropic.spec.ts +42 -7
  301. package/tests/builders.spec.ts +70 -2
  302. package/tests/pageValidator.spec.ts +548 -0
  303. package/tests/profiles.spec.ts +122 -0
  304. package/tests/sharedTableSchema.spec.ts +242 -0
  305. package/tests/transformPage.spec.ts +62 -81
  306. package/default-pages/application/page.json +0 -10
  307. package/default-pages/retro_game_starter/page.json +0 -12
  308. package/default-pages/sidebar_page/page.html +0 -51
  309. package/default-pages/sidebar_page/page.json +0 -10
  310. package/default-pages/two-panel_page/page.html +0 -68
  311. package/default-pages/two-panel_page/page.json +0 -10
@@ -0,0 +1,176 @@
1
+ /**
2
+ * storage.v3.js — Per-page and cross-page data & file storage
3
+ *
4
+ * Creates: synthos.data, synthos.files, synthos.shared
5
+ */
6
+ (function() {
7
+ window.synthos = window.synthos || {};
8
+ if (window.__synthOSStorage) return;
9
+ window.__synthOSStorage = true;
10
+
11
+ var _json = window.synthos._json;
12
+ var _pageName = window.synthos._pageName;
13
+
14
+ // Fallback if server.v3.js hasn't loaded yet (defensive)
15
+ if (!_json) {
16
+ _json = function(method, url, body) {
17
+ var opts = { method: method, headers: { 'Content-Type': 'application/json' } };
18
+ if (body !== undefined) opts.body = JSON.stringify(body);
19
+ return fetch(url, opts).then(function(res) {
20
+ var ct = res.headers.get('content-type') || '';
21
+ var isJson = ct.indexOf('application/json') !== -1;
22
+ return (isJson ? res.json() : res.text()).then(function(data) {
23
+ if (!res.ok) {
24
+ if (res.status === 404 && isJson && data && data.error === 'table_not_found') return null;
25
+ var err = new Error(isJson && data && data.error ? data.error : data);
26
+ err.status = res.status;
27
+ throw err;
28
+ }
29
+ return data;
30
+ });
31
+ });
32
+ };
33
+ }
34
+ if (!_pageName) {
35
+ _pageName = function() { return (window.pageInfo && window.pageInfo.name) || 'default'; };
36
+ }
37
+
38
+ function _pageData() {
39
+ return '/api/data/' + encodeURIComponent(_pageName());
40
+ }
41
+
42
+ window.synthos.data = {
43
+ list: function(table, opts) {
44
+ var url = _pageData() + '/' + encodeURIComponent(table);
45
+ if (opts && typeof opts.limit === 'number') {
46
+ url += '?limit=' + opts.limit;
47
+ if (typeof opts.offset === 'number') {
48
+ url += '&offset=' + opts.offset;
49
+ }
50
+ }
51
+ return _json('GET', url) || [];
52
+ },
53
+ get: function(table, id) {
54
+ return _json('GET', _pageData() + '/' + encodeURIComponent(table) + '/' + encodeURIComponent(id)) || null;
55
+ },
56
+ save: function(table, row) {
57
+ return _json('POST', _pageData() + '/' + encodeURIComponent(table), row);
58
+ },
59
+ remove: function(table, id) {
60
+ return _json('DELETE', _pageData() + '/' + encodeURIComponent(table) + '/' + encodeURIComponent(id));
61
+ },
62
+ schema: function(table) {
63
+ return _json('GET', _pageData() + '/' + encodeURIComponent(table) + '/_schema').then(function(w) {
64
+ return w && w.schema ? w.schema : null;
65
+ });
66
+ },
67
+ defineSchema: function(table, schema, options) {
68
+ var merge = (options && options.merge === 'replace') ? 'replace' : 'additive';
69
+ var url = _pageData() + '/' + encodeURIComponent(table) + '/_schema?merge=' + merge;
70
+ var body = { schema: schema };
71
+ if (options && typeof options.definedBy === 'string') body.definedBy = options.definedBy;
72
+ return _json('PUT', url, body);
73
+ },
74
+ tables: function() {
75
+ return _json('GET', _pageData() + '/_tables').then(function(res) {
76
+ return (res && res.tables) || [];
77
+ });
78
+ }
79
+ };
80
+
81
+ window.synthos.files = {
82
+ list: function() {
83
+ return _json('GET', '/api/files/' + encodeURIComponent(_pageName()));
84
+ },
85
+ upload: function(filename, blob) {
86
+ return fetch('/api/files/' + encodeURIComponent(_pageName()), {
87
+ method: 'POST',
88
+ headers: { 'x-filename': filename },
89
+ body: blob
90
+ }).then(function(res) {
91
+ if (!res.ok) {
92
+ return res.json().then(function(data) {
93
+ var err = new Error(data && data.error ? data.error : 'Upload failed');
94
+ err.status = res.status;
95
+ throw err;
96
+ });
97
+ }
98
+ return res.json();
99
+ });
100
+ },
101
+ url: function(filename) {
102
+ return '/api/files/' + encodeURIComponent(_pageName()) + '/' + encodeURIComponent(filename);
103
+ },
104
+ remove: function(filename) {
105
+ return _json('DELETE', '/api/files/' + encodeURIComponent(_pageName()) + '/' + encodeURIComponent(filename));
106
+ }
107
+ };
108
+
109
+ window.synthos.shared = {
110
+ data: {
111
+ list: function(table, opts) {
112
+ var url = '/api/shared/data/' + encodeURIComponent(table);
113
+ if (opts && typeof opts.limit === 'number') {
114
+ url += '?limit=' + opts.limit;
115
+ if (typeof opts.offset === 'number') {
116
+ url += '&offset=' + opts.offset;
117
+ }
118
+ }
119
+ return _json('GET', url) || [];
120
+ },
121
+ get: function(table, id) {
122
+ return _json('GET', '/api/shared/data/' + encodeURIComponent(table) + '/' + encodeURIComponent(id)) || null;
123
+ },
124
+ save: function(table, row) {
125
+ return _json('POST', '/api/shared/data/' + encodeURIComponent(table), row);
126
+ },
127
+ remove: function(table, id) {
128
+ return _json('DELETE', '/api/shared/data/' + encodeURIComponent(table) + '/' + encodeURIComponent(id));
129
+ },
130
+ schema: function(table) {
131
+ return _json('GET', '/api/shared/data/' + encodeURIComponent(table) + '/_schema').then(function(w) {
132
+ return w && w.schema ? w.schema : null;
133
+ });
134
+ },
135
+ defineSchema: function(table, schema, options) {
136
+ var merge = (options && options.merge === 'replace') ? 'replace' : 'additive';
137
+ var url = '/api/shared/data/' + encodeURIComponent(table) + '/_schema?merge=' + merge;
138
+ var body = { schema: schema };
139
+ if (options && typeof options.definedBy === 'string') body.definedBy = options.definedBy;
140
+ return _json('PUT', url, body);
141
+ },
142
+ tables: function() {
143
+ return _json('GET', '/api/shared/data/_tables').then(function(res) {
144
+ return (res && res.tables) || [];
145
+ });
146
+ }
147
+ },
148
+ files: {
149
+ list: function() {
150
+ return _json('GET', '/api/shared/files');
151
+ },
152
+ upload: function(filename, blob) {
153
+ return fetch('/api/shared/files', {
154
+ method: 'POST',
155
+ headers: { 'x-filename': filename },
156
+ body: blob
157
+ }).then(function(res) {
158
+ if (!res.ok) {
159
+ return res.json().then(function(data) {
160
+ var err = new Error(data && data.error ? data.error : 'Upload failed');
161
+ err.status = res.status;
162
+ throw err;
163
+ });
164
+ }
165
+ return res.json();
166
+ });
167
+ },
168
+ url: function(filename) {
169
+ return '/api/shared/files/' + encodeURIComponent(filename);
170
+ },
171
+ remove: function(filename) {
172
+ return _json('DELETE', '/api/shared/files/' + encodeURIComponent(filename));
173
+ }
174
+ }
175
+ };
176
+ })();
@@ -25,23 +25,23 @@ describe('buildAnthropicRequest', () => {
25
25
  assert.strictEqual(messages[2].content, 'Hello');
26
26
  });
27
27
 
28
- it('appends assistant prefill "{" in jsonMode', () => {
28
+ it('ends on user message in jsonMode (4.6+ rejects assistant prefill)', () => {
29
29
  const args: PromptCompletionArgs = { ...baseArgs, jsonMode: true };
30
30
  const { messages } = buildAnthropicRequest(args, 0.0);
31
31
  const last = messages[messages.length - 1];
32
- assert.strictEqual(last.role, 'assistant');
33
- assert.strictEqual(last.content, '{');
32
+ assert.strictEqual(last.role, 'user');
33
+ assert.strictEqual(last.content, 'Hello');
34
34
  });
35
35
 
36
- it('appends assistant prefill "{" when jsonSchema is provided', () => {
36
+ it('ends on user message when jsonSchema is provided', () => {
37
37
  const args: PromptCompletionArgs = { ...baseArgs, jsonSchema: { type: 'object' } };
38
38
  const { messages } = buildAnthropicRequest(args, 0.0);
39
39
  const last = messages[messages.length - 1];
40
- assert.strictEqual(last.role, 'assistant');
41
- assert.strictEqual(last.content, '{');
40
+ assert.strictEqual(last.role, 'user');
41
+ assert.strictEqual(last.content, 'Hello');
42
42
  });
43
43
 
44
- it('does not prefill in plain text mode', () => {
44
+ it('ends on user message in plain text mode', () => {
45
45
  const { messages } = buildAnthropicRequest(baseArgs, 0.0);
46
46
  const last = messages[messages.length - 1];
47
47
  assert.strictEqual(last.role, 'user');
@@ -81,4 +81,39 @@ describe('buildAnthropicRequest', () => {
81
81
  const { temperature } = buildAnthropicRequest(args, 0.7);
82
82
  assert.strictEqual(temperature, 0.3);
83
83
  });
84
+
85
+ it('passes tools through to the request', () => {
86
+ const args: PromptCompletionArgs = {
87
+ ...baseArgs,
88
+ tools: [
89
+ {
90
+ name: 'get_thing',
91
+ description: 'Returns the thing.',
92
+ input_schema: { type: 'object', properties: {}, additionalProperties: false },
93
+ },
94
+ ],
95
+ };
96
+ const { tools } = buildAnthropicRequest(args, 0.0);
97
+ assert.ok(tools);
98
+ assert.strictEqual(tools!.length, 1);
99
+ assert.strictEqual(tools![0].name, 'get_thing');
100
+ assert.strictEqual(tools![0].description, 'Returns the thing.');
101
+ });
102
+
103
+ it('returns no tools field when tools array is empty', () => {
104
+ const args: PromptCompletionArgs = { ...baseArgs, tools: [] };
105
+ const { tools } = buildAnthropicRequest(args, 0.0);
106
+ assert.strictEqual(tools, undefined);
107
+ });
108
+
109
+ it('disables JSON prefill when tools are provided', () => {
110
+ const args: PromptCompletionArgs = {
111
+ ...baseArgs,
112
+ jsonMode: true,
113
+ tools: [{ name: 't', description: 'd', input_schema: { type: 'object', properties: {}, additionalProperties: false } }],
114
+ };
115
+ const { messages } = buildAnthropicRequest(args, 0.0);
116
+ const last = messages[messages.length - 1];
117
+ assert.strictEqual(last.role, 'user', 'last message must be user when tools are bound (no "{" prefill)');
118
+ });
84
119
  });
@@ -1,8 +1,8 @@
1
1
  import assert from 'assert';
2
- import { createAnthropicBuilder, classifyRequest, buildWithModel } from '../src/builders/anthropic';
2
+ import { createAnthropicBuilder, buildWithModel, TOOLS_INSTRUCTION_HINT } from '../src/builders/anthropic';
3
3
  import { createBuilder } from '../src/builders/index';
4
4
  import { ContextSection, BuilderResult } from '../src/builders/types';
5
- import { completePrompt, AgentCompletion } from '../src/models/types';
5
+ import { completePrompt, AgentCompletion, PromptCompletionArgs, ToolDefinition, ToolHandler } from '../src/models/types';
6
6
 
7
7
  // ---------------------------------------------------------------------------
8
8
  // Helpers
@@ -13,6 +13,8 @@ const PAGE_HTML = '<html><body><h1>Hello</h1></body></html>';
13
13
  const currentPage: ContextSection = {
14
14
  title: '<CURRENT_PAGE>',
15
15
  content: PAGE_HTML,
16
+ sketch: null,
17
+ mode: 'always-full',
16
18
  instructions: '',
17
19
  };
18
20
 
@@ -103,6 +105,72 @@ describe('Anthropic Builder — Haiku Classifier Routing', () => {
103
105
  assert.strictEqual(result.text, 'The heading says Hello.');
104
106
  }
105
107
  });
108
+
109
+ it('appends the tools instruction hint to system when tools are bound', async () => {
110
+ let captured: PromptCompletionArgs | undefined;
111
+ const complete: completePrompt = async (args) => {
112
+ captured = args;
113
+ return { completed: true, value: '[]' };
114
+ };
115
+ const tools: ToolDefinition[] = [{
116
+ name: 'get_thing',
117
+ description: 'Returns a thing.',
118
+ input_schema: { type: 'object', properties: {}, additionalProperties: false },
119
+ }];
120
+ const handlers: Record<string, ToolHandler> = { get_thing: async () => 'ok' };
121
+
122
+ await buildWithModel(complete, currentPage, additionalSections, 'test', undefined, 'SynthOS', undefined, undefined, tools, handlers);
123
+
124
+ assert.ok(captured);
125
+ assert.ok(captured!.system!.content.includes(TOOLS_INSTRUCTION_HINT), 'system should include tools hint');
126
+ assert.strictEqual(captured!.tools, tools);
127
+ assert.strictEqual(captured!.toolHandlers, handlers);
128
+ });
129
+
130
+ it('omits the tools instruction hint when tools are not bound', async () => {
131
+ let captured: PromptCompletionArgs | undefined;
132
+ const complete: completePrompt = async (args) => {
133
+ captured = args;
134
+ return { completed: true, value: '[]' };
135
+ };
136
+
137
+ await buildWithModel(complete, currentPage, additionalSections, 'test', undefined, 'SynthOS');
138
+
139
+ assert.ok(captured);
140
+ assert.ok(!captured!.system!.content.includes(TOOLS_INSTRUCTION_HINT), 'system must not include tools hint');
141
+ assert.strictEqual(captured!.tools, undefined);
142
+ });
143
+ });
144
+
145
+ describe('Builder.run() — tool passthrough', () => {
146
+ it('passes tools, toolHandlers, and onToolCall through to the model', async () => {
147
+ const changes = JSON.stringify([{ op: 'replace', nodeId: '1', html: '<h1>Hi</h1>' }]);
148
+ let captured: PromptCompletionArgs | undefined;
149
+ const complete: completePrompt = async (args) => {
150
+ captured = args;
151
+ return { completed: true, value: changes };
152
+ };
153
+
154
+ const tools: ToolDefinition[] = [{
155
+ name: 'get_connectors',
156
+ description: 'Returns connectors.',
157
+ input_schema: { type: 'object', properties: {}, additionalProperties: false },
158
+ }];
159
+ const handlers: Record<string, ToolHandler> = { get_connectors: async () => '[]' };
160
+ const onToolCall = (_names: string[]) => { /* noop */ };
161
+
162
+ const builder = createAnthropicBuilder(complete, undefined, 'SynthOS', {
163
+ apiKey: 'test-key',
164
+ model: 'claude-sonnet-4-6',
165
+ });
166
+ const result = await builder.run(currentPage, additionalSections, 'change', false, undefined, tools, handlers, onToolCall);
167
+
168
+ assert.strictEqual(result.kind, 'transforms');
169
+ assert.ok(captured);
170
+ assert.strictEqual(captured!.tools, tools);
171
+ assert.strictEqual(captured!.toolHandlers, handlers);
172
+ assert.strictEqual(captured!.onToolCall, onToolCall);
173
+ });
106
174
  });
107
175
 
108
176
  describe('createBuilder factory', () => {