@palettelab/sdk 0.1.9 → 0.1.11

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/dist/index.mjs CHANGED
@@ -86,7 +86,10 @@ function createSandboxBridge(platform) {
86
86
  return {
87
87
  apiFetch: platform.apiFetch,
88
88
  navigate: platform.navigate,
89
- showToast: platform.showToast
89
+ showToast: platform.showToast,
90
+ getLanguage: () => platform.language ?? "en",
91
+ setLanguage: platform.setLanguage ?? (() => {
92
+ })
90
93
  };
91
94
  }
92
95
  function isSandboxRuntime() {
@@ -160,6 +163,11 @@ function createMockPlatformContext(overrides = {}) {
160
163
  orgs: [],
161
164
  agents: [],
162
165
  permissions: [],
166
+ language: "en",
167
+ fallbackLanguage: "en",
168
+ supportedLanguages: ["en", "ko"],
169
+ setLanguage: () => {
170
+ },
163
171
  apiFetch: async () => new Response(JSON.stringify({}), { status: 200 }),
164
172
  navigate: () => {
165
173
  },
@@ -177,6 +185,10 @@ function withPluginProvider(element, platform = {}) {
177
185
 
178
186
  // src/data-rooms.ts
179
187
  var DataRoomClient = class {
188
+ matchesName(actual, expected, options = {}) {
189
+ if (options.caseSensitive) return actual === expected;
190
+ return actual.localeCompare(expected, void 0, { sensitivity: "accent" }) === 0;
191
+ }
180
192
  async list() {
181
193
  const res = await apiFetch("/api/v1/data-rooms");
182
194
  return res.json();
@@ -196,6 +208,50 @@ var DataRoomClient = class {
196
208
  const res = await apiFetch(`/api/v1/data-rooms/${roomId}/folders/${folderId}`);
197
209
  return res.json();
198
210
  }
211
+ async findRoomByName(name, options = {}) {
212
+ const rooms = await this.list();
213
+ return rooms.find((room) => this.matchesName(room.name, name, options)) ?? null;
214
+ }
215
+ async requireRoomByName(name, options = {}) {
216
+ const room = await this.findRoomByName(name, options);
217
+ if (!room) throw new Error(`Data Room not found: ${name}`);
218
+ return room;
219
+ }
220
+ async ensureRoom(name, description) {
221
+ return await this.findRoomByName(name) ?? this.create({ name, description });
222
+ }
223
+ async createFolder(roomId, input) {
224
+ const res = await apiFetch(`/api/v1/data-rooms/${roomId}/folders`, {
225
+ method: "POST",
226
+ body: JSON.stringify({
227
+ name: input.name,
228
+ parent_folder_id: input.parentFolderId ?? null
229
+ })
230
+ });
231
+ return res.json();
232
+ }
233
+ async findFolderByName(roomId, name, options = {}) {
234
+ const contents = options.parentFolderId ? await this.folder(roomId, options.parentFolderId) : await this.get(roomId);
235
+ return contents.folders.find((folder) => this.matchesName(folder.name, name, options)) ?? null;
236
+ }
237
+ async ensureFolder(roomId, name, options = {}) {
238
+ return await this.findFolderByName(roomId, name, options) ?? this.createFolder(roomId, { name, parentFolderId: options.parentFolderId ?? null });
239
+ }
240
+ async resolveFolderPath(roomId, path, options = {}) {
241
+ const parts = Array.isArray(path) ? path : path.split("/").map((part) => part.trim()).filter(Boolean);
242
+ let parentFolderId = null;
243
+ let current = null;
244
+ for (const part of parts) {
245
+ current = options.create ? await this.ensureFolder(roomId, part, { ...options, parentFolderId }) : await this.findFolderByName(roomId, part, { ...options, parentFolderId });
246
+ if (!current) return null;
247
+ parentFolderId = current.id;
248
+ }
249
+ return current;
250
+ }
251
+ async findFileByName(roomId, name, options = {}) {
252
+ const contents = options.folderId ? await this.folder(roomId, options.folderId) : await this.get(roomId);
253
+ return contents.files.find((file) => this.matchesName(file.original_filename, name, options)) ?? null;
254
+ }
199
255
  async requestUpload(roomId, file, options = {}) {
200
256
  const res = await apiFetch(`/api/v1/data-rooms/${roomId}/files/request-upload`, {
201
257
  method: "POST",
@@ -333,14 +389,77 @@ function createPaletteClient(ctx) {
333
389
  };
334
390
  }
335
391
 
392
+ // src/i18n.ts
393
+ import { useCallback } from "react";
394
+ function normalizePaletteLanguage(language, fallback = "en") {
395
+ const trimmed = language?.trim().toLowerCase();
396
+ if (!trimmed) return fallback;
397
+ return trimmed.split("-")[0] || fallback;
398
+ }
399
+ function languageCandidates(language, fallbackLanguage = "en") {
400
+ const candidates = [
401
+ language,
402
+ normalizePaletteLanguage(language, fallbackLanguage),
403
+ fallbackLanguage,
404
+ normalizePaletteLanguage(fallbackLanguage, "en"),
405
+ "en"
406
+ ].filter(Boolean);
407
+ return Array.from(new Set(candidates));
408
+ }
409
+ function getValue(dictionary, key) {
410
+ if (!dictionary) return void 0;
411
+ let current = dictionary;
412
+ for (const part of key.split(".")) {
413
+ if (current === null || typeof current !== "object" || Array.isArray(current)) return void 0;
414
+ current = current[part];
415
+ }
416
+ if (typeof current === "string" || typeof current === "number" || typeof current === "boolean" || current === null) {
417
+ return current;
418
+ }
419
+ return void 0;
420
+ }
421
+ function interpolate(template, values) {
422
+ if (!values) return template;
423
+ return template.replace(/\{\{?\s*([a-zA-Z0-9_.-]+)\s*\}?\}/g, (match, key) => {
424
+ const value = values[key];
425
+ return value === void 0 || value === null ? match : String(value);
426
+ });
427
+ }
428
+ function translate(resources, key, options = {}) {
429
+ const fallbackLanguage = normalizePaletteLanguage(options.fallbackLanguage, "en");
430
+ for (const language of languageCandidates(options.language, fallbackLanguage)) {
431
+ const value = getValue(resources[language], key);
432
+ if (value !== void 0) {
433
+ return interpolate(String(value ?? ""), options.values);
434
+ }
435
+ }
436
+ return interpolate(options.defaultValue ?? key, options.values);
437
+ }
438
+ function usePluginTranslations(resources, options = {}) {
439
+ const platform = usePlatform();
440
+ const language = normalizePaletteLanguage(platform.language, options.fallbackLanguage ?? platform.fallbackLanguage);
441
+ const fallbackLanguage = normalizePaletteLanguage(options.fallbackLanguage ?? platform.fallbackLanguage, "en");
442
+ const t = useCallback(
443
+ (key, values, defaultValue) => translate(resources, key, { language, fallbackLanguage, values, defaultValue }),
444
+ [fallbackLanguage, language, resources]
445
+ );
446
+ return {
447
+ language,
448
+ fallbackLanguage,
449
+ supportedLanguages: platform.supportedLanguages,
450
+ setLanguage: platform.setLanguage,
451
+ t
452
+ };
453
+ }
454
+
336
455
  // src/hooks/use-plugin-tasks.ts
337
- import { useCallback, useEffect, useState } from "react";
456
+ import { useCallback as useCallback2, useEffect, useState } from "react";
338
457
  function usePluginTasks(agentId) {
339
458
  const { apiFetch: apiFetch2 } = usePlatform();
340
459
  const [tasks, setTasks] = useState([]);
341
460
  const [stats, setStats] = useState(null);
342
461
  const [loading, setLoading] = useState(true);
343
- const fetchTasks = useCallback(async () => {
462
+ const fetchTasks = useCallback2(async () => {
344
463
  try {
345
464
  const params = new URLSearchParams();
346
465
  if (agentId) params.set("agent_id", String(agentId));
@@ -349,7 +468,7 @@ function usePluginTasks(agentId) {
349
468
  } catch {
350
469
  }
351
470
  }, [apiFetch2, agentId]);
352
- const fetchStats = useCallback(async () => {
471
+ const fetchStats = useCallback2(async () => {
353
472
  try {
354
473
  const res = await apiFetch2("/api/v1/tasks/stats");
355
474
  setStats(await res.json());
@@ -360,7 +479,7 @@ function usePluginTasks(agentId) {
360
479
  setLoading(true);
361
480
  Promise.all([fetchTasks(), fetchStats()]).finally(() => setLoading(false));
362
481
  }, [fetchTasks, fetchStats]);
363
- const createTask = useCallback(async (payload) => {
482
+ const createTask = useCallback2(async (payload) => {
364
483
  const res = await apiFetch2("/api/v1/tasks", {
365
484
  method: "POST",
366
485
  body: JSON.stringify(payload)
@@ -369,7 +488,7 @@ function usePluginTasks(agentId) {
369
488
  await Promise.all([fetchTasks(), fetchStats()]);
370
489
  return task;
371
490
  }, [apiFetch2, fetchTasks, fetchStats]);
372
- const updateTask = useCallback(async (taskId, payload) => {
491
+ const updateTask = useCallback2(async (taskId, payload) => {
373
492
  const res = await apiFetch2(`/api/v1/tasks/${taskId}`, {
374
493
  method: "PATCH",
375
494
  body: JSON.stringify(payload)
@@ -378,7 +497,7 @@ function usePluginTasks(agentId) {
378
497
  await Promise.all([fetchTasks(), fetchStats()]);
379
498
  return task;
380
499
  }, [apiFetch2, fetchTasks, fetchStats]);
381
- const deleteTask = useCallback(async (taskId) => {
500
+ const deleteTask = useCallback2(async (taskId) => {
382
501
  await apiFetch2(`/api/v1/tasks/${taskId}`, { method: "DELETE" });
383
502
  await Promise.all([fetchTasks(), fetchStats()]);
384
503
  }, [apiFetch2, fetchTasks, fetchStats]);
@@ -386,12 +505,12 @@ function usePluginTasks(agentId) {
386
505
  }
387
506
 
388
507
  // src/hooks/use-plugin-data-rooms.ts
389
- import { useCallback as useCallback2, useEffect as useEffect2, useState as useState2 } from "react";
508
+ import { useCallback as useCallback3, useEffect as useEffect2, useState as useState2 } from "react";
390
509
  function usePluginDataRooms() {
391
510
  const { apiFetch: apiFetch2 } = usePlatform();
392
511
  const [rooms, setRooms] = useState2([]);
393
512
  const [loading, setLoading] = useState2(true);
394
- const fetchRooms = useCallback2(async () => {
513
+ const fetchRooms = useCallback3(async () => {
395
514
  try {
396
515
  const res = await apiFetch2("/api/v1/data-rooms");
397
516
  setRooms(await res.json());
@@ -402,7 +521,7 @@ function usePluginDataRooms() {
402
521
  setLoading(true);
403
522
  fetchRooms().finally(() => setLoading(false));
404
523
  }, [fetchRooms]);
405
- const fetchFolder = useCallback2(async (roomId, folderId) => {
524
+ const fetchFolder = useCallback3(async (roomId, folderId) => {
406
525
  const path = folderId ? `/api/v1/data-rooms/${roomId}/folders/${folderId}` : `/api/v1/data-rooms/${roomId}`;
407
526
  const res = await apiFetch2(path);
408
527
  return res.json();
@@ -411,7 +530,7 @@ function usePluginDataRooms() {
411
530
  }
412
531
 
413
532
  // src/hooks/use-plugin-chat.ts
414
- import { useCallback as useCallback3, useRef, useState as useState3 } from "react";
533
+ import { useCallback as useCallback4, useRef, useState as useState3 } from "react";
415
534
  function usePluginChat(agentId) {
416
535
  const { apiFetch: apiFetch2 } = usePlatform();
417
536
  const [threads, setThreads] = useState3([]);
@@ -419,11 +538,11 @@ function usePluginChat(agentId) {
419
538
  const [streaming, setStreaming] = useState3(false);
420
539
  const [activeThreadId, setActiveThreadId] = useState3(null);
421
540
  const abortRef = useRef(null);
422
- const fetchThreads = useCallback3(async () => {
541
+ const fetchThreads = useCallback4(async () => {
423
542
  const res = await apiFetch2(`/api/v1/chat/${agentId}/threads`);
424
543
  setThreads(await res.json());
425
544
  }, [apiFetch2, agentId]);
426
- const createThread = useCallback3(async () => {
545
+ const createThread = useCallback4(async () => {
427
546
  const res = await apiFetch2(`/api/v1/chat/${agentId}/threads`, { method: "POST" });
428
547
  const thread = await res.json();
429
548
  setActiveThreadId(thread.id);
@@ -431,13 +550,13 @@ function usePluginChat(agentId) {
431
550
  await fetchThreads();
432
551
  return thread;
433
552
  }, [apiFetch2, agentId, fetchThreads]);
434
- const fetchMessages = useCallback3(async (threadId) => {
553
+ const fetchMessages = useCallback4(async (threadId) => {
435
554
  const res = await apiFetch2(`/api/v1/chat/threads/${threadId}/messages`);
436
555
  const msgs = await res.json();
437
556
  setMessages(msgs);
438
557
  setActiveThreadId(threadId);
439
558
  }, [apiFetch2]);
440
- const sendMessage = useCallback3(async (threadId, content) => {
559
+ const sendMessage = useCallback4(async (threadId, content) => {
441
560
  setStreaming(true);
442
561
  abortRef.current = new AbortController();
443
562
  const userMsg = {
@@ -505,7 +624,7 @@ function usePluginChat(agentId) {
505
624
  abortRef.current = null;
506
625
  }
507
626
  }, []);
508
- const stopStreaming = useCallback3(() => {
627
+ const stopStreaming = useCallback4(() => {
509
628
  abortRef.current?.abort();
510
629
  }, []);
511
630
  return {
@@ -542,12 +661,15 @@ export {
542
661
  hasPermission,
543
662
  isPaletteApiError,
544
663
  isSandboxRuntime,
664
+ normalizePaletteLanguage,
545
665
  setBaseUrl,
666
+ translate,
546
667
  updateInstallConfig,
547
668
  uploadToSignedUrl,
548
669
  usePlatform,
549
670
  usePluginChat,
550
671
  usePluginDataRooms,
551
672
  usePluginTasks,
673
+ usePluginTranslations,
552
674
  withPluginProvider
553
675
  };
@@ -67,6 +67,8 @@ interface AgentConfig {
67
67
  notes: string | null;
68
68
  }
69
69
 
70
+ /** BCP-47 language tag used by Palette OS and plugin translation helpers */
71
+ type PaletteLanguage = string;
70
72
  /** App store category */
71
73
  type AppCategory = "All" | "Productivity" | "Design" | "Marketing" | "Analytics";
72
74
  /** Plugin manifest — corresponds to palette-plugin.json */
@@ -149,6 +151,14 @@ interface PlatformContext {
149
151
  orgs: OrgSummary[];
150
152
  /** Available agents */
151
153
  agents: Agent[];
154
+ /** Current Palette OS language, normalized for plugin translation lookup */
155
+ language: PaletteLanguage;
156
+ /** Fallback language used when a plugin does not provide a key for language */
157
+ fallbackLanguage: PaletteLanguage;
158
+ /** Languages available in the current Palette OS environment */
159
+ supportedLanguages: PaletteLanguage[];
160
+ /** Update the Palette OS language preference */
161
+ setLanguage: (language: PaletteLanguage) => void;
152
162
  /** API fetch helper with auth handling */
153
163
  apiFetch: (path: string, init?: RequestInit) => Promise<Response>;
154
164
  /** Navigate to a platform route */
@@ -163,4 +173,4 @@ interface PluginComponentProps {
163
173
  platform: PlatformContext;
164
174
  }
165
175
 
166
- export type { Agent as A, OrgSummary as O, PlatformContext as P, User as U, AgentConfig as a, AppCategory as b, AuthContextValue as c, PluginAgentDefinition as d, PluginComponentProps as e, PluginManifest as f, PluginToolDefinition as g };
176
+ 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, PluginManifest as g, PluginToolDefinition as h };
@@ -67,6 +67,8 @@ interface AgentConfig {
67
67
  notes: string | null;
68
68
  }
69
69
 
70
+ /** BCP-47 language tag used by Palette OS and plugin translation helpers */
71
+ type PaletteLanguage = string;
70
72
  /** App store category */
71
73
  type AppCategory = "All" | "Productivity" | "Design" | "Marketing" | "Analytics";
72
74
  /** Plugin manifest — corresponds to palette-plugin.json */
@@ -149,6 +151,14 @@ interface PlatformContext {
149
151
  orgs: OrgSummary[];
150
152
  /** Available agents */
151
153
  agents: Agent[];
154
+ /** Current Palette OS language, normalized for plugin translation lookup */
155
+ language: PaletteLanguage;
156
+ /** Fallback language used when a plugin does not provide a key for language */
157
+ fallbackLanguage: PaletteLanguage;
158
+ /** Languages available in the current Palette OS environment */
159
+ supportedLanguages: PaletteLanguage[];
160
+ /** Update the Palette OS language preference */
161
+ setLanguage: (language: PaletteLanguage) => void;
152
162
  /** API fetch helper with auth handling */
153
163
  apiFetch: (path: string, init?: RequestInit) => Promise<Response>;
154
164
  /** Navigate to a platform route */
@@ -163,4 +173,4 @@ interface PluginComponentProps {
163
173
  platform: PlatformContext;
164
174
  }
165
175
 
166
- export type { Agent as A, OrgSummary as O, PlatformContext as P, User as U, AgentConfig as a, AppCategory as b, AuthContextValue as c, PluginAgentDefinition as d, PluginComponentProps as e, PluginManifest as f, PluginToolDefinition as g };
176
+ 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, PluginManifest as g, PluginToolDefinition as h };
@@ -1,4 +1,4 @@
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';
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 PluginManifest, h as PluginToolDefinition, U as User } from '../plugin-DZRaxKt3.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, P as PlatformContext, d as PluginAgentDefinition, e as PluginComponentProps, f as PluginManifest, g as PluginToolDefinition, U as User } from '../plugin-o-qmdCBl.js';
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 PluginManifest, h as PluginToolDefinition, U as User } from '../plugin-DZRaxKt3.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.9",
3
+ "version": "0.1.11",
4
4
  "description": "Palette Platform SDK for building plugins and apps",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",