@notis_ai/cli 0.2.0-beta.19.1 → 0.2.0-beta.196.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (216) hide show
  1. package/README.md +822 -135
  2. package/bin/check-runtime.js +15 -0
  3. package/bin/notis.js +2 -0
  4. package/config/notis_app_boundary_rules.json +50 -0
  5. package/config/notis_app_design_rules.json +135 -0
  6. package/config/portal-route-roots.json +48 -0
  7. package/dist/agent-hooks/notis-agent-hook.mjs +45587 -0
  8. package/dist/base-skills/notis-apps/SKILL.md +93 -0
  9. package/dist/base-skills/notis-apps/references/architecture.md +114 -0
  10. package/dist/base-skills/notis-apps/references/context.md +81 -0
  11. package/dist/base-skills/notis-apps/references/design.md +97 -0
  12. package/dist/base-skills/notis-apps/references/memory.md +58 -0
  13. package/dist/base-skills/notis-apps/references/reading.md +67 -0
  14. package/dist/base-skills/notis-apps/references/release.md +107 -0
  15. package/dist/base-skills/notis-apps/references/sdk.md +116 -0
  16. package/dist/base-skills/notis-apps/references/troubleshooting.md +24 -0
  17. package/dist/base-skills/notis-apps/references/views.md +142 -0
  18. package/dist/base-skills/notis-cli/SKILL.md +154 -0
  19. package/dist/base-skills/notis-cli/references/app-delivery.md +19 -0
  20. package/dist/base-skills/notis-cli/references/intelligence.md +94 -0
  21. package/dist/base-skills/notis-cli/references/native-databases.md +21 -0
  22. package/dist/base-skills/notis-cli/references/tool-examples.md +56 -0
  23. package/dist/base-skills/notis-cli/references/troubleshooting.md +39 -0
  24. package/dist/base-skills/notis-query/SKILL.md +41 -0
  25. package/dist/base-skills/notis-query/references/database-discovery.md +60 -0
  26. package/dist/base-skills/notis-query/references/documents.md +63 -0
  27. package/dist/base-skills/notis-query/references/query.md +76 -0
  28. package/{template/packages/notis-sdk → dist/sdk}/package.json +14 -4
  29. package/dist/sdk/src/agentContext.ts +36 -0
  30. package/dist/sdk/src/bundleModule.ts +79 -0
  31. package/dist/sdk/src/components/Dialog.tsx +46 -0
  32. package/dist/sdk/src/components/DocumentEditor.tsx +106 -0
  33. package/dist/sdk/src/components/DocumentPage.tsx +141 -0
  34. package/dist/sdk/src/components/Markdown.tsx +60 -0
  35. package/dist/sdk/src/components/MarkdownEditor.tsx +121 -0
  36. package/dist/sdk/src/components/MultiSelectActionBar.tsx +285 -0
  37. package/dist/sdk/src/components/MultiSelectCheckbox.tsx +97 -0
  38. package/dist/sdk/src/components/MultiSelectDragOverlay.tsx +39 -0
  39. package/dist/sdk/src/components/NotisCommentBoundary.tsx +172 -0
  40. package/dist/sdk/src/components/NotisSelectionBoundary.tsx +59 -0
  41. package/dist/sdk/src/components/RecordComponents.tsx +33 -0
  42. package/dist/sdk/src/components/RenderChartData.tsx +19 -0
  43. package/dist/sdk/src/components/ShortcutHints.tsx +56 -0
  44. package/dist/sdk/src/components/Skeleton.tsx +24 -0
  45. package/dist/sdk/src/config.ts +239 -0
  46. package/dist/sdk/src/documents.ts +258 -0
  47. package/dist/sdk/src/hooks/useAction.ts +28 -0
  48. package/dist/sdk/src/hooks/useActiveResource.ts +19 -0
  49. package/dist/sdk/src/hooks/useAgentContext.ts +23 -0
  50. package/dist/sdk/src/hooks/useCloudComputer.ts +95 -0
  51. package/dist/sdk/src/hooks/useCloudComputerShell.ts +114 -0
  52. package/dist/sdk/src/hooks/useCollectionInteractions.ts +838 -0
  53. package/dist/sdk/src/hooks/useDatabaseSchema.ts +49 -0
  54. package/dist/sdk/src/hooks/useDatabaseSubscription.ts +76 -0
  55. package/dist/sdk/src/hooks/useDocument.ts +43 -0
  56. package/dist/sdk/src/hooks/useDocuments.ts +84 -0
  57. package/dist/sdk/src/hooks/useHandover.ts +78 -0
  58. package/dist/sdk/src/hooks/useLongPressSelection.ts +79 -0
  59. package/dist/sdk/src/hooks/useMultiSelect.ts +95 -0
  60. package/dist/sdk/src/hooks/useNativeDocumentBody.ts +50 -0
  61. package/dist/sdk/src/hooks/useNativeDocuments.ts +83 -0
  62. package/dist/sdk/src/hooks/useNotis.ts +42 -0
  63. package/dist/sdk/src/hooks/useNotisNavigation.ts +67 -0
  64. package/dist/sdk/src/hooks/useQuery.ts +74 -0
  65. package/dist/sdk/src/hooks/useTool.ts +65 -0
  66. package/dist/sdk/src/hooks/useToolQuery.ts +12 -0
  67. package/dist/sdk/src/hooks/useTopBarSearch.ts +81 -0
  68. package/dist/sdk/src/hooks/useUpsertDocument.ts +95 -0
  69. package/dist/sdk/src/hooks/useViewParams.ts +121 -0
  70. package/dist/sdk/src/hooks/useViewerReads.ts +129 -0
  71. package/dist/sdk/src/index.ts +200 -0
  72. package/dist/sdk/src/interactions/actions.ts +59 -0
  73. package/dist/sdk/src/interactions/shortcuts.tsx +740 -0
  74. package/dist/sdk/src/interactions/visibility.ts +13 -0
  75. package/dist/sdk/src/interactions.ts +45 -0
  76. package/dist/sdk/src/nativeData.ts +39 -0
  77. package/dist/sdk/src/presentation.tsx +82 -0
  78. package/dist/sdk/src/provider.tsx +49 -0
  79. package/dist/sdk/src/queryCache.ts +172 -0
  80. package/dist/sdk/src/queryErrors.ts +51 -0
  81. package/dist/sdk/src/runtime.ts +603 -0
  82. package/dist/sdk/src/space.ts +425 -0
  83. package/dist/sdk/src/styles.css +290 -0
  84. package/dist/sdk/src/tailwind.ts +66 -0
  85. package/dist/sdk/src/vite.ts +83 -0
  86. package/dist/skill-sync/index.js +2143 -0
  87. package/dist/skill-sync/index.js.map +7 -0
  88. package/dist/skill-sync-worker.mjs +3487 -0
  89. package/dist/space-harness/host.js +66 -0
  90. package/dist/view-renderer/dist/host.css +1 -0
  91. package/dist/view-renderer/dist/host.js +1042 -0
  92. package/dist/view-renderer/dist/theme.css +73 -0
  93. package/dist/view-renderer/src/dom.js +180 -0
  94. package/dist/view-renderer/src/errors.js +8 -0
  95. package/dist/view-renderer/src/host.tsx +173 -0
  96. package/dist/view-renderer/src/index.js +4 -0
  97. package/dist/view-renderer/src/pool.js +76 -0
  98. package/dist/view-renderer/src/remote-broker.js +59 -0
  99. package/dist/view-renderer/src/renderer.js +201 -0
  100. package/package.json +25 -8
  101. package/skills/notis-apps/cli.md +406 -0
  102. package/skills/notis-cli/AGENT_INSTRUCTIONS.md +39 -0
  103. package/skills/notis-onboarding/BRIEF.md +133 -0
  104. package/skills/notis-query/cli.md +39 -0
  105. package/src/agent-hook-entry.js +5 -0
  106. package/src/cli.js +294 -25
  107. package/src/command-specs/agents.js +392 -0
  108. package/src/command-specs/apps.js +1476 -203
  109. package/src/command-specs/auth.js +114 -137
  110. package/src/command-specs/diagnostics.js +730 -0
  111. package/src/command-specs/files.js +29 -0
  112. package/src/command-specs/handover.js +374 -0
  113. package/src/command-specs/helpers.js +86 -82
  114. package/src/command-specs/index.js +31 -6
  115. package/src/command-specs/meta.js +150 -18
  116. package/src/command-specs/onboarding.js +290 -0
  117. package/src/command-specs/profile.js +358 -0
  118. package/src/command-specs/skills.js +304 -0
  119. package/src/command-specs/smoke.js +386 -0
  120. package/src/command-specs/spaces.js +572 -0
  121. package/src/command-specs/tools.js +455 -139
  122. package/src/command-specs/views.js +69 -0
  123. package/src/runtime/agent-browser.js +700 -0
  124. package/src/runtime/agent-memory-state.js +126 -0
  125. package/src/runtime/agent-setup.js +383 -0
  126. package/src/runtime/app-boundary-validator.js +407 -0
  127. package/src/runtime/app-changelog.js +79 -0
  128. package/src/runtime/app-data-literals.js +82 -0
  129. package/src/runtime/app-platform.js +2752 -237
  130. package/src/runtime/app-registry-scaffolds.js +367 -0
  131. package/src/runtime/app-test-server.js +293 -0
  132. package/src/runtime/assets/store-screenshot-dark.png +0 -0
  133. package/src/runtime/auth-recovery.js +110 -0
  134. package/src/runtime/base-skills.d.ts +20 -0
  135. package/src/runtime/base-skills.js +167 -0
  136. package/src/runtime/channel.js +133 -0
  137. package/src/runtime/confined-space-build.js +74 -0
  138. package/src/runtime/confined-space-verify.js +49 -0
  139. package/src/runtime/delegated-context.js +68 -0
  140. package/src/runtime/errors.js +1 -0
  141. package/src/runtime/git.js +233 -0
  142. package/src/runtime/login-listener.js +15 -0
  143. package/src/runtime/native-record-files.js +47 -0
  144. package/src/runtime/oauth.js +2622 -0
  145. package/src/runtime/output.js +37 -5
  146. package/src/runtime/ports.js +31 -0
  147. package/src/runtime/profiles.js +906 -55
  148. package/src/runtime/retired-sdk-files.js +20 -0
  149. package/src/runtime/screenshot-framing.js +85 -0
  150. package/src/runtime/skill-sync/cloud-client.ts +121 -0
  151. package/src/runtime/skill-sync/index.ts +905 -0
  152. package/src/runtime/skill-sync/local-scanner.ts +1259 -0
  153. package/src/runtime/skill-sync/native-identity.ts +102 -0
  154. package/src/runtime/skill-sync/native-plan.ts +59 -0
  155. package/src/runtime/skill-sync/symlink-manager.ts +433 -0
  156. package/src/runtime/skill-sync/sync-plan.ts +54 -0
  157. package/src/runtime/skill-sync/types.ts +157 -0
  158. package/src/runtime/skill-sync/write-cloud-skill.ts +50 -0
  159. package/src/runtime/skill-sync-service.js +109 -0
  160. package/src/runtime/source-root.js +32 -0
  161. package/src/runtime/space-collection-scaffold.js +66 -0
  162. package/src/runtime/space-database-structures.js +229 -0
  163. package/src/runtime/space-fixture-broker.js +50 -0
  164. package/src/runtime/space-lock.js +337 -0
  165. package/src/runtime/space-platform.js +105 -0
  166. package/src/runtime/space-source.js +281 -0
  167. package/src/runtime/space-test-server.js +327 -0
  168. package/src/runtime/space-verification.js +89 -0
  169. package/src/runtime/space-verify-browser-worker.js +51 -0
  170. package/src/runtime/space-view-manifest.js +254 -0
  171. package/src/runtime/store-screenshot.js +146 -0
  172. package/src/runtime/sync-skills.d.ts +37 -0
  173. package/src/runtime/sync-skills.js +231 -0
  174. package/src/runtime/telemetry.js +92 -0
  175. package/src/runtime/transport.js +331 -45
  176. package/src/runtime/view-render.js +49 -0
  177. package/src/skill-sync-worker-entry.js +2 -0
  178. package/src/skill-sync-worker.js +50 -0
  179. package/src/space-harness-host.ts +103 -0
  180. package/template/.harness/index.html.tmpl +435 -0
  181. package/template/CHANGELOG.md +5 -0
  182. package/template/app/globals.css +29 -3
  183. package/template/app/layout.tsx +6 -3
  184. package/template/app/page.tsx +49 -42
  185. package/template/components/page-heading.tsx +23 -0
  186. package/template/components/ui/badge.tsx +7 -4
  187. package/template/components/ui/button.tsx +1 -1
  188. package/template/components/ui/card.tsx +24 -11
  189. package/template/components/ui/native-select.tsx +24 -0
  190. package/template/notis.config.ts +24 -6
  191. package/template/package-lock.json +3642 -0
  192. package/template/package.json +19 -16
  193. package/template/postcss.config.mjs +1 -1
  194. package/template/tailwind.config.ts +1 -6
  195. package/template/tsconfig.json +1 -0
  196. package/src/command-specs/db.js +0 -163
  197. package/src/runtime/app-preview-server.js +0 -312
  198. package/template/packages/notis-sdk/src/config.ts +0 -48
  199. package/template/packages/notis-sdk/src/helpers.ts +0 -131
  200. package/template/packages/notis-sdk/src/hooks/useAppState.ts +0 -50
  201. package/template/packages/notis-sdk/src/hooks/useCollectionItem.ts +0 -58
  202. package/template/packages/notis-sdk/src/hooks/useDatabase.ts +0 -87
  203. package/template/packages/notis-sdk/src/hooks/useDocument.ts +0 -61
  204. package/template/packages/notis-sdk/src/hooks/useNotis.ts +0 -31
  205. package/template/packages/notis-sdk/src/hooks/useNotisNavigation.ts +0 -49
  206. package/template/packages/notis-sdk/src/hooks/useTool.ts +0 -49
  207. package/template/packages/notis-sdk/src/hooks/useUpsertDocument.ts +0 -57
  208. package/template/packages/notis-sdk/src/index.ts +0 -47
  209. package/template/packages/notis-sdk/src/provider.tsx +0 -44
  210. package/template/packages/notis-sdk/src/runtime.ts +0 -159
  211. package/template/packages/notis-sdk/src/styles.css +0 -123
  212. package/template/packages/notis-sdk/src/vite.ts +0 -54
  213. package/template/packages/notis-sdk/tsconfig.json +0 -15
  214. /package/{template/packages/notis-sdk → dist/sdk}/src/hooks/useBackend.ts +0 -0
  215. /package/{template/packages/notis-sdk → dist/sdk}/src/hooks/useTools.ts +0 -0
  216. /package/{template/packages/notis-sdk → dist/sdk}/src/ui.ts +0 -0
