@personaai/react 0.15.0 → 0.16.0

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.d.cts CHANGED
@@ -170,7 +170,8 @@ interface PersonaFileItem {
170
170
  createdAt: string;
171
171
  }
172
172
  interface PersonaMemoryFile {
173
- scope?: "user" | "agent";
173
+ scope?: "user" | "agent" | "workspace";
174
+ /** Set when `scope` is `"agent"` or `"workspace"`. */
174
175
  agentId?: string;
175
176
  path: string;
176
177
  content: string;
@@ -178,7 +179,11 @@ interface PersonaMemoryFile {
178
179
  createdAt?: string;
179
180
  updatedAt?: string;
180
181
  }
181
- /** One agent's group of agent-scoped memory files, as returned by `GET /memory`. */
182
+ /**
183
+ * One agent's group of scoped memory files, as returned by `GET /memory` —
184
+ * used for both `agentMemories` (`scope: "agent"`) and `agentWorkspaces`
185
+ * (`scope: "workspace"`).
186
+ */
182
187
  interface PersonaMemoryAgentGroup {
183
188
  agentId: string;
184
189
  /** `null` if the agent no longer exists. */
@@ -188,6 +193,14 @@ interface PersonaMemoryAgentGroup {
188
193
  interface PersonaMemoryList {
189
194
  userFiles: PersonaMemoryFile[];
190
195
  agentMemories: PersonaMemoryAgentGroup[];
196
+ /**
197
+ * Files under an Agent's own `/workspace/` filesystem route — the SAME
198
+ * persistent store `write_file`/`read_file` tool calls under
199
+ * `/workspace/...` actually read and write. Scoped by Agent + Subject,
200
+ * shared across every Thread that Subject has with that Agent (not
201
+ * private to one conversation).
202
+ */
203
+ agentWorkspaces: PersonaMemoryAgentGroup[];
191
204
  }
192
205
  /**
193
206
  * AG-UI protocol events emitted during streaming — mirrors exactly what
@@ -1296,18 +1309,18 @@ declare function useMemory(autoFetch?: boolean): {
1296
1309
  refetch: () => Promise<PersonaMemoryList>;
1297
1310
  getFile: (params: {
1298
1311
  path: string;
1299
- scope?: "user" | "agent";
1312
+ scope?: "user" | "agent" | "workspace";
1300
1313
  agentId?: string;
1301
1314
  }) => Promise<PersonaMemoryFile>;
1302
1315
  writeFile: (params: {
1303
1316
  path: string;
1304
1317
  content: string;
1305
- scope?: "user" | "agent";
1318
+ scope?: "user" | "agent" | "workspace";
1306
1319
  agentId?: string;
1307
1320
  }) => Promise<PersonaMemoryFile>;
1308
1321
  deleteFile: (params: {
1309
1322
  path: string;
1310
- scope?: "user" | "agent";
1323
+ scope?: "user" | "agent" | "workspace";
1311
1324
  agentId?: string;
1312
1325
  }) => Promise<void>;
1313
1326
  };
@@ -1337,17 +1350,22 @@ declare function useThreads(autoFetch?: boolean): {
1337
1350
  };
1338
1351
 
1339
1352
  /**
1340
- * CRUD over one Thread's workspace files (the agent's own virtual
1341
- * filesystem) — `useChat()` already exposes a read-only `files` snapshot
1342
- * tied to that thread's live/loaded messages; this hook is for a
1343
- * standalone file-explorer UI that needs to list, read, write, and delete
1344
- * files independently of an active chat session.
1353
+ * CRUD over one Agent's `/workspace/` files — the SAME persistent store a
1354
+ * `write_file`/`read_file` tool call under `/workspace/...` actually reads
1355
+ * and writes (deepagents routes that path prefix to a Mongo-backed memory
1356
+ * store, NOT the LangGraph checkpoint's `files` state channel — a Thread's
1357
+ * live/checkpointed state is a different, much narrower thing that rarely
1358
+ * has anything in it, since agents are instructed to write all real output
1359
+ * under `/workspace/outputs/`). Scoped by Agent + Subject: shared across
1360
+ * every Thread that Subject has with that Agent, not private to one
1361
+ * conversation — the same model the platform's own Files panel uses.
1345
1362
  *
1346
- * KNOWN LIMITATION (inherited from the backend): no lock exists against a
1347
- * concurrent live run on the same Thread — writing here while the agent is
1348
- * actively mid-run could race with its own file writes.
1363
+ * Thin wrapper over `client.memory` (`scope: "workspace"`) — no parallel
1364
+ * type vocabulary, `PersonaWorkspaceFile` here is just `PersonaMemoryFile`
1365
+ * reshaped to the `{content, size, createdAt, modifiedAt}` display shape
1366
+ * `useChat()`'s own (read-only, live-run) `files` snapshot already uses.
1349
1367
  */
1350
- declare function useWorkspaceFiles(threadId: string | undefined, autoFetch?: boolean): {
1368
+ declare function useWorkspaceFiles(agentId: string | undefined, autoFetch?: boolean): {
1351
1369
  files: Record<string, PersonaWorkspaceFile>;
1352
1370
  isLoading: boolean;
1353
1371
  isSaving: boolean;
package/dist/index.d.ts CHANGED
@@ -170,7 +170,8 @@ interface PersonaFileItem {
170
170
  createdAt: string;
171
171
  }
172
172
  interface PersonaMemoryFile {
173
- scope?: "user" | "agent";
173
+ scope?: "user" | "agent" | "workspace";
174
+ /** Set when `scope` is `"agent"` or `"workspace"`. */
174
175
  agentId?: string;
175
176
  path: string;
176
177
  content: string;
@@ -178,7 +179,11 @@ interface PersonaMemoryFile {
178
179
  createdAt?: string;
179
180
  updatedAt?: string;
180
181
  }
181
- /** One agent's group of agent-scoped memory files, as returned by `GET /memory`. */
182
+ /**
183
+ * One agent's group of scoped memory files, as returned by `GET /memory` —
184
+ * used for both `agentMemories` (`scope: "agent"`) and `agentWorkspaces`
185
+ * (`scope: "workspace"`).
186
+ */
182
187
  interface PersonaMemoryAgentGroup {
183
188
  agentId: string;
184
189
  /** `null` if the agent no longer exists. */
@@ -188,6 +193,14 @@ interface PersonaMemoryAgentGroup {
188
193
  interface PersonaMemoryList {
189
194
  userFiles: PersonaMemoryFile[];
190
195
  agentMemories: PersonaMemoryAgentGroup[];
196
+ /**
197
+ * Files under an Agent's own `/workspace/` filesystem route — the SAME
198
+ * persistent store `write_file`/`read_file` tool calls under
199
+ * `/workspace/...` actually read and write. Scoped by Agent + Subject,
200
+ * shared across every Thread that Subject has with that Agent (not
201
+ * private to one conversation).
202
+ */
203
+ agentWorkspaces: PersonaMemoryAgentGroup[];
191
204
  }
192
205
  /**
193
206
  * AG-UI protocol events emitted during streaming — mirrors exactly what
@@ -1296,18 +1309,18 @@ declare function useMemory(autoFetch?: boolean): {
1296
1309
  refetch: () => Promise<PersonaMemoryList>;
1297
1310
  getFile: (params: {
1298
1311
  path: string;
1299
- scope?: "user" | "agent";
1312
+ scope?: "user" | "agent" | "workspace";
1300
1313
  agentId?: string;
1301
1314
  }) => Promise<PersonaMemoryFile>;
1302
1315
  writeFile: (params: {
1303
1316
  path: string;
1304
1317
  content: string;
1305
- scope?: "user" | "agent";
1318
+ scope?: "user" | "agent" | "workspace";
1306
1319
  agentId?: string;
1307
1320
  }) => Promise<PersonaMemoryFile>;
1308
1321
  deleteFile: (params: {
1309
1322
  path: string;
1310
- scope?: "user" | "agent";
1323
+ scope?: "user" | "agent" | "workspace";
1311
1324
  agentId?: string;
1312
1325
  }) => Promise<void>;
1313
1326
  };
@@ -1337,17 +1350,22 @@ declare function useThreads(autoFetch?: boolean): {
1337
1350
  };
1338
1351
 
1339
1352
  /**
1340
- * CRUD over one Thread's workspace files (the agent's own virtual
1341
- * filesystem) — `useChat()` already exposes a read-only `files` snapshot
1342
- * tied to that thread's live/loaded messages; this hook is for a
1343
- * standalone file-explorer UI that needs to list, read, write, and delete
1344
- * files independently of an active chat session.
1353
+ * CRUD over one Agent's `/workspace/` files — the SAME persistent store a
1354
+ * `write_file`/`read_file` tool call under `/workspace/...` actually reads
1355
+ * and writes (deepagents routes that path prefix to a Mongo-backed memory
1356
+ * store, NOT the LangGraph checkpoint's `files` state channel — a Thread's
1357
+ * live/checkpointed state is a different, much narrower thing that rarely
1358
+ * has anything in it, since agents are instructed to write all real output
1359
+ * under `/workspace/outputs/`). Scoped by Agent + Subject: shared across
1360
+ * every Thread that Subject has with that Agent, not private to one
1361
+ * conversation — the same model the platform's own Files panel uses.
1345
1362
  *
1346
- * KNOWN LIMITATION (inherited from the backend): no lock exists against a
1347
- * concurrent live run on the same Thread — writing here while the agent is
1348
- * actively mid-run could race with its own file writes.
1363
+ * Thin wrapper over `client.memory` (`scope: "workspace"`) — no parallel
1364
+ * type vocabulary, `PersonaWorkspaceFile` here is just `PersonaMemoryFile`
1365
+ * reshaped to the `{content, size, createdAt, modifiedAt}` display shape
1366
+ * `useChat()`'s own (read-only, live-run) `files` snapshot already uses.
1349
1367
  */
1350
- declare function useWorkspaceFiles(threadId: string | undefined, autoFetch?: boolean): {
1368
+ declare function useWorkspaceFiles(agentId: string | undefined, autoFetch?: boolean): {
1351
1369
  files: Record<string, PersonaWorkspaceFile>;
1352
1370
  isLoading: boolean;
1353
1371
  isSaving: boolean;
package/dist/index.js CHANGED
@@ -1666,7 +1666,8 @@ function useMemory(autoFetch = true) {
1666
1666
  const { fetchWithAuth } = usePersonaContext();
1667
1667
  const [memory, setMemory] = useState3({
1668
1668
  userFiles: [],
1669
- agentMemories: []
1669
+ agentMemories: [],
1670
+ agentWorkspaces: []
1670
1671
  });
1671
1672
  const [isLoading, setIsLoading] = useState3(false);
1672
1673
  const [error, setError] = useState3(null);
@@ -1684,7 +1685,7 @@ function useMemory(autoFetch = true) {
1684
1685
  } catch (err) {
1685
1686
  const errorObj = err instanceof Error ? err : new Error(String(err));
1686
1687
  setError(errorObj);
1687
- return { userFiles: [], agentMemories: [] };
1688
+ return { userFiles: [], agentMemories: [], agentWorkspaces: [] };
1688
1689
  } finally {
1689
1690
  setIsLoading(false);
1690
1691
  }
@@ -1891,21 +1892,36 @@ function useThreads(autoFetch = true) {
1891
1892
 
1892
1893
  // src/hooks/useWorkspaceFiles.ts
1893
1894
  import { useCallback as useCallback5, useEffect as useEffect5, useState as useState5 } from "react";
1894
- function useWorkspaceFiles(threadId, autoFetch = true) {
1895
+ function toWorkspaceFile(file) {
1896
+ return {
1897
+ content: file.content,
1898
+ size: file.content.length,
1899
+ createdAt: file.createdAt ?? null,
1900
+ modifiedAt: file.updatedAt ?? null
1901
+ };
1902
+ }
1903
+ function useWorkspaceFiles(agentId, autoFetch = true) {
1895
1904
  const { fetchWithAuth } = usePersonaContext();
1896
1905
  const [files, setFiles] = useState5({});
1897
1906
  const [isLoading, setIsLoading] = useState5(false);
1898
1907
  const [isSaving, setIsSaving] = useState5(false);
1899
1908
  const [error, setError] = useState5(null);
1900
1909
  const fetchFiles = useCallback5(async () => {
1901
- if (!threadId) return {};
1910
+ if (!agentId) return {};
1902
1911
  setIsLoading(true);
1903
1912
  setError(null);
1904
1913
  try {
1905
- const res = await fetchWithAuth(`/threads/${threadId}/files`);
1914
+ const res = await fetchWithAuth("/memory");
1906
1915
  if (!res.ok) throw new Error(`Failed to list workspace files: ${res.statusText}`);
1907
1916
  const data = await res.json();
1908
- const normalized = normalizeWorkspaceFiles(data?.data ?? data ?? {});
1917
+ const body = data?.data ?? data;
1918
+ const group = (body?.agentWorkspaces ?? []).find(
1919
+ (g) => g.agentId === agentId
1920
+ );
1921
+ const normalized = {};
1922
+ for (const file of group?.files ?? []) {
1923
+ normalized[file.path] = toWorkspaceFile(file);
1924
+ }
1909
1925
  setFiles(normalized);
1910
1926
  return normalized;
1911
1927
  } catch (err) {
@@ -1915,35 +1931,34 @@ function useWorkspaceFiles(threadId, autoFetch = true) {
1915
1931
  } finally {
1916
1932
  setIsLoading(false);
1917
1933
  }
1918
- }, [fetchWithAuth, threadId]);
1934
+ }, [fetchWithAuth, agentId]);
1919
1935
  const getFile = useCallback5(
1920
1936
  async (path) => {
1921
- if (!threadId) throw new Error("useWorkspaceFiles: no threadId set");
1922
- const res = await fetchWithAuth(
1923
- `/threads/${threadId}/file?path=${encodeURIComponent(path)}`
1924
- );
1937
+ if (!agentId) throw new Error("useWorkspaceFiles: no agentId set");
1938
+ const query = new URLSearchParams({ path, scope: "workspace", agentId });
1939
+ const res = await fetchWithAuth(`/memory/file?${query.toString()}`);
1925
1940
  if (!res.ok) throw new Error(`Failed to read workspace file: ${res.statusText}`);
1926
1941
  const data = await res.json();
1927
1942
  const raw = data?.data ?? data;
1928
- return normalizeWorkspaceFiles({ [path]: raw })[path];
1943
+ return toWorkspaceFile(raw);
1929
1944
  },
1930
- [fetchWithAuth, threadId]
1945
+ [fetchWithAuth, agentId]
1931
1946
  );
1932
1947
  const writeFile = useCallback5(
1933
1948
  async (path, content) => {
1934
- if (!threadId) throw new Error("useWorkspaceFiles: no threadId set");
1949
+ if (!agentId) throw new Error("useWorkspaceFiles: no agentId set");
1935
1950
  setIsSaving(true);
1936
1951
  setError(null);
1937
1952
  try {
1938
- const res = await fetchWithAuth(`/threads/${threadId}/file`, {
1953
+ const res = await fetchWithAuth("/memory/file", {
1939
1954
  method: "PUT",
1940
1955
  headers: { "Content-Type": "application/json" },
1941
- body: JSON.stringify({ path, content })
1956
+ body: JSON.stringify({ path, content, scope: "workspace", agentId })
1942
1957
  });
1943
1958
  if (!res.ok) throw new Error(`Failed to write workspace file: ${res.statusText}`);
1944
1959
  const data = await res.json();
1945
1960
  const raw = data?.data ?? data;
1946
- const file = normalizeWorkspaceFiles({ [path]: raw })[path];
1961
+ const file = toWorkspaceFile(raw);
1947
1962
  setFiles((prev) => ({ ...prev, [path]: file }));
1948
1963
  return file;
1949
1964
  } catch (err) {
@@ -1954,15 +1969,13 @@ function useWorkspaceFiles(threadId, autoFetch = true) {
1954
1969
  setIsSaving(false);
1955
1970
  }
1956
1971
  },
1957
- [fetchWithAuth, threadId]
1972
+ [fetchWithAuth, agentId]
1958
1973
  );
1959
1974
  const deleteFile = useCallback5(
1960
1975
  async (path) => {
1961
- if (!threadId) throw new Error("useWorkspaceFiles: no threadId set");
1962
- const res = await fetchWithAuth(
1963
- `/threads/${threadId}/file?path=${encodeURIComponent(path)}`,
1964
- { method: "DELETE" }
1965
- );
1976
+ if (!agentId) throw new Error("useWorkspaceFiles: no agentId set");
1977
+ const query = new URLSearchParams({ path, scope: "workspace", agentId });
1978
+ const res = await fetchWithAuth(`/memory/file?${query.toString()}`, { method: "DELETE" });
1966
1979
  if (!res.ok) throw new Error(`Failed to delete workspace file: ${res.statusText}`);
1967
1980
  setFiles((prev) => {
1968
1981
  const next = { ...prev };
@@ -1970,15 +1983,15 @@ function useWorkspaceFiles(threadId, autoFetch = true) {
1970
1983
  return next;
1971
1984
  });
1972
1985
  },
1973
- [fetchWithAuth, threadId]
1986
+ [fetchWithAuth, agentId]
1974
1987
  );
1975
1988
  useEffect5(() => {
1976
- if (autoFetch && threadId) {
1989
+ if (autoFetch && agentId) {
1977
1990
  void fetchFiles();
1978
- } else if (!threadId) {
1991
+ } else if (!agentId) {
1979
1992
  setFiles({});
1980
1993
  }
1981
- }, [autoFetch, threadId, fetchFiles]);
1994
+ }, [autoFetch, agentId, fetchFiles]);
1982
1995
  return {
1983
1996
  files,
1984
1997
  isLoading,