@athenaintel/react 0.30.0 → 0.35.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 +160 -9
- package/dist/agent-runtime/src/athena-asset-drag.cjs +44 -0
- package/dist/agent-runtime/src/athena-asset-drag.cjs.map +1 -0
- package/dist/agent-runtime/src/athena-asset-drag.js +44 -0
- package/dist/agent-runtime/src/athena-asset-drag.js.map +1 -0
- package/dist/agent-runtime/src/composer-markdown.cjs.map +1 -1
- package/dist/agent-runtime/src/composer-markdown.js.map +1 -1
- package/dist/agent-runtime/src/config-mutations.cjs +59 -0
- package/dist/agent-runtime/src/config-mutations.cjs.map +1 -0
- package/dist/agent-runtime/src/config-mutations.js +59 -0
- package/dist/agent-runtime/src/config-mutations.js.map +1 -0
- package/dist/agent-runtime/src/deep-agent-transport-recipe.cjs +2 -3
- package/dist/agent-runtime/src/deep-agent-transport-recipe.cjs.map +1 -1
- package/dist/agent-runtime/src/deep-agent-transport-recipe.js +3 -4
- package/dist/agent-runtime/src/deep-agent-transport-recipe.js.map +1 -1
- package/dist/agent-runtime/src/edit-command.cjs.map +1 -1
- package/dist/agent-runtime/src/edit-command.js.map +1 -1
- package/dist/agent-runtime/src/generated/runconfig-contract.cjs +6 -0
- package/dist/agent-runtime/src/generated/runconfig-contract.cjs.map +1 -1
- package/dist/agent-runtime/src/generated/runconfig-contract.js +6 -0
- package/dist/agent-runtime/src/generated/runconfig-contract.js.map +1 -1
- package/dist/agent-runtime/src/messages.cjs +57 -2
- package/dist/agent-runtime/src/messages.cjs.map +1 -1
- package/dist/agent-runtime/src/messages.js +57 -2
- package/dist/agent-runtime/src/messages.js.map +1 -1
- package/dist/agent-runtime/src/quota-safe-local-storage-session.cjs +72 -3
- package/dist/agent-runtime/src/quota-safe-local-storage-session.cjs.map +1 -1
- package/dist/agent-runtime/src/quota-safe-local-storage-session.js +73 -4
- package/dist/agent-runtime/src/quota-safe-local-storage-session.js.map +1 -1
- package/dist/agent-runtime/src/statewire-transport.cjs +4 -13
- package/dist/agent-runtime/src/statewire-transport.cjs.map +1 -1
- package/dist/agent-runtime/src/statewire-transport.js +5 -14
- package/dist/agent-runtime/src/statewire-transport.js.map +1 -1
- package/dist/agent-runtime/src/tool-metadata.cjs +26 -7
- package/dist/agent-runtime/src/tool-metadata.cjs.map +1 -1
- package/dist/agent-runtime/src/tool-metadata.js +26 -7
- package/dist/agent-runtime/src/tool-metadata.js.map +1 -1
- package/dist/agent-runtime/src/use-deep-agent-config.cjs +117 -1
- package/dist/agent-runtime/src/use-deep-agent-config.cjs.map +1 -1
- package/dist/agent-runtime/src/use-deep-agent-config.js +118 -2
- package/dist/agent-runtime/src/use-deep-agent-config.js.map +1 -1
- package/dist/agent-runtime/src/use-deep-agent-thread.cjs.map +1 -1
- package/dist/agent-runtime/src/use-deep-agent-thread.js.map +1 -1
- package/dist/assets/AthenaAssetEmbed.cjs +9 -2
- package/dist/assets/AthenaAssetEmbed.cjs.map +1 -1
- package/dist/assets/AthenaAssetEmbed.d.ts +9 -0
- package/dist/assets/AthenaAssetEmbed.js +11 -4
- package/dist/assets/AthenaAssetEmbed.js.map +1 -1
- package/dist/assets/asset-embed-messages.cjs +6 -0
- package/dist/assets/asset-embed-messages.cjs.map +1 -1
- package/dist/assets/asset-embed-messages.d.ts +7 -0
- package/dist/assets/asset-embed-messages.js +6 -0
- package/dist/assets/asset-embed-messages.js.map +1 -1
- package/dist/assets/use-asset-embed.cjs +71 -71
- package/dist/assets/use-asset-embed.cjs.map +1 -1
- package/dist/assets/use-asset-embed.d.ts +20 -7
- package/dist/assets/use-asset-embed.js +72 -72
- package/dist/assets/use-asset-embed.js.map +1 -1
- package/dist/catalog/agent-model-options.cjs +122 -0
- package/dist/catalog/agent-model-options.cjs.map +1 -0
- package/dist/catalog/agent-model-options.d.ts +115 -0
- package/dist/catalog/agent-model-options.js +122 -0
- package/dist/catalog/agent-model-options.js.map +1 -0
- package/dist/catalog/chat-pickers.cjs +184 -4
- package/dist/catalog/chat-pickers.cjs.map +1 -1
- package/dist/catalog/chat-pickers.d.ts +27 -3
- package/dist/catalog/chat-pickers.js +187 -7
- package/dist/catalog/chat-pickers.js.map +1 -1
- package/dist/catalog/runtime-catalog.cjs +117 -3
- package/dist/catalog/runtime-catalog.cjs.map +1 -1
- package/dist/catalog/runtime-catalog.d.ts +104 -0
- package/dist/catalog/runtime-catalog.js +119 -5
- package/dist/catalog/runtime-catalog.js.map +1 -1
- package/dist/chat/AthenaChat.cjs +41 -26
- package/dist/chat/AthenaChat.cjs.map +1 -1
- package/dist/chat/AthenaChat.d.ts +8 -7
- package/dist/chat/AthenaChat.js +41 -26
- package/dist/chat/AthenaChat.js.map +1 -1
- package/dist/chat/super-grouping/SuperGroupingCard.cjs +61 -14
- package/dist/chat/super-grouping/SuperGroupingCard.cjs.map +1 -1
- package/dist/chat/super-grouping/SuperGroupingCard.d.ts +26 -12
- package/dist/chat/super-grouping/SuperGroupingCard.js +63 -16
- package/dist/chat/super-grouping/SuperGroupingCard.js.map +1 -1
- package/dist/chat/super-grouping/SuperGroupingTranscript.cjs +80 -53
- package/dist/chat/super-grouping/SuperGroupingTranscript.cjs.map +1 -1
- package/dist/chat/super-grouping/SuperGroupingTranscript.d.ts +10 -10
- package/dist/chat/super-grouping/SuperGroupingTranscript.js +81 -54
- package/dist/chat/super-grouping/SuperGroupingTranscript.js.map +1 -1
- package/dist/chat/super-grouping/activity-timeline.cjs +19 -4
- package/dist/chat/super-grouping/activity-timeline.cjs.map +1 -1
- package/dist/chat/super-grouping/activity-timeline.d.ts +24 -5
- package/dist/chat/super-grouping/activity-timeline.js +19 -4
- package/dist/chat/super-grouping/activity-timeline.js.map +1 -1
- package/dist/chat/super-grouping/index.cjs +2 -0
- package/dist/chat/super-grouping/index.cjs.map +1 -1
- package/dist/chat/super-grouping/index.d.ts +7 -6
- package/dist/chat/super-grouping/index.js +3 -1
- package/dist/chat/super-grouping/toolkit-map.cjs +4 -1
- package/dist/chat/super-grouping/toolkit-map.cjs.map +1 -1
- package/dist/chat/super-grouping/toolkit-map.js +4 -1
- package/dist/chat/super-grouping/toolkit-map.js.map +1 -1
- package/dist/chat-ui/composer/tiptap-composer.cjs +40 -4
- package/dist/chat-ui/composer/tiptap-composer.cjs.map +1 -1
- package/dist/chat-ui/composer/tiptap-composer.js +40 -4
- package/dist/chat-ui/composer/tiptap-composer.js.map +1 -1
- package/dist/chat-ui/index.cjs +1 -0
- package/dist/chat-ui/index.cjs.map +1 -1
- package/dist/chat-ui/index.d.ts +1 -1
- package/dist/chat-ui/index.js +2 -1
- package/dist/chat-ui/mentions/mention-chip.cjs +29 -2
- package/dist/chat-ui/mentions/mention-chip.cjs.map +1 -1
- package/dist/chat-ui/mentions/mention-chip.d.ts +2 -5
- package/dist/chat-ui/mentions/mention-chip.js +30 -3
- package/dist/chat-ui/mentions/mention-chip.js.map +1 -1
- package/dist/chat-ui/mentions/mention-extension.cjs +1 -1
- package/dist/chat-ui/mentions/mention-extension.cjs.map +1 -1
- package/dist/chat-ui/mentions/mention-extension.js +1 -1
- package/dist/chat-ui/mentions/mention-extension.js.map +1 -1
- package/dist/chat-ui/mentions/suggestions/data/api-client.cjs +33 -2
- package/dist/chat-ui/mentions/suggestions/data/api-client.cjs.map +1 -1
- package/dist/chat-ui/mentions/suggestions/data/api-client.d.ts +14 -0
- package/dist/chat-ui/mentions/suggestions/data/api-client.js +33 -2
- package/dist/chat-ui/mentions/suggestions/data/api-client.js.map +1 -1
- package/dist/chat-ui/mentions/use-account-workspace-id.cjs +61 -0
- package/dist/chat-ui/mentions/use-account-workspace-id.cjs.map +1 -0
- package/dist/chat-ui/mentions/use-account-workspace-id.d.ts +3 -0
- package/dist/chat-ui/mentions/use-account-workspace-id.js +61 -0
- package/dist/chat-ui/mentions/use-account-workspace-id.js.map +1 -0
- package/dist/chat-ui/mentions/use-member-avatar.cjs +75 -0
- package/dist/chat-ui/mentions/use-member-avatar.cjs.map +1 -0
- package/dist/chat-ui/mentions/use-member-avatar.d.ts +2 -0
- package/dist/chat-ui/mentions/use-member-avatar.js +75 -0
- package/dist/chat-ui/mentions/use-member-avatar.js.map +1 -0
- package/dist/collab/client.cjs +80 -19
- package/dist/collab/client.cjs.map +1 -1
- package/dist/collab/client.d.ts +22 -0
- package/dist/collab/client.js +80 -19
- package/dist/collab/client.js.map +1 -1
- package/dist/diagnostics/athena-diagnostics.cjs.map +1 -1
- package/dist/diagnostics/athena-diagnostics.d.ts +3 -1
- package/dist/diagnostics/athena-diagnostics.js.map +1 -1
- package/dist/index.cjs +5 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +6 -3
- package/dist/index.js +7 -2
- package/dist/index.js.map +1 -1
- package/dist/lib/use-athena-rest-query.cjs +4 -0
- package/dist/lib/use-athena-rest-query.cjs.map +1 -1
- package/dist/lib/use-athena-rest-query.d.ts +6 -0
- package/dist/lib/use-athena-rest-query.js +4 -0
- package/dist/lib/use-athena-rest-query.js.map +1 -1
- package/dist/provider/AthenaProvider.cjs +57 -6
- package/dist/provider/AthenaProvider.cjs.map +1 -1
- package/dist/provider/AthenaProvider.d.ts +21 -5
- package/dist/provider/AthenaProvider.js +59 -8
- package/dist/provider/AthenaProvider.js.map +1 -1
- package/dist/provider/agent-selection-context.cjs +6 -0
- package/dist/provider/agent-selection-context.cjs.map +1 -0
- package/dist/provider/agent-selection-context.d.ts +14 -0
- package/dist/provider/agent-selection-context.js +6 -0
- package/dist/provider/agent-selection-context.js.map +1 -0
- package/dist/react/package.json.cjs +1 -1
- package/dist/react/package.json.js +1 -1
- package/dist/runtime/StatewireThreadConfigLaneSync.cjs +125 -0
- package/dist/runtime/StatewireThreadConfigLaneSync.cjs.map +1 -0
- package/dist/runtime/StatewireThreadConfigLaneSync.d.ts +54 -0
- package/dist/runtime/StatewireThreadConfigLaneSync.js +125 -0
- package/dist/runtime/StatewireThreadConfigLaneSync.js.map +1 -0
- package/dist/runtime/statewire-lifecycle.cjs +5 -2
- package/dist/runtime/statewire-lifecycle.cjs.map +1 -1
- package/dist/runtime/statewire-lifecycle.d.ts +5 -0
- package/dist/runtime/statewire-lifecycle.js +5 -2
- package/dist/runtime/statewire-lifecycle.js.map +1 -1
- package/dist/runtime/statewire-model-lane.cjs +16 -0
- package/dist/runtime/statewire-model-lane.cjs.map +1 -0
- package/dist/runtime/statewire-model-lane.d.ts +66 -0
- package/dist/runtime/statewire-model-lane.js +16 -0
- package/dist/runtime/statewire-model-lane.js.map +1 -0
- package/dist/runtime/statewire-run-config.cjs +16 -2
- package/dist/runtime/statewire-run-config.cjs.map +1 -1
- package/dist/runtime/statewire-run-config.d.ts +10 -0
- package/dist/runtime/statewire-run-config.js +16 -2
- package/dist/runtime/statewire-run-config.js.map +1 -1
- package/dist/runtime/statewire-server-lane-context.cjs +24 -0
- package/dist/runtime/statewire-server-lane-context.cjs.map +1 -0
- package/dist/runtime/statewire-server-lane-context.d.ts +30 -0
- package/dist/runtime/statewire-server-lane-context.js +24 -0
- package/dist/runtime/statewire-server-lane-context.js.map +1 -0
- package/dist/runtime/statewire-thread-config-lane.cjs +84 -0
- package/dist/runtime/statewire-thread-config-lane.cjs.map +1 -0
- package/dist/runtime/statewire-thread-config-lane.d.ts +94 -0
- package/dist/runtime/statewire-thread-config-lane.js +84 -0
- package/dist/runtime/statewire-thread-config-lane.js.map +1 -0
- package/dist/runtime/useAthenaStatewireRuntime.cjs +38 -18
- package/dist/runtime/useAthenaStatewireRuntime.cjs.map +1 -1
- package/dist/runtime/useAthenaStatewireRuntime.d.ts +8 -1
- package/dist/runtime/useAthenaStatewireRuntime.js +39 -19
- package/dist/runtime/useAthenaStatewireRuntime.js.map +1 -1
- package/dist/styles.css +1 -1
- package/dist/threads/api.cjs +2 -1
- package/dist/threads/api.cjs.map +1 -1
- package/dist/threads/api.d.ts +1 -0
- package/dist/threads/api.js +2 -1
- package/dist/threads/api.js.map +1 -1
- package/dist/threads/use-athena-thread-model.cjs +22 -0
- package/dist/threads/use-athena-thread-model.cjs.map +1 -0
- package/dist/threads/use-athena-thread-model.d.ts +27 -0
- package/dist/threads/use-athena-thread-model.js +22 -0
- package/dist/threads/use-athena-thread-model.js.map +1 -0
- package/package.json +4 -4
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import { QueryClient } from '@tanstack/react-query';
|
|
2
|
+
import { type MentionAuthContext } from '../chat-ui/mentions/suggestions/data/api-client';
|
|
3
|
+
import { type AgentModelSource, type AthenaAgentModelOption } from './agent-model-options';
|
|
1
4
|
/**
|
|
2
5
|
* The workspace's runtime catalog for a chat's model and agent pickers: the models the signed-in
|
|
3
6
|
* person may run (the workspace's allow or deny list, admin-only models for admins), and the
|
|
@@ -96,5 +99,106 @@ export declare function credentialFingerprint({ credential }: {
|
|
|
96
99
|
}): string;
|
|
97
100
|
/** The models the signed-in person may pick (`normalizeModelCatalog`). */
|
|
98
101
|
export declare function useAthenaModelCatalog(): import("@tanstack/react-query").UseQueryResult<AthenaModelOption[], Error>;
|
|
102
|
+
/** The model catalog's query on a given client (one client for every read a hook makes). */
|
|
103
|
+
declare function useModelCatalogQuery({ auth, principal, queryClient, }: {
|
|
104
|
+
auth: MentionAuthContext;
|
|
105
|
+
principal: string;
|
|
106
|
+
queryClient: QueryClient;
|
|
107
|
+
}): import("@tanstack/react-query").UseQueryResult<AthenaModelOption[], Error>;
|
|
99
108
|
/** The published collab agents the signed-in person can see (`normalizeAgentCatalog`). */
|
|
100
109
|
export declare function useAthenaAgentCatalog(): import("@tanstack/react-query").UseQueryResult<AthenaAgentOption[], Error>;
|
|
110
|
+
export declare const ATHENA_AGENT_MODELS_QUERY = "\n query AthenaAgentModels($assetId: String!) {\n getAssetById(assetId: $assetId, withMetadata: true) { athenaMetadata }\n }\n";
|
|
111
|
+
/** What reading the agent's published models found: its models, or that this person cannot know them. */
|
|
112
|
+
export type AgentModelRead = {
|
|
113
|
+
readable: true;
|
|
114
|
+
source: AgentModelSource | null;
|
|
115
|
+
} | {
|
|
116
|
+
readable: false;
|
|
117
|
+
};
|
|
118
|
+
/**
|
|
119
|
+
* Where `useAthenaAgentModelOptions` stands:
|
|
120
|
+
*
|
|
121
|
+
* - `idle`: no agent given;
|
|
122
|
+
* - `loading`: the agent (or the model catalog that names its models) is being read;
|
|
123
|
+
* - `ready`: the agent's published models are known;
|
|
124
|
+
* - `unavailable`: this person cannot know them: no VIEW on the agent, no such
|
|
125
|
+
* agent, or one never published (or whose published definition names no
|
|
126
|
+
* model). Not an error: `allowAnyModel` stays `true`, so a picker keeps the
|
|
127
|
+
* workspace's models;
|
|
128
|
+
* - `error`: the read failed (network, server); `allowAnyModel` stays `true`.
|
|
129
|
+
*/
|
|
130
|
+
export type AthenaAgentModelOptionsStatus = 'idle' | 'loading' | 'ready' | 'unavailable' | 'error';
|
|
131
|
+
export interface AthenaAgentModelOptions {
|
|
132
|
+
status: AthenaAgentModelOptionsStatus;
|
|
133
|
+
/** The agent's model choices (see {@link AthenaAgentModelOption}); empty unless `ready`. */
|
|
134
|
+
options: readonly AthenaAgentModelOption[];
|
|
135
|
+
/**
|
|
136
|
+
* The model the thread runs while it pins none: the channel's override, else
|
|
137
|
+
* the agent's own model. `null` unless `ready`.
|
|
138
|
+
*/
|
|
139
|
+
defaultModel: string | null;
|
|
140
|
+
/**
|
|
141
|
+
* Whether people may pick any workspace model with this agent: the agent's
|
|
142
|
+
* "Allow any workspace model" switch (`allowAnyModel` in its published
|
|
143
|
+
* definition). Only an explicit `false` restricts a picker to `options`;
|
|
144
|
+
* absent, `null` or `true` (every agent saved before the switch) allow any,
|
|
145
|
+
* and so does an agent this person cannot read. `true` unless `ready`.
|
|
146
|
+
*/
|
|
147
|
+
allowAnyModel: boolean;
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* A selected collab agent's own model choices, and whether the agent restricts
|
|
151
|
+
* a picker to them (`allowAnyModel: false`, the agent's "Allow any workspace
|
|
152
|
+
* model" switch turned off). Restriction is opt-in per agent: with
|
|
153
|
+
* `allowAnyModel` true (the default) a picker keeps the workspace's models and
|
|
154
|
+
* can still show `defaultModel` as the agent's own; `ChatModelPicker` does
|
|
155
|
+
* both.
|
|
156
|
+
*
|
|
157
|
+
* `agent` is the agent's asset id or its `collab_agent:<id>` ref (`null`:
|
|
158
|
+
* none, `idle`). `channel` is the collab channel the chat runs on: its model
|
|
159
|
+
* override is the default there. The rules are in `agent-model-options.ts`.
|
|
160
|
+
*
|
|
161
|
+
* The agent is read through `getAssetById(withMetadata: true)`, the
|
|
162
|
+
* permission-checked asset read (VIEW on the agent), with the provider's
|
|
163
|
+
* credentials: a person without VIEW gets `unavailable` with no options. The
|
|
164
|
+
* model the thread pins comes from `useAthenaThreadModel()` (inside
|
|
165
|
+
* `<AthenaProvider>`; none outside one): a pinned model outside the agent's
|
|
166
|
+
* list is an option with `pinnedOutside`.
|
|
167
|
+
*
|
|
168
|
+
* Picking the `isDefault` option means "no model": hand the provider
|
|
169
|
+
* `model={undefined}` so the agent's (or channel's) default runs, and a session
|
|
170
|
+
* pinning another model is unpinned.
|
|
171
|
+
*
|
|
172
|
+
* While shown, the agent is read again every
|
|
173
|
+
* {@link AGENT_MODELS_REFRESH_MS}: an author publishing new models elsewhere
|
|
174
|
+
* invalidates nothing here.
|
|
175
|
+
*/
|
|
176
|
+
export declare function useAthenaAgentModelOptions({ agent, channel, }: {
|
|
177
|
+
agent: string | null | undefined;
|
|
178
|
+
channel?: string | null;
|
|
179
|
+
}): AthenaAgentModelOptions;
|
|
180
|
+
/** How often an agent's published models are read again while a hook shows them. */
|
|
181
|
+
export declare const AGENT_MODELS_REFRESH_MS: number;
|
|
182
|
+
/**
|
|
183
|
+
* The re-read cadence of an agent model read: every
|
|
184
|
+
* {@link AGENT_MODELS_REFRESH_MS} while it answers, never for a denial (asking
|
|
185
|
+
* again answers the same).
|
|
186
|
+
*/
|
|
187
|
+
export declare function agentModelsRefetchInterval({ data, }: {
|
|
188
|
+
data: AgentModelRead | undefined;
|
|
189
|
+
}): number | false;
|
|
190
|
+
/**
|
|
191
|
+
* {@link useAthenaAgentModelOptions} plus the catalog label of any model id,
|
|
192
|
+
* from the same query client and catalog read (a picker needs both; reading
|
|
193
|
+
* the catalog again through its own client would fetch it twice). Internal.
|
|
194
|
+
*/
|
|
195
|
+
export declare function useAgentModelChoices({ agent, channel, }: {
|
|
196
|
+
agent: string | null | undefined;
|
|
197
|
+
channel: string | null;
|
|
198
|
+
}): {
|
|
199
|
+
choices: AthenaAgentModelOptions;
|
|
200
|
+
modelLabel: (model: string) => string;
|
|
201
|
+
/** The workspace model catalog, read through the same client as the agent. */
|
|
202
|
+
catalog: ReturnType<typeof useModelCatalogQuery>;
|
|
203
|
+
};
|
|
204
|
+
export {};
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { useQuery, QueryClientContext, QueryClient } from "@tanstack/react-query";
|
|
2
|
-
import { useMemo, useContext, useState } from "react";
|
|
2
|
+
import { useMemo, useContext, useState, useCallback } from "react";
|
|
3
3
|
import { AthenaAuthContext } from "../auth/AthenaAuthContext.js";
|
|
4
|
-
import { fetchGraphQL } from "../chat-ui/mentions/suggestions/data/api-client.js";
|
|
4
|
+
import { fetchGraphQL, AthenaGraphQLError } from "../chat-ui/mentions/suggestions/data/api-client.js";
|
|
5
5
|
import { useAthenaConfig } from "../provider/AthenaContext.js";
|
|
6
|
+
import { useOptionalAthenaThreadModel } from "../threads/use-athena-thread-model.js";
|
|
7
|
+
import { agentAssetIdOf, publishedAgentModelSource, buildAgentModelOptions } from "./agent-model-options.js";
|
|
6
8
|
const MODEL_PROVIDER_LABELS = {
|
|
7
9
|
ANTHROPIC: "Anthropic",
|
|
8
10
|
OPENAI: "OpenAI",
|
|
@@ -134,9 +136,17 @@ function useCatalogQueryClient() {
|
|
|
134
136
|
return host ?? own;
|
|
135
137
|
}
|
|
136
138
|
function useAthenaModelCatalog() {
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
139
|
+
return useModelCatalogQuery({
|
|
140
|
+
auth: useCatalogAuth(),
|
|
141
|
+
principal: useCatalogPrincipal(),
|
|
142
|
+
queryClient: useCatalogQueryClient()
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
function useModelCatalogQuery({
|
|
146
|
+
auth,
|
|
147
|
+
principal,
|
|
148
|
+
queryClient
|
|
149
|
+
}) {
|
|
140
150
|
return useQuery(
|
|
141
151
|
{
|
|
142
152
|
queryKey: ["athena-sdk", "catalog", "models", auth.backendUrl, principal],
|
|
@@ -166,16 +176,120 @@ function useAthenaAgentCatalog() {
|
|
|
166
176
|
queryClient
|
|
167
177
|
);
|
|
168
178
|
}
|
|
179
|
+
const ATHENA_AGENT_MODELS_QUERY = `
|
|
180
|
+
query AthenaAgentModels($assetId: String!) {
|
|
181
|
+
getAssetById(assetId: $assetId, withMetadata: true) { athenaMetadata }
|
|
182
|
+
}
|
|
183
|
+
`;
|
|
184
|
+
const AGENT_READ_DENIAL_CODES = /* @__PURE__ */ new Set([
|
|
185
|
+
"UNAUTHORIZED",
|
|
186
|
+
"FORBIDDEN",
|
|
187
|
+
"WORKSPACE_MISMATCH"
|
|
188
|
+
]);
|
|
189
|
+
const NO_AGENT_MODEL_OPTIONS = {
|
|
190
|
+
idle: { status: "idle", options: [], defaultModel: null, allowAnyModel: true },
|
|
191
|
+
loading: { status: "loading", options: [], defaultModel: null, allowAnyModel: true },
|
|
192
|
+
unavailable: { status: "unavailable", options: [], defaultModel: null, allowAnyModel: true },
|
|
193
|
+
error: { status: "error", options: [], defaultModel: null, allowAnyModel: true }
|
|
194
|
+
};
|
|
195
|
+
function isAgentReadDenial(error) {
|
|
196
|
+
return error instanceof AthenaGraphQLError && error.code !== null && AGENT_READ_DENIAL_CODES.has(error.code);
|
|
197
|
+
}
|
|
198
|
+
function useAthenaAgentModelOptions({
|
|
199
|
+
agent,
|
|
200
|
+
channel = null
|
|
201
|
+
}) {
|
|
202
|
+
return useAgentModelChoices({ agent, channel }).choices;
|
|
203
|
+
}
|
|
204
|
+
const AGENT_MODELS_REFRESH_MS = 60 * 1e3;
|
|
205
|
+
function agentModelsRefetchInterval({
|
|
206
|
+
data
|
|
207
|
+
}) {
|
|
208
|
+
return data !== void 0 && !data.readable ? false : AGENT_MODELS_REFRESH_MS;
|
|
209
|
+
}
|
|
210
|
+
function useAgentModelChoices({
|
|
211
|
+
agent,
|
|
212
|
+
channel
|
|
213
|
+
}) {
|
|
214
|
+
const assetId = agentAssetIdOf(agent);
|
|
215
|
+
const auth = useCatalogAuth();
|
|
216
|
+
const principal = useCatalogPrincipal();
|
|
217
|
+
const queryClient = useCatalogQueryClient();
|
|
218
|
+
const read = useQuery(
|
|
219
|
+
{
|
|
220
|
+
queryKey: ["athena-sdk", "catalog", "agent-models", auth.backendUrl, principal, assetId],
|
|
221
|
+
queryFn: async () => {
|
|
222
|
+
try {
|
|
223
|
+
const data = await fetchGraphQL(
|
|
224
|
+
auth,
|
|
225
|
+
ATHENA_AGENT_MODELS_QUERY,
|
|
226
|
+
{ assetId }
|
|
227
|
+
);
|
|
228
|
+
if (data.getAssetById === null) return { readable: false };
|
|
229
|
+
return {
|
|
230
|
+
readable: true,
|
|
231
|
+
source: publishedAgentModelSource(data.getAssetById.athenaMetadata)
|
|
232
|
+
};
|
|
233
|
+
} catch (error) {
|
|
234
|
+
if (isAgentReadDenial(error)) return { readable: false };
|
|
235
|
+
throw error;
|
|
236
|
+
}
|
|
237
|
+
},
|
|
238
|
+
enabled: assetId !== null,
|
|
239
|
+
staleTime: AGENT_MODELS_REFRESH_MS,
|
|
240
|
+
refetchInterval: (query) => agentModelsRefetchInterval({ data: query.state.data })
|
|
241
|
+
},
|
|
242
|
+
queryClient
|
|
243
|
+
);
|
|
244
|
+
const catalog = useModelCatalogQuery({ auth, principal, queryClient });
|
|
245
|
+
const threadModel = useOptionalAthenaThreadModel();
|
|
246
|
+
const pinnedModel = threadModel !== null && threadModel.ready && threadModel.configured ? threadModel.model : null;
|
|
247
|
+
const trimmedChannel = (channel == null ? void 0 : channel.trim()) || null;
|
|
248
|
+
const models = catalog.data;
|
|
249
|
+
const catalogPending = catalog.isPending;
|
|
250
|
+
const { isPending: readPending, data: readData } = read;
|
|
251
|
+
const modelLabel = useCallback(
|
|
252
|
+
(model) => {
|
|
253
|
+
var _a;
|
|
254
|
+
return ((_a = models == null ? void 0 : models.find((option) => option.id === model)) == null ? void 0 : _a.label) ?? model;
|
|
255
|
+
},
|
|
256
|
+
[models]
|
|
257
|
+
);
|
|
258
|
+
const choices = useMemo(() => {
|
|
259
|
+
if (assetId === null) return NO_AGENT_MODEL_OPTIONS.idle;
|
|
260
|
+
if (readData === void 0) {
|
|
261
|
+
return readPending ? NO_AGENT_MODEL_OPTIONS.loading : NO_AGENT_MODEL_OPTIONS.error;
|
|
262
|
+
}
|
|
263
|
+
if (!readData.readable || readData.source === null) return NO_AGENT_MODEL_OPTIONS.unavailable;
|
|
264
|
+
if (catalogPending) return NO_AGENT_MODEL_OPTIONS.loading;
|
|
265
|
+
return {
|
|
266
|
+
status: "ready",
|
|
267
|
+
...buildAgentModelOptions({
|
|
268
|
+
source: readData.source,
|
|
269
|
+
channel: trimmedChannel,
|
|
270
|
+
pinnedModel,
|
|
271
|
+
modelLabel
|
|
272
|
+
}),
|
|
273
|
+
allowAnyModel: readData.source.allowAnyModel
|
|
274
|
+
};
|
|
275
|
+
}, [assetId, readPending, readData, catalogPending, modelLabel, trimmedChannel, pinnedModel]);
|
|
276
|
+
return useMemo(() => ({ choices, modelLabel, catalog }), [choices, modelLabel, catalog]);
|
|
277
|
+
}
|
|
169
278
|
export {
|
|
279
|
+
AGENT_MODELS_REFRESH_MS,
|
|
170
280
|
ATHENA_AGENT_CATALOG_QUERY,
|
|
281
|
+
ATHENA_AGENT_MODELS_QUERY,
|
|
171
282
|
ATHENA_MODEL_CATALOG_QUERY,
|
|
172
283
|
MODEL_PROVIDER_LABELS,
|
|
284
|
+
agentModelsRefetchInterval,
|
|
173
285
|
credentialFingerprint,
|
|
174
286
|
groupModelsByProvider,
|
|
175
287
|
normalizeAgentCatalog,
|
|
176
288
|
normalizeModelCatalog,
|
|
177
289
|
resolveCatalogModelId,
|
|
290
|
+
useAgentModelChoices,
|
|
178
291
|
useAthenaAgentCatalog,
|
|
292
|
+
useAthenaAgentModelOptions,
|
|
179
293
|
useAthenaModelCatalog
|
|
180
294
|
};
|
|
181
295
|
//# sourceMappingURL=runtime-catalog.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runtime-catalog.js","sources":["../../src/catalog/runtime-catalog.ts"],"sourcesContent":["import { QueryClient, QueryClientContext, useQuery } from '@tanstack/react-query';\nimport { useContext, useMemo, useState } from 'react';\nimport { AthenaAuthContext } from '../auth/AthenaAuthContext';\nimport { fetchGraphQL, type MentionAuthContext } from '../chat-ui/mentions/suggestions/data/api-client';\nimport { useAthenaConfig } from '../provider/AthenaContext';\n\n/**\n * The workspace's runtime catalog for a chat's model and agent pickers: the models the signed-in\n * person may run (the workspace's allow or deny list, admin-only models for admins), and the\n * published collab agents they can see. The rules are the Chrome extension's, which every host now\n * reads from here.\n */\n\nexport type AthenaModelStatus = 'ACTIVE' | 'LEGACY' | 'RECOMMENDED';\n\nexport interface AthenaModelOption {\n id: string;\n label: string;\n description: string | null;\n /** Upper-case provider key, e.g. `ANTHROPIC`, `OPENAI`. */\n provider: string;\n status: AthenaModelStatus;\n sortOrder: number;\n familyId: string;\n familyName: string;\n isFamilyDefault: boolean;\n isFeatured: boolean;\n variantOrder: number;\n}\n\nexport interface AthenaAgentOption {\n /** The collab agent's asset id; pass `collab_agent:<id>` as the provider's `agent`. */\n id: string;\n name: string;\n}\n\n/** The provider labels a model picker groups by. */\nexport const MODEL_PROVIDER_LABELS: Readonly<Record<string, string>> = {\n ANTHROPIC: 'Anthropic',\n OPENAI: 'OpenAI',\n GOOGLE: 'Google',\n XAI: 'xAI',\n META: 'Meta',\n MISTRAL: 'Mistral',\n DEEPSEEK: 'DeepSeek',\n QWEN: 'Qwen',\n MOONSHOT: 'Moonshot',\n MINIMAX: 'MiniMax',\n ZAI: 'Z.ai',\n};\n\nexport const ATHENA_MODEL_CATALOG_QUERY = `\n query AthenaModelCatalog {\n getCurrentUserWithWorkspace { user { isAdmin } }\n settings { workspace { approvedLargeLlms blacklistedLlms } }\n availableModels {\n id name provider status description adminOnly sortOrder\n familyId familyName isFamilyDefault isFeatured variantOrder\n }\n }\n`;\n\nexport const ATHENA_AGENT_CATALOG_QUERY = `\n query AthenaAgentCatalog {\n getAllAssets(filterByAthenaOriginalType: [\"collab_agent\"]) { id title }\n }\n`;\n\nexport interface AthenaModelCatalogResponse {\n getCurrentUserWithWorkspace: { user: { isAdmin: boolean } };\n settings: { workspace: { approvedLargeLlms: string[]; blacklistedLlms: string[] } };\n availableModels: Array<{\n id: string;\n name: string;\n provider: string;\n status: AthenaModelStatus;\n description: string | null;\n adminOnly: boolean;\n sortOrder: number;\n familyId: string;\n familyName: string;\n isFamilyDefault: boolean;\n isFeatured: boolean;\n variantOrder: number;\n }>;\n}\n\n/**\n * The models the person may pick, in catalog order. A workspace with an allow list offers only\n * those; otherwise everything except its deny list. Admin-only models are offered to admins only.\n */\nexport function normalizeModelCatalog({\n response,\n}: {\n response: AthenaModelCatalogResponse;\n}): AthenaModelOption[] {\n const isAdmin = response.getCurrentUserWithWorkspace.user.isAdmin;\n const approved = new Set(response.settings.workspace.approvedLargeLlms);\n const denied = new Set(response.settings.workspace.blacklistedLlms);\n const hasAllowlist = approved.size > 0;\n return response.availableModels\n .filter(\n (model) =>\n (!model.adminOnly || isAdmin) && (hasAllowlist ? approved.has(model.id) : !denied.has(model.id)),\n )\n .map(\n (model): AthenaModelOption => ({\n id: model.id,\n label: model.name,\n description: model.description,\n provider: model.provider,\n status: model.status,\n sortOrder: model.sortOrder,\n familyId: model.familyId,\n familyName: model.familyName,\n isFamilyDefault: model.isFamilyDefault,\n isFeatured: model.isFeatured,\n variantOrder: model.variantOrder,\n }),\n )\n .sort(\n (left, right) =>\n left.sortOrder - right.sortOrder ||\n left.variantOrder - right.variantOrder ||\n left.label.localeCompare(right.label),\n );\n}\n\n/** The published collab agents, named and sorted; assets with a blank id are dropped. */\nexport function normalizeAgentCatalog({\n assets,\n}: {\n assets: ReadonlyArray<{ id: string; title: string | null }>;\n}): AthenaAgentOption[] {\n return assets\n .filter((asset) => asset.id.trim().length > 0)\n .map((asset) => ({ id: asset.id, name: asset.title?.trim() || 'Untitled agent' }))\n .sort((left, right) => left.name.localeCompare(right.name));\n}\n\n/**\n * The model a picker shows as chosen: the stored choice while the catalog offers it, else the\n * default (unless retired), else a recommended family default, else any live model. While the\n * catalog is empty (loading, or unreachable) the stored choice or the default stands.\n */\nexport function resolveCatalogModelId({\n stored,\n defaultModelId,\n models,\n}: {\n stored: string | null;\n defaultModelId: string;\n models: readonly AthenaModelOption[];\n}): string {\n if (stored && models.some((model) => model.id === stored)) return stored;\n return (\n (\n models.find((model) => model.id === defaultModelId && model.status !== 'LEGACY') ??\n models.find((model) => model.status === 'RECOMMENDED' && model.isFamilyDefault) ??\n models.find((model) => model.status !== 'LEGACY' && model.isFamilyDefault) ??\n models.find((model) => model.status !== 'LEGACY') ??\n models[0]\n )?.id ?? (stored || defaultModelId)\n );\n}\n\n/** Models grouped under their provider's label, in catalog order. */\nexport function groupModelsByProvider({\n models,\n}: {\n models: readonly AthenaModelOption[];\n}): Array<{ provider: string; models: AthenaModelOption[] }> {\n const groups = new Map<string, AthenaModelOption[]>();\n for (const model of models) {\n const label = MODEL_PROVIDER_LABELS[model.provider] ?? model.provider;\n groups.set(label, [...(groups.get(label) ?? []), model]);\n }\n return Array.from(groups, ([provider, grouped]) => ({ provider, models: grouped }));\n}\n\n/** The provider's credentials as the SDK's GraphQL client takes them. */\nfunction useCatalogAuth(): MentionAuthContext {\n const config = useAthenaConfig();\n return useMemo<MentionAuthContext>(\n () => ({\n backendUrl: config.backendUrl,\n appUrl: config.appUrl,\n apiKey: config.apiKey,\n credentials: 'include',\n get accessToken() {\n return config.token ?? undefined;\n },\n getAccessToken: async () => (await config.getToken?.()) ?? undefined,\n renewAccessToken: async () => (await config.getToken?.({ force: true })) ?? undefined,\n }),\n [config],\n );\n}\n\n/**\n * A short fingerprint (two FNV-1a rounds, 64 bits) of a credential: it tells accounts apart in an\n * in-memory cache key without the credential itself, or anything it could be recovered from,\n * entering the key.\n */\nexport function credentialFingerprint({ credential }: { credential: string }): string {\n const round = (seed: number) => {\n let hash = seed;\n for (let index = 0; index < credential.length; index += 1) {\n hash ^= credential.charCodeAt(index);\n hash = Math.imul(hash, 0x01000193) >>> 0;\n }\n return hash.toString(16).padStart(8, '0');\n };\n return `${round(0x811c9dc5)}${round(0x01000193)}`;\n}\n\n/**\n * Who is asking, for the cache key: the catalog differs per account (admin-only models, the\n * workspace's lists, the agents shared with them), and a host can switch accounts while keeping its\n * query client. The signed-in user's id when the SDK knows it, else a fingerprint of the credential\n * in use. Never the credential itself.\n */\nfunction useCatalogPrincipal(): string {\n const config = useAthenaConfig();\n const userId = useContext(AthenaAuthContext)?.user?.userId;\n if (userId) return `user:${userId}`;\n if (config.apiKey) return `key:${credentialFingerprint({ credential: config.apiKey })}`;\n if (config.token) return `token:${credentialFingerprint({ credential: config.token })}`;\n return 'session';\n}\n\n/**\n * The host's QueryClient when there is one (the thread list provides one), else one of the\n * pickers' own, so the catalog hooks work with or without the thread list.\n */\nfunction useCatalogQueryClient(): QueryClient {\n const host = useContext(QueryClientContext);\n const [own] = useState(() => new QueryClient());\n return host ?? own;\n}\n\n/** The models the signed-in person may pick (`normalizeModelCatalog`). */\nexport function useAthenaModelCatalog() {\n const auth = useCatalogAuth();\n const principal = useCatalogPrincipal();\n const queryClient = useCatalogQueryClient();\n return useQuery(\n {\n queryKey: ['athena-sdk', 'catalog', 'models', auth.backendUrl, principal],\n queryFn: async () =>\n normalizeModelCatalog({\n response: await fetchGraphQL<AthenaModelCatalogResponse>(auth, ATHENA_MODEL_CATALOG_QUERY),\n }),\n staleTime: 5 * 60 * 1000,\n },\n queryClient,\n );\n}\n\n/** The published collab agents the signed-in person can see (`normalizeAgentCatalog`). */\nexport function useAthenaAgentCatalog() {\n const auth = useCatalogAuth();\n const principal = useCatalogPrincipal();\n const queryClient = useCatalogQueryClient();\n return useQuery(\n {\n queryKey: ['athena-sdk', 'catalog', 'agents', auth.backendUrl, principal],\n queryFn: async () =>\n normalizeAgentCatalog({\n assets:\n (\n await fetchGraphQL<{ getAllAssets: Array<{ id: string; title: string | null }> }>(\n auth,\n ATHENA_AGENT_CATALOG_QUERY,\n )\n ).getAllAssets ?? [],\n }),\n staleTime: 60 * 1000,\n },\n queryClient,\n );\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"runtime-catalog.js","sources":["../../src/catalog/runtime-catalog.ts"],"sourcesContent":["import { QueryClient, QueryClientContext, useQuery } from '@tanstack/react-query';\nimport { useCallback, useContext, useMemo, useState } from 'react';\nimport { AthenaAuthContext } from '../auth/AthenaAuthContext';\nimport {\n AthenaGraphQLError,\n fetchGraphQL,\n type MentionAuthContext,\n} from '../chat-ui/mentions/suggestions/data/api-client';\nimport { useAthenaConfig } from '../provider/AthenaContext';\nimport { useOptionalAthenaThreadModel } from '../threads/use-athena-thread-model';\nimport {\n type AgentModelSource,\n type AthenaAgentModelOption,\n agentAssetIdOf,\n buildAgentModelOptions,\n publishedAgentModelSource,\n} from './agent-model-options';\n\n/**\n * The workspace's runtime catalog for a chat's model and agent pickers: the models the signed-in\n * person may run (the workspace's allow or deny list, admin-only models for admins), and the\n * published collab agents they can see. The rules are the Chrome extension's, which every host now\n * reads from here.\n */\n\nexport type AthenaModelStatus = 'ACTIVE' | 'LEGACY' | 'RECOMMENDED';\n\nexport interface AthenaModelOption {\n id: string;\n label: string;\n description: string | null;\n /** Upper-case provider key, e.g. `ANTHROPIC`, `OPENAI`. */\n provider: string;\n status: AthenaModelStatus;\n sortOrder: number;\n familyId: string;\n familyName: string;\n isFamilyDefault: boolean;\n isFeatured: boolean;\n variantOrder: number;\n}\n\nexport interface AthenaAgentOption {\n /** The collab agent's asset id; pass `collab_agent:<id>` as the provider's `agent`. */\n id: string;\n name: string;\n}\n\n/** The provider labels a model picker groups by. */\nexport const MODEL_PROVIDER_LABELS: Readonly<Record<string, string>> = {\n ANTHROPIC: 'Anthropic',\n OPENAI: 'OpenAI',\n GOOGLE: 'Google',\n XAI: 'xAI',\n META: 'Meta',\n MISTRAL: 'Mistral',\n DEEPSEEK: 'DeepSeek',\n QWEN: 'Qwen',\n MOONSHOT: 'Moonshot',\n MINIMAX: 'MiniMax',\n ZAI: 'Z.ai',\n};\n\nexport const ATHENA_MODEL_CATALOG_QUERY = `\n query AthenaModelCatalog {\n getCurrentUserWithWorkspace { user { isAdmin } }\n settings { workspace { approvedLargeLlms blacklistedLlms } }\n availableModels {\n id name provider status description adminOnly sortOrder\n familyId familyName isFamilyDefault isFeatured variantOrder\n }\n }\n`;\n\nexport const ATHENA_AGENT_CATALOG_QUERY = `\n query AthenaAgentCatalog {\n getAllAssets(filterByAthenaOriginalType: [\"collab_agent\"]) { id title }\n }\n`;\n\nexport interface AthenaModelCatalogResponse {\n getCurrentUserWithWorkspace: { user: { isAdmin: boolean } };\n settings: { workspace: { approvedLargeLlms: string[]; blacklistedLlms: string[] } };\n availableModels: Array<{\n id: string;\n name: string;\n provider: string;\n status: AthenaModelStatus;\n description: string | null;\n adminOnly: boolean;\n sortOrder: number;\n familyId: string;\n familyName: string;\n isFamilyDefault: boolean;\n isFeatured: boolean;\n variantOrder: number;\n }>;\n}\n\n/**\n * The models the person may pick, in catalog order. A workspace with an allow list offers only\n * those; otherwise everything except its deny list. Admin-only models are offered to admins only.\n */\nexport function normalizeModelCatalog({\n response,\n}: {\n response: AthenaModelCatalogResponse;\n}): AthenaModelOption[] {\n const isAdmin = response.getCurrentUserWithWorkspace.user.isAdmin;\n const approved = new Set(response.settings.workspace.approvedLargeLlms);\n const denied = new Set(response.settings.workspace.blacklistedLlms);\n const hasAllowlist = approved.size > 0;\n return response.availableModels\n .filter(\n (model) =>\n (!model.adminOnly || isAdmin) && (hasAllowlist ? approved.has(model.id) : !denied.has(model.id)),\n )\n .map(\n (model): AthenaModelOption => ({\n id: model.id,\n label: model.name,\n description: model.description,\n provider: model.provider,\n status: model.status,\n sortOrder: model.sortOrder,\n familyId: model.familyId,\n familyName: model.familyName,\n isFamilyDefault: model.isFamilyDefault,\n isFeatured: model.isFeatured,\n variantOrder: model.variantOrder,\n }),\n )\n .sort(\n (left, right) =>\n left.sortOrder - right.sortOrder ||\n left.variantOrder - right.variantOrder ||\n left.label.localeCompare(right.label),\n );\n}\n\n/** The published collab agents, named and sorted; assets with a blank id are dropped. */\nexport function normalizeAgentCatalog({\n assets,\n}: {\n assets: ReadonlyArray<{ id: string; title: string | null }>;\n}): AthenaAgentOption[] {\n return assets\n .filter((asset) => asset.id.trim().length > 0)\n .map((asset) => ({ id: asset.id, name: asset.title?.trim() || 'Untitled agent' }))\n .sort((left, right) => left.name.localeCompare(right.name));\n}\n\n/**\n * The model a picker shows as chosen: the stored choice while the catalog offers it, else the\n * default (unless retired), else a recommended family default, else any live model. While the\n * catalog is empty (loading, or unreachable) the stored choice or the default stands.\n */\nexport function resolveCatalogModelId({\n stored,\n defaultModelId,\n models,\n}: {\n stored: string | null;\n defaultModelId: string;\n models: readonly AthenaModelOption[];\n}): string {\n if (stored && models.some((model) => model.id === stored)) return stored;\n return (\n (\n models.find((model) => model.id === defaultModelId && model.status !== 'LEGACY') ??\n models.find((model) => model.status === 'RECOMMENDED' && model.isFamilyDefault) ??\n models.find((model) => model.status !== 'LEGACY' && model.isFamilyDefault) ??\n models.find((model) => model.status !== 'LEGACY') ??\n models[0]\n )?.id ?? (stored || defaultModelId)\n );\n}\n\n/** Models grouped under their provider's label, in catalog order. */\nexport function groupModelsByProvider({\n models,\n}: {\n models: readonly AthenaModelOption[];\n}): Array<{ provider: string; models: AthenaModelOption[] }> {\n const groups = new Map<string, AthenaModelOption[]>();\n for (const model of models) {\n const label = MODEL_PROVIDER_LABELS[model.provider] ?? model.provider;\n groups.set(label, [...(groups.get(label) ?? []), model]);\n }\n return Array.from(groups, ([provider, grouped]) => ({ provider, models: grouped }));\n}\n\n/** The provider's credentials as the SDK's GraphQL client takes them. */\nfunction useCatalogAuth(): MentionAuthContext {\n const config = useAthenaConfig();\n return useMemo<MentionAuthContext>(\n () => ({\n backendUrl: config.backendUrl,\n appUrl: config.appUrl,\n apiKey: config.apiKey,\n credentials: 'include',\n get accessToken() {\n return config.token ?? undefined;\n },\n getAccessToken: async () => (await config.getToken?.()) ?? undefined,\n renewAccessToken: async () => (await config.getToken?.({ force: true })) ?? undefined,\n }),\n [config],\n );\n}\n\n/**\n * A short fingerprint (two FNV-1a rounds, 64 bits) of a credential: it tells accounts apart in an\n * in-memory cache key without the credential itself, or anything it could be recovered from,\n * entering the key.\n */\nexport function credentialFingerprint({ credential }: { credential: string }): string {\n const round = (seed: number) => {\n let hash = seed;\n for (let index = 0; index < credential.length; index += 1) {\n hash ^= credential.charCodeAt(index);\n hash = Math.imul(hash, 0x01000193) >>> 0;\n }\n return hash.toString(16).padStart(8, '0');\n };\n return `${round(0x811c9dc5)}${round(0x01000193)}`;\n}\n\n/**\n * Who is asking, for the cache key: the catalog differs per account (admin-only models, the\n * workspace's lists, the agents shared with them), and a host can switch accounts while keeping its\n * query client. The signed-in user's id when the SDK knows it, else a fingerprint of the credential\n * in use. Never the credential itself.\n */\nfunction useCatalogPrincipal(): string {\n const config = useAthenaConfig();\n const userId = useContext(AthenaAuthContext)?.user?.userId;\n if (userId) return `user:${userId}`;\n if (config.apiKey) return `key:${credentialFingerprint({ credential: config.apiKey })}`;\n if (config.token) return `token:${credentialFingerprint({ credential: config.token })}`;\n return 'session';\n}\n\n/**\n * The host's QueryClient when there is one (the thread list provides one), else one of the\n * pickers' own, so the catalog hooks work with or without the thread list.\n */\nfunction useCatalogQueryClient(): QueryClient {\n const host = useContext(QueryClientContext);\n const [own] = useState(() => new QueryClient());\n return host ?? own;\n}\n\n/** The models the signed-in person may pick (`normalizeModelCatalog`). */\nexport function useAthenaModelCatalog() {\n return useModelCatalogQuery({\n auth: useCatalogAuth(),\n principal: useCatalogPrincipal(),\n queryClient: useCatalogQueryClient(),\n });\n}\n\n/** The model catalog's query on a given client (one client for every read a hook makes). */\nfunction useModelCatalogQuery({\n auth,\n principal,\n queryClient,\n}: {\n auth: MentionAuthContext;\n principal: string;\n queryClient: QueryClient;\n}) {\n return useQuery(\n {\n queryKey: ['athena-sdk', 'catalog', 'models', auth.backendUrl, principal],\n queryFn: async () =>\n normalizeModelCatalog({\n response: await fetchGraphQL<AthenaModelCatalogResponse>(auth, ATHENA_MODEL_CATALOG_QUERY),\n }),\n staleTime: 5 * 60 * 1000,\n },\n queryClient,\n );\n}\n\n/** The published collab agents the signed-in person can see (`normalizeAgentCatalog`). */\nexport function useAthenaAgentCatalog() {\n const auth = useCatalogAuth();\n const principal = useCatalogPrincipal();\n const queryClient = useCatalogQueryClient();\n return useQuery(\n {\n queryKey: ['athena-sdk', 'catalog', 'agents', auth.backendUrl, principal],\n queryFn: async () =>\n normalizeAgentCatalog({\n assets:\n (\n await fetchGraphQL<{ getAllAssets: Array<{ id: string; title: string | null }> }>(\n auth,\n ATHENA_AGENT_CATALOG_QUERY,\n )\n ).getAllAssets ?? [],\n }),\n staleTime: 60 * 1000,\n },\n queryClient,\n );\n}\n\nexport const ATHENA_AGENT_MODELS_QUERY = `\n query AthenaAgentModels($assetId: String!) {\n getAssetById(assetId: $assetId, withMetadata: true) { athenaMetadata }\n }\n`;\n\n/**\n * The `getAssetById` error codes that mean \"this person may not read the\n * agent\": no VIEW on it (`UNAUTHORIZED`, `FORBIDDEN`), or it lives in another\n * workspace (`WORKSPACE_MISMATCH`). Asking again answers the same.\n */\nconst AGENT_READ_DENIAL_CODES: ReadonlySet<string> = new Set([\n 'UNAUTHORIZED',\n 'FORBIDDEN',\n 'WORKSPACE_MISMATCH',\n]);\n\n/** What reading the agent's published models found: its models, or that this person cannot know them. */\nexport type AgentModelRead = { readable: true; source: AgentModelSource | null } | { readable: false };\n\n/**\n * Where `useAthenaAgentModelOptions` stands:\n *\n * - `idle`: no agent given;\n * - `loading`: the agent (or the model catalog that names its models) is being read;\n * - `ready`: the agent's published models are known;\n * - `unavailable`: this person cannot know them: no VIEW on the agent, no such\n * agent, or one never published (or whose published definition names no\n * model). Not an error: `allowAnyModel` stays `true`, so a picker keeps the\n * workspace's models;\n * - `error`: the read failed (network, server); `allowAnyModel` stays `true`.\n */\nexport type AthenaAgentModelOptionsStatus = 'idle' | 'loading' | 'ready' | 'unavailable' | 'error';\n\nexport interface AthenaAgentModelOptions {\n status: AthenaAgentModelOptionsStatus;\n /** The agent's model choices (see {@link AthenaAgentModelOption}); empty unless `ready`. */\n options: readonly AthenaAgentModelOption[];\n /**\n * The model the thread runs while it pins none: the channel's override, else\n * the agent's own model. `null` unless `ready`.\n */\n defaultModel: string | null;\n /**\n * Whether people may pick any workspace model with this agent: the agent's\n * \"Allow any workspace model\" switch (`allowAnyModel` in its published\n * definition). Only an explicit `false` restricts a picker to `options`;\n * absent, `null` or `true` (every agent saved before the switch) allow any,\n * and so does an agent this person cannot read. `true` unless `ready`.\n */\n allowAnyModel: boolean;\n}\n\nconst NO_AGENT_MODEL_OPTIONS: Readonly<\n Record<Exclude<AthenaAgentModelOptionsStatus, 'ready'>, AthenaAgentModelOptions>\n> = {\n idle: { status: 'idle', options: [], defaultModel: null, allowAnyModel: true },\n loading: { status: 'loading', options: [], defaultModel: null, allowAnyModel: true },\n unavailable: { status: 'unavailable', options: [], defaultModel: null, allowAnyModel: true },\n error: { status: 'error', options: [], defaultModel: null, allowAnyModel: true },\n};\n\n/** Whether a failed read is a denial: an answer, not a failure (nothing to retry or report). */\nfunction isAgentReadDenial(error: unknown): boolean {\n return (\n error instanceof AthenaGraphQLError &&\n error.code !== null &&\n AGENT_READ_DENIAL_CODES.has(error.code)\n );\n}\n\n/**\n * A selected collab agent's own model choices, and whether the agent restricts\n * a picker to them (`allowAnyModel: false`, the agent's \"Allow any workspace\n * model\" switch turned off). Restriction is opt-in per agent: with\n * `allowAnyModel` true (the default) a picker keeps the workspace's models and\n * can still show `defaultModel` as the agent's own; `ChatModelPicker` does\n * both.\n *\n * `agent` is the agent's asset id or its `collab_agent:<id>` ref (`null`:\n * none, `idle`). `channel` is the collab channel the chat runs on: its model\n * override is the default there. The rules are in `agent-model-options.ts`.\n *\n * The agent is read through `getAssetById(withMetadata: true)`, the\n * permission-checked asset read (VIEW on the agent), with the provider's\n * credentials: a person without VIEW gets `unavailable` with no options. The\n * model the thread pins comes from `useAthenaThreadModel()` (inside\n * `<AthenaProvider>`; none outside one): a pinned model outside the agent's\n * list is an option with `pinnedOutside`.\n *\n * Picking the `isDefault` option means \"no model\": hand the provider\n * `model={undefined}` so the agent's (or channel's) default runs, and a session\n * pinning another model is unpinned.\n *\n * While shown, the agent is read again every\n * {@link AGENT_MODELS_REFRESH_MS}: an author publishing new models elsewhere\n * invalidates nothing here.\n */\nexport function useAthenaAgentModelOptions({\n agent,\n channel = null,\n}: {\n agent: string | null | undefined;\n channel?: string | null;\n}): AthenaAgentModelOptions {\n return useAgentModelChoices({ agent, channel }).choices;\n}\n\n/** How often an agent's published models are read again while a hook shows them. */\nexport const AGENT_MODELS_REFRESH_MS = 60 * 1000;\n\n/**\n * The re-read cadence of an agent model read: every\n * {@link AGENT_MODELS_REFRESH_MS} while it answers, never for a denial (asking\n * again answers the same).\n */\nexport function agentModelsRefetchInterval({\n data,\n}: {\n data: AgentModelRead | undefined;\n}): number | false {\n return data !== undefined && !data.readable ? false : AGENT_MODELS_REFRESH_MS;\n}\n\n/**\n * {@link useAthenaAgentModelOptions} plus the catalog label of any model id,\n * from the same query client and catalog read (a picker needs both; reading\n * the catalog again through its own client would fetch it twice). Internal.\n */\nexport function useAgentModelChoices({\n agent,\n channel,\n}: {\n agent: string | null | undefined;\n channel: string | null;\n}): {\n choices: AthenaAgentModelOptions;\n modelLabel: (model: string) => string;\n /** The workspace model catalog, read through the same client as the agent. */\n catalog: ReturnType<typeof useModelCatalogQuery>;\n} {\n const assetId = agentAssetIdOf(agent);\n const auth = useCatalogAuth();\n const principal = useCatalogPrincipal();\n const queryClient = useCatalogQueryClient();\n const read = useQuery(\n {\n queryKey: ['athena-sdk', 'catalog', 'agent-models', auth.backendUrl, principal, assetId],\n queryFn: async (): Promise<AgentModelRead> => {\n try {\n const data = await fetchGraphQL<{ getAssetById: { athenaMetadata: unknown } | null }>(\n auth,\n ATHENA_AGENT_MODELS_QUERY,\n { assetId },\n );\n if (data.getAssetById === null) return { readable: false };\n return {\n readable: true,\n source: publishedAgentModelSource(data.getAssetById.athenaMetadata),\n };\n } catch (error) {\n if (isAgentReadDenial(error)) return { readable: false };\n throw error;\n }\n },\n enabled: assetId !== null,\n staleTime: AGENT_MODELS_REFRESH_MS,\n refetchInterval: (query) => agentModelsRefetchInterval({ data: query.state.data }),\n },\n queryClient,\n );\n const catalog = useModelCatalogQuery({ auth, principal, queryClient });\n const threadModel = useOptionalAthenaThreadModel();\n const pinnedModel =\n threadModel !== null && threadModel.ready && threadModel.configured ? threadModel.model : null;\n const trimmedChannel = channel?.trim() || null;\n const models = catalog.data;\n const catalogPending = catalog.isPending;\n const { isPending: readPending, data: readData } = read;\n const modelLabel = useCallback(\n (model: string) => models?.find((option) => option.id === model)?.label ?? model,\n [models],\n );\n const choices = useMemo((): AthenaAgentModelOptions => {\n if (assetId === null) return NO_AGENT_MODEL_OPTIONS.idle;\n // A failed re-read keeps the last answer; only a first read that failed is an error.\n if (readData === undefined) {\n return readPending ? NO_AGENT_MODEL_OPTIONS.loading : NO_AGENT_MODEL_OPTIONS.error;\n }\n if (!readData.readable || readData.source === null) return NO_AGENT_MODEL_OPTIONS.unavailable;\n // The catalog names the models: wait for it, unless it failed (ids then name them).\n if (catalogPending) return NO_AGENT_MODEL_OPTIONS.loading;\n return {\n status: 'ready',\n ...buildAgentModelOptions({\n source: readData.source,\n channel: trimmedChannel,\n pinnedModel,\n modelLabel,\n }),\n allowAnyModel: readData.source.allowAnyModel,\n };\n }, [assetId, readPending, readData, catalogPending, modelLabel, trimmedChannel, pinnedModel]);\n return useMemo(() => ({ choices, modelLabel, catalog }), [choices, modelLabel, catalog]);\n}\n"],"names":[],"mappings":"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"}
|
package/dist/chat/AthenaChat.cjs
CHANGED
|
@@ -34,6 +34,7 @@ const dictationState = require("../dictation/dictation-state.cjs");
|
|
|
34
34
|
const useAthenaDictationEngine = require("../dictation/use-athena-dictation-engine.cjs");
|
|
35
35
|
const tiptapComposer = require("../chat-ui/composer/tiptap-composer.cjs");
|
|
36
36
|
const apiClient = require("../chat-ui/mentions/suggestions/data/api-client.cjs");
|
|
37
|
+
const useAccountWorkspaceId = require("../chat-ui/mentions/use-account-workspace-id.cjs");
|
|
37
38
|
const messageComponents = require("../chat-ui/messages/message-components.cjs");
|
|
38
39
|
const messageActionsConfig = require("../chat-ui/messages/message-actions-config.cjs");
|
|
39
40
|
const useAthenaRunLive = require("./use-athena-run-live.cjs");
|
|
@@ -41,6 +42,7 @@ const athenaChatWelcome = require("./athena-chat-welcome.cjs");
|
|
|
41
42
|
const athenaComposerControls = require("./athena-composer-controls.cjs");
|
|
42
43
|
const composerKeyboardHint = require("./composer-keyboard-hint.cjs");
|
|
43
44
|
const usePrefersReducedMotion = require("../lib/use-prefers-reduced-motion.cjs");
|
|
45
|
+
const AthenaAuthContext = require("../auth/AthenaAuthContext.cjs");
|
|
44
46
|
const react = require("@assistant-ui/react");
|
|
45
47
|
const lucideReact = require("lucide-react");
|
|
46
48
|
const react$1 = require("react");
|
|
@@ -148,29 +150,42 @@ const AthenaChat = ({
|
|
|
148
150
|
composer: composerSlots,
|
|
149
151
|
dictation = true
|
|
150
152
|
}) => {
|
|
151
|
-
var _a, _b, _c, _d, _e;
|
|
153
|
+
var _a, _b, _c, _d, _e, _f;
|
|
152
154
|
const athenaConfig = AthenaContext.useAthenaConfig();
|
|
155
|
+
const authState = react$1.useContext(AthenaAuthContext.AthenaAuthContext);
|
|
153
156
|
const statewireThreadId = react$1.useContext(threadIdContext.AthenaStatewireThreadIdContext);
|
|
154
157
|
const startNewSession = (_a = statewireThreadList.useAthenaStatewireThreadList()) == null ? void 0 : _a.newThread;
|
|
158
|
+
const mentionCredentials = react$1.useMemo(
|
|
159
|
+
() => {
|
|
160
|
+
var _a2;
|
|
161
|
+
return {
|
|
162
|
+
backendUrl: athenaConfig.backendUrl,
|
|
163
|
+
appUrl: athenaConfig.appUrl,
|
|
164
|
+
apiKey: athenaConfig.apiKey,
|
|
165
|
+
credentials: "include",
|
|
166
|
+
userId: (_a2 = authState == null ? void 0 : authState.user) == null ? void 0 : _a2.userId,
|
|
167
|
+
get accessToken() {
|
|
168
|
+
return athenaConfig.token ?? void 0;
|
|
169
|
+
},
|
|
170
|
+
getAccessToken: async () => {
|
|
171
|
+
var _a3;
|
|
172
|
+
return await ((_a3 = athenaConfig.getToken) == null ? void 0 : _a3.call(athenaConfig)) ?? void 0;
|
|
173
|
+
},
|
|
174
|
+
renewAccessToken: async () => {
|
|
175
|
+
var _a3;
|
|
176
|
+
return await ((_a3 = athenaConfig.getToken) == null ? void 0 : _a3.call(athenaConfig, { force: true })) ?? void 0;
|
|
177
|
+
}
|
|
178
|
+
};
|
|
179
|
+
},
|
|
180
|
+
[athenaConfig, (_b = authState == null ? void 0 : authState.user) == null ? void 0 : _b.userId]
|
|
181
|
+
);
|
|
182
|
+
const accountWorkspaceId = useAccountWorkspaceId.useAccountWorkspaceId(mentionCredentials);
|
|
155
183
|
const mentionAuth = react$1.useMemo(
|
|
156
184
|
() => ({
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
apiKey: athenaConfig.apiKey,
|
|
160
|
-
credentials: "include",
|
|
161
|
-
get accessToken() {
|
|
162
|
-
return athenaConfig.token ?? void 0;
|
|
163
|
-
},
|
|
164
|
-
getAccessToken: async () => {
|
|
165
|
-
var _a2;
|
|
166
|
-
return await ((_a2 = athenaConfig.getToken) == null ? void 0 : _a2.call(athenaConfig)) ?? void 0;
|
|
167
|
-
},
|
|
168
|
-
renewAccessToken: async () => {
|
|
169
|
-
var _a2;
|
|
170
|
-
return await ((_a2 = athenaConfig.getToken) == null ? void 0 : _a2.call(athenaConfig, { force: true })) ?? void 0;
|
|
171
|
-
}
|
|
185
|
+
...mentionCredentials,
|
|
186
|
+
workspaceId: mentionCredentials.workspaceId ?? accountWorkspaceId
|
|
172
187
|
}),
|
|
173
|
-
[
|
|
188
|
+
[mentionCredentials, accountWorkspaceId]
|
|
174
189
|
);
|
|
175
190
|
const providerMentionTools = react$1.useMemo(() => {
|
|
176
191
|
const uniqueToolkitIds = Array.from(new Set(athenaConfig.enabledToolkits));
|
|
@@ -196,10 +211,10 @@ const AthenaChat = ({
|
|
|
196
211
|
}),
|
|
197
212
|
[toolUIs]
|
|
198
213
|
);
|
|
199
|
-
const textComponent = ((
|
|
200
|
-
const userTextComponent = ((
|
|
201
|
-
const reasoningComponent = (
|
|
202
|
-
const emptyComponent = ((
|
|
214
|
+
const textComponent = ((_c = components == null ? void 0 : components.messageParts) == null ? void 0 : _c.Text) ?? tiptapText.TiptapText;
|
|
215
|
+
const userTextComponent = ((_d = components == null ? void 0 : components.messageParts) == null ? void 0 : _d.Text) ?? messageComponents.UserMessageText;
|
|
216
|
+
const reasoningComponent = (_e = components == null ? void 0 : components.messageParts) == null ? void 0 : _e.Reasoning;
|
|
217
|
+
const emptyComponent = ((_f = components == null ? void 0 : components.messageParts) == null ? void 0 : _f.Empty) ?? AthenaAssistantMessageEmpty;
|
|
203
218
|
const actionBarComponent = (components == null ? void 0 : components.AssistantActionBar) ?? AthenaAssistantActionBar;
|
|
204
219
|
const avatarComponent = components == null ? void 0 : components.AssistantAvatar;
|
|
205
220
|
const defaultComponentsContextValue = react$1.useMemo(
|
|
@@ -233,7 +248,7 @@ const AthenaChat = ({
|
|
|
233
248
|
}),
|
|
234
249
|
[AssistantMessageComponent, UserMessageComponent]
|
|
235
250
|
);
|
|
236
|
-
return /* @__PURE__ */ jsxRuntime.jsx(AthenaChatDefaultComponentsContext.Provider, { value: defaultComponentsContextValue, children: /* @__PURE__ */ jsxRuntime.jsx(AthenaChatErrorBoundary.AthenaChatErrorBoundary, { children: /* @__PURE__ */ jsxRuntime.jsx(toolFallback.ToolFallbackAppearanceProvider, { appearance: "thread", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
251
|
+
return /* @__PURE__ */ jsxRuntime.jsx(AthenaChatDefaultComponentsContext.Provider, { value: defaultComponentsContextValue, children: /* @__PURE__ */ jsxRuntime.jsx(AthenaChatErrorBoundary.AthenaChatErrorBoundary, { children: /* @__PURE__ */ jsxRuntime.jsx(toolFallback.ToolFallbackAppearanceProvider, { appearance: "thread", children: /* @__PURE__ */ jsxRuntime.jsx(apiClient.MentionAuthCtx.Provider, { value: mentionAuth, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
237
252
|
chatThreadShell.ChatThreadShell,
|
|
238
253
|
{
|
|
239
254
|
overlay: /* @__PURE__ */ jsxRuntime.jsx(threadLoadingOverlay.ThreadLoadingOverlay, {}),
|
|
@@ -260,10 +275,10 @@ const AthenaChat = ({
|
|
|
260
275
|
/* @__PURE__ */ jsxRuntime.jsx(statewireBanners.StatewireErrorBanner, { onStartNewSession: startNewSession }),
|
|
261
276
|
/* @__PURE__ */ jsxRuntime.jsx(StatewireRunRefusalNotice.StatewireRunRefusalNotice, { onStartNewSession: startNewSession }),
|
|
262
277
|
/* @__PURE__ */ jsxRuntime.jsx(StatewireApprovalCard.StatewireApprovalCard, {}),
|
|
263
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
278
|
+
/* @__PURE__ */ jsxRuntime.jsx(StatewireQueuedMessages.StatewireQueuedMessages, {}),
|
|
264
279
|
/* @__PURE__ */ jsxRuntime.jsx(AttachmentContext.AttachmentProvider, { children: /* @__PURE__ */ jsxRuntime.jsxs(QuoteContext.QuoteProvider, { children: [
|
|
265
280
|
/* @__PURE__ */ jsxRuntime.jsx(QuotePostMessageBridge, {}),
|
|
266
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
281
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
267
282
|
AthenaChatComposer,
|
|
268
283
|
{
|
|
269
284
|
tools,
|
|
@@ -271,11 +286,11 @@ const AthenaChat = ({
|
|
|
271
286
|
dictation,
|
|
272
287
|
welcomeSuggestionCount: welcomeSuggestions.length
|
|
273
288
|
}
|
|
274
|
-
)
|
|
289
|
+
)
|
|
275
290
|
] }) })
|
|
276
291
|
] })
|
|
277
292
|
}
|
|
278
|
-
) }) }, statewireThreadId ?? void 0) });
|
|
293
|
+
) }) }) }, statewireThreadId ?? void 0) });
|
|
279
294
|
};
|
|
280
295
|
const THREAD_VIEWPORT_ATTR = "data-aui-thread-viewport";
|
|
281
296
|
const useScrollToTop = () => {
|