@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.
- package/README.md +542 -146
- package/bin/check-runtime.js +15 -0
- package/bin/notis.js +2 -0
- package/config/notis_app_design_rules.json +320 -0
- package/config/portal-route-roots.json +45 -0
- package/dist/agent-hooks/notis-agent-hook.mjs +42325 -18273
- package/dist/base-skills/notis-cli/.notis-base-skill.json +1 -0
- package/dist/base-skills/notis-cli/SKILL.md +51 -280
- package/dist/base-skills/notis-cli/references/app-delivery.md +17 -0
- package/dist/base-skills/notis-cli/references/intelligence.md +94 -0
- package/dist/base-skills/notis-cli/references/native-databases.md +21 -0
- package/dist/base-skills/notis-cli/references/tool-examples.md +56 -0
- package/dist/base-skills/notis-cli/references/troubleshooting.md +67 -0
- package/dist/base-skills/notis-query/.notis-base-skill.json +1 -0
- package/dist/base-skills/notis-query/SKILL.md +35 -699
- package/dist/base-skills/notis-query/references/database-discovery.md +59 -0
- package/dist/base-skills/notis-query/references/documents.md +74 -0
- package/dist/base-skills/notis-query/references/query.md +76 -0
- package/dist/base-skills/notis-spaces/.notis-base-skill.json +1 -0
- package/dist/base-skills/notis-spaces/SKILL.md +218 -0
- package/dist/base-skills/notis-spaces/references/architecture.md +116 -0
- package/dist/base-skills/notis-spaces/references/context.md +81 -0
- package/dist/base-skills/notis-spaces/references/design.md +141 -0
- package/dist/base-skills/notis-spaces/references/fixtures.md +29 -0
- package/dist/base-skills/notis-spaces/references/memory.md +58 -0
- package/dist/base-skills/notis-spaces/references/reading.md +73 -0
- package/dist/base-skills/notis-spaces/references/release.md +120 -0
- package/dist/base-skills/notis-spaces/references/reports.md +77 -0
- package/dist/base-skills/notis-spaces/references/sdk.md +273 -0
- package/dist/base-skills/notis-spaces/references/store.md +118 -0
- package/dist/base-skills/notis-spaces/references/troubleshooting.md +28 -0
- package/dist/base-skills/notis-spaces/references/views.md +229 -0
- package/{template/packages → dist}/sdk/package.json +9 -10
- package/dist/sdk/src/agentContext.ts +36 -0
- package/dist/sdk/src/bundleModule.ts +175 -0
- package/dist/sdk/src/components/Dialog.tsx +103 -0
- package/dist/sdk/src/components/DocumentEditor.tsx +113 -0
- package/dist/sdk/src/components/DocumentPage.tsx +184 -0
- package/{template/packages → dist}/sdk/src/components/Markdown.tsx +9 -3
- package/{template/packages → dist}/sdk/src/components/MarkdownEditor.tsx +26 -5
- package/{template/packages → dist}/sdk/src/components/MultiSelectActionBar.tsx +95 -12
- package/{template/packages → dist}/sdk/src/components/MultiSelectCheckbox.tsx +4 -2
- package/dist/sdk/src/components/NotisCommentBoundary.tsx +172 -0
- package/{template/packages → dist}/sdk/src/components/NotisSelectionBoundary.tsx +9 -5
- package/dist/sdk/src/components/RecordComponents.tsx +111 -0
- package/dist/sdk/src/components/Skeleton.tsx +38 -0
- package/dist/sdk/src/config.ts +31 -0
- package/{template/packages → dist}/sdk/src/documents.ts +21 -6
- package/dist/sdk/src/hooks/useAction.ts +28 -0
- package/dist/sdk/src/hooks/useAgentContext.ts +23 -0
- package/{template/packages → dist}/sdk/src/hooks/useBackend.ts +3 -2
- package/dist/sdk/src/hooks/useCloudComputer.ts +94 -0
- package/dist/sdk/src/hooks/useCloudComputerShell.ts +114 -0
- package/{template/packages → dist}/sdk/src/hooks/useCollectionInteractions.ts +157 -147
- package/dist/sdk/src/hooks/useDatabaseSchema.ts +50 -0
- package/{template/packages → dist}/sdk/src/hooks/useDatabaseSubscription.ts +2 -2
- package/dist/sdk/src/hooks/useDocument.ts +51 -0
- package/{template/packages → dist}/sdk/src/hooks/useDocuments.ts +25 -59
- package/{template/packages → dist}/sdk/src/hooks/useHandover.ts +7 -7
- package/dist/sdk/src/hooks/useLongPressSelection.ts +79 -0
- package/dist/sdk/src/hooks/useMarqueeSelection.ts +194 -0
- package/{template/packages → dist}/sdk/src/hooks/useMultiSelect.ts +2 -8
- package/dist/sdk/src/hooks/useNativeDocumentBody.ts +50 -0
- package/dist/sdk/src/hooks/useNativeDocuments.ts +143 -0
- package/{template/packages → dist}/sdk/src/hooks/useNotis.ts +6 -1
- package/dist/sdk/src/hooks/useNotisNavigation.ts +70 -0
- package/dist/sdk/src/hooks/useQuery.ts +81 -0
- package/dist/sdk/src/hooks/useToolQuery.ts +12 -0
- package/dist/sdk/src/hooks/useTopBarSearch.ts +102 -0
- package/dist/sdk/src/hooks/useTopBarTitleLeaf.ts +75 -0
- package/{template/packages → dist}/sdk/src/hooks/useUpsertDocument.ts +1 -1
- package/dist/sdk/src/hooks/useViewParams.ts +195 -0
- package/dist/sdk/src/hooks/useViewerReads.ts +129 -0
- package/{template/packages → dist}/sdk/src/index.ts +64 -1
- package/{template/packages → dist}/sdk/src/interactions/actions.ts +14 -1
- package/{template/packages → dist}/sdk/src/interactions/shortcuts.tsx +129 -23
- package/dist/sdk/src/interactions/visibility.ts +13 -0
- package/{template/packages → dist}/sdk/src/interactions.ts +5 -1
- package/dist/sdk/src/nativeData.ts +39 -0
- package/{template/packages → dist}/sdk/src/provider.tsx +9 -4
- package/dist/sdk/src/queryCache.ts +292 -0
- package/dist/sdk/src/queryErrors.ts +51 -0
- package/dist/sdk/src/runtime.ts +675 -0
- package/dist/sdk/src/runtimeModules.ts +33 -0
- package/dist/sdk/src/space.ts +442 -0
- package/dist/sdk/src/standardViewParams.ts +36 -0
- package/{template/packages → dist}/sdk/src/styles.css +81 -16
- package/dist/sdk/src/tailwind.ts +66 -0
- package/dist/sdk/src/ui/charts/RenderChartData.tsx +25 -0
- package/dist/sdk/src/ui/engine/core.ts +392 -0
- package/dist/sdk/src/ui/engine/dom.ts +183 -0
- package/dist/sdk/src/ui/engine/hooks.ts +195 -0
- package/dist/sdk/src/ui/engine/instance.ts +63 -0
- package/dist/sdk/src/ui/engine/keycapContext.ts +2 -0
- package/dist/sdk/src/ui/engine/registry.ts +262 -0
- package/dist/sdk/src/ui/engine/types.ts +62 -0
- package/dist/sdk/src/ui/icons.tsx +91 -0
- package/dist/sdk/src/ui/util.ts +83 -0
- package/dist/sdk/src/viewPeriod.ts +26 -0
- package/dist/sdk/src/vite.ts +92 -0
- package/dist/sdk/src/words/actions.ts +295 -0
- package/dist/sdk/src/words/clashes.ts +158 -0
- package/dist/sdk/src/words/format.ts +136 -0
- package/dist/sdk/src/words/index.ts +13 -0
- package/dist/sdk/src/words/keymap.ts +72 -0
- package/dist/sdk/src/words/keys.ts +297 -0
- package/dist/sdk/src/words/shell.ts +46 -0
- package/dist/sdk/src/words/types.ts +65 -0
- package/dist/skill-sync/index.js +832 -151
- package/dist/skill-sync/index.js.map +4 -4
- package/dist/skill-sync-worker.mjs +3941 -0
- package/dist/space-harness/host.js +1460 -0
- package/dist/space-sdk/dist/chunk-ZSN57ATH.js +5 -0
- package/dist/space-sdk/dist/index.js +15 -0
- package/dist/space-sdk/dist/ui.js +18 -0
- package/dist/space-sdk/package.json +33 -0
- package/dist/space-sdk/src/agentContext.d.ts +36 -0
- package/dist/space-sdk/src/components/Dialog.d.ts +20 -0
- package/dist/space-sdk/src/components/DocumentEditor.d.ts +46 -0
- package/dist/space-sdk/src/components/DocumentPage.d.ts +53 -0
- package/dist/space-sdk/src/components/Markdown.d.ts +18 -0
- package/dist/space-sdk/src/components/MarkdownEditor.d.ts +11 -0
- package/dist/space-sdk/src/components/MultiSelectActionBar.d.ts +31 -0
- package/dist/space-sdk/src/components/MultiSelectCheckbox.d.ts +14 -0
- package/dist/space-sdk/src/components/MultiSelectDragOverlay.d.ts +8 -0
- package/dist/space-sdk/src/components/NotisCommentBoundary.d.ts +36 -0
- package/dist/space-sdk/src/components/NotisSelectionBoundary.d.ts +16 -0
- package/dist/space-sdk/src/components/RecordComponents.d.ts +64 -0
- package/dist/space-sdk/src/components/ShortcutHints.d.ts +12 -0
- package/dist/space-sdk/src/components/Skeleton.d.ts +23 -0
- package/dist/space-sdk/src/config.ts +31 -0
- package/dist/space-sdk/src/documents.d.ts +59 -0
- package/dist/space-sdk/src/hooks/useAction.d.ts +8 -0
- package/dist/space-sdk/src/hooks/useActiveResource.d.ts +3 -0
- package/dist/space-sdk/src/hooks/useAgentContext.d.ts +7 -0
- package/dist/space-sdk/src/hooks/useBackend.d.ts +23 -0
- package/dist/space-sdk/src/hooks/useCloudComputer.d.ts +45 -0
- package/dist/space-sdk/src/hooks/useCloudComputerShell.d.ts +49 -0
- package/dist/space-sdk/src/hooks/useCollectionInteractions.d.ts +118 -0
- package/dist/space-sdk/src/hooks/useDatabaseSchema.d.ts +14 -0
- package/dist/space-sdk/src/hooks/useDatabaseSubscription.d.ts +26 -0
- package/dist/space-sdk/src/hooks/useDocument.d.ts +22 -0
- package/dist/space-sdk/src/hooks/useDocuments.d.ts +31 -0
- package/dist/space-sdk/src/hooks/useHandover.d.ts +43 -0
- package/dist/space-sdk/src/hooks/useLongPressSelection.d.ts +9 -0
- package/dist/space-sdk/src/hooks/useMarqueeSelection.d.ts +57 -0
- package/dist/space-sdk/src/hooks/useMultiSelect.d.ts +51 -0
- package/dist/space-sdk/src/hooks/useNativeDocumentBody.d.ts +24 -0
- package/dist/space-sdk/src/hooks/useNativeDocuments.d.ts +55 -0
- package/dist/space-sdk/src/hooks/useNotis.d.ts +25 -0
- package/dist/space-sdk/src/hooks/useNotisNavigation.d.ts +33 -0
- package/dist/space-sdk/src/hooks/useQuery.d.ts +22 -0
- package/dist/space-sdk/src/hooks/useTool.d.ts +20 -0
- package/dist/space-sdk/src/hooks/useToolQuery.d.ts +3 -0
- package/dist/space-sdk/src/hooks/useTools.d.ts +15 -0
- package/dist/space-sdk/src/hooks/useTopBarSearch.d.ts +48 -0
- package/dist/space-sdk/src/hooks/useTopBarTitleLeaf.d.ts +24 -0
- package/dist/space-sdk/src/hooks/useUpsertDocument.d.ts +27 -0
- package/dist/space-sdk/src/hooks/useViewParams.d.ts +76 -0
- package/dist/space-sdk/src/hooks/useViewerReads.d.ts +38 -0
- package/dist/space-sdk/src/index.d.ts +98 -0
- package/dist/space-sdk/src/interactions/actions.d.ts +33 -0
- package/dist/space-sdk/src/interactions/shortcuts.d.ts +42 -0
- package/dist/space-sdk/src/interactions/visibility.d.ts +2 -0
- package/dist/space-sdk/src/nativeData.d.ts +66 -0
- package/dist/space-sdk/src/provider.d.ts +17 -0
- package/dist/space-sdk/src/queryCache.d.ts +45 -0
- package/dist/space-sdk/src/queryErrors.ts +51 -0
- package/dist/space-sdk/src/runtime.d.ts +615 -0
- package/dist/space-sdk/src/runtimeModules.ts +33 -0
- package/dist/space-sdk/src/space.ts +442 -0
- package/dist/space-sdk/src/standardViewParams.d.ts +15 -0
- package/dist/space-sdk/src/tailwind-candidates.d.ts +3418 -0
- package/dist/space-sdk/src/tailwind.ts +66 -0
- package/dist/space-sdk/src/ui/actions/ActionToast.d.ts +15 -0
- package/dist/space-sdk/src/ui/actions/actionWords.d.ts +16 -0
- package/dist/space-sdk/src/ui/actions/index.d.ts +7 -0
- package/dist/space-sdk/src/ui/actions/useActions.d.ts +69 -0
- package/dist/space-sdk/src/ui/actions/useToast.d.ts +41 -0
- package/dist/space-sdk/src/ui/blocks/Tabs.d.ts +139 -0
- package/dist/space-sdk/src/ui/blocks/blocks.d.ts +217 -0
- package/dist/space-sdk/src/ui/blocks/index.d.ts +4 -0
- package/dist/space-sdk/src/ui/board/BoardView.d.ts +36 -0
- package/dist/space-sdk/src/ui/board/boardModel.d.ts +46 -0
- package/dist/space-sdk/src/ui/board/boardWords.d.ts +9 -0
- package/dist/space-sdk/src/ui/board/index.d.ts +5 -0
- package/dist/space-sdk/src/ui/calendar/CalendarView.d.ts +49 -0
- package/dist/space-sdk/src/ui/calendar/DayPicker.d.ts +23 -0
- package/dist/space-sdk/src/ui/calendar/calendarMath.d.ts +81 -0
- package/dist/space-sdk/src/ui/charts/Chart.d.ts +203 -0
- package/dist/space-sdk/src/ui/charts/ChartTable.d.ts +37 -0
- package/dist/space-sdk/src/ui/charts/RenderChartData.d.ts +16 -0
- package/dist/space-sdk/src/ui/charts/StatRow.d.ts +59 -0
- package/dist/space-sdk/src/ui/charts/chartData.d.ts +84 -0
- package/dist/space-sdk/src/ui/comments/CommentPane.d.ts +58 -0
- package/dist/space-sdk/src/ui/comments/commentModel.d.ts +157 -0
- package/dist/space-sdk/src/ui/comments/commentWords.d.ts +60 -0
- package/dist/space-sdk/src/ui/comments/index.d.ts +4 -0
- package/dist/space-sdk/src/ui/comments/useComments.d.ts +146 -0
- package/dist/space-sdk/src/ui/engine/HelpSheet.d.ts +12 -0
- package/dist/space-sdk/src/ui/engine/KeyboardEngine.d.ts +27 -0
- package/dist/space-sdk/src/ui/engine/core.d.ts +73 -0
- package/dist/space-sdk/src/ui/engine/hooks.d.ts +64 -0
- package/dist/space-sdk/src/ui/engine/index.d.ts +14 -0
- package/dist/space-sdk/src/ui/engine/instance.d.ts +21 -0
- package/dist/space-sdk/src/ui/engine/keycapContext.d.ts +2 -0
- package/dist/space-sdk/src/ui/engine/registry.d.ts +77 -0
- package/dist/space-sdk/src/ui/engine/step.d.ts +11 -0
- package/dist/space-sdk/src/ui/engine/types.d.ts +54 -0
- package/dist/space-sdk/src/ui/fields/fieldWords.d.ts +56 -0
- package/dist/space-sdk/src/ui/fields/fields.d.ts +162 -0
- package/dist/space-sdk/src/ui/fields/index.d.ts +5 -0
- package/dist/space-sdk/src/ui/fields/useFieldDraft.d.ts +22 -0
- package/dist/space-sdk/src/ui/gallery/AttachmentGallery.d.ts +53 -0
- package/dist/space-sdk/src/ui/gallery/ImageViewer.d.ts +27 -0
- package/dist/space-sdk/src/ui/gallery/galleryWords.d.ts +95 -0
- package/dist/space-sdk/src/ui/gallery/index.d.ts +5 -0
- package/dist/space-sdk/src/ui/icons.d.ts +13 -0
- package/dist/space-sdk/src/ui/index.d.ts +54 -0
- package/dist/space-sdk/src/ui/keycap/Keycap.d.ts +22 -0
- package/dist/space-sdk/src/ui/keycap/index.d.ts +2 -0
- package/dist/space-sdk/src/ui/layout/Panels.d.ts +50 -0
- package/dist/space-sdk/src/ui/layout/chatPanelEdge.d.ts +77 -0
- package/dist/space-sdk/src/ui/layout/index.d.ts +5 -0
- package/dist/space-sdk/src/ui/layout/panelMath.d.ts +91 -0
- package/dist/space-sdk/src/ui/list/ListReader.d.ts +380 -0
- package/dist/space-sdk/src/ui/list/Row.d.ts +145 -0
- package/dist/space-sdk/src/ui/list/SelectionBar.d.ts +65 -0
- package/dist/space-sdk/src/ui/list/index.d.ts +14 -0
- package/dist/space-sdk/src/ui/list/rowState.d.ts +22 -0
- package/dist/space-sdk/src/ui/list/useListKeys.d.ts +89 -0
- package/dist/space-sdk/src/ui/list/useReorder.d.ts +86 -0
- package/dist/space-sdk/src/ui/list/useSelection.d.ts +90 -0
- package/dist/space-sdk/src/ui/open/OpenAsMenu.d.ts +15 -0
- package/dist/space-sdk/src/ui/open/index.d.ts +6 -0
- package/dist/space-sdk/src/ui/open/openModeStore.d.ts +39 -0
- package/dist/space-sdk/src/ui/open/useOpenMode.d.ts +17 -0
- package/dist/space-sdk/src/ui/overlay/Menu.d.ts +88 -0
- package/dist/space-sdk/src/ui/overlay/Popover.d.ts +28 -0
- package/dist/space-sdk/src/ui/overlay/Tooltip.d.ts +19 -0
- package/dist/space-sdk/src/ui/overlay/index.d.ts +9 -0
- package/dist/space-sdk/src/ui/overlay/layerRoot.d.ts +24 -0
- package/dist/space-sdk/src/ui/overlay/position.d.ts +31 -0
- package/dist/space-sdk/src/ui/period/PeriodPicker.d.ts +30 -0
- package/dist/space-sdk/src/ui/period/dateFormat.d.ts +50 -0
- package/dist/space-sdk/src/ui/period/dateWords.d.ts +88 -0
- package/dist/space-sdk/src/ui/period/periods.d.ts +70 -0
- package/dist/space-sdk/src/ui/period/usePeriod.d.ts +23 -0
- package/dist/space-sdk/src/ui/present/index.d.ts +3 -0
- package/dist/space-sdk/src/ui/present/presentWords.d.ts +27 -0
- package/dist/space-sdk/src/ui/present/screens.d.ts +36 -0
- package/dist/space-sdk/src/ui/present/useAudienceScreen.d.ts +38 -0
- package/dist/space-sdk/src/ui/styles.d.ts +21 -0
- package/dist/space-sdk/src/ui/timeline/TimelineView.d.ts +44 -0
- package/dist/space-sdk/src/ui/timeline/timelineMath.d.ts +123 -0
- package/dist/space-sdk/src/viewPeriod.d.ts +8 -0
- package/dist/space-sdk/src/vite.ts +92 -0
- package/dist/space-sdk/src/words/actions.ts +295 -0
- package/dist/space-sdk/src/words/clashes.ts +158 -0
- package/dist/space-sdk/src/words/format.ts +136 -0
- package/dist/space-sdk/src/words/index.ts +13 -0
- package/dist/space-sdk/src/words/keymap.ts +72 -0
- package/dist/space-sdk/src/words/keys.ts +297 -0
- package/dist/space-sdk/src/words/shell.ts +46 -0
- package/dist/space-sdk/src/words/types.ts +65 -0
- package/dist/view-renderer/dist/host.css +1 -0
- package/dist/view-renderer/dist/host.js +2374 -0
- package/dist/view-renderer/dist/theme.css +73 -0
- package/dist/view-renderer/src/dom.js +212 -0
- package/dist/view-renderer/src/errors.js +8 -0
- package/dist/view-renderer/src/host.tsx +250 -0
- package/dist/view-renderer/src/index.js +4 -0
- package/dist/view-renderer/src/png.js +213 -0
- package/dist/view-renderer/src/pool.js +110 -0
- package/dist/view-renderer/src/remote-broker.js +59 -0
- package/dist/view-renderer/src/renderer.js +279 -0
- package/package.json +21 -11
- package/skills/notis-cli/AGENT_INSTRUCTIONS.md +63 -12
- package/skills/notis-onboarding/BRIEF.md +14 -9
- package/skills/notis-query/cli.md +1 -1
- package/skills/notis-spaces/cli.md +540 -0
- package/src/cli.js +8 -8
- package/src/command-specs/agents.js +121 -8
- package/src/command-specs/auth.js +3 -3
- package/src/command-specs/diagnostics.js +97 -20
- package/src/command-specs/documents.js +158 -0
- package/src/command-specs/files.js +29 -0
- package/src/command-specs/handover.js +331 -79
- package/src/command-specs/helpers.js +50 -40
- package/src/command-specs/index.js +14 -5
- package/src/command-specs/meta.js +38 -9
- package/src/command-specs/onboarding.js +1 -1
- package/src/command-specs/profile.js +42 -1
- package/src/command-specs/skills.js +314 -9
- package/src/command-specs/smoke.js +16 -4
- package/src/command-specs/spaces.js +783 -0
- package/src/command-specs/tools.js +118 -21
- package/src/command-specs/version-history.js +20 -0
- package/src/command-specs/views.js +69 -0
- package/src/runtime/agent-browser.js +178 -267
- package/src/runtime/agent-setup.js +172 -13
- package/src/runtime/app-boundary-validator.js +338 -2
- package/src/runtime/app-data-literals.js +82 -0
- package/src/runtime/app-platform.js +750 -1570
- package/src/runtime/auth-recovery.js +17 -0
- package/src/runtime/base-skills.d.ts +11 -0
- package/src/runtime/base-skills.js +100 -3
- package/src/runtime/computer-identity.d.ts +30 -0
- package/src/runtime/computer-identity.js +151 -0
- package/src/runtime/config-lock.js +135 -0
- package/src/runtime/confined-space-build.js +74 -0
- package/src/runtime/confined-space-verify.js +49 -0
- package/src/runtime/delegated-context.js +5 -21
- package/src/runtime/native-record-files.js +47 -0
- package/src/runtime/oauth.js +342 -31
- package/src/runtime/profiles.js +19 -112
- package/src/runtime/retired-sdk-files.js +24 -0
- package/src/runtime/retry.js +150 -0
- package/src/runtime/skill-sync/cloud-client.ts +33 -8
- package/src/runtime/skill-sync/index.ts +443 -106
- package/src/runtime/skill-sync/local-scanner.ts +248 -32
- package/src/runtime/skill-sync/native-identity.ts +102 -0
- package/src/runtime/skill-sync/native-plan.ts +70 -0
- package/src/runtime/skill-sync/symlink-manager.ts +66 -16
- package/src/runtime/skill-sync/sync-plan.ts +34 -2
- package/src/runtime/skill-sync/types.ts +54 -0
- package/src/runtime/skill-sync/write-cloud-skill.ts +4 -4
- package/src/runtime/skill-sync-service.js +109 -0
- package/src/runtime/source-root.js +32 -0
- package/src/runtime/space-collection-scaffold.js +107 -0
- package/src/runtime/space-database-structures.js +229 -0
- package/src/runtime/space-fixture-broker.js +68 -0
- package/src/runtime/space-lock.js +337 -0
- package/src/runtime/space-platform.js +133 -0
- package/src/runtime/space-source.js +290 -0
- package/src/runtime/space-test-server.js +354 -0
- package/src/runtime/space-verification.js +94 -0
- package/src/runtime/space-verify-browser-worker.js +51 -0
- package/src/runtime/space-view-manifest.js +368 -0
- package/src/runtime/sync-skills.d.ts +5 -1
- package/src/runtime/sync-skills.js +11 -2
- package/src/runtime/tool-confirmation.js +138 -0
- package/src/runtime/transport.js +118 -24
- package/src/runtime/upsell.js +219 -0
- package/src/runtime/view-render.js +49 -0
- package/src/skill-sync-worker-entry.js +2 -0
- package/src/skill-sync-worker.js +114 -0
- package/src/space-harness-host.ts +122 -0
- package/template/.harness/index.html.tmpl +9 -352
- package/template/app/globals.css +29 -3
- package/template/app/layout.tsx +2 -6
- package/template/components/ui/badge.tsx +7 -4
- package/template/components/ui/button.tsx +1 -1
- package/template/components/ui/native-select.tsx +24 -0
- package/template/notis.config.ts +4 -36
- package/template/package-lock.json +1800 -1867
- package/template/package.json +16 -14
- package/template/postcss.config.mjs +1 -1
- package/template/tailwind.config.ts +1 -6
- package/template/tsconfig.json +1 -0
- package/template/vite.config.ts +2 -2
- package/dist/base-skills/notis-apps/SKILL.md +0 -613
- package/skills/notis-apps/cli.md +0 -285
- package/src/command-specs/apps.js +0 -3011
- package/src/runtime/app-changelog.js +0 -79
- package/src/runtime/app-dev-consumers.js +0 -154
- package/src/runtime/app-dev-host-lock.js +0 -80
- package/src/runtime/app-dev-process-identity.js +0 -111
- package/src/runtime/app-dev-roots.js +0 -284
- package/src/runtime/app-dev-server.js +0 -1140
- package/src/runtime/app-dev-sessions.js +0 -185
- package/src/runtime/app-registry-scaffolds.js +0 -367
- package/src/runtime/assets/store-screenshot-dark.png +0 -0
- package/src/runtime/cli-mode.generated.js +0 -5
- package/src/runtime/cli-mode.js +0 -34
- package/src/runtime/store-screenshot.js +0 -143
- package/template/CHANGELOG.md +0 -5
- package/template/app/page.tsx +0 -60
- package/template/components/ui/card.tsx +0 -56
- package/template/packages/sdk/src/components/DocumentEditor.tsx +0 -103
- package/template/packages/sdk/src/config.ts +0 -259
- package/template/packages/sdk/src/hooks/useCloudComputer.ts +0 -97
- package/template/packages/sdk/src/hooks/useDatabaseSchema.ts +0 -85
- package/template/packages/sdk/src/hooks/useDocument.ts +0 -78
- package/template/packages/sdk/src/hooks/useNotisNavigation.ts +0 -52
- package/template/packages/sdk/src/hooks/useTopBarSearch.ts +0 -73
- package/template/packages/sdk/src/runtime.ts +0 -439
- package/template/packages/sdk/src/vite.ts +0 -56
- package/template/packages/sdk/tsconfig.json +0 -15
- /package/{template/packages → dist}/sdk/src/components/MultiSelectDragOverlay.tsx +0 -0
- /package/{template/packages → dist}/sdk/src/components/ShortcutHints.tsx +0 -0
- /package/{template/packages → dist}/sdk/src/hooks/useActiveResource.ts +0 -0
- /package/{template/packages → dist}/sdk/src/hooks/useTool.ts +0 -0
- /package/{template/packages → dist}/sdk/src/hooks/useTools.ts +0 -0
- /package/{template/packages → dist}/sdk/src/ui.ts +0 -0
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import * as ReactDOM from 'react-dom';
|
|
3
|
+
import * as ReactDOMClient from 'react-dom/client';
|
|
4
|
+
import * as JSXRuntime from 'react/jsx-runtime';
|
|
5
|
+
import { importBundleSource, resolveBundleRouteExport } from '../../sdk/src/bundleModule';
|
|
6
|
+
import { SdkPresentation } from '../../sdk/src/presentation';
|
|
7
|
+
import { createPrefetchQueue, createQueryClient } from '../../sdk/src/queryCache';
|
|
8
|
+
import type { NotisRuntime } from '../../sdk/src/runtime';
|
|
9
|
+
import { SPACE_VIEWER_READ_OPERATIONS } from '../../sdk/src/space';
|
|
10
|
+
import * as NotisSDK from '../../sdk/src/index';
|
|
11
|
+
import * as NotisSDKUI from '../../sdk/src/ui/index';
|
|
12
|
+
// The toolkit stylesheet the host adopts into every Space shadow root (esbuild text import).
|
|
13
|
+
import toolkitCss from '../../sdk/src/ui/toolkit.css' with { type: 'text' };
|
|
14
|
+
import type { SpaceActionOptions, SpaceDocumentBodyRequest, SpaceViewerReadOperation } from '../../sdk/src/space';
|
|
15
|
+
|
|
16
|
+
type Call = { op: string; actionId?: string; ok: boolean | null; error?: string };
|
|
17
|
+
const state = { mounted: false, renderStarted: false, errors: [] as Array<{ phase: string; message: string }>, runtimeCalls: [] as Call[] };
|
|
18
|
+
// The Space runtime contract (packages/sdk/src/runtimeModules.ts): bundles import React and the SDK from these.
|
|
19
|
+
Object.assign(window, { __harness: state, React, ReactDOM, ReactDOMClient, __ReactJSXRuntime: JSXRuntime,
|
|
20
|
+
__NotisSDK: NotisSDK, __NotisSDKUI: NotisSDKUI });
|
|
21
|
+
NotisSDKUI.registerToolkitStyles(toolkitCss);
|
|
22
|
+
const diagnostic = (phase: string, reason: unknown) => state.errors.push({ phase,
|
|
23
|
+
message: reason instanceof Error ? reason.message : String(reason || 'Verification failed.') });
|
|
24
|
+
window.addEventListener('error', event => diagnostic('window_error', event.error || event.message));
|
|
25
|
+
window.addEventListener('unhandledrejection', event => diagnostic('unhandled_rejection', event.reason));
|
|
26
|
+
window.addEventListener('securitypolicyviolation', event => diagnostic('security_policy', `Blocked ${event.violatedDirective}`));
|
|
27
|
+
|
|
28
|
+
async function start() {
|
|
29
|
+
const response = await fetch('/snapshot', { credentials: 'omit' });
|
|
30
|
+
if (!response.ok) throw new Error('The frozen verification snapshot could not be loaded.');
|
|
31
|
+
const snapshot = await response.json();
|
|
32
|
+
const authority = structuredClone(snapshot.descriptor.space);
|
|
33
|
+
const runFixture = async (call: Call, input: unknown) => {
|
|
34
|
+
state.runtimeCalls.push(call);
|
|
35
|
+
try {
|
|
36
|
+
const result = await fetch('/fixture', { method: 'POST', credentials: 'omit',
|
|
37
|
+
headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(input), signal: AbortSignal.timeout(5_000) });
|
|
38
|
+
const payload = await result.json();
|
|
39
|
+
if (!result.ok) throw new Error(payload.message || 'No matching synthetic fixture.');
|
|
40
|
+
call.ok = true; return payload.result;
|
|
41
|
+
} catch (error) {
|
|
42
|
+
call.ok = false; call.error = error instanceof Error ? error.message : 'Verification request failed.';
|
|
43
|
+
throw error;
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
const protocolFailure = (message: string): Promise<never> => { diagnostic('protocol', message); return Promise.reject(new Error(message)); };
|
|
47
|
+
const deny = () => protocolFailure('Use a declared Space action.');
|
|
48
|
+
const queue = createPrefetchQueue(2);
|
|
49
|
+
const runtime: NotisRuntime = {
|
|
50
|
+
...snapshot.descriptor, databases: [],
|
|
51
|
+
context: { ...snapshot.descriptor.context,
|
|
52
|
+
resourceId: snapshot.descriptor.context?.resource_id ?? snapshot.descriptor.context?.resourceId ?? null,
|
|
53
|
+
collectionItem: snapshot.descriptor.context?.collection_item ?? snapshot.descriptor.context?.collectionItem ?? null },
|
|
54
|
+
queryClient: createQueryClient({ maxEntries: 100, schedule: queue }),
|
|
55
|
+
listTools: deny, callTool: deny, request: deny,
|
|
56
|
+
callAction<T>(id: string, inputs: Record<string, unknown> = {}, options: SpaceActionOptions = {}): Promise<T> {
|
|
57
|
+
if (!Object.hasOwn(authority.actions, id)) return protocolFailure('Undeclared verification action.');
|
|
58
|
+
if ((options.readOnly || options.dedupe) && authority.actions[id].readOnly !== true) {
|
|
59
|
+
return protocolFailure('A write action cannot run as a cached read.');
|
|
60
|
+
}
|
|
61
|
+
return runFixture({ op: 'callAction', actionId: id, ok: null }, { action_id: id, inputs });
|
|
62
|
+
},
|
|
63
|
+
viewerRead: authority.viewerReads?.length ? <T,>(operation: SpaceViewerReadOperation, input: Record<string, unknown> = {}): Promise<T> => {
|
|
64
|
+
const family = Object.hasOwn(SPACE_VIEWER_READ_OPERATIONS, operation) ? SPACE_VIEWER_READ_OPERATIONS[operation] : null;
|
|
65
|
+
if (!family || !authority.viewerReads.includes(family)) return protocolFailure('Undeclared verification viewer read.');
|
|
66
|
+
return runFixture({ op: 'viewerRead', actionId: operation, ok: null }, { viewer_read: { operation, input } });
|
|
67
|
+
} : undefined,
|
|
68
|
+
shown: Object.values(authority.shows || {}).some(list => 'database' in list) ? <T,>(name: string, params: Record<string, unknown> = {}): Promise<T> => {
|
|
69
|
+
const list = authority.shows && Object.hasOwn(authority.shows, name) ? authority.shows[name] : null;
|
|
70
|
+
if (!list || !('database' in list)) return protocolFailure('Undeclared verification list.');
|
|
71
|
+
return runFixture({ op: 'shown', actionId: name, ok: null }, { shown: { name, params } });
|
|
72
|
+
} : undefined,
|
|
73
|
+
documentBody(request: SpaceDocumentBodyRequest) {
|
|
74
|
+
return runFixture({ op: 'documentBody', actionId: request?.readAction, ok: null }, { document_body: request });
|
|
75
|
+
},
|
|
76
|
+
navigate(payload) {
|
|
77
|
+
// A view changing its own params (useViewParams().setParams): recorded, the view keeps its synthetic params.
|
|
78
|
+
if (payload.kind === 'view-params') {
|
|
79
|
+
const params = payload.params;
|
|
80
|
+
if (!params || typeof params !== 'object' || Array.isArray(params)
|
|
81
|
+
|| Object.keys(payload).some(key => !['kind', 'params', 'replace'].includes(key))
|
|
82
|
+
|| Object.values(params).some(value => !['string', 'number', 'boolean'].includes(typeof value))) {
|
|
83
|
+
return protocolFailure('View params must be an object of text, number or true/false values.');
|
|
84
|
+
}
|
|
85
|
+
state.runtimeCalls.push({ op: 'navigate', actionId: 'view-params', ok: true });
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
if (payload.kind !== 'space-reference' || typeof payload.alias !== 'string' || !authority.navigation?.includes(payload.alias)) {
|
|
89
|
+
return protocolFailure('Offline navigation requires a declared synthetic destination.');
|
|
90
|
+
}
|
|
91
|
+
// This observes a declaration only; no live navigation or access is claimed.
|
|
92
|
+
state.runtimeCalls.push({ op: 'navigate', actionId: payload.alias, ok: true });
|
|
93
|
+
},
|
|
94
|
+
publishActiveResource() {}, captureContextSelection() {},
|
|
95
|
+
addContext: async () => false, updateContext: async () => false, removeContext: async () => false,
|
|
96
|
+
registerTopBarSearch() {}, setTopBarSearchValue() {}, setTopBarSearchLoading() {},
|
|
97
|
+
};
|
|
98
|
+
const module = await importBundleSource(snapshot.source);
|
|
99
|
+
const view = resolveBundleRouteExport(module, ['SpaceView'], true);
|
|
100
|
+
if (!view) throw new Error('The SpaceView export is missing from this presentation.');
|
|
101
|
+
const host = document.createElement('div'); host.style.cssText = 'min-height:100vh;height:100vh';
|
|
102
|
+
const shadow = host.attachShadow({ mode: 'open' });
|
|
103
|
+
const css = document.createElement('style'); css.textContent = snapshot.css; shadow.appendChild(css);
|
|
104
|
+
NotisSDKUI.adoptToolkitStyles(shadow);
|
|
105
|
+
const mount = document.createElement('div'); mount.setAttribute('data-notis-app-mount', 'true');
|
|
106
|
+
mount.style.cssText = 'min-height:0;height:100%'; shadow.appendChild(mount);
|
|
107
|
+
document.body.appendChild(host);
|
|
108
|
+
const controller = document.createElement('div'); document.body.appendChild(controller);
|
|
109
|
+
const mode = new URLSearchParams(location.search).get('theme') === 'dark' ? 'dark' : 'light';
|
|
110
|
+
document.documentElement.classList.toggle('dark', mode === 'dark');
|
|
111
|
+
state.renderStarted = true;
|
|
112
|
+
ReactDOMClient.createRoot(controller).render(React.createElement(SdkPresentation, {
|
|
113
|
+
mount, runtime, component: view.component, shell: module.__AppShell, theme: { mode, style: { colorScheme: mode } },
|
|
114
|
+
resetKey: snapshot.cacheKey,
|
|
115
|
+
onCommit: (hasContent: boolean) => { state.mounted = hasContent; },
|
|
116
|
+
onError: (error: Error) => { state.mounted = false; state.errors.push({ phase: 'render', message: error.message }); },
|
|
117
|
+
onProtocolError: (error: Error) => diagnostic('protocol', error),
|
|
118
|
+
fallback: (error: Error) => React.createElement('div', { role: 'alert' }, error.message),
|
|
119
|
+
}));
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
void start().catch(reason => state.errors.push({ phase: 'boot', message: reason instanceof Error ? reason.message : 'Verification did not start.' }));
|
|
@@ -2,26 +2,13 @@
|
|
|
2
2
|
<html>
|
|
3
3
|
<head>
|
|
4
4
|
<meta charset="utf-8">
|
|
5
|
-
<title>Notis
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
<script type="importmap">
|
|
13
|
-
{
|
|
14
|
-
"imports": {
|
|
15
|
-
"react": "https://esm.sh/react@{{REACT_VERSION}}",
|
|
16
|
-
"react-dom": "https://esm.sh/react-dom@{{REACT_VERSION}}",
|
|
17
|
-
"react/jsx-runtime": "https://esm.sh/react@{{REACT_VERSION}}/jsx-runtime",
|
|
18
|
-
"react-dom/client": "https://esm.sh/react-dom@{{REACT_VERSION}}/client"
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
</script>
|
|
22
|
-
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
23
|
-
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
24
|
-
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap">
|
|
5
|
+
<title>Notis Space theme</title>
|
|
6
|
+
<!--
|
|
7
|
+
Canonical CLI and SDK theme. Only the style block below is read: the CLI
|
|
8
|
+
verification server serves it as /theme.css, and the view renderer build
|
|
9
|
+
writes it to dist/theme.css, which the renderer digest covers. Keep its
|
|
10
|
+
bytes stable. Nothing else in this file is served or copied into scaffolds.
|
|
11
|
+
-->
|
|
25
12
|
<style>
|
|
26
13
|
/*
|
|
27
14
|
* Portal-parity theme tokens. In production the portal copies its computed
|
|
@@ -93,338 +80,8 @@
|
|
|
93
80
|
color: hsl(var(--foreground));
|
|
94
81
|
-webkit-font-smoothing: antialiased;
|
|
95
82
|
}
|
|
96
|
-
#
|
|
97
|
-
#root { padding-top: 24px; min-height: 100vh; }
|
|
83
|
+
#root { min-height: 100vh; }
|
|
98
84
|
</style>
|
|
99
85
|
</head>
|
|
100
|
-
<body>
|
|
101
|
-
<div id="harness-status">harness: booting</div>
|
|
102
|
-
<div id="root"></div>
|
|
103
|
-
<script type="module">
|
|
104
|
-
const routeExport = {{ROUTE_EXPORT}};
|
|
105
|
-
const descriptor = {{RUNTIME_DESCRIPTOR}};
|
|
106
|
-
const mode = {{MODE}};
|
|
107
|
-
const apiBase = {{API_BASE}};
|
|
108
|
-
const jwt = {{JWT}};
|
|
109
|
-
const fixtures = {{FIXTURES}};
|
|
110
|
-
|
|
111
|
-
/**
|
|
112
|
-
* Resolves the canned response for one tool call.
|
|
113
|
-
*
|
|
114
|
-
* A plain `"TOOL_NAME"` key answers every call to that tool. An app that
|
|
115
|
-
* reaches several databases through a single tool needs to vary the
|
|
116
|
-
* payload per call, so a key may also be scoped to one argument with
|
|
117
|
-
* `"TOOL_NAME#arg=value"` — for example
|
|
118
|
-
* `"LOCAL_NOTIS_DATABASE_QUERY#database_slug=notes"`. Scoped keys are
|
|
119
|
-
* checked first; the unscoped key stays the fallback.
|
|
120
|
-
*/
|
|
121
|
-
function lookupToolFixture(name, args) {
|
|
122
|
-
const tools = fixtures && fixtures.tools;
|
|
123
|
-
if (!tools) return undefined;
|
|
124
|
-
for (const key of Object.keys(tools)) {
|
|
125
|
-
const sep = key.indexOf('#');
|
|
126
|
-
if (sep === -1 || key.slice(0, sep) !== name) continue;
|
|
127
|
-
const scope = key.slice(sep + 1);
|
|
128
|
-
const eq = scope.indexOf('=');
|
|
129
|
-
if (eq === -1) continue;
|
|
130
|
-
if (String(args[scope.slice(0, eq)]) === scope.slice(eq + 1)) {
|
|
131
|
-
return tools[key];
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
return Object.prototype.hasOwnProperty.call(tools, name) ? tools[name] : undefined;
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
const status = document.getElementById('harness-status');
|
|
138
|
-
const setStatus = (msg, color = '#0f0') => {
|
|
139
|
-
status.textContent = `harness: ${msg}`;
|
|
140
|
-
status.style.color = color;
|
|
141
|
-
};
|
|
142
|
-
|
|
143
|
-
window.__harness = {
|
|
144
|
-
errors: [],
|
|
145
|
-
runtimeCalls: [],
|
|
146
|
-
renderStarted: false,
|
|
147
|
-
mounted: false,
|
|
148
|
-
mode,
|
|
149
|
-
route: descriptor.route && descriptor.route.slug,
|
|
150
|
-
scenario: descriptor.context && descriptor.context.screenshotScenario,
|
|
151
|
-
};
|
|
152
|
-
|
|
153
|
-
window.addEventListener('error', (event) => {
|
|
154
|
-
window.__harness.errors.push({
|
|
155
|
-
type: 'window.error',
|
|
156
|
-
message: event.message,
|
|
157
|
-
stack: event.error && event.error.stack,
|
|
158
|
-
});
|
|
159
|
-
});
|
|
160
|
-
window.addEventListener('unhandledrejection', (event) => {
|
|
161
|
-
window.__harness.errors.push({
|
|
162
|
-
type: 'unhandledrejection',
|
|
163
|
-
reason: String((event.reason && event.reason.stack) || event.reason),
|
|
164
|
-
});
|
|
165
|
-
});
|
|
166
|
-
|
|
167
|
-
/**
|
|
168
|
-
* Records one runtime call and hands back the entry so the caller can
|
|
169
|
-
* stamp its outcome once the promise settles. Verify reads `ok` to tell a
|
|
170
|
-
* route that rendered from real data apart from one that only rendered its
|
|
171
|
-
* error states, so every runtime path must settle its own entry.
|
|
172
|
-
*/
|
|
173
|
-
function record(op, args) {
|
|
174
|
-
const entry = { op, args, ok: null, error: null, durationMs: null };
|
|
175
|
-
entry.startedAt = Date.now();
|
|
176
|
-
window.__harness.runtimeCalls.push(entry);
|
|
177
|
-
return entry;
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
function settle(entry, error) {
|
|
181
|
-
entry.durationMs = Date.now() - entry.startedAt;
|
|
182
|
-
delete entry.startedAt;
|
|
183
|
-
entry.ok = !error;
|
|
184
|
-
entry.error = error ? (error.message ? String(error.message) : String(error)) : null;
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
async function tracked(entry, run) {
|
|
188
|
-
try {
|
|
189
|
-
const value = await run();
|
|
190
|
-
settle(entry, null);
|
|
191
|
-
return value;
|
|
192
|
-
} catch (error) {
|
|
193
|
-
settle(entry, error);
|
|
194
|
-
throw error;
|
|
195
|
-
}
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
async function readJsonOrSnippet(response) {
|
|
199
|
-
const text = await response.text().catch(() => '');
|
|
200
|
-
if (!text) return { payload: null, snippet: null };
|
|
201
|
-
try {
|
|
202
|
-
return { payload: JSON.parse(text), snippet: null };
|
|
203
|
-
} catch {
|
|
204
|
-
const trimmed = text.trim();
|
|
205
|
-
return { payload: null, snippet: trimmed.length > 120 ? `${trimmed.slice(0, 120)}...` : trimmed };
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
async function runtimeQuery(body) {
|
|
210
|
-
if (!apiBase || !jwt || !descriptor.app || !descriptor.app.id) {
|
|
211
|
-
throw new Error('live harness mode requires apiBase, jwt, and app id');
|
|
212
|
-
}
|
|
213
|
-
const response = await fetch(`${String(apiBase).replace(/\/$/, '')}/portal_views/runtime_query`, {
|
|
214
|
-
method: 'POST',
|
|
215
|
-
headers: {
|
|
216
|
-
'Content-Type': 'application/json',
|
|
217
|
-
Authorization: `Bearer ${jwt}`,
|
|
218
|
-
},
|
|
219
|
-
body: JSON.stringify({
|
|
220
|
-
app_id: descriptor.app.id,
|
|
221
|
-
route_slug: descriptor.route && descriptor.route.slug,
|
|
222
|
-
...body,
|
|
223
|
-
}),
|
|
224
|
-
});
|
|
225
|
-
const { payload, snippet } = await readJsonOrSnippet(response);
|
|
226
|
-
if (!response.ok) {
|
|
227
|
-
const message = (payload && (payload.error || payload.message)) || snippet || `status ${response.status}`;
|
|
228
|
-
throw new Error(`Runtime request failed: ${message}`);
|
|
229
|
-
}
|
|
230
|
-
if (!payload) {
|
|
231
|
-
throw new Error(snippet ? `Runtime response was not JSON: ${snippet}` : 'Runtime response was empty');
|
|
232
|
-
}
|
|
233
|
-
if (payload.status === 'error' || payload.error) {
|
|
234
|
-
throw new Error(payload.message || payload.error || 'Runtime request failed');
|
|
235
|
-
}
|
|
236
|
-
return payload;
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
function stubRuntime() {
|
|
240
|
-
return {
|
|
241
|
-
app: descriptor.app,
|
|
242
|
-
route: descriptor.route,
|
|
243
|
-
context: descriptor.context || {},
|
|
244
|
-
navigate: (args) => {
|
|
245
|
-
settle(record('navigate', args), null);
|
|
246
|
-
},
|
|
247
|
-
// There is no manager chat here, so the handover is recorded and
|
|
248
|
-
// reported as drafted without any UI.
|
|
249
|
-
handover: async (payload) => {
|
|
250
|
-
settle(record('handover', payload), null);
|
|
251
|
-
return { status: 'drafted' };
|
|
252
|
-
},
|
|
253
|
-
registerTopBarSearch: () => {},
|
|
254
|
-
setTopBarSearchValue: () => {},
|
|
255
|
-
setTopBarSearchLoading: () => {},
|
|
256
|
-
// No change feed here, so `useDatabaseSubscription` reports live=false
|
|
257
|
-
// and the app keeps whatever manual refresh it offers.
|
|
258
|
-
subscribeDatabase: () => () => {},
|
|
259
|
-
// There is no cloud computer behind the harness. Answering "not
|
|
260
|
-
// available" rather than throwing keeps `useCloudComputer` on the same
|
|
261
|
-
// fallback branch a user without a cloud computer would see.
|
|
262
|
-
cloudComputerFacts: async () => tracked(
|
|
263
|
-
record('cloudComputerFacts', {}),
|
|
264
|
-
async () => ({
|
|
265
|
-
available: false,
|
|
266
|
-
reason: 'unsupported_host',
|
|
267
|
-
sandbox: null,
|
|
268
|
-
cli_auth: {
|
|
269
|
-
gh: { authenticated: null, account: null, checked_at: null, reason: 'unsupported_host' },
|
|
270
|
-
},
|
|
271
|
-
}),
|
|
272
|
-
),
|
|
273
|
-
listTools: async () => tracked(
|
|
274
|
-
record('listTools', {}),
|
|
275
|
-
async () => descriptor.tools || [],
|
|
276
|
-
),
|
|
277
|
-
callTool: async (name, args) => tracked(
|
|
278
|
-
record('callTool', { name, arguments: args || {} }),
|
|
279
|
-
async () => {
|
|
280
|
-
const fixture = lookupToolFixture(name, args || {});
|
|
281
|
-
if (fixture !== undefined) {
|
|
282
|
-
return structuredClone(fixture);
|
|
283
|
-
}
|
|
284
|
-
return { ok: true, result: null };
|
|
285
|
-
},
|
|
286
|
-
),
|
|
287
|
-
request: async (path, options) => tracked(
|
|
288
|
-
record('request', { path, options }),
|
|
289
|
-
async () => {
|
|
290
|
-
if (fixtures && fixtures.requests && Object.prototype.hasOwnProperty.call(fixtures.requests, path)) {
|
|
291
|
-
return structuredClone(fixtures.requests[path]);
|
|
292
|
-
}
|
|
293
|
-
return null;
|
|
294
|
-
},
|
|
295
|
-
),
|
|
296
|
-
};
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
const delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
300
|
-
|
|
301
|
-
async function applyScenarioActions() {
|
|
302
|
-
const actions = fixtures && fixtures.scenario && Array.isArray(fixtures.scenario.actions)
|
|
303
|
-
? fixtures.scenario.actions
|
|
304
|
-
: [];
|
|
305
|
-
for (const action of actions) {
|
|
306
|
-
if (action && action.type === 'wait') {
|
|
307
|
-
await delay(Math.max(0, Number(action.ms) || 0));
|
|
308
|
-
continue;
|
|
309
|
-
}
|
|
310
|
-
if (action && action.type === 'click' && typeof action.selector === 'string') {
|
|
311
|
-
const deadline = Date.now() + 5000;
|
|
312
|
-
let element = null;
|
|
313
|
-
while (!element && Date.now() < deadline) {
|
|
314
|
-
element = document.querySelector(action.selector);
|
|
315
|
-
if (!element) await delay(50);
|
|
316
|
-
}
|
|
317
|
-
if (!element || typeof element.click !== 'function') {
|
|
318
|
-
throw new Error(`Screenshot scenario could not click ${action.selector}`);
|
|
319
|
-
}
|
|
320
|
-
element.click();
|
|
321
|
-
await delay(Number(action.settle_ms) || 350);
|
|
322
|
-
}
|
|
323
|
-
}
|
|
324
|
-
}
|
|
325
|
-
|
|
326
|
-
function liveRuntime() {
|
|
327
|
-
return {
|
|
328
|
-
...stubRuntime(),
|
|
329
|
-
listTools: async () => tracked(
|
|
330
|
-
record('listTools', {}),
|
|
331
|
-
async () => {
|
|
332
|
-
const result = await runtimeQuery({ method: 'tools/list' });
|
|
333
|
-
return result.tools || [];
|
|
334
|
-
},
|
|
335
|
-
),
|
|
336
|
-
callTool: async (name, args) => tracked(
|
|
337
|
-
record('callTool', { name, arguments: args || {} }),
|
|
338
|
-
async () => runtimeQuery({ method: 'tools/call', name, arguments: args || {} }),
|
|
339
|
-
),
|
|
340
|
-
// Live mode must not inherit the stub's canned answer: it would settle
|
|
341
|
-
// ok: true with fake data and soften the all-calls-failed assertion.
|
|
342
|
-
cloudComputerFacts: async (options) => tracked(
|
|
343
|
-
record('cloudComputerFacts', options || {}),
|
|
344
|
-
async () => runtimeQuery({
|
|
345
|
-
method: 'cloud_computer/facts',
|
|
346
|
-
...(options && options.refresh ? { refresh: true } : {}),
|
|
347
|
-
}),
|
|
348
|
-
),
|
|
349
|
-
request: async (path, options) => tracked(
|
|
350
|
-
record('request', { path, options }),
|
|
351
|
-
async () => {
|
|
352
|
-
const response = await fetch(`${String(apiBase).replace(/\/$/, '')}${path}`, {
|
|
353
|
-
method: (options && options.method) || 'GET',
|
|
354
|
-
headers: {
|
|
355
|
-
Authorization: `Bearer ${jwt}`,
|
|
356
|
-
...((options && options.body) ? { 'Content-Type': 'application/json' } : {}),
|
|
357
|
-
...((options && options.headers) || {}),
|
|
358
|
-
},
|
|
359
|
-
body: options && options.body ? JSON.stringify(options.body) : undefined,
|
|
360
|
-
});
|
|
361
|
-
const { payload, snippet } = await readJsonOrSnippet(response);
|
|
362
|
-
if (!response.ok) {
|
|
363
|
-
throw new Error((payload && (payload.error || payload.message)) || snippet || `Request failed with status ${response.status}`);
|
|
364
|
-
}
|
|
365
|
-
return payload;
|
|
366
|
-
},
|
|
367
|
-
),
|
|
368
|
-
};
|
|
369
|
-
}
|
|
370
|
-
|
|
371
|
-
try {
|
|
372
|
-
setStatus('loading react');
|
|
373
|
-
const React = await import('react');
|
|
374
|
-
const { createRoot } = await import('react-dom/client');
|
|
375
|
-
|
|
376
|
-
setStatus('loading bundle');
|
|
377
|
-
const bundle = await import('./bundle/app.js');
|
|
378
|
-
|
|
379
|
-
setStatus('binding runtime context');
|
|
380
|
-
const RuntimeContext = globalThis[Symbol.for('notis.sdk.runtime_context')];
|
|
381
|
-
if (!RuntimeContext) {
|
|
382
|
-
throw new Error('runtime context Symbol not initialized by bundle');
|
|
383
|
-
}
|
|
384
|
-
|
|
385
|
-
const Page = bundle[routeExport];
|
|
386
|
-
if (!Page) {
|
|
387
|
-
throw new Error(`bundle has no ${routeExport} export`);
|
|
388
|
-
}
|
|
389
|
-
const Shell = bundle.__AppShell;
|
|
390
|
-
const runtime = mode === 'live' ? liveRuntime() : stubRuntime();
|
|
391
|
-
const Root = () =>
|
|
392
|
-
React.createElement(
|
|
393
|
-
RuntimeContext.Provider,
|
|
394
|
-
{ value: runtime },
|
|
395
|
-
Shell
|
|
396
|
-
? React.createElement(Shell, null, React.createElement(Page, null))
|
|
397
|
-
: React.createElement(Page, null),
|
|
398
|
-
);
|
|
399
|
-
|
|
400
|
-
setStatus('mounting');
|
|
401
|
-
window.__harness.renderStarted = true;
|
|
402
|
-
createRoot(document.getElementById('root')).render(React.createElement(Root));
|
|
403
|
-
|
|
404
|
-
requestAnimationFrame(() => requestAnimationFrame(async () => {
|
|
405
|
-
try {
|
|
406
|
-
await delay(500);
|
|
407
|
-
await applyScenarioActions();
|
|
408
|
-
window.__harness.mounted = true;
|
|
409
|
-
const errors = window.__harness.errors.length;
|
|
410
|
-
const calls = window.__harness.runtimeCalls.length;
|
|
411
|
-
setStatus(`mounted (errors=${errors}, runtimeCalls=${calls})`, errors ? '#f55' : '#0f0');
|
|
412
|
-
} catch (error) {
|
|
413
|
-
window.__harness.errors.push({
|
|
414
|
-
type: 'scenario',
|
|
415
|
-
message: error && error.message ? error.message : String(error),
|
|
416
|
-
});
|
|
417
|
-
setStatus(`scenario failed: ${error && error.message ? error.message : String(error)}`, '#f55');
|
|
418
|
-
}
|
|
419
|
-
}));
|
|
420
|
-
} catch (error) {
|
|
421
|
-
window.__harness.errors.push({
|
|
422
|
-
type: 'boot',
|
|
423
|
-
message: error && error.message ? error.message : String(error),
|
|
424
|
-
stack: error && error.stack,
|
|
425
|
-
});
|
|
426
|
-
setStatus(`boot failed: ${error && error.message ? error.message : String(error)}`, '#f55');
|
|
427
|
-
}
|
|
428
|
-
</script>
|
|
429
|
-
</body>
|
|
86
|
+
<body></body>
|
|
430
87
|
</html>
|
package/template/app/globals.css
CHANGED
|
@@ -1,3 +1,29 @@
|
|
|
1
|
-
@
|
|
2
|
-
|
|
3
|
-
@tailwind
|
|
1
|
+
@import "tailwindcss" source(none);
|
|
2
|
+
|
|
3
|
+
@config "../tailwind.config.ts";
|
|
4
|
+
@source "./";
|
|
5
|
+
@source "../components";
|
|
6
|
+
@source "../spaces";
|
|
7
|
+
@source "../lib";
|
|
8
|
+
@source "../packages/sdk/src";
|
|
9
|
+
|
|
10
|
+
/* Preserve v3 defaults while keeping the existing Notis theme/config. */
|
|
11
|
+
@theme {
|
|
12
|
+
--default-ring-width: 3px;
|
|
13
|
+
--default-ring-color: hsl(var(--ring) / 0.5);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
@layer base {
|
|
17
|
+
*, ::before, ::after, ::backdrop, ::file-selector-button {
|
|
18
|
+
border-color: var(--color-gray-200, currentColor);
|
|
19
|
+
}
|
|
20
|
+
input::placeholder, textarea::placeholder {
|
|
21
|
+
color: var(--color-gray-400);
|
|
22
|
+
}
|
|
23
|
+
button:not(:disabled), [role="button"]:not(:disabled) {
|
|
24
|
+
cursor: pointer;
|
|
25
|
+
}
|
|
26
|
+
dialog {
|
|
27
|
+
margin: auto;
|
|
28
|
+
}
|
|
29
|
+
}
|
package/template/app/layout.tsx
CHANGED
|
@@ -1,10 +1,6 @@
|
|
|
1
|
-
import '@notis/sdk/styles.css';
|
|
2
|
-
import { ShortcutProvider } from '@notis/sdk/interactions';
|
|
3
1
|
import './globals.css';
|
|
4
2
|
|
|
5
3
|
export default function AppShell({ children }: { children: React.ReactNode }) {
|
|
6
|
-
//
|
|
7
|
-
|
|
8
|
-
// ShortcutProvider is nesting-safe, so the hosted app still has one registry.
|
|
9
|
-
return <ShortcutProvider>{children}</ShortcutProvider>;
|
|
4
|
+
// The host provides the SDK, its keyboard engine and the toolkit stylesheet.
|
|
5
|
+
return <>{children}</>;
|
|
10
6
|
}
|
|
@@ -4,13 +4,16 @@ import { cva, type VariantProps } from 'class-variance-authority';
|
|
|
4
4
|
import { cn } from '@/lib/utils';
|
|
5
5
|
|
|
6
6
|
const badgeVariants = cva(
|
|
7
|
-
'inline-flex items-center rounded-full
|
|
7
|
+
'inline-flex items-center rounded-full px-2.5 py-0.5 text-xs font-medium transition-colors',
|
|
8
8
|
{
|
|
9
9
|
variants: {
|
|
10
10
|
variant: {
|
|
11
|
-
default: '
|
|
12
|
-
secondary: '
|
|
13
|
-
|
|
11
|
+
default: 'bg-primary/10 text-primary',
|
|
12
|
+
secondary: 'bg-foreground/[0.07] text-foreground',
|
|
13
|
+
destructive: 'bg-destructive/10 text-destructive',
|
|
14
|
+
// `outline` is kept for API compatibility and renders as plain text: the
|
|
15
|
+
// design bar has no outlined badges.
|
|
16
|
+
outline: 'bg-transparent text-foreground',
|
|
14
17
|
},
|
|
15
18
|
},
|
|
16
19
|
defaultVariants: {
|
|
@@ -5,7 +5,7 @@ import { cva, type VariantProps } from 'class-variance-authority';
|
|
|
5
5
|
import { cn } from '@/lib/utils';
|
|
6
6
|
|
|
7
7
|
const buttonVariants = cva(
|
|
8
|
-
'inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-
|
|
8
|
+
'inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50',
|
|
9
9
|
{
|
|
10
10
|
variants: {
|
|
11
11
|
variant: {
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { CaretDown } from '@phosphor-icons/react';
|
|
3
|
+
|
|
4
|
+
import { cn } from '@/lib/utils';
|
|
5
|
+
|
|
6
|
+
// Borderless native select: a tinted pill with a caret. Keeps the platform
|
|
7
|
+
// dropdown (no portal needed inside the app surface) and the portal focus ring.
|
|
8
|
+
const NativeSelect = React.forwardRef<HTMLSelectElement, React.SelectHTMLAttributes<HTMLSelectElement>>(
|
|
9
|
+
({ className, children, ...props }, ref) => (
|
|
10
|
+
<span className={cn('relative inline-flex', className)}>
|
|
11
|
+
<select
|
|
12
|
+
ref={ref}
|
|
13
|
+
className="h-9 w-full appearance-none rounded-md bg-muted pl-3 pr-8 text-sm text-foreground outline-hidden transition-colors hover:bg-muted/70 focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background"
|
|
14
|
+
{...props}
|
|
15
|
+
>
|
|
16
|
+
{children}
|
|
17
|
+
</select>
|
|
18
|
+
<CaretDown className="pointer-events-none absolute right-2.5 top-1/2 size-4 -translate-y-1/2 text-muted-foreground" />
|
|
19
|
+
</span>
|
|
20
|
+
),
|
|
21
|
+
);
|
|
22
|
+
NativeSelect.displayName = 'NativeSelect';
|
|
23
|
+
|
|
24
|
+
export { NativeSelect };
|
package/template/notis.config.ts
CHANGED
|
@@ -1,37 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { defineSpaces } from '@notis/sdk/config';
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
title: 'My Notis App',
|
|
7
|
-
description: 'A focused Notis app with one route and one database-backed workflow.',
|
|
8
|
-
icon: 'phosphor:squares-four',
|
|
9
|
-
author: { name: 'Notis User' },
|
|
10
|
-
categories: ['Productivity'],
|
|
11
|
-
tagline: 'A clean starting point for a focused workflow.',
|
|
12
|
-
|
|
13
|
-
databases: ['items'],
|
|
14
|
-
|
|
15
|
-
routes: [
|
|
16
|
-
{ path: '/', slug: 'home', name: 'Home', icon: 'phosphor:house', default: true },
|
|
17
|
-
// Example collection tree route:
|
|
18
|
-
// {
|
|
19
|
-
// path: '/notes',
|
|
20
|
-
// slug: 'notes',
|
|
21
|
-
// name: 'Notes',
|
|
22
|
-
// collection: {
|
|
23
|
-
// database: 'notes',
|
|
24
|
-
// titleProperty: 'Name',
|
|
25
|
-
// parentProperty: 'Parent',
|
|
26
|
-
// sidebar: {
|
|
27
|
-
// mode: 'tree',
|
|
28
|
-
// allowCreate: true,
|
|
29
|
-
// },
|
|
30
|
-
// },
|
|
31
|
-
// },
|
|
32
|
-
],
|
|
33
|
-
|
|
34
|
-
tools: [
|
|
35
|
-
'LOCAL_NOTIS_DATABASE_QUERY',
|
|
36
|
-
],
|
|
37
|
-
});
|
|
3
|
+
// The workspace Space index. `notis spaces init` replaces it with the Spaces it
|
|
4
|
+
// scaffolds; each entry points at a definition file that exports defineSpace().
|
|
5
|
+
export default defineSpaces({ spaces: {} });
|