doover-js 0.2.0 → 0.3.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/react/useChannelMessages.d.ts +13 -0
- package/dist/react/useChannelMessages.js +4 -1
- package/dist/react/useMultiAgentAggregates.js +16 -1
- package/dist/react/useMultiAgentChannelMessages.d.ts +7 -0
- package/dist/react/useMultiAgentChannelMessages.js +4 -1
- package/dist/react/useUpdateAggregate.d.ts +7 -0
- package/dist/react/useUpdateAggregate.js +3 -2
- package/dist/react/useUpdateMessage.d.ts +19 -3
- package/dist/react/useUpdateMessage.js +10 -4
- package/dist/viewer/doover-data-provider.d.ts +3 -3
- package/dist/viewer/doover-data-provider.js +4 -4
- package/package.json +1 -1
|
@@ -6,6 +6,19 @@ export interface UseChannelMessagesOptions {
|
|
|
6
6
|
limit?: number;
|
|
7
7
|
/** If false, skip subscribing for live message-create updates. Defaults true. */
|
|
8
8
|
liveUpdates?: boolean;
|
|
9
|
+
/**
|
|
10
|
+
* Restrict the returned messages to those whose payload contains any of
|
|
11
|
+
* these top-level field names. Passed through as `field_name` on the
|
|
12
|
+
* REST call.
|
|
13
|
+
*/
|
|
14
|
+
fields?: string[];
|
|
15
|
+
/**
|
|
16
|
+
* Optional first-page `before` cursor (snowflake id). Defaults to
|
|
17
|
+
* unset, which returns the latest messages. Use this when you need to
|
|
18
|
+
* guard against client-side clock skew (seed with a slightly-future
|
|
19
|
+
* snowflake so server-stamped messages don't get missed).
|
|
20
|
+
*/
|
|
21
|
+
initialBefore?: string;
|
|
9
22
|
}
|
|
10
23
|
type Page<TData> = MessageStructure<TData>[];
|
|
11
24
|
export interface UseChannelMessagesResult<TData> extends Omit<UseInfiniteQueryResult<InfiniteData<Page<TData>>>, "data"> {
|
|
@@ -20,6 +20,8 @@ function useChannelMessages(identifier, options) {
|
|
|
20
20
|
const { agentId, channelName } = identifier;
|
|
21
21
|
const limit = options?.limit;
|
|
22
22
|
const liveUpdates = options?.liveUpdates ?? true;
|
|
23
|
+
const fields = options?.fields;
|
|
24
|
+
const initialBefore = options?.initialBefore;
|
|
23
25
|
const key = channelMessagesQueryKey(agentId, channelName);
|
|
24
26
|
const onMessage = (0, react_1.useCallback)((message) => {
|
|
25
27
|
queryClient.setQueryData(key, (current) => {
|
|
@@ -41,12 +43,13 @@ function useChannelMessages(identifier, options) {
|
|
|
41
43
|
queryKey: key,
|
|
42
44
|
enabled: !!agentId && !!channelName,
|
|
43
45
|
staleTime: Infinity,
|
|
44
|
-
initialPageParam:
|
|
46
|
+
initialPageParam: initialBefore,
|
|
45
47
|
getNextPageParam: (lastPage) => lastPage && lastPage.length > 0 ? lastPage[0]?.id : undefined,
|
|
46
48
|
queryFn: async ({ pageParam }) => {
|
|
47
49
|
const page = await client.viewer.getMessages(identifier, {
|
|
48
50
|
...(typeof pageParam === "string" ? { before: pageParam } : {}),
|
|
49
51
|
...(limit !== undefined ? { limit } : {}),
|
|
52
|
+
...(fields && fields.length > 0 ? { field_name: fields } : {}),
|
|
50
53
|
});
|
|
51
54
|
return (page ?? []);
|
|
52
55
|
},
|
|
@@ -5,6 +5,7 @@ exports.useMultiAgentAggregates = useMultiAgentAggregates;
|
|
|
5
5
|
const react_1 = require("react");
|
|
6
6
|
const react_query_1 = require("@tanstack/react-query");
|
|
7
7
|
const context_1 = require("./context");
|
|
8
|
+
const useChannelAggregate_1 = require("./useChannelAggregate");
|
|
8
9
|
function multiAgentAggregatesQueryKey(channelName, agentIds) {
|
|
9
10
|
return [
|
|
10
11
|
"doover",
|
|
@@ -28,7 +29,18 @@ function useMultiAgentAggregates(channelName, agentIds, options) {
|
|
|
28
29
|
queryKey: key,
|
|
29
30
|
enabled: agentIds.length > 0,
|
|
30
31
|
staleTime: Infinity,
|
|
31
|
-
queryFn: () =>
|
|
32
|
+
queryFn: async () => {
|
|
33
|
+
const response = await client.agents.getMultiAgentAggregates(channelName, { agent_id: agentIds });
|
|
34
|
+
// Seed the per-agent `channelAggregateQueryKey` cache so that
|
|
35
|
+
// sibling `useChannelAggregate(id, channelName)` calls for any
|
|
36
|
+
// of these agents get an instant cache hit rather than issuing
|
|
37
|
+
// a second fetch for data we already have.
|
|
38
|
+
for (const result of response.results) {
|
|
39
|
+
const { agent_id, ...aggregate } = result;
|
|
40
|
+
queryClient.setQueryData((0, useChannelAggregate_1.channelAggregateQueryKey)(agent_id, channelName), aggregate);
|
|
41
|
+
}
|
|
42
|
+
return response;
|
|
43
|
+
},
|
|
32
44
|
});
|
|
33
45
|
const patchAgentAggregate = (0, react_1.useCallback)((agentId, aggregate) => {
|
|
34
46
|
queryClient.setQueryData(key, (current) => {
|
|
@@ -44,6 +56,9 @@ function useMultiAgentAggregates(channelName, agentIds, options) {
|
|
|
44
56
|
: current.results.map((r, i) => (i === idx ? next : r));
|
|
45
57
|
return { ...current, results };
|
|
46
58
|
});
|
|
59
|
+
// Mirror live updates into the per-agent cache so sibling
|
|
60
|
+
// `useChannelAggregate` consumers see them too.
|
|
61
|
+
queryClient.setQueryData((0, useChannelAggregate_1.channelAggregateQueryKey)(agentId, channelName), aggregate);
|
|
47
62
|
},
|
|
48
63
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
49
64
|
[queryClient, channelName, agentIds.join(",")]);
|
|
@@ -5,6 +5,13 @@ export interface UseMultiAgentChannelMessagesOptions {
|
|
|
5
5
|
limit?: number;
|
|
6
6
|
/** If false, skip live subscriptions per agent. Defaults true. */
|
|
7
7
|
liveUpdates?: boolean;
|
|
8
|
+
/**
|
|
9
|
+
* Restrict the returned messages to those whose payload contains any
|
|
10
|
+
* of these top-level field names. Forwarded as `field_name`.
|
|
11
|
+
*/
|
|
12
|
+
fields?: string[];
|
|
13
|
+
/** Optional first-page `before` cursor (snowflake id). */
|
|
14
|
+
initialBefore?: string;
|
|
8
15
|
}
|
|
9
16
|
interface Page {
|
|
10
17
|
results: MessageStructure[];
|
|
@@ -19,6 +19,8 @@ function useMultiAgentChannelMessages(channelName, agentIds, options) {
|
|
|
19
19
|
const queryClient = (0, react_query_1.useQueryClient)();
|
|
20
20
|
const limit = options?.limit;
|
|
21
21
|
const liveUpdates = options?.liveUpdates ?? true;
|
|
22
|
+
const fields = options?.fields;
|
|
23
|
+
const initialBefore = options?.initialBefore;
|
|
22
24
|
const key = multiAgentChannelMessagesQueryKey(channelName, agentIds);
|
|
23
25
|
const prependMessage = (0, react_1.useCallback)((message) => {
|
|
24
26
|
queryClient.setQueryData(key, (current) => {
|
|
@@ -62,13 +64,14 @@ function useMultiAgentChannelMessages(channelName, agentIds, options) {
|
|
|
62
64
|
queryKey: key,
|
|
63
65
|
enabled: agentIds.length > 0,
|
|
64
66
|
staleTime: Infinity,
|
|
65
|
-
initialPageParam:
|
|
67
|
+
initialPageParam: initialBefore,
|
|
66
68
|
getNextPageParam: (lastPage) => lastPage?.next,
|
|
67
69
|
queryFn: async ({ pageParam }) => {
|
|
68
70
|
const page = await client.agents.getMultiAgentMessages(channelName, {
|
|
69
71
|
agent_id: agentIds,
|
|
70
72
|
...(typeof pageParam === "string" ? { before: pageParam } : {}),
|
|
71
73
|
...(limit !== undefined ? { limit } : {}),
|
|
74
|
+
...(fields && fields.length > 0 ? { field_name: fields } : {}),
|
|
72
75
|
});
|
|
73
76
|
return page;
|
|
74
77
|
},
|
|
@@ -1,9 +1,16 @@
|
|
|
1
1
|
import { type UseMutationResult } from "@tanstack/react-query";
|
|
2
|
+
import type { AggregateMutationParams } from "../apis/aggregates-api";
|
|
2
3
|
import type { Aggregate } from "../types/common";
|
|
3
4
|
import type { ChannelIdentifier } from "../types/viewer";
|
|
4
5
|
export interface UseUpdateAggregateOptions {
|
|
5
6
|
/** If true, use PUT semantics (replace) instead of PATCH (merge). */
|
|
6
7
|
replace?: boolean;
|
|
8
|
+
/**
|
|
9
|
+
* Forwarded as query params to the aggregate endpoint:
|
|
10
|
+
* `log_update` (record a history message), `clear_attachments`,
|
|
11
|
+
* `suppress_response`. See `AggregateMutationParams`.
|
|
12
|
+
*/
|
|
13
|
+
params?: AggregateMutationParams;
|
|
7
14
|
}
|
|
8
15
|
/**
|
|
9
16
|
* Mutation wrapping `DooverDataProvider.updateAggregate` (PATCH) or
|
|
@@ -14,10 +14,11 @@ function useUpdateAggregate(identifier, options) {
|
|
|
14
14
|
const client = (0, context_1.useDooverClient)();
|
|
15
15
|
const queryClient = (0, react_query_1.useQueryClient)();
|
|
16
16
|
const replace = options?.replace ?? false;
|
|
17
|
+
const params = options?.params;
|
|
17
18
|
return (0, react_query_1.useMutation)({
|
|
18
19
|
mutationFn: (data) => replace
|
|
19
|
-
? client.viewer.putAggregate(identifier, data)
|
|
20
|
-
: client.viewer.updateAggregate(identifier, data),
|
|
20
|
+
? client.viewer.putAggregate(identifier, data, params)
|
|
21
|
+
: client.viewer.updateAggregate(identifier, data, params),
|
|
21
22
|
onSuccess: (aggregate) => {
|
|
22
23
|
queryClient.setQueryData((0, useChannelAggregate_1.channelAggregateQueryKey)(identifier.agentId, identifier.channelName), aggregate);
|
|
23
24
|
},
|
|
@@ -1,17 +1,33 @@
|
|
|
1
1
|
import { type UseMutationResult } from "@tanstack/react-query";
|
|
2
2
|
import type { MessageBody, MessageMutationParams } from "../apis/messages-api";
|
|
3
3
|
import type { ChannelIdentifier } from "../types/viewer";
|
|
4
|
-
export interface
|
|
5
|
-
/**
|
|
4
|
+
export interface UpdateMessageCallOptions {
|
|
5
|
+
/**
|
|
6
|
+
* If true, use PUT (replace) instead of PATCH (merge). Falls back to
|
|
7
|
+
* the hook-level `replace` option, which itself defaults to PATCH.
|
|
8
|
+
*/
|
|
6
9
|
replace?: boolean;
|
|
10
|
+
/**
|
|
11
|
+
* Query params forwarded to the message endpoint. Merged over the
|
|
12
|
+
* hook-level `params` option (per-call keys win).
|
|
13
|
+
*/
|
|
7
14
|
params?: MessageMutationParams;
|
|
8
15
|
}
|
|
16
|
+
export interface UseUpdateMessageOptions extends UpdateMessageCallOptions {
|
|
17
|
+
}
|
|
9
18
|
export interface UpdateMessageVariables {
|
|
10
19
|
messageId: string;
|
|
11
20
|
body: MessageBody;
|
|
21
|
+
/**
|
|
22
|
+
* Per-call overrides. Extensible — add new knobs here without breaking
|
|
23
|
+
* the variables shape.
|
|
24
|
+
*/
|
|
25
|
+
options?: UpdateMessageCallOptions;
|
|
12
26
|
}
|
|
13
27
|
/**
|
|
14
28
|
* Mutation wrapping `MessagesApi.patchMessage` or `putMessage`. Bound to a
|
|
15
|
-
* single channel; the message id and body are passed per-call.
|
|
29
|
+
* single channel; the message id and body are passed per-call. Each
|
|
30
|
+
* invocation can override `replace` / `params` via `variables.options` for
|
|
31
|
+
* mutation sites that sometimes PUT and sometimes PATCH the same channel.
|
|
16
32
|
*/
|
|
17
33
|
export declare function useUpdateMessage(identifier: ChannelIdentifier, options?: UseUpdateMessageOptions): UseMutationResult<unknown, Error, UpdateMessageVariables>;
|
|
@@ -5,17 +5,23 @@ const react_query_1 = require("@tanstack/react-query");
|
|
|
5
5
|
const context_1 = require("./context");
|
|
6
6
|
/**
|
|
7
7
|
* Mutation wrapping `MessagesApi.patchMessage` or `putMessage`. Bound to a
|
|
8
|
-
* single channel; the message id and body are passed per-call.
|
|
8
|
+
* single channel; the message id and body are passed per-call. Each
|
|
9
|
+
* invocation can override `replace` / `params` via `variables.options` for
|
|
10
|
+
* mutation sites that sometimes PUT and sometimes PATCH the same channel.
|
|
9
11
|
*/
|
|
10
12
|
function useUpdateMessage(identifier, options) {
|
|
11
13
|
const client = (0, context_1.useDooverClient)();
|
|
12
|
-
const
|
|
13
|
-
const
|
|
14
|
+
const defaultReplace = options?.replace ?? false;
|
|
15
|
+
const defaultParams = options?.params;
|
|
14
16
|
return (0, react_query_1.useMutation)({
|
|
15
|
-
mutationFn: ({ messageId, body }) => {
|
|
17
|
+
mutationFn: ({ messageId, body, options: call }) => {
|
|
16
18
|
if (!identifier.agentId || !identifier.channelName) {
|
|
17
19
|
throw new Error("useUpdateMessage requires both agentId and channelName on the identifier.");
|
|
18
20
|
}
|
|
21
|
+
const replace = call?.replace ?? defaultReplace;
|
|
22
|
+
const params = call?.params || defaultParams
|
|
23
|
+
? { ...defaultParams, ...call?.params }
|
|
24
|
+
: undefined;
|
|
19
25
|
return replace
|
|
20
26
|
? client.messages.putMessage(identifier.agentId, identifier.channelName, messageId, body, params)
|
|
21
27
|
: client.messages.patchMessage(identifier.agentId, identifier.channelName, messageId, body, params);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { AgentsApi } from "../apis/agents-api";
|
|
2
|
-
import { AggregatesApi } from "../apis/aggregates-api";
|
|
2
|
+
import { AggregatesApi, type AggregateMutationParams } from "../apis/aggregates-api";
|
|
3
3
|
import { ChannelsApi } from "../apis/channels-api";
|
|
4
4
|
import { ConnectionsApi } from "../apis/connections-api";
|
|
5
5
|
import { MessagesApi, type ListMessagesParams } from "../apis/messages-api";
|
|
@@ -68,8 +68,8 @@ export declare class DooverDataProvider implements ChannelsDataProvider<ChannelI
|
|
|
68
68
|
sendRPC<TRequest = object, TResponse = object, TPending = undefined>(identifier: ChannelIdentifier, rpcRequest: RpcRequest<TRequest>, options?: {
|
|
69
69
|
onStatus?: (status: RpcStatus<TPending>) => void;
|
|
70
70
|
}): Promise<TResponse>;
|
|
71
|
-
updateAggregate(identifier: ChannelIdentifier, message: object): Promise<Aggregate>;
|
|
72
|
-
putAggregate(identifier: ChannelIdentifier, message: object): Promise<Aggregate>;
|
|
71
|
+
updateAggregate(identifier: ChannelIdentifier, message: object, params?: AggregateMutationParams): Promise<Aggregate>;
|
|
72
|
+
putAggregate(identifier: ChannelIdentifier, message: object, params?: AggregateMutationParams): Promise<Aggregate>;
|
|
73
73
|
getChannelSubscriptions(identifier: ChannelIdentifier): Promise<SubscriptionDetails[]>;
|
|
74
74
|
getAgentConnections(identifier: ChannelIdentifier): Promise<ConnectionDetails[]>;
|
|
75
75
|
getIdentifierFromPath(path: string, searchParams: URLSearchParams): {
|
|
@@ -228,13 +228,13 @@ class DooverDataProvider {
|
|
|
228
228
|
});
|
|
229
229
|
});
|
|
230
230
|
}
|
|
231
|
-
updateAggregate(identifier, message) {
|
|
231
|
+
updateAggregate(identifier, message, params) {
|
|
232
232
|
const validated = this.requireChannel(identifier);
|
|
233
|
-
return this.aggregatesApi.patchAggregate(validated.agentId, validated.channelName, message);
|
|
233
|
+
return this.aggregatesApi.patchAggregate(validated.agentId, validated.channelName, message, params);
|
|
234
234
|
}
|
|
235
|
-
putAggregate(identifier, message) {
|
|
235
|
+
putAggregate(identifier, message, params) {
|
|
236
236
|
const validated = this.requireChannel(identifier);
|
|
237
|
-
return this.aggregatesApi.putAggregate(validated.agentId, validated.channelName, message);
|
|
237
|
+
return this.aggregatesApi.putAggregate(validated.agentId, validated.channelName, message, params);
|
|
238
238
|
}
|
|
239
239
|
getChannelSubscriptions(identifier) {
|
|
240
240
|
const validated = this.requireChannel(identifier);
|