@palettelab/sdk 0.1.23 → 0.1.25

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
@@ -185,6 +185,7 @@ Public frontend helpers exported by `@palettelab/sdk`:
185
185
  - Organization/user: `UserClient`, `OrganizationClient`, including `current`, `updateProfile`, `listMine`, `listMembers`, `getMember`, `getMemberByEmail`, `inviteMember`, and `updateMemberRole`.
186
186
  - Permissions: `hasPermission(ctx, permission)`, `hasAnyPermission(ctx, permissions)`, `hasAllPermissions(ctx, permissions)`.
187
187
  - Translations: `normalizePaletteLanguage`, `translate`, `usePluginTranslations`.
188
+ - OS context: `usePlatform().language`, `usePlatform().setLanguage()`, `usePlatform().colorMode`, and `usePlatform().setColorMode()`.
188
189
  - Hooks: `usePluginTasks`, `usePluginDataRooms`, `usePluginChat`.
189
190
  - Sandbox: `createSandboxBridge`, `isSandboxRuntime`.
190
191
  - Testing: `createMockPlatformContext`, `withPluginProvider`.
@@ -249,6 +250,32 @@ function App() {
249
250
  The same context is available in `pltt dev`, so local development and OS runtime
250
251
  use the same translation path.
251
252
 
253
+ ## App Color Mode And OS Theme
254
+
255
+ Palette OS also passes the current light/dark mode into every plugin through
256
+ `usePlatform()`. Apps can read `colorMode` to update app-owned styling or call
257
+ `setColorMode()` to request an OS-level light/dark change.
258
+
259
+ ```tsx
260
+ import { usePlatform } from "@palettelab/sdk"
261
+
262
+ function ThemeAwarePanel() {
263
+ const { colorMode, setColorMode } = usePlatform()
264
+
265
+ return (
266
+ <section data-color-mode={colorMode}>
267
+ <button onClick={() => setColorMode(colorMode === "dark" ? "light" : "dark")}>
268
+ Switch to {colorMode === "dark" ? "light" : "dark"}
269
+ </button>
270
+ </section>
271
+ )
272
+ }
273
+ ```
274
+
275
+ Native React apps re-render when Palette OS changes between light and dark mode.
276
+ For non-React code, Palette OS also dispatches a `palette:theme-change` browser
277
+ event with `{ colorMode: "light" | "dark" }` in `event.detail`.
278
+
252
279
  ## Next-Compatible Apps
253
280
 
254
281
  The Palette appstore runtime loads plugin frontends as native React modules. If
@@ -565,6 +592,7 @@ import { createSandboxBridge, isSandboxRuntime } from "@palettelab/sdk"
565
592
  if (isSandboxRuntime()) {
566
593
  const bridge = createSandboxBridge()
567
594
  const result = await bridge.apiFetch("/api/v1/tasks")
595
+ const colorMode = bridge.getColorMode()
568
596
  console.log(result)
569
597
  }
570
598
  ```
@@ -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-DXqw6d0s.mjs';
3
+ import { P as PlatformContext } from '../plugin-EHBRmN0H.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-DXqw6d0s.js';
3
+ import { P as PlatformContext } from '../plugin-EHBRmN0H.js';
4
4
 
5
5
  /**
6
6
  * Provider that wraps plugin components with the platform context.
@@ -1,4 +1,4 @@
1
- export { P as PlatformCtx, u as usePlatform, e as usePluginChat, f as usePluginDataRooms, g as usePluginTasks, h as usePluginTranslations } from '../index-CmY9M7Rg.mjs';
1
+ export { P as PlatformCtx, u as usePlatform, e as usePluginChat, f as usePluginDataRooms, g as usePluginTasks, h as usePluginTranslations } from '../index-DZqNC7hK.mjs';
2
2
  import 'react';
3
- import '../plugin-DXqw6d0s.mjs';
3
+ import '../plugin-EHBRmN0H.mjs';
4
4
  import '../data-room-Dtd9LLHf.mjs';
@@ -1,4 +1,4 @@
1
- export { P as PlatformCtx, u as usePlatform, e as usePluginChat, f as usePluginDataRooms, g as usePluginTasks, h as usePluginTranslations } from '../index-CGSwI4TZ.js';
1
+ export { P as PlatformCtx, u as usePlatform, e as usePluginChat, f as usePluginDataRooms, g as usePluginTasks, h as usePluginTranslations } from '../index-BFvgg3uv.js';
2
2
  import 'react';
3
- import '../plugin-DXqw6d0s.js';
3
+ import '../plugin-EHBRmN0H.js';
4
4
  import '../data-room-Dtd9LLHf.js';
@@ -1,5 +1,5 @@
1
1
  import * as react from 'react';
2
- import { d as PaletteLanguage, P as PlatformContext } from './plugin-DXqw6d0s.js';
2
+ import { e as PaletteLanguage, P as PlatformContext } from './plugin-EHBRmN0H.js';
3
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
  type TranslationPrimitive = string | number | boolean | null;
@@ -35,7 +35,7 @@ declare const PlatformCtx: react.Context<PlatformContext | null>;
35
35
  /**
36
36
  * Access the platform context from within a plugin component.
37
37
  *
38
- * Provides: user, organizationId, agents, apiFetch, navigate, showToast
38
+ * Provides: user, organizationId, agents, language, colorMode, apiFetch, navigate, showToast
39
39
  *
40
40
  * @example
41
41
  * ```tsx
@@ -1,5 +1,5 @@
1
1
  import * as react from 'react';
2
- import { d as PaletteLanguage, P as PlatformContext } from './plugin-DXqw6d0s.mjs';
2
+ import { e as PaletteLanguage, P as PlatformContext } from './plugin-EHBRmN0H.mjs';
3
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
  type TranslationPrimitive = string | number | boolean | null;
@@ -35,7 +35,7 @@ declare const PlatformCtx: react.Context<PlatformContext | null>;
35
35
  /**
36
36
  * Access the platform context from within a plugin component.
37
37
  *
38
- * Provides: user, organizationId, agents, apiFetch, navigate, showToast
38
+ * Provides: user, organizationId, agents, language, colorMode, apiFetch, navigate, showToast
39
39
  *
40
40
  * @example
41
41
  * ```tsx
package/dist/index.d.mts CHANGED
@@ -1,10 +1,10 @@
1
- import { P as PlatformContext, O as OrgSummary, U as User } from './plugin-DXqw6d0s.mjs';
2
- export { A as Agent, a as AgentConfig, b as AppCategory, c as AuthContextValue, d as PaletteLanguage, e as PluginAgentDefinition, f as PluginComponentProps, g as PluginConnectionDefinition, h as PluginManifest, i as PluginToolDefinition } from './plugin-DXqw6d0s.mjs';
1
+ import { P as PlatformContext, O as OrgSummary, U as User } from './plugin-EHBRmN0H.mjs';
2
+ export { A as Agent, a as AgentConfig, b as AppCategory, c as AuthContextValue, d as PaletteColorMode, e as PaletteLanguage, f as PluginAgentDefinition, g as PluginComponentProps, h as PluginConnectionDefinition, i as PluginManifest, j as PluginToolDefinition } from './plugin-EHBRmN0H.mjs';
3
3
  import { D as DataRoom, a as DataRoomFolder, b as DataRoomFile } from './data-room-Dtd9LLHf.mjs';
4
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';
5
5
  export { AgentResource, ResourcesByGroup } from './types/index.mjs';
6
6
  import { ReactElement } from 'react';
7
- export { P as PlatformCtx, T as TranslateOptions, a as TranslationDictionary, b as TranslationPrimitive, c as TranslationResources, d as TranslationValues, U as UsePluginTranslationsOptions, n as normalizePaletteLanguage, t as translate, u as usePlatform, e as usePluginChat, f as usePluginDataRooms, g as usePluginTasks, h as usePluginTranslations } from './index-CmY9M7Rg.mjs';
7
+ export { P as PlatformCtx, T as TranslateOptions, a as TranslationDictionary, b as TranslationPrimitive, c as TranslationResources, d as TranslationValues, U as UsePluginTranslationsOptions, n as normalizePaletteLanguage, t as translate, u as usePlatform, e as usePluginChat, f as usePluginDataRooms, g as usePluginTasks, h as usePluginTranslations } from './index-DZqNC7hK.mjs';
8
8
  export { Link, PaletteAppRoute, PaletteAppRouter, notFound, useParams, usePathname, useRouter, useSearchParams } from './router/index.mjs';
9
9
  export { PluginProvider } from './components/index.mjs';
10
10
  import 'react/jsx-runtime';
@@ -77,8 +77,10 @@ type SandboxBridge = {
77
77
  showToast: (message: string, type?: ToastType) => void;
78
78
  getLanguage: () => PlatformContext["language"];
79
79
  setLanguage: PlatformContext["setLanguage"];
80
+ getColorMode: () => PlatformContext["colorMode"];
81
+ setColorMode: PlatformContext["setColorMode"];
80
82
  };
81
- declare function createSandboxBridge(platform: Pick<PlatformContext, "apiFetch" | "navigate" | "showToast"> & Partial<Pick<PlatformContext, "language" | "setLanguage">>): SandboxBridge;
83
+ declare function createSandboxBridge(platform: Pick<PlatformContext, "apiFetch" | "navigate" | "showToast"> & Partial<Pick<PlatformContext, "language" | "setLanguage" | "colorMode" | "setColorMode">>): SandboxBridge;
82
84
  declare function isSandboxRuntime(): boolean;
83
85
 
84
86
  type InstallConfig = Record<string, unknown>;
@@ -187,6 +189,56 @@ declare const broker: {
187
189
  /** Typed proxy: `palette.services("org/v1").members.list({ ... })`. */
188
190
  declare function servicesProxy(namespaceVersion: string): any;
189
191
 
192
+ /**
193
+ * OS notifications — push a notification into the OS-level notification pool.
194
+ *
195
+ * import { notifications } from "@palettelab/sdk"
196
+ *
197
+ * await notifications.push({
198
+ * title: "Export complete",
199
+ * body: "Your report is ready to download.",
200
+ * severity: "success",
201
+ * route: "/exports/123", // opened inside this app when clicked
202
+ * })
203
+ *
204
+ * The notification appears in the OS notification center (and as a transient
205
+ * toast); clicking it opens/focuses the app window at `action_route`.
206
+ *
207
+ * The stable contract is `POST /api/v1/notifications/` on the platform API —
208
+ * this helper is sugar over it. Runs in the user's session (cookies included);
209
+ * sandboxed iframe apps are not supported yet (no session in the iframe).
210
+ */
211
+ type OsNotificationSeverity = "info" | "success" | "warning" | "error";
212
+ type OsNotificationInput = {
213
+ title: string;
214
+ body?: string;
215
+ /**
216
+ * Route to open when the notification is clicked. Relative routes
217
+ * ("/exports/123") resolve inside the calling app; absolute routes
218
+ * ("/apps/other-app") are used as-is.
219
+ */
220
+ route?: string;
221
+ severity?: OsNotificationSeverity;
222
+ /** Arbitrary structured payload, stored alongside the notification. */
223
+ data?: Record<string, unknown>;
224
+ /** Override the source app id. Inferred from the URL when omitted. */
225
+ appId?: string;
226
+ };
227
+ type OsNotification = {
228
+ id: number;
229
+ type: string;
230
+ title: string;
231
+ body: string | null;
232
+ source_app_id: string | null;
233
+ action_route: string | null;
234
+ severity: OsNotificationSeverity | null;
235
+ is_read: boolean;
236
+ created_at: string;
237
+ };
238
+ declare const notifications: {
239
+ push(input: OsNotificationInput): Promise<OsNotification>;
240
+ };
241
+
190
242
  interface DataRoomContents {
191
243
  room?: DataRoom;
192
244
  folders: DataRoomFolder[];
@@ -230,9 +282,11 @@ declare class DataRoomClient {
230
282
  upload_url: string;
231
283
  blob_path: string;
232
284
  file_url: string;
285
+ content_type?: string;
233
286
  }>;
234
287
  confirmUpload(roomId: number, file: File, upload: {
235
288
  blob_path: string;
289
+ content_type?: string;
236
290
  }, options?: DataRoomUploadOptions): Promise<DataRoomFile>;
237
291
  uploadFile(roomId: number, file: File, options?: DataRoomUploadOptions): Promise<DataRoomFile>;
238
292
  }
@@ -346,6 +400,13 @@ declare function createPaletteClient(ctx?: PlatformContext): {
346
400
  error: (message: string) => void | undefined;
347
401
  info: (message: string) => void | undefined;
348
402
  };
403
+ /**
404
+ * OS notification pool. Unlike `toast`, these persist in the OS
405
+ * notification center and can open the app when clicked.
406
+ */
407
+ notifications: {
408
+ push: (input: OsNotificationInput) => Promise<OsNotification>;
409
+ };
349
410
  /**
350
411
  * OS-broker RPC. Typed entry point: `palette.services("org/v1").members.list({...})`.
351
412
  * The proxy resolves a dotted method chain into a qualified target string
@@ -393,6 +454,13 @@ declare const palette: {
393
454
  error: (message: string) => void | undefined;
394
455
  info: (message: string) => void | undefined;
395
456
  };
457
+ /**
458
+ * OS notification pool. Unlike `toast`, these persist in the OS
459
+ * notification center and can open the app when clicked.
460
+ */
461
+ notifications: {
462
+ push: (input: OsNotificationInput) => Promise<OsNotification>;
463
+ };
396
464
  /**
397
465
  * OS-broker RPC. Typed entry point: `palette.services("org/v1").members.list({...})`.
398
466
  * The proxy resolves a dotted method chain into a qualified target string
@@ -419,4 +487,4 @@ declare function hasPermission(ctx: PlatformContext, permission: string): boolea
419
487
  declare function hasAnyPermission(ctx: PlatformContext, permissions: string[]): boolean;
420
488
  declare function hasAllPermissions(ctx: PlatformContext, permissions: string[]): boolean;
421
489
 
422
- export { BrokerCallError, type BrokerCallOptions, type ConnectionAuthStart, type ConnectionStatus, type ConnectionStatusValue, CrossAppGrantError, DataRoom, DataRoomClient, type DataRoomContents, DataRoomFile, DataRoomFolder, type DataRoomUploadOptions, type EventMeta, type InstallConfig, MissingDependencyError, type OrgInviteMemberInput, type OrgInviteMemberResponse, type OrgMember, type OrgMemberRole, OrgSummary, OrganizationClient, PaletteApiError, type PaletteClient, PlatformContext, type SandboxBridge, type SandboxBrokerMessage, StorageClient, type StorageUploadOptions, type StorageUploadProgress, type StorageUploadResult, type StorageUploadState, User, UserClient, apiFetch, apiUpload, broker, createMockPlatformContext, createPaletteClient, createSandboxBridge, dataRooms, disconnectConnection, errorFromResponse, events, getBaseUrl, getConnections, getInstallConfig, hasAllPermissions, hasAnyPermission, hasPermission, isPaletteApiError, isSandboxRuntime, palette, requireConnection, servicesProxy, setBaseUrl, startConnection, updateInstallConfig, uploadToSignedUrl, withPluginProvider };
490
+ export { BrokerCallError, type BrokerCallOptions, type ConnectionAuthStart, type ConnectionStatus, type ConnectionStatusValue, CrossAppGrantError, DataRoom, DataRoomClient, type DataRoomContents, DataRoomFile, DataRoomFolder, type DataRoomUploadOptions, type EventMeta, type InstallConfig, MissingDependencyError, type OrgInviteMemberInput, type OrgInviteMemberResponse, type OrgMember, type OrgMemberRole, OrgSummary, OrganizationClient, type OsNotification, type OsNotificationInput, type OsNotificationSeverity, PaletteApiError, type PaletteClient, PlatformContext, type SandboxBridge, type SandboxBrokerMessage, StorageClient, type StorageUploadOptions, type StorageUploadProgress, type StorageUploadResult, type StorageUploadState, User, UserClient, apiFetch, apiUpload, broker, createMockPlatformContext, createPaletteClient, createSandboxBridge, dataRooms, disconnectConnection, errorFromResponse, events, getBaseUrl, getConnections, getInstallConfig, hasAllPermissions, hasAnyPermission, hasPermission, isPaletteApiError, isSandboxRuntime, notifications, palette, requireConnection, servicesProxy, setBaseUrl, startConnection, updateInstallConfig, uploadToSignedUrl, withPluginProvider };
package/dist/index.d.ts CHANGED
@@ -1,10 +1,10 @@
1
- import { P as PlatformContext, O as OrgSummary, U as User } from './plugin-DXqw6d0s.js';
2
- export { A as Agent, a as AgentConfig, b as AppCategory, c as AuthContextValue, d as PaletteLanguage, e as PluginAgentDefinition, f as PluginComponentProps, g as PluginConnectionDefinition, h as PluginManifest, i as PluginToolDefinition } from './plugin-DXqw6d0s.js';
1
+ import { P as PlatformContext, O as OrgSummary, U as User } from './plugin-EHBRmN0H.js';
2
+ export { A as Agent, a as AgentConfig, b as AppCategory, c as AuthContextValue, d as PaletteColorMode, e as PaletteLanguage, f as PluginAgentDefinition, g as PluginComponentProps, h as PluginConnectionDefinition, i as PluginManifest, j as PluginToolDefinition } from './plugin-EHBRmN0H.js';
3
3
  import { D as DataRoom, a as DataRoomFolder, b as DataRoomFile } from './data-room-Dtd9LLHf.js';
4
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';
5
5
  export { AgentResource, ResourcesByGroup } from './types/index.js';
6
6
  import { ReactElement } from 'react';
7
- export { P as PlatformCtx, T as TranslateOptions, a as TranslationDictionary, b as TranslationPrimitive, c as TranslationResources, d as TranslationValues, U as UsePluginTranslationsOptions, n as normalizePaletteLanguage, t as translate, u as usePlatform, e as usePluginChat, f as usePluginDataRooms, g as usePluginTasks, h as usePluginTranslations } from './index-CGSwI4TZ.js';
7
+ export { P as PlatformCtx, T as TranslateOptions, a as TranslationDictionary, b as TranslationPrimitive, c as TranslationResources, d as TranslationValues, U as UsePluginTranslationsOptions, n as normalizePaletteLanguage, t as translate, u as usePlatform, e as usePluginChat, f as usePluginDataRooms, g as usePluginTasks, h as usePluginTranslations } from './index-BFvgg3uv.js';
8
8
  export { Link, PaletteAppRoute, PaletteAppRouter, notFound, useParams, usePathname, useRouter, useSearchParams } from './router/index.js';
9
9
  export { PluginProvider } from './components/index.js';
10
10
  import 'react/jsx-runtime';
@@ -77,8 +77,10 @@ type SandboxBridge = {
77
77
  showToast: (message: string, type?: ToastType) => void;
78
78
  getLanguage: () => PlatformContext["language"];
79
79
  setLanguage: PlatformContext["setLanguage"];
80
+ getColorMode: () => PlatformContext["colorMode"];
81
+ setColorMode: PlatformContext["setColorMode"];
80
82
  };
81
- declare function createSandboxBridge(platform: Pick<PlatformContext, "apiFetch" | "navigate" | "showToast"> & Partial<Pick<PlatformContext, "language" | "setLanguage">>): SandboxBridge;
83
+ declare function createSandboxBridge(platform: Pick<PlatformContext, "apiFetch" | "navigate" | "showToast"> & Partial<Pick<PlatformContext, "language" | "setLanguage" | "colorMode" | "setColorMode">>): SandboxBridge;
82
84
  declare function isSandboxRuntime(): boolean;
83
85
 
84
86
  type InstallConfig = Record<string, unknown>;
@@ -187,6 +189,56 @@ declare const broker: {
187
189
  /** Typed proxy: `palette.services("org/v1").members.list({ ... })`. */
188
190
  declare function servicesProxy(namespaceVersion: string): any;
189
191
 
192
+ /**
193
+ * OS notifications — push a notification into the OS-level notification pool.
194
+ *
195
+ * import { notifications } from "@palettelab/sdk"
196
+ *
197
+ * await notifications.push({
198
+ * title: "Export complete",
199
+ * body: "Your report is ready to download.",
200
+ * severity: "success",
201
+ * route: "/exports/123", // opened inside this app when clicked
202
+ * })
203
+ *
204
+ * The notification appears in the OS notification center (and as a transient
205
+ * toast); clicking it opens/focuses the app window at `action_route`.
206
+ *
207
+ * The stable contract is `POST /api/v1/notifications/` on the platform API —
208
+ * this helper is sugar over it. Runs in the user's session (cookies included);
209
+ * sandboxed iframe apps are not supported yet (no session in the iframe).
210
+ */
211
+ type OsNotificationSeverity = "info" | "success" | "warning" | "error";
212
+ type OsNotificationInput = {
213
+ title: string;
214
+ body?: string;
215
+ /**
216
+ * Route to open when the notification is clicked. Relative routes
217
+ * ("/exports/123") resolve inside the calling app; absolute routes
218
+ * ("/apps/other-app") are used as-is.
219
+ */
220
+ route?: string;
221
+ severity?: OsNotificationSeverity;
222
+ /** Arbitrary structured payload, stored alongside the notification. */
223
+ data?: Record<string, unknown>;
224
+ /** Override the source app id. Inferred from the URL when omitted. */
225
+ appId?: string;
226
+ };
227
+ type OsNotification = {
228
+ id: number;
229
+ type: string;
230
+ title: string;
231
+ body: string | null;
232
+ source_app_id: string | null;
233
+ action_route: string | null;
234
+ severity: OsNotificationSeverity | null;
235
+ is_read: boolean;
236
+ created_at: string;
237
+ };
238
+ declare const notifications: {
239
+ push(input: OsNotificationInput): Promise<OsNotification>;
240
+ };
241
+
190
242
  interface DataRoomContents {
191
243
  room?: DataRoom;
192
244
  folders: DataRoomFolder[];
@@ -230,9 +282,11 @@ declare class DataRoomClient {
230
282
  upload_url: string;
231
283
  blob_path: string;
232
284
  file_url: string;
285
+ content_type?: string;
233
286
  }>;
234
287
  confirmUpload(roomId: number, file: File, upload: {
235
288
  blob_path: string;
289
+ content_type?: string;
236
290
  }, options?: DataRoomUploadOptions): Promise<DataRoomFile>;
237
291
  uploadFile(roomId: number, file: File, options?: DataRoomUploadOptions): Promise<DataRoomFile>;
238
292
  }
@@ -346,6 +400,13 @@ declare function createPaletteClient(ctx?: PlatformContext): {
346
400
  error: (message: string) => void | undefined;
347
401
  info: (message: string) => void | undefined;
348
402
  };
403
+ /**
404
+ * OS notification pool. Unlike `toast`, these persist in the OS
405
+ * notification center and can open the app when clicked.
406
+ */
407
+ notifications: {
408
+ push: (input: OsNotificationInput) => Promise<OsNotification>;
409
+ };
349
410
  /**
350
411
  * OS-broker RPC. Typed entry point: `palette.services("org/v1").members.list({...})`.
351
412
  * The proxy resolves a dotted method chain into a qualified target string
@@ -393,6 +454,13 @@ declare const palette: {
393
454
  error: (message: string) => void | undefined;
394
455
  info: (message: string) => void | undefined;
395
456
  };
457
+ /**
458
+ * OS notification pool. Unlike `toast`, these persist in the OS
459
+ * notification center and can open the app when clicked.
460
+ */
461
+ notifications: {
462
+ push: (input: OsNotificationInput) => Promise<OsNotification>;
463
+ };
396
464
  /**
397
465
  * OS-broker RPC. Typed entry point: `palette.services("org/v1").members.list({...})`.
398
466
  * The proxy resolves a dotted method chain into a qualified target string
@@ -419,4 +487,4 @@ declare function hasPermission(ctx: PlatformContext, permission: string): boolea
419
487
  declare function hasAnyPermission(ctx: PlatformContext, permissions: string[]): boolean;
420
488
  declare function hasAllPermissions(ctx: PlatformContext, permissions: string[]): boolean;
421
489
 
422
- export { BrokerCallError, type BrokerCallOptions, type ConnectionAuthStart, type ConnectionStatus, type ConnectionStatusValue, CrossAppGrantError, DataRoom, DataRoomClient, type DataRoomContents, DataRoomFile, DataRoomFolder, type DataRoomUploadOptions, type EventMeta, type InstallConfig, MissingDependencyError, type OrgInviteMemberInput, type OrgInviteMemberResponse, type OrgMember, type OrgMemberRole, OrgSummary, OrganizationClient, PaletteApiError, type PaletteClient, PlatformContext, type SandboxBridge, type SandboxBrokerMessage, StorageClient, type StorageUploadOptions, type StorageUploadProgress, type StorageUploadResult, type StorageUploadState, User, UserClient, apiFetch, apiUpload, broker, createMockPlatformContext, createPaletteClient, createSandboxBridge, dataRooms, disconnectConnection, errorFromResponse, events, getBaseUrl, getConnections, getInstallConfig, hasAllPermissions, hasAnyPermission, hasPermission, isPaletteApiError, isSandboxRuntime, palette, requireConnection, servicesProxy, setBaseUrl, startConnection, updateInstallConfig, uploadToSignedUrl, withPluginProvider };
490
+ export { BrokerCallError, type BrokerCallOptions, type ConnectionAuthStart, type ConnectionStatus, type ConnectionStatusValue, CrossAppGrantError, DataRoom, DataRoomClient, type DataRoomContents, DataRoomFile, DataRoomFolder, type DataRoomUploadOptions, type EventMeta, type InstallConfig, MissingDependencyError, type OrgInviteMemberInput, type OrgInviteMemberResponse, type OrgMember, type OrgMemberRole, OrgSummary, OrganizationClient, type OsNotification, type OsNotificationInput, type OsNotificationSeverity, PaletteApiError, type PaletteClient, PlatformContext, type SandboxBridge, type SandboxBrokerMessage, StorageClient, type StorageUploadOptions, type StorageUploadProgress, type StorageUploadResult, type StorageUploadState, User, UserClient, apiFetch, apiUpload, broker, createMockPlatformContext, createPaletteClient, createSandboxBridge, dataRooms, disconnectConnection, errorFromResponse, events, getBaseUrl, getConnections, getInstallConfig, hasAllPermissions, hasAnyPermission, hasPermission, isPaletteApiError, isSandboxRuntime, notifications, palette, requireConnection, servicesProxy, setBaseUrl, startConnection, updateInstallConfig, uploadToSignedUrl, withPluginProvider };
package/dist/index.js CHANGED
@@ -52,6 +52,7 @@ __export(src_exports, {
52
52
  isSandboxRuntime: () => isSandboxRuntime,
53
53
  normalizePaletteLanguage: () => normalizePaletteLanguage,
54
54
  notFound: () => notFound,
55
+ notifications: () => notifications,
55
56
  palette: () => palette,
56
57
  requireConnection: () => requireConnection,
57
58
  servicesProxy: () => servicesProxy,
@@ -164,6 +165,9 @@ function createSandboxBridge(platform) {
164
165
  showToast: platform.showToast,
165
166
  getLanguage: () => platform.language ?? "en",
166
167
  setLanguage: platform.setLanguage ?? (() => {
168
+ }),
169
+ getColorMode: () => platform.colorMode ?? "light",
170
+ setColorMode: platform.setColorMode ?? (() => {
167
171
  })
168
172
  };
169
173
  }
@@ -269,6 +273,9 @@ function createMockPlatformContext(overrides = {}) {
269
273
  supportedLanguages: ["en", "ko"],
270
274
  setLanguage: () => {
271
275
  },
276
+ colorMode: "light",
277
+ setColorMode: () => {
278
+ },
272
279
  apiFetch: async () => new Response(JSON.stringify({}), { status: 200 }),
273
280
  navigate: () => {
274
281
  },
@@ -367,13 +374,14 @@ var DataRoomClient = class {
367
374
  return res.json();
368
375
  }
369
376
  async confirmUpload(roomId, file, upload, options = {}) {
377
+ const contentType = upload.content_type ?? options.contentType ?? file.type ?? "application/octet-stream";
370
378
  const res = await apiFetch(`/api/v1/data-rooms/${roomId}/files/confirm-upload`, {
371
379
  method: "POST",
372
380
  body: JSON.stringify({
373
381
  blob_path: upload.blob_path,
374
382
  original_filename: file.name,
375
383
  file_size: file.size,
376
- mime_type: options.contentType ?? file.type ?? "application/octet-stream",
384
+ mime_type: contentType,
377
385
  folder_id: options.folderId ?? null
378
386
  })
379
387
  });
@@ -381,9 +389,10 @@ var DataRoomClient = class {
381
389
  }
382
390
  async uploadFile(roomId, file, options = {}) {
383
391
  const upload = await this.requestUpload(roomId, file, options);
392
+ const contentType = upload.content_type ?? options.contentType ?? file.type ?? "application/octet-stream";
384
393
  const put = await fetch(upload.upload_url, {
385
394
  method: "PUT",
386
- headers: { "Content-Type": options.contentType ?? file.type ?? "application/octet-stream" },
395
+ headers: { "Content-Type": contentType },
387
396
  body: file
388
397
  });
389
398
  if (!put.ok) throw new Error(`Upload failed: ${put.statusText}`);
@@ -392,6 +401,13 @@ var DataRoomClient = class {
392
401
  };
393
402
  var dataRooms = new DataRoomClient();
394
403
 
404
+ // src/plugin-id.ts
405
+ function currentPluginId() {
406
+ if (typeof window === "undefined") return void 0;
407
+ const match = window.location.pathname.match(/\/apps\/([^/?#]+)/);
408
+ return match ? decodeURIComponent(match[1]) : void 0;
409
+ }
410
+
395
411
  // src/services.ts
396
412
  var BrokerCallError = class extends Error {
397
413
  constructor(message, target, status) {
@@ -424,11 +440,6 @@ function brokerError(message, target, status) {
424
440
  return new BrokerCallError(message, target, status);
425
441
  }
426
442
  var CALLER_HEADER = "X-Palette-Caller-App";
427
- function currentPluginId() {
428
- if (typeof window === "undefined") return void 0;
429
- const match = window.location.pathname.match(/\/apps\/([^/?#]+)/);
430
- return match ? decodeURIComponent(match[1]) : void 0;
431
- }
432
443
  async function brokerCallDirect(target, payload, options = {}) {
433
444
  const callerAppId = options.callerAppId ?? currentPluginId();
434
445
  const headers = {};
@@ -553,16 +564,11 @@ var SUBSCRIBERS = /* @__PURE__ */ new Map();
553
564
  var activeStream = null;
554
565
  var activeStreamUrl = null;
555
566
  var sandboxBound = false;
556
- function currentPluginId2() {
557
- if (typeof window === "undefined") return void 0;
558
- const match = window.location.pathname.match(/\/apps\/([^/?#]+)/);
559
- return match ? decodeURIComponent(match[1]) : void 0;
560
- }
561
567
  function streamUrl() {
562
568
  const params = new URLSearchParams();
563
569
  const targets = Array.from(SUBSCRIBERS.keys());
564
570
  if (targets.length) params.set("targets", targets.join(","));
565
- const callerAppId = currentPluginId2();
571
+ const callerAppId = currentPluginId();
566
572
  if (callerAppId) params.set("caller_app_id", callerAppId);
567
573
  const query = params.toString();
568
574
  return `${getBaseUrl()}/api/v1/os-broker/events/stream${query ? `?${query}` : ""}`;
@@ -658,6 +664,32 @@ var events = {
658
664
  }
659
665
  };
660
666
 
667
+ // src/notifications.ts
668
+ function resolveActionRoute(route, appId) {
669
+ if (!route) return appId ? `/apps/${appId}` : void 0;
670
+ if (route.startsWith("/apps/")) return route;
671
+ if (!appId) return route;
672
+ return `/apps/${appId}${route.startsWith("/") ? route : `/${route}`}`;
673
+ }
674
+ var notifications = {
675
+ async push(input) {
676
+ const appId = input.appId ?? currentPluginId();
677
+ const res = await apiFetch("/api/v1/notifications/", {
678
+ method: "POST",
679
+ body: JSON.stringify({
680
+ title: input.title,
681
+ body: input.body,
682
+ type: "app",
683
+ source_app_id: appId,
684
+ action_route: resolveActionRoute(input.route, appId),
685
+ severity: input.severity,
686
+ data: input.data
687
+ })
688
+ });
689
+ return await res.json();
690
+ }
691
+ };
692
+
661
693
  // src/permissions.ts
662
694
  function hasPermission(ctx, permission) {
663
695
  return ctx.permissions?.includes(permission) ?? false;
@@ -988,6 +1020,13 @@ function createPaletteClient(ctx) {
988
1020
  error: (message) => ctx?.showToast(message, "error"),
989
1021
  info: (message) => ctx?.showToast(message, "info")
990
1022
  },
1023
+ /**
1024
+ * OS notification pool. Unlike `toast`, these persist in the OS
1025
+ * notification center and can open the app when clicked.
1026
+ */
1027
+ notifications: {
1028
+ push: (input) => notifications.push({ appId: ctx?.pluginId || void 0, ...input })
1029
+ },
991
1030
  /**
992
1031
  * OS-broker RPC. Typed entry point: `palette.services("org/v1").members.list({...})`.
993
1032
  * The proxy resolves a dotted method chain into a qualified target string
@@ -1496,6 +1535,7 @@ function usePluginChat(agentId) {
1496
1535
  isSandboxRuntime,
1497
1536
  normalizePaletteLanguage,
1498
1537
  notFound,
1538
+ notifications,
1499
1539
  palette,
1500
1540
  requireConnection,
1501
1541
  servicesProxy,
package/dist/index.mjs CHANGED
@@ -89,6 +89,9 @@ function createSandboxBridge(platform) {
89
89
  showToast: platform.showToast,
90
90
  getLanguage: () => platform.language ?? "en",
91
91
  setLanguage: platform.setLanguage ?? (() => {
92
+ }),
93
+ getColorMode: () => platform.colorMode ?? "light",
94
+ setColorMode: platform.setColorMode ?? (() => {
92
95
  })
93
96
  };
94
97
  }
@@ -194,6 +197,9 @@ function createMockPlatformContext(overrides = {}) {
194
197
  supportedLanguages: ["en", "ko"],
195
198
  setLanguage: () => {
196
199
  },
200
+ colorMode: "light",
201
+ setColorMode: () => {
202
+ },
197
203
  apiFetch: async () => new Response(JSON.stringify({}), { status: 200 }),
198
204
  navigate: () => {
199
205
  },
@@ -292,13 +298,14 @@ var DataRoomClient = class {
292
298
  return res.json();
293
299
  }
294
300
  async confirmUpload(roomId, file, upload, options = {}) {
301
+ const contentType = upload.content_type ?? options.contentType ?? file.type ?? "application/octet-stream";
295
302
  const res = await apiFetch(`/api/v1/data-rooms/${roomId}/files/confirm-upload`, {
296
303
  method: "POST",
297
304
  body: JSON.stringify({
298
305
  blob_path: upload.blob_path,
299
306
  original_filename: file.name,
300
307
  file_size: file.size,
301
- mime_type: options.contentType ?? file.type ?? "application/octet-stream",
308
+ mime_type: contentType,
302
309
  folder_id: options.folderId ?? null
303
310
  })
304
311
  });
@@ -306,9 +313,10 @@ var DataRoomClient = class {
306
313
  }
307
314
  async uploadFile(roomId, file, options = {}) {
308
315
  const upload = await this.requestUpload(roomId, file, options);
316
+ const contentType = upload.content_type ?? options.contentType ?? file.type ?? "application/octet-stream";
309
317
  const put = await fetch(upload.upload_url, {
310
318
  method: "PUT",
311
- headers: { "Content-Type": options.contentType ?? file.type ?? "application/octet-stream" },
319
+ headers: { "Content-Type": contentType },
312
320
  body: file
313
321
  });
314
322
  if (!put.ok) throw new Error(`Upload failed: ${put.statusText}`);
@@ -317,6 +325,13 @@ var DataRoomClient = class {
317
325
  };
318
326
  var dataRooms = new DataRoomClient();
319
327
 
328
+ // src/plugin-id.ts
329
+ function currentPluginId() {
330
+ if (typeof window === "undefined") return void 0;
331
+ const match = window.location.pathname.match(/\/apps\/([^/?#]+)/);
332
+ return match ? decodeURIComponent(match[1]) : void 0;
333
+ }
334
+
320
335
  // src/services.ts
321
336
  var BrokerCallError = class extends Error {
322
337
  constructor(message, target, status) {
@@ -349,11 +364,6 @@ function brokerError(message, target, status) {
349
364
  return new BrokerCallError(message, target, status);
350
365
  }
351
366
  var CALLER_HEADER = "X-Palette-Caller-App";
352
- function currentPluginId() {
353
- if (typeof window === "undefined") return void 0;
354
- const match = window.location.pathname.match(/\/apps\/([^/?#]+)/);
355
- return match ? decodeURIComponent(match[1]) : void 0;
356
- }
357
367
  async function brokerCallDirect(target, payload, options = {}) {
358
368
  const callerAppId = options.callerAppId ?? currentPluginId();
359
369
  const headers = {};
@@ -478,16 +488,11 @@ var SUBSCRIBERS = /* @__PURE__ */ new Map();
478
488
  var activeStream = null;
479
489
  var activeStreamUrl = null;
480
490
  var sandboxBound = false;
481
- function currentPluginId2() {
482
- if (typeof window === "undefined") return void 0;
483
- const match = window.location.pathname.match(/\/apps\/([^/?#]+)/);
484
- return match ? decodeURIComponent(match[1]) : void 0;
485
- }
486
491
  function streamUrl() {
487
492
  const params = new URLSearchParams();
488
493
  const targets = Array.from(SUBSCRIBERS.keys());
489
494
  if (targets.length) params.set("targets", targets.join(","));
490
- const callerAppId = currentPluginId2();
495
+ const callerAppId = currentPluginId();
491
496
  if (callerAppId) params.set("caller_app_id", callerAppId);
492
497
  const query = params.toString();
493
498
  return `${getBaseUrl()}/api/v1/os-broker/events/stream${query ? `?${query}` : ""}`;
@@ -583,6 +588,32 @@ var events = {
583
588
  }
584
589
  };
585
590
 
591
+ // src/notifications.ts
592
+ function resolveActionRoute(route, appId) {
593
+ if (!route) return appId ? `/apps/${appId}` : void 0;
594
+ if (route.startsWith("/apps/")) return route;
595
+ if (!appId) return route;
596
+ return `/apps/${appId}${route.startsWith("/") ? route : `/${route}`}`;
597
+ }
598
+ var notifications = {
599
+ async push(input) {
600
+ const appId = input.appId ?? currentPluginId();
601
+ const res = await apiFetch("/api/v1/notifications/", {
602
+ method: "POST",
603
+ body: JSON.stringify({
604
+ title: input.title,
605
+ body: input.body,
606
+ type: "app",
607
+ source_app_id: appId,
608
+ action_route: resolveActionRoute(input.route, appId),
609
+ severity: input.severity,
610
+ data: input.data
611
+ })
612
+ });
613
+ return await res.json();
614
+ }
615
+ };
616
+
586
617
  // src/permissions.ts
587
618
  function hasPermission(ctx, permission) {
588
619
  return ctx.permissions?.includes(permission) ?? false;
@@ -913,6 +944,13 @@ function createPaletteClient(ctx) {
913
944
  error: (message) => ctx?.showToast(message, "error"),
914
945
  info: (message) => ctx?.showToast(message, "info")
915
946
  },
947
+ /**
948
+ * OS notification pool. Unlike `toast`, these persist in the OS
949
+ * notification center and can open the app when clicked.
950
+ */
951
+ notifications: {
952
+ push: (input) => notifications.push({ appId: ctx?.pluginId || void 0, ...input })
953
+ },
916
954
  /**
917
955
  * OS-broker RPC. Typed entry point: `palette.services("org/v1").members.list({...})`.
918
956
  * The proxy resolves a dotted method chain into a qualified target string
@@ -1429,6 +1467,7 @@ export {
1429
1467
  isSandboxRuntime,
1430
1468
  normalizePaletteLanguage,
1431
1469
  notFound,
1470
+ notifications,
1432
1471
  palette,
1433
1472
  requireConnection,
1434
1473
  servicesProxy,
@@ -69,6 +69,8 @@ interface AgentConfig {
69
69
 
70
70
  /** BCP-47 language tag used by Palette OS and plugin translation helpers */
71
71
  type PaletteLanguage = string;
72
+ /** Palette OS light/dark interface mode */
73
+ type PaletteColorMode = "light" | "dark";
72
74
  /** App store category */
73
75
  type AppCategory = "All" | "Productivity" | "Design" | "Marketing" | "Analytics";
74
76
  /** Plugin manifest — corresponds to palette-plugin.json */
@@ -240,6 +242,10 @@ interface PlatformContext {
240
242
  supportedLanguages: PaletteLanguage[];
241
243
  /** Update the Palette OS language preference */
242
244
  setLanguage: (language: PaletteLanguage) => void;
245
+ /** Current Palette OS light/dark interface mode */
246
+ colorMode: PaletteColorMode;
247
+ /** Update the Palette OS light/dark interface mode */
248
+ setColorMode: (mode: PaletteColorMode) => void;
243
249
  /** API fetch helper with auth handling */
244
250
  apiFetch: (path: string, init?: RequestInit) => Promise<Response>;
245
251
  /** Navigate to a platform route */
@@ -256,4 +262,4 @@ interface PluginComponentProps {
256
262
  platform: PlatformContext;
257
263
  }
258
264
 
259
- export type { Agent as A, OrgSummary as O, PlatformContext as P, User as U, AgentConfig as a, AppCategory as b, AuthContextValue as c, PaletteLanguage as d, PluginAgentDefinition as e, PluginComponentProps as f, PluginConnectionDefinition as g, PluginManifest as h, PluginToolDefinition as i };
265
+ export type { Agent as A, OrgSummary as O, PlatformContext as P, User as U, AgentConfig as a, AppCategory as b, AuthContextValue as c, PaletteColorMode as d, PaletteLanguage as e, PluginAgentDefinition as f, PluginComponentProps as g, PluginConnectionDefinition as h, PluginManifest as i, PluginToolDefinition as j };
@@ -69,6 +69,8 @@ interface AgentConfig {
69
69
 
70
70
  /** BCP-47 language tag used by Palette OS and plugin translation helpers */
71
71
  type PaletteLanguage = string;
72
+ /** Palette OS light/dark interface mode */
73
+ type PaletteColorMode = "light" | "dark";
72
74
  /** App store category */
73
75
  type AppCategory = "All" | "Productivity" | "Design" | "Marketing" | "Analytics";
74
76
  /** Plugin manifest — corresponds to palette-plugin.json */
@@ -240,6 +242,10 @@ interface PlatformContext {
240
242
  supportedLanguages: PaletteLanguage[];
241
243
  /** Update the Palette OS language preference */
242
244
  setLanguage: (language: PaletteLanguage) => void;
245
+ /** Current Palette OS light/dark interface mode */
246
+ colorMode: PaletteColorMode;
247
+ /** Update the Palette OS light/dark interface mode */
248
+ setColorMode: (mode: PaletteColorMode) => void;
243
249
  /** API fetch helper with auth handling */
244
250
  apiFetch: (path: string, init?: RequestInit) => Promise<Response>;
245
251
  /** Navigate to a platform route */
@@ -256,4 +262,4 @@ interface PluginComponentProps {
256
262
  platform: PlatformContext;
257
263
  }
258
264
 
259
- export type { Agent as A, OrgSummary as O, PlatformContext as P, User as U, AgentConfig as a, AppCategory as b, AuthContextValue as c, PaletteLanguage as d, PluginAgentDefinition as e, PluginComponentProps as f, PluginConnectionDefinition as g, PluginManifest as h, PluginToolDefinition as i };
265
+ export type { Agent as A, OrgSummary as O, PlatformContext as P, User as U, AgentConfig as a, AppCategory as b, AuthContextValue as c, PaletteColorMode as d, PaletteLanguage as e, PluginAgentDefinition as f, PluginComponentProps as g, PluginConnectionDefinition as h, PluginManifest as i, PluginToolDefinition as j };
@@ -1,4 +1,4 @@
1
- export { A as Agent, a as AgentConfig, b as AppCategory, c as AuthContextValue, O as OrgSummary, d as PaletteLanguage, P as PlatformContext, e as PluginAgentDefinition, f as PluginComponentProps, g as PluginConnectionDefinition, h as PluginManifest, i as PluginToolDefinition, U as User } from '../plugin-DXqw6d0s.mjs';
1
+ export { A as Agent, a as AgentConfig, b as AppCategory, c as AuthContextValue, O as OrgSummary, d as PaletteColorMode, e as PaletteLanguage, P as PlatformContext, f as PluginAgentDefinition, g as PluginComponentProps, h as PluginConnectionDefinition, i as PluginManifest, j as PluginToolDefinition, U as User } from '../plugin-EHBRmN0H.mjs';
2
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 {
@@ -1,4 +1,4 @@
1
- export { A as Agent, a as AgentConfig, b as AppCategory, c as AuthContextValue, O as OrgSummary, d as PaletteLanguage, P as PlatformContext, e as PluginAgentDefinition, f as PluginComponentProps, g as PluginConnectionDefinition, h as PluginManifest, i as PluginToolDefinition, U as User } from '../plugin-DXqw6d0s.js';
1
+ export { A as Agent, a as AgentConfig, b as AppCategory, c as AuthContextValue, O as OrgSummary, d as PaletteColorMode, e as PaletteLanguage, P as PlatformContext, f as PluginAgentDefinition, g as PluginComponentProps, h as PluginConnectionDefinition, i as PluginManifest, j as PluginToolDefinition, U as User } from '../plugin-EHBRmN0H.js';
2
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 {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@palettelab/sdk",
3
- "version": "0.1.23",
3
+ "version": "0.1.25",
4
4
  "description": "Palette Platform SDK for building plugins and apps",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",