@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
|
@@ -5,6 +5,18 @@ import { createRoot, type Root } from "react-dom/client";
|
|
|
5
5
|
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
|
6
6
|
|
|
7
7
|
const sharedEditorProps = vi.hoisted(() => ({ current: null as any }));
|
|
8
|
+
const modelCatalogMocks = vi.hoisted(() => ({ load: vi.fn() }));
|
|
9
|
+
const resourceI18nMocks = vi.hoisted(() => ({
|
|
10
|
+
labels: {} as Record<string, string>,
|
|
11
|
+
}));
|
|
12
|
+
|
|
13
|
+
vi.mock("@agent-native/core/client/i18n", () => ({
|
|
14
|
+
useT: () => (key: string) => resourceI18nMocks.labels[key] ?? key,
|
|
15
|
+
}));
|
|
16
|
+
|
|
17
|
+
vi.mock("@agent-native/core/client/use-chat-models", () => ({
|
|
18
|
+
loadChatModelCatalog: modelCatalogMocks.load,
|
|
19
|
+
}));
|
|
8
20
|
|
|
9
21
|
vi.mock("@agent-native/toolkit/editor/SharedRichEditor", async () => {
|
|
10
22
|
const React = await import("react");
|
|
@@ -20,10 +32,23 @@ vi.mock("@agent-native/toolkit/editor/SharedRichEditor", async () => {
|
|
|
20
32
|
};
|
|
21
33
|
});
|
|
22
34
|
|
|
35
|
+
import { BUILDER_MODEL_CONFIG } from "@agent-native/core/agent/model-config";
|
|
23
36
|
import type { Resource } from "@agent-native/core/client/resources/use-resources";
|
|
24
37
|
|
|
25
38
|
import { ResourceEditor } from "./ResourceEditor.js";
|
|
26
39
|
|
|
40
|
+
const builderModelEngine = {
|
|
41
|
+
name: "builder",
|
|
42
|
+
label: "Builder.io Gateway",
|
|
43
|
+
...BUILDER_MODEL_CONFIG,
|
|
44
|
+
};
|
|
45
|
+
const anthropicModelEngine = {
|
|
46
|
+
name: "anthropic",
|
|
47
|
+
label: "Anthropic",
|
|
48
|
+
defaultModel: "claude-sonnet-5-5",
|
|
49
|
+
supportedModels: ["claude-sonnet-5-5", "claude-haiku-5-5", "claude-fable-5"],
|
|
50
|
+
};
|
|
51
|
+
|
|
27
52
|
const resource: Resource = {
|
|
28
53
|
id: "resource-1",
|
|
29
54
|
path: "skills/release/SKILL.md",
|
|
@@ -48,6 +73,16 @@ describe("ResourceEditor markdown editing", () => {
|
|
|
48
73
|
beforeEach(() => {
|
|
49
74
|
vi.useFakeTimers();
|
|
50
75
|
vi.stubGlobal("IS_REACT_ACT_ENVIRONMENT", true);
|
|
76
|
+
resourceI18nMocks.labels = {
|
|
77
|
+
"agentResources.defaultModel": "Default model",
|
|
78
|
+
"agentResources.builderModelFallback": "Builder fallback",
|
|
79
|
+
"agentResources.modelOptionsUnavailable": "Model options unavailable",
|
|
80
|
+
};
|
|
81
|
+
modelCatalogMocks.load.mockReset();
|
|
82
|
+
modelCatalogMocks.load.mockResolvedValue({
|
|
83
|
+
state: "unavailable",
|
|
84
|
+
enginesUnavailable: true,
|
|
85
|
+
});
|
|
51
86
|
container = document.createElement("div");
|
|
52
87
|
document.body.appendChild(container);
|
|
53
88
|
root = createRoot(container);
|
|
@@ -96,7 +131,7 @@ describe("ResourceEditor markdown editing", () => {
|
|
|
96
131
|
);
|
|
97
132
|
});
|
|
98
133
|
|
|
99
|
-
it("offers the
|
|
134
|
+
it("offers the current Claude models for custom agents", () => {
|
|
100
135
|
const onSave = vi.fn();
|
|
101
136
|
act(() => {
|
|
102
137
|
root.render(
|
|
@@ -105,22 +140,222 @@ describe("ResourceEditor markdown editing", () => {
|
|
|
105
140
|
...resource,
|
|
106
141
|
path: "agents/researcher.md",
|
|
107
142
|
content:
|
|
108
|
-
"---\nname: Researcher\nmodel: claude-sonnet-5\n---\n# Research\n",
|
|
143
|
+
"---\nname: Researcher\nmodel: claude-sonnet-5-5\n---\n# Research\n",
|
|
109
144
|
}}
|
|
110
145
|
onSave={onSave}
|
|
111
146
|
view="visual"
|
|
147
|
+
modelEngine={builderModelEngine}
|
|
148
|
+
/>,
|
|
149
|
+
);
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
const modelPicker = container.querySelector("select")!;
|
|
153
|
+
expect(modelPicker.value).toBe("claude-sonnet-5-5");
|
|
154
|
+
expect(
|
|
155
|
+
Array.from(modelPicker.options).some(
|
|
156
|
+
(option) =>
|
|
157
|
+
option.value === "claude-sonnet-5-5" &&
|
|
158
|
+
option.textContent === "Claude Sonnet 5.5",
|
|
159
|
+
),
|
|
160
|
+
).toBe(true);
|
|
161
|
+
expect(
|
|
162
|
+
Array.from(modelPicker.options).some(
|
|
163
|
+
(option) => option.value === "claude-haiku-5-5",
|
|
164
|
+
),
|
|
165
|
+
).toBe(true);
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
it("preserves a saved legacy Claude model in the picker", () => {
|
|
169
|
+
act(() => {
|
|
170
|
+
root.render(
|
|
171
|
+
<ResourceEditor
|
|
172
|
+
resource={{
|
|
173
|
+
...resource,
|
|
174
|
+
path: "agents/researcher.md",
|
|
175
|
+
content:
|
|
176
|
+
"---\nname: Researcher\nmodel: claude-haiku-4-5-20251001\n---\n# Research\n",
|
|
177
|
+
}}
|
|
178
|
+
onSave={vi.fn()}
|
|
179
|
+
view="visual"
|
|
180
|
+
modelEngine={builderModelEngine}
|
|
112
181
|
/>,
|
|
113
182
|
);
|
|
114
183
|
});
|
|
115
184
|
|
|
116
185
|
const modelPicker = container.querySelector("select")!;
|
|
117
|
-
expect(modelPicker.value).toBe("claude-
|
|
186
|
+
expect(modelPicker.value).toBe("claude-haiku-4-5-20251001");
|
|
118
187
|
expect(
|
|
119
188
|
Array.from(modelPicker.options).some(
|
|
120
189
|
(option) =>
|
|
121
|
-
option.value === "claude-
|
|
122
|
-
option.textContent ===
|
|
190
|
+
option.value === "claude-haiku-4-5-20251001" &&
|
|
191
|
+
option.textContent ===
|
|
192
|
+
"Claude Haiku 4.5 → Claude Haiku 5.5 · Builder fallback",
|
|
123
193
|
),
|
|
124
194
|
).toBe(true);
|
|
195
|
+
expect(
|
|
196
|
+
Array.from(modelPicker.options).some(
|
|
197
|
+
(option) => option.value === "claude-haiku-5-5",
|
|
198
|
+
),
|
|
199
|
+
).toBe(true);
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
it("shows the saved model label outside its curated options", () => {
|
|
203
|
+
resourceI18nMocks.labels["agentResources.builderModelFallback"] =
|
|
204
|
+
"Modelo alternativo";
|
|
205
|
+
act(() => {
|
|
206
|
+
root.render(
|
|
207
|
+
<ResourceEditor
|
|
208
|
+
resource={{
|
|
209
|
+
...resource,
|
|
210
|
+
path: "agents/researcher.md",
|
|
211
|
+
content:
|
|
212
|
+
"---\nname: Researcher\nmodel: claude-fable-5\n---\n# Research\n",
|
|
213
|
+
}}
|
|
214
|
+
onSave={vi.fn()}
|
|
215
|
+
view="visual"
|
|
216
|
+
modelEngine={builderModelEngine}
|
|
217
|
+
/>,
|
|
218
|
+
);
|
|
219
|
+
});
|
|
220
|
+
|
|
221
|
+
const modelPicker = container.querySelector("select")!;
|
|
222
|
+
expect(modelPicker.value).toBe("claude-fable-5");
|
|
223
|
+
expect(
|
|
224
|
+
Array.from(modelPicker.options).find(
|
|
225
|
+
(option) => option.value === "claude-fable-5",
|
|
226
|
+
)?.textContent,
|
|
227
|
+
).toBe("Claude Fable 5 → GPT-6 Luna · Modelo alternativo");
|
|
228
|
+
});
|
|
229
|
+
|
|
230
|
+
it("keeps an unchecked but runtime-supported model from showing a false fallback", () => {
|
|
231
|
+
act(() => {
|
|
232
|
+
root.render(
|
|
233
|
+
<ResourceEditor
|
|
234
|
+
resource={{
|
|
235
|
+
...resource,
|
|
236
|
+
path: "agents/researcher.md",
|
|
237
|
+
content:
|
|
238
|
+
"---\nname: Researcher\nmodel: claude-fable-5\n---\n# Research\n",
|
|
239
|
+
}}
|
|
240
|
+
onSave={vi.fn()}
|
|
241
|
+
view="visual"
|
|
242
|
+
modelEngine={{
|
|
243
|
+
name: "anthropic",
|
|
244
|
+
label: "Anthropic",
|
|
245
|
+
defaultModel: "claude-sonnet-5-5",
|
|
246
|
+
supportedModels: [
|
|
247
|
+
"claude-haiku-5-5",
|
|
248
|
+
"claude-sonnet-5-5",
|
|
249
|
+
"claude-fable-5",
|
|
250
|
+
],
|
|
251
|
+
selectableModels: ["claude-haiku-5-5"],
|
|
252
|
+
}}
|
|
253
|
+
/>,
|
|
254
|
+
);
|
|
255
|
+
});
|
|
256
|
+
|
|
257
|
+
const modelOption = Array.from(
|
|
258
|
+
container.querySelector("select")!.options,
|
|
259
|
+
).find((option) => option.value === "claude-fable-5");
|
|
260
|
+
expect(modelOption?.textContent).toBe("Claude Fable 5");
|
|
261
|
+
});
|
|
262
|
+
|
|
263
|
+
it("loads model choices when a standalone custom-agent editor opens", async () => {
|
|
264
|
+
modelCatalogMocks.load.mockResolvedValue({
|
|
265
|
+
state: "available",
|
|
266
|
+
groups: [],
|
|
267
|
+
modelEngines: { anthropic: anthropicModelEngine },
|
|
268
|
+
currentModelEngine: anthropicModelEngine,
|
|
269
|
+
defaultModel: "claude-sonnet-5-5",
|
|
270
|
+
loadLiveGroups: async () => null,
|
|
271
|
+
});
|
|
272
|
+
await act(async () => {
|
|
273
|
+
root.render(
|
|
274
|
+
<ResourceEditor
|
|
275
|
+
resource={{
|
|
276
|
+
...resource,
|
|
277
|
+
path: "agents/researcher.md",
|
|
278
|
+
content: "---\nname: Researcher\nmodel: inherit\n---\n# Research\n",
|
|
279
|
+
}}
|
|
280
|
+
onSave={vi.fn()}
|
|
281
|
+
view="visual"
|
|
282
|
+
/>,
|
|
283
|
+
);
|
|
284
|
+
await Promise.resolve();
|
|
285
|
+
await Promise.resolve();
|
|
286
|
+
});
|
|
287
|
+
|
|
288
|
+
expect(modelCatalogMocks.load).toHaveBeenCalledOnce();
|
|
289
|
+
expect(
|
|
290
|
+
Array.from(container.querySelector("select")!.options).map(
|
|
291
|
+
(option) => option.value,
|
|
292
|
+
),
|
|
293
|
+
).toContain("claude-haiku-5-5");
|
|
294
|
+
});
|
|
295
|
+
|
|
296
|
+
it("offers Anthropic Fable and labels it without a Builder fallback", () => {
|
|
297
|
+
act(() => {
|
|
298
|
+
root.render(
|
|
299
|
+
<ResourceEditor
|
|
300
|
+
resource={{
|
|
301
|
+
...resource,
|
|
302
|
+
path: "agents/researcher.md",
|
|
303
|
+
content:
|
|
304
|
+
"---\nname: Researcher\nmodel: claude-fable-5\n---\n# Research\n",
|
|
305
|
+
}}
|
|
306
|
+
onSave={vi.fn()}
|
|
307
|
+
view="visual"
|
|
308
|
+
modelEngine={anthropicModelEngine}
|
|
309
|
+
/>,
|
|
310
|
+
);
|
|
311
|
+
});
|
|
312
|
+
|
|
313
|
+
const modelPicker = container.querySelector("select")!;
|
|
314
|
+
expect(
|
|
315
|
+
Array.from(modelPicker.options).some(
|
|
316
|
+
(option) =>
|
|
317
|
+
option.value === "claude-fable-5" &&
|
|
318
|
+
option.textContent === "Claude Fable 5",
|
|
319
|
+
),
|
|
320
|
+
).toBe(true);
|
|
321
|
+
});
|
|
322
|
+
|
|
323
|
+
it("uses friendly names for provider-prefixed custom-agent model choices", () => {
|
|
324
|
+
const engine = {
|
|
325
|
+
name: "ai-sdk:openrouter",
|
|
326
|
+
label: "OpenRouter",
|
|
327
|
+
defaultModel: "openai/gpt-5.5",
|
|
328
|
+
supportedModels: [
|
|
329
|
+
"openai/gpt-5.5",
|
|
330
|
+
"google/gemini-3.1-pro-preview",
|
|
331
|
+
"deepseek/deepseek-v4-pro",
|
|
332
|
+
"qwen/qwen3-coder",
|
|
333
|
+
],
|
|
334
|
+
};
|
|
335
|
+
|
|
336
|
+
act(() => {
|
|
337
|
+
root.render(
|
|
338
|
+
<ResourceEditor
|
|
339
|
+
resource={{
|
|
340
|
+
...resource,
|
|
341
|
+
path: "agents/researcher.md",
|
|
342
|
+
content:
|
|
343
|
+
"---\nname: Researcher\nmodel: openai/gpt-5.5\n---\n# Research\n",
|
|
344
|
+
}}
|
|
345
|
+
onSave={vi.fn()}
|
|
346
|
+
view="visual"
|
|
347
|
+
modelEngine={engine}
|
|
348
|
+
/>,
|
|
349
|
+
);
|
|
350
|
+
});
|
|
351
|
+
|
|
352
|
+
const options = Array.from(container.querySelector("select")!.options);
|
|
353
|
+
expect(options.map((option) => option.textContent)).toEqual([
|
|
354
|
+
"Default model",
|
|
355
|
+
"GPT-5.5",
|
|
356
|
+
"Gemini 3.1 Pro",
|
|
357
|
+
"DeepSeek V4 Pro",
|
|
358
|
+
"Qwen3 Coder",
|
|
359
|
+
]);
|
|
125
360
|
});
|
|
126
361
|
});
|
|
@@ -1,8 +1,9 @@
|
|
|
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 { agentNativePath } from "@agent-native/core/client/api-path";
|
|
6
|
+
import { useT } from "@agent-native/core/client/i18n";
|
|
6
7
|
import type { Resource } from "@agent-native/core/client/resources/use-resources";
|
|
7
8
|
import {
|
|
8
9
|
type ParsedFrontmatter,
|
|
@@ -24,6 +25,11 @@ import React, {
|
|
|
24
25
|
useMemo,
|
|
25
26
|
} from "react";
|
|
26
27
|
|
|
28
|
+
import {
|
|
29
|
+
getCustomAgentModelOptions,
|
|
30
|
+
useCustomAgentModelEngine,
|
|
31
|
+
} from "./custom-agent-model-options.js";
|
|
32
|
+
|
|
27
33
|
export interface ResourceEditorProps {
|
|
28
34
|
resource: Resource;
|
|
29
35
|
onSave: (content: string) => void;
|
|
@@ -31,6 +37,8 @@ export interface ResourceEditorProps {
|
|
|
31
37
|
onViewChange?: (v: "visual" | "code") => void;
|
|
32
38
|
hideToolbar?: boolean;
|
|
33
39
|
readOnly?: boolean;
|
|
40
|
+
modelEngine?: ModelEngineConfig | null;
|
|
41
|
+
builderFallbackLabel?: string;
|
|
34
42
|
}
|
|
35
43
|
|
|
36
44
|
const CONTROL_STYLE = { fontSize: 12, lineHeight: 1 } as const;
|
|
@@ -67,11 +75,15 @@ function FrontmatterBar({
|
|
|
67
75
|
frontmatter,
|
|
68
76
|
onChange,
|
|
69
77
|
readOnly,
|
|
78
|
+
modelEngine,
|
|
79
|
+
builderFallbackLabel,
|
|
70
80
|
}: {
|
|
71
81
|
resourcePath: string;
|
|
72
82
|
frontmatter: ParsedFrontmatter;
|
|
73
83
|
onChange: (updated: ParsedFrontmatter) => void;
|
|
74
84
|
readOnly?: boolean;
|
|
85
|
+
modelEngine?: ModelEngineConfig | null;
|
|
86
|
+
builderFallbackLabel?: string;
|
|
75
87
|
}) {
|
|
76
88
|
const getField = (key: string) => getFrontmatterValue(frontmatter, key) ?? "";
|
|
77
89
|
|
|
@@ -96,6 +108,18 @@ function FrontmatterBar({
|
|
|
96
108
|
const tools = getField("tools") || "inherit";
|
|
97
109
|
const isCustomAgent = isCustomAgentPath(resourcePath);
|
|
98
110
|
const isSkill = isSkillPath(resourcePath);
|
|
111
|
+
const t = useT();
|
|
112
|
+
const modelEngineLoad = useCustomAgentModelEngine(
|
|
113
|
+
modelEngine,
|
|
114
|
+
!readOnly && isCustomAgent,
|
|
115
|
+
);
|
|
116
|
+
const effectiveModelEngine = modelEngineLoad.engine;
|
|
117
|
+
const effectiveBuilderFallbackLabel =
|
|
118
|
+
builderFallbackLabel ?? t("agentResources.builderModelFallback");
|
|
119
|
+
const modelOptions = getCustomAgentModelOptions(effectiveModelEngine, {
|
|
120
|
+
defaultModel: t("agentResources.defaultModel"),
|
|
121
|
+
builderFallback: effectiveBuilderFallbackLabel,
|
|
122
|
+
});
|
|
99
123
|
|
|
100
124
|
return (
|
|
101
125
|
<div
|
|
@@ -177,13 +201,26 @@ function FrontmatterBar({
|
|
|
177
201
|
padding: "2px 6px",
|
|
178
202
|
}}
|
|
179
203
|
>
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
204
|
+
{modelOptions.map((option) => (
|
|
205
|
+
<option key={option.value} value={option.value}>
|
|
206
|
+
{option.label}
|
|
207
|
+
</option>
|
|
208
|
+
))}
|
|
209
|
+
{modelEngineLoad.state === "unavailable" && (
|
|
210
|
+
<option value="__model-options-unavailable" disabled>
|
|
211
|
+
{t("agentResources.modelOptionsUnavailable")}
|
|
212
|
+
</option>
|
|
213
|
+
)}
|
|
214
|
+
{model !== "inherit" &&
|
|
215
|
+
!modelOptions.some((option) => option.value === model) && (
|
|
216
|
+
<option value={model}>
|
|
217
|
+
{getModelOptionLabel(
|
|
218
|
+
model,
|
|
219
|
+
effectiveModelEngine ?? undefined,
|
|
220
|
+
effectiveBuilderFallbackLabel,
|
|
221
|
+
)}
|
|
222
|
+
</option>
|
|
223
|
+
)}
|
|
187
224
|
</select>
|
|
188
225
|
) : null}
|
|
189
226
|
</div>
|
|
@@ -367,11 +404,15 @@ function VisualMarkdownEditor({
|
|
|
367
404
|
onChange,
|
|
368
405
|
resourcePath,
|
|
369
406
|
readOnly,
|
|
407
|
+
modelEngine,
|
|
408
|
+
builderFallbackLabel,
|
|
370
409
|
}: {
|
|
371
410
|
content: string;
|
|
372
411
|
onChange: (md: string) => void;
|
|
373
412
|
resourcePath: string;
|
|
374
413
|
readOnly?: boolean;
|
|
414
|
+
modelEngine?: ModelEngineConfig | null;
|
|
415
|
+
builderFallbackLabel?: string;
|
|
375
416
|
}) {
|
|
376
417
|
const parsed = useMemo(() => parseFrontmatter(content), [content]);
|
|
377
418
|
const frontmatterRef = useRef(parsed);
|
|
@@ -393,6 +434,8 @@ function VisualMarkdownEditor({
|
|
|
393
434
|
resourcePath={resourcePath}
|
|
394
435
|
frontmatter={parsed}
|
|
395
436
|
readOnly={readOnly}
|
|
437
|
+
modelEngine={modelEngine}
|
|
438
|
+
builderFallbackLabel={builderFallbackLabel}
|
|
396
439
|
onChange={(updated) => {
|
|
397
440
|
if (readOnly) return;
|
|
398
441
|
frontmatterRef.current = updated;
|
|
@@ -569,6 +612,8 @@ export function ResourceEditor({
|
|
|
569
612
|
onViewChange,
|
|
570
613
|
hideToolbar,
|
|
571
614
|
readOnly,
|
|
615
|
+
modelEngine,
|
|
616
|
+
builderFallbackLabel,
|
|
572
617
|
}: ResourceEditorProps) {
|
|
573
618
|
const [content, setContent] = useState(resource.content);
|
|
574
619
|
const [internalView, setInternalView] = useState<"visual" | "code">(
|
|
@@ -687,6 +732,8 @@ export function ResourceEditor({
|
|
|
687
732
|
onChange={handleChange}
|
|
688
733
|
resourcePath={resource.path}
|
|
689
734
|
readOnly={readOnly}
|
|
735
|
+
modelEngine={modelEngine}
|
|
736
|
+
builderFallbackLabel={builderFallbackLabel}
|
|
690
737
|
/>
|
|
691
738
|
</div>
|
|
692
739
|
) : (
|
|
@@ -24,6 +24,11 @@ const storageMocks = vi.hoisted(() => ({
|
|
|
24
24
|
dismiss: null as (() => void) | null,
|
|
25
25
|
setup: null as (() => void) | null,
|
|
26
26
|
}));
|
|
27
|
+
const modelCatalogMocks = vi.hoisted(() => ({ load: vi.fn() }));
|
|
28
|
+
|
|
29
|
+
vi.mock("@agent-native/core/client/use-chat-models", () => ({
|
|
30
|
+
loadChatModelCatalog: modelCatalogMocks.load,
|
|
31
|
+
}));
|
|
27
32
|
|
|
28
33
|
vi.mock("@agent-native/core/client/uploads/use-file-upload-status", () => ({
|
|
29
34
|
useFileUploadStatus: () => ({
|
|
@@ -92,6 +97,7 @@ vi.mock("../chat/FileStorageSetupPopover.js", () => ({
|
|
|
92
97
|
},
|
|
93
98
|
}));
|
|
94
99
|
|
|
100
|
+
import type { ModelEngineConfig } from "@agent-native/core/agent/model-version";
|
|
95
101
|
import type { TreeNode } from "@agent-native/core/client/resources/use-resources";
|
|
96
102
|
|
|
97
103
|
import { isResourceRowReadOnly } from "./ResourceSettingsGroups.js";
|
|
@@ -462,6 +468,11 @@ describe("ResourcesPanel storage retries", () => {
|
|
|
462
468
|
storageMocks.retry = null;
|
|
463
469
|
storageMocks.dismiss = null;
|
|
464
470
|
storageMocks.setup = null;
|
|
471
|
+
modelCatalogMocks.load.mockReset();
|
|
472
|
+
modelCatalogMocks.load.mockResolvedValue({
|
|
473
|
+
state: "unavailable",
|
|
474
|
+
enginesUnavailable: true,
|
|
475
|
+
});
|
|
465
476
|
container = document.createElement("div");
|
|
466
477
|
document.body.appendChild(container);
|
|
467
478
|
root = createRoot(container);
|
|
@@ -476,6 +487,7 @@ describe("ResourcesPanel storage retries", () => {
|
|
|
476
487
|
|
|
477
488
|
function renderPanel(
|
|
478
489
|
resourceFilter: "instructions" | "agents" = "instructions",
|
|
490
|
+
modelEngine?: ModelEngineConfig | null,
|
|
479
491
|
) {
|
|
480
492
|
act(() =>
|
|
481
493
|
root.render(
|
|
@@ -484,6 +496,7 @@ describe("ResourcesPanel storage retries", () => {
|
|
|
484
496
|
showOnlyRequestedScope: true,
|
|
485
497
|
resourceFilter,
|
|
486
498
|
showMcpServers: false,
|
|
499
|
+
modelEngine,
|
|
487
500
|
}),
|
|
488
501
|
),
|
|
489
502
|
);
|
|
@@ -761,8 +774,17 @@ describe("ResourcesPanel storage retries", () => {
|
|
|
761
774
|
).toBe("current.png");
|
|
762
775
|
});
|
|
763
776
|
|
|
764
|
-
it("offers the
|
|
765
|
-
renderPanel("agents"
|
|
777
|
+
it("offers the current Claude models when creating custom agents", () => {
|
|
778
|
+
renderPanel("agents", {
|
|
779
|
+
name: "anthropic",
|
|
780
|
+
label: "Anthropic",
|
|
781
|
+
defaultModel: "claude-sonnet-5-5",
|
|
782
|
+
supportedModels: [
|
|
783
|
+
"claude-haiku-5-5",
|
|
784
|
+
"claude-sonnet-5-5",
|
|
785
|
+
"claude-fable-5",
|
|
786
|
+
],
|
|
787
|
+
});
|
|
766
788
|
const addAgent = Array.from(document.querySelectorAll("button")).find(
|
|
767
789
|
(button) => button.textContent?.includes("Add agent"),
|
|
768
790
|
);
|
|
@@ -784,10 +806,70 @@ describe("ResourcesPanel storage retries", () => {
|
|
|
784
806
|
const modelPicker = document.querySelector("select")!;
|
|
785
807
|
expect(Array.from(modelPicker.options)).toContainEqual(
|
|
786
808
|
expect.objectContaining({
|
|
787
|
-
value: "claude-sonnet-5",
|
|
788
|
-
textContent: "Claude Sonnet 5",
|
|
809
|
+
value: "claude-sonnet-5-5",
|
|
810
|
+
textContent: "Claude Sonnet 5.5",
|
|
789
811
|
}),
|
|
790
812
|
);
|
|
813
|
+
expect(Array.from(modelPicker.options)).toContainEqual(
|
|
814
|
+
expect.objectContaining({
|
|
815
|
+
value: "claude-haiku-5-5",
|
|
816
|
+
textContent: "Claude Haiku 5.5",
|
|
817
|
+
}),
|
|
818
|
+
);
|
|
819
|
+
expect(Array.from(modelPicker.options)).toContainEqual(
|
|
820
|
+
expect.objectContaining({
|
|
821
|
+
value: "claude-fable-5",
|
|
822
|
+
textContent: "Claude Fable 5",
|
|
823
|
+
}),
|
|
824
|
+
);
|
|
825
|
+
});
|
|
826
|
+
|
|
827
|
+
it("loads the model catalog only after opening the custom-agent form", async () => {
|
|
828
|
+
modelCatalogMocks.load.mockResolvedValue({
|
|
829
|
+
state: "available",
|
|
830
|
+
groups: [],
|
|
831
|
+
modelEngines: {},
|
|
832
|
+
currentModelEngine: {
|
|
833
|
+
name: "anthropic",
|
|
834
|
+
label: "Anthropic",
|
|
835
|
+
defaultModel: "claude-sonnet-5-5",
|
|
836
|
+
supportedModels: ["claude-haiku-5-5", "claude-sonnet-5-5"],
|
|
837
|
+
selectableModels: ["claude-haiku-5-5", "claude-sonnet-5-5"],
|
|
838
|
+
},
|
|
839
|
+
defaultModel: "claude-sonnet-5-5",
|
|
840
|
+
loadLiveGroups: async () => null,
|
|
841
|
+
});
|
|
842
|
+
renderPanel("agents");
|
|
843
|
+
expect(modelCatalogMocks.load).not.toHaveBeenCalled();
|
|
844
|
+
|
|
845
|
+
const addAgent = Array.from(document.querySelectorAll("button")).find(
|
|
846
|
+
(button) => button.textContent?.includes("Add agent"),
|
|
847
|
+
);
|
|
848
|
+
expect(addAgent).toBeDefined();
|
|
849
|
+
act(() => addAgent!.click());
|
|
850
|
+
const createAgent = Array.from(document.querySelectorAll("button")).find(
|
|
851
|
+
(button) => button.textContent?.includes("Create Custom Agent"),
|
|
852
|
+
);
|
|
853
|
+
expect(createAgent).toBeDefined();
|
|
854
|
+
act(() => createAgent!.click());
|
|
855
|
+
expect(modelCatalogMocks.load).not.toHaveBeenCalled();
|
|
856
|
+
|
|
857
|
+
const fillForm = Array.from(document.querySelectorAll("button")).find(
|
|
858
|
+
(button) => button.textContent?.includes("Fill Form"),
|
|
859
|
+
);
|
|
860
|
+
expect(fillForm).toBeDefined();
|
|
861
|
+
await act(async () => {
|
|
862
|
+
fillForm!.click();
|
|
863
|
+
await Promise.resolve();
|
|
864
|
+
await Promise.resolve();
|
|
865
|
+
});
|
|
866
|
+
|
|
867
|
+
expect(modelCatalogMocks.load).toHaveBeenCalledOnce();
|
|
868
|
+
expect(
|
|
869
|
+
Array.from(document.querySelector("select")!.options).map(
|
|
870
|
+
(option) => option.value,
|
|
871
|
+
),
|
|
872
|
+
).toContain("claude-haiku-5-5");
|
|
791
873
|
});
|
|
792
874
|
});
|
|
793
875
|
|