@@ -0,0 +1,603 @@
1
+ import type { AgentContextContent, AgentContextItem, AgentContextSource } from './agentContext';
2
+ /**
3
+ * NotisRuntime is the bridge between app code running in the browser and the
4
+ * Notis platform. The portal owns the runtime and injects it through
5
+ * `NotisProvider` when the app is rendered.
6
+ *
7
+ * App code should never reach for globals. Use the hooks from `@notis/sdk`
8
+ * (useTool, useNotis, etc.) which read from the NotisProvider context.
9
+ */
10
+
11
+ import type { ComponentType, ReactNode } from 'react';
12
+ import type { NotisQueryClient } from './queryCache';
13
+ import type { SpaceRuntimeDescriptor, SpaceActionOptions, SpaceDocumentBodyRequest, SpaceDocumentBodyResult, SpaceViewerReadOperation, SpaceShownOptions, SpaceCloudComputerTransport } from './space';
14
+
15
+ // ---------------------------------------------------------------------------
16
+ // Database types
17
+ // ---------------------------------------------------------------------------
18
+
19
+ export type DatabasePropertyType =
20
+ | 'title'
21
+ | 'rich_text'
22
+ | 'text'
23
+ | 'number'
24
+ | 'checkbox'
25
+ | 'date'
26
+ | 'select'
27
+ | 'multi_select'
28
+ | 'status'
29
+ | 'relation'
30
+ | 'formula'
31
+ | 'files'
32
+ | 'secret';
33
+
34
+ /**
35
+ * The value of a `secret` property. The platform stores a pointer to a
36
+ * credential held elsewhere and never the credential itself, so there is
37
+ * deliberately nothing here to read the secret material from — only whether
38
+ * one is attached, which credential it is, and its lifecycle state.
39
+ */
40
+ export interface SecretPropertyValue {
41
+ present: boolean;
42
+ reference: string | null;
43
+ status: string | null;
44
+ metadata: Record<string, unknown> | null;
45
+ }
46
+
47
+ export interface DatabasePropertyOption {
48
+ id?: string | null;
49
+ name: string;
50
+ color?: string | null;
51
+ order?: number;
52
+ }
53
+
54
+ export interface DatabaseProperty {
55
+ id?: string | null;
56
+ name: string;
57
+ type: DatabasePropertyType;
58
+ description?: string | null;
59
+ options?: DatabasePropertyOption[];
60
+ }
61
+
62
+ export interface DatabaseDescriptor {
63
+ slug: string;
64
+ title: string;
65
+ description?: string | null;
66
+ icon?: string | null;
67
+ properties: DatabaseProperty[];
68
+ }
69
+
70
+ /**
71
+ * A document's content is typed. `markdown` documents carry rich text as
72
+ * BlockNote JSON (canonical) with a derived markdown projection; `file`
73
+ * documents carry an uploaded file whose format is in `fileType`
74
+ * (pdf, xlsx, pptx, ...). Future content types (canvas, ...) extend this
75
+ * union without changing the component contracts.
76
+ */
77
+ export type DocumentContentType = 'markdown' | 'file' | 'view';
78
+
79
+ export interface DocumentRecord {
80
+ id: string;
81
+ recordKey?: string;
82
+ revision?: number;
83
+ title: string;
84
+ properties: Record<string, unknown>;
85
+ url?: string | null;
86
+ icon?: string | null;
87
+ cover?: string | null;
88
+ databaseSlug?: string;
89
+ contentType?: DocumentContentType | null;
90
+ fileType?: string | null;
91
+ contentBlocknote?: Array<Record<string, unknown>> | null;
92
+ contentMarkdown?: string | null;
93
+ plainText?: string | null;
94
+ viewType?: string | null;
95
+ viewState?: Record<string, unknown> | null;
96
+ viewRevision?: number | null;
97
+ createdAt?: string | null;
98
+ lastEditedTime?: string | null;
99
+ }
100
+
101
+ // ---------------------------------------------------------------------------
102
+ // Tool types
103
+ // ---------------------------------------------------------------------------
104
+
105
+ export type ToolInputSchema = Record<string, unknown>;
106
+
107
+ export interface ToolDescriptor {
108
+ name: string;
109
+ description?: string;
110
+ inputSchema?: ToolInputSchema;
111
+ }
112
+
113
+ export interface ToolCallOptions {
114
+ /** Explicitly identifies an idempotent read; never set on a mutation. */
115
+ readOnly?: boolean;
116
+ /**
117
+ * Coalesce an identical in-flight call. Only opt in for idempotent reads;
118
+ * mutations must execute once per invocation.
119
+ */
120
+ dedupe?: boolean;
121
+ }
122
+
123
+ // ---------------------------------------------------------------------------
124
+ // Route types
125
+ // ---------------------------------------------------------------------------
126
+
127
+ export interface RouteDescriptor {
128
+ slug: string;
129
+ path: string;
130
+ name: string;
131
+ icon?: string | null;
132
+ parentSlug?: string | null;
133
+ default?: boolean;
134
+ resourceDeepLinks?: boolean;
135
+ collection?: {
136
+ database: string;
137
+ titleProperty: string;
138
+ parentProperty?: string | null;
139
+ sidebar?: {
140
+ mode: 'flat-list' | 'tree';
141
+ allowCreate: boolean;
142
+ } | null;
143
+ } | null;
144
+ }
145
+
146
+ export interface CollectionItem {
147
+ id: string;
148
+ title: string;
149
+ icon?: string | null;
150
+ }
151
+
152
+ export interface CollectionItemDetail extends CollectionItem {
153
+ properties: Record<string, unknown>;
154
+ }
155
+
156
+ // ---------------------------------------------------------------------------
157
+ // App descriptor
158
+ // ---------------------------------------------------------------------------
159
+
160
+ export interface AppDescriptor {
161
+ id: string;
162
+ name: string;
163
+ icon?: string | null;
164
+ description?: string | null;
165
+ }
166
+
167
+ export interface QueryFilter {
168
+ filters?: Array<{
169
+ property: string;
170
+ operator: string;
171
+ type?: string;
172
+ value: unknown;
173
+ }>;
174
+ sorts?: Array<{
175
+ property: string;
176
+ direction: 'asc' | 'desc';
177
+ }>;
178
+ page_size?: number;
179
+ }
180
+
181
+ export interface NotisRuntimeContext {
182
+ /** Host UI language. */
183
+ locale?: 'en' | 'fr';
184
+ /** Untrusted UI selection, separate from the host's fixed record authority. */
185
+ selection?: string | null;
186
+ /** Raw URL query values; `useViewParams()` keeps only the declared, valid ones. */
187
+ params?: Record<string, string> | null;
188
+ /** Trusted anonymous record-Site pin; no credentials or physical native target. */
189
+ siteRecord?: { recordKey: string; param: string; params: Record<string, string | number | boolean> } | null;
190
+ collectionItem?: CollectionItemDetail | null;
191
+ /** App-owned resource requested through the route's `?resource=<id>` link. */
192
+ resourceId?: string | null;
193
+ /**
194
+ * Set when the app is being rendered by the screenshot harness (`notis apps
195
+ * screenshot`) for the named listing scenario. Lets apps and SDK components
196
+ * hide dev-only chrome from listing images.
197
+ */
198
+ screenshotScenario?: string | null;
199
+ }
200
+
201
+ // ---------------------------------------------------------------------------
202
+ // App context shared with Notis
203
+ // ---------------------------------------------------------------------------
204
+
205
+ export type ContextAttributeValue = string | number | boolean | null;
206
+
207
+ /**
208
+ * The specific thing currently in focus inside an app view. The host stamps
209
+ * app/view provenance onto this value before it reaches chat, so apps only
210
+ * describe their own resource rather than impersonating another surface.
211
+ */
212
+ export interface ContextResource extends AgentContextContent {
213
+ additionalContext?: Record<string, unknown>;
214
+ id: string;
215
+ kind: string;
216
+ label: string;
217
+ url?: string | null;
218
+ revision?: string | null;
219
+ attributes?: Record<string, ContextAttributeValue>;
220
+ snapshot?: {
221
+ format: 'text' | 'markdown';
222
+ content: string;
223
+ } | null;
224
+ }
225
+
226
+ /** A quote copied from an app, kept separate from the user's prompt. */
227
+ export interface ContextSelection extends AgentContextContent {
228
+ source?: AgentContextSource;
229
+ id: string;
230
+ text: string;
231
+ resource?: ContextResource | null;
232
+ }
233
+
234
+ // ---------------------------------------------------------------------------
235
+ // Host-provided UI
236
+ // ---------------------------------------------------------------------------
237
+
238
+ /**
239
+ * Props for the host-provided document editor. The host implementation
240
+ * dispatches on the document's content type (markdown -> rich text editor,
241
+ * file -> matching viewer/editor), so this contract stays stable as new
242
+ * content types ship.
243
+ */
244
+ export interface NotisRecordProps {
245
+ /** Stable native record key, authorized through this Space's declared databases. */
246
+ recordKey: string;
247
+ className?: string;
248
+ }
249
+
250
+ export type NotisDocumentEditorProps = ({ recordKey: string; documentId?: never } | {
251
+ /** Legacy Apps only. Spaces use recordKey. */
252
+ documentId: string; recordKey?: never;
253
+ }) & {
254
+ /** 'full' renders icon/title/cover above the content; 'body' renders content only. */
255
+ variant?: 'full' | 'body';
256
+ /** Show the database properties above the body (default true). */
257
+ showProperties?: boolean;
258
+ readOnly?: boolean;
259
+ className?: string;
260
+ onDirtyChange?: (dirty: boolean) => void;
261
+ onSavingChange?: (saving: boolean) => void;
262
+ }
263
+
264
+ export interface NotisRecordPropertiesProps extends NotisRecordProps {
265
+ readOnly?: boolean;
266
+ onSavingChange?: (saving: boolean) => void;
267
+ }
268
+
269
+ /** Inline HTML is useful for declared Site read actions; recordKey loads a signed-in record. */
270
+ export type NotisHtmlFrameProps = ({ recordKey: string; html?: never } | { html: string; recordKey?: never }) & {
271
+ title?: string;
272
+ className?: string;
273
+ };
274
+ export interface NotisReportFrameProps extends NotisRecordProps {}
275
+ export interface NotisShareControlProps extends NotisRecordProps {}
276
+
277
+ /** One breadcrumb before the record title; the title is always the last crumb. */
278
+ export interface NotisDocumentPageCrumb {
279
+ label: string;
280
+ onSelect?: () => void;
281
+ }
282
+
283
+ /** An extra entry in the page's '...' menu, after the host's own entries. */
284
+ export interface NotisDocumentPageMenuItem {
285
+ label: string;
286
+ onSelect: () => void;
287
+ destructive?: boolean;
288
+ disabled?: boolean;
289
+ }
290
+
291
+ /**
292
+ * The host-bound parts of one document page. They share one editor session and one save queue,
293
+ * so a Space can arrange them (for example the properties in a right column) without a second editor.
294
+ */
295
+ export interface NotisDocumentPageParts {
296
+ /** Breadcrumb, Saving or Saved status, actions, Share and the '...' menu. */
297
+ Toolbar: ComponentType;
298
+ /** Cover, icon and title. */
299
+ Header: ComponentType;
300
+ /** Editable or Read only, type, database, created and updated, with the Configure panel toggle. */
301
+ Meta: ComponentType;
302
+ /** The record's properties, saved automatically with the title, icon and cover. */
303
+ Properties: ComponentType;
304
+ /** The collaborative body (or the matching viewer for files, HTML and reports). */
305
+ Body: ComponentType;
306
+ }
307
+
308
+ /**
309
+ * The full page for one record that is the main content of a Space view (a note, a document):
310
+ * the same page Beta's document page showed, inside the Space. Every edit (title, icon, cover,
311
+ * properties, body) goes through the host's single save queue and live collaboration.
312
+ */
313
+ export interface NotisDocumentPageProps extends NotisRecordProps {
314
+ /** Crumbs before the record title, usually a way back to the list. `false` hides the breadcrumb. */
315
+ breadcrumb?: NotisDocumentPageCrumb[] | false;
316
+ /** Extra toolbar buttons, before Share and the '...' menu (for example the Space's own Trash button). */
317
+ actions?: ReactNode;
318
+ /** Extra '...' menu entries (for example a destructive Delete, as Beta's page had). Plain toolbar buttons on hosts without DocumentPage. */
319
+ menuItems?: NotisDocumentPageMenuItem[];
320
+ /** Show the host Share control (a record Site). Off by default: only Spaces whose records were shared on Beta turn it on. */
321
+ share?: boolean;
322
+ /** Which header parts show. `false` hides the whole header (cover, icon and title). */
323
+ header?: false | { cover?: boolean; icon?: boolean; title?: boolean };
324
+ /** Show the meta strip (Editable or Read only, type, database, dates). Default true. */
325
+ meta?: boolean;
326
+ /** 'panel' (default): properties in the Configure panel under the meta strip. 'hidden': none. Or choose and order them by property name. */
327
+ properties?: 'panel' | 'hidden' | { include?: string[]; exclude?: string[]; order?: string[] };
328
+ /** Rendered between the properties and the body. */
329
+ aboveBody?: ReactNode;
330
+ /** Rendered under the body. */
331
+ belowBody?: ReactNode;
332
+ /** Column width: standard (900px, as Beta), wide (1200px) or full. */
333
+ width?: 'standard' | 'wide' | 'full';
334
+ readOnly?: boolean;
335
+ onDirtyChange?: (dirty: boolean) => void;
336
+ onSavingChange?: (saving: boolean) => void;
337
+ /**
338
+ * Called after a title, icon, cover, property or body save is confirmed, so the Space can refresh its lists.
339
+ * On hosts without DocumentPage it is called when a save finishes, with `title` null.
340
+ */
341
+ onSaved?: (record: { recordKey: string; title: string | null }) => void;
342
+ /**
343
+ * Rearrange the page. Receives the host-bound parts; the default layout is Toolbar, Header, Meta (with
344
+ * Properties in its panel), Body. With a layout, Meta shows only its strip and Properties shows wherever
345
+ * the layout places it (once), so the record's properties are never edited from two places.
346
+ * aboveBody and belowBody are not drawn: place them in the layout.
347
+ */
348
+ layout?: (parts: NotisDocumentPageParts) => ReactNode;
349
+ }
350
+
351
+ export interface NotisMarkdownEditorSavePayload {
352
+ markdown: string;
353
+ expectedRevision?: string | null;
354
+ }
355
+
356
+ export interface NotisMarkdownEditorSaveResult {
357
+ revision?: string | null;
358
+ }
359
+
360
+ /**
361
+ * Storage-neutral host markdown editor. The app owns persistence through
362
+ * `onSave`; the host only supplies Notis' editing experience.
363
+ */
364
+ export interface NotisMarkdownEditorProps {
365
+ /** Stable identity of the edited resource. Changing it starts a fresh editor. */
366
+ resourceKey?: string;
367
+ value: string;
368
+ revision?: string | null;
369
+ readOnly?: boolean;
370
+ autosaveMs?: number;
371
+ placeholder?: string;
372
+ className?: string;
373
+ onChange?: (markdown: string) => void;
374
+ /** Persist an uploaded media/file block and return its durable URL. */
375
+ onUploadFile?: (file: File) => Promise<string>;
376
+ onSave?: (
377
+ payload: NotisMarkdownEditorSavePayload,
378
+ ) => Promise<NotisMarkdownEditorSaveResult | void>;
379
+ onDirtyChange?: (dirty: boolean) => void;
380
+ onSavingChange?: (saving: boolean) => void;
381
+ }
382
+
383
+ /**
384
+ * Components the host (portal) injects through the runtime. Apps consume them
385
+ * via the SDK wrappers (e.g. `DocumentEditor`), which fall back gracefully
386
+ * when a host component is unavailable (standalone dev harness, snapshots).
387
+ */
388
+ export interface NotisRuntimeUI {
389
+ DocumentEditor?: ComponentType<NotisDocumentEditorProps>;
390
+ DocumentPage?: ComponentType<NotisDocumentPageProps>;
391
+ MarkdownEditor?: ComponentType<NotisMarkdownEditorProps>;
392
+ RecordProperties?: ComponentType<NotisRecordPropertiesProps>;
393
+ HtmlFrame?: ComponentType<NotisHtmlFrameProps>;
394
+ ReportFrame?: ComponentType<NotisReportFrameProps>;
395
+ ShareControl?: ComponentType<NotisShareControlProps>;
396
+ /** Starts reading a record (and the page's code) before it opens, for example when a list row is hovered. */
397
+ prefetchRecord?: (recordKey: string) => void;
398
+ }
399
+
400
+ // ---------------------------------------------------------------------------
401
+ // NotisRuntime
402
+ // ---------------------------------------------------------------------------
403
+
404
+ /**
405
+ * Options for `NotisRuntime.subscribeDatabase`.
406
+ */
407
+ export interface SubscribeDatabaseOptions {
408
+ /**
409
+ * Called with `true` once a live change feed is attached, and with `false`
410
+ * when it drops or is torn down. Hosts without a change feed (dev harness,
411
+ * screenshot stub, vite preview) never call it, so `live` stays false there.
412
+ */
413
+ onStatusChange?: (live: boolean) => void;
414
+ }
415
+
416
+ /**
417
+ * Work an app hands to the Notis manager chat through `NotisRuntime.handover`.
418
+ */
419
+ export interface HandoverPayload {
420
+ /** Optional starter message. Omit it to open a context-only composer. */
421
+ prompt?: string;
422
+ /**
423
+ * Alias of a Skill this Space links (`skills/<alias>/` in its source). The
424
+ * host rejects an alias the Space does not link. Omit to hand over plain work.
425
+ */
426
+ skill?: string;
427
+ /** Space-only selected row context; never overrides the host's access scope. */
428
+ record?: { binding: string; recordKey: string; readAction: string };
429
+ /**
430
+ * Submit on an active user gesture when the host supports immediate handover;
431
+ * background calls still open an editable draft.
432
+ */
433
+ autoSend?: boolean;
434
+ }
435
+
436
+ export interface HandoverResult {
437
+ /** `drafted` when the user still has to press send, `sent` when it went straight through. */
438
+ status: 'drafted' | 'sent';
439
+ }
440
+
441
+ /**
442
+ * The user's cloud computer, as far as an app may see it.
443
+ *
444
+ * `exists` is false when the user has never had a sandbox provisioned. A
445
+ * `status` of anything other than `'running'` means the VM is asleep; reading
446
+ * these facts never wakes it.
447
+ */
448
+ export interface CloudComputerSandboxFacts {
449
+ exists: boolean;
450
+ status: string | null;
451
+ provider: string | null;
452
+ created_at: string | null;
453
+ updated_at: string | null;
454
+ }
455
+
456
+ /**
457
+ * Whether a CLI inside the cloud computer is signed in.
458
+ *
459
+ * `authenticated: null` means *unknown*, never *signed out*: the sandbox was
460
+ * not running, or the probe could not answer. `reason` says which
461
+ * (`'sandbox_not_running'`, `'no_sandbox'`, `'sandbox_status_unknown'`,
462
+ * `'probe_failed'`, `'not_signed_in'`).
463
+ */
464
+ export interface CloudComputerCliAuthFacts {
465
+ authenticated: boolean | null;
466
+ account: string | null;
467
+ checked_at: string | null;
468
+ reason: string | null;
469
+ }
470
+
471
+ export interface CloudComputerFacts {
472
+ /**
473
+ * False when this host cannot answer at all — no cloud computer on the user's
474
+ * plan, or the platform could not resolve the facts. Render whatever the app
475
+ * did before rather than an error.
476
+ */
477
+ available: boolean;
478
+ reason?: string | null;
479
+ sandbox: CloudComputerSandboxFacts | null;
480
+ cli_auth: { gh: CloudComputerCliAuthFacts };
481
+ }
482
+
483
+ export interface RuntimeResource {
484
+ kind: 'app' | 'report' | 'space';
485
+ /** Host-provided adoption eligibility, never report-authored authority. */
486
+ analytics_eligible?: boolean;
487
+ /** Host-derived report family for adoption analytics, e.g. skill review reports. */
488
+ report_kind?: 'skill_review' | 'custom';
489
+ id: string;
490
+ revision: number;
491
+ name?: string;
492
+ icon?: string | null;
493
+ description?: string | null;
494
+ }
495
+
496
+ export interface NotisRuntime {
497
+ space?: SpaceRuntimeDescriptor;
498
+ callAction?<TResult = unknown>(actionId: string, inputs?: Record<string, unknown>, options?: SpaceActionOptions): Promise<TResult>;
499
+ documentBody?(request: SpaceDocumentBodyRequest): Promise<SpaceDocumentBodyResult>;
500
+ /**
501
+ * Space-only declared viewer read (`viewerReads`): what the signed-in viewer can open,
502
+ * with their own authority. Absent on Sites, anonymous links and older hosts.
503
+ */
504
+ viewerRead?<TResult = unknown>(operation: SpaceViewerReadOperation, input?: Record<string, unknown>): Promise<TResult>;
505
+ /**
506
+ * Space-only V4 list (`shows`): runs exactly the declared filter with these params as the
507
+ * signed-in Editor. Absent on Sites and older hosts.
508
+ */
509
+ shown?<TResult = unknown>(name: string, params?: Record<string, unknown>, options?: SpaceShownOptions): Promise<TResult>;
510
+ /** Space-only unsent Manager draft; distinct from legacy App activation. */
511
+ draftHandover?(payload: HandoverPayload): Promise<HandoverResult>;
512
+ /**
513
+ * Space-only cloud computer (`cloudComputer`): the signed-in viewer's own cloud computer after that
514
+ * viewer allows it. Absent on Sites, links, verification harnesses and older hosts.
515
+ */
516
+ spaceCloudComputer?: SpaceCloudComputerTransport;
517
+ /** Authenticated runtime identity; app below is presentation metadata only. */
518
+ resource?: RuntimeResource;
519
+ /** Optional host-scoped in-memory read cache. Older hosts remain supported. */
520
+ queryClient?: NotisQueryClient;
521
+ app: AppDescriptor;
522
+ route: RouteDescriptor;
523
+ databases: DatabaseDescriptor[];
524
+ context: NotisRuntimeContext;
525
+ ui?: NotisRuntimeUI;
526
+
527
+ /** Publish or clear the focused resource inside the current app view. */
528
+ contextSource?: AgentContextSource;
529
+ publishActiveResource?(resource: ContextResource | null): void;
530
+
531
+ /** Remember a copied quote so the host can recover it across iframe paste. */
532
+ captureContextSelection?(selection: ContextSelection): void;
533
+ addContext?(item: AgentContextItem): Promise<boolean>;
534
+ updateContext?(item: AgentContextItem): Promise<boolean>;
535
+ removeContext?(id: string): Promise<boolean>;
536
+
537
+ /**
538
+ * Subscribe to changes on an app-owned database. Returns an unsubscribe.
539
+ *
540
+ * The change notification is only a signal — it carries no rows. Consumers
541
+ * react by refetching through the normal tool path, so app scoping,
542
+ * permissions and billing are unchanged. Use the `useDatabaseSubscription`
543
+ * hook rather than calling this directly. In a Space, `slug` is the database
544
+ * binding alias and the hook is `useNativeDocuments(alias, { subscribe: true })`.
545
+ */
546
+ subscribeDatabase?(
547
+ slug: string,
548
+ onChange: () => void,
549
+ options?: SubscribeDatabaseOptions,
550
+ ): () => void;
551
+
552
+ /**
553
+ * Hand a piece of work to the Notis manager chat. The app cannot run an
554
+ * agent itself: it describes the job, and the manager surface owns progress,
555
+ * billing, cancellation and the transcript. Results come back to the app
556
+ * through its own databases (see `useDatabaseSubscription`).
557
+ *
558
+ * Use the `useHandover` hook rather than calling this directly. Hosts
559
+ * without a manager chat (the dev harness, the vite preview) leave it
560
+ * undefined, so keep whatever fallback the app already offers.
561
+ */
562
+ handover?(payload: HandoverPayload): Promise<HandoverResult>;
563
+
564
+ /**
565
+ * Read-only facts about the user's cloud computer. Requires
566
+ * `capabilities.cloudComputer: 'read'` in `notis.config.ts` plus the user's
567
+ * approval; resolving it never creates, resumes or commands a sandbox.
568
+ *
569
+ * Use the `useCloudComputer` hook rather than calling this directly. Hosts
570
+ * without a cloud computer (the dev harness, the vite preview) answer
571
+ * `{ available: false }`, so keep whatever fallback the app already has.
572
+ * `{ refresh: true }` bypasses the host's short answer cache — the hook's
573
+ * refresh() sends it so a just-completed sign-in becomes visible.
574
+ */
575
+ cloudComputerFacts?(options?: { refresh?: boolean }): Promise<CloudComputerFacts>;
576
+
577
+ navigate?: (payload: { kind: string; [key: string]: unknown }) => void | Promise<void>;
578
+
579
+ registerTopBarSearch?: (
580
+ config:
581
+ | {
582
+ onChange: (value: string) => void;
583
+ placeholder?: string;
584
+ onSubmit?: () => void | Promise<void>;
585
+ }
586
+ | null,
587
+ ) => void;
588
+ setTopBarSearchValue?: (value: string) => void;
589
+ setTopBarSearchLoading?: (loading: boolean) => void;
590
+
591
+ listTools(): Promise<ToolDescriptor[]>;
592
+ callTool<TResult = unknown>(
593
+ name: string,
594
+ args?: Record<string, unknown>,
595
+ options?: ToolCallOptions,
596
+ ): Promise<TResult>;
597
+
598
+ request(path: string, options?: {
599
+ method?: string;
600
+ headers?: Record<string, string>;
601
+ body?: unknown;
602
+ }): Promise<unknown>;
603
+ }