@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
package/src/runtime/profiles.js
CHANGED
|
@@ -1,18 +1,17 @@
|
|
|
1
|
-
import { randomUUID } from 'node:crypto';
|
|
2
1
|
import {
|
|
3
2
|
existsSync,
|
|
4
3
|
mkdirSync,
|
|
5
4
|
readFileSync,
|
|
6
5
|
renameSync,
|
|
7
|
-
rmSync,
|
|
8
|
-
statSync,
|
|
9
6
|
writeFileSync,
|
|
10
7
|
} from 'node:fs';
|
|
11
8
|
import { homedir } from 'node:os';
|
|
12
9
|
import { dirname, join, parse, resolve } from 'node:path';
|
|
13
10
|
import { CliError, EXIT_CODES } from './errors.js';
|
|
11
|
+
import { withConfigFileWriteLock } from './config-lock.js';
|
|
14
12
|
import { getAuthRecovery, quoteShellArgument } from './auth-recovery.js';
|
|
15
13
|
import { channelFromProfile, cliCommandForChannel, isReleaseChannel } from './channel.js';
|
|
14
|
+
import { resolveRetryEnabled } from './retry.js';
|
|
16
15
|
|
|
17
16
|
export const CONFIG_DIR = join(homedir(), '.notis');
|
|
18
17
|
export const CONFIG_FILE = join(CONFIG_DIR, 'config.json');
|
|
@@ -34,14 +33,6 @@ const WORKTREE_RUNTIME_FILENAME = join('.context', 'notis-runtime.json');
|
|
|
34
33
|
const WORKTREE_ROUTING_FILENAME = join('.context', 'notis-routing.json');
|
|
35
34
|
const LOCAL_API_HOSTS = new Set(['localhost', '127.0.0.1', '::1']);
|
|
36
35
|
const LIVE_API_HOSTS = new Set(['api.notis.ai', 'api-beta.notis.ai']);
|
|
37
|
-
// Cross-process write lock over ~/.notis/config.json. Independent `notis`
|
|
38
|
-
// processes (a `login` in one terminal and a `tools exec` in another) all
|
|
39
|
-
// rewrite this file, so the lock directory name and these three timings are the
|
|
40
|
-
// whole coordination protocol. Guarded by the concurrency test in
|
|
41
|
-
// packages/cli/test/runtime-auth.test.js.
|
|
42
|
-
const CONFIG_WRITE_LOCK_TIMEOUT_MS = 5_000;
|
|
43
|
-
const CONFIG_WRITE_LOCK_STALE_MS = 2_000;
|
|
44
|
-
const CONFIG_WRITE_LOCK_POLL_MS = 10;
|
|
45
36
|
|
|
46
37
|
function clone(value) {
|
|
47
38
|
return JSON.parse(JSON.stringify(value));
|
|
@@ -206,7 +197,7 @@ function readJsonFile(path) {
|
|
|
206
197
|
}
|
|
207
198
|
}
|
|
208
199
|
|
|
209
|
-
function findUp(filename, startDir = process.cwd()) {
|
|
200
|
+
function findUp(filename, startDir = process.cwd(), boundary = null) {
|
|
210
201
|
let current = resolve(startDir);
|
|
211
202
|
const root = parse(current).root;
|
|
212
203
|
while (true) {
|
|
@@ -214,7 +205,7 @@ function findUp(filename, startDir = process.cwd()) {
|
|
|
214
205
|
if (existsSync(candidate)) {
|
|
215
206
|
return candidate;
|
|
216
207
|
}
|
|
217
|
-
if (current === root) {
|
|
208
|
+
if (current === root || current === boundary) {
|
|
218
209
|
return null;
|
|
219
210
|
}
|
|
220
211
|
current = dirname(current);
|
|
@@ -228,8 +219,11 @@ function processIsAlive(pid) {
|
|
|
228
219
|
try {
|
|
229
220
|
process.kill(pid, 0);
|
|
230
221
|
return true;
|
|
231
|
-
} catch {
|
|
232
|
-
|
|
222
|
+
} catch (error) {
|
|
223
|
+
// Sandboxed children may be allowed to observe the worktree lease but not
|
|
224
|
+
// signal its dev.sh supervisor. POSIX EPERM proves that the PID exists;
|
|
225
|
+
// ESRCH (and every other probe failure) does not.
|
|
226
|
+
return error?.code === 'EPERM';
|
|
233
227
|
}
|
|
234
228
|
}
|
|
235
229
|
|
|
@@ -240,8 +234,11 @@ export function resolveWorktreeRuntime(startDir = process.cwd()) {
|
|
|
240
234
|
) {
|
|
241
235
|
return null;
|
|
242
236
|
}
|
|
243
|
-
const runtimePath = findUp(WORKTREE_RUNTIME_FILENAME, startDir);
|
|
244
237
|
const routingPath = findUp(WORKTREE_ROUTING_FILENAME, startDir);
|
|
238
|
+
// A nested worktree's persistent policy survives its lease. Never cross that
|
|
239
|
+
// boundary and borrow a still-running ancestor worktree's credential/route.
|
|
240
|
+
const boundary = routingPath ? dirname(dirname(routingPath)) : null;
|
|
241
|
+
const runtimePath = findUp(WORKTREE_RUNTIME_FILENAME, startDir, boundary);
|
|
245
242
|
const routing = routingPath ? readJsonFile(routingPath) : null;
|
|
246
243
|
|
|
247
244
|
if (!runtimePath) {
|
|
@@ -369,103 +366,11 @@ function writeRawConfig(configFile, config) {
|
|
|
369
366
|
renameSync(temporaryFile, configFile);
|
|
370
367
|
}
|
|
371
368
|
|
|
372
|
-
//
|
|
373
|
-
//
|
|
374
|
-
//
|
|
375
|
-
// would then delete the thief's lock and admit a third writer. Both sides are
|
|
376
|
-
// on the same host, so the stored timestamp and Date.now() share a clock.
|
|
377
|
-
function readLockOwner(lockDirectory) {
|
|
378
|
-
try {
|
|
379
|
-
return JSON.parse(readFileSync(join(lockDirectory, 'owner'), 'utf-8'));
|
|
380
|
-
} catch {
|
|
381
|
-
return null;
|
|
382
|
-
}
|
|
383
|
-
}
|
|
384
|
-
|
|
385
|
-
function lockDirectoryMtime(lockDirectory) {
|
|
386
|
-
try {
|
|
387
|
-
return statSync(lockDirectory).mtimeMs;
|
|
388
|
-
} catch {
|
|
389
|
-
return null;
|
|
390
|
-
}
|
|
391
|
-
}
|
|
392
|
-
|
|
393
|
-
function publishConfigWriteLock(lockDirectory, ownerId) {
|
|
394
|
-
const candidateDirectory = `${lockDirectory}.candidate-${ownerId}`;
|
|
395
|
-
try {
|
|
396
|
-
mkdirSync(candidateDirectory);
|
|
397
|
-
writeFileSync(
|
|
398
|
-
join(candidateDirectory, 'owner'),
|
|
399
|
-
JSON.stringify({ id: ownerId, at: Date.now() }),
|
|
400
|
-
{ mode: 0o600 },
|
|
401
|
-
);
|
|
402
|
-
try {
|
|
403
|
-
renameSync(candidateDirectory, lockDirectory);
|
|
404
|
-
return true;
|
|
405
|
-
} catch (error) {
|
|
406
|
-
if (!existsSync(lockDirectory)) throw error;
|
|
407
|
-
return false;
|
|
408
|
-
}
|
|
409
|
-
} finally {
|
|
410
|
-
rmSync(candidateDirectory, { recursive: true, force: true });
|
|
411
|
-
}
|
|
412
|
-
}
|
|
413
|
-
|
|
369
|
+
// Independent `notis` processes and Desktop all rewrite this file. The lock
|
|
370
|
+
// protocol lives in config-lock.js, shared with computer.json and mirrored by
|
|
371
|
+
// Desktop.
|
|
414
372
|
function withConfigWriteLock(callback) {
|
|
415
|
-
|
|
416
|
-
const lockDirectory = `${configFile}.write-lock`;
|
|
417
|
-
const ownerId = `${process.pid}.${randomUUID()}`;
|
|
418
|
-
const deadline = Date.now() + CONFIG_WRITE_LOCK_TIMEOUT_MS;
|
|
419
|
-
mkdirSync(dirname(configFile), { recursive: true });
|
|
420
|
-
for (;;) {
|
|
421
|
-
if (!existsSync(lockDirectory) && publishConfigWriteLock(lockDirectory, ownerId)) {
|
|
422
|
-
break;
|
|
423
|
-
}
|
|
424
|
-
|
|
425
|
-
const owner = readLockOwner(lockDirectory);
|
|
426
|
-
const observedMtime = lockDirectoryMtime(lockDirectory);
|
|
427
|
-
const ownerIsStale =
|
|
428
|
-
owner?.id && Date.now() - Number(owner.at) > CONFIG_WRITE_LOCK_STALE_MS;
|
|
429
|
-
const ownerlessIsStale =
|
|
430
|
-
!owner
|
|
431
|
-
&& observedMtime !== null
|
|
432
|
-
&& Date.now() - observedMtime > CONFIG_WRITE_LOCK_STALE_MS;
|
|
433
|
-
if (ownerIsStale || ownerlessIsStale) {
|
|
434
|
-
try {
|
|
435
|
-
const currentOwner = readLockOwner(lockDirectory);
|
|
436
|
-
const ownerUnchanged = owner?.id
|
|
437
|
-
? currentOwner?.id === owner.id
|
|
438
|
-
: !currentOwner && lockDirectoryMtime(lockDirectory) === observedMtime;
|
|
439
|
-
if (ownerUnchanged) {
|
|
440
|
-
rmSync(lockDirectory, { recursive: true, force: true });
|
|
441
|
-
continue;
|
|
442
|
-
}
|
|
443
|
-
} catch {
|
|
444
|
-
// Losing the reclaim race is normal; fall through and keep waiting.
|
|
445
|
-
}
|
|
446
|
-
}
|
|
447
|
-
if (Date.now() >= deadline) {
|
|
448
|
-
throw new Error(`Timed out waiting to update ${configFile}`);
|
|
449
|
-
}
|
|
450
|
-
Atomics.wait(
|
|
451
|
-
new Int32Array(new SharedArrayBuffer(4)),
|
|
452
|
-
0,
|
|
453
|
-
0,
|
|
454
|
-
CONFIG_WRITE_LOCK_POLL_MS,
|
|
455
|
-
);
|
|
456
|
-
}
|
|
457
|
-
try {
|
|
458
|
-
return callback(configFile);
|
|
459
|
-
} finally {
|
|
460
|
-
try {
|
|
461
|
-
// Never release a lock that was reclaimed from us while we worked.
|
|
462
|
-
if (readLockOwner(lockDirectory)?.id === ownerId) {
|
|
463
|
-
rmSync(lockDirectory, { recursive: true, force: true });
|
|
464
|
-
}
|
|
465
|
-
} catch {
|
|
466
|
-
// The lock may already have been removed after an interrupted write.
|
|
467
|
-
}
|
|
468
|
-
}
|
|
373
|
+
return withConfigFileWriteLock(resolveConfigFile(), callback);
|
|
469
374
|
}
|
|
470
375
|
|
|
471
376
|
export function saveConfig(config) {
|
|
@@ -967,6 +872,8 @@ export function resolveRuntimeProfile(
|
|
|
967
872
|
nonInteractive,
|
|
968
873
|
outputMode,
|
|
969
874
|
timeoutMs,
|
|
875
|
+
// Automatic retries of interrupted calls that are safe to repeat.
|
|
876
|
+
retry: resolveRetryEnabled(globalOptions),
|
|
970
877
|
debugEntitlementOverride,
|
|
971
878
|
worktreeRuntime: devRuntime,
|
|
972
879
|
detachedWorktreeRuntime: devRuntime ? null : worktreeRuntime,
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/** Exact canonical files retired from the embedded SDK (one-Shadow-runtime cutover, toolkit move).
|
|
2
|
+
* Modified or additional source is retained for explicit reconciliation. */
|
|
3
|
+
// Host mounting code stays in the canonical SDK and CLI host bundle, not in
|
|
4
|
+
// authored apps' public SDK mirror. It is not a public package export.
|
|
5
|
+
export const HOST_ONLY_SDK_FILES = Object.freeze(['src/presentation.tsx']);
|
|
6
|
+
|
|
7
|
+
export const RETIRED_SDK_FILES = Object.freeze({
|
|
8
|
+
"src/presentation.tsx": [
|
|
9
|
+
"d29022f92e1e96b451b62cc8a561878a1c0cf8a3b4c0419181de7266f8a1b525"
|
|
10
|
+
],
|
|
11
|
+
"src/isolatedHost.tsx": [
|
|
12
|
+
"7f59049281a9533d39c557ca75635073c2f404f1eb0a528b274323d61db776cd"
|
|
13
|
+
],
|
|
14
|
+
"src/frameProtocol.ts": [
|
|
15
|
+
"f32337ddb507718be04289a4acf50cf2485698bc716556230f35f06a6f633f19"
|
|
16
|
+
],
|
|
17
|
+
"src/frameIsolation.ts": [
|
|
18
|
+
"8b57cb38f618eefc4133ae50fbf2b37bbdef5be02e44b39758d8328fb2a59ab6"
|
|
19
|
+
],
|
|
20
|
+
// Moved to src/ui/charts/RenderChartData.tsx with the Spaces toolkit.
|
|
21
|
+
"src/components/RenderChartData.tsx": [
|
|
22
|
+
"a3a8ab3ffe4cd7807e0591b6dace77c24dd08cb556e4170595783e986a513808"
|
|
23
|
+
]
|
|
24
|
+
});
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import { CliError } from './errors.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Safe automatic retries for tool calls.
|
|
5
|
+
*
|
|
6
|
+
* A call is replayed only when the replay is provably harmless:
|
|
7
|
+
* - A read the server proves read-only. Keyless writes are refused before
|
|
8
|
+
* they run, so replaying a keyless call never repeats an effect.
|
|
9
|
+
* - A call with an idempotency key. The server stores the first outcome under
|
|
10
|
+
* that key, so the same key and the same body either join the running call,
|
|
11
|
+
* or return its stored answer.
|
|
12
|
+
* - A native write that answered "outcome unknown" and carries its own
|
|
13
|
+
* `request_id`. Its stored answer is that unknown outcome, so the replay
|
|
14
|
+
* sends identical arguments under a fresh idempotency key and the native
|
|
15
|
+
* receipt for the `request_id` decides whether it already happened.
|
|
16
|
+
*
|
|
17
|
+
* Every other failure is returned after the first attempt.
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
export const RETRY_MAX_ATTEMPTS = 3;
|
|
21
|
+
export const RETRY_BASE_DELAY_MS = 250;
|
|
22
|
+
export const RETRY_MAX_DELAY_MS = 2000;
|
|
23
|
+
const RETRY_MIN_ATTEMPT_WINDOW_MS = 1000;
|
|
24
|
+
|
|
25
|
+
const TRANSIENT_HTTP_STATUSES = new Set([502, 503, 504]);
|
|
26
|
+
const TRANSIENT_NETWORK_CODES = new Set(['network_error', 'network_timeout']);
|
|
27
|
+
|
|
28
|
+
// Native tool results that end with an unknown outcome and dedupe a replay by
|
|
29
|
+
// the caller's `request_id`.
|
|
30
|
+
export const TOOL_OUTCOME_UNKNOWN_CODES = new Set([
|
|
31
|
+
'document_outcome_unknown',
|
|
32
|
+
'record_file_outcome_unknown',
|
|
33
|
+
]);
|
|
34
|
+
|
|
35
|
+
const FALSE_VALUES = new Set(['', '0', 'false', 'no', 'off']);
|
|
36
|
+
|
|
37
|
+
/** `--no-retry` or a truthy NOTIS_NO_RETRY turns automatic retries off. */
|
|
38
|
+
export function resolveRetryEnabled(globalOptions = {}, env = process.env) {
|
|
39
|
+
if (globalOptions.retry === false) return false;
|
|
40
|
+
const raw = env.NOTIS_NO_RETRY;
|
|
41
|
+
if (raw === undefined || raw === null) return true;
|
|
42
|
+
return FALSE_VALUES.has(String(raw).trim().toLowerCase());
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export function retriesEnabled(runtime) {
|
|
46
|
+
return runtime?.retry !== false;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function backendErrorCode(details) {
|
|
50
|
+
const error = details?.error;
|
|
51
|
+
if (error && typeof error === 'object' && typeof error.code === 'string') return error.code;
|
|
52
|
+
return typeof error === 'string' ? error : null;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/** Whether the failure is temporary, so the same request may succeed. */
|
|
56
|
+
export function isTransientFailure(error) {
|
|
57
|
+
if (!(error instanceof CliError)) return false;
|
|
58
|
+
if (TRANSIENT_NETWORK_CODES.has(error.code)) return true;
|
|
59
|
+
const code = backendErrorCode(error.details);
|
|
60
|
+
// An unknown outcome is a final answer for this key, never a transport blip.
|
|
61
|
+
if (typeof code === 'string' && code.endsWith('_outcome_unknown')) return false;
|
|
62
|
+
if (TRANSIENT_HTTP_STATUSES.has(error.httpStatus)) return true;
|
|
63
|
+
return error.httpStatus === 409 && code === 'idempotency_in_progress';
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/** Whether sending the identical request again can never repeat an effect. */
|
|
67
|
+
export function canReplayRequest({ mutating, idempotencyKey }) {
|
|
68
|
+
return Boolean(idempotencyKey) || !mutating;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* The native outcome-unknown code a tool answer carries, if any. The answer
|
|
73
|
+
* may be the tool output itself or a multi-execute envelope around it.
|
|
74
|
+
*/
|
|
75
|
+
export function findToolOutcomeUnknown(payload, depth = 0) {
|
|
76
|
+
if (!payload || typeof payload !== 'object' || depth > 6) return null;
|
|
77
|
+
if (Array.isArray(payload)) {
|
|
78
|
+
for (const item of payload) {
|
|
79
|
+
const code = findToolOutcomeUnknown(item, depth + 1);
|
|
80
|
+
if (code) return code;
|
|
81
|
+
}
|
|
82
|
+
return null;
|
|
83
|
+
}
|
|
84
|
+
const own = backendErrorCode(payload);
|
|
85
|
+
if (own && TOOL_OUTCOME_UNKNOWN_CODES.has(own)) return own;
|
|
86
|
+
for (const value of Object.values(payload)) {
|
|
87
|
+
if (value && typeof value === 'object') {
|
|
88
|
+
const code = findToolOutcomeUnknown(value, depth + 1);
|
|
89
|
+
if (code) return code;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
return null;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function hasRequestId(args) {
|
|
96
|
+
return Boolean(args) && typeof args === 'object' && typeof args.request_id === 'string'
|
|
97
|
+
&& args.request_id.trim().length > 0;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Whether the call names exactly one tool whose arguments carry a stable
|
|
102
|
+
* `request_id`. A batch of several tools is never resent: its other items
|
|
103
|
+
* might not deduplicate a second run.
|
|
104
|
+
*/
|
|
105
|
+
export function callCarriesToolRequestId(argumentsPayload) {
|
|
106
|
+
if (!argumentsPayload || typeof argumentsPayload !== 'object') return false;
|
|
107
|
+
if (Array.isArray(argumentsPayload.tools)) {
|
|
108
|
+
return argumentsPayload.tools.length === 1 && hasRequestId(argumentsPayload.tools[0]?.arguments);
|
|
109
|
+
}
|
|
110
|
+
return hasRequestId(argumentsPayload);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
export function retryDelayMs(attempt, random = Math.random) {
|
|
114
|
+
const ceiling = Math.min(RETRY_MAX_DELAY_MS, RETRY_BASE_DELAY_MS * (2 ** (attempt - 1)));
|
|
115
|
+
return Math.round(ceiling / 2 + random() * (ceiling / 2));
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Wait before the next attempt when it still fits in the overall time budget.
|
|
120
|
+
* Returns false when no attempt is left or the budget is spent.
|
|
121
|
+
*/
|
|
122
|
+
export async function waitForNextAttempt({ attempt, deadline, budgetMs, now = Date.now, sleep = defaultSleep }) {
|
|
123
|
+
if (attempt >= RETRY_MAX_ATTEMPTS) return false;
|
|
124
|
+
const delay = retryDelayMs(attempt);
|
|
125
|
+
const window = Math.min(RETRY_MIN_ATTEMPT_WINDOW_MS, Math.floor(budgetMs / 4));
|
|
126
|
+
if (deadline - now() - delay < window) return false;
|
|
127
|
+
await sleep(delay);
|
|
128
|
+
return true;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
function defaultSleep(ms) {
|
|
132
|
+
return new Promise((resolve) => { setTimeout(resolve, ms); });
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/** Record how many attempts a failed call made, without changing its shape. */
|
|
136
|
+
export function withAttempts(error, attempts) {
|
|
137
|
+
if (error instanceof CliError) {
|
|
138
|
+
const details = error.details && typeof error.details === 'object' && !Array.isArray(error.details)
|
|
139
|
+
? error.details
|
|
140
|
+
: {};
|
|
141
|
+
error.details = { ...details, attempts };
|
|
142
|
+
if (attempts > 1) {
|
|
143
|
+
error.hints = [
|
|
144
|
+
...(Array.isArray(error.hints) ? error.hints : []),
|
|
145
|
+
{ reason: `The CLI already tried this call ${attempts} times. Check the cause before running it again.` },
|
|
146
|
+
];
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
return error;
|
|
150
|
+
}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
import { createSkillBundleBase64 } from './local-scanner';
|
|
2
|
-
import
|
|
1
|
+
import { captureNativeSkillFiles, createSkillBundleBase64 } from './local-scanner';
|
|
2
|
+
import { createHash } from 'node:crypto';
|
|
3
|
+
import { checkedNativeReference } from './native-identity';
|
|
4
|
+
import type { AgentTargets, LocalSkill, NativeSkillReference, SyncPullResponse, SyncPushResponse, SyncSettings } from './types';
|
|
3
5
|
|
|
4
6
|
type JsonBody = Record<string, unknown> | undefined;
|
|
5
7
|
|
|
@@ -9,6 +11,7 @@ async function requestJson<T>(
|
|
|
9
11
|
options: { method?: string; body?: JsonBody } = {},
|
|
10
12
|
): Promise<T> {
|
|
11
13
|
const response = await fetch(url, {
|
|
14
|
+
signal: AbortSignal.timeout(90_000),
|
|
12
15
|
method: options.method || 'POST',
|
|
13
16
|
headers: {
|
|
14
17
|
'Content-Type': 'application/json',
|
|
@@ -33,7 +36,7 @@ export async function fetchSyncSettings(serverUrl: string, jwt: string): Promise
|
|
|
33
36
|
|
|
34
37
|
export async function pullSkills(serverUrl: string, jwt: string): Promise<SyncPullResponse> {
|
|
35
38
|
return requestJson<SyncPullResponse>(`${serverUrl}/portal_skills/sync-pull`, jwt, {
|
|
36
|
-
body: {},
|
|
39
|
+
body: { skill_sync_protocol: 2 },
|
|
37
40
|
});
|
|
38
41
|
}
|
|
39
42
|
|
|
@@ -48,18 +51,23 @@ export async function pushChangedSkills(
|
|
|
48
51
|
skill_md: skill.skillMd,
|
|
49
52
|
source_url: skill.sourceUrl,
|
|
50
53
|
folder_hash: skill.folderHash,
|
|
51
|
-
|
|
54
|
+
...(skill.nativeReference ? { bundle_files: await captureNativeSkillFiles(skill) }
|
|
55
|
+
: { bundle_base64: await createSkillBundleBase64(skill) }),
|
|
56
|
+
...(skill.cloudId ? { cloud_id: skill.cloudId } : {}),
|
|
57
|
+
...(skill.nativeReference ? { native_reference: skill.nativeReference, display_name: skill.displayName,
|
|
58
|
+
native_scope: skill.nativeScope } : {}),
|
|
52
59
|
})));
|
|
53
60
|
|
|
54
61
|
return requestJson<SyncPushResponse>(`${serverUrl}/portal_skills/sync-push`, jwt, {
|
|
55
62
|
body: {
|
|
63
|
+
skill_sync_protocol: 2,
|
|
56
64
|
skills: payloadSkills,
|
|
57
65
|
},
|
|
58
66
|
});
|
|
59
67
|
}
|
|
60
68
|
|
|
61
69
|
export async function downloadSkillBundle(bundleUrl: string): Promise<Buffer> {
|
|
62
|
-
const response = await fetch(bundleUrl);
|
|
70
|
+
const response = await fetch(bundleUrl, { signal: AbortSignal.timeout(90_000) });
|
|
63
71
|
if (!response.ok) {
|
|
64
72
|
const text = await response.text();
|
|
65
73
|
throw new Error(`GET ${bundleUrl} → ${response.status}: ${text}`);
|
|
@@ -72,13 +80,30 @@ export async function updateAgentTargets(
|
|
|
72
80
|
serverUrl: string,
|
|
73
81
|
jwt: string,
|
|
74
82
|
skillId: string,
|
|
75
|
-
targets: AgentTargets
|
|
76
|
-
|
|
77
|
-
|
|
83
|
+
targets: Partial<AgentTargets>,
|
|
84
|
+
expectedUpdatedAt?: string,
|
|
85
|
+
native?: { reference: NativeSkillReference; settingsRevision: number },
|
|
86
|
+
): Promise<{ success: boolean; agent_targets: AgentTargets; updated_at?: string }> {
|
|
87
|
+
if (native) {
|
|
88
|
+
checkedNativeReference(native.reference, skillId);
|
|
89
|
+
if (!Number.isSafeInteger(native.settingsRevision) || native.settingsRevision < 0) throw new Error('Refresh native Skill settings before changing assignments.');
|
|
90
|
+
const payload = { operation: 'update', target: { skill_id: skillId, access_revision: native.reference.access_revision },
|
|
91
|
+
revision: native.settingsRevision, patch: { agent_targets: Object.fromEntries(Object.entries(targets).sort(([a], [b]) => a.localeCompare(b))) } };
|
|
92
|
+
const requestId = 'sync-settings-' + createHash('sha256').update(JSON.stringify(payload)).digest('hex');
|
|
93
|
+
const saved = await requestJson<{ receipt_id: string; skill_id: string; target: { skill_id: string }; settings: { agent_targets: AgentTargets; updated_at: string };
|
|
94
|
+
current?: { target: { skill_id: string }; settings: { agent_targets: AgentTargets; updated_at: string } } }>(`${serverUrl}/portal_skills/native-settings`, jwt,
|
|
95
|
+
{ body: { ...payload, request_id: requestId } });
|
|
96
|
+
const current = saved.current || saved;
|
|
97
|
+
if (saved.skill_id !== skillId || typeof saved.receipt_id !== 'string' || !saved.receipt_id
|
|
98
|
+
|| current.target?.skill_id !== skillId || !current.settings) throw new Error('Native assignment update was not confirmed.');
|
|
99
|
+
return { success: true, agent_targets: current.settings.agent_targets, updated_at: current.settings.updated_at };
|
|
100
|
+
}
|
|
101
|
+
return requestJson<{ success: boolean; agent_targets: AgentTargets; updated_at?: string }>(`${serverUrl}/portal_skills/agent-targets`, jwt, {
|
|
78
102
|
method: 'PATCH',
|
|
79
103
|
body: {
|
|
80
104
|
skill_id: skillId,
|
|
81
105
|
agent_targets: targets,
|
|
106
|
+
...(expectedUpdatedAt ? { expected_updated_at: expectedUpdatedAt } : {}),
|
|
82
107
|
},
|
|
83
108
|
});
|
|
84
109
|
}
|