@notis_ai/cli 0.2.18 → 0.2.20

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 (395) hide show
  1. package/README.md +542 -146
  2. package/bin/check-runtime.js +15 -0
  3. package/bin/notis.js +2 -0
  4. package/config/notis_app_design_rules.json +320 -0
  5. package/config/portal-route-roots.json +45 -0
  6. package/dist/agent-hooks/notis-agent-hook.mjs +42325 -18273
  7. package/dist/base-skills/notis-cli/.notis-base-skill.json +1 -0
  8. package/dist/base-skills/notis-cli/SKILL.md +51 -280
  9. package/dist/base-skills/notis-cli/references/app-delivery.md +17 -0
  10. package/dist/base-skills/notis-cli/references/intelligence.md +94 -0
  11. package/dist/base-skills/notis-cli/references/native-databases.md +21 -0
  12. package/dist/base-skills/notis-cli/references/tool-examples.md +56 -0
  13. package/dist/base-skills/notis-cli/references/troubleshooting.md +67 -0
  14. package/dist/base-skills/notis-query/.notis-base-skill.json +1 -0
  15. package/dist/base-skills/notis-query/SKILL.md +35 -699
  16. package/dist/base-skills/notis-query/references/database-discovery.md +59 -0
  17. package/dist/base-skills/notis-query/references/documents.md +74 -0
  18. package/dist/base-skills/notis-query/references/query.md +76 -0
  19. package/dist/base-skills/notis-spaces/.notis-base-skill.json +1 -0
  20. package/dist/base-skills/notis-spaces/SKILL.md +218 -0
  21. package/dist/base-skills/notis-spaces/references/architecture.md +116 -0
  22. package/dist/base-skills/notis-spaces/references/context.md +81 -0
  23. package/dist/base-skills/notis-spaces/references/design.md +141 -0
  24. package/dist/base-skills/notis-spaces/references/fixtures.md +29 -0
  25. package/dist/base-skills/notis-spaces/references/memory.md +58 -0
  26. package/dist/base-skills/notis-spaces/references/reading.md +73 -0
  27. package/dist/base-skills/notis-spaces/references/release.md +120 -0
  28. package/dist/base-skills/notis-spaces/references/reports.md +77 -0
  29. package/dist/base-skills/notis-spaces/references/sdk.md +273 -0
  30. package/dist/base-skills/notis-spaces/references/store.md +118 -0
  31. package/dist/base-skills/notis-spaces/references/troubleshooting.md +28 -0
  32. package/dist/base-skills/notis-spaces/references/views.md +229 -0
  33. package/{template/packages → dist}/sdk/package.json +9 -10
  34. package/dist/sdk/src/agentContext.ts +36 -0
  35. package/dist/sdk/src/bundleModule.ts +175 -0
  36. package/dist/sdk/src/components/Dialog.tsx +103 -0
  37. package/dist/sdk/src/components/DocumentEditor.tsx +113 -0
  38. package/dist/sdk/src/components/DocumentPage.tsx +184 -0
  39. package/{template/packages → dist}/sdk/src/components/Markdown.tsx +9 -3
  40. package/{template/packages → dist}/sdk/src/components/MarkdownEditor.tsx +26 -5
  41. package/{template/packages → dist}/sdk/src/components/MultiSelectActionBar.tsx +95 -12
  42. package/{template/packages → dist}/sdk/src/components/MultiSelectCheckbox.tsx +4 -2
  43. package/dist/sdk/src/components/NotisCommentBoundary.tsx +172 -0
  44. package/{template/packages → dist}/sdk/src/components/NotisSelectionBoundary.tsx +9 -5
  45. package/dist/sdk/src/components/RecordComponents.tsx +111 -0
  46. package/dist/sdk/src/components/Skeleton.tsx +38 -0
  47. package/dist/sdk/src/config.ts +31 -0
  48. package/{template/packages → dist}/sdk/src/documents.ts +21 -6
  49. package/dist/sdk/src/hooks/useAction.ts +28 -0
  50. package/dist/sdk/src/hooks/useAgentContext.ts +23 -0
  51. package/{template/packages → dist}/sdk/src/hooks/useBackend.ts +3 -2
  52. package/dist/sdk/src/hooks/useCloudComputer.ts +94 -0
  53. package/dist/sdk/src/hooks/useCloudComputerShell.ts +114 -0
  54. package/{template/packages → dist}/sdk/src/hooks/useCollectionInteractions.ts +157 -147
  55. package/dist/sdk/src/hooks/useDatabaseSchema.ts +50 -0
  56. package/{template/packages → dist}/sdk/src/hooks/useDatabaseSubscription.ts +2 -2
  57. package/dist/sdk/src/hooks/useDocument.ts +51 -0
  58. package/{template/packages → dist}/sdk/src/hooks/useDocuments.ts +25 -59
  59. package/{template/packages → dist}/sdk/src/hooks/useHandover.ts +7 -7
  60. package/dist/sdk/src/hooks/useLongPressSelection.ts +79 -0
  61. package/dist/sdk/src/hooks/useMarqueeSelection.ts +194 -0
  62. package/{template/packages → dist}/sdk/src/hooks/useMultiSelect.ts +2 -8
  63. package/dist/sdk/src/hooks/useNativeDocumentBody.ts +50 -0
  64. package/dist/sdk/src/hooks/useNativeDocuments.ts +143 -0
  65. package/{template/packages → dist}/sdk/src/hooks/useNotis.ts +6 -1
  66. package/dist/sdk/src/hooks/useNotisNavigation.ts +70 -0
  67. package/dist/sdk/src/hooks/useQuery.ts +81 -0
  68. package/dist/sdk/src/hooks/useToolQuery.ts +12 -0
  69. package/dist/sdk/src/hooks/useTopBarSearch.ts +102 -0
  70. package/dist/sdk/src/hooks/useTopBarTitleLeaf.ts +75 -0
  71. package/{template/packages → dist}/sdk/src/hooks/useUpsertDocument.ts +1 -1
  72. package/dist/sdk/src/hooks/useViewParams.ts +195 -0
  73. package/dist/sdk/src/hooks/useViewerReads.ts +129 -0
  74. package/{template/packages → dist}/sdk/src/index.ts +64 -1
  75. package/{template/packages → dist}/sdk/src/interactions/actions.ts +14 -1
  76. package/{template/packages → dist}/sdk/src/interactions/shortcuts.tsx +129 -23
  77. package/dist/sdk/src/interactions/visibility.ts +13 -0
  78. package/{template/packages → dist}/sdk/src/interactions.ts +5 -1
  79. package/dist/sdk/src/nativeData.ts +39 -0
  80. package/{template/packages → dist}/sdk/src/provider.tsx +9 -4
  81. package/dist/sdk/src/queryCache.ts +292 -0
  82. package/dist/sdk/src/queryErrors.ts +51 -0
  83. package/dist/sdk/src/runtime.ts +675 -0
  84. package/dist/sdk/src/runtimeModules.ts +33 -0
  85. package/dist/sdk/src/space.ts +442 -0
  86. package/dist/sdk/src/standardViewParams.ts +36 -0
  87. package/{template/packages → dist}/sdk/src/styles.css +81 -16
  88. package/dist/sdk/src/tailwind.ts +66 -0
  89. package/dist/sdk/src/ui/charts/RenderChartData.tsx +25 -0
  90. package/dist/sdk/src/ui/engine/core.ts +392 -0
  91. package/dist/sdk/src/ui/engine/dom.ts +183 -0
  92. package/dist/sdk/src/ui/engine/hooks.ts +195 -0
  93. package/dist/sdk/src/ui/engine/instance.ts +63 -0
  94. package/dist/sdk/src/ui/engine/keycapContext.ts +2 -0
  95. package/dist/sdk/src/ui/engine/registry.ts +262 -0
  96. package/dist/sdk/src/ui/engine/types.ts +62 -0
  97. package/dist/sdk/src/ui/icons.tsx +91 -0
  98. package/dist/sdk/src/ui/util.ts +83 -0
  99. package/dist/sdk/src/viewPeriod.ts +26 -0
  100. package/dist/sdk/src/vite.ts +92 -0
  101. package/dist/sdk/src/words/actions.ts +295 -0
  102. package/dist/sdk/src/words/clashes.ts +158 -0
  103. package/dist/sdk/src/words/format.ts +136 -0
  104. package/dist/sdk/src/words/index.ts +13 -0
  105. package/dist/sdk/src/words/keymap.ts +72 -0
  106. package/dist/sdk/src/words/keys.ts +297 -0
  107. package/dist/sdk/src/words/shell.ts +46 -0
  108. package/dist/sdk/src/words/types.ts +65 -0
  109. package/dist/skill-sync/index.js +832 -151
  110. package/dist/skill-sync/index.js.map +4 -4
  111. package/dist/skill-sync-worker.mjs +3941 -0
  112. package/dist/space-harness/host.js +1460 -0
  113. package/dist/space-sdk/dist/chunk-ZSN57ATH.js +5 -0
  114. package/dist/space-sdk/dist/index.js +15 -0
  115. package/dist/space-sdk/dist/ui.js +18 -0
  116. package/dist/space-sdk/package.json +33 -0
  117. package/dist/space-sdk/src/agentContext.d.ts +36 -0
  118. package/dist/space-sdk/src/components/Dialog.d.ts +20 -0
  119. package/dist/space-sdk/src/components/DocumentEditor.d.ts +46 -0
  120. package/dist/space-sdk/src/components/DocumentPage.d.ts +53 -0
  121. package/dist/space-sdk/src/components/Markdown.d.ts +18 -0
  122. package/dist/space-sdk/src/components/MarkdownEditor.d.ts +11 -0
  123. package/dist/space-sdk/src/components/MultiSelectActionBar.d.ts +31 -0
  124. package/dist/space-sdk/src/components/MultiSelectCheckbox.d.ts +14 -0
  125. package/dist/space-sdk/src/components/MultiSelectDragOverlay.d.ts +8 -0
  126. package/dist/space-sdk/src/components/NotisCommentBoundary.d.ts +36 -0
  127. package/dist/space-sdk/src/components/NotisSelectionBoundary.d.ts +16 -0
  128. package/dist/space-sdk/src/components/RecordComponents.d.ts +64 -0
  129. package/dist/space-sdk/src/components/ShortcutHints.d.ts +12 -0
  130. package/dist/space-sdk/src/components/Skeleton.d.ts +23 -0
  131. package/dist/space-sdk/src/config.ts +31 -0
  132. package/dist/space-sdk/src/documents.d.ts +59 -0
  133. package/dist/space-sdk/src/hooks/useAction.d.ts +8 -0
  134. package/dist/space-sdk/src/hooks/useActiveResource.d.ts +3 -0
  135. package/dist/space-sdk/src/hooks/useAgentContext.d.ts +7 -0
  136. package/dist/space-sdk/src/hooks/useBackend.d.ts +23 -0
  137. package/dist/space-sdk/src/hooks/useCloudComputer.d.ts +45 -0
  138. package/dist/space-sdk/src/hooks/useCloudComputerShell.d.ts +49 -0
  139. package/dist/space-sdk/src/hooks/useCollectionInteractions.d.ts +118 -0
  140. package/dist/space-sdk/src/hooks/useDatabaseSchema.d.ts +14 -0
  141. package/dist/space-sdk/src/hooks/useDatabaseSubscription.d.ts +26 -0
  142. package/dist/space-sdk/src/hooks/useDocument.d.ts +22 -0
  143. package/dist/space-sdk/src/hooks/useDocuments.d.ts +31 -0
  144. package/dist/space-sdk/src/hooks/useHandover.d.ts +43 -0
  145. package/dist/space-sdk/src/hooks/useLongPressSelection.d.ts +9 -0
  146. package/dist/space-sdk/src/hooks/useMarqueeSelection.d.ts +57 -0
  147. package/dist/space-sdk/src/hooks/useMultiSelect.d.ts +51 -0
  148. package/dist/space-sdk/src/hooks/useNativeDocumentBody.d.ts +24 -0
  149. package/dist/space-sdk/src/hooks/useNativeDocuments.d.ts +55 -0
  150. package/dist/space-sdk/src/hooks/useNotis.d.ts +25 -0
  151. package/dist/space-sdk/src/hooks/useNotisNavigation.d.ts +33 -0
  152. package/dist/space-sdk/src/hooks/useQuery.d.ts +22 -0
  153. package/dist/space-sdk/src/hooks/useTool.d.ts +20 -0
  154. package/dist/space-sdk/src/hooks/useToolQuery.d.ts +3 -0
  155. package/dist/space-sdk/src/hooks/useTools.d.ts +15 -0
  156. package/dist/space-sdk/src/hooks/useTopBarSearch.d.ts +48 -0
  157. package/dist/space-sdk/src/hooks/useTopBarTitleLeaf.d.ts +24 -0
  158. package/dist/space-sdk/src/hooks/useUpsertDocument.d.ts +27 -0
  159. package/dist/space-sdk/src/hooks/useViewParams.d.ts +76 -0
  160. package/dist/space-sdk/src/hooks/useViewerReads.d.ts +38 -0
  161. package/dist/space-sdk/src/index.d.ts +98 -0
  162. package/dist/space-sdk/src/interactions/actions.d.ts +33 -0
  163. package/dist/space-sdk/src/interactions/shortcuts.d.ts +42 -0
  164. package/dist/space-sdk/src/interactions/visibility.d.ts +2 -0
  165. package/dist/space-sdk/src/nativeData.d.ts +66 -0
  166. package/dist/space-sdk/src/provider.d.ts +17 -0
  167. package/dist/space-sdk/src/queryCache.d.ts +45 -0
  168. package/dist/space-sdk/src/queryErrors.ts +51 -0
  169. package/dist/space-sdk/src/runtime.d.ts +615 -0
  170. package/dist/space-sdk/src/runtimeModules.ts +33 -0
  171. package/dist/space-sdk/src/space.ts +442 -0
  172. package/dist/space-sdk/src/standardViewParams.d.ts +15 -0
  173. package/dist/space-sdk/src/tailwind-candidates.d.ts +3418 -0
  174. package/dist/space-sdk/src/tailwind.ts +66 -0
  175. package/dist/space-sdk/src/ui/actions/ActionToast.d.ts +15 -0
  176. package/dist/space-sdk/src/ui/actions/actionWords.d.ts +16 -0
  177. package/dist/space-sdk/src/ui/actions/index.d.ts +7 -0
  178. package/dist/space-sdk/src/ui/actions/useActions.d.ts +69 -0
  179. package/dist/space-sdk/src/ui/actions/useToast.d.ts +41 -0
  180. package/dist/space-sdk/src/ui/blocks/Tabs.d.ts +139 -0
  181. package/dist/space-sdk/src/ui/blocks/blocks.d.ts +217 -0
  182. package/dist/space-sdk/src/ui/blocks/index.d.ts +4 -0
  183. package/dist/space-sdk/src/ui/board/BoardView.d.ts +36 -0
  184. package/dist/space-sdk/src/ui/board/boardModel.d.ts +46 -0
  185. package/dist/space-sdk/src/ui/board/boardWords.d.ts +9 -0
  186. package/dist/space-sdk/src/ui/board/index.d.ts +5 -0
  187. package/dist/space-sdk/src/ui/calendar/CalendarView.d.ts +49 -0
  188. package/dist/space-sdk/src/ui/calendar/DayPicker.d.ts +23 -0
  189. package/dist/space-sdk/src/ui/calendar/calendarMath.d.ts +81 -0
  190. package/dist/space-sdk/src/ui/charts/Chart.d.ts +203 -0
  191. package/dist/space-sdk/src/ui/charts/ChartTable.d.ts +37 -0
  192. package/dist/space-sdk/src/ui/charts/RenderChartData.d.ts +16 -0
  193. package/dist/space-sdk/src/ui/charts/StatRow.d.ts +59 -0
  194. package/dist/space-sdk/src/ui/charts/chartData.d.ts +84 -0
  195. package/dist/space-sdk/src/ui/comments/CommentPane.d.ts +58 -0
  196. package/dist/space-sdk/src/ui/comments/commentModel.d.ts +157 -0
  197. package/dist/space-sdk/src/ui/comments/commentWords.d.ts +60 -0
  198. package/dist/space-sdk/src/ui/comments/index.d.ts +4 -0
  199. package/dist/space-sdk/src/ui/comments/useComments.d.ts +146 -0
  200. package/dist/space-sdk/src/ui/engine/HelpSheet.d.ts +12 -0
  201. package/dist/space-sdk/src/ui/engine/KeyboardEngine.d.ts +27 -0
  202. package/dist/space-sdk/src/ui/engine/core.d.ts +73 -0
  203. package/dist/space-sdk/src/ui/engine/hooks.d.ts +64 -0
  204. package/dist/space-sdk/src/ui/engine/index.d.ts +14 -0
  205. package/dist/space-sdk/src/ui/engine/instance.d.ts +21 -0
  206. package/dist/space-sdk/src/ui/engine/keycapContext.d.ts +2 -0
  207. package/dist/space-sdk/src/ui/engine/registry.d.ts +77 -0
  208. package/dist/space-sdk/src/ui/engine/step.d.ts +11 -0
  209. package/dist/space-sdk/src/ui/engine/types.d.ts +54 -0
  210. package/dist/space-sdk/src/ui/fields/fieldWords.d.ts +56 -0
  211. package/dist/space-sdk/src/ui/fields/fields.d.ts +162 -0
  212. package/dist/space-sdk/src/ui/fields/index.d.ts +5 -0
  213. package/dist/space-sdk/src/ui/fields/useFieldDraft.d.ts +22 -0
  214. package/dist/space-sdk/src/ui/gallery/AttachmentGallery.d.ts +53 -0
  215. package/dist/space-sdk/src/ui/gallery/ImageViewer.d.ts +27 -0
  216. package/dist/space-sdk/src/ui/gallery/galleryWords.d.ts +95 -0
  217. package/dist/space-sdk/src/ui/gallery/index.d.ts +5 -0
  218. package/dist/space-sdk/src/ui/icons.d.ts +13 -0
  219. package/dist/space-sdk/src/ui/index.d.ts +54 -0
  220. package/dist/space-sdk/src/ui/keycap/Keycap.d.ts +22 -0
  221. package/dist/space-sdk/src/ui/keycap/index.d.ts +2 -0
  222. package/dist/space-sdk/src/ui/layout/Panels.d.ts +50 -0
  223. package/dist/space-sdk/src/ui/layout/chatPanelEdge.d.ts +77 -0
  224. package/dist/space-sdk/src/ui/layout/index.d.ts +5 -0
  225. package/dist/space-sdk/src/ui/layout/panelMath.d.ts +91 -0
  226. package/dist/space-sdk/src/ui/list/ListReader.d.ts +380 -0
  227. package/dist/space-sdk/src/ui/list/Row.d.ts +145 -0
  228. package/dist/space-sdk/src/ui/list/SelectionBar.d.ts +65 -0
  229. package/dist/space-sdk/src/ui/list/index.d.ts +14 -0
  230. package/dist/space-sdk/src/ui/list/rowState.d.ts +22 -0
  231. package/dist/space-sdk/src/ui/list/useListKeys.d.ts +89 -0
  232. package/dist/space-sdk/src/ui/list/useReorder.d.ts +86 -0
  233. package/dist/space-sdk/src/ui/list/useSelection.d.ts +90 -0
  234. package/dist/space-sdk/src/ui/open/OpenAsMenu.d.ts +15 -0
  235. package/dist/space-sdk/src/ui/open/index.d.ts +6 -0
  236. package/dist/space-sdk/src/ui/open/openModeStore.d.ts +39 -0
  237. package/dist/space-sdk/src/ui/open/useOpenMode.d.ts +17 -0
  238. package/dist/space-sdk/src/ui/overlay/Menu.d.ts +88 -0
  239. package/dist/space-sdk/src/ui/overlay/Popover.d.ts +28 -0
  240. package/dist/space-sdk/src/ui/overlay/Tooltip.d.ts +19 -0
  241. package/dist/space-sdk/src/ui/overlay/index.d.ts +9 -0
  242. package/dist/space-sdk/src/ui/overlay/layerRoot.d.ts +24 -0
  243. package/dist/space-sdk/src/ui/overlay/position.d.ts +31 -0
  244. package/dist/space-sdk/src/ui/period/PeriodPicker.d.ts +30 -0
  245. package/dist/space-sdk/src/ui/period/dateFormat.d.ts +50 -0
  246. package/dist/space-sdk/src/ui/period/dateWords.d.ts +88 -0
  247. package/dist/space-sdk/src/ui/period/periods.d.ts +70 -0
  248. package/dist/space-sdk/src/ui/period/usePeriod.d.ts +23 -0
  249. package/dist/space-sdk/src/ui/present/index.d.ts +3 -0
  250. package/dist/space-sdk/src/ui/present/presentWords.d.ts +27 -0
  251. package/dist/space-sdk/src/ui/present/screens.d.ts +36 -0
  252. package/dist/space-sdk/src/ui/present/useAudienceScreen.d.ts +38 -0
  253. package/dist/space-sdk/src/ui/styles.d.ts +21 -0
  254. package/dist/space-sdk/src/ui/timeline/TimelineView.d.ts +44 -0
  255. package/dist/space-sdk/src/ui/timeline/timelineMath.d.ts +123 -0
  256. package/dist/space-sdk/src/viewPeriod.d.ts +8 -0
  257. package/dist/space-sdk/src/vite.ts +92 -0
  258. package/dist/space-sdk/src/words/actions.ts +295 -0
  259. package/dist/space-sdk/src/words/clashes.ts +158 -0
  260. package/dist/space-sdk/src/words/format.ts +136 -0
  261. package/dist/space-sdk/src/words/index.ts +13 -0
  262. package/dist/space-sdk/src/words/keymap.ts +72 -0
  263. package/dist/space-sdk/src/words/keys.ts +297 -0
  264. package/dist/space-sdk/src/words/shell.ts +46 -0
  265. package/dist/space-sdk/src/words/types.ts +65 -0
  266. package/dist/view-renderer/dist/host.css +1 -0
  267. package/dist/view-renderer/dist/host.js +2374 -0
  268. package/dist/view-renderer/dist/theme.css +73 -0
  269. package/dist/view-renderer/src/dom.js +212 -0
  270. package/dist/view-renderer/src/errors.js +8 -0
  271. package/dist/view-renderer/src/host.tsx +250 -0
  272. package/dist/view-renderer/src/index.js +4 -0
  273. package/dist/view-renderer/src/png.js +213 -0
  274. package/dist/view-renderer/src/pool.js +110 -0
  275. package/dist/view-renderer/src/remote-broker.js +59 -0
  276. package/dist/view-renderer/src/renderer.js +279 -0
  277. package/package.json +21 -11
  278. package/skills/notis-cli/AGENT_INSTRUCTIONS.md +63 -12
  279. package/skills/notis-onboarding/BRIEF.md +14 -9
  280. package/skills/notis-query/cli.md +1 -1
  281. package/skills/notis-spaces/cli.md +540 -0
  282. package/src/cli.js +8 -8
  283. package/src/command-specs/agents.js +121 -8
  284. package/src/command-specs/auth.js +3 -3
  285. package/src/command-specs/diagnostics.js +97 -20
  286. package/src/command-specs/documents.js +158 -0
  287. package/src/command-specs/files.js +29 -0
  288. package/src/command-specs/handover.js +331 -79
  289. package/src/command-specs/helpers.js +50 -40
  290. package/src/command-specs/index.js +14 -5
  291. package/src/command-specs/meta.js +38 -9
  292. package/src/command-specs/onboarding.js +1 -1
  293. package/src/command-specs/profile.js +42 -1
  294. package/src/command-specs/skills.js +314 -9
  295. package/src/command-specs/smoke.js +16 -4
  296. package/src/command-specs/spaces.js +783 -0
  297. package/src/command-specs/tools.js +118 -21
  298. package/src/command-specs/version-history.js +20 -0
  299. package/src/command-specs/views.js +69 -0
  300. package/src/runtime/agent-browser.js +178 -267
  301. package/src/runtime/agent-setup.js +172 -13
  302. package/src/runtime/app-boundary-validator.js +338 -2
  303. package/src/runtime/app-data-literals.js +82 -0
  304. package/src/runtime/app-platform.js +750 -1570
  305. package/src/runtime/auth-recovery.js +17 -0
  306. package/src/runtime/base-skills.d.ts +11 -0
  307. package/src/runtime/base-skills.js +100 -3
  308. package/src/runtime/computer-identity.d.ts +30 -0
  309. package/src/runtime/computer-identity.js +151 -0
  310. package/src/runtime/config-lock.js +135 -0
  311. package/src/runtime/confined-space-build.js +74 -0
  312. package/src/runtime/confined-space-verify.js +49 -0
  313. package/src/runtime/delegated-context.js +5 -21
  314. package/src/runtime/native-record-files.js +47 -0
  315. package/src/runtime/oauth.js +342 -31
  316. package/src/runtime/profiles.js +19 -112
  317. package/src/runtime/retired-sdk-files.js +24 -0
  318. package/src/runtime/retry.js +150 -0
  319. package/src/runtime/skill-sync/cloud-client.ts +33 -8
  320. package/src/runtime/skill-sync/index.ts +443 -106
  321. package/src/runtime/skill-sync/local-scanner.ts +248 -32
  322. package/src/runtime/skill-sync/native-identity.ts +102 -0
  323. package/src/runtime/skill-sync/native-plan.ts +70 -0
  324. package/src/runtime/skill-sync/symlink-manager.ts +66 -16
  325. package/src/runtime/skill-sync/sync-plan.ts +34 -2
  326. package/src/runtime/skill-sync/types.ts +54 -0
  327. package/src/runtime/skill-sync/write-cloud-skill.ts +4 -4
  328. package/src/runtime/skill-sync-service.js +109 -0
  329. package/src/runtime/source-root.js +32 -0
  330. package/src/runtime/space-collection-scaffold.js +107 -0
  331. package/src/runtime/space-database-structures.js +229 -0
  332. package/src/runtime/space-fixture-broker.js +68 -0
  333. package/src/runtime/space-lock.js +337 -0
  334. package/src/runtime/space-platform.js +133 -0
  335. package/src/runtime/space-source.js +290 -0
  336. package/src/runtime/space-test-server.js +354 -0
  337. package/src/runtime/space-verification.js +94 -0
  338. package/src/runtime/space-verify-browser-worker.js +51 -0
  339. package/src/runtime/space-view-manifest.js +368 -0
  340. package/src/runtime/sync-skills.d.ts +5 -1
  341. package/src/runtime/sync-skills.js +11 -2
  342. package/src/runtime/tool-confirmation.js +138 -0
  343. package/src/runtime/transport.js +118 -24
  344. package/src/runtime/upsell.js +219 -0
  345. package/src/runtime/view-render.js +49 -0
  346. package/src/skill-sync-worker-entry.js +2 -0
  347. package/src/skill-sync-worker.js +114 -0
  348. package/src/space-harness-host.ts +122 -0
  349. package/template/.harness/index.html.tmpl +9 -352
  350. package/template/app/globals.css +29 -3
  351. package/template/app/layout.tsx +2 -6
  352. package/template/components/ui/badge.tsx +7 -4
  353. package/template/components/ui/button.tsx +1 -1
  354. package/template/components/ui/native-select.tsx +24 -0
  355. package/template/notis.config.ts +4 -36
  356. package/template/package-lock.json +1800 -1867
  357. package/template/package.json +16 -14
  358. package/template/postcss.config.mjs +1 -1
  359. package/template/tailwind.config.ts +1 -6
  360. package/template/tsconfig.json +1 -0
  361. package/template/vite.config.ts +2 -2
  362. package/dist/base-skills/notis-apps/SKILL.md +0 -613
  363. package/skills/notis-apps/cli.md +0 -285
  364. package/src/command-specs/apps.js +0 -3011
  365. package/src/runtime/app-changelog.js +0 -79
  366. package/src/runtime/app-dev-consumers.js +0 -154
  367. package/src/runtime/app-dev-host-lock.js +0 -80
  368. package/src/runtime/app-dev-process-identity.js +0 -111
  369. package/src/runtime/app-dev-roots.js +0 -284
  370. package/src/runtime/app-dev-server.js +0 -1140
  371. package/src/runtime/app-dev-sessions.js +0 -185
  372. package/src/runtime/app-registry-scaffolds.js +0 -367
  373. package/src/runtime/assets/store-screenshot-dark.png +0 -0
  374. package/src/runtime/cli-mode.generated.js +0 -5
  375. package/src/runtime/cli-mode.js +0 -34
  376. package/src/runtime/store-screenshot.js +0 -143
  377. package/template/CHANGELOG.md +0 -5
  378. package/template/app/page.tsx +0 -60
  379. package/template/components/ui/card.tsx +0 -56
  380. package/template/packages/sdk/src/components/DocumentEditor.tsx +0 -103
  381. package/template/packages/sdk/src/config.ts +0 -259
  382. package/template/packages/sdk/src/hooks/useCloudComputer.ts +0 -97
  383. package/template/packages/sdk/src/hooks/useDatabaseSchema.ts +0 -85
  384. package/template/packages/sdk/src/hooks/useDocument.ts +0 -78
  385. package/template/packages/sdk/src/hooks/useNotisNavigation.ts +0 -52
  386. package/template/packages/sdk/src/hooks/useTopBarSearch.ts +0 -73
  387. package/template/packages/sdk/src/runtime.ts +0 -439
  388. package/template/packages/sdk/src/vite.ts +0 -56
  389. package/template/packages/sdk/tsconfig.json +0 -15
  390. /package/{template/packages → dist}/sdk/src/components/MultiSelectDragOverlay.tsx +0 -0
  391. /package/{template/packages → dist}/sdk/src/components/ShortcutHints.tsx +0 -0
  392. /package/{template/packages → dist}/sdk/src/hooks/useActiveResource.ts +0 -0
  393. /package/{template/packages → dist}/sdk/src/hooks/useTool.ts +0 -0
  394. /package/{template/packages → dist}/sdk/src/hooks/useTools.ts +0 -0
  395. /package/{template/packages → dist}/sdk/src/ui.ts +0 -0
