@copilotz/admin 0.9.37 → 0.9.38

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.cjs CHANGED
@@ -159,6 +159,21 @@ function normalizeMessagePage(payload) {
159
159
  const pageInfo = isRecord(candidate) ? normalizeMessagePageInfo(candidate.pageInfo, data) : normalizeMessagePageInfo(void 0, data);
160
160
  return { data, pageInfo };
161
161
  }
162
+ function isQueueEvent(value) {
163
+ return isRecord(value) && typeof value.id === "string" && typeof value.threadId === "string" && typeof value.eventType === "string";
164
+ }
165
+ function normalizeQueueEvent(value) {
166
+ if (isQueueEvent(value)) return value;
167
+ if (isRecord(value) && isQueueEvent(value.data)) return value.data;
168
+ return void 0;
169
+ }
170
+ function normalizeQueueEvents(value) {
171
+ if (Array.isArray(value)) return value.filter(isQueueEvent);
172
+ if (isRecord(value) && Array.isArray(value.data)) {
173
+ return value.data.filter(isQueueEvent);
174
+ }
175
+ return [];
176
+ }
162
177
  function createAdminClient(options = {}) {
163
178
  const baseUrl = resolveBaseUrl(options.baseUrl);
164
179
  const paths = { ...DEFAULT_PATHS, ...options.paths };
@@ -265,9 +280,25 @@ function createAdminClient(options = {}) {
265
280
  );
266
281
  return normalizeMessagePage(payload);
267
282
  },
268
- getThreadEvent: async (threadId) => await requestJson(
269
- `${paths.threadsBase}/${encodeURIComponent(threadId)}/events`
270
- ),
283
+ listEvents: async (eventOptions = {}) => {
284
+ const payload = await requestJson(`${paths.adminBase}/events`, {
285
+ namespace: eventOptions.namespace,
286
+ threadId: eventOptions.threadId,
287
+ status: eventOptions.status,
288
+ eventType: eventOptions.eventType,
289
+ traceId: eventOptions.traceId,
290
+ search: eventOptions.search,
291
+ limit: String(eventOptions.limit ?? 50),
292
+ offset: eventOptions.offset ? String(eventOptions.offset) : void 0
293
+ });
294
+ return normalizeQueueEvents(payload);
295
+ },
296
+ getThreadEvent: async (threadId) => {
297
+ const payload = await requestJson(
298
+ `${paths.threadsBase}/${encodeURIComponent(threadId)}/events`
299
+ );
300
+ return normalizeQueueEvent(payload);
301
+ },
271
302
  listCollections: async () => await requestJson(paths.collectionsBase),
272
303
  listCollectionItems: async (collection, listOptions = {}) => await requestJson(
273
304
  `${paths.collectionsBase}/${encodeURIComponent(collection)}`,
@@ -2258,33 +2289,61 @@ function eventsModule() {
2258
2289
  }]
2259
2290
  };
2260
2291
  }
