@4djs/assistant 0.0.0 → 0.1.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 +49 -68
- package/dist/core/chat-activity.d.ts +19 -0
- package/dist/core/chat-activity.d.ts.map +1 -0
- package/dist/core/chat-commands.d.ts +33 -0
- package/dist/core/chat-commands.d.ts.map +1 -0
- package/dist/core/chat-history.d.ts +14 -0
- package/dist/core/chat-history.d.ts.map +1 -0
- package/dist/core/chat-reply-suggestions-parse.d.ts +20 -0
- package/dist/core/chat-reply-suggestions-parse.d.ts.map +1 -0
- package/dist/core/code-highlight.d.ts +3 -0
- package/dist/core/code-highlight.d.ts.map +1 -0
- package/dist/core/create-assistant-store.d.ts +33 -0
- package/dist/core/create-assistant-store.d.ts.map +1 -0
- package/dist/core/fetch-suggested-prompts.d.ts +11 -0
- package/dist/core/fetch-suggested-prompts.d.ts.map +1 -0
- package/dist/core/index.d.ts +19 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +2876 -0
- package/dist/core/interactive-tools/choices.d.ts +22 -0
- package/dist/core/interactive-tools/choices.d.ts.map +1 -0
- package/dist/core/interactive-tools/confirmation.d.ts +15 -0
- package/dist/core/interactive-tools/confirmation.d.ts.map +1 -0
- package/dist/core/interactive-tools/constants.d.ts +6 -0
- package/dist/core/interactive-tools/constants.d.ts.map +1 -0
- package/dist/core/interactive-tools/execute.d.ts +11 -0
- package/dist/core/interactive-tools/execute.d.ts.map +1 -0
- package/dist/core/interactive-tools/index.d.ts +7 -0
- package/dist/core/interactive-tools/index.d.ts.map +1 -0
- package/dist/core/interactive-tools/suggestions.d.ts +13 -0
- package/dist/core/interactive-tools/suggestions.d.ts.map +1 -0
- package/dist/core/interactive-tools/waiters.d.ts +4 -0
- package/dist/core/interactive-tools/waiters.d.ts.map +1 -0
- package/dist/core/llm-chat.d.ts +96 -0
- package/dist/core/llm-chat.d.ts.map +1 -0
- package/dist/core/llm-config.d.ts +24 -0
- package/dist/core/llm-config.d.ts.map +1 -0
- package/dist/core/llm-models.d.ts +14 -0
- package/dist/core/llm-models.d.ts.map +1 -0
- package/dist/core/llm-provider.d.ts +13 -0
- package/dist/core/llm-provider.d.ts.map +1 -0
- package/dist/core/llm-settings-storage.d.ts +47 -0
- package/dist/core/llm-settings-storage.d.ts.map +1 -0
- package/dist/core/llm-sse.d.ts +13 -0
- package/dist/core/llm-sse.d.ts.map +1 -0
- package/dist/core/llm-types.d.ts +49 -0
- package/dist/core/llm-types.d.ts.map +1 -0
- package/dist/core/markdown-utils.d.ts +3 -0
- package/dist/core/markdown-utils.d.ts.map +1 -0
- package/dist/core/prepare-markdown.d.ts +7 -0
- package/dist/core/prepare-markdown.d.ts.map +1 -0
- package/dist/core/types.d.ts +74 -0
- package/dist/core/types.d.ts.map +1 -0
- package/dist/index.css +1195 -0
- package/dist/index.js +184948 -0
- package/dist/react/Assistant.d.ts +10 -0
- package/dist/react/Assistant.d.ts.map +1 -0
- package/dist/react/components/HighlightedJsonCode.d.ts +6 -0
- package/dist/react/components/HighlightedJsonCode.d.ts.map +1 -0
- package/dist/react/components/MarkdownContent.d.ts +10 -0
- package/dist/react/components/MarkdownContent.d.ts.map +1 -0
- package/dist/react/components/MarkdownEditor.d.ts +11 -0
- package/dist/react/components/MarkdownEditor.d.ts.map +1 -0
- package/dist/react/components/MermaidDiagram.d.ts +8 -0
- package/dist/react/components/MermaidDiagram.d.ts.map +1 -0
- package/dist/react/components/ModelSelector.d.ts +8 -0
- package/dist/react/components/ModelSelector.d.ts.map +1 -0
- package/dist/react/components/chat/AssistantErrorCallout.d.ts +11 -0
- package/dist/react/components/chat/AssistantErrorCallout.d.ts.map +1 -0
- package/dist/react/components/chat/ChatActivity.d.ts +8 -0
- package/dist/react/components/chat/ChatActivity.d.ts.map +1 -0
- package/dist/react/components/chat/ChatComposer.d.ts +36 -0
- package/dist/react/components/chat/ChatComposer.d.ts.map +1 -0
- package/dist/react/components/chat/ChatEmptyState.d.ts +10 -0
- package/dist/react/components/chat/ChatEmptyState.d.ts.map +1 -0
- package/dist/react/components/chat/ChatInteractivePrompt/choices-prompt.d.ts +7 -0
- package/dist/react/components/chat/ChatInteractivePrompt/choices-prompt.d.ts.map +1 -0
- package/dist/react/components/chat/ChatInteractivePrompt/confirmation-prompt.d.ts +7 -0
- package/dist/react/components/chat/ChatInteractivePrompt/confirmation-prompt.d.ts.map +1 -0
- package/dist/react/components/chat/ChatInteractivePrompt/index.d.ts +7 -0
- package/dist/react/components/chat/ChatInteractivePrompt/index.d.ts.map +1 -0
- package/dist/react/components/chat/ChatInteractivePrompt/shell.d.ts +13 -0
- package/dist/react/components/chat/ChatInteractivePrompt/shell.d.ts.map +1 -0
- package/dist/react/components/chat/ChatInteractivePrompt/utils.d.ts +4 -0
- package/dist/react/components/chat/ChatInteractivePrompt/utils.d.ts.map +1 -0
- package/dist/react/components/chat/ChatMessage.d.ts +11 -0
- package/dist/react/components/chat/ChatMessage.d.ts.map +1 -0
- package/dist/react/components/chat/ChatMessageScroll.d.ts +8 -0
- package/dist/react/components/chat/ChatMessageScroll.d.ts.map +1 -0
- package/dist/react/components/chat/ChatReplySuggestions.d.ts +9 -0
- package/dist/react/components/chat/ChatReplySuggestions.d.ts.map +1 -0
- package/dist/react/components/chat/ComposerCommandMenu.d.ts +10 -0
- package/dist/react/components/chat/ComposerCommandMenu.d.ts.map +1 -0
- package/dist/react/components/chat/LlmSettingsStrip.d.ts +7 -0
- package/dist/react/components/chat/LlmSettingsStrip.d.ts.map +1 -0
- package/dist/react/components/chat/LlmSetupPrompt.d.ts +7 -0
- package/dist/react/components/chat/LlmSetupPrompt.d.ts.map +1 -0
- package/dist/react/components/chat/LlmUnavailableBanner.d.ts +6 -0
- package/dist/react/components/chat/LlmUnavailableBanner.d.ts.map +1 -0
- package/dist/react/components/chat/SuggestedPromptsList.d.ts +14 -0
- package/dist/react/components/chat/SuggestedPromptsList.d.ts.map +1 -0
- package/dist/react/components/chat/SuggestedPromptsStrip.d.ts +11 -0
- package/dist/react/components/chat/SuggestedPromptsStrip.d.ts.map +1 -0
- package/dist/react/components/chat/SystemPromptField.d.ts +10 -0
- package/dist/react/components/chat/SystemPromptField.d.ts.map +1 -0
- package/dist/react/components/highlighted-code.d.ts +8 -0
- package/dist/react/components/highlighted-code.d.ts.map +1 -0
- package/dist/react/context.d.ts +11 -0
- package/dist/react/context.d.ts.map +1 -0
- package/dist/react/hooks/use-composer-commands.d.ts +21 -0
- package/dist/react/hooks/use-composer-commands.d.ts.map +1 -0
- package/dist/react/hooks/use-suggested-prompts.d.ts +29 -0
- package/dist/react/hooks/use-suggested-prompts.d.ts.map +1 -0
- package/dist/react/index.d.ts +17 -0
- package/dist/react/index.d.ts.map +1 -0
- package/dist/react/lib/parse-assistant-error.d.ts +9 -0
- package/dist/react/lib/parse-assistant-error.d.ts.map +1 -0
- package/dist/react/lib/prompt-icons.d.ts +5 -0
- package/dist/react/lib/prompt-icons.d.ts.map +1 -0
- package/dist/react/types.d.ts +69 -0
- package/dist/react/types.d.ts.map +1 -0
- package/dist/react/utils/cn.d.ts +2 -0
- package/dist/react/utils/cn.d.ts.map +1 -0
- package/package.json +16 -5
- package/src/core/chat-activity.ts +0 -107
- package/src/core/chat-commands.ts +0 -173
- package/src/core/chat-history.ts +0 -113
- package/src/core/chat-reply-suggestions-parse.ts +0 -119
- package/src/core/code-highlight.ts +0 -20
- package/src/core/create-assistant-store.ts +0 -639
- package/src/core/fetch-suggested-prompts.ts +0 -53
- package/src/core/index.ts +0 -125
- package/src/core/interactive-tools/choices.ts +0 -155
- package/src/core/interactive-tools/confirmation.ts +0 -63
- package/src/core/interactive-tools/constants.ts +0 -22
- package/src/core/interactive-tools/execute.ts +0 -70
- package/src/core/interactive-tools/index.ts +0 -41
- package/src/core/interactive-tools/suggestions.ts +0 -87
- package/src/core/interactive-tools/waiters.ts +0 -55
- package/src/core/llm-chat.ts +0 -686
- package/src/core/llm-config.ts +0 -101
- package/src/core/llm-models.ts +0 -96
- package/src/core/llm-provider.ts +0 -99
- package/src/core/llm-settings-storage.ts +0 -331
- package/src/core/llm-sse.ts +0 -166
- package/src/core/llm-types.ts +0 -52
- package/src/core/markdown-utils.ts +0 -11
- package/src/core/prepare-markdown.ts +0 -38
- package/src/core/types.ts +0 -86
- package/src/css.d.ts +0 -1
- package/src/react/Assistant.tsx +0 -358
- package/src/react/components/HighlightedJsonCode.tsx +0 -24
- package/src/react/components/MarkdownContent.tsx +0 -98
- package/src/react/components/MarkdownEditor.tsx +0 -60
- package/src/react/components/MermaidDiagram.tsx +0 -139
- package/src/react/components/ModelSelector.tsx +0 -243
- package/src/react/components/chat/AssistantErrorCallout.tsx +0 -79
- package/src/react/components/chat/ChatActivity.tsx +0 -274
- package/src/react/components/chat/ChatComposer.tsx +0 -189
- package/src/react/components/chat/ChatEmptyState.tsx +0 -145
- package/src/react/components/chat/ChatInteractivePrompt/choices-prompt.tsx +0 -262
- package/src/react/components/chat/ChatInteractivePrompt/confirmation-prompt.tsx +0 -97
- package/src/react/components/chat/ChatInteractivePrompt/index.tsx +0 -60
- package/src/react/components/chat/ChatInteractivePrompt/shell.tsx +0 -60
- package/src/react/components/chat/ChatInteractivePrompt/utils.ts +0 -14
- package/src/react/components/chat/ChatMessage.tsx +0 -150
- package/src/react/components/chat/ChatMessageScroll.tsx +0 -116
- package/src/react/components/chat/ChatReplySuggestions.tsx +0 -231
- package/src/react/components/chat/ComposerCommandMenu.tsx +0 -69
- package/src/react/components/chat/LlmSettingsStrip.tsx +0 -348
- package/src/react/components/chat/LlmSetupPrompt.tsx +0 -58
- package/src/react/components/chat/LlmUnavailableBanner.tsx +0 -11
- package/src/react/components/chat/SuggestedPromptsList.tsx +0 -121
- package/src/react/components/chat/SuggestedPromptsStrip.tsx +0 -72
- package/src/react/components/chat/SystemPromptField.tsx +0 -107
- package/src/react/components/highlighted-code.tsx +0 -107
- package/src/react/context.tsx +0 -72
- package/src/react/hooks/use-composer-commands.ts +0 -129
- package/src/react/hooks/use-suggested-prompts.ts +0 -128
- package/src/react/index.ts +0 -39
- package/src/react/lib/parse-assistant-error.ts +0 -96
- package/src/react/lib/prompt-icons.ts +0 -40
- package/src/react/types.ts +0 -83
- package/src/react/utils/cn.ts +0 -5
- package/test/buildLlmHistory.test.ts +0 -95
- package/test/llm-config.test.ts +0 -72
- package/test/llmSettingsStorage.test.ts +0 -121
- package/test/parse-assistant-error.test.ts +0 -24
- package/tsconfig.json +0 -8
- /package/{src/styles/assistant.css → dist/styles.css} +0 -0
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
import type { LucideIcon } from "lucide-react";
|
|
2
|
-
import {
|
|
3
|
-
Code,
|
|
4
|
-
Database,
|
|
5
|
-
Layers,
|
|
6
|
-
Search,
|
|
7
|
-
Sparkles,
|
|
8
|
-
Table,
|
|
9
|
-
Terminal,
|
|
10
|
-
Wrench,
|
|
11
|
-
Zap,
|
|
12
|
-
} from "lucide-react";
|
|
13
|
-
|
|
14
|
-
const PROMPT_ICONS: Record<string, LucideIcon> = {
|
|
15
|
-
database: Database,
|
|
16
|
-
db: Database,
|
|
17
|
-
search: Search,
|
|
18
|
-
find: Search,
|
|
19
|
-
terminal: Terminal,
|
|
20
|
-
shell: Terminal,
|
|
21
|
-
wrench: Wrench,
|
|
22
|
-
tool: Wrench,
|
|
23
|
-
sparkles: Sparkles,
|
|
24
|
-
magic: Sparkles,
|
|
25
|
-
table: Table,
|
|
26
|
-
grid: Table,
|
|
27
|
-
code: Code,
|
|
28
|
-
layers: Layers,
|
|
29
|
-
stack: Layers,
|
|
30
|
-
zap: Zap,
|
|
31
|
-
lightning: Zap,
|
|
32
|
-
};
|
|
33
|
-
|
|
34
|
-
export function resolvePromptIcon(name?: string): LucideIcon | undefined {
|
|
35
|
-
if (!name) return undefined;
|
|
36
|
-
const key = name.trim().toLowerCase();
|
|
37
|
-
return PROMPT_ICONS[key];
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
export { Sparkles as DEFAULT_PROMPT_ICON };
|
package/src/react/types.ts
DELETED
|
@@ -1,83 +0,0 @@
|
|
|
1
|
-
import type { LucideIcon } from "lucide-react";
|
|
2
|
-
import type { ReactNode } from "react";
|
|
3
|
-
import type { AssistantStore } from "../core/create-assistant-store.ts";
|
|
4
|
-
import type {
|
|
5
|
-
AssistantStoreDependencies,
|
|
6
|
-
AssistantSuggestedPrompt,
|
|
7
|
-
AssistantToolDefinition,
|
|
8
|
-
} from "../core/types.ts";
|
|
9
|
-
|
|
10
|
-
export interface AssistantSuggestedPromptWithIcon
|
|
11
|
-
extends Omit<AssistantSuggestedPrompt, "icon"> {
|
|
12
|
-
icon?: LucideIcon;
|
|
13
|
-
hint?: string;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
export interface AssistantEmptyStateConfig {
|
|
17
|
-
title: string;
|
|
18
|
-
description: string;
|
|
19
|
-
/** Static fallback prompts when LLM is disabled or fetch fails */
|
|
20
|
-
suggestedPrompts?: AssistantSuggestedPromptWithIcon[];
|
|
21
|
-
/** Allow fetching contextual prompts via LLM (manual trigger; default: true) */
|
|
22
|
-
dynamicSuggestedPrompts?: boolean;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
export interface AssistantHeaderConfig {
|
|
26
|
-
title?: string;
|
|
27
|
-
subtitle?: string;
|
|
28
|
-
icon?: LucideIcon;
|
|
29
|
-
showClearButton?: boolean;
|
|
30
|
-
/** Show button to generate LLM suggested prompts (default: true when fetchSuggestedPrompts is set) */
|
|
31
|
-
showSuggestionsButton?: boolean;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
export interface AssistantUiConfig {
|
|
35
|
-
composerPlaceholder?: string;
|
|
36
|
-
showModelSelector?: boolean;
|
|
37
|
-
/** Show LLM settings button in the composer footer (default: true) */
|
|
38
|
-
showLlmSettings?: boolean;
|
|
39
|
-
maxWidth?: string;
|
|
40
|
-
className?: string;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
export interface AssistantConfig extends AssistantStoreDependencies {
|
|
44
|
-
emptyState?: AssistantEmptyStateConfig;
|
|
45
|
-
header?: AssistantHeaderConfig;
|
|
46
|
-
ui?: AssistantUiConfig;
|
|
47
|
-
/** Load LLM config on mount (default: true) */
|
|
48
|
-
autoLoadLlmStatus?: boolean;
|
|
49
|
-
/** Optional hook to fetch contextual empty-state prompts via the configured LLM */
|
|
50
|
-
fetchSuggestedPrompts?: (ctx: {
|
|
51
|
-
llmEnabled: boolean;
|
|
52
|
-
model: string | null;
|
|
53
|
-
tools: AssistantToolDefinition[];
|
|
54
|
-
}) => Promise<
|
|
55
|
-
Array<{
|
|
56
|
-
id: string;
|
|
57
|
-
label: string;
|
|
58
|
-
description?: string;
|
|
59
|
-
prompt: string;
|
|
60
|
-
icon?: string;
|
|
61
|
-
}>
|
|
62
|
-
>;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
export interface AssistantContextValue {
|
|
66
|
-
store: AssistantStore;
|
|
67
|
-
config: AssistantConfig;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
export interface AssistantProviderProps {
|
|
71
|
-
config: AssistantConfig;
|
|
72
|
-
children: ReactNode;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
export interface AssistantProps {
|
|
76
|
-
className?: string;
|
|
77
|
-
/** Override header from provider config */
|
|
78
|
-
header?: AssistantHeaderConfig;
|
|
79
|
-
/** Override empty state from provider config */
|
|
80
|
-
emptyState?: AssistantEmptyStateConfig;
|
|
81
|
-
/** Override UI options from provider config */
|
|
82
|
-
ui?: AssistantUiConfig;
|
|
83
|
-
}
|
package/src/react/utils/cn.ts
DELETED
|
@@ -1,95 +0,0 @@
|
|
|
1
|
-
import { expect, test } from "bun:test";
|
|
2
|
-
import { buildLlmHistory, sanitizeLlmMessages } from "../src/core/llm-chat.ts";
|
|
3
|
-
import type { LlmChatMessage } from "../src/core/llm-types.ts";
|
|
4
|
-
|
|
5
|
-
test("buildLlmHistory keeps assistant tool_calls grouped with tool results when trimming", () => {
|
|
6
|
-
const messages = Array.from({ length: 15 }, (_, index) => ({
|
|
7
|
-
role: "user" as const,
|
|
8
|
-
content: `question ${index}`,
|
|
9
|
-
}));
|
|
10
|
-
|
|
11
|
-
messages.push({
|
|
12
|
-
role: "assistant",
|
|
13
|
-
content: "Found users",
|
|
14
|
-
activity: [
|
|
15
|
-
{
|
|
16
|
-
name: "query_entities",
|
|
17
|
-
args: { dataClass: "User" },
|
|
18
|
-
result: { __COUNT: 1 },
|
|
19
|
-
},
|
|
20
|
-
{
|
|
21
|
-
name: "suggest_replies",
|
|
22
|
-
args: { question: "Next?", suggestions: ["A", "B"] },
|
|
23
|
-
result: { displayed: true },
|
|
24
|
-
},
|
|
25
|
-
],
|
|
26
|
-
});
|
|
27
|
-
|
|
28
|
-
const history = buildLlmHistory(messages);
|
|
29
|
-
expect(history[0]?.role).not.toBe("tool");
|
|
30
|
-
expect(history.some((message) => message.role === "tool")).toBe(true);
|
|
31
|
-
|
|
32
|
-
const assistantWithTools = history.find(
|
|
33
|
-
(message) => message.role === "assistant" && message.tool_calls?.length,
|
|
34
|
-
);
|
|
35
|
-
expect(assistantWithTools).toBeDefined();
|
|
36
|
-
for (const toolCall of assistantWithTools?.tool_calls ?? []) {
|
|
37
|
-
expect(
|
|
38
|
-
history.some(
|
|
39
|
-
(message) =>
|
|
40
|
-
message.role === "tool" && message.tool_call_id === toolCall.id,
|
|
41
|
-
),
|
|
42
|
-
).toBe(true);
|
|
43
|
-
}
|
|
44
|
-
});
|
|
45
|
-
|
|
46
|
-
test("sanitizeLlmMessages drops orphan tool messages", () => {
|
|
47
|
-
const messages: LlmChatMessage[] = [
|
|
48
|
-
{
|
|
49
|
-
role: "tool",
|
|
50
|
-
tool_call_id: "call_orphan",
|
|
51
|
-
content: "{}",
|
|
52
|
-
},
|
|
53
|
-
{ role: "user", content: "hello" },
|
|
54
|
-
{
|
|
55
|
-
role: "assistant",
|
|
56
|
-
content: null,
|
|
57
|
-
tool_calls: [
|
|
58
|
-
{
|
|
59
|
-
id: "call_ok_0",
|
|
60
|
-
type: "function",
|
|
61
|
-
function: { name: "query_entities", arguments: "{}" },
|
|
62
|
-
},
|
|
63
|
-
{
|
|
64
|
-
id: "call_ok_1",
|
|
65
|
-
type: "function",
|
|
66
|
-
function: { name: "suggest_replies", arguments: "{}" },
|
|
67
|
-
},
|
|
68
|
-
],
|
|
69
|
-
},
|
|
70
|
-
{ role: "tool", tool_call_id: "call_ok_0", content: "{}" },
|
|
71
|
-
{ role: "tool", tool_call_id: "call_ok_1", content: "{}" },
|
|
72
|
-
];
|
|
73
|
-
|
|
74
|
-
expect(sanitizeLlmMessages(messages)).toEqual([
|
|
75
|
-
{ role: "user", content: "hello" },
|
|
76
|
-
{
|
|
77
|
-
role: "assistant",
|
|
78
|
-
content: null,
|
|
79
|
-
tool_calls: [
|
|
80
|
-
{
|
|
81
|
-
id: "call_ok_0",
|
|
82
|
-
type: "function",
|
|
83
|
-
function: { name: "query_entities", arguments: "{}" },
|
|
84
|
-
},
|
|
85
|
-
{
|
|
86
|
-
id: "call_ok_1",
|
|
87
|
-
type: "function",
|
|
88
|
-
function: { name: "suggest_replies", arguments: "{}" },
|
|
89
|
-
},
|
|
90
|
-
],
|
|
91
|
-
},
|
|
92
|
-
{ role: "tool", tool_call_id: "call_ok_0", content: "{}" },
|
|
93
|
-
{ role: "tool", tool_call_id: "call_ok_1", content: "{}" },
|
|
94
|
-
]);
|
|
95
|
-
});
|
package/test/llm-config.test.ts
DELETED
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
import { describe, expect, test } from "bun:test";
|
|
2
|
-
import {
|
|
3
|
-
isLlmConfigured,
|
|
4
|
-
isLlmUnavailableMessage,
|
|
5
|
-
isLocalLlmBaseUrl,
|
|
6
|
-
} from "../src/core/llm-config.ts";
|
|
7
|
-
|
|
8
|
-
describe("isLocalLlmBaseUrl", () => {
|
|
9
|
-
test("detects localhost providers", () => {
|
|
10
|
-
expect(isLocalLlmBaseUrl("http://127.0.0.1:11434/v1")).toBe(true);
|
|
11
|
-
expect(isLocalLlmBaseUrl("http://localhost:1234/v1")).toBe(true);
|
|
12
|
-
});
|
|
13
|
-
|
|
14
|
-
test("rejects remote providers", () => {
|
|
15
|
-
expect(isLocalLlmBaseUrl("https://api.openai.com/v1")).toBe(false);
|
|
16
|
-
});
|
|
17
|
-
});
|
|
18
|
-
|
|
19
|
-
describe("isLlmConfigured", () => {
|
|
20
|
-
test("requires an api key for remote providers", () => {
|
|
21
|
-
expect(
|
|
22
|
-
isLlmConfigured({
|
|
23
|
-
enabled: true,
|
|
24
|
-
baseUrl: "https://api.openai.com/v1",
|
|
25
|
-
apiKey: null,
|
|
26
|
-
model: "gpt-4o-mini",
|
|
27
|
-
}),
|
|
28
|
-
).toBe(false);
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
test("allows local providers without an api key", () => {
|
|
32
|
-
expect(
|
|
33
|
-
isLlmConfigured({
|
|
34
|
-
enabled: true,
|
|
35
|
-
baseUrl: "http://127.0.0.1:11434/v1",
|
|
36
|
-
apiKey: null,
|
|
37
|
-
model: "llama3.2",
|
|
38
|
-
}),
|
|
39
|
-
).toBe(true);
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
test("accepts remote providers with an api key", () => {
|
|
43
|
-
expect(
|
|
44
|
-
isLlmConfigured({
|
|
45
|
-
enabled: true,
|
|
46
|
-
baseUrl: "https://api.openai.com/v1",
|
|
47
|
-
apiKey: "sk-test",
|
|
48
|
-
model: "gpt-4o-mini",
|
|
49
|
-
}),
|
|
50
|
-
).toBe(true);
|
|
51
|
-
});
|
|
52
|
-
});
|
|
53
|
-
|
|
54
|
-
describe("isLlmUnavailableMessage", () => {
|
|
55
|
-
test("detects explicit setup flag", () => {
|
|
56
|
-
expect(
|
|
57
|
-
isLlmUnavailableMessage({
|
|
58
|
-
content: "anything",
|
|
59
|
-
llmSetupRequired: true,
|
|
60
|
-
}),
|
|
61
|
-
).toBe(true);
|
|
62
|
-
});
|
|
63
|
-
|
|
64
|
-
test("detects legacy plain-text content", () => {
|
|
65
|
-
expect(
|
|
66
|
-
isLlmUnavailableMessage({
|
|
67
|
-
content:
|
|
68
|
-
"Chat requires an LLM. Open LLM settings to add your provider base URL, model, and API key (optional for local servers).",
|
|
69
|
-
}),
|
|
70
|
-
).toBe(true);
|
|
71
|
-
});
|
|
72
|
-
});
|
|
@@ -1,121 +0,0 @@
|
|
|
1
|
-
import { expect, test } from "bun:test";
|
|
2
|
-
import {
|
|
3
|
-
assistantToStored,
|
|
4
|
-
createDefaultStoredSettings,
|
|
5
|
-
isLlmSettingsFormDirty,
|
|
6
|
-
mergeLlmSettings,
|
|
7
|
-
normalizeStoredSettings,
|
|
8
|
-
normalizeStoredSystemPrompt,
|
|
9
|
-
resolveSelectedModel,
|
|
10
|
-
storedSettingsHaveOverrides,
|
|
11
|
-
storedToAssistant,
|
|
12
|
-
toStoredSettings,
|
|
13
|
-
} from "../src/core/llm-settings-storage.ts";
|
|
14
|
-
|
|
15
|
-
const base = {
|
|
16
|
-
enabled: true,
|
|
17
|
-
baseUrl: "https://api.openai.com/v1",
|
|
18
|
-
apiKey: "env-key",
|
|
19
|
-
model: "gpt-4o-mini",
|
|
20
|
-
models: ["gpt-4o-mini", "gpt-4o"],
|
|
21
|
-
systemPrompt: "Default prompt",
|
|
22
|
-
};
|
|
23
|
-
|
|
24
|
-
test("toStoredSettings persists all fields including empty system prompt", () => {
|
|
25
|
-
const stored = toStoredSettings(
|
|
26
|
-
{
|
|
27
|
-
baseUrl: "https://custom.example/v1",
|
|
28
|
-
apiKey: "",
|
|
29
|
-
model: "gpt-4o",
|
|
30
|
-
modelsText: "gpt-4o, gpt-4o-mini",
|
|
31
|
-
systemPrompt: "",
|
|
32
|
-
},
|
|
33
|
-
"existing-key",
|
|
34
|
-
);
|
|
35
|
-
|
|
36
|
-
expect(stored).toEqual({
|
|
37
|
-
baseUrl: "https://custom.example/v1",
|
|
38
|
-
apiKey: "existing-key",
|
|
39
|
-
model: "gpt-4o",
|
|
40
|
-
models: ["gpt-4o", "gpt-4o-mini"],
|
|
41
|
-
systemPrompt: "",
|
|
42
|
-
});
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
test("stored settings round-trip through merge", () => {
|
|
46
|
-
const stored = assistantToStored(base);
|
|
47
|
-
const merged = mergeLlmSettings(
|
|
48
|
-
{ enabled: false, baseUrl: "x", apiKey: null, model: "y" },
|
|
49
|
-
stored,
|
|
50
|
-
);
|
|
51
|
-
|
|
52
|
-
expect(merged).toEqual(storedToAssistant(stored));
|
|
53
|
-
});
|
|
54
|
-
|
|
55
|
-
test("normalizeStoredSettings fills missing legacy fields from base", () => {
|
|
56
|
-
const normalized = normalizeStoredSettings({ model: "gpt-4.1" }, base);
|
|
57
|
-
|
|
58
|
-
expect(normalized?.model).toBe("gpt-4.1");
|
|
59
|
-
expect(normalized?.baseUrl).toBe(base.baseUrl);
|
|
60
|
-
expect(normalized?.apiKey).toBe(base.apiKey);
|
|
61
|
-
expect(normalized?.systemPrompt).toBe(base.systemPrompt);
|
|
62
|
-
});
|
|
63
|
-
|
|
64
|
-
test("empty stored system prompt falls back to base default", () => {
|
|
65
|
-
const stored = createDefaultStoredSettings(base);
|
|
66
|
-
const merged = mergeLlmSettings(base, stored);
|
|
67
|
-
|
|
68
|
-
expect(merged.systemPrompt).toBe(base.systemPrompt);
|
|
69
|
-
});
|
|
70
|
-
|
|
71
|
-
test("storedSettingsHaveOverrides ignores default system prompt content", () => {
|
|
72
|
-
const defaults = createDefaultStoredSettings(base);
|
|
73
|
-
expect(storedSettingsHaveOverrides(defaults, base)).toBe(false);
|
|
74
|
-
expect(
|
|
75
|
-
storedSettingsHaveOverrides(
|
|
76
|
-
{ ...defaults, systemPrompt: base.systemPrompt ?? "" },
|
|
77
|
-
base,
|
|
78
|
-
),
|
|
79
|
-
).toBe(false);
|
|
80
|
-
expect(
|
|
81
|
-
storedSettingsHaveOverrides(
|
|
82
|
-
{ ...defaults, systemPrompt: "Custom prompt" },
|
|
83
|
-
base,
|
|
84
|
-
),
|
|
85
|
-
).toBe(true);
|
|
86
|
-
});
|
|
87
|
-
|
|
88
|
-
test("normalizeStoredSystemPrompt collapses base prompt to empty", () => {
|
|
89
|
-
expect(normalizeStoredSystemPrompt("", base)).toBe("");
|
|
90
|
-
expect(normalizeStoredSystemPrompt("Default prompt", base)).toBe("");
|
|
91
|
-
expect(normalizeStoredSystemPrompt("Custom prompt", base)).toBe(
|
|
92
|
-
"Custom prompt",
|
|
93
|
-
);
|
|
94
|
-
});
|
|
95
|
-
|
|
96
|
-
test("isLlmSettingsFormDirty detects unsaved form edits", () => {
|
|
97
|
-
const saved = {
|
|
98
|
-
baseUrl: "https://api.openai.com/v1",
|
|
99
|
-
apiKey: "",
|
|
100
|
-
model: "gpt-4o-mini",
|
|
101
|
-
modelsText: "",
|
|
102
|
-
systemPrompt: "",
|
|
103
|
-
};
|
|
104
|
-
|
|
105
|
-
expect(isLlmSettingsFormDirty(saved, saved)).toBe(false);
|
|
106
|
-
expect(isLlmSettingsFormDirty({ ...saved, model: "gpt-4o" }, saved)).toBe(
|
|
107
|
-
true,
|
|
108
|
-
);
|
|
109
|
-
});
|
|
110
|
-
|
|
111
|
-
test("resolveSelectedModel keeps stored custom models", () => {
|
|
112
|
-
expect(
|
|
113
|
-
resolveSelectedModel("gpt-4o", "gpt-4o-mini", ["gpt-4o-mini", "gpt-4o"]),
|
|
114
|
-
).toBe("gpt-4o");
|
|
115
|
-
expect(
|
|
116
|
-
resolveSelectedModel("gpt-5.5", "gpt-4o-mini", ["gpt-4o-mini", "gpt-4o"]),
|
|
117
|
-
).toBe("gpt-5.5");
|
|
118
|
-
expect(
|
|
119
|
-
resolveSelectedModel("", "gpt-4o-mini", ["gpt-4o-mini", "gpt-4o"]),
|
|
120
|
-
).toBe("gpt-4o-mini");
|
|
121
|
-
});
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import { describe, expect, test } from "bun:test";
|
|
2
|
-
import { parseAssistantError } from "../src/react/lib/parse-assistant-error.ts";
|
|
3
|
-
|
|
4
|
-
describe("parseAssistantError", () => {
|
|
5
|
-
test("strips chat prefix and maps fetch failures to network", () => {
|
|
6
|
-
const parsed = parseAssistantError("Chat failed: Failed to fetch");
|
|
7
|
-
expect(parsed.title).toBe("Connection lost");
|
|
8
|
-
expect(parsed.detail).toBe("Failed to fetch");
|
|
9
|
-
expect(parsed.kind).toBe("network");
|
|
10
|
-
expect(parsed.hint).toContain("LLM endpoint");
|
|
11
|
-
});
|
|
12
|
-
|
|
13
|
-
test("maps auth errors", () => {
|
|
14
|
-
const parsed = parseAssistantError("401 Unauthorized");
|
|
15
|
-
expect(parsed.title).toBe("Authentication failed");
|
|
16
|
-
expect(parsed.kind).toBe("auth");
|
|
17
|
-
});
|
|
18
|
-
|
|
19
|
-
test("uses suggestions context copy", () => {
|
|
20
|
-
const parsed = parseAssistantError("Failed to fetch", "suggestions");
|
|
21
|
-
expect(parsed.title).toBe("Connection lost");
|
|
22
|
-
expect(parsed.hint).toContain("LLM settings");
|
|
23
|
-
});
|
|
24
|
-
});
|
package/tsconfig.json
DELETED
|
File without changes
|