@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,38 @@
|
|
|
1
|
+
import type { CSSProperties } from 'react';
|
|
2
|
+
import { useNotisRuntime } from '../provider';
|
|
3
|
+
import { pick, type Locale, type Words } from '../words/types';
|
|
4
|
+
|
|
5
|
+
/** What a loading placeholder says to screen readers. */
|
|
6
|
+
export const SKELETON_WORDS = Object.freeze({
|
|
7
|
+
loading: { en: 'Loading content', fr: 'Chargement du contenu' },
|
|
8
|
+
}) satisfies Readonly<Record<string, Words>>;
|
|
9
|
+
|
|
10
|
+
/** Content-shaped placeholder. Never use it to replace a successful cached result. */
|
|
11
|
+
export function Skeleton({ className, style }: { className?: string; style?: CSSProperties }) {
|
|
12
|
+
return <span aria-hidden="true" className={className} style={{ display: 'block', height: 16,
|
|
13
|
+
// Apps may define --muted as HSL channels or a complete CSS color. A
|
|
14
|
+
// neutral default remains visible with either token format and no theme.
|
|
15
|
+
borderRadius: 6, background: 'rgba(128,128,128,.18)', ...style }} />;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/** A whole view loading: a title bar and table, cards, graph or detail placeholders, named for screen readers in the Space's language. */
|
|
19
|
+
export function ViewSkeleton({ variant = 'table', rows = 5, label, locale }: {
|
|
20
|
+
variant?: 'table' | 'cards' | 'graph' | 'detail'; rows?: number;
|
|
21
|
+
/** What loads, said to screen readers ("Loading meetings"). Default "Loading content". */
|
|
22
|
+
label?: Words | string;
|
|
23
|
+
/** Default the Space's locale. */
|
|
24
|
+
locale?: Locale;
|
|
25
|
+
}) {
|
|
26
|
+
const runtimeLocale = useNotisRuntime()?.context?.locale;
|
|
27
|
+
const shown = locale ?? (runtimeLocale === 'fr' ? 'fr' : 'en');
|
|
28
|
+
return <div role="status" aria-label={pick(label ?? SKELETON_WORDS.loading, shown)} aria-busy="true" data-notis-content-skeleton
|
|
29
|
+
style={{ width: '100%', display: 'grid', gap: 16, padding: 24 }}>
|
|
30
|
+
<Skeleton style={{ width: '32%', height: 28 }} />
|
|
31
|
+
{variant === 'graph' ? <Skeleton style={{ height: 420 }} /> :
|
|
32
|
+
<div style={{ display: 'grid', gap: 12, gridTemplateColumns: variant === 'cards' ? 'repeat(auto-fit,minmax(180px,1fr))' : '1fr' }}>
|
|
33
|
+
{Array.from({ length: rows }, (_, index) => <Skeleton key={index}
|
|
34
|
+
style={{ height: variant === 'cards' ? 112 : variant === 'detail' ? 20 : 44,
|
|
35
|
+
width: variant === 'detail' && index === rows - 1 ? '65%' : '100%' }} />)}
|
|
36
|
+
</div>}
|
|
37
|
+
</div>;
|
|
38
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
export { defineSpace, defineSpaces } from './space';
|
|
2
|
+
export type { SpaceDefinition, SpacesWorkspace, SpaceActionTemplate, SpaceResourceReference, SpaceDatabaseCreate } from './space';
|
|
3
|
+
export type { SpaceViewParam, SpaceViewParamType, SpaceShows, SpaceMemoryPolicy, SpaceMemorySnapshot, SpaceChrome, SpaceMarkdownInput } from './space';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Configuration utilities for notis.config.ts and Space definitions.
|
|
7
|
+
*
|
|
8
|
+
* Usage:
|
|
9
|
+
* ```ts
|
|
10
|
+
* // notis.config.ts
|
|
11
|
+
* import { defineSpaces } from '@notis/sdk/config';
|
|
12
|
+
*
|
|
13
|
+
* export default defineSpaces({
|
|
14
|
+
* spaces: { notes: { definition: 'spaces/notes/space.config.ts' } },
|
|
15
|
+
* });
|
|
16
|
+
* ```
|
|
17
|
+
*
|
|
18
|
+
* Each definition file exports `defineSpace({ ... })`. `notis spaces build`
|
|
19
|
+
* reads only these two shapes.
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Identity helper kept so older sources whose configuration files still import
|
|
24
|
+
* it keep loading and bundling. It accepts any object and returns it unchanged;
|
|
25
|
+
* `notis spaces build` never reads that shape.
|
|
26
|
+
*
|
|
27
|
+
* @deprecated Use `defineSpaces` for the workspace index and `defineSpace` for each Space.
|
|
28
|
+
*/
|
|
29
|
+
export function defineNotisApp<T extends object>(config: T): T {
|
|
30
|
+
return config;
|
|
31
|
+
}
|
|
@@ -14,6 +14,17 @@ import type {
|
|
|
14
14
|
DocumentRecord,
|
|
15
15
|
SecretPropertyValue,
|
|
16
16
|
} from './runtime';
|
|
17
|
+
import { pick, type Locale, type Words } from './words/types';
|
|
18
|
+
|
|
19
|
+
/** The words the document helpers fall back on. */
|
|
20
|
+
export const DOCUMENT_WORDS = Object.freeze({
|
|
21
|
+
untitled: { en: 'Untitled', fr: 'Sans titre' },
|
|
22
|
+
}) satisfies Readonly<Record<string, Words>>;
|
|
23
|
+
|
|
24
|
+
/** The locale of the fallback words ("Untitled"). Default English; the SDK hooks pass the Space's locale. */
|
|
25
|
+
export interface DocumentWordsOptions {
|
|
26
|
+
locale?: Locale;
|
|
27
|
+
}
|
|
17
28
|
|
|
18
29
|
// ---------------------------------------------------------------------------
|
|
19
30
|
// Value primitives
|
|
@@ -113,9 +124,10 @@ function normalizeContentType(value: unknown): DocumentContentType | null {
|
|
|
113
124
|
/**
|
|
114
125
|
* Normalizes a raw document from a Notis database tool result
|
|
115
126
|
* (LOCAL_NOTIS_DATABASE_QUERY / GET_DOCUMENT / UPSERT_*) into a
|
|
116
|
-
* `DocumentRecord`: camelCases fields and collapses property values.
|
|
127
|
+
* `DocumentRecord`: camelCases fields and collapses property values. A
|
|
128
|
+
* document with no title is titled "Untitled" in `options.locale`.
|
|
117
129
|
*/
|
|
118
|
-
export function normalizeDocumentRecord(value: unknown): DocumentRecord {
|
|
130
|
+
export function normalizeDocumentRecord(value: unknown, options: DocumentWordsOptions = {}): DocumentRecord {
|
|
119
131
|
const record = asRecord(value) ?? {};
|
|
120
132
|
const rawProperties = asRecord(record.properties) ?? {};
|
|
121
133
|
const properties: Record<string, unknown> = {};
|
|
@@ -125,7 +137,9 @@ export function normalizeDocumentRecord(value: unknown): DocumentRecord {
|
|
|
125
137
|
|
|
126
138
|
return {
|
|
127
139
|
id: optionalString(record.id) ?? '',
|
|
128
|
-
|
|
140
|
+
recordKey: optionalString(record.recordKey) ?? optionalString(record.record_key) ?? undefined,
|
|
141
|
+
revision: typeof record.revision === 'number' ? record.revision : undefined,
|
|
142
|
+
title: optionalString(record.title) ?? pick(DOCUMENT_WORDS.untitled, options.locale ?? 'en'),
|
|
129
143
|
url: optionalString(record.url),
|
|
130
144
|
properties,
|
|
131
145
|
icon: optionalString(record.icon),
|
|
@@ -241,9 +255,10 @@ export function blockNoteToPlainText(blocks: unknown): string {
|
|
|
241
255
|
|
|
242
256
|
/**
|
|
243
257
|
* Best-available plain-text preview for a document:
|
|
244
|
-
* plainText -> contentMarkdown -> contentBlocknote -> title
|
|
258
|
+
* plainText -> contentMarkdown -> contentBlocknote -> title, else "Untitled"
|
|
259
|
+
* in `options.locale`.
|
|
245
260
|
*/
|
|
246
|
-
export function getDocumentPreview(document: DocumentRecord): string {
|
|
261
|
+
export function getDocumentPreview(document: DocumentRecord, options: DocumentWordsOptions = {}): string {
|
|
247
262
|
if (isPresentString(document.plainText)) {
|
|
248
263
|
return document.plainText.replace(/\s+/g, ' ').trim();
|
|
249
264
|
}
|
|
@@ -252,5 +267,5 @@ export function getDocumentPreview(document: DocumentRecord): string {
|
|
|
252
267
|
}
|
|
253
268
|
const fromBlocks = blockNoteToPlainText(document.contentBlocknote);
|
|
254
269
|
if (fromBlocks) return fromBlocks;
|
|
255
|
-
return isPresentString(document.title) ? document.title : '
|
|
270
|
+
return isPresentString(document.title) ? document.title : pick(DOCUMENT_WORDS.untitled, options.locale ?? 'en');
|
|
256
271
|
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { useCallback, useState } from 'react';
|
|
4
|
+
import { useNotisRuntime } from '../provider';
|
|
5
|
+
import { useQuery, type UseQueryOptions, type UseQueryResult } from './useQuery';
|
|
6
|
+
import type { SpaceActionOptions } from '../space';
|
|
7
|
+
|
|
8
|
+
export function useAction<TInput extends Record<string, unknown> = Record<string, unknown>, TResult = unknown>(actionId: string): {
|
|
9
|
+
call: (inputs: TInput, options?: SpaceActionOptions) => Promise<TResult>; loading: boolean; error: Error | null;
|
|
10
|
+
} {
|
|
11
|
+
const runtime = useNotisRuntime();
|
|
12
|
+
const [pending, setPending] = useState(0);
|
|
13
|
+
const [error, setError] = useState<Error | null>(null);
|
|
14
|
+
const call = useCallback(async (inputs: TInput, options?: SpaceActionOptions) => {
|
|
15
|
+
if (runtime?.resource?.kind !== 'space' || !runtime.callAction) throw new Error('A Space action runtime is required.');
|
|
16
|
+
setPending((value) => value + 1); setError(null);
|
|
17
|
+
try { return await runtime.callAction<TResult>(actionId, inputs, options); }
|
|
18
|
+
catch (cause) { const failure = cause instanceof Error ? cause : new Error(String(cause)); setError(failure); throw failure; }
|
|
19
|
+
finally { setPending((value) => value - 1); }
|
|
20
|
+
}, [runtime, actionId]);
|
|
21
|
+
return { call, loading: pending > 0, error };
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export function useActionQuery<TResult = unknown>(actionId: string, inputs: Record<string, unknown>,
|
|
25
|
+
options: UseQueryOptions = { readOnly: true }): UseQueryResult<TResult> {
|
|
26
|
+
const { call } = useAction<Record<string, unknown>, TResult>(actionId);
|
|
27
|
+
return useQuery(['action', actionId, inputs], () => call(inputs, { readOnly: true, dedupe: true }), options);
|
|
28
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { useMemo } from 'react';
|
|
3
|
+
import { useNotisRuntime } from '../provider';
|
|
4
|
+
import type { AgentContextItem } from '../agentContext';
|
|
5
|
+
|
|
6
|
+
/** Share context without owning storage, opening a new thread, or sending a message. */
|
|
7
|
+
export function useAgentContext() {
|
|
8
|
+
const runtime = useNotisRuntime();
|
|
9
|
+
return useMemo(() => ({
|
|
10
|
+
add(item: AgentContextItem): Promise<boolean> {
|
|
11
|
+
if (!runtime?.addContext) return Promise.reject(new Error('Chat context is unavailable in this host.'));
|
|
12
|
+
return runtime.addContext(item);
|
|
13
|
+
},
|
|
14
|
+
update(item: AgentContextItem): Promise<boolean> {
|
|
15
|
+
if (!runtime?.updateContext) return Promise.reject(new Error('Chat context is unavailable in this host.'));
|
|
16
|
+
return runtime.updateContext(item);
|
|
17
|
+
},
|
|
18
|
+
remove(id: string): Promise<boolean> {
|
|
19
|
+
if (!runtime?.removeContext) return Promise.reject(new Error('Chat context is unavailable in this host.'));
|
|
20
|
+
return runtime.removeContext(id);
|
|
21
|
+
},
|
|
22
|
+
}), [runtime]);
|
|
23
|
+
}
|
|
@@ -6,7 +6,7 @@ import { useNotisRuntime } from '../provider';
|
|
|
6
6
|
interface UseBackendResult {
|
|
7
7
|
/**
|
|
8
8
|
* Make an authenticated request to the Notis backend.
|
|
9
|
-
* The path should be an absolute backend path (e.g. `/portal_composio/
|
|
9
|
+
* The path should be an absolute backend path (e.g. `/portal_composio/toolkits`).
|
|
10
10
|
*/
|
|
11
11
|
request: (path: string, options?: {
|
|
12
12
|
method?: string;
|
|
@@ -18,10 +18,11 @@ interface UseBackendResult {
|
|
|
18
18
|
/**
|
|
19
19
|
* Raw backend request proxy. Use this for custom server endpoints or
|
|
20
20
|
* integration APIs not covered by the typed hooks.
|
|
21
|
+
* Spaces deny raw requests; use useAction or useActionQuery for declared actions.
|
|
21
22
|
*
|
|
22
23
|
* ```tsx
|
|
23
24
|
* const { request } = useBackend();
|
|
24
|
-
* const data = await request('/portal_composio/
|
|
25
|
+
* const data = await request('/portal_composio/toolkits', { method: 'GET' });
|
|
25
26
|
* ```
|
|
26
27
|
*/
|
|
27
28
|
export function useBackend(): UseBackendResult {
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { useCallback, useRef } from 'react';
|
|
4
|
+
import { useQuery } from './useQuery';
|
|
5
|
+
import { useNotisRuntime } from '../provider';
|
|
6
|
+
import { queryKey } from '../queryCache';
|
|
7
|
+
import { spaceQueryKey } from '../space';
|
|
8
|
+
import type { CloudComputerFacts, NotisRuntime } from '../runtime';
|
|
9
|
+
|
|
10
|
+
/** Cache key of the facts read; re-read once the viewer allows a Space to use the cloud computer. */
|
|
11
|
+
export const CLOUD_COMPUTER_FACTS_KEY = ['cloud-computer-facts'] as const;
|
|
12
|
+
|
|
13
|
+
/** Marks the facts stale in the host cache so every mounted `useCloudComputer()` reads them again. */
|
|
14
|
+
export function invalidateCloudComputerFacts(runtime: NotisRuntime | null): void {
|
|
15
|
+
try {
|
|
16
|
+
runtime?.queryClient?.invalidate(queryKey(spaceQueryKey(runtime, CLOUD_COMPUTER_FACTS_KEY)));
|
|
17
|
+
} catch {
|
|
18
|
+
// A host without a Space access context has no shared facts cache to refresh.
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export interface UseCloudComputerResult {
|
|
23
|
+
/**
|
|
24
|
+
* The facts, or null while the first read is in flight. `facts.available`
|
|
25
|
+
* is false when this host cannot answer — render the app's own fallback.
|
|
26
|
+
*/
|
|
27
|
+
facts: CloudComputerFacts | null;
|
|
28
|
+
loading: boolean;
|
|
29
|
+
isFetching: boolean;
|
|
30
|
+
error: Error | null;
|
|
31
|
+
/** Re-read the facts. The platform caches them for a few minutes. */
|
|
32
|
+
refresh: () => Promise<void>;
|
|
33
|
+
/**
|
|
34
|
+
* Space only (`cloudComputer: 'read'` or `'shell'`): ask the host to show its approval prompt.
|
|
35
|
+
* Resolves true once the viewer allowed it (the facts are then read again), false when they did
|
|
36
|
+
* not, and null on hosts without the prompt (Beta Apps, Sites, previews offline).
|
|
37
|
+
*/
|
|
38
|
+
requestApproval: () => Promise<boolean | null>;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const UNAVAILABLE: CloudComputerFacts = {
|
|
42
|
+
available: false,
|
|
43
|
+
reason: 'unsupported_host',
|
|
44
|
+
sandbox: null,
|
|
45
|
+
cli_auth: {
|
|
46
|
+
gh: { authenticated: null, account: null, checked_at: null, reason: 'unsupported_host' },
|
|
47
|
+
},
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Read-only facts about the user's cloud computer.
|
|
52
|
+
*
|
|
53
|
+
* ```tsx
|
|
54
|
+
* const { facts } = useCloudComputer();
|
|
55
|
+
* const gh = facts?.available ? facts.cli_auth.gh : null;
|
|
56
|
+
*
|
|
57
|
+
* return gh?.authenticated
|
|
58
|
+
* ? <p>Signed in as {gh.account}</p>
|
|
59
|
+
* : <GithubConnect />;
|
|
60
|
+
* ```
|
|
61
|
+
*
|
|
62
|
+
* Requires `cloudComputer: 'read'` (or `'shell'`) in `defineSpace` and the
|
|
63
|
+
* viewer's approval; until the viewer allows it the facts answer
|
|
64
|
+
* unavailable, so offer `requestApproval()`. It answers with state the platform already
|
|
65
|
+
* holds: reading it never creates, resumes or commands a sandbox, and the GitHub
|
|
66
|
+
* probe only runs when the sandbox is already awake. `authenticated: null`
|
|
67
|
+
* therefore means *unknown*, not *signed out* — keep the app's own fallback for
|
|
68
|
+
* that case and for hosts that answer `{ available: false }` (the dev harness,
|
|
69
|
+
* the vite preview).
|
|
70
|
+
*/
|
|
71
|
+
export function useCloudComputer(): UseCloudComputerResult {
|
|
72
|
+
const runtime = useNotisRuntime();
|
|
73
|
+
const explicitRefresh = useRef(false);
|
|
74
|
+
const query = useQuery<CloudComputerFacts>(CLOUD_COMPUTER_FACTS_KEY, async () => {
|
|
75
|
+
const refresh = explicitRefresh.current;
|
|
76
|
+
explicitRefresh.current = false;
|
|
77
|
+
return runtime?.cloudComputerFacts ? runtime.cloudComputerFacts(refresh ? { refresh: true } : undefined) : UNAVAILABLE;
|
|
78
|
+
}, { readOnly: true });
|
|
79
|
+
const refresh = useCallback(async () => {
|
|
80
|
+
explicitRefresh.current = true;
|
|
81
|
+
await query.refetch();
|
|
82
|
+
}, [query.refetch]);
|
|
83
|
+
const transport = runtime?.spaceCloudComputer;
|
|
84
|
+
const requestApproval = useCallback(async () => {
|
|
85
|
+
if (!transport) return null;
|
|
86
|
+
const status = await transport.requestApproval();
|
|
87
|
+
if (status?.approved !== true) return false;
|
|
88
|
+
invalidateCloudComputerFacts(runtime);
|
|
89
|
+
await query.refetch();
|
|
90
|
+
return true;
|
|
91
|
+
}, [query.refetch, runtime, transport]);
|
|
92
|
+
return { facts: query.data ?? (query.error ? UNAVAILABLE : null), loading: query.loading,
|
|
93
|
+
isFetching: query.isFetching, error: query.error, refresh, requestApproval };
|
|
94
|
+
}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { useCallback, useEffect, useRef, useState } from 'react';
|
|
4
|
+
import { useNotisRuntime } from '../provider';
|
|
5
|
+
import { invalidateCloudComputerFacts } from './useCloudComputer';
|
|
6
|
+
import type {
|
|
7
|
+
SpaceCloudComputerLevel,
|
|
8
|
+
SpaceCloudComputerRunResult,
|
|
9
|
+
SpaceCloudComputerStatus,
|
|
10
|
+
SpaceCloudComputerUploadInput,
|
|
11
|
+
SpaceCloudComputerUploadResult,
|
|
12
|
+
} from '../space';
|
|
13
|
+
|
|
14
|
+
export interface UseCloudComputerShellResult {
|
|
15
|
+
/**
|
|
16
|
+
* The level this Space declares (`'read'` or `'shell'`) when this host offers the cloud computer,
|
|
17
|
+
* else null (Sites, links, verification harnesses, older hosts): keep the page's own fallback.
|
|
18
|
+
*/
|
|
19
|
+
level: SpaceCloudComputerLevel | null;
|
|
20
|
+
/** True when `run` and `upload` are offered: the host offers the cloud computer and the Space declares `'shell'`. */
|
|
21
|
+
available: boolean;
|
|
22
|
+
/** The viewer's approval for this Space's current code (either level), or null while it is read. */
|
|
23
|
+
status: SpaceCloudComputerStatus | null;
|
|
24
|
+
approved: boolean;
|
|
25
|
+
loading: boolean;
|
|
26
|
+
/**
|
|
27
|
+
* Run one non-interactive command on the viewer's own cloud computer. Same result as the shell tool.
|
|
28
|
+
* Pass the same `requestId` when the page retries this run itself: a run is never repeated for one key.
|
|
29
|
+
*/
|
|
30
|
+
run(command: string, options?: RunOptions): Promise<SpaceCloudComputerRunResult>;
|
|
31
|
+
/** Write one file (at most 1 MiB) straight to the cloud computer; it never travels by URL or chat. */
|
|
32
|
+
upload(file: SpaceCloudComputerUploadInput): Promise<SpaceCloudComputerUploadResult>;
|
|
33
|
+
/**
|
|
34
|
+
* Ask the host to show its approval prompt, for either declared level. Only the person's click in
|
|
35
|
+
* that prompt approves; once allowed, every `useCloudComputer()` reads the facts again.
|
|
36
|
+
*/
|
|
37
|
+
requestApproval(): Promise<SpaceCloudComputerStatus | null>;
|
|
38
|
+
refresh(): Promise<void>;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
type RunOptions = { cwd?: string; timeoutMs?: number; maxOutputLength?: number; requestId?: string };
|
|
42
|
+
|
|
43
|
+
const unavailable = async (): Promise<never> => {
|
|
44
|
+
throw new Error('The cloud computer is not available in this Space.');
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* The viewer's approval and, for `cloudComputer: 'shell'`, commands and file writes on the signed-in
|
|
49
|
+
* viewer's own cloud computer, from a Space page.
|
|
50
|
+
*
|
|
51
|
+
* ```tsx
|
|
52
|
+
* const shell = useCloudComputerShell();
|
|
53
|
+
* if (!shell.level) return <AskNotisFallback />;
|
|
54
|
+
* if (!shell.approved) return <Button onClick={() => shell.requestApproval()}>Allow</Button>;
|
|
55
|
+
* const result = await shell.run(`bash ${SCRIPTS}/workspace.sh sync ${quote(repo)} ${quote(name)}`);
|
|
56
|
+
* ```
|
|
57
|
+
*
|
|
58
|
+
* Requires `cloudComputer` in `defineSpace` and the viewer's approval, which the Portal asks for in
|
|
59
|
+
* its own prompt and which covers only the exact code the viewer allowed: any new release asks again.
|
|
60
|
+
*/
|
|
61
|
+
export function useCloudComputerShell(): UseCloudComputerShellResult {
|
|
62
|
+
const runtime = useNotisRuntime();
|
|
63
|
+
const transport = runtime?.spaceCloudComputer;
|
|
64
|
+
const declared = runtime?.space?.cloudComputer;
|
|
65
|
+
const level: SpaceCloudComputerLevel | null = transport && (declared === 'read' || declared === 'shell') ? declared : null;
|
|
66
|
+
const available = level === 'shell';
|
|
67
|
+
const [status, setStatus] = useState<SpaceCloudComputerStatus | null>(null);
|
|
68
|
+
const [loading, setLoading] = useState(Boolean(level));
|
|
69
|
+
const mounted = useRef(true);
|
|
70
|
+
useEffect(() => () => { mounted.current = false; }, []);
|
|
71
|
+
|
|
72
|
+
const refresh = useCallback(async () => {
|
|
73
|
+
if (!level || !transport) return;
|
|
74
|
+
setLoading(true);
|
|
75
|
+
try {
|
|
76
|
+
const next = await transport.status();
|
|
77
|
+
if (mounted.current) setStatus(next);
|
|
78
|
+
} catch {
|
|
79
|
+
if (mounted.current) setStatus(null);
|
|
80
|
+
} finally {
|
|
81
|
+
if (mounted.current) setLoading(false);
|
|
82
|
+
}
|
|
83
|
+
}, [level, transport]);
|
|
84
|
+
|
|
85
|
+
useEffect(() => {
|
|
86
|
+
mounted.current = true;
|
|
87
|
+
void refresh();
|
|
88
|
+
}, [refresh]);
|
|
89
|
+
|
|
90
|
+
const run = useCallback(async (command: string, options: RunOptions = {}) => {
|
|
91
|
+
if (!available || !transport) return unavailable();
|
|
92
|
+
return transport.run({ command, ...(options.cwd ? { cwd: options.cwd } : {}),
|
|
93
|
+
...(options.timeoutMs ? { timeout_ms: options.timeoutMs } : {}),
|
|
94
|
+
...(options.maxOutputLength ? { max_output_length: options.maxOutputLength } : {}),
|
|
95
|
+
...(options.requestId ? { request_id: options.requestId } : {}) });
|
|
96
|
+
}, [available, transport]);
|
|
97
|
+
|
|
98
|
+
const upload = useCallback(async (file: SpaceCloudComputerUploadInput) => {
|
|
99
|
+
if (!available || !transport) return unavailable();
|
|
100
|
+
return transport.upload(file);
|
|
101
|
+
}, [available, transport]);
|
|
102
|
+
|
|
103
|
+
const requestApproval = useCallback(async () => {
|
|
104
|
+
if (!level || !transport) return null;
|
|
105
|
+
const next = await transport.requestApproval();
|
|
106
|
+
if (mounted.current) setStatus(next);
|
|
107
|
+
// A facts read refused before the approval must not keep showing "unavailable".
|
|
108
|
+
if (next?.approved === true) invalidateCloudComputerFacts(runtime);
|
|
109
|
+
return next;
|
|
110
|
+
}, [level, runtime, transport]);
|
|
111
|
+
|
|
112
|
+
return { level, available, status, approved: status?.approved === true, loading: Boolean(level) && loading,
|
|
113
|
+
run, upload, requestApproval, refresh };
|
|
114
|
+
}
|