@palettelab/sdk 0.1.7 → 0.1.9

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 CHANGED
@@ -12,12 +12,116 @@ npm install @palettelab/sdk react react-dom
12
12
 
13
13
  `react` and `react-dom` are peer dependencies. Plugin bundles should externalize React and `@palettelab/sdk`; the Palette CLI handles this for standard templates.
14
14
 
15
+ ## Recommended Developer Flow
16
+
17
+ Create apps with the Palette CLI and use this SDK from the generated frontend.
18
+
19
+ ```bash
20
+ npx --yes @palettelab/cli@latest init simple-todo --template database
21
+ cd simple-todo
22
+ npm install
23
+ npx --yes @palettelab/cli@latest dev
24
+ ```
25
+
26
+ `pltt dev` starts the local SDK simulator. It provides mock platform context,
27
+ authenticated API helpers, local backend routing, and a local database when the
28
+ app declares database support. This is the fastest loop for building UI,
29
+ calling backend routes, and checking SDK behavior.
30
+
31
+ For real Palette OS testing without Docker, configure a hosted sandbox and run:
32
+
33
+ ```bash
34
+ npx --yes @palettelab/cli@latest login \
35
+ --env staging \
36
+ --url https://YOUR-PALETTE-STAGING-URL \
37
+ --token pltt_xxxxx
38
+
39
+ npx --yes @palettelab/cli@latest dev --sandbox --env staging
40
+ ```
41
+
42
+ The hosted sandbox publishes a preview into the configured Palette environment
43
+ and returns an OS preview URL. Use that URL when the app must be tested with
44
+ real login context, organization context, Data Room APIs, storage, install
45
+ state, review/publish state, logs, permissions, and platform APIs.
46
+
47
+ ## Staging URL And Token
48
+
49
+ The staging URL is the base URL of the Palette backend/API environment used by
50
+ the CLI. It must serve backend API paths such as:
51
+
52
+ ```text
53
+ /api/v1/health
54
+ /api/v1/appstore/sign-upload
55
+ /api/v1/appstore/publish
56
+ /api/v1/developer/publish-tokens
57
+ ```
58
+
59
+ Validate it before configuring the CLI:
60
+
61
+ ```bash
62
+ curl https://YOUR-PALETTE-STAGING-URL/api/v1/health
63
+ ```
64
+
65
+ If this returns backend health JSON, the URL is correct. If it returns the
66
+ frontend app HTML, use the backend domain instead or configure your reverse
67
+ proxy so `/api/v1/*` and `/api/superadmin/*` are routed to the backend.
68
+
69
+ Publish tokens start with `pltt_`. Developers can create one after logging in:
70
+
71
+ 1. Open Palette OS.
72
+ 2. Open Settings.
73
+ 3. Open Developer.
74
+ 4. Create a developer publish token.
75
+ 5. Copy it immediately. The raw token is shown only once.
76
+
77
+ Then save it locally:
78
+
79
+ ```bash
80
+ npx --yes @palettelab/cli@latest login \
81
+ --env staging \
82
+ --url https://YOUR-PALETTE-STAGING-URL \
83
+ --token pltt_xxxxx
84
+ ```
85
+
86
+ The CLI stores this in `~/.palette/config.json` with restricted file
87
+ permissions. You can also use environment variables:
88
+
89
+ ```bash
90
+ export PALETTE_STAGING_URL=https://YOUR-PALETTE-STAGING-URL
91
+ export PALETTE_STAGING_TOKEN=pltt_xxxxx
92
+ ```
93
+
94
+ ## Local Simulator Versus Hosted OS
95
+
96
+ Use the local simulator for everyday development:
97
+
98
+ ```bash
99
+ npx --yes @palettelab/cli@latest dev
100
+ ```
101
+
102
+ Use hosted sandbox for full OS behavior:
103
+
104
+ ```bash
105
+ npx --yes @palettelab/cli@latest dev --sandbox --env staging
106
+ ```
107
+
108
+ For internal sandbox environments where manual approval should not block app
109
+ testing, run the Palette backend with:
110
+
111
+ ```bash
112
+ APPSTORE_AUTO_APPROVE_SANDBOX_PREVIEWS=true
113
+ ```
114
+
115
+ When enabled, passing sandbox preview publishes become active automatically, so
116
+ the developer can immediately test the app inside the OS preview URL.
117
+
15
118
  ## Exports
16
119
 
17
120
  ```ts
18
121
  import {
19
122
  PluginProvider,
20
123
  usePlatform,
124
+ createPaletteClient,
21
125
  usePluginTasks,
22
126
  usePluginDataRooms,
23
127
  usePluginChat,
@@ -65,6 +169,53 @@ export default function PluginRoot(props: PluginComponentProps) {
65
169
  }
66
170
  ```
67
171
 
172
+ ## Palette Client
173
+
174
+ Use `createPaletteClient()` when an app needs common Palette OS services without
175
+ remembering raw API routes.
176
+
177
+ ```tsx
178
+ import { createPaletteClient, usePlatform } from "@palettelab/sdk"
179
+
180
+ function App() {
181
+ const platform = usePlatform()
182
+ const palette = createPaletteClient(platform)
183
+
184
+ async function upload(file: File) {
185
+ const rooms = await palette.dataRooms.list()
186
+ await palette.dataRooms.uploadFile(rooms[0].id, file)
187
+ palette.toast.success("Uploaded")
188
+ }
189
+
190
+ return <button onClick={() => palette.user.current()}>Load profile</button>
191
+ }
192
+ ```
193
+
194
+ Included clients:
195
+
196
+ - `palette.user.current()` and `palette.user.updateProfile()`
197
+ - `palette.organization.currentId()`, `currentRole()`, and `listMine()`
198
+ - `palette.dataRooms.list()`, `create()`, `get()`, `folder()`, and `uploadFile()`
199
+ - `palette.config.get()` and `palette.config.update(values)`, with optional plugin ID override
200
+ - `palette.permissions.has()`, `hasAny()`, and `hasAll()`
201
+ - `palette.storage.uploadToSignedUrl()`
202
+ - `palette.toast.success()`, `error()`, and `info()`
203
+
204
+ These helpers are intentionally thin wrappers over platform APIs. Apps can still
205
+ use `apiFetch()` directly for custom backend routes.
206
+
207
+ ## Permissions
208
+
209
+ Use permission helpers to keep UI actions aligned with backend permission gates.
210
+
211
+ ```tsx
212
+ const palette = createPaletteClient(usePlatform())
213
+ const canWrite = palette.permissions.has("resources:write")
214
+ ```
215
+
216
+ Backend routes should still enforce permissions with the Python SDK. Frontend
217
+ permission checks are for UX only.
218
+
68
219
  ## API Helpers