2292
+ var EVENT_STATUSES = [
2293
+ "all",
2294
+ "pending",
2295
+ "processing",
2296
+ "completed",
2297
+ "failed",
2298
+ "expired",
2299
+ "overwritten"
2300
+ ];
2261
2301
  function EventsPage({ context }) {
2262
2302
  const [threadId, setThreadId] = import_react4.default.useState("");
2263
- const [status, setStatus] = import_react4.default.useState("");
2264
- const [type, setType] = import_react4.default.useState("");
2303
+ const [status, setStatus] = import_react4.default.useState(
2304
+ "all"
2305
+ );
2306
+ const [eventType, setEventType] = import_react4.default.useState("");
2265
2307
  const [traceId, setTraceId] = import_react4.default.useState("");
2266
- const [event, setEvent] = import_react4.default.useState(null);
2308
+ const [events, setEvents] = import_react4.default.useState([]);
2309
+ const [selectedEvent, setSelectedEvent] = import_react4.default.useState(null);
2267
2310
  const [error, setError] = import_react4.default.useState(null);
2268
- const [hasSearched, setHasSearched] = import_react4.default.useState(false);
2311
+ const [loading, setLoading] = import_react4.default.useState(false);
2312
+ const [hasLoaded, setHasLoaded] = import_react4.default.useState(false);
2269
2313
  const inspect = async () => {
2270
- if (!threadId.trim()) return;
2271
- setHasSearched(true);
2314
+ setHasLoaded(true);
2315
+ setLoading(true);
2272
2316
  setError(null);
2273
2317
  try {
2274
- const next = await context.client.getThreadEvent(threadId.trim());
2275
- setEvent(next ?? null);
2318
+ const next = await context.client.listEvents({
2319
+ namespace: context.scope.namespace || void 0,
2320
+ threadId: threadId.trim() || void 0,
2321
+ status: status === "all" ? void 0 : status,
2322
+ eventType: eventType.trim() || void 0,
2323
+ traceId: traceId.trim() || void 0,
2324
+ limit: 50
2325
+ });
2326
+ setEvents(next);
2327
+ setSelectedEvent(
2328
+ (current) => current && next.some((event) => event.id === current.id) ? current : next[0] ?? null
2329
+ );
2276
2330
  } catch (cause) {
2277
2331
  setError(cause instanceof Error ? cause.message : "Failed to load event");
2278
- setEvent(null);
2332
+ setEvents([]);
2333
+ setSelectedEvent(null);
2334
+ } finally {
2335
+ setLoading(false);
2279
2336
  }
2280
2337
  };
2281
- const rows = event && (!status || event.status.includes(status)) && (!type || event.eventType.includes(type)) && (!traceId || event.traceId?.includes(traceId)) ? [event] : [];
2338
+ import_react4.default.useEffect(() => {
2339
+ void inspect();
2340
+ }, [context.client, context.refreshKey, context.scope.namespace]);
2282
2341
  return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "space-y-4", children: [
2283
2342
  /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
2284
2343
  PageHeader,
2285
2344
  {
2286
2345
  title: "Events",
2287
- description: "Queue and event inspection. Current backend support is thread-focused; filters are ready for broader event listing."
2346
+ description: "Queue and event inspection across the active namespace."
2288
2347
  }
2289
2348
  ),
2290
2349
  /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(
@@ -2293,13 +2352,13 @@ function EventsPage({ context }) {
2293
2352
  actions: /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(
2294
2353
  Button,
2295
2354
  {
2296
- disabled: !threadId.trim(),
2355
+ disabled: loading,
2297
2356
  onClick: () => void inspect(),
2298
2357
  size: "sm",
2299
2358
  type: "button",
2300
2359
  children: [
2301
2360
  /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_lucide_react8.Search, { className: "size-3" }),
2302
- "Inspect"
2361
+ loading ? "Loading" : "Inspect"
2303
2362
  ]
2304
2363
  }
2305
2364
  ),
@@ -2308,37 +2367,45 @@ function EventsPage({ context }) {
2308
2367
  Input,
2309
2368
  {
2310
2369
  className: "h-8 w-[220px]",
2311
- onChange: (event2) => setThreadId(event2.target.value),
2312
- onKeyDown: (event2) => {
2313
- if (event2.key === "Enter") void inspect();
2370
+ onChange: (event) => setThreadId(event.target.value),
2371
+ onKeyDown: (event) => {
2372
+ if (event.key === "Enter") void inspect();
2314
2373
  },
2315
2374
  placeholder: "Thread ID",
2316
2375
  value: threadId
2317
2376
  }
2318
2377
  ),
2319
- /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
2320
- Input,
2378
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(
2379
+ Select,
2321
2380
  {
2322
- className: "h-8 w-[150px]",
2323
- onChange: (event2) => setStatus(event2.target.value),
2324
- placeholder: "Status",
2325
- value: status
2381
+ value: status,
2382
+ onValueChange: (value) => setStatus(value),
2383
+ children: [
2384
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(SelectTrigger, { className: "h-8 w-[150px] text-xs", "aria-label": "Status", children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(SelectValue, {}) }),
2385
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(SelectContent, { children: EVENT_STATUSES.map((option) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(SelectItem, { value: option, children: option === "all" ? "All statuses" : option }, option)) })
2386
+ ]
2326
2387
  }
2327
2388
  ),
2328
2389
  /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
2329
2390
  Input,
2330
2391
  {
2331
2392
  className: "h-8 w-[180px]",
2332
- onChange: (event2) => setType(event2.target.value),
2393
+ onChange: (event) => setEventType(event.target.value),
2394
+ onKeyDown: (event) => {
2395
+ if (event.key === "Enter") void inspect();
2396
+ },
2333
2397
  placeholder: "Event type",
2334
- value: type
2398
+ value: eventType
2335
2399
  }
2336
2400
  ),
2337
2401
  /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
2338
2402
  Input,
2339
2403
  {
2340
2404
  className: "h-8 w-[180px]",
2341
- onChange: (event2) => setTraceId(event2.target.value),
2405
+ onChange: (event) => setTraceId(event.target.value),
2406
+ onKeyDown: (event) => {
2407
+ if (event.key === "Enter") void inspect();
2408
+ },
2342
2409
  placeholder: "Trace ID",
2343
2410
  value: traceId
2344
2411
  }
@@ -2346,27 +2413,34 @@ function EventsPage({ context }) {
2346
2413
  ]
2347
2414
  }
2348
2415
  ),
