@notis_ai/cli 0.2.18 → 0.2.19
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 +271 -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
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
import { createHash } from 'node:crypto';
|
|
2
|
-
import { basename } from 'node:path';
|
|
2
|
+
import { basename, isAbsolute } from 'node:path';
|
|
3
3
|
|
|
4
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
installAgentSetup,
|
|
6
|
+
installRecallOnlyAgentHooks,
|
|
7
|
+
shouldInstallLocalAgentSetup,
|
|
8
|
+
} from '../runtime/agent-setup.js';
|
|
5
9
|
import {
|
|
6
10
|
completePendingTurn,
|
|
7
11
|
freshRecallItems,
|
|
@@ -42,7 +46,54 @@ export function installLocalAgentContext(
|
|
|
42
46
|
});
|
|
43
47
|
}
|
|
44
48
|
|
|
49
|
+
/**
|
|
50
|
+
* Recall-only install for a hosted coding agent. The local guard against
|
|
51
|
+
* hosted environments does not apply: this mode is asked for explicitly, binds
|
|
52
|
+
* to the session's injected credential instead of a stored profile, and
|
|
53
|
+
* writes only into the agent's own config folder.
|
|
54
|
+
*/
|
|
55
|
+
export function installRecallOnlyAgentContext(ctx, env = process.env) {
|
|
56
|
+
const options = ctx.options || {};
|
|
57
|
+
if (options.memoryHooks === false) {
|
|
58
|
+
throw usageError('--recall-only installs memory hooks; it cannot be combined with --no-memory-hooks');
|
|
59
|
+
}
|
|
60
|
+
if (options.envFile !== undefined && (typeof options.envFile !== 'string' || !isAbsolute(options.envFile))) {
|
|
61
|
+
throw usageError('--env-file must be an absolute path');
|
|
62
|
+
}
|
|
63
|
+
const agents = selectedAgents(options);
|
|
64
|
+
if (ctx.runtime.credentialKind !== 'env' || !ctx.runtime.jwt) {
|
|
65
|
+
return agents.map((agent) => ({ agent, status: 'skipped_requires_session_credential' }));
|
|
66
|
+
}
|
|
67
|
+
return agents.map((agent) => {
|
|
68
|
+
const configDir = agent === 'codex' ? env.CODEX_HOME : env.CLAUDE_CONFIG_DIR;
|
|
69
|
+
if (typeof configDir !== 'string' || !isAbsolute(configDir)) {
|
|
70
|
+
return { agent, status: 'skipped_requires_agent_config_dir' };
|
|
71
|
+
}
|
|
72
|
+
return installRecallOnlyAgentHooks({ agentId: agent, configDir, envFile: options.envFile || null });
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
|
|
45
76
|
async function agentsInstallHandler(ctx) {
|
|
77
|
+
if (ctx.options?.recallOnly) {
|
|
78
|
+
const results = installRecallOnlyAgentContext(ctx);
|
|
79
|
+
const installed = results.filter((result) => result.mode === 'recall_only'
|
|
80
|
+
&& result.memory_hook?.status !== 'error');
|
|
81
|
+
const hookErrors = results.filter((result) => result.memory_hook?.status === 'error');
|
|
82
|
+
return ctx.output.emitSuccess({
|
|
83
|
+
command: 'agents install',
|
|
84
|
+
data: { mode: 'recall_only', agents: results },
|
|
85
|
+
humanSummary: installed.length
|
|
86
|
+
? `Installed recall-only Notis memory hooks for ${installed.length} coding agent${installed.length === 1 ? '' : 's'}.`
|
|
87
|
+
: 'Skipped recall-only coding-agent memory hooks.',
|
|
88
|
+
warnings: hookErrors.map((result) => result.memory_hook.message),
|
|
89
|
+
hints: [],
|
|
90
|
+
renderHuman: () => results.map((result) => (
|
|
91
|
+
result.mode === 'recall_only'
|
|
92
|
+
? `${result.agent}: recall-only memory hook ${result.memory_hook?.status || 'skipped'}`
|
|
93
|
+
: `${result.agent}: ${result.status}`
|
|
94
|
+
)).join('\n'),
|
|
95
|
+
});
|
|
96
|
+
}
|
|
46
97
|
const results = installLocalAgentContext(ctx);
|
|
47
98
|
const hookErrors = results.filter((result) => result.memory_hook?.status === 'error');
|
|
48
99
|
const configuredCount = results.filter((result) => result.instructions).length;
|
|
@@ -132,10 +183,12 @@ export function formatMemoryContext(data, { sessionStart = false } = {}) {
|
|
|
132
183
|
return lines.join('\n');
|
|
133
184
|
}
|
|
134
185
|
|
|
135
|
-
function withFreshResults(input, data) {
|
|
186
|
+
function withFreshResults(input, data, home) {
|
|
136
187
|
const results = Array.isArray(data?.results) ? data.results : [];
|
|
137
188
|
const texts = results.map(memoryText);
|
|
138
|
-
const freshTexts = new Set(
|
|
189
|
+
const freshTexts = new Set(home === undefined
|
|
190
|
+
? freshRecallItems(input, texts.filter(Boolean))
|
|
191
|
+
: freshRecallItems(input, texts.filter(Boolean), home));
|
|
139
192
|
const emitted = new Set();
|
|
140
193
|
return {
|
|
141
194
|
...data,
|
|
@@ -148,6 +201,45 @@ function withFreshResults(input, data) {
|
|
|
148
201
|
};
|
|
149
202
|
}
|
|
150
203
|
|
|
204
|
+
const WORKER_CONTEXT_PREFIX = 'Current worker context for this turn.';
|
|
205
|
+
const INJECTED_BLOCK_PATTERN = /<(system_instruction|notis_[a-z_]+|delegated_provider|interaction_id|relevant_memory|instructions)>[\s\S]*?<\/\1>/g;
|
|
206
|
+
|
|
207
|
+
function withoutInjectedBlocks(text) {
|
|
208
|
+
return text.replace(INJECTED_BLOCK_PATTERN, '\n');
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* The user's own request inside a delegated Notis turn. A hosted coding agent
|
|
213
|
+
* receives the Notis contract, earlier history, delivery receipts and a worker
|
|
214
|
+
* context snapshot in the same message; searching all of that would recall
|
|
215
|
+
* memories about the contract instead of the request. Each request follows its
|
|
216
|
+
* `<interaction_id>` tag and ends before the next tag or the worker context.
|
|
217
|
+
*/
|
|
218
|
+
export function delegatedRequestText(prompt) {
|
|
219
|
+
const text = typeof prompt === 'string' ? prompt : '';
|
|
220
|
+
const workerAt = text.indexOf(WORKER_CONTEXT_PREFIX);
|
|
221
|
+
const head = workerAt >= 0 ? text.slice(0, workerAt) : text;
|
|
222
|
+
const tagPattern = /<interaction_id>[\s\S]*?<\/interaction_id>/g;
|
|
223
|
+
const tags = [...head.matchAll(tagPattern)];
|
|
224
|
+
let request = '';
|
|
225
|
+
if (tags.length) {
|
|
226
|
+
request = tags.map((tag, index) => {
|
|
227
|
+
const start = tag.index + tag[0].length;
|
|
228
|
+
const end = index + 1 < tags.length ? tags[index + 1].index : head.length;
|
|
229
|
+
return withoutInjectedBlocks(head.slice(start, end)).trim();
|
|
230
|
+
}).filter(Boolean).join('\n');
|
|
231
|
+
} else {
|
|
232
|
+
request = withoutInjectedBlocks(text)
|
|
233
|
+
.replace(/Current worker context for this turn\.[^\n]*(?:\n\{[^\n]*\})?/g, '\n')
|
|
234
|
+
.trim();
|
|
235
|
+
}
|
|
236
|
+
if (!request) {
|
|
237
|
+
const goal = /<goal>([\s\S]*?)<\/goal>/.exec(text);
|
|
238
|
+
request = goal ? goal[1].trim() : '';
|
|
239
|
+
}
|
|
240
|
+
return request.replace(/\n{3,}/g, '\n\n').slice(0, 12000);
|
|
241
|
+
}
|
|
242
|
+
|
|
151
243
|
function memoryStateInput(input, runtime) {
|
|
152
244
|
return {
|
|
153
245
|
...input,
|
|
@@ -166,7 +258,19 @@ export async function agentContextHandler(ctx, {
|
|
|
166
258
|
// Hook failures are deliberately silent and fail-open. A temporary Notis
|
|
167
259
|
// outage must not prevent the user's Codex or Claude prompt from running.
|
|
168
260
|
try {
|
|
169
|
-
const
|
|
261
|
+
const recallOnly = ctx.options?.recallOnly === true;
|
|
262
|
+
const stateDir = recallOnly && typeof ctx.options?.stateDir === 'string' && isAbsolute(ctx.options.stateDir)
|
|
263
|
+
? ctx.options.stateDir
|
|
264
|
+
: undefined;
|
|
265
|
+
if (recallOnly) {
|
|
266
|
+
// Recall-only hooks never capture, so no turn is held for a Stop hook.
|
|
267
|
+
rememberPending = () => {};
|
|
268
|
+
clearPending = () => {};
|
|
269
|
+
}
|
|
270
|
+
const rawInput = await readInput();
|
|
271
|
+
const input = recallOnly && rawInput?.hook_event_name === 'UserPromptSubmit'
|
|
272
|
+
? { ...rawInput, prompt: delegatedRequestText(rawInput.prompt) }
|
|
273
|
+
: rawInput;
|
|
170
274
|
const stateInput = memoryStateInput(input, ctx.runtime);
|
|
171
275
|
const event = input?.hook_event_name;
|
|
172
276
|
if (!['SessionStart', 'UserPromptSubmit'].includes(event)) return 0;
|
|
@@ -194,7 +298,7 @@ export async function agentContextHandler(ctx, {
|
|
|
194
298
|
include_profile: event === 'SessionStart',
|
|
195
299
|
},
|
|
196
300
|
});
|
|
197
|
-
const data = withFreshResults(stateInput, unwrapToolPayload(result.payload));
|
|
301
|
+
const data = withFreshResults(stateInput, unwrapToolPayload(result.payload), stateDir);
|
|
198
302
|
const additionalContext = formatMemoryContext(data, { sessionStart: event === 'SessionStart' });
|
|
199
303
|
if (!additionalContext) return 0;
|
|
200
304
|
process.stdout.write(`${JSON.stringify({
|
|
@@ -333,13 +437,15 @@ export const agentsCommandSpecs = [
|
|
|
333
437
|
command_path: ['agents', 'install'],
|
|
334
438
|
summary: 'Install Notis instructions and recall/capture hooks for local Codex and Claude Code.',
|
|
335
439
|
when_to_use:
|
|
336
|
-
'Run after login to give local coding agents durable Notis CLI guidance, session-start profile context, deduplicated relevant recall, and automatic completed-turn capture. Hosted Notis sandboxes
|
|
440
|
+
'Run after login to give local coding agents durable Notis CLI guidance, session-start profile context, deduplicated relevant recall, and automatic completed-turn capture. Hosted Notis sandboxes are skipped unless --recall-only is given: that mode installs only recall hooks into the hosted agent\'s own config folder, signed in with the session\'s injected credential.',
|
|
337
441
|
args_schema: {
|
|
338
442
|
arguments: [],
|
|
339
443
|
options: [
|
|
340
444
|
{ flags: '--codex-only', description: 'Configure only Codex.' },
|
|
341
445
|
{ flags: '--claude-only', description: 'Configure only Claude Code.' },
|
|
342
446
|
{ flags: '--no-memory-hooks', description: 'Install static instructions and remove Notis recall/capture hooks.' },
|
|
447
|
+
{ flags: '--recall-only', description: 'Hosted coding agents: install only recall hooks (no capture, no instructions) into CODEX_HOME or CLAUDE_CONFIG_DIR, signed in with the injected NOTIS_JWT.' },
|
|
448
|
+
{ flags: '--env-file <path>', description: 'With --recall-only: a shell file each hook sources first to pick up the current injected sign-in.' },
|
|
343
449
|
],
|
|
344
450
|
},
|
|
345
451
|
examples: [
|
|
@@ -347,6 +453,7 @@ export const agentsCommandSpecs = [
|
|
|
347
453
|
'notis agents install --codex-only',
|
|
348
454
|
'notis agents install --claude-only',
|
|
349
455
|
'notis agents install --no-memory-hooks',
|
|
456
|
+
'notis agents install --recall-only --codex-only',
|
|
350
457
|
],
|
|
351
458
|
output_schema: 'Returns each configured agent, instruction file path/status, memory-hook file path/status, and profile binding.',
|
|
352
459
|
mutates: true,
|
|
@@ -360,7 +467,13 @@ export const agentsCommandSpecs = [
|
|
|
360
467
|
command_path: ['agent-context'],
|
|
361
468
|
summary: 'Internal hook adapter that injects relevant Notis memory.',
|
|
362
469
|
when_to_use: 'Called by installed Codex and Claude Code UserPromptSubmit hooks; not intended for direct use.',
|
|
363
|
-
args_schema: {
|
|
470
|
+
args_schema: {
|
|
471
|
+
arguments: [],
|
|
472
|
+
options: [
|
|
473
|
+
{ flags: '--recall-only', description: 'Hosted recall: search only the user request inside a delegated turn and never hold a turn for capture.' },
|
|
474
|
+
{ flags: '--state-dir <dir>', description: 'Folder for per-session recall state instead of the home folder.' },
|
|
475
|
+
],
|
|
476
|
+
},
|
|
364
477
|
examples: [],
|
|
365
478
|
output_schema: 'Emits vendor-compatible hook JSON with additionalContext, or no output when context is unavailable.',
|
|
366
479
|
mutates: false,
|
|
@@ -108,7 +108,7 @@ export const authCommandSpecs = [
|
|
|
108
108
|
{ flags: '--mode <mode>', description: 'auto (default) hands the browser callback to a background listener when this command cannot wait; browser waits in-process; code shows a one-time code to copy.' },
|
|
109
109
|
{ flags: '--paste-code', description: 'Alias for --mode code.' },
|
|
110
110
|
{ flags: '--timeout-seconds <n>', description: 'Authorization lifetime in seconds (default 300 while waiting in a terminal; 1800 for detached or code hand-offs).' },
|
|
111
|
-
{ flags: '--scope <scope>', description: 'OAuth permission to request (repeatable).', collect: true },
|
|
111
|
+
{ flags: '--scope <scope>', description: 'OAuth permission to request (repeatable). Default: every permission Notis offers the CLI.', collect: true },
|
|
112
112
|
{ flags: '--code <code>', description: 'Redeem the code shown in the browser after a non-interactive login.' },
|
|
113
113
|
],
|
|
114
114
|
},
|
|
@@ -133,9 +133,9 @@ export const authCommandSpecs = [
|
|
|
133
133
|
},
|
|
134
134
|
{
|
|
135
135
|
command_path: ['logout'],
|
|
136
|
-
summary: '
|
|
136
|
+
summary: 'Sign this computer out of one CLI profile: revoke and remove its OAuth credential.',
|
|
137
137
|
when_to_use:
|
|
138
|
-
'Use this to disconnect a single account.
|
|
138
|
+
'Use this to disconnect a single account on this computer. Its sign-ins on other computers stay, and other profiles keep their credentials unless you pass --all-profiles.',
|
|
139
139
|
args_schema: {
|
|
140
140
|
arguments: [],
|
|
141
141
|
options: [
|
|
@@ -4,6 +4,8 @@ import { usageError } from '../runtime/errors.js';
|
|
|
4
4
|
import {
|
|
5
5
|
COMPOSIO_MULTI_EXECUTE_TOOL,
|
|
6
6
|
fetchToolDiscovery,
|
|
7
|
+
fetchToolSchema,
|
|
8
|
+
fetchToolkits,
|
|
7
9
|
healthCheck,
|
|
8
10
|
nextIdempotencyKey,
|
|
9
11
|
runToolCommand,
|
|
@@ -37,6 +39,22 @@ function discoveredToolNames(payload) {
|
|
|
37
39
|
return [...new Set(names.filter(Boolean))];
|
|
38
40
|
}
|
|
39
41
|
|
|
42
|
+
function isNotisAppSupabase(value) {
|
|
43
|
+
const upper = String(value || '').toUpperCase();
|
|
44
|
+
return upper.includes('SUPABASE') && upper.includes('NOTIS_APP') && !upper.includes('WEBSITE');
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export function selectSupabaseSqlTool(discoveredNames, toolkits = []) {
|
|
48
|
+
const discovered = discoveredNames.find((name) => (
|
|
49
|
+
isNotisAppSupabase(name) && name.toUpperCase().includes('EXECUTE_SQL')
|
|
50
|
+
));
|
|
51
|
+
if (discovered) return discovered;
|
|
52
|
+
// Semantic search ranks Composio's generic Supabase tools above a connected
|
|
53
|
+
// custom MCP server, so derive the canonical name from the connected toolkit.
|
|
54
|
+
const toolkit = toolkits.find((entry) => entry.has_active_connection && isNotisAppSupabase(entry.id));
|
|
55
|
+
return toolkit ? `${String(toolkit.id).toUpperCase()}_EXECUTE_SQL` : null;
|
|
56
|
+
}
|
|
57
|
+
|
|
40
58
|
async function discoverSupabaseSqlTool(runtime) {
|
|
41
59
|
const payload = await fetchToolDiscovery(
|
|
42
60
|
runtime,
|
|
@@ -44,10 +62,20 @@ async function discoverSupabaseSqlTool(runtime) {
|
|
|
44
62
|
'query',
|
|
45
63
|
);
|
|
46
64
|
const names = discoveredToolNames(payload);
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
65
|
+
let match = selectSupabaseSqlTool(names);
|
|
66
|
+
if (!match) {
|
|
67
|
+
const { toolkits } = await fetchToolkits(runtime);
|
|
68
|
+
const candidate = selectSupabaseSqlTool([], toolkits);
|
|
69
|
+
if (candidate) {
|
|
70
|
+
try {
|
|
71
|
+
await fetchToolSchema(runtime, candidate);
|
|
72
|
+
match = candidate;
|
|
73
|
+
} catch (error) {
|
|
74
|
+
// Only an unknown tool name means the toolkit lacks it; surface outages.
|
|
75
|
+
if (error?.code !== 'usage_error' || !/not found/.test(error.message)) throw error;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
51
79
|
if (!match) {
|
|
52
80
|
throw usageError('No connected Supabase execute-SQL capability was discovered. Run `notis tools link mcp_supabase_notis_app`.');
|
|
53
81
|
}
|
|
@@ -56,7 +84,8 @@ async function discoverSupabaseSqlTool(runtime) {
|
|
|
56
84
|
|
|
57
85
|
export function unwrapToolExecutionPayload(payload) {
|
|
58
86
|
return (
|
|
59
|
-
payload?.data?.results?.[0]?.response?.data
|
|
87
|
+
payload?.data?.data?.results?.[0]?.response?.data
|
|
88
|
+
?? payload?.data?.results?.[0]?.response?.data
|
|
60
89
|
?? payload?.results?.[0]?.response?.data
|
|
61
90
|
?? payload?.data?.result
|
|
62
91
|
?? payload?.result
|
|
@@ -72,30 +101,30 @@ function parseJsonCandidate(value) {
|
|
|
72
101
|
return JSON.parse(trimmed);
|
|
73
102
|
} catch {
|
|
74
103
|
const boundaryEnd = trimmed.lastIndexOf('</untrusted-data');
|
|
75
|
-
const
|
|
76
|
-
? trimmed.
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
104
|
+
const boundaryName = boundaryEnd >= 0
|
|
105
|
+
? trimmed.slice(boundaryEnd + 2, trimmed.indexOf('>', boundaryEnd)) : null;
|
|
106
|
+
const opening = boundaryName ? `<${boundaryName}>` : null;
|
|
107
|
+
for (let boundaryStart = opening ? trimmed.indexOf(opening) : -1;
|
|
108
|
+
boundaryStart >= 0 && boundaryStart < boundaryEnd;
|
|
109
|
+
boundaryStart = trimmed.indexOf(opening, boundaryStart + opening.length)) {
|
|
110
|
+
const contentStart = boundaryStart + opening.length;
|
|
80
111
|
// Supabase MCP sometimes returns the prose envelope with literal "\\n"
|
|
81
112
|
// separators. Strip those only at the boundary: globally replacing them
|
|
82
113
|
// corrupts valid escaped newlines inside JSON string values.
|
|
83
114
|
const inner = trimmed
|
|
84
115
|
.slice(contentStart, boundaryEnd)
|
|
85
116
|
.trim()
|
|
86
|
-
.replace(/^(?:\\r?\\n)+/, '')
|
|
87
|
-
.replace(/(?:\\r?\\n)+$/, '')
|
|
117
|
+
.replace(/^(?:(?:\\r)?\\n)+/, '')
|
|
118
|
+
.replace(/(?:(?:\\r)?\\n)+$/, '')
|
|
88
119
|
.trim();
|
|
89
120
|
try {
|
|
90
121
|
return JSON.parse(inner);
|
|
91
|
-
} catch
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
throw usageError(
|
|
95
|
-
`Supabase diagnostic rows were not valid JSON: ${error instanceof Error ? error.message : String(error)}; prefix=${JSON.stringify(inner.slice(0, 100))}`,
|
|
96
|
-
);
|
|
122
|
+
} catch {
|
|
123
|
+
// The provider also mentions this marker in its introductory prose.
|
|
124
|
+
// Try its actual opening, never a nested tool result's different marker.
|
|
97
125
|
}
|
|
98
126
|
}
|
|
127
|
+
if (boundaryEnd >= 0) throw usageError('Supabase diagnostic rows were not valid JSON.');
|
|
99
128
|
const arrayMatch = trimmed.match(/(\[[\s\S]*\])/);
|
|
100
129
|
if (arrayMatch) {
|
|
101
130
|
try {
|
|
@@ -445,7 +474,15 @@ async function debugEntitlementOverrideHandler(ctx) {
|
|
|
445
474
|
});
|
|
446
475
|
}
|
|
447
476
|
|
|
448
|
-
function
|
|
477
|
+
export function langfuseTraceIdCandidates(reference) {
|
|
478
|
+
const value = String(reference);
|
|
479
|
+
const compact = value.replaceAll('-', '').toLowerCase();
|
|
480
|
+
const providerId = /^[0-9a-f]{32}$/.test(compact) && !/^0+$/.test(compact)
|
|
481
|
+
? compact : createHash('sha256').update(value).digest('hex').slice(0, 32);
|
|
482
|
+
return [...new Set([providerId, value])];
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
export function buildTraceCostSql(reference) {
|
|
449
486
|
const literal = sqlLiteral(reference);
|
|
450
487
|
return `
|
|
451
488
|
SELECT jsonb_build_object(
|
|
@@ -464,6 +501,8 @@ SELECT jsonb_build_object(
|
|
|
464
501
|
FROM public.interactions AS i
|
|
465
502
|
WHERE i.id::text = ${literal}
|
|
466
503
|
OR to_jsonb(i)->>'trace_id' = ${literal}
|
|
504
|
+
OR replace(i.id::text, '-', '') = lower(${literal})
|
|
505
|
+
OR replace(to_jsonb(i)->>'trace_id', '-', '') = lower(${literal})
|
|
467
506
|
ORDER BY i.created_at ASC;`;
|
|
468
507
|
}
|
|
469
508
|
|
|
@@ -579,7 +618,10 @@ async function debugTraceCostHandler(ctx) {
|
|
|
579
618
|
refund_basis: refundableEstimate === null
|
|
580
619
|
? 'Requires confirmed Notis bug evidence and an explicit bug-attributable cost. Misunderstandings and service limitations are not goodwill bugs.'
|
|
581
620
|
: 'Capped at the lower of recorded provider cost and the explicitly attributed true-bug amount.',
|
|
582
|
-
interactions
|
|
621
|
+
interactions: interactions.map((item) => ({
|
|
622
|
+
...item,
|
|
623
|
+
langfuse_trace_id_candidates: langfuseTraceIdCandidates(item.trace_id || item.id),
|
|
624
|
+
})),
|
|
583
625
|
trace_file: traceDiagnostics,
|
|
584
626
|
};
|
|
585
627
|
return ctx.output.emitSuccess({
|
|
@@ -606,7 +648,42 @@ async function debugWorkerIdentityHandler(ctx) {
|
|
|
606
648
|
});
|
|
607
649
|
}
|
|
608
650
|
|
|
651
|
+
export function buildProcessDiagnosticsSql(reference) {
|
|
652
|
+
if (typeof reference !== 'string' || !reference.trim() || reference.length > 256) {
|
|
653
|
+
throw usageError('An interaction id of 1–256 characters is required.');
|
|
654
|
+
}
|
|
655
|
+
return `BEGIN READ ONLY; SET LOCAL request.jwt.claim.role='service_role'; SELECT public.notis_process_diagnostics_v1(${sqlLiteral(reference)}) AS diagnostic; COMMIT;`;
|
|
656
|
+
}
|
|
657
|
+
|
|
658
|
+
async function debugProcessHandler(ctx) {
|
|
659
|
+
const execution = await executeReadOnlySql(ctx, buildProcessDiagnosticsSql(ctx.args.interactionId), 'process');
|
|
660
|
+
const raw = execution.rows[0]?.diagnostic;
|
|
661
|
+
const diagnostic = typeof raw === 'string' ? JSON.parse(raw) : raw;
|
|
662
|
+
if (!diagnostic || diagnostic.definition_version !== 1 || diagnostic.status) {
|
|
663
|
+
throw usageError(`Process diagnostics unavailable: ${diagnostic?.status || 'invalid response'}.`);
|
|
664
|
+
}
|
|
665
|
+
if (diagnostic.interaction_id !== ctx.args.interactionId) throw usageError('Crossed diagnostic identity.');
|
|
666
|
+
return ctx.output.emitSuccess({
|
|
667
|
+
command: ctx.spec.command_path.join(' '), data: diagnostic, requestId: execution.requestId,
|
|
668
|
+
humanSummary: `${diagnostic.user_outcome}; ${diagnostic.handling}; ${diagnostic.reason_code || 'no incident'}.`,
|
|
669
|
+
meta: { mutating: false, sql_tool: execution.toolName },
|
|
670
|
+
renderHuman: () => JSON.stringify(diagnostic, null, 2),
|
|
671
|
+
});
|
|
672
|
+
}
|
|
673
|
+
|
|
609
674
|
export const diagnosticCommandSpecs = [
|
|
675
|
+
{
|
|
676
|
+
command_path: ['debug', 'process'],
|
|
677
|
+
summary: 'Read receipt-backed process diagnostics for one interaction.',
|
|
678
|
+
when_to_use: 'Correlate an interaction with Temporal runs, private failure references, delivery and settlement.',
|
|
679
|
+
args_schema: { arguments: [{ token: '<interaction-id>', key: 'interactionId', description: 'Exact interaction id.' }], options: [] },
|
|
680
|
+
examples: ['notis debug process interaction_123 --json'],
|
|
681
|
+
output_schema: 'Versioned, content-free logical outcome, handling, workflow/run and evidence references.',
|
|
682
|
+
mutates: false, idempotent: true,
|
|
683
|
+
related_commands: ['notis debug worker-identity', 'notis debug trace-cost <trace-or-interaction>'],
|
|
684
|
+
backend_call: { type: 'tool-discovery', name: 'Supabase execute SQL capability' },
|
|
685
|
+
handler: debugProcessHandler,
|
|
686
|
+
},
|
|
610
687
|
{
|
|
611
688
|
command_path: ['debug', 'user-context'],
|
|
612
689
|
summary: 'Resolve a user’s effective redacted runtime and billing context.',
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import { usageError } from '../runtime/errors.js';
|
|
2
|
+
import { httpRequest } from '../runtime/transport.js';
|
|
3
|
+
import { unifiedDiffSummary, versionName } from './version-history.js';
|
|
4
|
+
|
|
5
|
+
const documentArgument = { token: '<document-id>', key: 'documentId', description: 'Exact document ID.' };
|
|
6
|
+
const versionOption = { flags: '--version-id <version-id>', description: 'Saved version ID from versions list.' };
|
|
7
|
+
|
|
8
|
+
async function remote(ctx, operation, { method = 'POST', body, query, humanSummary } = {}) {
|
|
9
|
+
const suffix = query ? `?${new URLSearchParams(Object.entries(query).filter(([, value]) => value != null))}` : '';
|
|
10
|
+
const result = await httpRequest({ runtime: ctx.runtime, method, path: `/portal_documents/${operation}${suffix}`, body, spacesProtocol: true });
|
|
11
|
+
return ctx.output.emitSuccess({ command: ctx.spec.command_path.join(' '), data: result.payload,
|
|
12
|
+
humanSummary: humanSummary ? humanSummary(result.payload) : JSON.stringify(result.payload, null, 2),
|
|
13
|
+
meta: { mutating: method !== 'GET', request_id: result.requestId } });
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function versionId(options) {
|
|
17
|
+
if (typeof options.versionId !== 'string' || !options.versionId.trim()) throw usageError('Pass --version-id with a saved version ID from versions list.');
|
|
18
|
+
return options.versionId;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function limit(value) {
|
|
22
|
+
if (value === undefined) return undefined;
|
|
23
|
+
if (!/^\d+$/.test(value) || Number(value) < 1 || Number(value) > 100) throw usageError('Pass --limit as a whole number from 1 to 100.');
|
|
24
|
+
return Number(value);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function confirmed(options, what) {
|
|
28
|
+
if (!options.yes) throw usageError(`${what} cannot be undone. Only do it when the user asked, then pass --yes.`);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export const documentsCommandSpecs = [
|
|
32
|
+
{
|
|
33
|
+
command_path: ['documents', 'versions', 'list'],
|
|
34
|
+
summary: 'Read a document’s saved versions, newest first.',
|
|
35
|
+
when_to_use: 'See when and by whom a document changed, before comparing or restoring a version.',
|
|
36
|
+
args_schema: { arguments: [documentArgument], options: [
|
|
37
|
+
{ flags: '--before <version-id>', description: 'Read versions older than this version.' },
|
|
38
|
+
{ flags: '--limit <count>', description: 'How many versions to read (1 to 100).' },
|
|
39
|
+
] },
|
|
40
|
+
examples: ['notis documents versions list <document-id>'], mutates: false, idempotent: true, require_auth: true,
|
|
41
|
+
backend_call: { type: 'http', path: '/portal_documents/versions' },
|
|
42
|
+
handler(ctx) {
|
|
43
|
+
return remote(ctx, 'versions', { method: 'GET', query: { document_id: ctx.args.documentId,
|
|
44
|
+
before: ctx.options.before, limit: limit(ctx.options.limit) } });
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
command_path: ['documents', 'versions', 'read'],
|
|
49
|
+
summary: 'Read one saved version of a document.',
|
|
50
|
+
when_to_use: 'See exactly what a saved version said, before comparing or restoring it.',
|
|
51
|
+
args_schema: { arguments: [documentArgument], options: [versionOption] },
|
|
52
|
+
examples: ['notis documents versions read <document-id> --version-id <version-id>'],
|
|
53
|
+
mutates: false, idempotent: true, require_auth: true,
|
|
54
|
+
backend_call: { type: 'http', path: '/portal_documents/versions/read' },
|
|
55
|
+
handler(ctx) {
|
|
56
|
+
return remote(ctx, 'versions/read', { method: 'GET', query: { document_id: ctx.args.documentId, version_id: versionId(ctx.options) } });
|
|
57
|
+
},
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
command_path: ['documents', 'versions', 'diff'],
|
|
61
|
+
summary: 'Compare two saved versions of a document, or one with the current version.',
|
|
62
|
+
when_to_use: 'See what changed between versions. Prints the unified diff; pass --json for the full comparison.',
|
|
63
|
+
args_schema: { arguments: [documentArgument], options: [
|
|
64
|
+
{ flags: '--from <version-id>', description: 'The older saved version.' },
|
|
65
|
+
{ flags: '--to <version-id>', description: 'The newer saved version, or current (default).' },
|
|
66
|
+
] },
|
|
67
|
+
examples: ['notis documents versions diff <document-id> --from <version-id>',
|
|
68
|
+
'notis documents versions diff <document-id> --from <version-id> --to <version-id> --json'],
|
|
69
|
+
mutates: false, idempotent: true, require_auth: true,
|
|
70
|
+
backend_call: { type: 'http', path: '/portal_documents/versions/diff' },
|
|
71
|
+
handler(ctx) {
|
|
72
|
+
if (typeof ctx.options.from !== 'string' || !ctx.options.from.trim()) throw usageError('Pass --from with a saved version ID from versions list.');
|
|
73
|
+
return remote(ctx, 'versions/diff', { method: 'GET', humanSummary: unifiedDiffSummary,
|
|
74
|
+
query: { document_id: ctx.args.documentId, from: ctx.options.from, to: ctx.options.to || 'current' } });
|
|
75
|
+
},
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
command_path: ['documents', 'versions', 'restore'],
|
|
79
|
+
summary: 'Bring a document back to a saved version; what it replaces is kept as a version.',
|
|
80
|
+
when_to_use: 'Undo changes to a document by restoring an earlier version.',
|
|
81
|
+
args_schema: { arguments: [documentArgument], options: [versionOption,
|
|
82
|
+
{ flags: '--request-id <id>', description: 'Stable restore request ID; reuse on retry.' }] },
|
|
83
|
+
examples: ['notis documents versions restore <document-id> --version-id <version-id> --request-id undo-edit'],
|
|
84
|
+
mutates: true, idempotent: true, require_auth: true,
|
|
85
|
+
backend_call: { type: 'http', path: '/portal_documents/versions/restore' },
|
|
86
|
+
handler(ctx) {
|
|
87
|
+
const version = versionId(ctx.options);
|
|
88
|
+
if (!ctx.options.requestId) throw usageError('Pass a stable --request-id and reuse it on retry.');
|
|
89
|
+
return remote(ctx, 'versions/restore', { body: { document_id: ctx.args.documentId, version_id: version,
|
|
90
|
+
request_id: ctx.options.requestId } });
|
|
91
|
+
},
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
command_path: ['documents', 'versions', 'name'],
|
|
95
|
+
summary: 'Name a saved version of a document, or clear its name.',
|
|
96
|
+
when_to_use: 'Mark a version worth keeping. Named versions are kept past the usual retention.',
|
|
97
|
+
args_schema: { arguments: [documentArgument], options: [versionOption,
|
|
98
|
+
{ flags: '--name <name>', description: 'The version name.' },
|
|
99
|
+
{ flags: '--clear', description: 'Remove the version name.' }] },
|
|
100
|
+
examples: ['notis documents versions name <document-id> --version-id <version-id> --name "Final draft"'],
|
|
101
|
+
mutates: true, idempotent: true, require_auth: true,
|
|
102
|
+
backend_call: { type: 'http', path: '/portal_documents/versions/name' },
|
|
103
|
+
handler(ctx) {
|
|
104
|
+
return remote(ctx, 'versions/name', { body: { document_id: ctx.args.documentId, version_id: versionId(ctx.options),
|
|
105
|
+
name: versionName(ctx.options) } });
|
|
106
|
+
},
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
command_path: ['documents', 'versions', 'delete'],
|
|
110
|
+
summary: 'Delete one saved version of a document for good.',
|
|
111
|
+
when_to_use: 'Only when the user asked to delete this version. It cannot be restored afterwards.',
|
|
112
|
+
args_schema: { arguments: [documentArgument], options: [versionOption,
|
|
113
|
+
{ flags: '--yes', description: 'Confirm the user asked to delete this version for good.' }] },
|
|
114
|
+
examples: ['notis documents versions delete <document-id> --version-id <version-id> --yes'],
|
|
115
|
+
mutates: true, idempotent: true, require_auth: true,
|
|
116
|
+
backend_call: { type: 'http', path: '/portal_documents/versions/delete' },
|
|
117
|
+
handler(ctx) {
|
|
118
|
+
const version = versionId(ctx.options);
|
|
119
|
+
confirmed(ctx.options, 'Deleting a saved version');
|
|
120
|
+
return remote(ctx, 'versions/delete', { body: { document_id: ctx.args.documentId, version_id: version } });
|
|
121
|
+
},
|
|
122
|
+
},
|
|
123
|
+
{
|
|
124
|
+
command_path: ['documents', 'bin', 'list'],
|
|
125
|
+
summary: 'List the documents in your Bin.',
|
|
126
|
+
when_to_use: 'Find a deleted document to bring back, or to remove for good.',
|
|
127
|
+
args_schema: { arguments: [], options: [] },
|
|
128
|
+
examples: ['notis documents bin list'], mutates: false, idempotent: true, require_auth: true,
|
|
129
|
+
backend_call: { type: 'http', path: '/portal_documents/bin' },
|
|
130
|
+
handler(ctx) {
|
|
131
|
+
return remote(ctx, 'bin', { method: 'GET' });
|
|
132
|
+
},
|
|
133
|
+
},
|
|
134
|
+
{
|
|
135
|
+
command_path: ['documents', 'bin', 'restore'],
|
|
136
|
+
summary: 'Bring a document back from the Bin.',
|
|
137
|
+
when_to_use: 'Undo deleting a document.',
|
|
138
|
+
args_schema: { arguments: [documentArgument], options: [] },
|
|
139
|
+
examples: ['notis documents bin restore <document-id>'], mutates: true, idempotent: true, require_auth: true,
|
|
140
|
+
backend_call: { type: 'http', path: '/portal_documents/bin/restore' },
|
|
141
|
+
handler(ctx) {
|
|
142
|
+
return remote(ctx, 'bin/restore', { body: { document_id: ctx.args.documentId } });
|
|
143
|
+
},
|
|
144
|
+
},
|
|
145
|
+
{
|
|
146
|
+
command_path: ['documents', 'bin', 'remove'],
|
|
147
|
+
summary: 'Remove a document from the Bin for good.',
|
|
148
|
+
when_to_use: 'Only when the user asked to remove this document for good. It cannot be brought back afterwards.',
|
|
149
|
+
args_schema: { arguments: [documentArgument], options: [
|
|
150
|
+
{ flags: '--yes', description: 'Confirm the user asked to remove this document for good.' }] },
|
|
151
|
+
examples: ['notis documents bin remove <document-id> --yes'], mutates: true, idempotent: true, require_auth: true,
|
|
152
|
+
backend_call: { type: 'http', path: '/portal_documents/bin/remove' },
|
|
153
|
+
handler(ctx) {
|
|
154
|
+
confirmed(ctx.options, 'Removing a document from the Bin');
|
|
155
|
+
return remote(ctx, 'bin/remove', { body: { document_id: ctx.args.documentId } });
|
|
156
|
+
},
|
|
157
|
+
},
|
|
158
|
+
];
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { uploadNativeRecordFileWithCliRuntime } from '../runtime/native-record-files.js';
|
|
2
|
+
import { parseJson } from './helpers.js';
|
|
3
|
+
import { usageError } from '../runtime/errors.js';
|
|
4
|
+
|
|
5
|
+
export const filesCommandSpecs = [{
|
|
6
|
+
command_path: ['files', 'upload'],
|
|
7
|
+
summary: 'Upload a local file for one native record you can edit.',
|
|
8
|
+
when_to_use: 'Save file bytes without a cloud computer; attach the returned file reference through a normal revision-checked row update.',
|
|
9
|
+
args_schema: { arguments: [{ token: '<file>', key: 'file', description: 'Local regular file up to 8 MB.' }], options: [
|
|
10
|
+
{ flags: '--target <json>', description: 'Exact native target returned by schema discovery.' },
|
|
11
|
+
{ flags: '--record-key <id>', description: 'Stable record key to attach this file to.' },
|
|
12
|
+
{ flags: '--schema-revision <number>', description: 'Current native schema revision.' },
|
|
13
|
+
{ flags: '--request-id <uuid>', description: 'Stable UUID; reuse with identical bytes after an uncertain response.' },
|
|
14
|
+
{ flags: '--name <name>', description: 'Attachment name; defaults to the local basename.' },
|
|
15
|
+
{ flags: '--content-type <mime>', description: 'File MIME type; inferred from known extensions.' },
|
|
16
|
+
] },
|
|
17
|
+
examples: ['notis files upload ./report.html --target \'{"database_id":"<database-id>"}\' --record-key <record-key> --schema-revision 1 --request-id <uuid>'],
|
|
18
|
+
mutates: true, idempotent: true, require_auth: true,
|
|
19
|
+
backend_call: { type: 'http', path: '/portal_native_files/upload' },
|
|
20
|
+
async handler(ctx) {
|
|
21
|
+
if (!ctx.options.target || ctx.options.schemaRevision === undefined) throw usageError('Pass the discovered native --target and --schema-revision.');
|
|
22
|
+
const result = await uploadNativeRecordFileWithCliRuntime({ runtime: ctx.runtime, filePath: ctx.args.file,
|
|
23
|
+
target: parseJson(ctx.options.target, '--target'), recordKey: ctx.options.recordKey,
|
|
24
|
+
schemaRevision: Number(ctx.options.schemaRevision), requestId: ctx.options.requestId,
|
|
25
|
+
...(ctx.options.name ? { name: ctx.options.name } : {}), ...(ctx.options.contentType ? { contentType: ctx.options.contentType } : {}) });
|
|
26
|
+
return ctx.output.emitSuccess({ command: 'files upload', data: result,
|
|
27
|
+
humanSummary: 'Uploaded and verified the file. Attach the returned file reference with a revision-checked record update.', meta: { mutating: true } });
|
|
28
|
+
},
|
|
29
|
+
}];
|