@antelopejs/dms-ai 0.1.3 → 0.1.5
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 +48 -29
- package/dist/channels/bridge.d.ts +2 -8
- package/dist/channels/bridge.js +26 -42
- package/dist/channels/bridge.js.map +1 -1
- package/dist/channels/channel-service.d.ts +2 -2
- package/dist/channels/channel-service.js +12 -31
- package/dist/channels/channel-service.js.map +1 -1
- package/dist/channels/registry.d.ts +2 -2
- package/dist/channels/registry.js +7 -7
- package/dist/channels/registry.js.map +1 -1
- package/dist/config.d.ts +1 -0
- package/dist/config.js +8 -1
- package/dist/config.js.map +1 -1
- package/dist/constants/channels.d.ts +5 -10
- package/dist/constants/channels.js +6 -10
- package/dist/constants/channels.js.map +1 -1
- package/dist/constants/sidecar.d.ts +2 -1
- package/dist/constants/sidecar.js +3 -2
- package/dist/constants/sidecar.js.map +1 -1
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -1
- package/dist/lifecycle/build-id.d.ts +1 -0
- package/dist/lifecycle/build-id.js +32 -0
- package/dist/lifecycle/build-id.js.map +1 -0
- package/dist/lifecycle/sidecar-socket.d.ts +1 -1
- package/dist/lifecycle/sidecar-socket.js +2 -2
- package/dist/lifecycle/sidecar-socket.js.map +1 -1
- package/dist/lifecycle/spawn-sidecar.d.ts +0 -1
- package/dist/lifecycle/spawn-sidecar.js +5 -27
- package/dist/lifecycle/spawn-sidecar.js.map +1 -1
- package/dist/pages/settings/page.js.map +1 -1
- package/dist/routes/channels.d.ts +3 -3
- package/dist/routes/channels.js +11 -12
- package/dist/routes/channels.js.map +1 -1
- package/dist/routes/index.d.ts +0 -1
- package/dist/routes/index.js +0 -1
- package/dist/routes/index.js.map +1 -1
- package/frontend-vue/.prettierignore +3 -0
- package/frontend-vue/.prettierrc +10 -0
- package/frontend-vue/app/chat/components/ChatView.vue +582 -0
- package/frontend-vue/app/chat/components/ComposerInput.vue +742 -0
- package/frontend-vue/app/chat/components/ConnectionBanner.vue +105 -0
- package/frontend-vue/app/chat/components/ConversationDrawer.vue +266 -0
- package/frontend-vue/app/chat/components/MarkdownContent.vue +196 -0
- package/frontend-vue/app/chat/components/MessageList.vue +474 -0
- package/frontend-vue/app/chat/components/PermissionRequests.vue +323 -0
- package/frontend-vue/app/chat/components/QuestionPrompt.vue +275 -0
- package/frontend-vue/app/chat/components/QueuedMessages.vue +109 -0
- package/frontend-vue/app/chat/components/TodoList.vue +291 -0
- package/frontend-vue/app/chat/components/ToolCallEntry.vue +218 -0
- package/frontend-vue/app/chat/components/ToolCluster.vue +282 -0
- package/frontend-vue/app/chat/composables/useChatChannel.ts +116 -0
- package/frontend-vue/app/chat/composables/useConversation.ts +838 -0
- package/frontend-vue/app/chat/composables/useConversationId.ts +34 -0
- package/frontend-vue/app/chat/composables/useConversationList.ts +56 -0
- package/frontend-vue/app/chat/composables/usePermissionQueue.ts +59 -0
- package/frontend-vue/app/chat/composables/useQuestionQueue.ts +50 -0
- package/frontend-vue/app/chat/composables/useRunClock.ts +28 -0
- package/frontend-vue/app/chat/composables/useSettings.ts +67 -0
- package/frontend-vue/app/chat/constants/attachments.ts +16 -0
- package/frontend-vue/app/chat/constants/connection-banner.ts +7 -0
- package/frontend-vue/app/chat/constants/conversation-drawer.ts +13 -0
- package/frontend-vue/app/chat/constants/conversation.ts +75 -0
- package/frontend-vue/app/chat/constants/permissions.ts +50 -0
- package/frontend-vue/app/chat/constants/protocol.ts +48 -0
- package/frontend-vue/app/chat/constants/run-status.ts +50 -0
- package/frontend-vue/app/chat/constants/settings.ts +60 -0
- package/frontend-vue/app/chat/types/conversation.ts +87 -0
- package/frontend-vue/app/chat/types/permission.ts +7 -0
- package/frontend-vue/app/chat/types/question.ts +17 -0
- package/frontend-vue/app/chat/types/settings.ts +27 -0
- package/frontend-vue/app/chat/utils/attachments.ts +62 -0
- package/frontend-vue/app/chat/utils/format.ts +14 -0
- package/frontend-vue/app/chat/utils/ids.ts +34 -0
- package/frontend-vue/app/chat/utils/markdown.ts +188 -0
- package/frontend-vue/app/chat/utils/run-status.ts +90 -0
- package/frontend-vue/app/chat/utils/todos.ts +64 -0
- package/frontend-vue/app/chat/utils/tool-summary.ts +53 -0
- package/frontend-vue/app/components/ActivityView.vue +34 -34
- package/frontend-vue/app/components/ChatPanel.vue +276 -0
- package/frontend-vue/app/components/SettingsView.vue +127 -130
- package/frontend-vue/app/components/SkillsView.vue +55 -53
- package/frontend-vue/app/plugins/ai.client.ts +145 -129
- package/frontend-vue/app/runtime/assistant-session.ts +21 -0
- package/frontend-vue/app/runtime/backoff.ts +11 -14
- package/frontend-vue/app/runtime/channel-client.ts +130 -141
- package/frontend-vue/app/runtime/chat-transport.ts +25 -55
- package/frontend-vue/app/runtime/constants.ts +70 -60
- package/frontend-vue/app/runtime/current-page.ts +49 -15
- package/frontend-vue/app/runtime/event-stream.ts +35 -35
- package/frontend-vue/app/runtime/frame-router.ts +30 -0
- package/frontend-vue/app/runtime/header-action.ts +18 -18
- package/frontend-vue/app/runtime/host-commands.ts +57 -56
- package/frontend-vue/app/runtime/listeners.ts +31 -0
- package/frontend-vue/app/runtime/navigation-complete.ts +7 -7
- package/frontend-vue/app/runtime/overlay-prefs.ts +36 -36
- package/frontend-vue/app/runtime/panel-state.ts +88 -0
- package/frontend-vue/app/runtime/session-gate.ts +8 -8
- package/frontend-vue/app/runtime/shortcuts.ts +12 -12
- package/frontend-vue/app/runtime/sidecar-status.ts +61 -61
- package/frontend-vue/app/runtime/typed-message.ts +11 -0
- package/frontend-vue/dms.frontend.ts +12 -12
- package/frontend-vue/eslint.config.mjs +13 -13
- package/frontend-vue/package.json +11 -4
- package/frontend-vue/pnpm-lock.yaml +298 -96
- package/frontend-vue/tests/backoff.test.ts +26 -30
- package/frontend-vue/tests/channel-client.test.ts +187 -188
- package/frontend-vue/tests/chat/markdown.test.ts +271 -0
- package/frontend-vue/tests/chat/useChatChannel.test.ts +124 -0
- package/frontend-vue/tests/chat/useConversation.test.ts +283 -0
- package/frontend-vue/tests/chat-panel.test.ts +354 -0
- package/frontend-vue/tests/chat-transport.test.ts +84 -57
- package/frontend-vue/tests/host-commands.test.ts +126 -87
- package/frontend-vue/tests/navigation.test.ts +65 -34
- package/frontend-vue/tests/overlay-prefs.test.ts +49 -49
- package/frontend-vue/tests/panel-state.test.ts +58 -0
- package/frontend-vue/tests/session-gate.test.ts +33 -33
- package/frontend-vue/tests/sidecar-guest.test.ts +46 -46
- package/frontend-vue/tests/sidecar-status.test.ts +29 -29
- package/frontend-vue/tsconfig.chat.json +16 -0
- package/frontend-vue/vitest.config.ts +6 -4
- package/package.json +5 -5
- package/sidecar/dist/agent/effective-mode.d.ts +2 -2
- package/sidecar/dist/agent/effective-mode.js +1 -1
- package/sidecar/dist/agent/effective-mode.js.map +1 -1
- package/sidecar/dist/agent/host-context.js +7 -9
- package/sidecar/dist/agent/host-context.js.map +1 -1
- package/sidecar/dist/agent/permission-bus.d.ts +1 -1
- package/sidecar/dist/agent/permission-bus.js +2 -2
- package/sidecar/dist/agent/permission-bus.js.map +1 -1
- package/sidecar/dist/agent/provider.d.ts +2 -2
- package/sidecar/dist/agent/question-bus.d.ts +1 -1
- package/sidecar/dist/agent/question-bus.js +2 -2
- package/sidecar/dist/agent/question-bus.js.map +1 -1
- package/sidecar/dist/agent/runner.d.ts +2 -2
- package/sidecar/dist/agent/runner.js +24 -8
- package/sidecar/dist/agent/runner.js.map +1 -1
- package/sidecar/dist/agent/session.d.ts +2 -2
- package/sidecar/dist/agent/session.js +49 -9
- package/sidecar/dist/agent/session.js.map +1 -1
- package/sidecar/dist/agent/switching-runner.js +10 -5
- package/sidecar/dist/agent/switching-runner.js.map +1 -1
- package/sidecar/dist/agent/turn-end-reasons.d.ts +2 -0
- package/sidecar/dist/agent/turn-end-reasons.js +6 -1
- package/sidecar/dist/agent/turn-end-reasons.js.map +1 -1
- package/sidecar/dist/constants/agent.d.ts +4 -1
- package/sidecar/dist/constants/agent.js +4 -1
- package/sidecar/dist/constants/agent.js.map +1 -1
- package/sidecar/dist/constants/cli.d.ts +0 -1
- package/sidecar/dist/constants/cli.js +0 -1
- package/sidecar/dist/constants/cli.js.map +1 -1
- package/sidecar/dist/constants/codex.d.ts +5 -2
- package/sidecar/dist/constants/codex.js +5 -2
- package/sidecar/dist/constants/codex.js.map +1 -1
- package/sidecar/dist/constants/http.d.ts +0 -9
- package/sidecar/dist/constants/http.js +0 -19
- package/sidecar/dist/constants/http.js.map +1 -1
- package/sidecar/dist/constants/mcp.d.ts +1 -1
- package/sidecar/dist/constants/mcp.js +1 -1
- package/sidecar/dist/constants/mcp.js.map +1 -1
- package/sidecar/dist/constants/paths.d.ts +0 -1
- package/sidecar/dist/constants/paths.js +0 -1
- package/sidecar/dist/constants/paths.js.map +1 -1
- package/sidecar/dist/constants/ws.d.ts +3 -4
- package/sidecar/dist/constants/ws.js +3 -4
- package/sidecar/dist/constants/ws.js.map +1 -1
- package/sidecar/dist/index.d.ts +0 -1
- package/sidecar/dist/index.js +6 -10
- package/sidecar/dist/index.js.map +1 -1
- package/sidecar/dist/mcp/tools/find-pages-using.js +5 -10
- package/sidecar/dist/mcp/tools/find-pages-using.js.map +1 -1
- package/sidecar/dist/mcp/types.d.ts +1 -1
- package/sidecar/dist/pages/page-filepath.d.ts +4 -0
- package/sidecar/dist/pages/page-filepath.js +28 -0
- package/sidecar/dist/pages/page-filepath.js.map +1 -0
- package/sidecar/dist/prompts/agent.d.ts +1 -1
- package/sidecar/dist/prompts/agent.js +1 -1
- package/sidecar/dist/prompts/agent.js.map +1 -1
- package/sidecar/dist/protocol/events.js +2 -2
- package/sidecar/dist/protocol/events.js.map +1 -1
- package/sidecar/dist/protocol/messages.d.ts +4 -15
- package/sidecar/dist/protocol/messages.js +4 -11
- package/sidecar/dist/protocol/messages.js.map +1 -1
- package/sidecar/dist/providers/claude/config.d.ts +2 -2
- package/sidecar/dist/providers/claude/config.js +2 -2
- package/sidecar/dist/providers/claude/config.js.map +1 -1
- package/sidecar/dist/providers/claude/provider.js +1 -1
- package/sidecar/dist/providers/claude/provider.js.map +1 -1
- package/sidecar/dist/providers/codex/config.d.ts +3 -2
- package/sidecar/dist/providers/codex/config.js +3 -3
- package/sidecar/dist/providers/codex/config.js.map +1 -1
- package/sidecar/dist/providers/codex/process.js +107 -74
- package/sidecar/dist/providers/codex/process.js.map +1 -1
- package/sidecar/dist/providers/codex/provider.js +68 -31
- package/sidecar/dist/providers/codex/provider.js.map +1 -1
- package/sidecar/dist/providers/codex/skills.d.ts +1 -0
- package/sidecar/dist/providers/codex/skills.js +4 -1
- package/sidecar/dist/providers/codex/skills.js.map +1 -1
- package/sidecar/dist/providers/codex/stop.d.ts +4 -0
- package/sidecar/dist/providers/codex/stop.js +71 -0
- package/sidecar/dist/providers/codex/stop.js.map +1 -0
- package/sidecar/dist/server/{iframe-socket-registry.d.ts → chat-socket-registry.d.ts} +3 -2
- package/sidecar/dist/server/{iframe-socket-registry.js → chat-socket-registry.js} +4 -3
- package/sidecar/dist/server/chat-socket-registry.js.map +1 -0
- package/sidecar/dist/server/client-auth.js +2 -14
- package/sidecar/dist/server/client-auth.js.map +1 -1
- package/sidecar/dist/server/host-command-router.d.ts +5 -0
- package/sidecar/dist/server/host-command-router.js +4 -0
- package/sidecar/dist/server/host-command-router.js.map +1 -0
- package/sidecar/dist/server/host-socket-registry.d.ts +1 -1
- package/sidecar/dist/server/host-socket-registry.js +16 -13
- package/sidecar/dist/server/host-socket-registry.js.map +1 -1
- package/sidecar/dist/server/http.d.ts +0 -1
- package/sidecar/dist/server/http.js +1 -44
- package/sidecar/dist/server/http.js.map +1 -1
- package/sidecar/dist/server/routing.d.ts +5 -6
- package/sidecar/dist/server/routing.js +18 -28
- package/sidecar/dist/server/routing.js.map +1 -1
- package/sidecar/dist/server/ws.d.ts +2 -2
- package/sidecar/dist/server/ws.js +41 -39
- package/sidecar/dist/server/ws.js.map +1 -1
- package/sidecar/dist/state/host-state.d.ts +10 -2
- package/sidecar/dist/state/host-state.js +13 -3
- package/sidecar/dist/state/host-state.js.map +1 -1
- package/sidecar/dist/state/settings-store.js +2 -2
- package/sidecar/dist/state/settings-store.js.map +1 -1
- package/sidecar/dist/state/settings-types.d.ts +3 -3
- package/sidecar/dist/state/settings-types.js +1 -1
- package/sidecar/dist/state/settings-types.js.map +1 -1
- package/sidecar/package.json +3 -5
- package/dist/chatbox/passthrough.d.ts +0 -3
- package/dist/chatbox/passthrough.js +0 -53
- package/dist/chatbox/passthrough.js.map +0 -1
- package/dist/constants/chatbox.d.ts +0 -10
- package/dist/constants/chatbox.js +0 -35
- package/dist/constants/chatbox.js.map +0 -1
- package/dist/routes/chatbox.d.ts +0 -7
- package/dist/routes/chatbox.js +0 -47
- package/dist/routes/chatbox.js.map +0 -1
- package/frontend-vue/app/runtime/overlay.ts +0 -400
- package/frontend-vue/app/runtime/theme-bridge.ts +0 -189
- package/sidecar/chatbox/dist/assets/index-C8u7mkHn.css +0 -1
- package/sidecar/chatbox/dist/assets/index-tdZvY7ee.js +0 -52
- package/sidecar/chatbox/dist/index.html +0 -13
- package/sidecar/dist/server/iframe-socket-registry.js.map +0 -1
|
@@ -1,193 +1,191 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
import { computed, onMounted, ref } from
|
|
2
|
+
import { computed, onMounted, ref } from "vue";
|
|
3
3
|
|
|
4
|
-
type Mode =
|
|
5
|
-
type Thinking =
|
|
6
|
-
type GenerationMode =
|
|
7
|
-
type ProviderName =
|
|
4
|
+
type Mode = "normal" | "acceptEdits" | "plan" | "auto";
|
|
5
|
+
type Thinking = "off" | "low" | "medium" | "high";
|
|
6
|
+
type GenerationMode = "safe" | "vibe";
|
|
7
|
+
type ProviderName = "claude" | "codex";
|
|
8
8
|
|
|
9
9
|
interface ProviderAvailability {
|
|
10
|
-
available: boolean
|
|
11
|
-
reason?: string
|
|
10
|
+
available: boolean;
|
|
11
|
+
reason?: string;
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
interface AiSettings {
|
|
15
|
-
provider: ProviderName
|
|
16
|
-
mode: Mode
|
|
17
|
-
thinking: Thinking
|
|
18
|
-
generationMode: GenerationMode
|
|
19
|
-
allowLocalSkills: boolean
|
|
20
|
-
builderAvailable: boolean
|
|
21
|
-
providers: Record<ProviderName, ProviderAvailability
|
|
15
|
+
provider: ProviderName;
|
|
16
|
+
mode: Mode;
|
|
17
|
+
thinking: Thinking;
|
|
18
|
+
generationMode: GenerationMode;
|
|
19
|
+
allowLocalSkills: boolean;
|
|
20
|
+
builderAvailable: boolean;
|
|
21
|
+
providers: Record<ProviderName, ProviderAvailability>;
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
-
const { $authFetch } = useAuthFetch()
|
|
24
|
+
const { $authFetch } = useAuthFetch();
|
|
25
25
|
|
|
26
26
|
const settings = ref<AiSettings>({
|
|
27
|
-
provider:
|
|
28
|
-
mode:
|
|
29
|
-
thinking:
|
|
30
|
-
generationMode:
|
|
27
|
+
provider: "claude",
|
|
28
|
+
mode: "normal",
|
|
29
|
+
thinking: "medium",
|
|
30
|
+
generationMode: "safe",
|
|
31
31
|
allowLocalSkills: false,
|
|
32
32
|
builderAvailable: false,
|
|
33
33
|
providers: { claude: { available: true }, codex: { available: false } },
|
|
34
|
-
})
|
|
35
|
-
const loading = ref(false)
|
|
36
|
-
const saving = ref(false)
|
|
37
|
-
const error = ref<string | null>(null)
|
|
34
|
+
});
|
|
35
|
+
const loading = ref(false);
|
|
36
|
+
const saving = ref(false);
|
|
37
|
+
const error = ref<string | null>(null);
|
|
38
38
|
|
|
39
39
|
const MODE_OPTIONS: Array<{ value: Mode; label: string; hint: string }> = [
|
|
40
|
-
{ value:
|
|
40
|
+
{ value: "normal", label: "Normal", hint: "Ask before each tool action" },
|
|
41
41
|
{
|
|
42
|
-
value:
|
|
43
|
-
label:
|
|
44
|
-
hint:
|
|
42
|
+
value: "acceptEdits",
|
|
43
|
+
label: "Accept edits",
|
|
44
|
+
hint: "Auto-accept file edits, ask for the rest",
|
|
45
45
|
},
|
|
46
|
-
{ value:
|
|
47
|
-
{ value:
|
|
48
|
-
]
|
|
46
|
+
{ value: "plan", label: "Plan", hint: "Plan only — propose without changes" },
|
|
47
|
+
{ value: "auto", label: "Auto", hint: "Auto-approve every tool action" },
|
|
48
|
+
];
|
|
49
49
|
|
|
50
50
|
// Safe mode refuses raw edits whatever the mode, and Auto stops short of
|
|
51
51
|
// approving everything there, so the mode hint says so while it is active.
|
|
52
52
|
const SAFE_MODE_MODE_NOTE =
|
|
53
|
-
|
|
53
|
+
"Safe mode: raw edits and shell commands stay blocked, and Auto still asks before other actions.";
|
|
54
54
|
|
|
55
|
-
|
|
56
|
-
value: ProviderName
|
|
57
|
-
label: string
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
{ value:
|
|
62
|
-
|
|
55
|
+
interface ProviderOption {
|
|
56
|
+
value: ProviderName;
|
|
57
|
+
label: string;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const PROVIDER_OPTIONS: ProviderOption[] = [
|
|
61
|
+
{ value: "claude", label: "Anthropic (Claude)" },
|
|
62
|
+
{ value: "codex", label: "OpenAI (Codex)" },
|
|
63
|
+
];
|
|
63
64
|
|
|
64
65
|
// One control, two meanings: a token budget on Claude, a reasoning effort level
|
|
65
66
|
// on Codex, which has no "off" and maps it to its lowest level.
|
|
66
67
|
const THINKING_HINTS: Record<ProviderName, string> = {
|
|
67
|
-
claude:
|
|
68
|
+
claude: "Thinking budget handed to the model.",
|
|
68
69
|
codex:
|
|
69
70
|
'Reasoning effort handed to the model. Codex has no "off": it maps to the lowest level.',
|
|
70
|
-
}
|
|
71
|
+
};
|
|
71
72
|
|
|
72
73
|
const THINKING_OPTIONS: Array<{ value: Thinking; label: string }> = [
|
|
73
|
-
{ value:
|
|
74
|
-
{ value:
|
|
75
|
-
{ value:
|
|
76
|
-
{ value:
|
|
77
|
-
]
|
|
74
|
+
{ value: "off", label: "Off" },
|
|
75
|
+
{ value: "low", label: "Low" },
|
|
76
|
+
{ value: "medium", label: "Medium" },
|
|
77
|
+
{ value: "high", label: "High" },
|
|
78
|
+
];
|
|
78
79
|
|
|
79
80
|
async function load(): Promise<void> {
|
|
80
|
-
loading.value = true
|
|
81
|
-
error.value = null
|
|
81
|
+
loading.value = true;
|
|
82
|
+
error.value = null;
|
|
82
83
|
try {
|
|
83
|
-
settings.value = await $authFetch<AiSettings>(
|
|
84
|
+
settings.value = await $authFetch<AiSettings>("/ai/settings");
|
|
84
85
|
} catch (e) {
|
|
85
|
-
error.value = e instanceof Error ? e.message : String(e)
|
|
86
|
+
error.value = e instanceof Error ? e.message : String(e);
|
|
86
87
|
} finally {
|
|
87
|
-
loading.value = false
|
|
88
|
+
loading.value = false;
|
|
88
89
|
}
|
|
89
90
|
}
|
|
90
91
|
|
|
91
92
|
async function persist(): Promise<void> {
|
|
92
|
-
saving.value = true
|
|
93
|
-
error.value = null
|
|
93
|
+
saving.value = true;
|
|
94
|
+
error.value = null;
|
|
94
95
|
try {
|
|
95
|
-
settings.value = await $authFetch<AiSettings>(
|
|
96
|
-
method:
|
|
96
|
+
settings.value = await $authFetch<AiSettings>("/ai/settings", {
|
|
97
|
+
method: "PUT",
|
|
97
98
|
body: settings.value,
|
|
98
|
-
})
|
|
99
|
+
});
|
|
99
100
|
} catch (e) {
|
|
100
|
-
error.value = e instanceof Error ? e.message : String(e)
|
|
101
|
+
error.value = e instanceof Error ? e.message : String(e);
|
|
101
102
|
} finally {
|
|
102
|
-
saving.value = false
|
|
103
|
+
saving.value = false;
|
|
103
104
|
}
|
|
104
105
|
}
|
|
105
106
|
|
|
106
107
|
function availabilityOf(name: ProviderName): ProviderAvailability {
|
|
107
|
-
return settings.value.providers?.[name] ?? { available: false }
|
|
108
|
+
return settings.value.providers?.[name] ?? { available: false };
|
|
108
109
|
}
|
|
109
110
|
|
|
110
|
-
function providerLabel(option:
|
|
111
|
+
function providerLabel(option: ProviderOption): string {
|
|
111
112
|
return availabilityOf(option.value).available
|
|
112
113
|
? option.label
|
|
113
|
-
: `${option.label} — unavailable
|
|
114
|
+
: `${option.label} — unavailable`;
|
|
114
115
|
}
|
|
115
116
|
|
|
116
|
-
const activeProvider = computed(() => settings.value.provider)
|
|
117
|
+
const activeProvider = computed(() => settings.value.provider);
|
|
117
118
|
|
|
118
119
|
const providerReason = computed(
|
|
119
120
|
() => availabilityOf(settings.value.provider).reason ?? null,
|
|
120
|
-
)
|
|
121
|
-
|
|
122
|
-
const activeModel = computed(
|
|
123
|
-
() =>
|
|
124
|
-
PROVIDER_OPTIONS.find((o) => o.value === settings.value.provider)?.model ??
|
|
125
|
-
'',
|
|
126
|
-
)
|
|
121
|
+
);
|
|
127
122
|
|
|
128
123
|
function onProvider(event: Event): void {
|
|
129
|
-
const next = (event.target as HTMLSelectElement).value as ProviderName
|
|
124
|
+
const next = (event.target as HTMLSelectElement).value as ProviderName;
|
|
130
125
|
if (!availabilityOf(next).available) {
|
|
131
126
|
// The option is disabled, so this only fires on a stale DOM; snap back.
|
|
132
|
-
|
|
133
|
-
return
|
|
127
|
+
(event.target as HTMLSelectElement).value = settings.value.provider;
|
|
128
|
+
return;
|
|
134
129
|
}
|
|
135
|
-
settings.value.provider = next
|
|
136
|
-
void persist()
|
|
130
|
+
settings.value.provider = next;
|
|
131
|
+
void persist();
|
|
137
132
|
}
|
|
138
133
|
|
|
139
134
|
function onMode(event: Event): void {
|
|
140
|
-
settings.value.mode = (event.target as HTMLSelectElement).value as Mode
|
|
141
|
-
void persist()
|
|
135
|
+
settings.value.mode = (event.target as HTMLSelectElement).value as Mode;
|
|
136
|
+
void persist();
|
|
142
137
|
}
|
|
143
138
|
|
|
144
139
|
function onThinking(event: Event): void {
|
|
145
|
-
settings.value.thinking = (event.target as HTMLSelectElement)
|
|
146
|
-
|
|
140
|
+
settings.value.thinking = (event.target as HTMLSelectElement)
|
|
141
|
+
.value as Thinking;
|
|
142
|
+
void persist();
|
|
147
143
|
}
|
|
148
144
|
|
|
149
145
|
function onAllowLocalSkills(event: Event): void {
|
|
150
|
-
settings.value.allowLocalSkills = (event.target as HTMLInputElement).checked
|
|
151
|
-
void persist()
|
|
146
|
+
settings.value.allowLocalSkills = (event.target as HTMLInputElement).checked;
|
|
147
|
+
void persist();
|
|
152
148
|
}
|
|
153
149
|
|
|
154
150
|
const activeMode = computed<GenerationMode>(() =>
|
|
155
|
-
settings.value.generationMode ===
|
|
156
|
-
?
|
|
157
|
-
:
|
|
158
|
-
)
|
|
151
|
+
settings.value.generationMode === "safe" && settings.value.builderAvailable
|
|
152
|
+
? "safe"
|
|
153
|
+
: "vibe",
|
|
154
|
+
);
|
|
159
155
|
|
|
160
156
|
function onGenerationMode(mode: GenerationMode): void {
|
|
161
|
-
if (mode ===
|
|
162
|
-
if (mode === settings.value.generationMode) return
|
|
163
|
-
settings.value.generationMode = mode
|
|
164
|
-
void persist()
|
|
157
|
+
if (mode === "safe" && !settings.value.builderAvailable) return;
|
|
158
|
+
if (mode === settings.value.generationMode) return;
|
|
159
|
+
settings.value.generationMode = mode;
|
|
160
|
+
void persist();
|
|
165
161
|
}
|
|
166
162
|
|
|
167
|
-
onMounted(load)
|
|
163
|
+
onMounted(load);
|
|
168
164
|
|
|
169
165
|
const SELECT_CLASS =
|
|
170
|
-
|
|
166
|
+
"w-full rounded-md border border-default bg-elevated px-3 py-2 text-sm";
|
|
171
167
|
</script>
|
|
172
168
|
|
|
173
169
|
<template>
|
|
174
170
|
<div class="flex w-full flex-col gap-5 pb-10">
|
|
175
171
|
<div
|
|
176
172
|
v-if="error"
|
|
177
|
-
class="
|
|
173
|
+
class="border-error bg-error/10 text-error rounded-lg border p-4 text-sm"
|
|
178
174
|
>
|
|
179
175
|
{{ error }}
|
|
180
176
|
</div>
|
|
181
177
|
|
|
182
|
-
<!-- Row 1:
|
|
178
|
+
<!-- Row 1: Provider (left) · Default behavior (right) -->
|
|
183
179
|
<div class="grid gap-5 lg:grid-cols-2">
|
|
184
|
-
<section class="
|
|
185
|
-
<header class="border-
|
|
186
|
-
<h2 class="text-sm font-semibold
|
|
180
|
+
<section class="border-default bg-elevated/30 rounded-xl border">
|
|
181
|
+
<header class="border-default border-b px-5 py-4">
|
|
182
|
+
<h2 class="text-highlighted text-sm font-semibold">Provider</h2>
|
|
187
183
|
</header>
|
|
188
184
|
<div class="flex flex-col gap-4 p-5">
|
|
189
185
|
<div>
|
|
190
|
-
<label class="mb-1.5 block text-xs font-medium
|
|
186
|
+
<label class="text-toned mb-1.5 block text-xs font-medium">
|
|
187
|
+
Provider
|
|
188
|
+
</label>
|
|
191
189
|
<select
|
|
192
190
|
:class="SELECT_CLASS"
|
|
193
191
|
:value="activeProvider"
|
|
@@ -203,30 +201,27 @@ const SELECT_CLASS =
|
|
|
203
201
|
{{ providerLabel(option) }}
|
|
204
202
|
</option>
|
|
205
203
|
</select>
|
|
206
|
-
<p v-if="providerReason" class="mt-1.5 text-xs
|
|
204
|
+
<p v-if="providerReason" class="text-error mt-1.5 text-xs">
|
|
207
205
|
{{ providerReason }}
|
|
208
206
|
</p>
|
|
209
|
-
<p class="mt-1.5 text-xs
|
|
210
|
-
|
|
211
|
-
their transcripts are
|
|
207
|
+
<p class="text-dimmed mt-1.5 text-xs">
|
|
208
|
+
The provider runs its own default model. Switching provider ends
|
|
209
|
+
the live context of open conversations; their transcripts are
|
|
210
|
+
kept.
|
|
212
211
|
</p>
|
|
213
212
|
</div>
|
|
214
|
-
<div>
|
|
215
|
-
<label class="mb-1.5 block text-xs font-medium text-toned">Model</label>
|
|
216
|
-
<select :class="SELECT_CLASS" disabled>
|
|
217
|
-
<option>{{ activeModel }}</option>
|
|
218
|
-
</select>
|
|
219
|
-
</div>
|
|
220
213
|
</div>
|
|
221
214
|
</section>
|
|
222
215
|
|
|
223
|
-
<section class="
|
|
224
|
-
<header class="border-
|
|
225
|
-
<h2 class="text-sm font-semibold
|
|
216
|
+
<section class="border-default bg-elevated/30 rounded-xl border">
|
|
217
|
+
<header class="border-default border-b px-5 py-4">
|
|
218
|
+
<h2 class="text-highlighted text-sm font-semibold">
|
|
219
|
+
Default behavior
|
|
220
|
+
</h2>
|
|
226
221
|
</header>
|
|
227
222
|
<div class="flex flex-col gap-4 p-5">
|
|
228
223
|
<div>
|
|
229
|
-
<label class="mb-1.5 block text-xs font-medium
|
|
224
|
+
<label class="text-toned mb-1.5 block text-xs font-medium">
|
|
230
225
|
Operating mode
|
|
231
226
|
</label>
|
|
232
227
|
<select
|
|
@@ -243,15 +238,15 @@ const SELECT_CLASS =
|
|
|
243
238
|
{{ option.label }}
|
|
244
239
|
</option>
|
|
245
240
|
</select>
|
|
246
|
-
<p class="mt-1.5 text-xs
|
|
241
|
+
<p class="text-dimmed mt-1.5 text-xs">
|
|
247
242
|
{{ MODE_OPTIONS.find((o) => o.value === settings.mode)?.hint }}
|
|
248
243
|
</p>
|
|
249
|
-
<p v-if="activeMode === 'safe'" class="mt-1 text-xs
|
|
244
|
+
<p v-if="activeMode === 'safe'" class="text-dimmed mt-1 text-xs">
|
|
250
245
|
{{ SAFE_MODE_MODE_NOTE }}
|
|
251
246
|
</p>
|
|
252
247
|
</div>
|
|
253
248
|
<div>
|
|
254
|
-
<label class="mb-1.5 block text-xs font-medium
|
|
249
|
+
<label class="text-toned mb-1.5 block text-xs font-medium">
|
|
255
250
|
Thinking
|
|
256
251
|
</label>
|
|
257
252
|
<select
|
|
@@ -268,7 +263,7 @@ const SELECT_CLASS =
|
|
|
268
263
|
{{ option.label }}
|
|
269
264
|
</option>
|
|
270
265
|
</select>
|
|
271
|
-
<p class="mt-1.5 text-xs
|
|
266
|
+
<p class="text-dimmed mt-1.5 text-xs">
|
|
272
267
|
{{ THINKING_HINTS[settings.provider] }}
|
|
273
268
|
</p>
|
|
274
269
|
</div>
|
|
@@ -276,20 +271,20 @@ const SELECT_CLASS =
|
|
|
276
271
|
<label class="flex items-start gap-3">
|
|
277
272
|
<input
|
|
278
273
|
type="checkbox"
|
|
279
|
-
class="mt-0.5 size-4 rounded
|
|
274
|
+
class="border-default mt-0.5 size-4 rounded"
|
|
280
275
|
:checked="settings.allowLocalSkills"
|
|
281
276
|
:disabled="loading || saving"
|
|
282
277
|
@change="onAllowLocalSkills"
|
|
283
|
-
|
|
278
|
+
/>
|
|
284
279
|
<span>
|
|
285
|
-
<span class="block text-xs font-medium
|
|
280
|
+
<span class="text-toned block text-xs font-medium">
|
|
286
281
|
Use machine-local skills (~/.claude/skills)
|
|
287
282
|
</span>
|
|
288
|
-
<span class="mt-0.5 block text-xs
|
|
289
|
-
Adds the skills from your machine
|
|
290
|
-
|
|
291
|
-
modules. Machine-local, so not
|
|
292
|
-
Off by default.
|
|
283
|
+
<span class="text-dimmed mt-0.5 block text-xs">
|
|
284
|
+
Adds the skills from your machine (
|
|
285
|
+
<code>~/.claude/skills</code>
|
|
286
|
+
) on top of the ones bundled by modules. Machine-local, so not
|
|
287
|
+
shared with other environments. Off by default.
|
|
293
288
|
</span>
|
|
294
289
|
</span>
|
|
295
290
|
</label>
|
|
@@ -299,10 +294,12 @@ const SELECT_CLASS =
|
|
|
299
294
|
</div>
|
|
300
295
|
|
|
301
296
|
<!-- Row 2: Generation mode (full width) -->
|
|
302
|
-
<section class="
|
|
303
|
-
<header class="border-
|
|
304
|
-
<h2 class="text-sm font-semibold
|
|
305
|
-
<p class="mt-0.5 text-xs
|
|
297
|
+
<section class="border-default bg-elevated/30 rounded-xl border">
|
|
298
|
+
<header class="border-default border-b px-5 py-4">
|
|
299
|
+
<h2 class="text-highlighted text-sm font-semibold">Generation mode</h2>
|
|
300
|
+
<p class="text-dimmed mt-0.5 text-xs">
|
|
301
|
+
Default mode applied to new prompts
|
|
302
|
+
</p>
|
|
306
303
|
</header>
|
|
307
304
|
<div class="grid gap-4 p-5 sm:grid-cols-2">
|
|
308
305
|
<button
|
|
@@ -314,7 +311,7 @@ const SELECT_CLASS =
|
|
|
314
311
|
? 'border-primary bg-primary/10'
|
|
315
312
|
: 'border-default',
|
|
316
313
|
settings.builderAvailable
|
|
317
|
-
? '
|
|
314
|
+
? 'hover:border-primary/60 cursor-pointer'
|
|
318
315
|
: 'cursor-not-allowed opacity-60',
|
|
319
316
|
]"
|
|
320
317
|
@click="onGenerationMode('safe')"
|
|
@@ -344,7 +341,7 @@ const SELECT_CLASS =
|
|
|
344
341
|
Unavailable
|
|
345
342
|
</UBadge>
|
|
346
343
|
</div>
|
|
347
|
-
<p class="text-xs leading-relaxed
|
|
344
|
+
<p class="text-dimmed text-xs leading-relaxed">
|
|
348
345
|
Acts only through the Builder (MCP) — emits accepted configurations,
|
|
349
346
|
never raw code.
|
|
350
347
|
<template v-if="!settings.builderAvailable">
|
|
@@ -359,7 +356,7 @@ const SELECT_CLASS =
|
|
|
359
356
|
:class="
|
|
360
357
|
activeMode === 'vibe'
|
|
361
358
|
? 'border-primary bg-primary/10'
|
|
362
|
-
: '
|
|
359
|
+
: 'border-default hover:border-primary/60 cursor-pointer'
|
|
363
360
|
"
|
|
364
361
|
@click="onGenerationMode('vibe')"
|
|
365
362
|
>
|
|
@@ -379,7 +376,7 @@ const SELECT_CLASS =
|
|
|
379
376
|
Active
|
|
380
377
|
</UBadge>
|
|
381
378
|
</div>
|
|
382
|
-
<p class="text-xs leading-relaxed
|
|
379
|
+
<p class="text-dimmed text-xs leading-relaxed">
|
|
383
380
|
Free to write custom code and bespoke pages beyond the Builder
|
|
384
381
|
blocks — full creative range.
|
|
385
382
|
</p>
|
|
@@ -1,91 +1,91 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
import { computed, onMounted, ref } from
|
|
2
|
+
import { computed, onMounted, ref } from "vue";
|
|
3
3
|
|
|
4
4
|
interface SkillItem {
|
|
5
|
-
id: string
|
|
6
|
-
name: string
|
|
7
|
-
description: string
|
|
8
|
-
icon?: string
|
|
9
|
-
category?: string
|
|
10
|
-
tags: string[]
|
|
11
|
-
provenance: string
|
|
12
|
-
body: string
|
|
5
|
+
id: string;
|
|
6
|
+
name: string;
|
|
7
|
+
description: string;
|
|
8
|
+
icon?: string;
|
|
9
|
+
category?: string;
|
|
10
|
+
tags: string[];
|
|
11
|
+
provenance: string;
|
|
12
|
+
body: string;
|
|
13
13
|
}
|
|
14
14
|
|
|
15
|
-
const LOCAL_PROVENANCE =
|
|
15
|
+
const LOCAL_PROVENANCE = "local";
|
|
16
16
|
|
|
17
|
-
const { $authFetch } = useAuthFetch()
|
|
17
|
+
const { $authFetch } = useAuthFetch();
|
|
18
18
|
|
|
19
|
-
const items = ref<SkillItem[]>([])
|
|
20
|
-
const loading = ref(false)
|
|
21
|
-
const error = ref<string | null>(null)
|
|
22
|
-
const search = ref(
|
|
23
|
-
const selected = ref<SkillItem | null>(null)
|
|
19
|
+
const items = ref<SkillItem[]>([]);
|
|
20
|
+
const loading = ref(false);
|
|
21
|
+
const error = ref<string | null>(null);
|
|
22
|
+
const search = ref("");
|
|
23
|
+
const selected = ref<SkillItem | null>(null);
|
|
24
24
|
|
|
25
25
|
async function load(): Promise<void> {
|
|
26
|
-
loading.value = true
|
|
27
|
-
error.value = null
|
|
26
|
+
loading.value = true;
|
|
27
|
+
error.value = null;
|
|
28
28
|
try {
|
|
29
|
-
const res = await $authFetch<{ items: SkillItem[] }>(
|
|
30
|
-
items.value = res.items
|
|
29
|
+
const res = await $authFetch<{ items: SkillItem[] }>("/ai/skills");
|
|
30
|
+
items.value = res.items;
|
|
31
31
|
} catch (e) {
|
|
32
|
-
error.value = e instanceof Error ? e.message : String(e)
|
|
32
|
+
error.value = e instanceof Error ? e.message : String(e);
|
|
33
33
|
} finally {
|
|
34
|
-
loading.value = false
|
|
34
|
+
loading.value = false;
|
|
35
35
|
}
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
-
onMounted(load)
|
|
38
|
+
onMounted(load);
|
|
39
39
|
|
|
40
40
|
// Flat list, sorted by provenance then name so skills from the same package
|
|
41
41
|
// stay adjacent without a grouping layer.
|
|
42
42
|
const filtered = computed(() => {
|
|
43
|
-
const q = search.value.trim().toLowerCase()
|
|
43
|
+
const q = search.value.trim().toLowerCase();
|
|
44
44
|
return items.value
|
|
45
45
|
.filter((s) => {
|
|
46
|
-
if (q.length === 0) return true
|
|
47
|
-
const haystack = [s.name, s.description, s.category ??
|
|
48
|
-
.join(
|
|
49
|
-
.toLowerCase()
|
|
50
|
-
return haystack.includes(q)
|
|
46
|
+
if (q.length === 0) return true;
|
|
47
|
+
const haystack = [s.name, s.description, s.category ?? "", ...s.tags]
|
|
48
|
+
.join(" ")
|
|
49
|
+
.toLowerCase();
|
|
50
|
+
return haystack.includes(q);
|
|
51
51
|
})
|
|
52
52
|
.sort(
|
|
53
53
|
(a, b) =>
|
|
54
54
|
a.provenance.localeCompare(b.provenance) ||
|
|
55
55
|
a.name.localeCompare(b.name),
|
|
56
|
-
)
|
|
57
|
-
})
|
|
56
|
+
);
|
|
57
|
+
});
|
|
58
58
|
|
|
59
59
|
function isLocal(provenance: string): boolean {
|
|
60
|
-
return provenance === LOCAL_PROVENANCE
|
|
60
|
+
return provenance === LOCAL_PROVENANCE;
|
|
61
61
|
}
|
|
62
62
|
|
|
63
63
|
function open(skill: SkillItem): void {
|
|
64
|
-
selected.value = skill
|
|
64
|
+
selected.value = skill;
|
|
65
65
|
}
|
|
66
66
|
|
|
67
67
|
function close(): void {
|
|
68
|
-
selected.value = null
|
|
68
|
+
selected.value = null;
|
|
69
69
|
}
|
|
70
70
|
|
|
71
71
|
const CARD_CLASS =
|
|
72
|
-
|
|
72
|
+
"flex flex-col gap-2 rounded-xl border border-default bg-elevated/30 p-4 text-left transition-colors hover:border-primary";
|
|
73
73
|
</script>
|
|
74
74
|
|
|
75
75
|
<template>
|
|
76
76
|
<div class="flex w-full flex-col gap-5 pb-10">
|
|
77
77
|
<div
|
|
78
78
|
v-if="error"
|
|
79
|
-
class="
|
|
79
|
+
class="border-error bg-error/10 text-error rounded-lg border p-4 text-sm"
|
|
80
80
|
>
|
|
81
81
|
{{ error }}
|
|
82
82
|
</div>
|
|
83
83
|
|
|
84
84
|
<!-- Stat row -->
|
|
85
85
|
<div class="grid gap-4 sm:grid-cols-2">
|
|
86
|
-
<div class="
|
|
87
|
-
<p class="text-xs font-medium
|
|
88
|
-
<p class="mt-1 text-2xl font-semibold
|
|
86
|
+
<div class="border-default bg-elevated/30 rounded-xl border p-4">
|
|
87
|
+
<p class="text-toned text-xs font-medium">Total skills</p>
|
|
88
|
+
<p class="text-highlighted mt-1 text-2xl font-semibold">
|
|
89
89
|
{{ items.length }}
|
|
90
90
|
</p>
|
|
91
91
|
</div>
|
|
@@ -97,13 +97,13 @@ const CARD_CLASS =
|
|
|
97
97
|
v-model="search"
|
|
98
98
|
type="search"
|
|
99
99
|
placeholder="Search skills…"
|
|
100
|
-
class="w-full max-w-xs rounded-md border
|
|
101
|
-
|
|
100
|
+
class="border-default bg-elevated w-full max-w-xs rounded-md border px-3 py-2 text-sm"
|
|
101
|
+
/>
|
|
102
102
|
</div>
|
|
103
103
|
|
|
104
104
|
<p
|
|
105
105
|
v-if="!loading && items.length === 0"
|
|
106
|
-
class="
|
|
106
|
+
class="border-default bg-elevated/30 text-dimmed rounded-lg border p-6 text-center text-sm"
|
|
107
107
|
>
|
|
108
108
|
No skills are loaded. Module-contributed skills appear here, plus
|
|
109
109
|
machine-local skills when enabled in Settings.
|
|
@@ -121,13 +121,13 @@ const CARD_CLASS =
|
|
|
121
121
|
<div class="flex items-start gap-2">
|
|
122
122
|
<UIcon
|
|
123
123
|
:name="skill.icon || 'i-ph-sparkle'"
|
|
124
|
-
class="mt-0.5 shrink-0
|
|
124
|
+
class="text-primary mt-0.5 shrink-0"
|
|
125
125
|
/>
|
|
126
126
|
<div class="min-w-0">
|
|
127
|
-
<p class="truncate text-sm font-semibold
|
|
127
|
+
<p class="text-highlighted truncate text-sm font-semibold">
|
|
128
128
|
{{ skill.name }}
|
|
129
129
|
</p>
|
|
130
|
-
<p class="truncate text-xs
|
|
130
|
+
<p class="text-dimmed truncate text-xs">
|
|
131
131
|
{{ skill.provenance }}
|
|
132
132
|
</p>
|
|
133
133
|
</div>
|
|
@@ -141,7 +141,7 @@ const CARD_CLASS =
|
|
|
141
141
|
Local
|
|
142
142
|
</UBadge>
|
|
143
143
|
</div>
|
|
144
|
-
<p class="line-clamp-3 text-xs leading-relaxed
|
|
144
|
+
<p class="text-toned line-clamp-3 text-xs leading-relaxed">
|
|
145
145
|
{{ skill.description }}
|
|
146
146
|
</p>
|
|
147
147
|
<div v-if="skill.tags.length" class="mt-auto flex flex-wrap gap-1">
|
|
@@ -165,18 +165,18 @@ const CARD_CLASS =
|
|
|
165
165
|
@click.self="close"
|
|
166
166
|
>
|
|
167
167
|
<div
|
|
168
|
-
class="flex h-full w-full max-w-lg flex-col overflow-y-auto border-l
|
|
168
|
+
class="border-default bg-default flex h-full w-full max-w-lg flex-col overflow-y-auto border-l p-6 shadow-xl"
|
|
169
169
|
>
|
|
170
170
|
<div class="mb-4 flex items-start gap-3">
|
|
171
171
|
<UIcon
|
|
172
172
|
:name="selected.icon || 'i-ph-sparkle'"
|
|
173
|
-
class="mt-1 shrink-0 text-xl
|
|
173
|
+
class="text-primary mt-1 shrink-0 text-xl"
|
|
174
174
|
/>
|
|
175
175
|
<div class="min-w-0 flex-1">
|
|
176
|
-
<h2 class="text-lg font-semibold
|
|
176
|
+
<h2 class="text-highlighted text-lg font-semibold">
|
|
177
177
|
{{ selected.name }}
|
|
178
178
|
</h2>
|
|
179
|
-
<p class="text-
|
|
179
|
+
<p class="text-dimmed text-xs">{{ selected.id }}</p>
|
|
180
180
|
</div>
|
|
181
181
|
<UButton
|
|
182
182
|
icon="i-ph-x"
|
|
@@ -211,15 +211,17 @@ const CARD_CLASS =
|
|
|
211
211
|
</UBadge>
|
|
212
212
|
</div>
|
|
213
213
|
|
|
214
|
-
<p class="mb-4 text-sm leading-relaxed
|
|
214
|
+
<p class="text-toned mb-4 text-sm leading-relaxed">
|
|
215
215
|
{{ selected.description }}
|
|
216
216
|
</p>
|
|
217
217
|
|
|
218
|
-
<h3
|
|
218
|
+
<h3
|
|
219
|
+
class="text-dimmed mb-2 text-xs font-semibold uppercase tracking-wide"
|
|
220
|
+
>
|
|
219
221
|
Instructions (SKILL.md)
|
|
220
222
|
</h3>
|
|
221
223
|
<pre
|
|
222
|
-
class="whitespace-pre-wrap rounded-lg border
|
|
224
|
+
class="border-default bg-elevated/40 text-toned whitespace-pre-wrap rounded-lg border p-4 text-xs leading-relaxed"
|
|
223
225
|
>{{ selected.body }}</pre
|
|
224
226
|
>
|
|
225
227
|
</div>
|