@@ -0,0 +1,33 @@
1
+ /**
2
+ * The runtime contract between a Space bundle and its host (Spaces protocol 2).
3
+ *
4
+ * A Space bundle never contains SDK code. Its build externalizes these
5
+ * specifiers and the host (Portal, Site, CLI verify, view renderer) provides
6
+ * them as window globals, set from the module objects the host itself imports,
7
+ * so every Space on a page shares one SDK instance with the host.
8
+ *
9
+ * React is provided the same way (`window.React`, `window.ReactDOM`,
10
+ * `window.ReactDOMClient`, `window.__ReactJSXRuntime`).
11
+ *
12
+ * Pure data: the Vite config and the bundle loader both read it.
13
+ */
14
+ export const NOTIS_SDK_HOST_MODULES = Object.freeze({
15
+ '@notis/sdk': '__NotisSDK',
16
+ '@notis/sdk/ui': '__NotisSDKUI',
17
+ } as const);
18
+
19
+ export type NotisSdkHostModule = keyof typeof NOTIS_SDK_HOST_MODULES;
20
+ export type NotisSdkHostGlobal = (typeof NOTIS_SDK_HOST_MODULES)[NotisSdkHostModule];
21
+
22
+ export const REACT_HOST_MODULES = Object.freeze([
23
+ 'react', 'react-dom', 'react-dom/client', 'react/jsx-runtime', 'react/jsx-dev-runtime',
24
+ ] as const);
25
+
26
+ /**
27
+ * The only other `@notis/sdk` entries a Space may import. They are pure or
28
+ * build-time only, so the Space build inlines them (or runs them in Node); a
29
+ * built bundle never imports them at runtime.
30
+ */
31
+ export const NOTIS_SDK_BUNDLED_MODULES = Object.freeze([
32
+ '@notis/sdk/words', '@notis/sdk/config', '@notis/sdk/vite',
33
+ ] as const);
@@ -0,0 +1,442 @@
1
+ /** Portable Space source contracts. Grants and account identities are host-owned. */
2
+ import type { NotisRuntime, ToolInputSchema } from './runtime';
3
+ import type { NativeFilter, NativeMutationReceipt, NativeQuery } from './nativeData';
4
+ import { SdkQueryError, type QueryErrorKey } from './queryErrors';
5
+
6
+ export type SpaceJson = null | boolean | number | string | SpaceJson[] | { [key: string]: SpaceJson };
7
+
8
+ /** Exact server template format; slots are data, never JavaScript inference. */
9
+ export interface SpaceActionTemplate {
10
+ tool: string;
11
+ inputs: ToolInputSchema;
12
+ arguments: Record<string, SpaceJson>;
13
+ }
14
+
15
+ /**
16
+ * Explorer reads with the signed-in viewer's own authority: everything that viewer can
17
+ * already open, never the Space owner's or an action issuer's. Read-only, no grant, no
18
+ * billing, never on a Site or anonymous link.
19
+ */
20
+ export type SpaceViewerReadFamily = 'databases' | 'skills';
21
+ export type SpaceViewerReadOperation = 'list_databases' | 'get_database' | 'query_database' | 'list_skills' | 'get_skill';
22
+ export const SPACE_VIEWER_READ_OPERATIONS: Readonly<Record<SpaceViewerReadOperation, SpaceViewerReadFamily>> = Object.freeze({
23
+ list_databases: 'databases', get_database: 'databases', query_database: 'databases', list_skills: 'skills', get_skill: 'skills',
24
+ });
25
+
26
+ /**
27
+ * Space cloud computer access, declared as `cloudComputer` in `defineSpace`.
28
+ * `read`: facts only. `shell`: facts, one command, one file write. Always the signed-in viewer's own
29
+ * cloud computer, after that viewer allows it; never on a Site, a link or an agent render.
30
+ */
31
+ export type SpaceCloudComputerLevel = 'read' | 'shell';
32
+ export type SpaceCloudComputerOperation = 'facts' | 'run' | 'upload';
33
+ export interface SpaceCloudComputerStatus {
34
+ level: SpaceCloudComputerLevel;
35
+ approved: boolean;
36
+ /** Why it is not approved: never allowed yet, or the Space changed since you allowed it. */
37
+ reason: 'approval_required' | 'source_changed' | null;
38
+ /** While not approved: the code asking, as the host prompt shows it. It informs the person and decides nothing. */
39
+ release?: SpaceCloudComputerRelease;
40
+ }
41
+ /** Who released the code asking into this Space, and whether it is an unreleased preview. */
42
+ export interface SpaceCloudComputerRelease {
43
+ preview: boolean;
44
+ /** You (with your agents and the CLI), or another person by first name or email; null when not recorded. */
45
+ released_by: { you: boolean; name: string | null } | null;
46
+ /** Copied in from another Space or the Store: the person named applied it and may not have written it. */
47
+ copied: boolean;
48
+ }
49
+ export interface SpaceCloudComputerRunInput {
50
+ command: string; cwd?: string; timeout_ms?: number; max_output_length?: number;
51
+ /**
52
+ * One key per run, kept when the page retries that run: a key that already reached the cloud computer is
53
+ * never run again (`cloud_computer_already_ran`). The host makes one when absent and keeps it for a retry
54
+ * of the same run after an uncertain outcome.
55
+ */
56
+ request_id?: string;
57
+ }
58
+ export interface SpaceCloudComputerRunResult {
59
+ status?: 'success' | 'error' | string; stdout?: string; stderr?: string; exit_code?: number;
60
+ message?: string; code?: string; truncated?: boolean;
61
+ }
62
+ export interface SpaceCloudComputerUploadInput {
63
+ path: string; content: string; content_encoding?: 'base64' | 'utf-8'; overwrite?: boolean; mode?: number;
64
+ /** As for a run: one key per upload, kept when retrying it. */
65
+ request_id?: string;
66
+ }
67
+ export interface SpaceCloudComputerUploadResult { status?: string; path?: string; size?: number; message?: string; code?: string }
68
+ /** Host transport. Approval is only ever given in host UI the person clicks; the view can only ask. */
69
+ export interface SpaceCloudComputerTransport {
70
+ status(): Promise<SpaceCloudComputerStatus>;
71
+ requestApproval(): Promise<SpaceCloudComputerStatus>;
72
+ facts(options?: { refresh?: boolean }): Promise<import('./runtime').CloudComputerFacts>;
73
+ run(input: SpaceCloudComputerRunInput): Promise<SpaceCloudComputerRunResult>;
74
+ upload(input: SpaceCloudComputerUploadInput): Promise<SpaceCloudComputerUploadResult>;
75
+ }
76
+ export const SPACE_CLOUD_COMPUTER_OPERATIONS: Readonly<Record<SpaceCloudComputerOperation, SpaceCloudComputerLevel>> = Object.freeze({
77
+ facts: 'read', run: 'shell', upload: 'shell',
78
+ });
79
+ export function spaceCloudComputerAllows(level: SpaceCloudComputerLevel | undefined, operation: SpaceCloudComputerOperation): boolean {
80
+ const needed = SPACE_CLOUD_COMPUTER_OPERATIONS[operation];
81
+ return level === 'shell' || (level === 'read' && needed === 'read');
82
+ }
83
+
84
+ /** A link the viewer can use (R10); unavailable links are never returned. */
85
+ export interface SpaceViewerLink { space_id: string; space_name: string | null; binding_id: string; alias: string | null }
86
+ export interface SpaceViewerDatabase {
87
+ id: string; name: string | null; slug: string | null; description: string | null;
88
+ /** Direct access of the viewer (own or Team); otherwise reached through `links`. */
89
+ standalone: boolean;
90
+ links: SpaceViewerLink[];
91
+ target: { database_id: string } | { space_id: string; binding: string };
92
+ /** Catalog facts; null when unknown, absent from older servers. */
93
+ updated_at?: string | null;
94
+ /** Active documents (stored count, else live). */
95
+ documents_count?: number | null;
96
+ /** The root Space the database came from (a converted App), when the viewer reaches it. */
97
+ owner_space_id?: string | null;
98
+ owner_space_name?: string | null;
99
+ }
100
+ export interface SpaceViewerDatabaseSchema extends SpaceViewerDatabase { schema: Record<string, unknown>; schema_revision: number }
101
+ export interface SpaceViewerSkill {
102
+ skill_id: string; name: string | null; description: string | null;
103
+ kind: 'standalone' | 'space' | 'curated' | 'legacy'; status: string; enabled: boolean | null;
104
+ version: { revision: number; digest: string } | null; updated_at: string | null; created_at: string | null;
105
+ links: SpaceViewerLink[];
106
+ /** Present when content was requested; null where the viewer holds no content access (curated, legacy). */
107
+ skill_md?: string | null;
108
+ }
109
+ export interface SpaceViewerSkillPage { skills: SpaceViewerSkill[]; has_more: boolean; next: string | null }
110
+ export type SpaceViewerReadInput = {
111
+ list_databases: Record<string, never>;
112
+ get_database: { database_id: string };
113
+ query_database: { database_id: string; request: NativeQuery };
114
+ list_skills: { after?: string; limit?: number; include_disabled?: boolean; include_content?: boolean };
115
+ get_skill: { skill_id: string };
116
+ };
117
+ export type SpaceViewerReadResult = {
118
+ list_databases: { databases: SpaceViewerDatabase[] };
119
+ get_database: { database: SpaceViewerDatabaseSchema };
120
+ query_database: { rows?: Array<Record<string, unknown>>; database_id: string; [key: string]: unknown };
121
+ list_skills: SpaceViewerSkillPage;
122
+ get_skill: { skill: SpaceViewerSkill & { skill_md: string | null } };
123
+ };
124
+
125
+ /** V11 can atomically create a database as part of a source release.
126
+ * A created database must have a record param with main:true in the same view.
127
+ * After creation, pull projects its live schema; later schema edits use database tools.
128
+ */
129
+ export interface SpaceDatabaseCreate {
130
+ name: string;
131
+ schema: Record<string, SpaceJson>;
132
+ starterRows?: Array<Record<string, SpaceJson>>;
133
+ }
134
+ export type SpaceResourceReference = {
135
+ kind: 'database' | 'document' | 'skill' | 'automation';
136
+ /** Portable resource key, resolved against this profile's explicit bindings. */
137
+ key: string;
138
+ create?: never;
139
+ } | {
140
+ kind: 'database';
141
+ create: SpaceDatabaseCreate;
142
+ key?: never;
143
+ };
144
+
145
+ /** Optional V4 marker. Presentations always require path, description and memory at build time. */
146
+ export const SPACE_VIEW_SPEC_VERSION = 2;
147
+ export type SpaceViewParamType = 'record' | 'enum' | 'text' | 'number' | 'date' | 'period' | 'boolean';
148
+ /** A declared URL param; unknown params are dropped and every param is described for agents. */
149
+ export interface SpaceViewParam {
150
+ type: SpaceViewParamType;
151
+ /** What the param selects, for agents and people. Required. */
152
+ description: string;
153
+ required?: boolean;
154
+ /** Type-checked; never for record params. */
155
+ default?: string | number | boolean;
156
+ /** Enum values (enum only). */
157
+ values?: readonly string[];
158
+ /** Record params: the declared database resource alias whose records this param opens. */
159
+ database?: string;
160
+ /** Record params: this view is the database's main view (one per database). */
161
+ main?: boolean;
162
+ /** Record params: the property that makes the record slug in links; defaults to the title. */
163
+ slugProperty?: string;
164
+ /**
165
+ * Record params, at most one per view: a record matching `where` (fixed values only) opens full screen as its own
166
+ * page instead of this view. Editors see saved HTML pages and reports in the Portal; a record Site shows its HTML
167
+ * page only. The server checks the rule; it never reaches the browser.
168
+ */
169
+ page?: { where: NativeFilter };
170
+ /** IANA timezone for relative dates/periods (UTC if omitted). */
171
+ timezone?: string;
172
+ }
173
+ /**
174
+ * Notis data the view lists: exactly this native filter over a declared database, with `{param}`,
175
+ * `{param.property}`, `{record}` and `{record.property}` placeholders. Anything else is described.
176
+ */
177
+ export type SpaceViewFilter = { and: SpaceViewFilter[] } | { or: SpaceViewFilter[] }
178
+ | (Extract<NativeFilter, { field: unknown }> & { /** Apply only when this boolean param is true. */ when?: string });
179
+ export type SpaceShows =
180
+ | { database: string; where: SpaceViewFilter | Record<string, never>; open?: string }
181
+ | { about: string; services?: readonly string[] };
182
+ /** When view snapshots go to memory: on render, on a UTC cron (fixed minute), or after changes settle. */
183
+ export type SpaceMemorySnapshot = 'on_render' | { scheduled: string } | { on_change: { debounceSeconds: number } };
184
+ /** What this view sends to memory; records follow their database's main view. See the memory guide. */
185
+ export interface SpaceMemoryPolicy {
186
+ markdown: boolean;
187
+ attachments: boolean;
188
+ screenshot: boolean;
189
+ snapshots: readonly SpaceMemorySnapshot[];
190
+ }
191
+ export type SpaceChrome = 'portal' | 'hidden';
192
+ /**
193
+ * Public runtime form of `shows`: list names only, never filters. `params` names the declared params
194
+ * the list's filter reads (current hosts); without it every param is assumed to matter.
195
+ */
196
+ export type SpaceShownDescriptor = { database: string; open?: string; params?: readonly string[] }
197
+ | { about: string; services?: readonly string[] };
198
+ export interface SpaceShownOptions {
199
+ sorts?: NativeQuery['sorts'];
200
+ pageSize?: number;
201
+ offset?: number;
202
+ includeContent?: boolean;
203
+ }
204
+ export interface SpaceShownResult {
205
+ rows: Array<Record<string, unknown>>;
206
+ list: string;
207
+ database: string;
208
+ params: Record<string, unknown>;
209
+ /** The list database's schema revision: pass it as `schemaRevision` to a declared row write. */
210
+ schema_revision?: number;
211
+ [key: string]: unknown;
212
+ }
213
+ /** Input of a `markdown` module's default export (V8 renders). */
214
+ export interface SpaceMarkdownInput {
215
+ params: Record<string, unknown>;
216
+ shown: Record<string, SpaceShownResult | undefined>;
217
+ }
218
+
219
+ export interface SpaceDefinition {
220
+ name: string;
221
+ /** Optional marker (2); omitting it does not waive a presentation's required declarations. */
222
+ specVersion?: typeof SPACE_VIEW_SPEC_VERSION;
223
+ /** Words used in this view's links, such as `notes` or `seo/keywords`. */
224
+ path?: string;
225
+ /** Questions this view can answer; used by agents when choosing an existing view. */
226
+ questions?: string[];
227
+ params?: Record<string, SpaceViewParam>;
228
+ shows?: Record<string, SpaceShows>;
229
+ memory?: SpaceMemoryPolicy;
230
+ /** `hidden` hides the Portal sidebar and header for this view, keeping a small exit control. */
231
+ chrome?: SpaceChrome;
232
+ /** Source-relative module whose default export `(input: SpaceMarkdownInput) => string` renders this view as Markdown. */
233
+ markdown?: string;
234
+ description?: string;
235
+ icon?: string;
236
+ accent?: string;
237
+ /** No entry means a container; it needs no dummy JavaScript artifact. */
238
+ entry?: string;
239
+ layout?: string;
240
+ readableContext?: string;
241
+ resources?: Record<string, SpaceResourceReference>;
242
+ /** Named destinations bound by the host; package keys never contain account IDs. */
243
+ navigation?: Record<string, { key: string }>;
244
+ actions?: Record<string, SpaceActionTemplate>;
245
+ /**
246
+ * Reviewable declaration that this page reads what each signed-in viewer can open
247
+ * (`databases`: list, schema, rows; `skills`: list, content), with that viewer's own
248
+ * authority. Undeclared reads are refused; Sites and anonymous links never get them.
249
+ */
250
+ viewerReads?: SpaceViewerReadFamily[];
251
+ /**
252
+ * Reviewable declaration that this page uses each signed-in viewer's own cloud computer
253
+ * (`read`: facts; `shell`: commands and file writes), once that viewer allows it.
254
+ */
255
+ cloudComputer?: SpaceCloudComputerLevel;
256
+ collection?: { database: string; titleProperty: string; parentProperty?: string; allowCreate?: boolean };
257
+ /** Reproducible source dependencies not discovered by the module graph. */
258
+ sourceIncludes?: string[];
259
+ /** Explicit synthetic action cases for offline render verification. */
260
+ verificationFixtures?: string;
261
+ }
262
+
263
+ export interface SpacesWorkspace {
264
+ /** One project, independently built/released definitions. */
265
+ spaces: Record<string, { definition: string; parent?: string; defaultChild?: string }>;
266
+ resources?: Record<string, { kind: SpaceResourceReference['kind']; source: string }>;
267
+ defaultSpace?: string;
268
+ }
269
+
270
+ export function defineSpace<const T extends SpaceDefinition>(definition: T): T { return definition; }
271
+ export function defineSpaces<const T extends SpacesWorkspace>(workspace: T): T { return workspace; }
272
+
273
+ export interface SpaceActionDescriptor {
274
+ id: string;
275
+ inputSchema: ToolInputSchema;
276
+ /** Determined by the server's tool classifier, not the source author. */
277
+ readOnly: boolean;
278
+ }
279
+
280
+ export interface SpaceRuntimeDescriptor {
281
+ id: string;
282
+ revision: number;
283
+ /** Opaque host identity includes actor/link, record context and live policy version. */
284
+ cacheScope: string;
285
+ navigation?: string[];
286
+ /** Declared viewer reads; present only for a signed-in viewer, never on a Site. */
287
+ viewerReads?: SpaceViewerReadFamily[];
288
+ /** Declared cloud computer access; present only for a signed-in Editor, never on a Site. */
289
+ cloudComputer?: SpaceCloudComputerLevel;
290
+ /** V4: declared URL params (never a record param's `page` rule), list names and chrome of the executable revision. */
291
+ params?: Record<string, Omit<SpaceViewParam, 'page'>>;
292
+ shows?: Record<string, SpaceShownDescriptor>;
293
+ chrome?: SpaceChrome;
294
+ actions: Record<string, SpaceActionDescriptor>;
295
+ bindings: Record<string, {
296
+ kind: SpaceResourceReference['kind'];
297
+ operations?: Partial<Record<'query' | 'insert' | 'update' | 'delete', string>>;
298
+ /** Signed-in viewers: the opaque name of this database's live change signal (never its id). */
299
+ live?: string;
300
+ }>;
301
+ }
302
+
303
+ export interface SpaceActionOptions {
304
+ /** A caller-controlled idempotency key is stable across a deliberate retry. */
305
+ requestId?: string;
306
+ /** Revision discovered with the native schema/query; required for row writes. */
307
+ schemaRevision?: number;
308
+ readOnly?: boolean;
309
+ dedupe?: boolean;
310
+ /**
311
+ * A write that is one step of a batch: the host skips re-reading every cached list after it,
312
+ * and the batch calls `queryClient.invalidate()` once at the end. Hosts that predate it ignore it.
313
+ */
314
+ deferRefresh?: boolean;
315
+ }
316
+
317
+ export type SpaceDocumentBodyRequest = {
318
+ operation: 'read'; binding: string; recordKey: string; readAction: string;
319
+ } | {
320
+ operation: 'save'; binding: string; recordKey: string; readAction: string; writeAction: string;
321
+ contentMarkdown: string; expectedRevision: number; schemaRevision: number; requestId: string;
322
+ };
323
+ export interface SpaceDocumentBodyRead {
324
+ record_key: string; title: string | null; revision: number; schema_revision: number; content_markdown: string;
325
+ }
326
+ export type SpaceDocumentBodySave = {
327
+ status: 'succeeded'; billing_status: 'free'; receipt_id: string; result: NativeMutationReceipt;
328
+ } | { status: 'unchanged'; revision: number; schema_revision: number };
329
+ export type SpaceDocumentBodyResult = SpaceDocumentBodyRead | SpaceDocumentBodySave;
330
+
331
+ export interface SpaceActionFailureDetails {
332
+ requestId: string;
333
+ receiptId?: string;
334
+ status?: string;
335
+ pendingRequestIds?: string[];
336
+ /** Why a settled action failed, when the host knows a stable reason: `read_timeout` (a read its time limit stopped). */
337
+ code?: string;
338
+ }
339
+
340
+ /** Retain requestId when offering a retry of an uncertain external effect. */
341
+ export class SpaceActionError extends Error implements SpaceActionFailureDetails {
342
+ constructor(message: string, public readonly requestId: string, public readonly receiptId?: string,
343
+ public readonly status?: string, public readonly pendingRequestIds?: string[], public readonly code?: string) {
344
+ super(message); this.name = 'SpaceActionError';
345
+ }
346
+ }
347
+
348
+ export function spaceActionFailureDetails(error: unknown): SpaceActionFailureDetails | undefined {
349
+ if (!(error instanceof SpaceActionError)) return undefined;
350
+ return { requestId: error.requestId, receiptId: error.receiptId, status: error.status, pendingRequestIds: error.pendingRequestIds,
351
+ ...(error.code ? { code: error.code } : {}) };
352
+ }
353
+
354
+ export function restoreSpaceActionError(message: string, details?: SpaceActionFailureDetails): Error {
355
+ return details ? new SpaceActionError(message, details.requestId, details.receiptId, details.status, details.pendingRequestIds, details.code)
356
+ : new Error(message);
357
+ }
358
+
359
+ /** Superseded UI intent, distinct from an authorization or transport failure. */
360
+ export class SpaceNavigationCancelled extends Error {
361
+ readonly code = 'space_navigation_cancelled';
362
+ constructor(message = 'This navigation is no longer active.') { super(message); this.name = 'SpaceNavigationCancelled'; }
363
+ }
364
+
365
+ export function isSpaceNavigationCancelled(error: unknown): error is SpaceNavigationCancelled {
366
+ // Source bundles and the host may contain separate SDK instances.
367
+ return error instanceof Error && error.name === 'SpaceNavigationCancelled'
368
+ && (error as SpaceNavigationCancelled).code === 'space_navigation_cancelled';
369
+ }
370
+
371
+ export type SpaceRuntimeFailureDetails = SpaceActionFailureDetails | { kind: 'navigation_cancelled' };
372
+ export function spaceRuntimeFailureDetails(error: unknown): SpaceRuntimeFailureDetails | undefined {
373
+ return isSpaceNavigationCancelled(error) ? { kind: 'navigation_cancelled' } : spaceActionFailureDetails(error);
374
+ }
375
+ export function restoreSpaceRuntimeError(message: string, details?: SpaceRuntimeFailureDetails): Error {
376
+ if (details && 'kind' in details) return details.kind === 'navigation_cancelled' ? new SpaceNavigationCancelled(message) : new Error(message);
377
+ return restoreSpaceActionError(message, details);
378
+ }
379
+
380
+ export function spaceQueryKey(runtime: NotisRuntime | null, key: readonly unknown[]): readonly unknown[] {
381
+ if (runtime?.resource?.kind !== 'space') return key;
382
+ const space = runtime.space;
383
+ if (!space?.cacheScope || space.id !== runtime.resource.id || space.revision !== runtime.resource.revision) {
384
+ throw new Error('The host must provide this Space revision and access context.');
385
+ }
386
+ return ['space', space.id, space.revision, space.cacheScope, ...key];
387
+ }
388
+
389
+ /** SDK defense in depth. The host/server independently reject these transports. */
390
+ export function guardSpaceRuntime(runtime: NotisRuntime | null, onProtocolError?: (error: Error) => void): NotisRuntime | null {
391
+ if (runtime?.resource?.kind !== 'space') return runtime;
392
+ spaceQueryKey(runtime, []);
393
+ const protocolError = (message: string, key?: QueryErrorKey) => {
394
+ const error = key ? new SdkQueryError(key, message, runtime.context?.locale) : new Error(message);
395
+ onProtocolError?.(error); return error;
396
+ };
397
+ const deny = async (): Promise<never> => { throw protocolError('Use a declared Space action; account-wide tool and backend calls are unavailable.'); };
398
+ const callAction = runtime.callAction;
399
+ if (!callAction) throw new Error('This host needs the current Space action protocol.');
400
+ const viewerRead = runtime.viewerRead;
401
+ const shown = runtime.shown;
402
+ const cloudComputer = runtime.spaceCloudComputer;
403
+ const cloudLevel = runtime.space!.cloudComputer;
404
+ const guardedCloud = (operation: SpaceCloudComputerOperation) => {
405
+ if (!cloudComputer || !spaceCloudComputerAllows(cloudLevel, operation)) {
406
+ throw protocolError(operation === 'facts' ? 'This Space does not use the cloud computer.'
407
+ : 'This Space does not declare cloudComputer: shell.');
408
+ }
409
+ return cloudComputer;
410
+ };
411
+ return Object.freeze({ ...runtime, callTool: deny, request: deny, listTools: deny,
412
+ shown: shown ? async function guardedShown<TResult>(name: string, params: Record<string, unknown> = {},
413
+ options: SpaceShownOptions = {}): Promise<TResult> {
414
+ const list = runtime.space!.shows && Object.hasOwn(runtime.space!.shows, name) ? runtime.space!.shows[name] : null;
415
+ if (!list || !('database' in list)) throw protocolError('This view does not declare that list with a filter.', 'listUnavailable');
416
+ return shown<TResult>(name, params, options);
417
+ } : undefined,
418
+ handover: undefined,
419
+ // The legacy facts hook keeps working in a Space that declares the cloud computer.
420
+ cloudComputerFacts: cloudComputer && cloudLevel ? async (options?: { refresh?: boolean }) => guardedCloud('facts').facts(options) : undefined,
421
+ spaceCloudComputer: cloudComputer && cloudLevel ? Object.freeze({
422
+ status: () => cloudComputer.status(),
423
+ requestApproval: () => cloudComputer.requestApproval(),
424
+ facts: async (options?: { refresh?: boolean }) => guardedCloud('facts').facts(options),
425
+ run: async (input: SpaceCloudComputerRunInput) => guardedCloud('run').run(input),
426
+ upload: async (input: SpaceCloudComputerUploadInput) => guardedCloud('upload').upload(input),
427
+ }) : undefined,
428
+ viewerRead: viewerRead ? async function guardedViewerRead<TResult>(operation: SpaceViewerReadOperation,
429
+ input: Record<string, unknown> = {}): Promise<TResult> {
430
+ const family = Object.hasOwn(SPACE_VIEWER_READ_OPERATIONS, operation) ? SPACE_VIEWER_READ_OPERATIONS[operation] : null;
431
+ if (!family) throw protocolError('Viewer reads never change data. Choose a supported read.', 'readUnavailable');
432
+ if (!runtime.space!.viewerReads?.includes(family)) throw protocolError(`This Space does not declare viewer reads of ${family}.`, 'readUnavailable');
433
+ return viewerRead<TResult>(operation, input);
434
+ } : undefined,
435
+ async callAction<TResult>(id: string, inputs: Record<string, unknown> = {}, options: SpaceActionOptions = {}): Promise<TResult> {
436
+ const descriptor = Object.hasOwn(runtime.space!.actions, id) ? runtime.space!.actions[id] : null;
437
+ if (!descriptor) throw protocolError('This action is not declared by the published Space.', options.readOnly || options.dedupe ? 'actionUnavailable' : undefined);
438
+ if ((options.readOnly || options.dedupe) && !descriptor.readOnly) throw protocolError('A write action cannot run as a cached read.', 'readUnavailable');
439
+ return callAction<TResult>(id, inputs, options);
440
+ },
441
+ });
442
+ }
@@ -0,0 +1,36 @@
1
+ import type { SpaceViewParam, SpaceViewFilter } from './space';
2
+
3
+ /** Standard Journal/Tasks URL settings. Authors bind these to their actual schemas and controls. */
4
+ export function journalViewParams(timezone: string): Record<string, SpaceViewParam> {
5
+ return { period: { type: 'period', description: 'Calendar period, inclusive. Which dates should the journal show?', timezone } };
6
+ }
7
+
8
+ export function tasksViewParams({ timezone, projectDatabase, statuses }: {
9
+ timezone: string; projectDatabase: string; statuses: readonly string[];
10
+ }): Record<string, SpaceViewParam> {
11
+ return {
12
+ ...journalViewParams(timezone),
13
+ dueDate: { type: 'date', description: 'Which exact due date should the task list show?', timezone },
14
+ late: { type: 'boolean', description: 'Only unfinished tasks due before today in the selected timezone.' },
15
+ notPlanned: { type: 'boolean', description: 'Only tasks without a due date.' },
16
+ today: { type: 'date', default: 'today', timezone, description: 'Reference date for late tasks; pin it for a dated answer.' },
17
+ project: { type: 'record', database: projectDatabase, description: 'Which project should the tasks belong to?' },
18
+ status: { type: 'enum', values: statuses, description: 'Which task status should the list show?' },
19
+ };
20
+ }
21
+
22
+ /** Server-side filters, applied before pagination. Omitted URL settings omit their conditions. */
23
+ export function tasksViewFilter({ dueProperty, statusProperty, projectProperty, doneStatus }: {
24
+ dueProperty: string; statusProperty: string; projectProperty: string; doneStatus: string;
25
+ }): SpaceViewFilter {
26
+ return { and: [
27
+ { field: { property: dueProperty }, op: 'equals', value: '{dueDate}' },
28
+ { field: { property: dueProperty }, op: 'on_or_after', value: '{period.start}' },
29
+ { field: { property: dueProperty }, op: 'on_or_before', value: '{period.end}' },
30
+ { field: { property: dueProperty }, op: 'before', value: '{today}', when: 'late' },
31
+ { field: { property: statusProperty }, op: 'not_equals', value: doneStatus, when: 'late' },
32
+ { field: { property: dueProperty }, op: 'is_empty', when: 'notPlanned' },
33
+ { field: { property: projectProperty }, op: 'contains', value: '{project}' },
34
+ { field: { property: statusProperty }, op: 'equals', value: '{status}' },
35
+ ] };
36
+ }
@@ -8,32 +8,78 @@
8
8
  * The portal injects the live Notis theme variables at render time.
