dooers-agents-client 0.3.0 → 0.4.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/README.md CHANGED
@@ -12,21 +12,21 @@ Peer dependency: `react >= 18`
12
12
 
13
13
  ## Quick Start
14
14
 
15
- Wrap your component tree in `WorkerProvider`, then use hooks anywhere inside.
15
+ Wrap your component tree in `AgentProvider`, then use hooks anywhere inside.
16
16
 
17
17
  ```tsx
18
- import { WorkerProvider, useConnection, useThreadDetails, useMessage } from "dooers-agents-client"
18
+ import { AgentProvider, useConnection, useThreadDetails, useMessage } from "dooers-agents-client"
19
19
 
20
20
  function App() {
21
21
  return (
22
- <WorkerProvider
22
+ <AgentProvider
23
23
  url="ws://localhost:8000/ws"
24
- workerId="worker-1"
24
+ agentId="agent-1"
25
25
  userId="user-1"
26
26
  userName="Alice"
27
27
  >
28
28
  <Chat threadId="thread-1" />
29
- </WorkerProvider>
29
+ </AgentProvider>
30
30
  )
31
31
  }
32
32
 
@@ -60,12 +60,12 @@ function Chat({ threadId }: { threadId: string }) {
60
60
 
61
61
  ## Provider
62
62
 
63
- `WorkerProvider` manages the WebSocket lifecycle. On mount it connects, on unmount it disconnects. When any prop changes, the connection resets.
63
+ `AgentProvider` manages the WebSocket lifecycle. On mount it connects, on unmount it disconnects. When any prop changes, the connection resets.
64
64
 
65
65
  ```tsx
66
- <WorkerProvider
66
+ <AgentProvider
67
67
  url="ws://localhost:8000/ws" // WebSocket endpoint
68
- workerId="worker-1" // Worker to connect to
68
+ agentId="agent-1" // Agent to connect to
69
69
  organizationId="org-1" // Context passed to handler
70
70
  workspaceId="ws-1"
71
71
  userId="user-1"