2349
- error ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(EmptyState, { title: "Unable to inspect event", description: error }) : !hasSearched ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
2416
+ error ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(EmptyState, { title: "Unable to inspect event", description: error }) : !hasLoaded && loading ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
2350
2417
  EmptyState,
2351
2418
  {
2352
2419
  icon: import_lucide_react8.Activity,
2353
- title: "Choose a thread",
2354
- description: "Enter a thread ID to inspect its next pending event."
2420
+ title: "Loading events",
2421
+ description: "Fetching recent queue events for the active namespace."
2355
2422
  }
2356
2423
  ) : /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "grid gap-4 xl:grid-cols-[1fr_420px]", children: [
2357
2424
  /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
2358
2425
  ResourceTable,
2359
2426
  {
2360
- rows,
2427
+ rows: events,
2361
2428
  getRowKey: (row) => row.id,
2429
+ onRowClick: setSelectedEvent,
2362
2430
  empty: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
2363
2431
  EmptyState,
2364
2432
  {
2365
- title: "No matching event",
2366
- description: "No pending event matched the current filters."
2433
+ title: "No matching events",
2434
+ description: "No event rows matched the current filters."
2367
2435
  }
2368
2436
  ),
2369
2437
  columns: [
2438
+ {
2439
+ id: "thread",
2440
+ header: "Thread",
2441
+ className: "max-w-[180px] truncate font-mono text-xs",
2442
+ render: (row) => row.threadId
2443
+ },
2370
2444
  {
2371
2445
  id: "type",
2372
2446
  header: "Type",
@@ -2390,7 +2464,20 @@ function EventsPage({ context }) {
2390
2464
  ]
2391
2465
  }
2392
2466
  ),
2393
- /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(JsonPanel, { title: "Event JSON", value: event, minHeight: 420 })
2467
+ selectedEvent ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
2468
+ JsonPanel,
2469
+ {
2470
+ title: "Event JSON",
2471
+ value: selectedEvent,
2472
+ minHeight: 420
2473
+ }
2474
+ ) : /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
2475
+ EmptyState,
2476
+ {
2477
+ title: "No event selected",
2478
+ description: "Select an event row to inspect its payload."
2479
+ }
2480
+ )
2394
2481
  ] })
2395
2482
  ] });
2396
2483
  }