@notis_ai/cli 0.2.1 → 0.2.2

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 (66) hide show
  1. package/README.md +98 -163
  2. package/dist/scaffolds/notes/app/globals.css +3 -0
  3. package/dist/scaffolds/notes/app/layout.tsx +6 -0
  4. package/dist/scaffolds/notes/app/page.tsx +1465 -0
  5. package/dist/scaffolds/notes/components/ui/badge.tsx +28 -0
  6. package/dist/scaffolds/notes/components/ui/button.tsx +53 -0
  7. package/dist/scaffolds/notes/components/ui/card.tsx +56 -0
  8. package/dist/scaffolds/notes/components.json +20 -0
  9. package/dist/scaffolds/notes/lib/utils.ts +6 -0
  10. package/dist/scaffolds/notes/notis.config.ts +31 -0
  11. package/dist/scaffolds/notes/package.json +31 -0
  12. package/dist/scaffolds/notes/postcss.config.mjs +8 -0
  13. package/dist/scaffolds/notes/tailwind.config.ts +58 -0
  14. package/dist/scaffolds/notes/tsconfig.json +22 -0
  15. package/dist/scaffolds/notes/vite.config.ts +10 -0
  16. package/dist/scaffolds.json +13 -0
  17. package/package.json +7 -3
  18. package/skills/notis-apps/SKILL.md +162 -0
  19. package/skills/notis-apps/cli.md +208 -0
  20. package/skills/notis-cli/SKILL.md +258 -0
  21. package/skills/notis-query/cli.md +40 -0
  22. package/src/cli.js +1 -1
  23. package/src/command-specs/apps.js +211 -46
  24. package/src/command-specs/helpers.js +0 -60
  25. package/src/command-specs/index.js +0 -6
  26. package/src/command-specs/meta.js +7 -6
  27. package/src/command-specs/tools.js +1 -33
  28. package/src/runtime/app-dev-server.js +32 -4
  29. package/src/runtime/app-platform.js +404 -24
  30. package/src/runtime/profiles.js +2 -2
  31. package/src/runtime/transport.js +2 -2
  32. package/template/.harness/index.html.tmpl +1 -50
  33. package/template/app/page.tsx +41 -6
  34. package/template/metadata/cover.png +0 -0
  35. package/template/metadata/screenshot-1.png +0 -0
  36. package/template/metadata/screenshot-2.png +0 -0
  37. package/template/metadata/screenshot-3.png +0 -0
  38. package/template/notis.config.ts +10 -6
  39. package/template/package.json +2 -2
  40. package/template/packages/{notis-sdk → sdk}/package.json +6 -0
  41. package/template/packages/{notis-sdk → sdk}/src/components/MultiSelectActionBar.tsx +2 -1
  42. package/template/packages/{notis-sdk → sdk}/src/components/MultiSelectCheckbox.tsx +2 -2
  43. package/template/packages/{notis-sdk → sdk}/src/components/MultiSelectDragOverlay.tsx +2 -2
  44. package/template/packages/{notis-sdk → sdk}/src/config.ts +1 -1
  45. package/template/packages/{notis-sdk → sdk}/src/hooks/useDatabase.ts +1 -13
  46. package/template/packages/{notis-sdk → sdk}/src/hooks/useMultiSelect.ts +4 -3
  47. package/template/packages/{notis-sdk → sdk}/src/hooks/useNotis.ts +4 -3
  48. package/template/packages/{notis-sdk → sdk}/src/hooks/useNotisNavigation.ts +3 -3
  49. package/template/packages/{notis-sdk → sdk}/src/hooks/useTool.ts +22 -7
  50. package/template/packages/{notis-sdk → sdk}/src/hooks/useUpsertDocument.ts +0 -8
  51. package/template/packages/{notis-sdk → sdk}/src/index.ts +2 -15
  52. package/template/packages/{notis-sdk → sdk}/src/provider.tsx +1 -1
  53. package/template/packages/{notis-sdk → sdk}/src/runtime.ts +5 -26
  54. package/src/command-specs/auth.js +0 -178
  55. package/src/command-specs/db.js +0 -163
  56. package/template/packages/notis-sdk/src/helpers.ts +0 -131
  57. package/template/packages/notis-sdk/src/hooks/useAppState.ts +0 -50
  58. package/template/packages/notis-sdk/src/hooks/useCollectionItem.ts +0 -58
  59. package/template/packages/notis-sdk/src/hooks/useDocument.ts +0 -61
  60. /package/template/packages/{notis-sdk → sdk}/src/hooks/useBackend.ts +0 -0
  61. /package/template/packages/{notis-sdk → sdk}/src/hooks/useTools.ts +0 -0
  62. /package/template/packages/{notis-sdk → sdk}/src/hooks/useTopBarSearch.ts +0 -0
  63. /package/template/packages/{notis-sdk → sdk}/src/styles.css +0 -0
  64. /package/template/packages/{notis-sdk → sdk}/src/ui.ts +0 -0
  65. /package/template/packages/{notis-sdk → sdk}/src/vite.ts +0 -0
  66. /package/template/packages/{notis-sdk → sdk}/tsconfig.json +0 -0
