@agent-native/toolkit 0.205.0 → 0.206.0-nightly-20261009011246
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/app/agentkit/react/components.d.ts.map +1 -1
- package/dist/app/agentkit/react/components.js +17 -9
- package/dist/app/agentkit/react/components.js.map +1 -1
- package/dist/app/auth/AuthPage.d.ts.map +1 -1
- package/dist/app/auth/AuthPage.js +11 -0
- package/dist/app/auth/AuthPage.js.map +1 -1
- package/dist/app/chat/AgentKitAssistantChat.d.ts +2 -0
- package/dist/app/chat/AgentKitAssistantChat.d.ts.map +1 -1
- package/dist/app/chat/AgentKitAssistantChat.js +24 -14
- package/dist/app/chat/AgentKitAssistantChat.js.map +1 -1
- package/dist/app/chat/AgentPanel.d.ts.map +1 -1
- package/dist/app/chat/AgentPanel.js +3 -2
- package/dist/app/chat/AgentPanel.js.map +1 -1
- package/dist/app/chat/MultiTabAssistantChat.d.ts +4 -1
- package/dist/app/chat/MultiTabAssistantChat.d.ts.map +1 -1
- package/dist/app/chat/MultiTabAssistantChat.js +61 -3
- package/dist/app/chat/MultiTabAssistantChat.js.map +1 -1
- package/dist/app/chat/agentkit-chat/approval-card.d.ts.map +1 -1
- package/dist/app/chat/agentkit-chat/approval-card.js +2 -1
- package/dist/app/chat/agentkit-chat/approval-card.js.map +1 -1
- package/dist/app/chat/chat/run-recovery.d.ts.map +1 -1
- package/dist/app/chat/chat/run-recovery.js +74 -8
- package/dist/app/chat/chat/run-recovery.js.map +1 -1
- package/dist/app/chat/chat/tool-call-display.d.ts.map +1 -1
- package/dist/app/chat/chat/tool-call-display.js +6 -4
- package/dist/app/chat/chat/tool-call-display.js.map +1 -1
- package/dist/app/chat/chat-first/ChatFirstAgentActivityPanel.d.ts.map +1 -1
- package/dist/app/chat/chat-first/ChatFirstAgentActivityPanel.js +2 -1
- package/dist/app/chat/chat-first/ChatFirstAgentActivityPanel.js.map +1 -1
- package/dist/app/chat/conversation/AgentConversation.d.ts.map +1 -1
- package/dist/app/chat/conversation/AgentConversation.js +10 -7
- package/dist/app/chat/conversation/AgentConversation.js.map +1 -1
- package/dist/app/chat/fallback-chat-title.d.ts.map +1 -1
- package/dist/app/chat/fallback-chat-title.js +2 -4
- package/dist/app/chat/fallback-chat-title.js.map +1 -1
- package/dist/app/chat/mcp-apps/McpAppRenderer.d.ts.map +1 -1
- package/dist/app/chat/mcp-apps/McpAppRenderer.js +3 -2
- package/dist/app/chat/mcp-apps/McpAppRenderer.js.map +1 -1
- package/dist/app/chat/session-replay-privacy.d.ts +7 -0
- package/dist/app/chat/session-replay-privacy.d.ts.map +1 -0
- package/dist/app/chat/session-replay-privacy.js +6 -0
- package/dist/app/chat/session-replay-privacy.js.map +1 -0
- package/dist/app/extensions/ExtensionViewer.d.ts +4 -1
- package/dist/app/extensions/ExtensionViewer.d.ts.map +1 -1
- package/dist/app/extensions/ExtensionViewer.js +3 -3
- package/dist/app/extensions/ExtensionViewer.js.map +1 -1
- package/dist/app/extensions/ExtensionViewerPage.d.ts +4 -1
- package/dist/app/extensions/ExtensionViewerPage.d.ts.map +1 -1
- package/dist/app/extensions/ExtensionViewerPage.js +2 -2
- package/dist/app/extensions/ExtensionViewerPage.js.map +1 -1
- package/dist/app/onboarding/FirstRunOnboarding.d.ts.map +1 -1
- package/dist/app/onboarding/FirstRunOnboarding.js +53 -12
- package/dist/app/onboarding/FirstRunOnboarding.js.map +1 -1
- package/dist/app/onboarding/OnboardingPanel.d.ts.map +1 -1
- package/dist/app/onboarding/OnboardingPanel.js +14 -4
- package/dist/app/onboarding/OnboardingPanel.js.map +1 -1
- package/dist/app/resources/ResourceEditor.d.ts +4 -1
- package/dist/app/resources/ResourceEditor.d.ts.map +1 -1
- package/dist/app/resources/ResourceEditor.js +18 -7
- package/dist/app/resources/ResourceEditor.js.map +1 -1
- package/dist/app/resources/ResourcesPanel.d.ts +4 -1
- package/dist/app/resources/ResourcesPanel.d.ts.map +1 -1
- package/dist/app/resources/ResourcesPanel.js +18 -18
- package/dist/app/resources/ResourcesPanel.js.map +1 -1
- package/dist/app/resources/custom-agent-model-options.d.ts +16 -0
- package/dist/app/resources/custom-agent-model-options.d.ts.map +1 -0
- package/dist/app/resources/custom-agent-model-options.js +53 -0
- package/dist/app/resources/custom-agent-model-options.js.map +1 -0
- package/dist/app/settings/SettingsPanel.d.ts.map +1 -1
- package/dist/app/settings/SettingsPanel.js +34 -3
- package/dist/app/settings/SettingsPanel.js.map +1 -1
- package/dist/app/settings/SettingsTabsPage.d.ts.map +1 -1
- package/dist/app/settings/SettingsTabsPage.js +2 -0
- package/dist/app/settings/SettingsTabsPage.js.map +1 -1
- package/dist/app/settings/api-keys/ApiKeyDialogs.d.ts.map +1 -1
- package/dist/app/settings/api-keys/ApiKeyDialogs.js +49 -9
- package/dist/app/settings/api-keys/ApiKeyDialogs.js.map +1 -1
- package/dist/app/settings/api-keys/ApiKeysSettingsPage.js +2 -1
- package/dist/app/settings/api-keys/ApiKeysSettingsPage.js.map +1 -1
- package/dist/app/settings/model/ModelSettingsPage.d.ts.map +1 -1
- package/dist/app/settings/model/ModelSettingsPage.js +43 -9
- package/dist/app/settings/model/ModelSettingsPage.js.map +1 -1
- package/dist/app/settings/model/ProviderDialog.d.ts +4 -0
- package/dist/app/settings/model/ProviderDialog.d.ts.map +1 -1
- package/dist/app/settings/model/ProviderDialog.js +107 -11
- package/dist/app/settings/model/ProviderDialog.js.map +1 -1
- package/dist/app/settings/useBuilderStatus.d.ts.map +1 -1
- package/dist/app/settings/useBuilderStatus.js +13 -10
- package/dist/app/settings/useBuilderStatus.js.map +1 -1
- package/dist/composer/TiptapComposer.d.ts.map +1 -1
- package/dist/composer/TiptapComposer.js +51 -13
- package/dist/composer/TiptapComposer.js.map +1 -1
- package/package.json +4 -4
- package/src/app/agentkit/react/components.interaction.spec.tsx +229 -1
- package/src/app/agentkit/react/components.spec.tsx +42 -1
- package/src/app/agentkit/react/components.tsx +46 -12
- package/src/app/auth/AuthPage.tsx +13 -0
- package/src/app/chat/AgentKitAssistantChat.spec.tsx +116 -5
- package/src/app/chat/AgentKitAssistantChat.tsx +41 -20
- package/src/app/chat/AgentPanel.tsx +5 -1
- package/src/app/chat/MultiTabAssistantChat.spec.tsx +152 -7
- package/src/app/chat/MultiTabAssistantChat.tsx +71 -4
- package/src/app/chat/agentkit-chat/approval-card.spec.tsx +17 -0
- package/src/app/chat/agentkit-chat/approval-card.tsx +2 -0
- package/src/app/chat/chat/run-recovery.spec.tsx +354 -9
- package/src/app/chat/chat/run-recovery.tsx +178 -10
- package/src/app/chat/chat/tool-call-display.spec.tsx +77 -0
- package/src/app/chat/chat/tool-call-display.tsx +23 -6
- package/src/app/chat/chat-first/ChatFirstAgentActivityPanel.tsx +2 -1
- package/src/app/chat/conversation/AgentConversation.spec.tsx +190 -1
- package/src/app/chat/conversation/AgentConversation.tsx +32 -8
- package/src/app/chat/fallback-chat-title.spec.ts +44 -0
- package/src/app/chat/fallback-chat-title.ts +3 -4
- package/src/app/chat/mcp-apps/McpAppRenderer.spec.ts +24 -0
- package/src/app/chat/mcp-apps/McpAppRenderer.tsx +10 -2
- package/src/app/chat/session-replay-privacy.spec.ts +14 -0
- package/src/app/chat/session-replay-privacy.ts +5 -0
- package/src/app/extensions/ExtensionViewer.tsx +15 -3
- package/src/app/extensions/ExtensionViewerPage.tsx +7 -3
- package/src/app/onboarding/FirstRunOnboarding.spec.tsx +252 -2
- package/src/app/onboarding/FirstRunOnboarding.tsx +56 -9
- package/src/app/onboarding/OnboardingPanel.save-scope.spec.tsx +1 -0
- package/src/app/onboarding/OnboardingPanel.tsx +15 -3
- package/src/app/resources/ResourceEditor.spec.tsx +240 -5
- package/src/app/resources/ResourceEditor.tsx +57 -10
- package/src/app/resources/ResourcesPanel.spec.ts +86 -4
- package/src/app/resources/ResourcesPanel.tsx +49 -16
- package/src/app/resources/custom-agent-model-options.ts +92 -0
- package/src/app/settings/SettingsPanel.model-defaults.spec.tsx +26 -13
- package/src/app/settings/SettingsPanel.tsx +35 -3
- package/src/app/settings/SettingsTabsPage.spec.tsx +97 -0
- package/src/app/settings/SettingsTabsPage.tsx +2 -0
- package/src/app/settings/api-keys/ApiKeyDialogs.tsx +84 -22
- package/src/app/settings/api-keys/ApiKeysSettingsPage.spec.tsx +229 -1
- package/src/app/settings/api-keys/ApiKeysSettingsPage.tsx +3 -2
- package/src/app/settings/model/ModelSettingsPage.spec.tsx +99 -9
- package/src/app/settings/model/ModelSettingsPage.tsx +79 -11
- package/src/app/settings/model/ProviderDialog.spec.tsx +192 -1
- package/src/app/settings/model/ProviderDialog.tsx +225 -29
- package/src/app/settings/useBuilderStatus.spec.tsx +49 -0
- package/src/app/settings/useBuilderStatus.ts +16 -10
- package/src/composer/TiptapComposer.spec.ts +97 -2
- package/src/composer/TiptapComposer.tsx +67 -13
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
} from "@agent-native/core/agent/model-
|
|
2
|
+
getModelOptionLabel,
|
|
3
|
+
type ModelEngineConfig,
|
|
4
|
+
} from "@agent-native/core/agent/model-version";
|
|
5
5
|
import { sendToAgentChat } from "@agent-native/core/client/agent-chat";
|
|
6
6
|
import { agentNativePath } from "@agent-native/core/client/api-path";
|
|
7
7
|
import { useT } from "@agent-native/core/client/i18n";
|
|
@@ -94,6 +94,10 @@ import {
|
|
|
94
94
|
type FileStorageSetupCloseReason,
|
|
95
95
|
} from "../chat/FileStorageSetupPopover.js";
|
|
96
96
|
import { BuiltinCapabilityDetail } from "./BuiltinCapabilityDetail.js";
|
|
97
|
+
import {
|
|
98
|
+
getCustomAgentModelOptions,
|
|
99
|
+
useCustomAgentModelEngine,
|
|
100
|
+
} from "./custom-agent-model-options.js";
|
|
97
101
|
import { McpIntegrationDialog } from "./McpIntegrationDialog.js";
|
|
98
102
|
import { McpServerDetail } from "./McpServerDetail.js";
|
|
99
103
|
import { ResourceEditor } from "./ResourceEditor.js";
|
|
@@ -233,17 +237,6 @@ type CreateMenuView =
|
|
|
233
237
|
| "agent-prompt"
|
|
234
238
|
| "agent-form";
|
|
235
239
|
|
|
236
|
-
const AGENT_MODEL_OPTIONS = [
|
|
237
|
-
{ value: "inherit", label: "Default model" },
|
|
238
|
-
{ value: "claude-fable-5", label: "Claude Fable 5" },
|
|
239
|
-
{ value: "claude-opus-5-5", label: "Claude Opus 5.5" },
|
|
240
|
-
{
|
|
241
|
-
value: BUILDER_CLAUDE_SONNET_MODEL_ID,
|
|
242
|
-
label: BUILDER_CLAUDE_SONNET_MODEL_LABEL,
|
|
243
|
-
},
|
|
244
|
-
{ value: "claude-haiku-4-5-20251001", label: "Claude Haiku 4.5" },
|
|
245
|
-
] as const;
|
|
246
|
-
|
|
247
240
|
export function slugifyName(value: string): string {
|
|
248
241
|
return (
|
|
249
242
|
value
|
|
@@ -433,6 +426,7 @@ function CreateMenu({
|
|
|
433
426
|
triggerVariant = "icon",
|
|
434
427
|
triggerLabel,
|
|
435
428
|
initialView = "menu",
|
|
429
|
+
modelEngine,
|
|
436
430
|
}: {
|
|
437
431
|
scope: ResourceScope;
|
|
438
432
|
resourceFilter?: ResourceView;
|
|
@@ -466,11 +460,25 @@ function CreateMenu({
|
|
|
466
460
|
triggerVariant?: "icon" | "outline";
|
|
467
461
|
triggerLabel?: string;
|
|
468
462
|
initialView?: CreateMenuView;
|
|
463
|
+
modelEngine?: ModelEngineConfig | null;
|
|
469
464
|
}) {
|
|
470
465
|
const t = useT();
|
|
471
466
|
const [open, setOpen] = useState(false);
|
|
472
467
|
const [mcpDialogOpen, setMcpDialogOpen] = useState(false);
|
|
473
468
|
const [view, setView] = useState<CreateMenuView>("menu");
|
|
469
|
+
const modelEngineLoad = useCustomAgentModelEngine(
|
|
470
|
+
modelEngine,
|
|
471
|
+
open && view === "agent-form",
|
|
472
|
+
);
|
|
473
|
+
const effectiveModelEngine = modelEngineLoad.engine;
|
|
474
|
+
const modelLabels = {
|
|
475
|
+
defaultModel: t("agentResources.defaultModel"),
|
|
476
|
+
builderFallback: t("agentResources.builderModelFallback"),
|
|
477
|
+
};
|
|
478
|
+
const agentModelOptions = getCustomAgentModelOptions(
|
|
479
|
+
effectiveModelEngine,
|
|
480
|
+
modelLabels,
|
|
481
|
+
);
|
|
474
482
|
const showMcpIntegrations = useMemo(
|
|
475
483
|
() => hasAvailableMcpIntegrations(mcpIntegrations),
|
|
476
484
|
[mcpIntegrations],
|
|
@@ -1108,11 +1116,28 @@ The job will run automatically on the schedule. Make the instructions specific
|
|
|
1108
1116
|
onChange={(e) => setAgentModel(e.target.value)}
|
|
1109
1117
|
className="w-full rounded-md border border-border bg-background px-2.5 py-1.5 text-[13px] text-foreground outline-none focus:ring-1 focus:ring-accent"
|
|
1110
1118
|
>
|
|
1111
|
-
{
|
|
1119
|
+
{agentModelOptions.map((option) => (
|
|
1112
1120
|
<option key={option.value} value={option.value}>
|
|
1113
1121
|
{option.label}
|
|
1114
1122
|
</option>
|
|
1115
1123
|
))}
|
|
1124
|
+
{modelEngineLoad.state === "unavailable" && (
|
|
1125
|
+
<option value="__model-options-unavailable" disabled>
|
|
1126
|
+
{t("agentResources.modelOptionsUnavailable")}
|
|
1127
|
+
</option>
|
|
1128
|
+
)}
|
|
1129
|
+
{agentModel !== "inherit" &&
|
|
1130
|
+
!agentModelOptions.some(
|
|
1131
|
+
(option) => option.value === agentModel,
|
|
1132
|
+
) && (
|
|
1133
|
+
<option value={agentModel}>
|
|
1134
|
+
{getModelOptionLabel(
|
|
1135
|
+
agentModel,
|
|
1136
|
+
effectiveModelEngine ?? undefined,
|
|
1137
|
+
modelLabels.builderFallback,
|
|
1138
|
+
)}
|
|
1139
|
+
</option>
|
|
1140
|
+
)}
|
|
1116
1141
|
</select>
|
|
1117
1142
|
<label className="block text-[11px] font-medium text-muted-foreground">
|
|
1118
1143
|
Instructions
|
|
@@ -1240,6 +1265,8 @@ export interface ResourcesPanelProps {
|
|
|
1240
1265
|
openResourceRef?: { current: ((id: string) => void) | null };
|
|
1241
1266
|
/** Called when the editor opens or closes, so a page can yield to it. */
|
|
1242
1267
|
onEditingChange?: (editing: boolean) => void;
|
|
1268
|
+
/** Exact selected chat engine, when this panel is paired with a chat. */
|
|
1269
|
+
modelEngine?: ModelEngineConfig | null;
|
|
1243
1270
|
}
|
|
1244
1271
|
|
|
1245
1272
|
/** Owners, admins, and solo deployments (no organization) edit org resources. */
|
|
@@ -1348,11 +1375,12 @@ export function ResourcesPanel({
|
|
|
1348
1375
|
settingsGroups,
|
|
1349
1376
|
openResourceRef,
|
|
1350
1377
|
onEditingChange,
|
|
1378
|
+
modelEngine,
|
|
1351
1379
|
}: ResourcesPanelProps = {}) {
|
|
1352
1380
|
const t = useT();
|
|
1353
1381
|
const { data: org } = useOrg();
|
|
1354
1382
|
const canEditOrg = canEditOrganizationResources(org);
|
|
1355
|
-
|
|
1383
|
+
const effectiveModelEngine = modelEngine;
|
|
1356
1384
|
const [activeScope, setActiveScope] = useState<ResourceScope>(() =>
|
|
1357
1385
|
resolveInitialResourceScope(requestedScope, canEditOrg),
|
|
1358
1386
|
);
|
|
@@ -1918,6 +1946,7 @@ export function ResourcesPanel({
|
|
|
1918
1946
|
return (
|
|
1919
1947
|
<CreateMenu
|
|
1920
1948
|
scope={targetScope}
|
|
1949
|
+
modelEngine={effectiveModelEngine}
|
|
1921
1950
|
resourceFilter={resourceFilter}
|
|
1922
1951
|
personalMcpOnly={mode === "personal-mcp"}
|
|
1923
1952
|
onCreateFile={(name) => handleCreateFromToolbar(targetScope, name)}
|
|
@@ -1962,6 +1991,7 @@ export function ResourcesPanel({
|
|
|
1962
1991
|
return (
|
|
1963
1992
|
<CreateMenu
|
|
1964
1993
|
scope={targetScope}
|
|
1994
|
+
modelEngine={effectiveModelEngine}
|
|
1965
1995
|
resourceFilter={resourceFilter}
|
|
1966
1996
|
personalMcpOnly={mode === "personal-mcp"}
|
|
1967
1997
|
onCreateFile={(name) => handleCreateFromToolbar(targetScope, name)}
|
|
@@ -2232,6 +2262,7 @@ export function ResourcesPanel({
|
|
|
2232
2262
|
(!resourceFilter || resourceFilter === "files") && (
|
|
2233
2263
|
<CreateMenu
|
|
2234
2264
|
scope={activeScope}
|
|
2265
|
+
modelEngine={effectiveModelEngine}
|
|
2235
2266
|
resourceFilter={resourceFilter}
|
|
2236
2267
|
personalMcpOnly={activeCreateMenuMode === "personal-mcp"}
|
|
2237
2268
|
onCreateFile={(name) =>
|
|
@@ -2349,6 +2380,8 @@ export function ResourcesPanel({
|
|
|
2349
2380
|
onViewChange={setEditorView}
|
|
2350
2381
|
hideToolbar
|
|
2351
2382
|
readOnly={selectedResourceReadOnly}
|
|
2383
|
+
modelEngine={effectiveModelEngine}
|
|
2384
|
+
builderFallbackLabel={t("agentResources.builderModelFallback")}
|
|
2352
2385
|
/>
|
|
2353
2386
|
</div>
|
|
2354
2387
|
) : resourceQuery.isError ? (
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { CURRENT_BUILDER_CLAUDE_MODEL_OPTIONS } from "@agent-native/core/agent/model-config";
|
|
2
|
+
import {
|
|
3
|
+
getModelOptionLabel,
|
|
4
|
+
type ModelEngineConfig,
|
|
5
|
+
} from "@agent-native/core/agent/model-version";
|
|
6
|
+
import { loadChatModelCatalog } from "@agent-native/core/client/use-chat-models";
|
|
7
|
+
import { useEffect, useState } from "react";
|
|
8
|
+
|
|
9
|
+
export interface CustomAgentModelOption {
|
|
10
|
+
value: string;
|
|
11
|
+
label: string;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export interface CustomAgentModelOptionLabels {
|
|
15
|
+
defaultModel: string;
|
|
16
|
+
builderFallback: string;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export type CustomAgentModelEngineLoadState =
|
|
20
|
+
| "idle"
|
|
21
|
+
| "loading"
|
|
22
|
+
| "available"
|
|
23
|
+
| "unavailable";
|
|
24
|
+
|
|
25
|
+
export function useCustomAgentModelEngine(
|
|
26
|
+
suppliedEngine: ModelEngineConfig | null | undefined,
|
|
27
|
+
enabled: boolean,
|
|
28
|
+
): {
|
|
29
|
+
engine: ModelEngineConfig | null;
|
|
30
|
+
state: CustomAgentModelEngineLoadState;
|
|
31
|
+
} {
|
|
32
|
+
const [loaded, setLoaded] = useState<{
|
|
33
|
+
engine: ModelEngineConfig | null;
|
|
34
|
+
state: CustomAgentModelEngineLoadState;
|
|
35
|
+
}>({ engine: null, state: "idle" });
|
|
36
|
+
|
|
37
|
+
useEffect(() => {
|
|
38
|
+
if (suppliedEngine !== undefined || !enabled) return;
|
|
39
|
+
let cancelled = false;
|
|
40
|
+
setLoaded({ engine: null, state: "loading" });
|
|
41
|
+
void loadChatModelCatalog()
|
|
42
|
+
.then((catalog) => {
|
|
43
|
+
if (cancelled) return;
|
|
44
|
+
const engine =
|
|
45
|
+
catalog.state === "available" ? catalog.currentModelEngine : null;
|
|
46
|
+
setLoaded({
|
|
47
|
+
engine,
|
|
48
|
+
state: engine ? "available" : "unavailable",
|
|
49
|
+
});
|
|
50
|
+
})
|
|
51
|
+
.catch((error: unknown) => {
|
|
52
|
+
if (cancelled) return;
|
|
53
|
+
console.error(
|
|
54
|
+
"[agent-resources] model catalog could not be loaded",
|
|
55
|
+
error,
|
|
56
|
+
);
|
|
57
|
+
setLoaded({ engine: null, state: "unavailable" });
|
|
58
|
+
});
|
|
59
|
+
return () => {
|
|
60
|
+
cancelled = true;
|
|
61
|
+
};
|
|
62
|
+
}, [enabled, suppliedEngine]);
|
|
63
|
+
|
|
64
|
+
if (suppliedEngine !== undefined) {
|
|
65
|
+
return {
|
|
66
|
+
engine: suppliedEngine,
|
|
67
|
+
state: suppliedEngine ? "available" : "unavailable",
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
return loaded;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export function getCustomAgentModelOptions(
|
|
74
|
+
engine: ModelEngineConfig | null | undefined,
|
|
75
|
+
labels: CustomAgentModelOptionLabels,
|
|
76
|
+
): CustomAgentModelOption[] {
|
|
77
|
+
const selectableModels = engine?.selectableModels ?? engine?.supportedModels;
|
|
78
|
+
const models =
|
|
79
|
+
engine?.name === "builder"
|
|
80
|
+
? CURRENT_BUILDER_CLAUDE_MODEL_OPTIONS.filter((option) =>
|
|
81
|
+
selectableModels?.includes(option.value),
|
|
82
|
+
).map((option) => option.value)
|
|
83
|
+
: (selectableModels ?? []);
|
|
84
|
+
|
|
85
|
+
return [
|
|
86
|
+
{ value: "inherit", label: labels.defaultModel },
|
|
87
|
+
...[...new Set(models)].map((value) => ({
|
|
88
|
+
value,
|
|
89
|
+
label: getModelOptionLabel(value),
|
|
90
|
+
})),
|
|
91
|
+
];
|
|
92
|
+
}
|
|
@@ -4,20 +4,31 @@ import React, { act } from "react";
|
|
|
4
4
|
import { createRoot, type Root } from "react-dom/client";
|
|
5
5
|
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
|
6
6
|
|
|
7
|
-
import { AppDefaultModelField } from "./SettingsPanel.js";
|
|
7
|
+
import { AppDefaultModelField, friendlyModelName } from "./SettingsPanel.js";
|
|
8
8
|
|
|
9
9
|
const BUILDER_MODELS = [
|
|
10
10
|
"auto",
|
|
11
|
+
"claude-haiku-5-5",
|
|
12
|
+
"claude-sonnet-5-5",
|
|
11
13
|
"claude-opus-5-5",
|
|
12
|
-
"
|
|
13
|
-
"claude-haiku-4-5",
|
|
14
|
-
"gpt-5-6-sol",
|
|
14
|
+
"gpt-6-1-sol",
|
|
15
15
|
"gpt-5-6-terra",
|
|
16
|
-
"gpt-
|
|
16
|
+
"gpt-6-luna",
|
|
17
17
|
"gemini-3-1-pro",
|
|
18
|
-
"gemini-3-
|
|
18
|
+
"gemini-3-8-flash",
|
|
19
|
+
"gemini-3-5-flash-lite",
|
|
20
|
+
"gemini-3-1-flash-lite",
|
|
19
21
|
];
|
|
20
22
|
|
|
23
|
+
describe("friendlyModelName", () => {
|
|
24
|
+
it("keeps custom model ids safe and formats dated Claude ids", () => {
|
|
25
|
+
expect(friendlyModelName("toString")).toBe("toString");
|
|
26
|
+
expect(friendlyModelName("claude-haiku-4-20251001")).toBe("Haiku 4");
|
|
27
|
+
expect(friendlyModelName("claude-fable-5-1")).toBe("Fable 5.1");
|
|
28
|
+
expect(friendlyModelName("x-ai/grok-build-0.1")).toBe("Grok Build 0.1");
|
|
29
|
+
});
|
|
30
|
+
});
|
|
31
|
+
|
|
21
32
|
describe("AppDefaultModelField", () => {
|
|
22
33
|
let container: HTMLDivElement;
|
|
23
34
|
let root: Root;
|
|
@@ -42,7 +53,7 @@ describe("AppDefaultModelField", () => {
|
|
|
42
53
|
<AppDefaultModelField
|
|
43
54
|
engine="builder"
|
|
44
55
|
models={BUILDER_MODELS}
|
|
45
|
-
value="gpt-
|
|
56
|
+
value="gpt-6-1-sol"
|
|
46
57
|
onValueChange={vi.fn()}
|
|
47
58
|
/>,
|
|
48
59
|
);
|
|
@@ -52,7 +63,7 @@ describe("AppDefaultModelField", () => {
|
|
|
52
63
|
'button[role="combobox"][aria-label="Model"]',
|
|
53
64
|
);
|
|
54
65
|
expect(trigger).not.toBeNull();
|
|
55
|
-
expect(trigger?.textContent).toContain("GPT-
|
|
66
|
+
expect(trigger?.textContent).toContain("GPT-6.1 Sol");
|
|
56
67
|
expect(container.querySelector("input[list]")).toBeNull();
|
|
57
68
|
|
|
58
69
|
act(() => {
|
|
@@ -71,14 +82,16 @@ describe("AppDefaultModelField", () => {
|
|
|
71
82
|
);
|
|
72
83
|
expect(options).toEqual([
|
|
73
84
|
"auto",
|
|
85
|
+
"Haiku 5.5",
|
|
86
|
+
"Sonnet 5.5",
|
|
74
87
|
"Opus 5.5",
|
|
75
|
-
"
|
|
76
|
-
"Haiku 4.5",
|
|
77
|
-
"GPT-5.6 Sol",
|
|
88
|
+
"GPT-6.1 Sol",
|
|
78
89
|
"GPT-5.6 Terra",
|
|
79
|
-
"GPT-
|
|
90
|
+
"GPT-6 Luna",
|
|
80
91
|
"Gemini 3.1 Pro",
|
|
81
|
-
"Gemini 3.
|
|
92
|
+
"Gemini 3.8 Flash",
|
|
93
|
+
"Gemini 3.5 Flash Lite",
|
|
94
|
+
"Gemini 3.1 Flash Lite",
|
|
82
95
|
]);
|
|
83
96
|
});
|
|
84
97
|
|
|
@@ -584,11 +584,43 @@ function ManualSetupCard({
|
|
|
584
584
|
);
|
|
585
585
|
}
|
|
586
586
|
|
|
587
|
+
const FRIENDLY_MODEL_NAMES: Record<string, string> = {
|
|
588
|
+
"z-ai/glm-5.2": "GLM 5.2",
|
|
589
|
+
"grok-code-fast": "Grok Code Fast",
|
|
590
|
+
"x-ai/grok-4.7": "Grok 4.7",
|
|
591
|
+
"x-ai/grok-build-0.1": "Grok Build 0.1",
|
|
592
|
+
"qwen3-coder": "Qwen3 Coder",
|
|
593
|
+
"qwen/qwen3-coder": "Qwen3 Coder",
|
|
594
|
+
"kimi-k2-5": "Kimi K2.5",
|
|
595
|
+
"moonshotai/kimi-k2.5": "Kimi K2.5",
|
|
596
|
+
"deepseek-v4-pro": "DeepSeek V4 Pro",
|
|
597
|
+
"deepseek-v4-1-flash": "DeepSeek V4.1 Flash",
|
|
598
|
+
"deepseek-v3-1": "DeepSeek v3.1",
|
|
599
|
+
"deepseek/deepseek-v4-pro": "DeepSeek V4 Pro",
|
|
600
|
+
"deepseek/deepseek-v4.1-flash": "DeepSeek V4.1 Flash",
|
|
601
|
+
"deepseek/deepseek-chat-v3.1": "DeepSeek v3.1",
|
|
602
|
+
"z-ai-glm-4-5": "Z-AI GLM 4.5",
|
|
603
|
+
"z-ai-glm-5-1": "Z-AI GLM 5.1",
|
|
604
|
+
"z-ai-glm-5-3-flash": "Z-AI GLM 5.3 Flash",
|
|
605
|
+
"z-ai/glm-4.5": "GLM 4.5",
|
|
606
|
+
"z-ai/glm-5.1": "GLM 5.1",
|
|
607
|
+
"z-ai/glm-5.3-flash": "GLM 5.3 Flash",
|
|
608
|
+
"anthropic/claude-haiku-5.5": "Claude Haiku 5.5",
|
|
609
|
+
"google/gemini-3.8-flash": "Gemini 3.8 Flash",
|
|
610
|
+
"google/gemini-3.5-flash-lite": "Gemini 3.5 Flash-Lite",
|
|
611
|
+
"google/gemini-3.1-flash-lite": "Gemini 3.1 Flash-Lite",
|
|
612
|
+
"google/gemini-3.1-pro-preview": "Gemini 3.1 Pro",
|
|
613
|
+
};
|
|
614
|
+
|
|
587
615
|
export function friendlyModelName(model: string): string {
|
|
588
|
-
|
|
616
|
+
const friendlyName = Object.hasOwn(FRIENDLY_MODEL_NAMES, model)
|
|
617
|
+
? FRIENDLY_MODEL_NAMES[model]
|
|
618
|
+
: undefined;
|
|
619
|
+
if (friendlyName !== undefined) return friendlyName;
|
|
589
620
|
const normalizedModel = model.replace(/^(?:anthropic|openai)\//, "");
|
|
590
|
-
const
|
|
591
|
-
|
|
621
|
+
const undatedModel = normalizedModel.replace(/-\d{8,}$/, "");
|
|
622
|
+
const claude = undatedModel.match(
|
|
623
|
+
/^claude-(opus|sonnet|haiku|fable)-(\d+)(?:[-.](\d+))?$/,
|
|
592
624
|
);
|
|
593
625
|
if (claude) {
|
|
594
626
|
const tier = claude[1][0].toUpperCase() + claude[1].slice(1);
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
// @vitest-environment happy-dom
|
|
2
2
|
|
|
3
|
+
import {
|
|
4
|
+
setCustomKeyOnboardingAttempt,
|
|
5
|
+
trackCustomKeyOnboardingOutcome,
|
|
6
|
+
} from "@agent-native/core/client/onboarding/use-onboarding";
|
|
3
7
|
import { SIGN_OUT_SEARCH_TERMS } from "@agent-native/core/client/sign-out";
|
|
4
8
|
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
|
|
5
9
|
import React, { act } from "react";
|
|
@@ -78,6 +82,30 @@ function captureAnimationFrame() {
|
|
|
78
82
|
}
|
|
79
83
|
|
|
80
84
|
let activeQueryClient: QueryClient | null = null;
|
|
85
|
+
let restoreLocalStorage: (() => void) | null = null;
|
|
86
|
+
|
|
87
|
+
function installTestLocalStorage() {
|
|
88
|
+
const descriptor = Object.getOwnPropertyDescriptor(window, "localStorage");
|
|
89
|
+
const values = new Map<string, string>();
|
|
90
|
+
Object.defineProperty(window, "localStorage", {
|
|
91
|
+
configurable: true,
|
|
92
|
+
value: {
|
|
93
|
+
get length() {
|
|
94
|
+
return values.size;
|
|
95
|
+
},
|
|
96
|
+
clear: () => values.clear(),
|
|
97
|
+
getItem: (key: string) => values.get(key) ?? null,
|
|
98
|
+
key: (index: number) => [...values.keys()][index] ?? null,
|
|
99
|
+
removeItem: (key: string) => values.delete(key),
|
|
100
|
+
setItem: (key: string, value: string) => values.set(key, String(value)),
|
|
101
|
+
} satisfies Storage,
|
|
102
|
+
});
|
|
103
|
+
restoreLocalStorage = () => {
|
|
104
|
+
if (descriptor) Object.defineProperty(window, "localStorage", descriptor);
|
|
105
|
+
else Reflect.deleteProperty(window, "localStorage");
|
|
106
|
+
restoreLocalStorage = null;
|
|
107
|
+
};
|
|
108
|
+
}
|
|
81
109
|
|
|
82
110
|
function createQueryClientWithLabs(labs: Record<string, unknown>) {
|
|
83
111
|
const queryClient = new QueryClient({
|
|
@@ -104,6 +132,7 @@ describe("SettingsTabsPage", () => {
|
|
|
104
132
|
act(() => root.unmount());
|
|
105
133
|
activeQueryClient?.clear();
|
|
106
134
|
activeQueryClient = null;
|
|
135
|
+
restoreLocalStorage?.();
|
|
107
136
|
container.remove();
|
|
108
137
|
document.body.innerHTML = "";
|
|
109
138
|
vi.unstubAllGlobals();
|
|
@@ -256,6 +285,74 @@ describe("SettingsTabsPage", () => {
|
|
|
256
285
|
expect(document.activeElement).toBe(teamTab);
|
|
257
286
|
});
|
|
258
287
|
|
|
288
|
+
it("keeps an onboarding attempt through legacy settings tab navigation", async () => {
|
|
289
|
+
installTestLocalStorage();
|
|
290
|
+
vi.stubGlobal(
|
|
291
|
+
"fetch",
|
|
292
|
+
vi.fn(
|
|
293
|
+
async () =>
|
|
294
|
+
new Response(JSON.stringify({ error: "not authenticated" }), {
|
|
295
|
+
headers: { "Content-Type": "application/json" },
|
|
296
|
+
}),
|
|
297
|
+
),
|
|
298
|
+
);
|
|
299
|
+
expect(await setCustomKeyOnboardingAttempt("legacy-settings-nav")).toBe(
|
|
300
|
+
"stored",
|
|
301
|
+
);
|
|
302
|
+
|
|
303
|
+
act(() => {
|
|
304
|
+
root.render(
|
|
305
|
+
<SettingsTabsPage
|
|
306
|
+
general={<div>General content</div>}
|
|
307
|
+
team={<div>Team members</div>}
|
|
308
|
+
redesign={false}
|
|
309
|
+
/>,
|
|
310
|
+
);
|
|
311
|
+
});
|
|
312
|
+
|
|
313
|
+
const teamTab =
|
|
314
|
+
container.querySelector<HTMLButtonElement>("#settings-tab-team");
|
|
315
|
+
expect(teamTab).not.toBeNull();
|
|
316
|
+
act(() => teamTab!.click());
|
|
317
|
+
|
|
318
|
+
expect(trackCustomKeyOnboardingOutcome("credential_saved")).toBe("tracked");
|
|
319
|
+
});
|
|
320
|
+
|
|
321
|
+
it("records abandonment when a legacy settings route exits", async () => {
|
|
322
|
+
installTestLocalStorage();
|
|
323
|
+
vi.stubGlobal(
|
|
324
|
+
"fetch",
|
|
325
|
+
vi.fn(
|
|
326
|
+
async () =>
|
|
327
|
+
new Response(JSON.stringify({ error: "not authenticated" }), {
|
|
328
|
+
headers: { "Content-Type": "application/json" },
|
|
329
|
+
}),
|
|
330
|
+
),
|
|
331
|
+
);
|
|
332
|
+
expect(await setCustomKeyOnboardingAttempt("legacy-settings-exit")).toBe(
|
|
333
|
+
"stored",
|
|
334
|
+
);
|
|
335
|
+
|
|
336
|
+
act(() => {
|
|
337
|
+
root.render(
|
|
338
|
+
<SettingsTabsPage
|
|
339
|
+
general={<div>General content</div>}
|
|
340
|
+
team={<div>Team members</div>}
|
|
341
|
+
redesign={false}
|
|
342
|
+
/>,
|
|
343
|
+
);
|
|
344
|
+
});
|
|
345
|
+
|
|
346
|
+
const renderedRoot = root;
|
|
347
|
+
await act(async () => {
|
|
348
|
+
renderedRoot.unmount();
|
|
349
|
+
await Promise.resolve();
|
|
350
|
+
});
|
|
351
|
+
root = createRoot(container);
|
|
352
|
+
|
|
353
|
+
expect(trackCustomKeyOnboardingOutcome("credential_saved")).toBe("missing");
|
|
354
|
+
});
|
|
355
|
+
|
|
259
356
|
it("opens general settings by default when the route has no hash", () => {
|
|
260
357
|
act(() => {
|
|
261
358
|
root.render(
|
|
@@ -5,6 +5,7 @@ import {
|
|
|
5
5
|
import { useFeatureFlagState } from "@agent-native/core/client/feature-flags/use-feature-flag";
|
|
6
6
|
import { useT } from "@agent-native/core/client/i18n";
|
|
7
7
|
import type { LabStates } from "@agent-native/core/client/labs/use-lab";
|
|
8
|
+
import { useCustomKeyOnboardingAttemptLifecycle } from "@agent-native/core/client/onboarding/use-onboarding";
|
|
8
9
|
import { useActionQuery } from "@agent-native/core/client/use-action";
|
|
9
10
|
import { SETTINGS_REDESIGN_FLAG } from "@agent-native/core/feature-flags/registry";
|
|
10
11
|
import { CHATGPT_SUBSCRIPTION_LAB } from "@agent-native/core/labs/core-labs";
|
|
@@ -1058,6 +1059,7 @@ function RedesignedSettingsTabsPage(props: SettingsTabsPageProps) {
|
|
|
1058
1059
|
}
|
|
1059
1060
|
|
|
1060
1061
|
export function SettingsTabsPage(props: SettingsTabsPageProps) {
|
|
1062
|
+
useCustomKeyOnboardingAttemptLifecycle();
|
|
1061
1063
|
// No query client means no action surface to read the flag from, so the
|
|
1062
1064
|
// flag fails closed exactly as it does for a signed-out viewer. It also
|
|
1063
1065
|
// means the server's registered labs are unknown, so core labs stay hidden.
|