69
220
 
70
221
  Use `apiFetch` for authenticated platform API calls. It includes credentials and performs the platform refresh flow for normal portal runtime.
@@ -1,6 +1,6 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import react__default from 'react';
3
- import { P as PlatformContext } from '../plugin-DzSTKgkz.mjs';
3
+ import { P as PlatformContext } from '../plugin-o-qmdCBl.mjs';
4
4
 
5
5
  /**
6
6
  * Provider that wraps plugin components with the platform context.
@@ -1,6 +1,6 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import react__default from 'react';
3
- import { P as PlatformContext } from '../plugin-DzSTKgkz.js';
3
+ import { P as PlatformContext } from '../plugin-o-qmdCBl.js';
4
4
 
5
5
  /**
6
6
  * Provider that wraps plugin components with the platform context.
@@ -122,4 +122,4 @@ interface DataRoomFile {
122
122
  updated_at: string;
123
123
  }
124
124
 
125
- export type { ChatAttachment as C, DataRoom as D, Task as T, ChatMessage as a, ChatThread as b, DataRoomFile as c, DataRoomFolder as d, DataRoomPermission as e, TaskAgentSnippet as f, TaskCreatePayload as g, TaskPriority as h, TaskStats as i, TaskStatus as j, TaskType as k, TaskUpdatePayload as l };
125
+ export type { ChatAttachment as C, DataRoom as D, Task as T, DataRoomFolder as a, DataRoomFile as b, ChatMessage as c, ChatThread as d, DataRoomPermission as e, TaskAgentSnippet as f, TaskCreatePayload as g, TaskPriority as h, TaskStats as i, TaskStatus as j, TaskType as k, TaskUpdatePayload as l };
@@ -122,4 +122,4 @@ interface DataRoomFile {
122
122
  updated_at: string;
123
123
  }
124
124
 
125
- export type { ChatAttachment as C, DataRoom as D, Task as T, ChatMessage as a, ChatThread as b, DataRoomFile as c, DataRoomFolder as d, DataRoomPermission as e, TaskAgentSnippet as f, TaskCreatePayload as g, TaskPriority as h, TaskStats as i, TaskStatus as j, TaskType as k, TaskUpdatePayload as l };
125
+ export type { ChatAttachment as C, DataRoom as D, Task as T, DataRoomFolder as a, DataRoomFile as b, ChatMessage as c, ChatThread as d, DataRoomPermission as e, TaskAgentSnippet as f, TaskCreatePayload as g, TaskPriority as h, TaskStats as i, TaskStatus as j, TaskType as k, TaskUpdatePayload as l };
@@ -1,6 +1,6 @@
1
1
  import * as react from 'react';
2
- import { P as PlatformContext } from '../plugin-DzSTKgkz.mjs';
3
- import { T as Task, i as TaskStats, g as TaskCreatePayload, l as TaskUpdatePayload, D as DataRoom, d as DataRoomFolder, c as DataRoomFile, b as ChatThread, a as ChatMessage } from '../data-room-BP0PjYoe.mjs';
2
+ import { P as PlatformContext } from '../plugin-o-qmdCBl.mjs';
3
+ import { T as Task, i as TaskStats, g as TaskCreatePayload, l as TaskUpdatePayload, D as DataRoom, a as DataRoomFolder, b as DataRoomFile, d as ChatThread, c as ChatMessage } from '../data-room-Dtd9LLHf.mjs';
4
4
 
5
5
  /**
6
6
  * React context for platform services.
@@ -1,6 +1,6 @@
1
1
  import * as react from 'react';
2
- import { P as PlatformContext } from '../plugin-DzSTKgkz.js';
3
- import { T as Task, i as TaskStats, g as TaskCreatePayload, l as TaskUpdatePayload, D as DataRoom, d as DataRoomFolder, c as DataRoomFile, b as ChatThread, a as ChatMessage } from '../data-room-BP0PjYoe.js';
2
+ import { P as PlatformContext } from '../plugin-o-qmdCBl.js';
3
+ import { T as Task, i as TaskStats, g as TaskCreatePayload, l as TaskUpdatePayload, D as DataRoom, a as DataRoomFolder, b as DataRoomFile, d as ChatThread, c as ChatMessage } from '../data-room-Dtd9LLHf.js';
4
4
 
5
5
  /**
6
6
  * React context for platform services.
package/dist/index.d.mts CHANGED
@@ -1,6 +1,7 @@
1
- import { P as PlatformContext } from './plugin-DzSTKgkz.mjs';
2
- export { A as Agent, a as AgentConfig, b as AppCategory, c as AuthContextValue, O as OrgSummary, d as PluginAgentDefinition, e as PluginComponentProps, f as PluginManifest, g as PluginToolDefinition, U as User } from './plugin-DzSTKgkz.mjs';
3
- export { C as ChatAttachment, a as ChatMessage, b as ChatThread, D as DataRoom, c as DataRoomFile, d as DataRoomFolder, e as DataRoomPermission, T as Task, f as TaskAgentSnippet, g as TaskCreatePayload, h as TaskPriority, i as TaskStats, j as TaskStatus, k as TaskType, l as TaskUpdatePayload } from './data-room-BP0PjYoe.mjs';
1
+ import { P as PlatformContext, O as OrgSummary, U as User } from './plugin-o-qmdCBl.mjs';
2
+ export { A as Agent, a as AgentConfig, b as AppCategory, c as AuthContextValue, d as PluginAgentDefinition, e as PluginComponentProps, f as PluginManifest, g as PluginToolDefinition } from './plugin-o-qmdCBl.mjs';
3
+ import { D as DataRoom, a as DataRoomFolder, b as DataRoomFile } from './data-room-Dtd9LLHf.mjs';
4
+ export { C as ChatAttachment, c as ChatMessage, d as ChatThread, e as DataRoomPermission, T as Task, f as TaskAgentSnippet, g as TaskCreatePayload, h as TaskPriority, i as TaskStats, j as TaskStatus, k as TaskType, l as TaskUpdatePayload } from './data-room-Dtd9LLHf.mjs';
4
5
  export { AgentResource, ResourcesByGroup } from './types/index.mjs';
5
6
  import { ReactElement } from 'react';
6
7
  export { PlatformCtx, usePlatform, usePluginChat, usePluginDataRooms, usePluginTasks } from './hooks/index.mjs';
@@ -53,4 +54,81 @@ declare function updateInstallConfig(pluginId: string, config: InstallConfig): P
53
54
  declare function createMockPlatformContext(overrides?: Partial<PlatformContext>): PlatformContext;
54
55
  declare function withPluginProvider(element: ReactElement, platform?: Partial<PlatformContext>): ReactElement;
55
56
 
56
- export { type InstallConfig, PaletteApiError, PlatformContext, type SandboxBridge, apiFetch, apiUpload, createMockPlatformContext, createSandboxBridge, errorFromResponse, getBaseUrl, getInstallConfig, isPaletteApiError, isSandboxRuntime, setBaseUrl, updateInstallConfig, withPluginProvider };
57
+ interface DataRoomContents {
58
+ room?: DataRoom;
59
+ folders: DataRoomFolder[];
60
+ files: DataRoomFile[];
61
+ }
62
+ interface DataRoomUploadOptions {
63
+ folderId?: number | null;
64
+ contentType?: string;
65
+ }
66
+ declare class DataRoomClient {
67
+ list(): Promise<DataRoom[]>;
68
+ create(input: {
69
+ name: string;
70
+ description?: string | null;
71
+ }): Promise<DataRoom>;
72
+ get(roomId: number): Promise<DataRoomContents>;
73
+ folder(roomId: number, folderId: number): Promise<DataRoomContents>;
74
+ requestUpload(roomId: number, file: File, options?: DataRoomUploadOptions): Promise<{
75
+ upload_url: string;
76
+ blob_path: string;
77
+ file_url: string;
78
+ }>;
79
+ confirmUpload(roomId: number, file: File, upload: {
80
+ blob_path: string;
81
+ }, options?: DataRoomUploadOptions): Promise<DataRoomFile>;
82
+ uploadFile(roomId: number, file: File, options?: DataRoomUploadOptions): Promise<DataRoomFile>;
83
+ }
84
+ declare const dataRooms: DataRoomClient;
85
+
86
+ declare function uploadToSignedUrl(uploadUrl: string, file: Blob, contentType?: string): Promise<void>;
87
+ declare class StorageClient {
88
+ uploadToSignedUrl: typeof uploadToSignedUrl;
89
+ }
90
+
91
+ declare class UserClient {
92
+ private readonly ctx?;
93
+ constructor(ctx?: PlatformContext | undefined);
94
+ current(): Promise<User>;
95
+ updateProfile(input: {
96
+ name?: string;
97
+ company_name?: string | null;
98
+ }): Promise<User>;
99
+ }
100
+ declare class OrganizationClient {
101
+ private readonly ctx?;
102
+ constructor(ctx?: PlatformContext | undefined);
103
+ currentId(): number | null;
104
+ currentRole(): string | null;
105
+ listMine(): Promise<OrgSummary[]>;
106
+ }
107
+
108
+ declare function createPaletteClient(ctx?: PlatformContext): {
109
+ user: UserClient;
110
+ organization: OrganizationClient;
111
+ dataRooms: DataRoomClient;
112
+ storage: StorageClient;
113
+ config: {
114
+ get: (pluginId?: string) => Promise<InstallConfig>;
115
+ update: (values: Record<string, unknown>, pluginId?: string) => Promise<InstallConfig>;
116
+ };
117
+ permissions: {
118
+ has: (permission: string) => boolean;
119
+ hasAny: (permissions: string[]) => boolean;
120
+ hasAll: (permissions: string[]) => boolean;
121
+ };
122
+ toast: {
123
+ success: (message: string) => void | undefined;
124
+ error: (message: string) => void | undefined;
125
+ info: (message: string) => void | undefined;
126
+ };
127
+ };
128
+ type PaletteClient = ReturnType<typeof createPaletteClient>;
129
+
130
+ declare function hasPermission(ctx: PlatformContext, permission: string): boolean;
131
+ declare function hasAnyPermission(ctx: PlatformContext, permissions: string[]): boolean;
132
+ declare function hasAllPermissions(ctx: PlatformContext, permissions: string[]): boolean;
133
+
134
+ export { DataRoom, DataRoomClient, type DataRoomContents, DataRoomFile, DataRoomFolder, type DataRoomUploadOptions, type InstallConfig, OrgSummary, OrganizationClient, PaletteApiError, type PaletteClient, PlatformContext, type SandboxBridge, StorageClient, User, UserClient, apiFetch, apiUpload, createMockPlatformContext, createPaletteClient, createSandboxBridge, dataRooms, errorFromResponse, getBaseUrl, getInstallConfig, hasAllPermissions, hasAnyPermission, hasPermission, isPaletteApiError, isSandboxRuntime, setBaseUrl, updateInstallConfig, uploadToSignedUrl, withPluginProvider };
package/dist/index.d.ts CHANGED
@@ -1,6 +1,7 @@
1
- import { P as PlatformContext } from './plugin-DzSTKgkz.js';
2
- export { A as Agent, a as AgentConfig, b as AppCategory, c as AuthContextValue, O as OrgSummary, d as PluginAgentDefinition, e as PluginComponentProps, f as PluginManifest, g as PluginToolDefinition, U as User } from './plugin-DzSTKgkz.js';
3
- export { C as ChatAttachment, a as ChatMessage, b as ChatThread, D as DataRoom, c as DataRoomFile, d as DataRoomFolder, e as DataRoomPermission, T as Task, f as TaskAgentSnippet, g as TaskCreatePayload, h as TaskPriority, i as TaskStats, j as TaskStatus, k as TaskType, l as TaskUpdatePayload } from './data-room-BP0PjYoe.js';
1
+ import { P as PlatformContext, O as OrgSummary, U as User } from './plugin-o-qmdCBl.js';
2
+ export { A as Agent, a as AgentConfig, b as AppCategory, c as AuthContextValue, d as PluginAgentDefinition, e as PluginComponentProps, f as PluginManifest, g as PluginToolDefinition } from './plugin-o-qmdCBl.js';
3
+ import { D as DataRoom, a as DataRoomFolder, b as DataRoomFile } from './data-room-Dtd9LLHf.js';
4
+ export { C as ChatAttachment, c as ChatMessage, d as ChatThread, e as DataRoomPermission, T as Task, f as TaskAgentSnippet, g as TaskCreatePayload, h as TaskPriority, i as TaskStats, j as TaskStatus, k as TaskType, l as TaskUpdatePayload } from './data-room-Dtd9LLHf.js';
4
5
  export { AgentResource, ResourcesByGroup } from './types/index.js';
5
6
  import { ReactElement } from 'react';
6
7
  export { PlatformCtx, usePlatform, usePluginChat, usePluginDataRooms, usePluginTasks } from './hooks/index.js';
@@ -53,4 +54,81 @@ declare function updateInstallConfig(pluginId: string, config: InstallConfig): P
53
54
  declare function createMockPlatformContext(overrides?: Partial<PlatformContext>): PlatformContext;
54
55
  declare function withPluginProvider(element: ReactElement, platform?: Partial<PlatformContext>): ReactElement;
55
56
 
56
- export { type InstallConfig, PaletteApiError, PlatformContext, type SandboxBridge, apiFetch, apiUpload, createMockPlatformContext, createSandboxBridge, errorFromResponse, getBaseUrl, getInstallConfig, isPaletteApiError, isSandboxRuntime, setBaseUrl, updateInstallConfig, withPluginProvider };
57
+ interface DataRoomContents {
58
+ room?: DataRoom;
59
+ folders: DataRoomFolder[];
60
+ files: DataRoomFile[];
61
+ }
62
+ interface DataRoomUploadOptions {
63
+ folderId?: number | null;
64
+ contentType?: string;
65
+ }
66
+ declare class DataRoomClient {
67
+ list(): Promise<DataRoom[]>;
68
+ create(input: {
69
+ name: string;
70
+ description?: string | null;
71
+ }): Promise<DataRoom>;
72
+ get(roomId: number): Promise<DataRoomContents>;
73
+ folder(roomId: number, folderId: number): Promise<DataRoomContents>;
74
+ requestUpload(roomId: number, file: File, options?: DataRoomUploadOptions): Promise<{
75
+ upload_url: string;
76
+ blob_path: string;
77
+ file_url: string;
78
+ }>;
79
+ confirmUpload(roomId: number, file: File, upload: {
80
+ blob_path: string;
81
+ }, options?: DataRoomUploadOptions): Promise<DataRoomFile>;
82
+ uploadFile(roomId: number, file: File, options?: DataRoomUploadOptions): Promise<DataRoomFile>;
83
+ }
84
+ declare const dataRooms: DataRoomClient;
85
+
86
+ declare function uploadToSignedUrl(uploadUrl: string, file: Blob, contentType?: string): Promise<void>;
87
+ declare class StorageClient {
88
+ uploadToSignedUrl: typeof uploadToSignedUrl;
89
+ }
90
+
91
+ declare class UserClient {
92
+ private readonly ctx?;
93
+ constructor(ctx?: PlatformContext | undefined);
94
+ current(): Promise<User>;
95
+ updateProfile(input: {
96
+ name?: string;
97
+ company_name?: string | null;
98
+ }): Promise<User>;
99
+ }
100
+ declare class OrganizationClient {
101
+ private readonly ctx?;
102
+ constructor(ctx?: PlatformContext | undefined);
103
+ currentId(): number | null;
104
+ currentRole(): string | null;
105
+ listMine(): Promise<OrgSummary[]>;
106
+ }
107
+
108
+ declare function createPaletteClient(ctx?: PlatformContext): {
109
+ user: UserClient;
110
+ organization: OrganizationClient;
111
+ dataRooms: DataRoomClient;
112
+ storage: StorageClient;
113
+ config: {
114
+ get: (pluginId?: string) => Promise<InstallConfig>;
115
+ update: (values: Record<string, unknown>, pluginId?: string) => Promise<InstallConfig>;
116
+ };
117
+ permissions: {
118
+ has: (permission: string) => boolean;
119
+ hasAny: (permissions: string[]) => boolean;
120
+ hasAll: (permissions: string[]) => boolean;
121
+ };
122
+ toast: {
123
+ success: (message: string) => void | undefined;
124
+ error: (message: string) => void | undefined;
125
+ info: (message: string) => void | undefined;
126
+ };
127
+ };
128
+ type PaletteClient = ReturnType<typeof createPaletteClient>;
129
+
130
+ declare function hasPermission(ctx: PlatformContext, permission: string): boolean;
131
+ declare function hasAnyPermission(ctx: PlatformContext, permissions: string[]): boolean;
132
+ declare function hasAllPermissions(ctx: PlatformContext, permissions: string[]): boolean;
133
+
134
+ export { DataRoom, DataRoomClient, type DataRoomContents, DataRoomFile, DataRoomFolder, type DataRoomUploadOptions, type InstallConfig, OrgSummary, OrganizationClient, PaletteApiError, type PaletteClient, PlatformContext, type SandboxBridge, StorageClient, User, UserClient, apiFetch, apiUpload, createMockPlatformContext, createPaletteClient, createSandboxBridge, dataRooms, errorFromResponse, getBaseUrl, getInstallConfig, hasAllPermissions, hasAnyPermission, hasPermission, isPaletteApiError, isSandboxRuntime, setBaseUrl, updateInstallConfig, uploadToSignedUrl, withPluginProvider };
package/dist/index.js CHANGED
@@ -20,20 +20,30 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
20
20
  // src/index.ts
21
21
  var src_exports = {};
22
22
  __export(src_exports, {
23
+ DataRoomClient: () => DataRoomClient,
24
+ OrganizationClient: () => OrganizationClient,
23
25
  PaletteApiError: () => PaletteApiError,
24
26
  PlatformCtx: () => PlatformCtx,
25
27
  PluginProvider: () => PluginProvider,
28
+ StorageClient: () => StorageClient,
29
+ UserClient: () => UserClient,
26
30
  apiFetch: () => apiFetch,
27
31
  apiUpload: () => apiUpload,
28
32
  createMockPlatformContext: () => createMockPlatformContext,
33
+ createPaletteClient: () => createPaletteClient,
29
34
  createSandboxBridge: () => createSandboxBridge,
35
+ dataRooms: () => dataRooms,
30
36
  errorFromResponse: () => errorFromResponse,
31
37
  getBaseUrl: () => getBaseUrl,
32
38
  getInstallConfig: () => getInstallConfig,
39
+ hasAllPermissions: () => hasAllPermissions,
40
+ hasAnyPermission: () => hasAnyPermission,
41
+ hasPermission: () => hasPermission,
33
42
  isPaletteApiError: () => isPaletteApiError,
34
43
  isSandboxRuntime: () => isSandboxRuntime,
35
44
  setBaseUrl: () => setBaseUrl,
36
45
  updateInstallConfig: () => updateInstallConfig,
46
+ uploadToSignedUrl: () => uploadToSignedUrl,
37
47
  usePlatform: () => usePlatform,
38
48
  usePluginChat: () => usePluginChat,
39
49
  usePluginDataRooms: () => usePluginDataRooms,
@@ -203,6 +213,7 @@ function createMockPlatformContext(overrides = {}) {
203
213
  orgRole: "owner",
204
214
  orgs: [],
205
215
  agents: [],
216
+ permissions: [],
206
217
  apiFetch: async () => new Response(JSON.stringify({}), { status: 200 }),
207
218
  navigate: () => {
208
219
  },
@@ -218,6 +229,164 @@ function withPluginProvider(element, platform = {}) {
218
229
  );
219
230
  }
220
231
 
232
+ // src/data-rooms.ts
233
+ var DataRoomClient = class {
234
+ async list() {
235
+ const res = await apiFetch("/api/v1/data-rooms");
236
+ return res.json();
237
+ }
238
+ async create(input) {
239
+ const res = await apiFetch("/api/v1/data-rooms", {
240
+ method: "POST",
241
+ body: JSON.stringify(input)
242
+ });
243
+ return res.json();
244
+ }
245
+ async get(roomId) {
246
+ const res = await apiFetch(`/api/v1/data-rooms/${roomId}`);
247
+ return res.json();
248
+ }
249
+ async folder(roomId, folderId) {
250
+ const res = await apiFetch(`/api/v1/data-rooms/${roomId}/folders/${folderId}`);
251
+ return res.json();
252
+ }
253
+ async requestUpload(roomId, file, options = {}) {
254
+ const res = await apiFetch(`/api/v1/data-rooms/${roomId}/files/request-upload`, {
255
+ method: "POST",
256
+ body: JSON.stringify({
257
+ filename: file.name,
258
+ content_type: options.contentType ?? file.type ?? "application/octet-stream",
259
+ file_size: file.size,
260
+ folder_id: options.folderId ?? null
261
+ })
262
+ });
263
+ return res.json();
264
+ }
265
+ async confirmUpload(roomId, file, upload, options = {}) {
266
+ const res = await apiFetch(`/api/v1/data-rooms/${roomId}/files/confirm-upload`, {
267
+ method: "POST",
268
+ body: JSON.stringify({
269
+ blob_path: upload.blob_path,
270
+ original_filename: file.name,
271
+ file_size: file.size,
272
+ mime_type: options.contentType ?? file.type ?? "application/octet-stream",
273
+ folder_id: options.folderId ?? null
274
+ })
275
+ });
276
+ return res.json();
277
+ }
278
+ async uploadFile(roomId, file, options = {}) {
279
+ const upload = await this.requestUpload(roomId, file, options);
280
+ const put = await fetch(upload.upload_url, {
281
+ method: "PUT",
282
+ headers: { "Content-Type": options.contentType ?? file.type ?? "application/octet-stream" },
283
+ body: file
284
+ });
285
+ if (!put.ok) throw new Error(`Upload failed: ${put.statusText}`);
286
+ return this.confirmUpload(roomId, file, upload, options);
287
+ }
288
+ };
289
+ var dataRooms = new DataRoomClient();
290
+
291
+ // src/permissions.ts
292
+ function hasPermission(ctx, permission) {
293
+ return ctx.permissions?.includes(permission) ?? false;
294
+ }
295
+ function hasAnyPermission(ctx, permissions) {
296
+ return permissions.some((permission) => hasPermission(ctx, permission));
297
+ }
298
+ function hasAllPermissions(ctx, permissions) {
299
+ return permissions.every((permission) => hasPermission(ctx, permission));
300
+ }
301
+
302
+ // src/storage.ts
303
+ async function uploadToSignedUrl(uploadUrl, file, contentType = "application/octet-stream") {
304
+ const res = await fetch(uploadUrl, {
305
+ method: "PUT",
306
+ headers: { "Content-Type": contentType },
307
+ body: file
308
+ });
309
+ if (!res.ok) throw new Error(`Upload failed: ${res.statusText}`);
310
+ }
311
+ var StorageClient = class {
312
+ constructor() {
313
+ this.uploadToSignedUrl = uploadToSignedUrl;
314
+ }
315
+ };
316
+
317
+ // src/user-org.ts
318
+ var UserClient = class {
319
+ constructor(ctx) {
320
+ this.ctx = ctx;
321
+ }
322
+ async current() {
323
+ if (this.ctx?.user) return this.ctx.user;
324
+ const res = await apiFetch("/api/v1/auth/me");
325
+ return res.json();
326
+ }
327
+ async updateProfile(input) {
328
+ const res = await apiFetch("/api/v1/auth/profile", {
329
+ method: "PATCH",
330
+ body: JSON.stringify(input)
331
+ });
332
+ return res.json();
333
+ }
334
+ };
335
+ var OrganizationClient = class {
336
+ constructor(ctx) {
337
+ this.ctx = ctx;
338
+ }
339
+ currentId() {
340
+ return this.ctx?.organizationId ?? null;
341
+ }
342
+ currentRole() {
343
+ return this.ctx?.orgRole ?? null;
344
+ }
345
+ async listMine() {
346
+ if (this.ctx?.orgs?.length) return this.ctx.orgs;
347
+ const res = await apiFetch("/api/v1/auth/my-orgs");
348
+ return res.json();
349
+ }
350
+ };
351
+
352
+ // src/palette-client.ts
353
+ function createPaletteClient(ctx) {
354
+ const defaultPluginId = () => {
355
+ if (ctx?.pluginId) return ctx.pluginId;
356
+ if (typeof window === "undefined") return "";
357
+ const match = window.location.pathname.match(/\/apps\/([^/?#]+)/);
358
+ return match ? decodeURIComponent(match[1]) : "";
359
+ };
360
+ return {
361
+ user: new UserClient(ctx),
362
+ organization: new OrganizationClient(ctx),
363
+ dataRooms: new DataRoomClient(),
364
+ storage: new StorageClient(),
365
+ config: {
366
+ get: (pluginId = ctx?.pluginId ?? "") => {
367
+ const resolved = pluginId || defaultPluginId();
368
+ if (!resolved) throw new Error("pluginId is required to read install config");
369
+ return getInstallConfig(resolved);
370
+ },
371
+ update: (values, pluginId = ctx?.pluginId ?? "") => {
372
+ const resolved = pluginId || defaultPluginId();
373
+ if (!resolved) throw new Error("pluginId is required to update install config");
374
+ return updateInstallConfig(resolved, values);
375
+ }
376
+ },
377
+ permissions: {
378
+ has: (permission) => ctx ? hasPermission(ctx, permission) : false,
379
+ hasAny: (permissions) => ctx ? hasAnyPermission(ctx, permissions) : false,
380
+ hasAll: (permissions) => ctx ? hasAllPermissions(ctx, permissions) : false
381
+ },
382
+ toast: {
383
+ success: (message) => ctx?.showToast(message, "success"),
384
+ error: (message) => ctx?.showToast(message, "error"),
385
+ info: (message) => ctx?.showToast(message, "info")
386
+ }
387
+ };
388
+ }
389
+
221
390
  // src/hooks/use-plugin-tasks.ts
222
391
  var import_react3 = require("react");
223
392
  function usePluginTasks(agentId) {
@@ -407,20 +576,30 @@ function usePluginChat(agentId) {
407
576
  }
408
577
  // Annotate the CommonJS export names for ESM import in node:
409
578
  0 && (module.exports = {
579
+ DataRoomClient,
580
+ OrganizationClient,
410
581
  PaletteApiError,
411
582
  PlatformCtx,
412
583
  PluginProvider,
584
+ StorageClient,
585
+ UserClient,
413
586
  apiFetch,
414
587
  apiUpload,
415
588
  createMockPlatformContext,
589
+ createPaletteClient,
416
590
  createSandboxBridge,
591
+ dataRooms,
417
592
  errorFromResponse,
418
593
  getBaseUrl,
419
594
  getInstallConfig,
595
+ hasAllPermissions,
596
+ hasAnyPermission,
597
+ hasPermission,
420
598
  isPaletteApiError,
421
599
  isSandboxRuntime,
422
600
  setBaseUrl,
423
601
  updateInstallConfig,
602
+ uploadToSignedUrl,
424
603
  usePlatform,
425
604
  usePluginChat,
426
605
  usePluginDataRooms,
package/dist/index.mjs CHANGED
@@ -159,6 +159,7 @@ function createMockPlatformContext(overrides = {}) {
159
159
  orgRole: "owner",
160
160
  orgs: [],
161
161
  agents: [],
162
+ permissions: [],
162
163
  apiFetch: async () => new Response(JSON.stringify({}), { status: 200 }),
163
164
  navigate: () => {
164
165
  },
@@ -174,6 +175,164 @@ function withPluginProvider(element, platform = {}) {
174
175
  );
175
176
  }
176
177
 
178
+ // src/data-rooms.ts
179
+ var DataRoomClient = class {
180
+ async list() {
181
+ const res = await apiFetch("/api/v1/data-rooms");
182
+ return res.json();
183
+ }
184
+ async create(input) {
185
+ const res = await apiFetch("/api/v1/data-rooms", {
186
+ method: "POST",
187
+ body: JSON.stringify(input)
188
+ });
189
+ return res.json();
190
+ }
191
+ async get(roomId) {
192
+ const res = await apiFetch(`/api/v1/data-rooms/${roomId}`);
193
+ return res.json();
194
+ }
195
+ async folder(roomId, folderId) {
196
+ const res = await apiFetch(`/api/v1/data-rooms/${roomId}/folders/${folderId}`);
197
+ return res.json();
198
+ }
199
+ async requestUpload(roomId, file, options = {}) {
200
+ const res = await apiFetch(`/api/v1/data-rooms/${roomId}/files/request-upload`, {
201
+ method: "POST",
202
+ body: JSON.stringify({
203
+ filename: file.name,
204
+ content_type: options.contentType ?? file.type ?? "application/octet-stream",
205
+ file_size: file.size,
206
+ folder_id: options.folderId ?? null
207
+ })
208
+ });
209
+ return res.json();
210
+ }
211
+ async confirmUpload(roomId, file, upload, options = {}) {
212
+ const res = await apiFetch(`/api/v1/data-rooms/${roomId}/files/confirm-upload`, {
213
+ method: "POST",
214
+ body: JSON.stringify({
215
+ blob_path: upload.blob_path,
216
+ original_filename: file.name,
217
+ file_size: file.size,
218
+ mime_type: options.contentType ?? file.type ?? "application/octet-stream",
219
+ folder_id: options.folderId ?? null
220
+ })
221
+ });
222
+ return res.json();
223
+ }
224
+ async uploadFile(roomId, file, options = {}) {
225
+ const upload = await this.requestUpload(roomId, file, options);
226
+ const put = await fetch(upload.upload_url, {
227
+ method: "PUT",
228
+ headers: { "Content-Type": options.contentType ?? file.type ?? "application/octet-stream" },
229
+ body: file
230
+ });
231
+ if (!put.ok) throw new Error(`Upload failed: ${put.statusText}`);
232
+ return this.confirmUpload(roomId, file, upload, options);
233
+ }
234
+ };
235
+ var dataRooms = new DataRoomClient();
236
+
237
+ // src/permissions.ts
238
+ function hasPermission(ctx, permission) {
239
+ return ctx.permissions?.includes(permission) ?? false;
240
+ }
241
+ function hasAnyPermission(ctx, permissions) {
242
+ return permissions.some((permission) => hasPermission(ctx, permission));
243
+ }
244
+ function hasAllPermissions(ctx, permissions) {
245
+ return permissions.every((permission) => hasPermission(ctx, permission));
246
+ }
247
+
248
+ // src/storage.ts
249
+ async function uploadToSignedUrl(uploadUrl, file, contentType = "application/octet-stream") {
250
+ const res = await fetch(uploadUrl, {
251
+ method: "PUT",
252
+ headers: { "Content-Type": contentType },
253
+ body: file
254
+ });
255
+ if (!res.ok) throw new Error(`Upload failed: ${res.statusText}`);
256
+ }
257
+ var StorageClient = class {
258
+ constructor() {
259
+ this.uploadToSignedUrl = uploadToSignedUrl;
260
+ }
261
+ };
262
+
263
+ // src/user-org.ts
264
+ var UserClient = class {
265
+ constructor(ctx) {
266
+ this.ctx = ctx;
267
+ }
268
+ async current() {
269
+ if (this.ctx?.user) return this.ctx.user;
270
+ const res = await apiFetch("/api/v1/auth/me");
271
+ return res.json();
272
+ }
273
+ async updateProfile(input) {
274
+ const res = await apiFetch("/api/v1/auth/profile", {
275
+ method: "PATCH",
276
+ body: JSON.stringify(input)
277
+ });
278
+ return res.json();
279
+ }
280
+ };
281
+ var OrganizationClient = class {
282
+ constructor(ctx) {
283
+ this.ctx = ctx;
284
+ }
285
+ currentId() {
286
+ return this.ctx?.organizationId ?? null;
287
+ }
288
+ currentRole() {
289
+ return this.ctx?.orgRole ?? null;
290
+ }
291
+ async listMine() {
292
+ if (this.ctx?.orgs?.length) return this.ctx.orgs;
293
+ const res = await apiFetch("/api/v1/auth/my-orgs");
294
+ return res.json();
295
+ }
296
+ };
297
+
298
+ // src/palette-client.ts
299
+ function createPaletteClient(ctx) {
300
+ const defaultPluginId = () => {
301
+ if (ctx?.pluginId) return ctx.pluginId;
302
+ if (typeof window === "undefined") return "";
303
+ const match = window.location.pathname.match(/\/apps\/([^/?#]+)/);
304
+ return match ? decodeURIComponent(match[1]) : "";
305
+ };
306
+ return {
307
+ user: new UserClient(ctx),
308
+ organization: new OrganizationClient(ctx),
309
+ dataRooms: new DataRoomClient(),
310
+ storage: new StorageClient(),
311
+ config: {
312
+ get: (pluginId = ctx?.pluginId ?? "") => {
313
+ const resolved = pluginId || defaultPluginId();
314
+ if (!resolved) throw new Error("pluginId is required to read install config");
315
+ return getInstallConfig(resolved);
316
+ },
317
+ update: (values, pluginId = ctx?.pluginId ?? "") => {
318
+ const resolved = pluginId || defaultPluginId();
319
+ if (!resolved) throw new Error("pluginId is required to update install config");
320
+ return updateInstallConfig(resolved, values);
321
+ }
322
+ },
323
+ permissions: {
324
+ has: (permission) => ctx ? hasPermission(ctx, permission) : false,
325
+ hasAny: (permissions) => ctx ? hasAnyPermission(ctx, permissions) : false,
326
+ hasAll: (permissions) => ctx ? hasAllPermissions(ctx, permissions) : false
327
+ },
328
+ toast: {
329
+ success: (message) => ctx?.showToast(message, "success"),
330
+ error: (message) => ctx?.showToast(message, "error"),
331
+ info: (message) => ctx?.showToast(message, "info")
332
+ }
333
+ };
334
+ }
335
+
177
336
  // src/hooks/use-plugin-tasks.ts
178
337
  import { useCallback, useEffect, useState } from "react";
179
338
  function usePluginTasks(agentId) {
@@ -362,20 +521,30 @@ function usePluginChat(agentId) {
362
521
  };
363
522
  }
364
523
  export {
524
+ DataRoomClient,
525
+ OrganizationClient,
365
526
  PaletteApiError,
366
527
  PlatformCtx,
367
528
  PluginProvider,
529
+ StorageClient,
530
+ UserClient,
368
531
  apiFetch,
369
532
  apiUpload,
370
533
  createMockPlatformContext,
534
+ createPaletteClient,
371
535
  createSandboxBridge,
536
+ dataRooms,
372
537
  errorFromResponse,
373
538
  getBaseUrl,
374
539
  getInstallConfig,
540
+ hasAllPermissions,
541
+ hasAnyPermission,
542
+ hasPermission,
375
543
  isPaletteApiError,
376
544
  isSandboxRuntime,
377
545
  setBaseUrl,
378
546
  updateInstallConfig,
547
+ uploadToSignedUrl,
379
548
  usePlatform,
380
549
  usePluginChat,
381
550
  usePluginDataRooms,
@@ -141,6 +141,8 @@ interface PlatformContext {
141
141
  user: User;
142
142
  /** Current organization ID */