@@ -1,12 +1,47 @@
1
1
  'use client';
2
2
 
3
- import { useNotis, useDatabase } from '@notis/sdk';
3
+ import { useEffect, useState } from 'react';
4
+ import { useNotis, useTool } from '@notis/sdk';
4
5
  import { Badge } from '@/components/ui/badge';
5
6
  import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card';
6
7
 
8
+ type ItemDocument = {
9
+ id?: string;
10
+ document_id?: string;
11
+ title?: string;
12
+ properties?: Record<string, unknown>;
13
+ };
14
+
15
+ type QueryItemsArgs = {
16
+ database_slug: string;
17
+ query: {
18
+ page_size?: number;
19
+ };
20
+ };
21
+
22
+ type QueryItemsResult = {
23
+ documents?: ItemDocument[];
24
+ };
25
+
7
26
  export default function HomePage() {
8
27
  const { app, ready } = useNotis();
9
- const { documents, loading } = useDatabase('items');
28
+ const queryItems = useTool<QueryItemsArgs, QueryItemsResult>('notis-default-query');
29
+ const [documents, setDocuments] = useState<ItemDocument[]>([]);
30
+
31
+ useEffect(() => {
32
+ let cancelled = false;
33
+ queryItems
34
+ .call({ database_slug: 'items', query: { page_size: 25 } })
35
+ .then((result) => {
36
+ if (!cancelled) setDocuments(result.documents || []);
37
+ })
38
+ .catch(() => {
39
+ if (!cancelled) setDocuments([]);
40
+ });
41
+ return () => {
42
+ cancelled = true;
43
+ };
44
+ }, [queryItems.call]);
10
45
 
11
46
  return (
12
47
  <main className="notis-app-shell space-y-6">
@@ -28,7 +63,7 @@ export default function HomePage() {
28
63
  <CardDescription>Use shadcn surfaces and portal tokens so the app feels native inside Notis.</CardDescription>
29
64
  </CardHeader>
30
65
  <CardContent>
31
- {loading ? (
66
+ {queryItems.loading ? (
32
67
  <p className="text-sm text-muted-foreground">Loading...</p>
33
68
  ) : documents.length === 0 ? (
34
69
  <div className="rounded-xl border border-dashed border-border px-4 py-10 text-center text-sm text-muted-foreground">
@@ -37,10 +72,10 @@ export default function HomePage() {
37
72
  ) : (
38
73
  <div className="space-y-3">
39
74
  {documents.map((doc) => (
40
- <div key={doc.id} className="rounded-xl border border-border bg-background px-4 py-3">
75
+ <div key={doc.id || doc.document_id || doc.title} className="rounded-xl border border-border bg-background px-4 py-3">
41
76
  <div className="flex items-center justify-between gap-3">
42
- <p className="font-medium">{doc.title}</p>
43
- {doc.properties.status ? (
77
+ <p className="font-medium">{doc.title || 'Untitled'}</p>
78
+ {doc.properties?.status ? (
44
79
  <Badge variant="outline">{String(doc.properties.status)}</Badge>
45
80
  ) : null}
46
81
  </div>
Binary file
@@ -1,14 +1,19 @@
1
1
  import { defineNotisApp } from '@notis/sdk/config';
2
2
 
3
3
  export default defineNotisApp({
4
- name: 'My Notis App',
5
- description: 'A new Notis app',
6
- icon: 'lucide:layout-dashboard',
4
+ name: 'my-notis-app',
5
+ title: 'My Notis App',
6
+ description: 'A focused Notis app with one route and one database-backed workflow.',
7
+ icon: 'phosphor:squares-four',
8
+ author: { name: 'Notis User' },
9
+ categories: ['Productivity'],
10
+ tagline: 'A clean starting point for a focused workflow.',
11
+ versionNotes: 'Initial release.',
7
12
 
8
13
  databases: ['items'],
9
14
 
10
15
  routes: [
11
- { path: '/', slug: 'home', name: 'Home', icon: 'lucide:home', default: true },
16
+ { path: '/', slug: 'home', name: 'Home', icon: 'phosphor:house', default: true },
12
17
  // Example collection tree route:
13
18
  // {
14
19
  // path: '/notes',
@@ -27,7 +32,6 @@ export default defineNotisApp({
27
32
  ],
28
33
 
29
34
  tools: [
30
- 'notis_query_database',
31
- 'notis_upsert_document',
35
+ 'notis-default-query',
32
36
  ],
33
37
  });
@@ -8,11 +8,11 @@
8
8
  "build": "vite build"
9
9
  },
10
10
  "dependencies": {
11
- "@notis/sdk": "file:./packages/notis-sdk",
11
+ "@notis/sdk": "file:./packages/sdk",
12
+ "@phosphor-icons/react": "^2.1.10",
12
13
  "@radix-ui/react-slot": "^1.1.0",
13
14
  "class-variance-authority": "^0.7.0",
14
15
  "clsx": "^2.1.1",
15
- "lucide-react": "^0.474.0",
16
16
  "react": "^19.0.0",
17
17
  "react-dom": "^19.0.0",
18
18
  "tailwind-merge": "^2.6.0",
@@ -14,6 +14,9 @@
14
14
  "src",
15
15
  "template"
16
16
  ],
17
+ "scripts": {
18
+ "type-check": "tsc --noEmit"
19
+ },
17
20
  "peerDependencies": {
18
21
  "react": ">=18.0.0",
19
22
  "react-dom": ">=18.0.0",
@@ -21,6 +24,9 @@
21
24
  "@vitejs/plugin-react": ">=4.0.0"
22
25
  },
23
26
  "devDependencies": {
27
+ "@types/node": "^20.0.0",
28
+ "@types/react": "^19.0.0",
29
+ "@types/react-dom": "^19.0.0",
24
30
  "typescript": "^5.0.0"
25
31
  }
26
32
  }
@@ -6,6 +6,7 @@ import {
6
6
  useRef,
7
7
  useState,
8
8
  type CSSProperties,
9
+ type ReactElement,
9
10
  type ReactNode,
10
11
  } from 'react';
11
12
 
@@ -174,7 +175,7 @@ export function MultiSelectActionBar({
174
175
  itemLabel,
175
176
  className,
176
177
  style,
177
- }: MultiSelectActionBarProps): JSX.Element | null {
178
+ }: MultiSelectActionBarProps): ReactElement | null {
178
179
  const actionsRef = useRef(actions);
179
180
  actionsRef.current = actions;
180
181
 
@@ -1,6 +1,6 @@
1
1
  'use client';
2
2
 
3
- import { type CSSProperties, type MouseEvent as ReactMouseEvent } from 'react';
3
+ import { type CSSProperties, type MouseEvent as ReactMouseEvent, type ReactElement } from 'react';
4
4
 
5
5
  export interface MultiSelectCheckboxProps {
6
6
  isSelected: boolean;
@@ -44,7 +44,7 @@ export function MultiSelectCheckbox({
44
44
  ariaLabel,
45
45
  className,
46
46
  style,
47
- }: MultiSelectCheckboxProps): JSX.Element {
47
+ }: MultiSelectCheckboxProps): ReactElement {
48
48
  const merged: CSSProperties = {
49
49
  ...baseStyle,
50
50
  ...(isSelected ? selectedStyle : null),
@@ -1,6 +1,6 @@
1
1
  'use client';
2
2
 
3
- import { type CSSProperties } from 'react';
3
+ import { type CSSProperties, type ReactElement } from 'react';
4
4
  import type { DragRect } from '../hooks/useMultiSelect';
5
5
 
6
6
  export interface MultiSelectDragOverlayProps {
@@ -22,7 +22,7 @@ export function MultiSelectDragOverlay({
22
22
  rect,
23
23
  className,
24
24
  style,
25
- }: MultiSelectDragOverlayProps): JSX.Element | null {
25
+ }: MultiSelectDragOverlayProps): ReactElement | null {
26
26
  if (!rect) return null;
27
27
  if (rect.width === 0 && rect.height === 0) return null;
28
28
 
@@ -9,7 +9,7 @@
9
9
  * export default defineNotisApp({
10
10
  * name: 'My App',
11
11
  * description: 'Does things',
12
- * icon: 'lucide:layout-dashboard',
12
+ * icon: 'phosphor:squares-four',
13
13
  * databases: ['tasks'],
14
14
  * routes: [
15
15
  * {
@@ -8,7 +8,6 @@ interface UseDatabaseOptions {
8
8
  filter?: QueryFilter;
9
9
  pageSize?: number;
10
10
  offset?: number;
11
- /** Set to false to skip the initial fetch. */
12
11
  enabled?: boolean;
13
12
  }
14
13
 
@@ -19,16 +18,6 @@ interface UseDatabaseResult {
19
18
  refetch: () => void;
20
19
  }
21
20
 
22
- /**
23
- * Query documents from a Notis database owned by this app.
24
- *
25
- * ```tsx
26
- * const { documents, loading } = useDatabase('transactions', {
27
- * filter: { sorts: [{ property: 'date', direction: 'desc' }] },
28
- * pageSize: 20,
29
- * });
30
- * ```
31
- */
32
21
  export function useDatabase(
33
22
  databaseSlug: string,
34
23
  options: UseDatabaseOptions = {},
@@ -43,7 +32,7 @@ export function useDatabase(
43
32
  const filterKey = JSON.stringify(options.filter ?? null);
44
33
 
45
34
  const refetch = useCallback(() => {
46
- setFetchKey((k) => k + 1);
35
+ setFetchKey((key) => key + 1);
47
36
  }, []);
48
37
 
49
38
  useEffect(() => {
@@ -81,7 +70,6 @@ export function useDatabase(
81
70
  return () => {
82
71
  cancelled = true;
83
72
  };
84
- // eslint-disable-next-line react-hooks/exhaustive-deps
85
73
  }, [runtime, databaseSlug, fetchKey, enabled, filterKey, options.offset, options.pageSize]);
86
74
 
87
75
  return { documents, loading, error, refetch };
@@ -149,7 +149,7 @@ export function useMultiSelect<T>(opts: UseMultiSelectOptions<T>): MultiSelectCo
149
149
 
150
150
  const select = useCallback((ids: string[]) => {
151
151
  setSelectedIds(new Set(ids));
152
- setLastClickedId(ids.length > 0 ? ids[ids.length - 1] : null);
152
+ setLastClickedId(ids.length > 0 ? ids[ids.length - 1] ?? null : null);
153
153
  }, []);
154
154
 
155
155
  const clear = useCallback(() => {
@@ -159,7 +159,7 @@ export function useMultiSelect<T>(opts: UseMultiSelectOptions<T>): MultiSelectCo
159
159
  const selectAll = useCallback(() => {
160
160
  const all = orderedIdsRef.current;
161
161
  setSelectedIds(new Set(all));
162
- setLastClickedId(all.length > 0 ? all[all.length - 1] : null);
162
+ setLastClickedId(all.length > 0 ? all[all.length - 1] ?? null : null);
163
163
  }, []);
164
164
 
165
165
  const selectRange = useCallback((anchorId: string, targetId: string) => {
@@ -346,7 +346,7 @@ export function useMultiSelect<T>(opts: UseMultiSelectOptions<T>): MultiSelectCo
346
346
  bottom: rect.top + rect.height,
347
347
  });
348
348
  setSelectedIds(new Set(ids));
349
- setLastClickedId(ids.length > 0 ? ids[ids.length - 1] : null);
349
+ setLastClickedId(ids.length > 0 ? ids[ids.length - 1] ?? null : null);
350
350
  };
351
351
 
352
352
  const handleMouseUp = () => {
@@ -447,6 +447,7 @@ export function useMultiSelect<T>(opts: UseMultiSelectOptions<T>): MultiSelectCo
447
447
  : Math.min(all.length - 1, Math.max(0, currentIdx + direction));
448
448
  if (newIdx === currentIdx) return;
449
449
  const newHead = all[newIdx];
450
+ if (!newHead) return;
450
451
  const anchorId = lastClickedIdRef.current ?? currentHead ?? newHead;
451
452
  const anchorIdx = all.indexOf(anchorId);
452
453
  if (anchorIdx === -1) {
@@ -1,7 +1,7 @@
1
1
  'use client';
2
2
 
3
3
  import { useNotisRuntime } from '../provider';
4
- import type { AppDescriptor, RouteDescriptor, DatabaseDescriptor, CollectionItemDetail } from '../runtime';
4
+ import type { AppDescriptor, CollectionItemDetail, DatabaseDescriptor, RouteDescriptor } from '../runtime';
5
5
 
6
6
  interface NotisContext {
7
7
  /** App metadata (id, name, icon, description). Null before runtime loads. */
@@ -17,8 +17,9 @@ interface NotisContext {
17
17
  }
18
18
 
19
19
  /**
20
- * Access app-level metadata: the app descriptor, current route, and declared
21
- * databases. Returns safe defaults when the portal runtime is not available.
20
+ * Access app-level metadata, the current route, declared databases, and the
21
+ * selected collection item. Returns safe defaults when the portal runtime is
22
+ * not available.
22
23
  */
23
24
  export function useNotis(): NotisContext {
24
25
  const runtime = useNotisRuntime();
@@ -7,7 +7,7 @@ interface NavigationActions {
7
7
  /** Navigate to a route within the app by its path. */
8
8
  toRoute: (path: string) => void;
9
9
  /** Navigate to a document detail view. */
10
- toDocument: (documentId: string) => void;
10
+ toDocument: (documentId: string, title?: string | null) => void;
11
11
  /** Navigate to the app's default route. */
12
12
  toApp: () => void;
13
13
  }
@@ -33,9 +33,9 @@ export function useNotisNavigation(): NavigationActions {
33
33
  }
34
34
  }, [runtime]);
35
35
 
36
- const toDocument = useCallback((documentId: string) => {
36
+ const toDocument = useCallback((documentId: string, title?: string | null) => {
37
37
  if (runtime?.navigate) {
38
- runtime.navigate({ kind: 'document', documentId });
38
+ runtime.navigate({ kind: 'document', documentId, title: title ?? undefined });
39
39
  }
40
40
  }, [runtime]);
41
41
 
@@ -3,27 +3,42 @@
3
3
  import { useCallback, useState } from 'react';
4
4
  import { useNotisRuntime } from '../provider';
5
5
 
6
- interface UseToolResult {
7
- call: (args?: Record<string, unknown>) => Promise<unknown>;
6
+ type ToolArguments = Record<string, unknown>;
7
+
8
+ type ToolCall<TArgs extends ToolArguments | undefined, TResult> = undefined extends TArgs
9
+ ? (args?: Exclude<TArgs, undefined>) => Promise<TResult>
10
+ : (args: TArgs) => Promise<TResult>;
11
+
12
+ export interface ToolCallState {
8
13
  loading: boolean;
9
14
  error: Error | null;
10
15
  }
11
16
 
17
+ export interface UseToolResult<
18
+ TArgs extends ToolArguments | undefined = ToolArguments | undefined,
19
+ TResult = unknown,
20
+ > extends ToolCallState {
21
+ call: ToolCall<TArgs, TResult>;
22
+ }
23
+
12
24
  /**
13
25
  * Call a specific Notis tool by name.
14
26
  *
15
27
  * ```tsx
16
- * const { call, loading } = useTool('notis_web_search');
28
+ * const { call, loading } = useTool('notis-default-web_search');
17
29
  * const result = await call({ query: 'latest news' });
18
30
  * ```
19
31
  */
20
- export function useTool(toolName: string): UseToolResult {
32
+ export function useTool<
33
+ TArgs extends ToolArguments | undefined = ToolArguments | undefined,
34
+ TResult = unknown,
35
+ >(toolName: string): UseToolResult<TArgs, TResult> {
21
36
  const runtime = useNotisRuntime();
22
37
  const [loading, setLoading] = useState(false);
23
38
  const [error, setError] = useState<Error | null>(null);
24
39
 
25
40
  const call = useCallback(
26
- async (args?: Record<string, unknown>): Promise<unknown> => {
41
+ async (args?: ToolArguments): Promise<TResult> => {
27
42
  if (!runtime) {
28
43
  throw new Error('Notis runtime not available. Ensure NotisProvider is mounted.');
29
44
  }
@@ -32,7 +47,7 @@ export function useTool(toolName: string): UseToolResult {
32
47
  setError(null);
33
48
 
34
49
  try {
35
- const result = await runtime.callTool(toolName, args);
50
+ const result = await runtime.callTool<TResult>(toolName, args);
36
51
  return result;
37
52
  } catch (err) {
38
53
  const e = err instanceof Error ? err : new Error(String(err));
@@ -43,7 +58,7 @@ export function useTool(toolName: string): UseToolResult {
43
58
  }
44
59
  },
45
60
  [runtime, toolName],
46
- );
61
+ ) as ToolCall<TArgs, TResult>;
47
62
 
48
63
  return { call, loading, error };
49
64
  }
@@ -18,14 +18,6 @@ interface UseUpsertDocumentResult {
18
18
  error: Error | null;
19
19
  }
20
20
 
21
- /**
22
- * Create or update a document in a Notis database.
23
- *
24
- * ```tsx
25
- * const { upsert, loading } = useUpsertDocument();
26
- * await upsert({ databaseSlug: 'tasks', title: 'New task', properties: { status: 'Open' } });
27
- * ```
28
- */
29
21
  export function useUpsertDocument(): UseUpsertDocumentResult {
30
22
  const runtime = useNotisRuntime();
31
23
  const [loading, setLoading] = useState(false);
@@ -12,15 +12,13 @@ export { NotisProvider, useNotisRuntime } from './provider';
12
12
  // Hooks
13
13
  export { useNotis } from './hooks/useNotis';
14
14
  export { useDatabase } from './hooks/useDatabase';
15
- export { useDocument } from './hooks/useDocument';
16
15
  export { useUpsertDocument } from './hooks/useUpsertDocument';
17
16
  export { useTool } from './hooks/useTool';
17
+ export type { ToolCallState, UseToolResult } from './hooks/useTool';
18
18
  export { useTools } from './hooks/useTools';
19
- export { useCollectionItems } from './hooks/useCollectionItem';
20
19
  export { useNotisNavigation } from './hooks/useNotisNavigation';
21
20
  export { useTopBarSearch } from './hooks/useTopBarSearch';
22
21
  export { useBackend } from './hooks/useBackend';
23
- export { useAppState } from './hooks/useAppState';
24
22
  export { useMultiSelect } from './hooks/useMultiSelect';
25
23
 
26
24
  // Multi-select components
@@ -39,18 +37,6 @@ export type {
39
37
  export type { MultiSelectCheckboxProps } from './components/MultiSelectCheckbox';
40
38
  export type { MultiSelectDragOverlayProps } from './components/MultiSelectDragOverlay';
41
39
 
42
- // Property extraction helpers
43
- export {
44
- extractText,
45
- extractSelect,
46
- extractDate,
47
- extractNumber,
48
- extractCheckbox,
49
- extractMultiSelect,
50
- extractRelation,
51
- docTitle,
52
- } from './helpers';
53
-
54
40
  // Types (re-exported for convenience)
55
41
  export type {
56
42
  AppDescriptor,
@@ -64,4 +50,5 @@ export type {
64
50
  QueryFilter,
65
51
  RouteDescriptor,
66
52
  ToolDescriptor,
53
+ ToolInputSchema,
67
54
  } from './runtime';
@@ -36,7 +36,7 @@ export function NotisProvider({ children, runtime }: { children: ReactNode; runt
36
36
 
37
37
  /**
38
38
  * Returns the raw NotisRuntime or null if not yet available.
39
- * Prefer the typed hooks (useDatabase, useTool, etc.) over this.
39
+ * Prefer the typed hooks (useTool, useNotis, etc.) over this.
40
40
  */
41
41
  export function useNotisRuntime(): NotisRuntime | null {
42
42
  return useContext(NotisContext);
@@ -4,7 +4,7 @@
4
4
  * `NotisProvider` when the app is rendered.
5
5
  *
6
6
  * App code should never reach for globals. Use the hooks from `@notis/sdk`
7
- * (useDatabase, useTool, etc.) which read from the NotisProvider context.
7
+ * (useTool, useNotis, etc.) which read from the NotisProvider context.
8
8
  */
9
9
 
10
10
  // ---------------------------------------------------------------------------
@@ -44,10 +44,12 @@ export interface DocumentRecord {
44
44
  // Tool types
45
45
  // ---------------------------------------------------------------------------
46
46
 
47
+ export type ToolInputSchema = Record<string, unknown>;
48
+
47
49
  export interface ToolDescriptor {
48
50
  name: string;
49
51
  description?: string;
50
- input_schema?: Record<string, unknown>;
52
+ inputSchema?: ToolInputSchema;
51
53
  }
52
54
 
53
55
  // ---------------------------------------------------------------------------
@@ -82,11 +84,6 @@ export interface CollectionItemDetail extends CollectionItem {
82
84
  properties: Record<string, unknown>;
83
85
  }
84
86
 
85
- export interface CollectionTreeItem extends CollectionItem {
86
- parent_id: string | null;
87
- has_children: boolean;
88
- }
89
-
90
87
  // ---------------------------------------------------------------------------
91
88
  // App descriptor
92
89
  // ---------------------------------------------------------------------------
@@ -98,10 +95,6 @@ export interface AppDescriptor {
98
95
  description?: string | null;
99
96
  }
100
97
 
101
- // ---------------------------------------------------------------------------
102
- // Query types
103
- // ---------------------------------------------------------------------------
104
-
105
98
  export interface QueryFilter {
106
99
  filters?: Array<{
107
100
  property: string;
@@ -144,7 +137,7 @@ export interface NotisRuntime {
144
137
  setTopBarSearchLoading?: (loading: boolean) => void;
145
138
 
146
139
  listTools(): Promise<ToolDescriptor[]>;
147
- callTool(name: string, args?: Record<string, unknown>): Promise<unknown>;
140
+ callTool<TResult = unknown>(name: string, args?: Record<string, unknown>): Promise<TResult>;
148
141
 
149
142
  queryDatabase(args: {
150
143
  databaseSlug: string;
@@ -152,10 +145,6 @@ export interface NotisRuntime {
152
145
  offset?: number;
153
146
  }): Promise<{ documents: DocumentRecord[] }>;
154
147
 
155
- getDocument(args: {
156
- documentId: string;
157
- }): Promise<DocumentRecord>;
158
-
159
148
  upsertDocument(args: {
160
149
  databaseSlug: string;
161
150
  documentId?: string;
@@ -164,16 +153,6 @@ export interface NotisRuntime {
164
153
  contentBlocknote?: Array<Record<string, unknown>> | null;
165
154
  }): Promise<{ status: string; document: DocumentRecord }>;
166
155
 
167
- listCollectionItems(args?: {
168
- databaseSlug?: string;
169
- pageSize?: number;
170
- }): Promise<{ items: CollectionItem[] }>;
171
-
172
- listCollectionTree?(args?: {
173
- databaseSlug?: string;
174
- pageSize?: number;
175
- }): Promise<{ items: CollectionTreeItem[] }>;
176
-
177
156
  request(path: string, options?: {
178
157
  method?: string;
179
158
  headers?: Record<string, string>;