9
9
  */
10
10
 
11
- @tailwind base;
12
- @tailwind components;
13
- @tailwind utilities;
14
-
15
- @layer base {
11
+ /* The SDK Dialog's rules live in toolkit.css (section: dialog), so they also reach a Space's shadow root. */
12
+
13
+ /* Framework-neutral styles: the app owns its Tailwind entry point. This file
14
+ * is also consumed in shadow roots and by apps on older Tailwind versions.
15
+ * The shell rules live in the native sublayer `components.notis-sdk`, so a
16
+ * page's Tailwind utilities (p-4, border-red-500) still win over them. Never
17
+ * use a bare Tailwind-owned `@layer base` / `@layer components` block: Vite
18
+ * processes this import separately from the app stylesheet, and Tailwind 3
19
+ * rejects those blocks without matching `@tailwind` directives.
20
+ *
21
+ * Tailwind 4: the statement below repeats its full layer order, including the
22
+ * `properties` layer it declares first for its --tw-* fallback reset, so the
23
+ * order holds whichever stylesheet loads first and the shell rules win over
24
+ * preflight and the app's base defaults.
25
+ * Tailwind 3: preflight, components and utilities are unlayered and beat every
26
+ * layered rule, so its preflight (`button` and list resets, `*` border colour)
27
+ * wins over these shell rules; utilities still win too. A Tailwind 3 app that
28
+ * puts a shell class on a `button`, `ul` or `ol` restates the background and
29
+ * padding it needs. */
30
+ @layer properties, theme, base, components, utilities;
31
+
32
+ @layer components.notis-sdk {
16
33
  * {
17
- @apply border-border;
34
+ border-color: hsl(var(--border));
18
35
  }
19
36
  [data-notis-app-root] {
20
37
  color: hsl(var(--foreground));
21
38
  display: block;
22
39
  min-height: 100%;
23
40
  }
24
- }
25
41
 
26
- @layer components {
27
- .notis-app-shell {
28
- @apply mx-auto w-full max-w-[var(--portal-page-max-width)] px-4 py-6 md:px-4 md:py-8;
42
+ /* Split pages are full-bleed; only the list pane carries a hairline. */
43
+ .notis-app-split {
44
+ display: flex;
45
+ height: 100%;
46
+ min-height: 0;
47
+ width: 100%;
48
+ max-width: none;
49
+ flex-direction: column;
29
50
  }
30
51
 
31
- .notis-app-surface {
32
- @apply rounded-2xl border border-border bg-card text-card-foreground shadow-sm;
52
+ .notis-app-pane-list {
53
+ width: 100%;
54
+ flex-shrink: 0;
55
+ background-color: hsl(var(--muted) / 0.4);
56
+ }
57
+
58
+ .notis-app-pane-detail {
59
+ min-width: 0;
60
+ flex: 1 1 0%;
61
+ background-color: hsl(var(--background));
33
62
  }
34
63
 
35
64
  .notis-app-section {
36
- @apply p-5 md:p-6;
65
+ padding: 1.25rem;
66
+ }
67
+
68
+ @media (min-width: 768px) {
69
+ .notis-app-section { padding: 1.5rem; }
70
+ }
71
+
72
+ @media (min-width: 1024px) {
73
+ .notis-app-split { flex-direction: row; }
74
+ .notis-app-pane-list {
75
+ width: 20rem;
76
+ border-right-width: 1px;
77
+ border-right-color: hsl(var(--border));
78
+ }
79
+ }
80
+
81
+ @media (min-width: 1280px) {
82
+ .notis-app-pane-list { width: 24rem; }
37
83
  }
38
84
  }
39
85
 
@@ -114,13 +160,23 @@
114
160
  accent-color: hsl(var(--primary));
115
161
  }
116
162
 
163
+ /* A flat tinted block, like a callout; never an edge on one side. */
117
164
  .notis-markdown blockquote {
118
165
  margin: 0.75em 0;
119
- padding: 0.125em 0 0.125em 0.875em;
120
- border-left: 3px solid hsl(var(--border));
166
+ padding: 0.5em 0.875em;
167
+ border-radius: 0.5rem;
168
+ background: hsl(var(--muted) / 0.5);
121
169
  color: hsl(var(--muted-foreground));
122
170
  }
123
171
 
172
+ .notis-markdown blockquote > :first-child {
173
+ margin-top: 0;
174
+ }
175
+
176
+ .notis-markdown blockquote > :last-child {
177
+ margin-bottom: 0;
178
+ }
179
+
124
180
  .notis-markdown a {
125
181
  color: hsl(var(--primary));
126
182
  text-decoration: underline;
@@ -166,8 +222,16 @@
166
222
  border-radius: 0.5rem;
167
223
  }
168
224
 
169
- .notis-markdown table {
225
+ /* The Markdown component wraps each table in a scroll box, so a wide table scrolls sideways on a phone. */
226
+ .notis-markdown-table {
170
227
  margin: 0.75em 0;
228
+ max-width: 100%;
229
+ overflow-x: auto;
230
+ overscroll-behavior-x: contain;
231
+ }
232
+
233
+ .notis-markdown table {
234
+ margin: 0;
171
235
  width: 100%;
172
236
  border-collapse: collapse;
173
237
  font-size: 0.95em;
@@ -175,6 +239,7 @@
175
239
 
176
240
  .notis-markdown th,
177
241
  .notis-markdown td {
242
+ min-width: 6em;
178
243
  padding: 0.375em 0.75em;
179
244
  border: 1px solid hsl(var(--border));
180
245
  text-align: left;