143
143
  organizationId: number;
144
+ /** Current plugin ID */
145
+ pluginId?: string;
144
146
  /** User's org role */
145
147
  orgRole: string | null;
146
148
  /** Available orgs */
@@ -153,6 +155,8 @@ interface PlatformContext {
153
155
  navigate: (path: string) => void;
154
156
  /** Show a toast notification */
155
157
  showToast: (message: string, type?: "success" | "error" | "info") => void;
158
+ /** Permissions declared for the current plugin install/runtime */
159
+ permissions?: string[];
156
160
  }
157
161
  /** Props passed to a plugin's root component */
158
162
  interface PluginComponentProps {
@@ -141,6 +141,8 @@ interface PlatformContext {
141
141
  user: User;
142
142
  /** Current organization ID */
143
143
  organizationId: number;
144
+ /** Current plugin ID */
145
+ pluginId?: string;
144
146
  /** User's org role */
145
147
  orgRole: string | null;
146
148
  /** Available orgs */
@@ -153,6 +155,8 @@ interface PlatformContext {
153
155
  navigate: (path: string) => void;
154
156
  /** Show a toast notification */
155
157
  showToast: (message: string, type?: "success" | "error" | "info") => void;
158
+ /** Permissions declared for the current plugin install/runtime */
159
+ permissions?: string[];
156
160
  }
157
161
  /** Props passed to a plugin's root component */
158
162
  interface PluginComponentProps {
@@ -1,5 +1,5 @@
1
- export { A as Agent, a as AgentConfig, b as AppCategory, c as AuthContextValue, O as OrgSummary, P as PlatformContext, d as PluginAgentDefinition, e as PluginComponentProps, f as PluginManifest, g as PluginToolDefinition, U as User } from '../plugin-DzSTKgkz.mjs';
2
- export { C as ChatAttachment, a as ChatMessage, b as ChatThread, D as DataRoom, c as DataRoomFile, d as DataRoomFolder, e as DataRoomPermission, T as Task, f as TaskAgentSnippet, g as TaskCreatePayload, h as TaskPriority, i as TaskStats, j as TaskStatus, k as TaskType, l as TaskUpdatePayload } from '../data-room-BP0PjYoe.mjs';
1
+ export { A as Agent, a as AgentConfig, b as AppCategory, c as AuthContextValue, O as OrgSummary, P as PlatformContext, d as PluginAgentDefinition, e as PluginComponentProps, f as PluginManifest, g as PluginToolDefinition, U as User } from '../plugin-o-qmdCBl.mjs';
2
+ export { C as ChatAttachment, c as ChatMessage, d as ChatThread, D as DataRoom, b as DataRoomFile, a as DataRoomFolder, e as DataRoomPermission, T as Task, f as TaskAgentSnippet, g as TaskCreatePayload, h as TaskPriority, i as TaskStats, j as TaskStatus, k as TaskType, l as TaskUpdatePayload } from '../data-room-Dtd9LLHf.mjs';
3
3
 
4
4
  interface AgentResource {
5
5
  id: number;
@@ -1,5 +1,5 @@
1
- export { A as Agent, a as AgentConfig, b as AppCategory, c as AuthContextValue, O as OrgSummary, P as PlatformContext, d as PluginAgentDefinition, e as PluginComponentProps, f as PluginManifest, g as PluginToolDefinition, U as User } from '../plugin-DzSTKgkz.js';
2
- export { C as ChatAttachment, a as ChatMessage, b as ChatThread, D as DataRoom, c as DataRoomFile, d as DataRoomFolder, e as DataRoomPermission, T as Task, f as TaskAgentSnippet, g as TaskCreatePayload, h as TaskPriority, i as TaskStats, j as TaskStatus, k as TaskType, l as TaskUpdatePayload } from '../data-room-BP0PjYoe.js';
1
+ export { A as Agent, a as AgentConfig, b as AppCategory, c as AuthContextValue, O as OrgSummary, P as PlatformContext, d as PluginAgentDefinition, e as PluginComponentProps, f as PluginManifest, g as PluginToolDefinition, U as User } from '../plugin-o-qmdCBl.js';
2
+ export { C as ChatAttachment, c as ChatMessage, d as ChatThread, D as DataRoom, b as DataRoomFile, a as DataRoomFolder, e as DataRoomPermission, T as Task, f as TaskAgentSnippet, g as TaskCreatePayload, h as TaskPriority, i as TaskStats, j as TaskStatus, k as TaskType, l as TaskUpdatePayload } from '../data-room-Dtd9LLHf.js';
3
3
 
4
4
  interface AgentResource {
5
5
  id: number;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@palettelab/sdk",
3
- "version": "0.1.7",
3
+ "version": "0.1.9",
4
4
  "description": "Palette Platform SDK for building plugins and apps",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",