dooers-agents-client 0.13.0 → 0.15.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/main.cjs CHANGED
@@ -24,9 +24,6 @@ function apiMessagesUrlToWebSocketUrl(url) {
24
24
  throw new Error("API Messages URL must start with http://, https://, ws://, or wss://");
25
25
  }
26
26
 
27
- // src/version.ts
28
- var PACKAGE_VERSION = "0.13.0";
29
-
30
27
  // src/types.ts
31
28
  function isSettingsFieldGroup(item) {
32
29
  return "fields" in item && Array.isArray(item.fields);
@@ -171,6 +168,34 @@ function toFormResponseEventData(data) {
171
168
  values: data.values ?? {}
172
169
  };
173
170
  }
171
+ function toChartSeries(w) {
172
+ return {
173
+ key: w.key,
174
+ label: w.label ?? null,
175
+ color: w.color ?? null
176
+ };
177
+ }
178
+ function toChartEventData(data) {
179
+ const series = data.series ?? [];
180
+ return {
181
+ title: data.title ?? "",
182
+ message: data.message ?? "",
183
+ chartType: data.chart_type ?? "bar",
184
+ size: data.size ?? "medium",
185
+ xKey: data.x_key ?? "",
186
+ yKeys: data.y_keys ?? [],
187
+ data: data.data ?? [],
188
+ series: series.map(
189
+ (item) => toChartSeries({
190
+ key: item.key ?? "",
191
+ label: item.label ?? null,
192
+ color: item.color ?? null
193
+ })
194
+ ),
195
+ xLabel: data.x_label ?? null,
196
+ yLabel: data.y_label ?? null
197
+ };
198
+ }
174
199
  function toThreadEvent(w) {
175
200
  return {
176
201
  id: w.id,
@@ -186,6 +211,20 @@ function toThreadEvent(w) {
186
211
  clientEventId: w.client_event_id
187
212
  };
188
213
  }
214
+ function toThreadArtifact(w) {
215
+ return {
216
+ eventId: w.event_id,
217
+ direction: w.direction,
218
+ kind: w.kind,
219
+ filename: w.filename,
220
+ mimeType: w.mime_type,
221
+ url: w.url,
222
+ refId: w.ref_id,
223
+ createdAt: w.created_at,
224
+ userId: w.user_id,
225
+ userName: w.user_name
226
+ };
227
+ }
189
228
  function toRun(w) {
190
229
  return {
191
230
  id: w.id,
@@ -282,10 +321,14 @@ function toWireContentPart(p) {
282
321
  }
283
322
  }
284
323
 
324
+ // src/version.ts
325
+ var PACKAGE_VERSION = "0.15.0";
326
+
285
327
  // src/client.ts
286
328
  var MAX_RECONNECT_ATTEMPTS = 5;
287
329
  var RECONNECT_DELAYS = [1e3, 2e3, 4e3, 8e3, 16e3];
288
330
  var SEND_MESSAGE_TIMEOUT = 3e4;
331
+ var ARTIFACTS_LIST_TIMEOUT = 3e4;
289
332
  var PING_INTERVAL_MS = 3e4;
290
333
  function blobPartFilename(blob, override) {
291
334
  const o = (override ?? "").trim();
@@ -439,6 +482,7 @@ var AgentClient = class {
439
482
  pendingOptimistic = /* @__PURE__ */ new Map();
440
483
  // Pending message promises — keyed by outbound frame id (same as client_event_id for sends).
441
484
  pendingMessages = /* @__PURE__ */ new Map();
485
+ pendingArtifactsRequests = /* @__PURE__ */ new Map();
442
486
  // Track last event ID per thread for gap recovery on reconnect
443
487
  lastEventIds = /* @__PURE__ */ new Map();
444
488
  // Pagination
@@ -576,6 +620,13 @@ var AgentClient = class {
576
620
  }
577
621
  this.pendingMessages.clear();
578
622
  }
623
+ abortPendingArtifacts(reason) {
624
+ for (const [frameId, pending] of this.pendingArtifactsRequests) {
625
+ clearTimeout(pending.timer);
626
+ this.pendingArtifactsRequests.delete(frameId);
627
+ pending.reject(new Error(reason));
628
+ }
629
+ }
579
630
  disconnect() {
580
631
  this.isIntentionallyClosed = true;
581
632
  this.stopHeartbeat();
@@ -584,6 +635,7 @@ var AgentClient = class {
584
635
  this.reconnectTimer = null;
585
636
  }
586
637
  this.abortPendingMessages("Disconnected");
638
+ this.abortPendingArtifacts("Disconnected");
587
639
  if (this.ws) {
588
640
  this.ws.onopen = null;
589
641
  this.ws.onmessage = null;
@@ -642,6 +694,40 @@ var AgentClient = class {
642
694
  limit
643
695
  });
644
696
  }
697
+ requestThreadArtifactsList(threadId, options) {
698
+ if (!this.isConnected()) {
699
+ return Promise.reject(new Error("Not connected"));
700
+ }
701
+ const frameId = crypto.randomUUID();
702
+ return new Promise((resolve, reject) => {
703
+ const timer = setTimeout(() => {
704
+ this.pendingArtifactsRequests.delete(frameId);
705
+ reject(new Error("thread.artifacts.list timed out"));
706
+ }, ARTIFACTS_LIST_TIMEOUT);
707
+ this.pendingArtifactsRequests.set(frameId, {
708
+ threadId,
709
+ resolve: (value) => {
710
+ clearTimeout(timer);
711
+ resolve(value);
712
+ },
713
+ reject: (err) => {
714
+ clearTimeout(timer);
715
+ reject(err);
716
+ },
717
+ timer
718
+ });
719
+ this.sendRaw({
720
+ id: frameId,
721
+ type: "thread.artifacts.list",
722
+ payload: {
723
+ thread_id: threadId,
724
+ cursor: options?.cursor ?? null,
725
+ limit: options?.limit,
726
+ direction: options?.direction ?? "all"
727
+ }
728
+ });
729
+ });
730
+ }
645
731
  // --- Settings ---
646
732
  subscribeSettings(options) {
647
733
  const audience = options?.audience ?? "user";
@@ -887,6 +973,13 @@ var AgentClient = class {
887
973
  pending.reject(new Error(msg));
888
974
  this.callbacks.setSendError(msg);
889
975
  }
976
+ const artifactsPending = this.pendingArtifactsRequests.get(ackId);
977
+ if (artifactsPending) {
978
+ clearTimeout(artifactsPending.timer);
979
+ this.pendingArtifactsRequests.delete(ackId);
980
+ const msg = err.message || "Request rejected";
981
+ artifactsPending.reject(new Error(msg));
982
+ }
890
983
  }
891
984
  this.onError?.({
892
985
  code: err.code,
@@ -971,6 +1064,21 @@ var AgentClient = class {
971
1064
  );
972
1065
  break;
973
1066
  }
1067
+ case "thread.artifacts.list.result": {
1068
+ const threadId = frame.payload.thread_id;
1069
+ for (const [frameId, pending] of this.pendingArtifactsRequests) {
1070
+ if (pending.threadId !== threadId) continue;
1071
+ clearTimeout(pending.timer);
1072
+ this.pendingArtifactsRequests.delete(frameId);
1073
+ pending.resolve({
1074
+ artifacts: this.resolveArtifactUrls(frame.payload.artifacts.map(toThreadArtifact)),
1075
+ cursor: frame.payload.cursor,
1076
+ hasMore: frame.payload.has_more
1077
+ });
1078
+ break;
1079
+ }
1080
+ break;
1081
+ }
974
1082
  case "thread.upsert":
975
1083
  this.callbacks.onThreadUpsert(toThread(frame.payload.thread));
976
1084
  break;
@@ -1032,6 +1140,7 @@ var AgentClient = class {
1032
1140
  this.stopHeartbeat();
1033
1141
  if (this.reconnectAttempts >= MAX_RECONNECT_ATTEMPTS) {
1034
1142
  this.abortPendingMessages("Connection lost after maximum retries");
1143
+ this.abortPendingArtifacts("Connection lost after maximum retries");
1035
1144
  this.callbacks.setReconnectFailed();
1036
1145
  this.callbacks.setConnectionStatus("error", "Connection lost after maximum retries");
1037
1146
  return;
@@ -1076,6 +1185,14 @@ var AgentClient = class {
1076
1185
  };
1077
1186
  });
1078
1187
  }
1188
+ resolveArtifactUrls(artifacts) {
1189
+ if (!this.httpBaseUrl) return artifacts;
1190
+ const base = this.httpBaseUrl;
1191
+ return artifacts.map((artifact) => {
1192
+ if (!artifact.url?.startsWith("/")) return artifact;
1193
+ return { ...artifact, url: `${base}${artifact.url}` };
1194
+ });
1195
+ }
1079
1196
  };
1080
1197
  function mergeDisplayContentParts(prev, next) {
1081
1198
  if (!next?.length) return prev;
@@ -1997,6 +2114,60 @@ function useThreadEvents(threadId) {
1997
2114
  );
1998
2115
  return { hasOlderEvents, loadOlderEvents };
1999
2116
  }
2117
+ function useThreadArtifacts(threadId, options) {
2118
+ const { client } = useAgentContext();
2119
+ const direction = options?.direction ?? "all";
2120
+ const enabled = options?.enabled !== false;
2121
+ const limit = options?.limit;
2122
+ const [artifacts, setArtifacts] = react.useState([]);
2123
+ const [cursor, setCursor] = react.useState(null);
2124
+ const [hasMore, setHasMore] = react.useState(false);
2125
+ const [isLoading, setIsLoading] = react.useState(false);
2126
+ const [error, setError] = react.useState(null);
2127
+ const cursorRef = react.useRef(null);
2128
+ const load = react.useCallback(
2129
+ async (append) => {
2130
+ if (!threadId) return;
2131
+ setIsLoading(true);
2132
+ setError(null);
2133
+ try {
2134
+ const result = await client.requestThreadArtifactsList(threadId, {
2135
+ cursor: append ? cursorRef.current : null,
2136
+ limit,
2137
+ direction
2138
+ });
2139
+ cursorRef.current = result.cursor;
2140
+ setCursor(result.cursor);
2141
+ setHasMore(result.hasMore);
2142
+ setArtifacts((prev) => append ? [...prev, ...result.artifacts] : result.artifacts);
2143
+ } catch (err) {
2144
+ setError(err instanceof Error ? err.message : "Failed to load artifacts");
2145
+ } finally {
2146
+ setIsLoading(false);
2147
+ }
2148
+ },
2149
+ [threadId, client, limit, direction]
2150
+ );
2151
+ react.useEffect(() => {
2152
+ if (!threadId || !enabled) {
2153
+ setArtifacts([]);
2154
+ setCursor(null);
2155
+ cursorRef.current = null;
2156
+ setHasMore(false);
2157
+ setError(null);
2158
+ return;
2159
+ }
2160
+ void load(false);
2161
+ }, [threadId, enabled, direction, load]);
2162
+ const loadMore = react.useCallback(() => {
2163
+ if (!hasMore || isLoading) return;
2164
+ void load(true);
2165
+ }, [hasMore, isLoading, load]);
2166
+ const refresh = react.useCallback(() => {
2167
+ void load(false);
2168
+ }, [load]);
2169
+ return { artifacts, cursor, hasMore, isLoading, error, loadMore, refresh };
2170
+ }
2000
2171
  function useThreadsList() {
2001
2172
  const threadOrder = useStore((s) => s.threadOrder);
2002
2173
  const threadMap = useStore((s) => s.threads);
@@ -2045,6 +2216,7 @@ exports.AgentServerClient = AgentServerClient;
2045
2216
  exports.PACKAGE_VERSION = PACKAGE_VERSION;
2046
2217
  exports.apiMessagesUrlToWebSocketUrl = apiMessagesUrlToWebSocketUrl;
2047
2218
  exports.isSettingsFieldGroup = isSettingsFieldGroup;
2219
+ exports.toChartEventData = toChartEventData;
2048
2220
  exports.toFormElement = toFormElement;
2049
2221
  exports.toFormEventData = toFormEventData;
2050
2222
  exports.toFormResponseEventData = toFormResponseEventData;
@@ -2058,6 +2230,7 @@ exports.useFormFileUpload = useFormFileUpload;
2058
2230
  exports.useMessage = useMessage;
2059
2231
  exports.useSettings = useSettings;
2060
2232
  exports.useSettingsFileUpload = useSettingsFileUpload;
2233
+ exports.useThreadArtifacts = useThreadArtifacts;
2061
2234
  exports.useThreadDetails = useThreadDetails;
2062
2235
  exports.useThreadEvents = useThreadEvents;
2063
2236
  exports.useThreadsActions = useThreadsActions;