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,283 @@
1
+ <!DOCTYPE html><html lang="en"><head>
2
+ <meta charset="UTF-8">
3
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
4
+ <title>SynthOS - Tutorial Starter</title>
5
+ <script id="theme-info" src="/api/theme-info.js" data-locked="true"></script>
6
+ <link id="theme-css" rel="stylesheet" href="/api/theme.css" data-locked="true">
7
+ <style>
8
+ html, body { height: 100%; }
9
+ body { margin: 0; }
10
+ .viewer-panel { height: 100%; }
11
+ .tut-app {
12
+ display: grid;
13
+ grid-template-columns: 260px 1fr;
14
+ height: 100%;
15
+ min-height: 100%;
16
+ }
17
+ @media (max-width: 700px) {
18
+ .tut-app { grid-template-columns: 1fr; }
19
+ .tut-rail { display: none; }
20
+ .tut-rail.open { display: block; position: absolute; z-index: 10; width: 80%; height: 100%; }
21
+ }
22
+ .tut-rail {
23
+ background: var(--defaultStateBackground, #faf9f8);
24
+ border-right: 1px solid var(--bodyDivider, #edebe9);
25
+ padding: 20px 0;
26
+ overflow-y: auto;
27
+ }
28
+ .tut-rail h2 {
29
+ margin: 0 16px 12px;
30
+ font-size: 12px;
31
+ text-transform: uppercase;
32
+ letter-spacing: 0.05em;
33
+ color: var(--bodySubtext, #605e5c);
34
+ }
35
+ .step-list {
36
+ list-style: none;
37
+ margin: 0;
38
+ padding: 0;
39
+ }
40
+ .step-item {
41
+ padding: 10px 16px;
42
+ cursor: pointer;
43
+ display: flex;
44
+ align-items: center;
45
+ gap: 8px;
46
+ border-left: 3px solid transparent;
47
+ color: var(--bodyText, #333333);
48
+ }
49
+ .step-item:hover { background: var(--bodyBackgroundHovered, #f3f2f1); }
50
+ .step-item.active {
51
+ background: var(--bodyBackgroundHovered, #f3f2f1);
52
+ border-left-color: var(--themePrimary, #0078d4);
53
+ font-weight: 600;
54
+ }
55
+ .step-num {
56
+ display: inline-flex;
57
+ justify-content: center;
58
+ align-items: center;
59
+ width: 22px;
60
+ height: 22px;
61
+ border-radius: 50%;
62
+ background: var(--bodyDivider, #edebe9);
63
+ color: var(--bodyText, #333333);
64
+ font-size: 11px;
65
+ font-weight: 600;
66
+ flex-shrink: 0;
67
+ }
68
+ .step-item.active .step-num {
69
+ background: var(--themePrimary, #0078d4);
70
+ color: #ffffff;
71
+ }
72
+ .step-item.complete .step-num {
73
+ background: #2e7d32;
74
+ color: #ffffff;
75
+ }
76
+ .step-item.complete .step-num::before { content: '✓'; }
77
+ .step-item.complete .step-num span { display: none; }
78
+ .tut-body {
79
+ display: flex;
80
+ flex-direction: column;
81
+ overflow: hidden;
82
+ min-height: 0;
83
+ }
84
+ .tut-content {
85
+ padding: 32px 40px;
86
+ overflow-y: auto;
87
+ flex: 1 1 auto;
88
+ min-height: 0;
89
+ }
90
+ @media (max-width: 700px) { .tut-content { padding: 20px; } }
91
+ .tut-content h1 {
92
+ margin: 0 0 8px;
93
+ font-size: 26px;
94
+ color: var(--bodyText, #333333);
95
+ }
96
+ .tut-content .step-meta {
97
+ font-size: 12px;
98
+ color: var(--bodySubtext, #605e5c);
99
+ text-transform: uppercase;
100
+ letter-spacing: 0.05em;
101
+ margin-bottom: 16px;
102
+ }
103
+ .tut-content p {
104
+ color: var(--bodyText, #333333);
105
+ line-height: 1.6;
106
+ font-size: 15px;
107
+ }
108
+ .tut-content .screenshot {
109
+ display: block;
110
+ width: 100%;
111
+ max-width: 600px;
112
+ background: var(--defaultStateBackground, #faf9f8);
113
+ border: 1px solid var(--bodyDivider, #edebe9);
114
+ border-radius: 6px;
115
+ margin: 16px 0;
116
+ padding: 32px;
117
+ text-align: center;
118
+ color: var(--bodySubtext, #605e5c);
119
+ font-size: 13px;
120
+ }
121
+ .tut-content pre {
122
+ background: var(--defaultStateBackground, #faf9f8);
123
+ border: 1px solid var(--bodyDivider, #edebe9);
124
+ border-radius: 6px;
125
+ padding: 12px 16px;
126
+ overflow-x: auto;
127
+ font-family: 'Cascadia Code', 'Consolas', monospace;
128
+ font-size: 13px;
129
+ color: var(--bodyText, #333333);
130
+ line-height: 1.5;
131
+ }
132
+ .tut-content .try-it {
133
+ background: var(--bodyBackground, #ffffff);
134
+ border: 2px solid var(--themePrimary, #0078d4);
135
+ border-radius: 8px;
136
+ padding: 16px;
137
+ margin: 16px 0;
138
+ }
139
+ .tut-content .try-it strong { color: var(--themePrimary, #0078d4); }
140
+ .tut-footer {
141
+ padding: 14px 40px;
142
+ border-top: 1px solid var(--bodyDivider, #edebe9);
143
+ background: var(--defaultStateBackground, #faf9f8);
144
+ display: flex;
145
+ justify-content: space-between;
146
+ align-items: center;
147
+ gap: 12px;
148
+ flex-wrap: wrap;
149
+ }
150
+ .footer-meta {
151
+ font-size: 12px;
152
+ color: var(--bodySubtext, #605e5c);
153
+ }
154
+ .footer-actions {
155
+ display: flex;
156
+ gap: 8px;
157
+ align-items: center;
158
+ }
159
+ </style>
160
+ </head>
161
+ <body>
162
+ <div class="viewer-panel" id="viewerPanel" style="padding: 0;">
163
+ <div class="tut-app">
164
+ <aside class="tut-rail" id="stepRail">
165
+ <h2>Steps</h2>
166
+ <ul class="step-list" id="stepList"></ul>
167
+ </aside>
168
+ <div class="tut-body">
169
+ <div class="tut-content" id="tutContent"></div>
170
+ <div class="tut-footer">
171
+ <div class="footer-meta" id="footerMeta">Step 1 of —</div>
172
+ <div class="footer-actions">
173
+ <button class="flm-button" id="markCompleteBtn" data-icon="CheckMark">Mark complete</button>
174
+ <button class="flm-button" id="prevBtn" data-icon="ChevronLeft">Back</button>
175
+ <button class="flm-button flm-button--primary" id="nextBtn" data-icon="ChevronRight">Next</button>
176
+ </div>
177
+ </div>
178
+ </div>
179
+ </div>
180
+ </div>
181
+
182
+ <div id="instructions" style="display: none;" data-locked="true">Tutorial / Walkthrough archetype. Sequenced explainer with left rail of steps and right body of content. Each step: { title, body (HTML), screenshot? (URL or null), code? (string), tryIt? (HTML) }. Track progress in completed[] (persist via synthos.data.save("tutorial_progress", { completedIds }) or localStorage). Replace the STEPS array with the tutorial's actual content. Footer shows position, lets user mark complete and navigate. The rail collapses on narrow screens. Use theme tokens (avoid the natural pallet) unless the user requests an alternative color.</div>
183
+ <div id="thoughts" style="display: none;" data-locked="true"></div>
184
+
185
+ <script>
186
+ (function () {
187
+ var STEPS = [
188
+ {
189
+ id: 'intro',
190
+ title: 'Welcome to the tutorial',
191
+ body: '<p>This is the first step of your walkthrough. Replace this content with what you want to teach.</p><p>Use the rail on the left to jump between steps, or the Back / Next buttons below.</p>',
192
+ screenshot: null,
193
+ code: null,
194
+ tryIt: null
195
+ },
196
+ {
197
+ id: 'concept',
198
+ title: 'Step 2 — A core concept',
199
+ body: '<p>Explain a concept here. Add a paragraph, a screenshot, or a code block — whatever fits.</p>',
200
+ screenshot: '[Screenshot placeholder]',
201
+ code: null,
202
+ tryIt: null
203
+ },
204
+ {
205
+ id: 'code',
206
+ title: 'Step 3 — Try some code',
207
+ body: '<p>Code blocks render in a monospace box with horizontal scroll. Use them for snippets the user should copy.</p>',
208
+ screenshot: null,
209
+ code: 'function greet(name) {\n return "Hello, " + name + "!";\n}\n\ngreet("world");',
210
+ tryIt: '<strong>Try it:</strong> Paste the snippet into the browser console and call greet("you").'
211
+ },
212
+ {
213
+ id: 'wrap',
214
+ title: 'Step 4 — Wrap up',
215
+ body: '<p>Final step. Summarize what was covered and point to next-step resources.</p>',
216
+ screenshot: null,
217
+ code: null,
218
+ tryIt: null
219
+ }
220
+ ];
221
+
222
+ var current = 0;
223
+ var completed = {};
224
+
225
+ var stepList = document.getElementById('stepList');
226
+ var content = document.getElementById('tutContent');
227
+ var footerMeta = document.getElementById('footerMeta');
228
+ var prevBtn = document.getElementById('prevBtn');
229
+ var nextBtn = document.getElementById('nextBtn');
230
+ var markBtn = document.getElementById('markCompleteBtn');
231
+
232
+ function renderRail() {
233
+ var html = '';
234
+ STEPS.forEach(function (s, i) {
235
+ var classes = ['step-item'];
236
+ if (i === current) classes.push('active');
237
+ if (completed[s.id]) classes.push('complete');
238
+ html += '<li class="' + classes.join(' ') + '" data-idx="' + i + '"><span class="step-num"><span>' + (i + 1) + '</span></span><span>' + escapeHtml(s.title) + '</span></li>';
239
+ });
240
+ stepList.innerHTML = html;
241
+ }
242
+
243
+ function renderStep() {
244
+ var s = STEPS[current];
245
+ var html = '<div class="step-meta">Step ' + (current + 1) + ' of ' + STEPS.length + '</div>';
246
+ html += '<h1>' + escapeHtml(s.title) + '</h1>';
247
+ html += s.body;
248
+ if (s.screenshot) html += '<div class="screenshot">' + escapeHtml(s.screenshot) + '</div>';
249
+ if (s.code) html += '<pre>' + escapeHtml(s.code) + '</pre>';
250
+ if (s.tryIt) html += '<div class="try-it">' + s.tryIt + '</div>';
251
+ content.innerHTML = html;
252
+ content.scrollTop = 0;
253
+ footerMeta.textContent = 'Step ' + (current + 1) + ' of ' + STEPS.length + ' · ' + Object.keys(completed).length + ' complete';
254
+ prevBtn.disabled = current === 0;
255
+ prevBtn.style.opacity = current === 0 ? '0.4' : '1';
256
+ nextBtn.disabled = current === STEPS.length - 1;
257
+ nextBtn.style.opacity = current === STEPS.length - 1 ? '0.4' : '1';
258
+ markBtn.textContent = completed[s.id] ? '✓ Completed' : 'Mark complete';
259
+ renderRail();
260
+ }
261
+
262
+ stepList.addEventListener('click', function (e) {
263
+ var item = e.target.closest('.step-item');
264
+ if (!item) return;
265
+ current = parseInt(item.getAttribute('data-idx'), 10);
266
+ renderStep();
267
+ });
268
+ prevBtn.addEventListener('click', function () { if (current > 0) { current--; renderStep(); } });
269
+ nextBtn.addEventListener('click', function () { if (current < STEPS.length - 1) { current++; renderStep(); } });
270
+ markBtn.addEventListener('click', function () {
271
+ var id = STEPS[current].id;
272
+ completed[id] = !completed[id];
273
+ // synthos.data.save('tutorial_progress', { completed: completed });
274
+ renderStep();
275
+ });
276
+
277
+ function escapeHtml(s) { return String(s).replace(/[&<>"']/g, function (c) { return ({ '&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#39;' })[c]; }); }
278
+
279
+ // synthos.data.load('tutorial_progress').then(function (p) { if (p && p.completed) { completed = p.completed; renderStep(); } });
280
+ renderStep();
281
+ })();
282
+ </script>
283
+ </body></html>
@@ -0,0 +1,13 @@
1
+ {
2
+ "title": "Tutorial",
3
+ "description": "Teach a topic step-by-step with a progress rail, content blocks, and try-it interactions.",
4
+ "categories": [
5
+ "_Starters"
6
+ ],
7
+ "pinned": false,
8
+ "showInAll": false,
9
+ "pageVersion": 3,
10
+ "mode": "unlocked",
11
+ "greeting": "Welcome to the Tutorial starter — a sequenced explainer scaffold. Tell me what you'd like to teach (e.g. an onboarding tour, a recipe, a getting-started guide, a repair walkthrough) and I'll wire the step rail, content blocks, and progress tracking.",
12
+ "firstRunGreeting": ""
13
+ }
@@ -0,0 +1,122 @@
1
+ /**
2
+ * agent.v3.js — AI agent system (A2A, OpenClaw)
3
+ *
4
+ * Creates: synthos.agent (including .chat, .isEnabled, .getCapabilities)
5
+ */
6
+ (function() {
7
+ window.synthos = window.synthos || {};
8
+ if (window.__synthOSAgent) return;
9
+ window.__synthOSAgent = true;
10
+
11
+ var _json = window.synthos._json;
12
+ if (!_json) {
13
+ _json = function(method, url, body) {
14
+ var opts = { method: method, headers: { 'Content-Type': 'application/json' } };
15
+ if (body !== undefined) opts.body = JSON.stringify(body);
16
+ return fetch(url, opts).then(function(res) {
17
+ var ct = res.headers.get('content-type') || '';
18
+ var isJson = ct.indexOf('application/json') !== -1;
19
+ return (isJson ? res.json() : res.text()).then(function(data) {
20
+ if (!res.ok) { var err = new Error(isJson && data && data.error ? data.error : data); err.status = res.status; throw err; }
21
+ return data;
22
+ });
23
+ });
24
+ };
25
+ }
26
+
27
+ window.synthos.agent = {
28
+ list: function(opts) {
29
+ var url = '/api/agents';
30
+ var params = [];
31
+ if (opts) {
32
+ if (typeof opts.enabled === 'boolean') params.push('enabled=' + opts.enabled);
33
+ if (opts.provider) params.push('provider=' + encodeURIComponent(opts.provider));
34
+ }
35
+ if (params.length) url += '?' + params.join('&');
36
+ return _json('GET', url);
37
+ },
38
+ send: function(agentId, message, attachments) {
39
+ var body = { message: message };
40
+ if (attachments) body.attachments = attachments;
41
+ return _json('POST', '/api/agents/' + encodeURIComponent(agentId) + '/send', body);
42
+ },
43
+ sendStream: function(agentId, message, onEventOrOpts, attachments) {
44
+ var onEvent, atts;
45
+ if (typeof onEventOrOpts === 'function') {
46
+ onEvent = onEventOrOpts;
47
+ atts = attachments;
48
+ } else if (onEventOrOpts && typeof onEventOrOpts === 'object') {
49
+ onEvent = onEventOrOpts.onEvent;
50
+ atts = onEventOrOpts.attachments;
51
+ }
52
+ var body = { message: message };
53
+ if (atts) body.attachments = atts;
54
+ var aborted = false;
55
+ var controller = new AbortController();
56
+ fetch('/api/agents/' + encodeURIComponent(agentId) + '/stream', {
57
+ method: 'POST',
58
+ headers: { 'Content-Type': 'application/json' },
59
+ body: JSON.stringify(body),
60
+ signal: controller.signal
61
+ }).then(function(res) {
62
+ var reader = res.body.getReader();
63
+ var decoder = new TextDecoder();
64
+ var buffer = '';
65
+ function pump() {
66
+ return reader.read().then(function(result) {
67
+ if (result.done || aborted) return;
68
+ buffer += decoder.decode(result.value, { stream: true });
69
+ var lines = buffer.split('\n');
70
+ buffer = lines.pop() || '';
71
+ for (var i = 0; i < lines.length; i++) {
72
+ var line = lines[i];
73
+ if (line.indexOf('data: ') === 0) {
74
+ var data = line.substring(6);
75
+ if (data === '[DONE]') return;
76
+ try {
77
+ var event = JSON.parse(data);
78
+ if (onEvent) onEvent(event);
79
+ } catch(e) { /* skip malformed lines */ }
80
+ }
81
+ }
82
+ return pump();
83
+ });
84
+ }
85
+ return pump();
86
+ }).catch(function(err) {
87
+ if (!aborted && onEvent) onEvent({ kind: 'error', data: err.message });
88
+ });
89
+ return { close: function() { aborted = true; controller.abort(); } };
90
+ },
91
+ chat: {
92
+ send: function(agentId, message, attachments) {
93
+ return window.synthos.agent.send(agentId, message, attachments);
94
+ },
95
+ sendStream: function(agentId, message, onEventOrOpts, attachments) {
96
+ return window.synthos.agent.sendStream(agentId, message, onEventOrOpts, attachments);
97
+ },
98
+ history: function(agentId) {
99
+ return _json('POST', '/api/agents/' + encodeURIComponent(agentId) + '/chat/history', {}).then(function(res) {
100
+ return res.messages || [];
101
+ });
102
+ },
103
+ abort: function(agentId) {
104
+ return _json('POST', '/api/agents/' + encodeURIComponent(agentId) + '/chat/abort', {});
105
+ },
106
+ clear: function(agentId) {
107
+ return _json('POST', '/api/agents/' + encodeURIComponent(agentId) + '/chat/clear', {});
108
+ }
109
+ },
110
+ isEnabled: function(agentId) {
111
+ return _json('GET', '/api/agents?enabled=true').then(function(agents) {
112
+ return agents.some(function(a) { return a.id === agentId; });
113
+ });
114
+ },
115
+ getCapabilities: function(agentId) {
116
+ return _json('GET', '/api/agents').then(function(agents) {
117
+ var agent = agents.find(function(a) { return a.id === agentId; });
118
+ return agent ? (agent.capabilities || {}) : null;
119
+ });
120
+ }
121
+ };
122
+ })();
@@ -0,0 +1,48 @@
1
+ /**
2
+ * connector.v3.js — External service connector calls
3
+ *
4
+ * Creates: synthos.connector
5
+ */
6
+ (function() {
7
+ window.synthos = window.synthos || {};
8
+ if (window.__synthOSConnector) return;
9
+ window.__synthOSConnector = true;
10
+
11
+ var _json = window.synthos._json;
12
+ if (!_json) {
13
+ _json = function(method, url, body) {
14
+ var opts = { method: method, headers: { 'Content-Type': 'application/json' } };
15
+ if (body !== undefined) opts.body = JSON.stringify(body);
16
+ return fetch(url, opts).then(function(res) {
17
+ var ct = res.headers.get('content-type') || '';
18
+ var isJson = ct.indexOf('application/json') !== -1;
19
+ return (isJson ? res.json() : res.text()).then(function(data) {
20
+ if (!res.ok) { var err = new Error(isJson && data && data.error ? data.error : data); err.status = res.status; throw err; }
21
+ return data;
22
+ });
23
+ });
24
+ };
25
+ }
26
+
27
+ window.synthos.connector = {
28
+ call: function(connector, method, path, opts) {
29
+ var body = { connector: connector, method: method, path: path };
30
+ if (opts) {
31
+ if (opts.headers) body.headers = opts.headers;
32
+ if (opts.body) body.body = opts.body;
33
+ if (opts.query) body.query = opts.query;
34
+ }
35
+ return _json('POST', '/api/connectors', body);
36
+ },
37
+ list: function(opts) {
38
+ var url = '/api/connectors';
39
+ var params = [];
40
+ if (opts) {
41
+ if (opts.category) params.push('category=' + encodeURIComponent(opts.category));
42
+ if (opts.id) params.push('id=' + encodeURIComponent(opts.id));
43
+ }
44
+ if (params.length) url += '?' + params.join('&');
45
+ return _json('GET', url);
46
+ }
47
+ };
48
+ })();
@@ -0,0 +1,188 @@
1
+ /**
2
+ * extract.v3.js — Smart Upload helper (E13)
3
+ *
4
+ * Creates: window.__synthOSExtract
5
+ *
6
+ * Three call shapes:
7
+ * await __synthOSExtract({ schema, accept, prompt?, multiple?, model?, timeout?, persist? }) // picker
8
+ * await __synthOSExtract(file, { schema, ... }) // direct
9
+ * __synthOSExtract.dropZone(el, opts, onResult, onError?) // drag-drop
10
+ *
11
+ * Lazy-init: zero DOM/network until first call.
12
+ */
13
+ (function() {
14
+ window.synthos = window.synthos || {};
15
+ if (window.__synthOSExtract && window.__synthOSExtract.__bound) return;
16
+
17
+ var inFlight = 0;
18
+
19
+ function setInFlight(n) {
20
+ inFlight = n;
21
+ if (window.__synthOSExtract) window.__synthOSExtract.inFlight = n;
22
+ }
23
+
24
+ // File → { mimeType, base64, filename }
25
+ function readFile(file) {
26
+ return new Promise(function(resolve, reject) {
27
+ var reader = new FileReader();
28
+ reader.onerror = function() { reject(reader.error || new Error('File read failed')); };
29
+ reader.onload = function() {
30
+ var url = String(reader.result || '');
31
+ var commaIdx = url.indexOf(',');
32
+ if (commaIdx === -1) { reject(new Error('Failed to parse data URL')); return; }
33
+ resolve({
34
+ mimeType: file.type || 'application/octet-stream',
35
+ base64: url.substring(commaIdx + 1),
36
+ filename: file.name || 'file'
37
+ });
38
+ };
39
+ reader.readAsDataURL(file);
40
+ });
41
+ }
42
+
43
+ // POST /api/extract — returns { ok, json }
44
+ function postExtract(body, timeoutMs) {
45
+ var ac = new AbortController();
46
+ var clientTimeout = (typeof timeoutMs === 'number' && timeoutMs > 0)
47
+ ? Math.min(timeoutMs + 10000, 320000)
48
+ : 130000;
49
+ var abortTimer = setTimeout(function() { ac.abort(); }, clientTimeout);
50
+ return fetch('/api/extract', {
51
+ method: 'POST',
52
+ headers: { 'Content-Type': 'application/json' },
53
+ body: JSON.stringify(body),
54
+ signal: ac.signal
55
+ }).then(function(r) {
56
+ clearTimeout(abortTimer);
57
+ return r.json().then(
58
+ function(json) { return { ok: r.ok, json: json }; },
59
+ function() { return { ok: r.ok, json: { error: 'invalid_response', message: 'Server returned non-JSON response' } }; }
60
+ );
61
+ }, function(err) {
62
+ clearTimeout(abortTimer);
63
+ throw err;
64
+ });
65
+ }
66
+
67
+ function runOne(file, opts) {
68
+ if (!file) return Promise.reject(new Error('No file provided'));
69
+ if (!opts || typeof opts !== 'object') return Promise.reject(new Error('opts required'));
70
+ if (!opts.schema || typeof opts.schema !== 'object') return Promise.reject(new Error('opts.schema is required'));
71
+ var page = (window.pageInfo && window.pageInfo.name) || '';
72
+ if (!page) return Promise.reject(new Error('window.pageInfo.name is not available'));
73
+
74
+ setInFlight(inFlight + 1);
75
+
76
+ var promise = readFile(file).then(function(f) {
77
+ var body = {
78
+ page: page,
79
+ filename: f.filename,
80
+ mimeType: f.mimeType,
81
+ data: f.base64,
82
+ schema: opts.schema
83
+ };
84
+ if (typeof opts.prompt === 'string' && opts.prompt.length > 0) body.prompt = opts.prompt;
85
+ if (typeof opts.model === 'string' && opts.model.length > 0) body.model = opts.model;
86
+ if (opts.persist === true) body.persist = true;
87
+ if (typeof opts.timeout === 'number' && opts.timeout > 0) body.timeout = opts.timeout;
88
+ return postExtract(body, opts.timeout);
89
+ }).then(function(resp) {
90
+ if (!resp.ok) {
91
+ var err = new Error((resp.json && resp.json.message) || 'Extraction failed');
92
+ err.code = resp.json && resp.json.error;
93
+ err.modelUsed = resp.json && resp.json.modelUsed;
94
+ throw err;
95
+ }
96
+ var result = { data: resp.json.data, file: file, modelUsed: resp.json.modelUsed };
97
+ if (resp.json.savedFile) result.savedFile = resp.json.savedFile;
98
+ return result;
99
+ });
100
+
101
+ return promise.then(function(v) {
102
+ setInFlight(inFlight - 1);
103
+ return v;
104
+ }, function(err) {
105
+ setInFlight(inFlight - 1);
106
+ throw err;
107
+ });
108
+ }
109
+
110
+ function pickFiles(opts) {
111
+ return new Promise(function(resolve) {
112
+ var input = document.createElement('input');
113
+ input.type = 'file';
114
+ input.style.display = 'none';
115
+ if (typeof opts.accept === 'string' && opts.accept.length > 0) input.accept = opts.accept;
116
+ if (opts.multiple === true) input.multiple = true;
117
+ document.body.appendChild(input);
118
+
119
+ var resolved = false;
120
+ function done(value) {
121
+ if (resolved) return;
122
+ resolved = true;
123
+ try { input.remove(); } catch (e) { /* ignore */ }
124
+ resolve(value);
125
+ }
126
+ input.addEventListener('change', function() {
127
+ if (input.files && input.files.length > 0) {
128
+ done(Array.prototype.slice.call(input.files));
129
+ } else {
130
+ done(null);
131
+ }
132
+ });
133
+ input.addEventListener('cancel', function() { done(null); });
134
+ input.click();
135
+ });
136
+ }
137
+
138
+ function extract(fileOrOpts, maybeOpts) {
139
+ // Direct mode: extract(file, opts)
140
+ if (fileOrOpts instanceof Blob) {
141
+ var file = fileOrOpts;
142
+ if (!(file instanceof File)) {
143
+ file = new File([file], 'upload', { type: file.type || 'application/octet-stream' });
144
+ }
145
+ return runOne(file, maybeOpts || {});
146
+ }
147
+ // Picker mode: extract(opts)
148
+ var opts = fileOrOpts || {};
149
+ if (!opts.schema) return Promise.reject(new Error('opts.schema is required'));
150
+ return pickFiles(opts).then(function(files) {
151
+ if (!files) return null;
152
+ if (opts.multiple === true) {
153
+ return Promise.all(files.map(function(f) { return runOne(f, opts); }));
154
+ }
155
+ return runOne(files[0], opts);
156
+ });
157
+ }
158
+
159
+ extract.dropZone = function(el, opts, onResult, onError) {
160
+ if (!el) return function() { /* no-op */ };
161
+ function over(e) { e.preventDefault(); e.stopPropagation(); }
162
+ function drop(e) {
163
+ e.preventDefault(); e.stopPropagation();
164
+ var dt = e.dataTransfer;
165
+ if (!dt || !dt.files || dt.files.length === 0) return;
166
+ var files = Array.prototype.slice.call(dt.files);
167
+ for (var i = 0; i < files.length; i++) {
168
+ (function(f) {
169
+ runOne(f, opts).then(function(r) {
170
+ if (typeof onResult === 'function') onResult(r);
171
+ }, function(err) {
172
+ if (typeof onError === 'function') onError(err, f);
173
+ });
174
+ })(files[i]);
175
+ }
176
+ }
177
+ el.addEventListener('dragover', over);
178
+ el.addEventListener('drop', drop);
179
+ return function unsubscribe() {
180
+ el.removeEventListener('dragover', over);
181
+ el.removeEventListener('drop', drop);
182
+ };
183
+ };
184
+
185
+ extract.inFlight = 0;
186
+ extract.__bound = true;
187
+ window.__synthOSExtract = extract;
188
+ })();