@@ -78,14 +78,14 @@ function Chat({ threadId }: { threadId: string }) {
78
78
  onError={(err) => console.error(err.code, err.message)}
79
79
  >
80
80
  {children}
81
- </WorkerProvider>
81
+ </AgentProvider>
82
82
  ```
83
83
 
84
84
  All props except `children` and `onError` are primitive strings, so React can diff them cheaply.
85
85
 
86
86
  ## Hooks
87
87
 
88
- All hooks must be called inside a `WorkerProvider`.
88
+ All hooks must be called inside a `AgentProvider`.
89
89
 
90
90
  ### useConnection
91
91
 
@@ -121,7 +121,7 @@ if (hasOlderEvents) {
121
121
 
122
122
  ### useThreadsList
123
123
 
124
- Read-only thread list for the connected worker.
124
+ Read-only thread list for the connected agent.
125
125
 
126
126
  ```tsx
127
127
  const { threads, isLoading, hasMore, totalCount } = useThreadsList()
@@ -190,7 +190,7 @@ useEffect(() => {
190
190
 
191
191
  ### useSettings
192
192
 
193
- Worker settings with real-time sync across clients.
193
+ Agent settings with real-time sync across clients.
194
194
 
195
195
  ```tsx
196
196
  const { fields, updatedAt, isLoading, subscribe, unsubscribe, patchField } = useSettings()
@@ -215,7 +215,7 @@ All public types are camelCase. The SDK transforms the wire format (snake_case)
215
215
  ```typescript
216
216
  import type {
217
217
  User, // { userId, userName, userEmail, systemRole, organizationRole, workspaceRole }
218
- Thread, // { id, workerId, organizationId, workspaceId, owner, users, title, ... }
218
+ Thread, // { id, agentId, organizationId, workspaceId, owner, users, title, ... }
219
219
  ThreadEvent, // { id, threadId, type, actor, author, user, content, data, createdAt, ... }
220
220
  Run, // { id, threadId, agentId, status, startedAt, endedAt, error }
221
221
  ContentPart, // TextPart | ImagePart | DocumentPart
@@ -238,9 +238,9 @@ import { isSettingsFieldGroup } from "dooers-agents-client" // type guard
238
238
  ## Architecture
239
239
 
240
240
  ```
241
- WorkerProvider
242
- ├── WorkerClient WebSocket lifecycle, reconnection, optimistic events
243
- └── WorkerStore Zustand vanilla store
241
+ AgentProvider
242
+ ├── AgentClient WebSocket lifecycle, reconnection, optimistic events
243
+ └── AgentStore Zustand vanilla store
244
244
  ├── connection { status, error, reconnectFailed }
245
245
  ├── threads Record<id, Thread>
246
246
  ├── events Record<threadId, ThreadEvent[]>
package/dist/main.cjs CHANGED
@@ -27,7 +27,7 @@ function toUser(w) {
27
27
  function toThread(w) {
28
28
  return {
29
29
  id: w.id,
30
- workerId: w.worker_id,
30
+ agentId: w.agent_id,
31
31
  organizationId: w.organization_id,
32
32
  workspaceId: w.workspace_id,
33
33
  owner: toUser(w.owner),
@@ -187,7 +187,9 @@ function toSettingsField(w) {
187
187
  rows: w.rows,
188
188
  src: w.src,
189
189
  width: w.width,
190
- height: w.height
190
+ height: w.height,
191
+ uploadUrl: w.upload_url,
192
+ accept: w.accept
191
193
  };
192
194
  }
193
195
  function toSettingsItem(w) {
@@ -206,7 +208,7 @@ function toAnalyticsEvent(w) {
206
208
  return {
207
209
  event: w.event,
208
210
  timestamp: w.timestamp,
209
- workerId: w.worker_id,
211
+ agentId: w.agent_id,
210
212
  threadId: w.thread_id,
211
213
  userId: w.user_id,
212
214
  runId: w.run_id,
@@ -231,13 +233,13 @@ function toWireContentPart(p) {
231
233
  var MAX_RECONNECT_ATTEMPTS = 5;
232
234
  var RECONNECT_DELAYS = [1e3, 2e3, 4e3, 8e3, 16e3];
233
235
  var SEND_MESSAGE_TIMEOUT = 3e4;
234
- var WorkerClient = class {
236
+ var AgentClient = class {
235
237
  ws = null;
236
238
  callbacks;
237
239
  onError = null;
238
240
  url = "";
239
241
  httpBaseUrl = "";
240
- workerId = "";
242
+ agentId = "";
241
243
  uploadUrl;
242
244
  config = {
243
245
  organizationId: "",
@@ -296,9 +298,9 @@ var WorkerClient = class {
296
298
  sizeBytes: result.size_bytes
297
299
  };
298
300
  }
299
- connect(url, workerId, config) {
301
+ connect(url, agentId, config) {
300
302
  this.url = url;
301
- this.workerId = workerId;
303
+ this.agentId = agentId;
302
304
  this.config = config ?? { organizationId: "", workspaceId: "", userId: "" };
303
305
  this.isIntentionallyClosed = false;
304
306
  try {
@@ -384,10 +386,10 @@ var WorkerClient = class {
384
386
  }
385
387
  // --- Settings ---
386
388
  subscribeSettings() {
387
- this.send("settings.subscribe", { worker_id: this.workerId });
389
+ this.send("settings.subscribe", { agent_id: this.agentId });
388
390
  }
389
391
  unsubscribeSettings() {
390
- this.send("settings.unsubscribe", { worker_id: this.workerId });
392
+ this.send("settings.unsubscribe", { agent_id: this.agentId });
391
393
  }
392
394
  patchSetting(fieldId, value) {
393
395
  this.send("settings.patch", { field_id: fieldId, value });
@@ -404,10 +406,10 @@ var WorkerClient = class {
404
406
  }
405
407
  // --- Analytics ---
406
408
  subscribeAnalytics() {
407
- this.send("analytics.subscribe", { worker_id: this.workerId });
409
+ this.send("analytics.subscribe", { agent_id: this.agentId });
408
410
  }
409
411
  unsubscribeAnalytics() {
410
- this.send("analytics.unsubscribe", { worker_id: this.workerId });
412
+ this.send("analytics.unsubscribe", { agent_id: this.agentId });
411
413
  }
412
414
  // --- Messaging ---
413
415
  sendMessage(params) {
@@ -527,7 +529,7 @@ var WorkerClient = class {
527
529
  id: this.connectFrameId,
528
530
  type: "connect",
529
531
  payload: {
530
- worker_id: this.workerId,
532
+ agent_id: this.agentId,
531
533
  organization_id: this.config.organizationId ?? "",
532
534
  workspace_id: this.config.workspaceId ?? "",
533
535
  user: {
@@ -726,7 +728,7 @@ function extractFormStates(events, existing) {
726
728
  }
727
729
  return result;
728
730
  }
729
- function createWorkerStore() {
731
+ function createAgentStore() {
730
732
  return vanilla.createStore()((set) => ({
731
733
  connection: {
732
734
  status: "idle",
@@ -1063,10 +1065,10 @@ function createWorkerStore() {
1063
1065
  }
1064
1066
  }));
1065
1067
  }
1066
- var WorkerContext = react.createContext(null);
1067
- function WorkerProvider({
1068
+ var AgentContext = react.createContext(null);
1069
+ function AgentProvider({
1068
1070
  url,
1069
- workerId,
1071
+ agentId,
1070
1072
  organizationId,
1071
1073
  workspaceId,
1072
1074
  userId,
@@ -1084,8 +1086,8 @@ function WorkerProvider({
1084
1086
  const storeRef = react.useRef(void 0);
1085
1087
  const clientRef = react.useRef(void 0);
1086
1088
  if (!storeRef.current) {
1087
- storeRef.current = createWorkerStore();
1088
- clientRef.current = new WorkerClient(storeRef.current.getState().actions);
1089
+ storeRef.current = createAgentStore();
1090
+ clientRef.current = new AgentClient(storeRef.current.getState().actions);
1089
1091
  }
1090
1092
  react.useEffect(() => {
1091
1093
  clientRef.current?.setOnError(onError ?? null);
@@ -1095,8 +1097,8 @@ function WorkerProvider({
1095
1097
  }, [uploadUrl]);
1096
1098
  const identityIdsKey = identityIds?.join(",") ?? "";
1097
1099
  react.useEffect(() => {
1098
- if (!url || !workerId) return;
1099
- clientRef.current?.connect(url, workerId, {
1100
+ if (!url || !agentId) return;
1101
+ clientRef.current?.connect(url, agentId, {
1100
1102
  organizationId,
1101
1103
  workspaceId,
1102
1104
  userId,
@@ -1111,7 +1113,7 @@ function WorkerProvider({
1111
1113
  return () => clientRef.current?.disconnect();
1112
1114
  }, [
1113
1115
  url,
1114
- workerId,
1116
+ agentId,
1115
1117
  organizationId,
1116
1118
  workspaceId,
1117
1119
  userId,
@@ -1127,27 +1129,27 @@ function WorkerProvider({
1127
1129
  () => ({ store: storeRef.current, client: clientRef.current }),
1128
1130
  []
1129
1131
  );
1130
- return /* @__PURE__ */ jsxRuntime.jsx(WorkerContext.Provider, { value: contextValue, children });
1132
+ return /* @__PURE__ */ jsxRuntime.jsx(AgentContext.Provider, { value: contextValue, children });
1131
1133
  }
1132
- function useWorkerContext() {
1133
- const ctx = react.useContext(WorkerContext);
1134
+ function useAgentContext() {
1135
+ const ctx = react.useContext(AgentContext);
1134
1136
  if (!ctx) {
1135
- throw new Error("useWorkerContext must be used within a <WorkerProvider>");
1137
+ throw new Error("useAgentContext must be used within a <AgentProvider>");
1136
1138
  }
1137
1139
  return ctx;
1138
1140
  }
1139
1141
  function useStore(selector) {
1140
- const { store } = useWorkerContext();
1142
+ const { store } = useAgentContext();
1141
1143
  return zustand.useStore(store, selector);
1142
1144
  }
1143
1145
  function useShallowStore(selector) {
1144
- const { store } = useWorkerContext();
1146
+ const { store } = useAgentContext();
1145
1147
  return zustand.useStore(store, shallow.useShallow(selector));
1146
1148
  }
1147
1149
 
1148
1150
  // src/hooks/use-analytics.ts
1149
1151
  function useAnalytics() {
1150
- const { client } = useWorkerContext();
1152
+ const { client } = useAgentContext();
1151
1153
  const events = useShallowStore((s) => s.analytics.events);
1152
1154
  const counters = useShallowStore((s) => s.analytics.counters);
1153
1155
  const subscribe = react.useCallback(() => client.subscribeAnalytics(), [client]);
@@ -1259,7 +1261,7 @@ function useAudioRecorder() {
1259
1261
  return { start, stop, cancel, isRecording, duration, analyserNode: analyserRef.current };
1260
1262
  }
1261
1263
  function useConnection() {
1262
- const { client } = useWorkerContext();
1264
+ const { client } = useAgentContext();
1263
1265
  const status = useStore((s) => s.connection.status);
1264
1266
  const error = useStore((s) => s.connection.error);
1265
1267
  const reconnectFailed = useStore((s) => s.connection.reconnectFailed);
@@ -1267,7 +1269,7 @@ function useConnection() {
1267
1269
  return { status, error, reconnectFailed, reconnect };
1268
1270
  }
1269
1271
  function useFeedback(targetId, targetType = "event") {
1270
- const { client } = useWorkerContext();
1272
+ const { client } = useAgentContext();
1271
1273
  const feedback = useStore((s) => s.feedback[targetId] ?? null);
1272
1274
  const like = react.useCallback(
1273
1275
  (reason, classification) => client.sendFeedback(targetType, targetId, "like", reason, classification),
@@ -1280,7 +1282,7 @@ function useFeedback(targetId, targetType = "event") {
1280
1282
  return { feedback, like, dislike };
1281
1283
  }
1282
1284
  function useForm(formEventId, formData, threadId) {
1283
- const { client, store } = useWorkerContext();
1285
+ const { client, store } = useAgentContext();
1284
1286
  const formState = useStore((s) => s.formStates[formEventId]);
1285
1287
  const [errors, setErrors] = react.useState({});
1286
1288
  react.useEffect(() => {
@@ -1422,7 +1424,7 @@ function useFormFileUpload() {
1422
1424
  return { upload, isUploading, error, clearError };
1423
1425
  }
1424
1426
  function useMessage() {
1425
- const { client } = useWorkerContext();
1427
+ const { client } = useAgentContext();
1426
1428
  const send = react.useCallback(
1427
1429
  (params) => {
1428
1430
  return client.sendMessage(params);
@@ -1432,7 +1434,7 @@ function useMessage() {
1432
1434
  return { send };
1433
1435
  }
1434
1436
  function useSettings() {
1435
- const { client } = useWorkerContext();
1437
+ const { client } = useAgentContext();
1436
1438
  const fields = useShallowStore((s) => s.settings.fields);
1437
1439
  const updatedAt = useStore((s) => s.settings.updatedAt);
1438
1440
  const isLoading = useStore((s) => s.settings.isLoading);
@@ -1444,10 +1446,45 @@ function useSettings() {
1444
1446
  );
1445
1447
  return { fields, updatedAt, isLoading, subscribe, unsubscribe, patchField };
1446
1448
  }
1449
+ function useSettingsFileUpload() {
1450
+ const [isUploading, setIsUploading] = react.useState(false);
1451
+ const [error, setError] = react.useState(null);
1452
+ const upload = react.useCallback(
1453
+ async (params) => {
1454
+ setIsUploading(true);
1455
+ setError(null);
1456
+ try {
1457
+ const formData = new FormData();
1458
+ formData.append("file", params.file);
1459
+ formData.append("source", "settings");
1460
+ formData.append("field_id", params.fieldId);
1461
+ formData.append("agent_id", params.agentId);
1462
+ const response = await fetch(params.uploadUrl, {
1463
+ method: "POST",
1464
+ body: formData
1465
+ });
1466
+ if (!response.ok) {
1467
+ const detail = await response.text().catch(() => "");
1468
+ throw new Error(detail || `Upload failed (${response.status})`);
1469
+ }
1470
+ return await response.json();
1471
+ } catch (err) {
1472
+ const message = err instanceof Error ? err.message : "Upload failed";
1473
+ setError(message);
1474
+ throw err;
1475
+ } finally {
1476
+ setIsUploading(false);
1477
+ }
1478
+ },
1479
+ []
1480
+ );
1481
+ const clearError = react.useCallback(() => setError(null), []);
1482
+ return { upload, isUploading, error, clearError };
1483
+ }
1447
1484
  var EMPTY_ARRAY = [];
1448
1485
  var EMPTY_RUNS = [];
1449
1486
  function useThreadDetails(threadId) {
1450
- const { client } = useWorkerContext();
1487
+ const { client } = useAgentContext();
1451
1488
  react.useEffect(() => {
1452
1489
  if (!threadId) return;
1453
1490
  client.subscribe(threadId);
@@ -1472,7 +1509,7 @@ function useThreadDetails(threadId) {
1472
1509
  return { thread, events, runs, isLoading, isWaiting };
1473
1510
  }
1474
1511
  function useThreadEvents(threadId) {
1475
- const { client } = useWorkerContext();
1512
+ const { client } = useAgentContext();
1476
1513
  const hasOlderEvents = useStore(
1477
1514
  (s) => threadId ? s.eventPagination[threadId]?.hasMore ?? false : false
1478
1515
  );
@@ -1500,13 +1537,13 @@ function useThreadsList() {
1500
1537
  return { threads, isLoading, hasMore, totalCount };
1501
1538
  }
1502
1539
  function useThreadsActions() {
1503
- const { client } = useWorkerContext();
1540
+ const { client } = useAgentContext();
1504
1541
  const deleteThread = react.useCallback((threadId) => client.deleteThread(threadId), [client]);
1505
1542
  const loadMore = react.useCallback((limit) => client.loadMoreThreads(limit), [client]);
1506
1543
  return { deleteThread, loadMore };
1507
1544
  }
1508
1545
  function useUpload() {
1509
- const { client } = useWorkerContext();
1546
+ const { client } = useAgentContext();
1510
1547
  const [isUploading, setIsUploading] = react.useState(false);
1511
1548
  const activeCountRef = react.useRef(0);
1512
1549
  const upload = react.useCallback(
@@ -1527,7 +1564,7 @@ function useUpload() {
1527
1564
  return { upload, isUploading };
1528
1565
  }
1529
1566
 
1530
- exports.WorkerProvider = WorkerProvider;
1567
+ exports.AgentProvider = AgentProvider;
1531
1568
  exports.isSettingsFieldGroup = isSettingsFieldGroup;
1532
1569
  exports.toFormElement = toFormElement;
1533
1570
  exports.toFormEventData = toFormEventData;
@@ -1540,6 +1577,7 @@ exports.useForm = useForm;
1540
1577
  exports.useFormFileUpload = useFormFileUpload;
1541
1578
  exports.useMessage = useMessage;
1542
1579
  exports.useSettings = useSettings;
1580
+ exports.useSettingsFileUpload = useSettingsFileUpload;
1543
1581
  exports.useThreadDetails = useThreadDetails;
1544
1582
  exports.useThreadEvents = useThreadEvents;
1545
1583
  exports.useThreadsActions = useThreadsActions;