doover-js 0.4.6 → 0.4.8
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/apis/messages-api.d.ts +1 -0
- package/dist/apis/messages-api.js +3 -0
- package/dist/react/index.d.ts +2 -0
- package/dist/react/index.js +4 -1
- package/dist/react/useChannelMessages.d.ts +14 -0
- package/dist/react/useChannelMessages.js +10 -0
- package/dist/react/useInvocationLogs.d.ts +23 -0
- package/dist/react/useInvocationLogs.js +41 -0
- package/dist/test/react.test.js +36 -0
- package/package.json +1 -1
|
@@ -28,5 +28,6 @@ export declare class MessagesApi {
|
|
|
28
28
|
patchMessage(agentId: string, channelName: string, messageId: string, body: MessageBody, params?: MessageMutationParams): Promise<unknown>;
|
|
29
29
|
deleteMessage(agentId: string, channelName: string, messageId: string): Promise<unknown>;
|
|
30
30
|
getMessageAttachment(agentId: string, channelName: string, messageId: string, attachmentId: string): Promise<Blob>;
|
|
31
|
+
getInvocationLogs<TLog = unknown>(agentId: string, channelName: string, messageId: string): Promise<TLog[]>;
|
|
31
32
|
createMultipartPayload(jsonPayload: Record<string, unknown>, attachments: Array<Blob | File>): FormData;
|
|
32
33
|
}
|
|
@@ -33,6 +33,9 @@ class MessagesApi {
|
|
|
33
33
|
getMessageAttachment(agentId, channelName, messageId, attachmentId) {
|
|
34
34
|
return this.rest.get(`/agents/${agentId}/channels/${channelName}/messages/${messageId}/attachments/${attachmentId}`);
|
|
35
35
|
}
|
|
36
|
+
getInvocationLogs(agentId, channelName, messageId) {
|
|
37
|
+
return this.rest.get(`/agents/${agentId}/channels/${channelName}/messages/${messageId}/logs`);
|
|
38
|
+
}
|
|
36
39
|
createMultipartPayload(jsonPayload, attachments) {
|
|
37
40
|
const formData = new FormData();
|
|
38
41
|
formData.set("json_payload", JSON.stringify(jsonPayload));
|
package/dist/react/index.d.ts
CHANGED
|
@@ -17,6 +17,8 @@ export { useChannelMessages, channelMessagesQueryKey, } from "./useChannelMessag
|
|
|
17
17
|
export type { UseChannelMessagesOptions, UseChannelMessagesResult, } from "./useChannelMessages";
|
|
18
18
|
export { useChannelMessage, channelMessageQueryKey, } from "./useChannelMessage";
|
|
19
19
|
export type { UseChannelMessageOptions, UseChannelMessageResult, } from "./useChannelMessage";
|
|
20
|
+
export { useInvocationLogs, invocationLogsQueryKey, } from "./useInvocationLogs";
|
|
21
|
+
export type { UseInvocationLogsOptions } from "./useInvocationLogs";
|
|
20
22
|
export { useSendRpc } from "./useSendRpc";
|
|
21
23
|
export type { RpcCommandId, RpcStatusEvent, SendRpcVariables, UseSendRpcOptions, UseSendRpcResult, } from "./useSendRpc";
|
|
22
24
|
export { useMultiAgentAggregates, multiAgentAggregatesQueryKey, } from "./useMultiAgentAggregates";
|
package/dist/react/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.resetSharedQueryClient = exports.getSharedQueryClient = exports.useTurnCredentials = exports.multiAgentChannelMessagesQueryKey = exports.useMultiAgentChannelMessages = exports.multiAgentAggregatesQueryKey = exports.useMultiAgentAggregates = exports.useSendRpc = exports.channelMessageQueryKey = exports.useChannelMessage = exports.channelMessagesQueryKey = exports.useChannelMessages = exports.useUpdateMessage = exports.useUpdateAggregate = exports.useSendMessage = exports.useAgentChannel = exports.channelAggregateQueryKey = exports.useChannelAggregate = exports.useChannelSubscription = exports.agentConnectionsQueryKey = exports.useAgentConnections = exports.useConnectionState = exports.useDooverClient = exports.DooverProvider = void 0;
|
|
3
|
+
exports.resetSharedQueryClient = exports.getSharedQueryClient = exports.useTurnCredentials = exports.multiAgentChannelMessagesQueryKey = exports.useMultiAgentChannelMessages = exports.multiAgentAggregatesQueryKey = exports.useMultiAgentAggregates = exports.useSendRpc = exports.invocationLogsQueryKey = exports.useInvocationLogs = exports.channelMessageQueryKey = exports.useChannelMessage = exports.channelMessagesQueryKey = exports.useChannelMessages = exports.useUpdateMessage = exports.useUpdateAggregate = exports.useSendMessage = exports.useAgentChannel = exports.channelAggregateQueryKey = exports.useChannelAggregate = exports.useChannelSubscription = exports.agentConnectionsQueryKey = exports.useAgentConnections = exports.useConnectionState = exports.useDooverClient = exports.DooverProvider = void 0;
|
|
4
4
|
var context_1 = require("./context");
|
|
5
5
|
Object.defineProperty(exports, "DooverProvider", { enumerable: true, get: function () { return context_1.DooverProvider; } });
|
|
6
6
|
Object.defineProperty(exports, "useDooverClient", { enumerable: true, get: function () { return context_1.useDooverClient; } });
|
|
@@ -28,6 +28,9 @@ Object.defineProperty(exports, "channelMessagesQueryKey", { enumerable: true, ge
|
|
|
28
28
|
var useChannelMessage_1 = require("./useChannelMessage");
|
|
29
29
|
Object.defineProperty(exports, "useChannelMessage", { enumerable: true, get: function () { return useChannelMessage_1.useChannelMessage; } });
|
|
30
30
|
Object.defineProperty(exports, "channelMessageQueryKey", { enumerable: true, get: function () { return useChannelMessage_1.channelMessageQueryKey; } });
|
|
31
|
+
var useInvocationLogs_1 = require("./useInvocationLogs");
|
|
32
|
+
Object.defineProperty(exports, "useInvocationLogs", { enumerable: true, get: function () { return useInvocationLogs_1.useInvocationLogs; } });
|
|
33
|
+
Object.defineProperty(exports, "invocationLogsQueryKey", { enumerable: true, get: function () { return useInvocationLogs_1.invocationLogsQueryKey; } });
|
|
31
34
|
var useSendRpc_1 = require("./useSendRpc");
|
|
32
35
|
Object.defineProperty(exports, "useSendRpc", { enumerable: true, get: function () { return useSendRpc_1.useSendRpc; } });
|
|
33
36
|
var useMultiAgentAggregates_1 = require("./useMultiAgentAggregates");
|
|
@@ -19,6 +19,20 @@ export interface UseChannelMessagesOptions {
|
|
|
19
19
|
* snowflake so server-stamped messages don't get missed).
|
|
20
20
|
*/
|
|
21
21
|
initialBefore?: string;
|
|
22
|
+
/**
|
|
23
|
+
* Optional lower-bound snowflake id. The server only returns messages
|
|
24
|
+
* newer than this on every page, so paginating older eventually returns
|
|
25
|
+
* an empty page and `hasNextPage` flips to false — useful for fetching
|
|
26
|
+
* a bounded time window (e.g. last 24h) without a manual cutoff loop on
|
|
27
|
+
* the consumer side.
|
|
28
|
+
*/
|
|
29
|
+
after?: string;
|
|
30
|
+
/**
|
|
31
|
+
* Keep paging older automatically until `hasNextPage` is false. Almost
|
|
32
|
+
* always combined with `after` (or a small channel) — without a lower
|
|
33
|
+
* bound this will walk the channel back to its first message.
|
|
34
|
+
*/
|
|
35
|
+
autoPaginate?: boolean;
|
|
22
36
|
}
|
|
23
37
|
type Page<TData> = MessageStructure<TData>[];
|
|
24
38
|
export interface UseChannelMessagesResult<TData> extends Omit<UseInfiniteQueryResult<InfiniteData<Page<TData>>>, "data"> {
|
|
@@ -22,6 +22,8 @@ function useChannelMessages(identifier, options) {
|
|
|
22
22
|
const liveUpdates = options?.liveUpdates ?? true;
|
|
23
23
|
const fields = options?.fields;
|
|
24
24
|
const initialBefore = options?.initialBefore;
|
|
25
|
+
const after = options?.after;
|
|
26
|
+
const autoPaginate = options?.autoPaginate ?? false;
|
|
25
27
|
const key = channelMessagesQueryKey(agentId, channelName);
|
|
26
28
|
const onMessage = (0, react_1.useCallback)((message) => {
|
|
27
29
|
queryClient.setQueryData(key, (current) => {
|
|
@@ -50,10 +52,18 @@ function useChannelMessages(identifier, options) {
|
|
|
50
52
|
...(typeof pageParam === "string" ? { before: pageParam } : {}),
|
|
51
53
|
...(limit !== undefined ? { limit } : {}),
|
|
52
54
|
...(fields && fields.length > 0 ? { field_name: fields } : {}),
|
|
55
|
+
...(after !== undefined ? { after } : {}),
|
|
53
56
|
});
|
|
54
57
|
return (page ?? []);
|
|
55
58
|
},
|
|
56
59
|
});
|
|
60
|
+
(0, react_1.useEffect)(() => {
|
|
61
|
+
if (!autoPaginate)
|
|
62
|
+
return;
|
|
63
|
+
if (query.isFetching || !query.hasNextPage)
|
|
64
|
+
return;
|
|
65
|
+
query.fetchNextPage();
|
|
66
|
+
}, [autoPaginate, query.isFetching, query.hasNextPage, query.fetchNextPage]);
|
|
57
67
|
const messages = (0, react_1.useMemo)(() => (query.data?.pages ?? []).flat(), [query.data]);
|
|
58
68
|
return { ...query, messages };
|
|
59
69
|
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { type UseQueryResult } from "@tanstack/react-query";
|
|
2
|
+
import type { ChannelIdentifier } from "../types/viewer";
|
|
3
|
+
export declare function invocationLogsQueryKey(agentId: string | undefined, channelName: string | undefined, messageId: string | undefined): readonly ["doover", "agent", string | undefined, "channel", string | undefined, "message", string | undefined, "logs"];
|
|
4
|
+
export interface UseInvocationLogsOptions {
|
|
5
|
+
/** Defaults to true. Set false to skip the query (e.g. dialog closed). */
|
|
6
|
+
enabled?: boolean;
|
|
7
|
+
/**
|
|
8
|
+
* react-query retry behaviour. Defaults to false — the logs endpoint
|
|
9
|
+
* commonly 404s while logs are still materialising server-side, and a
|
|
10
|
+
* manual refetch button is friendlier than silent retry.
|
|
11
|
+
*/
|
|
12
|
+
retry?: boolean | number;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Fetch the log entries for a single invocation message. The `/logs`
|
|
16
|
+
* endpoint is only meaningful for invocation messages (channel name like
|
|
17
|
+
* `dv-proc-inv-…`); other message types return 404.
|
|
18
|
+
*
|
|
19
|
+
* Generic on `TLog` — the shape of a single log entry. Defaults to `unknown`
|
|
20
|
+
* because log payloads are domain-specific (lambda telemetry, app-level
|
|
21
|
+
* structured logs, etc.) and doover-js does not own the canonical shape.
|
|
22
|
+
*/
|
|
23
|
+
export declare function useInvocationLogs<TLog = unknown>(identifier: ChannelIdentifier, messageId: string | undefined, options?: UseInvocationLogsOptions): UseQueryResult<TLog[]>;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.invocationLogsQueryKey = invocationLogsQueryKey;
|
|
4
|
+
exports.useInvocationLogs = useInvocationLogs;
|
|
5
|
+
const react_query_1 = require("@tanstack/react-query");
|
|
6
|
+
const context_1 = require("./context");
|
|
7
|
+
function invocationLogsQueryKey(agentId, channelName, messageId) {
|
|
8
|
+
return [
|
|
9
|
+
"doover",
|
|
10
|
+
"agent",
|
|
11
|
+
agentId,
|
|
12
|
+
"channel",
|
|
13
|
+
channelName,
|
|
14
|
+
"message",
|
|
15
|
+
messageId,
|
|
16
|
+
"logs",
|
|
17
|
+
];
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Fetch the log entries for a single invocation message. The `/logs`
|
|
21
|
+
* endpoint is only meaningful for invocation messages (channel name like
|
|
22
|
+
* `dv-proc-inv-…`); other message types return 404.
|
|
23
|
+
*
|
|
24
|
+
* Generic on `TLog` — the shape of a single log entry. Defaults to `unknown`
|
|
25
|
+
* because log payloads are domain-specific (lambda telemetry, app-level
|
|
26
|
+
* structured logs, etc.) and doover-js does not own the canonical shape.
|
|
27
|
+
*/
|
|
28
|
+
function useInvocationLogs(identifier, messageId, options) {
|
|
29
|
+
const client = (0, context_1.useDooverClient)();
|
|
30
|
+
const { agentId, channelName } = identifier;
|
|
31
|
+
return (0, react_query_1.useQuery)({
|
|
32
|
+
queryKey: invocationLogsQueryKey(agentId, channelName, messageId),
|
|
33
|
+
queryFn: () => client.messages.getInvocationLogs(agentId, channelName, messageId),
|
|
34
|
+
enabled: !!agentId &&
|
|
35
|
+
!!channelName &&
|
|
36
|
+
!!messageId &&
|
|
37
|
+
(options?.enabled ?? true),
|
|
38
|
+
retry: options?.retry ?? false,
|
|
39
|
+
staleTime: Infinity,
|
|
40
|
+
});
|
|
41
|
+
}
|
package/dist/test/react.test.js
CHANGED
|
@@ -336,6 +336,42 @@ function wrapper(client) {
|
|
|
336
336
|
});
|
|
337
337
|
await (0, react_1.waitFor)(() => (0, chai_1.expect)(result.current.data?.response?.status).to.equal("success"));
|
|
338
338
|
});
|
|
339
|
+
(0, mocha_1.it)("useInvocationLogs fetches logs for the message", async () => {
|
|
340
|
+
const messageId = (0, snowflake_1.generateSnowflakeIdAtTime)(new Date("2026-01-01T00:00:00.000Z"));
|
|
341
|
+
const fetchMock = (0, helpers_1.createFetchMock)(() => (0, helpers_1.createJsonResponse)([
|
|
342
|
+
{ level: "INFO", message: "hello", timestamp: 1 },
|
|
343
|
+
{ level: "ERROR", message: "boom", timestamp: 2 },
|
|
344
|
+
]));
|
|
345
|
+
const client = new doover_client_1.DooverClient({
|
|
346
|
+
dataRestUrl: "https://api.example.com",
|
|
347
|
+
controlApiUrl: "https://control.example.com",
|
|
348
|
+
dataWssUrl: "wss://ws.example.com",
|
|
349
|
+
fetchImpl: fetchMock,
|
|
350
|
+
webSocketImpl: helpers_1.MockWebSocket,
|
|
351
|
+
disableBrowserLifecycleHooks: true,
|
|
352
|
+
});
|
|
353
|
+
const { result } = (0, react_1.renderHook)(() => (0, react_2.useInvocationLogs)({ agentId: "a1", channelName: "dv-proc-inv-1" }, messageId), { wrapper: wrapper(client) });
|
|
354
|
+
await (0, react_1.waitFor)(() => (0, chai_1.expect)(result.current.isSuccess).to.equal(true));
|
|
355
|
+
(0, chai_1.expect)(result.current.data?.map((l) => l.level)).to.deep.equal([
|
|
356
|
+
"INFO",
|
|
357
|
+
"ERROR",
|
|
358
|
+
]);
|
|
359
|
+
const requestUrl = fetchMock.firstCall?.args[0];
|
|
360
|
+
(0, chai_1.expect)(requestUrl).to.contain(`/agents/a1/channels/dv-proc-inv-1/messages/${messageId}/logs`);
|
|
361
|
+
});
|
|
362
|
+
(0, mocha_1.it)("useInvocationLogs is disabled when messageId is undefined", () => {
|
|
363
|
+
const fetchMock = (0, helpers_1.createFetchMock)(() => (0, helpers_1.createJsonResponse)([]));
|
|
364
|
+
const client = new doover_client_1.DooverClient({
|
|
365
|
+
dataRestUrl: "https://api.example.com",
|
|
366
|
+
controlApiUrl: "https://control.example.com",
|
|
367
|
+
dataWssUrl: "wss://ws.example.com",
|
|
368
|
+
fetchImpl: fetchMock,
|
|
369
|
+
webSocketImpl: helpers_1.MockWebSocket,
|
|
370
|
+
disableBrowserLifecycleHooks: true,
|
|
371
|
+
});
|
|
372
|
+
(0, react_1.renderHook)(() => (0, react_2.useInvocationLogs)({ agentId: "a1", channelName: "dv-proc-inv-1" }, undefined), { wrapper: wrapper(client) });
|
|
373
|
+
(0, chai_1.expect)(fetchMock.callCount).to.equal(0);
|
|
374
|
+
});
|
|
339
375
|
(0, mocha_1.it)("getSharedQueryClient returns the same QueryClient across callers", () => {
|
|
340
376
|
(0, react_2.resetSharedQueryClient)();
|
|
341
377
|
const a = (0, react_2.getSharedQueryClient)();
|