@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.
Files changed (245) hide show
  1. package/README.md +48 -29
  2. package/dist/channels/bridge.d.ts +2 -8
  3. package/dist/channels/bridge.js +26 -42
  4. package/dist/channels/bridge.js.map +1 -1
  5. package/dist/channels/channel-service.d.ts +2 -2
  6. package/dist/channels/channel-service.js +12 -31
  7. package/dist/channels/channel-service.js.map +1 -1
  8. package/dist/channels/registry.d.ts +2 -2
  9. package/dist/channels/registry.js +7 -7
  10. package/dist/channels/registry.js.map +1 -1
  11. package/dist/config.d.ts +1 -0
  12. package/dist/config.js +8 -1
  13. package/dist/config.js.map +1 -1
  14. package/dist/constants/channels.d.ts +5 -10
  15. package/dist/constants/channels.js +6 -10
  16. package/dist/constants/channels.js.map +1 -1
  17. package/dist/constants/sidecar.d.ts +2 -1
  18. package/dist/constants/sidecar.js +3 -2
  19. package/dist/constants/sidecar.js.map +1 -1
  20. package/dist/index.js +8 -0
  21. package/dist/index.js.map +1 -1
  22. package/dist/lifecycle/build-id.d.ts +1 -0
  23. package/dist/lifecycle/build-id.js +32 -0
  24. package/dist/lifecycle/build-id.js.map +1 -0
  25. package/dist/lifecycle/sidecar-socket.d.ts +1 -1
  26. package/dist/lifecycle/sidecar-socket.js +2 -2
  27. package/dist/lifecycle/sidecar-socket.js.map +1 -1
  28. package/dist/lifecycle/spawn-sidecar.d.ts +0 -1
  29. package/dist/lifecycle/spawn-sidecar.js +5 -27
  30. package/dist/lifecycle/spawn-sidecar.js.map +1 -1
  31. package/dist/pages/settings/page.js.map +1 -1
  32. package/dist/routes/channels.d.ts +3 -3
  33. package/dist/routes/channels.js +11 -12
  34. package/dist/routes/channels.js.map +1 -1
  35. package/dist/routes/index.d.ts +0 -1
  36. package/dist/routes/index.js +0 -1
  37. package/dist/routes/index.js.map +1 -1
  38. package/frontend-vue/.prettierignore +3 -0
  39. package/frontend-vue/.prettierrc +10 -0
  40. package/frontend-vue/app/chat/components/ChatView.vue +582 -0
  41. package/frontend-vue/app/chat/components/ComposerInput.vue +742 -0
  42. package/frontend-vue/app/chat/components/ConnectionBanner.vue +105 -0
  43. package/frontend-vue/app/chat/components/ConversationDrawer.vue +266 -0
  44. package/frontend-vue/app/chat/components/MarkdownContent.vue +196 -0
  45. package/frontend-vue/app/chat/components/MessageList.vue +474 -0
  46. package/frontend-vue/app/chat/components/PermissionRequests.vue +323 -0
  47. package/frontend-vue/app/chat/components/QuestionPrompt.vue +275 -0
  48. package/frontend-vue/app/chat/components/QueuedMessages.vue +109 -0
  49. package/frontend-vue/app/chat/components/TodoList.vue +291 -0
  50. package/frontend-vue/app/chat/components/ToolCallEntry.vue +218 -0
  51. package/frontend-vue/app/chat/components/ToolCluster.vue +282 -0
  52. package/frontend-vue/app/chat/composables/useChatChannel.ts +116 -0
  53. package/frontend-vue/app/chat/composables/useConversation.ts +838 -0
  54. package/frontend-vue/app/chat/composables/useConversationId.ts +34 -0
  55. package/frontend-vue/app/chat/composables/useConversationList.ts +56 -0
  56. package/frontend-vue/app/chat/composables/usePermissionQueue.ts +59 -0
  57. package/frontend-vue/app/chat/composables/useQuestionQueue.ts +50 -0
  58. package/frontend-vue/app/chat/composables/useRunClock.ts +28 -0
  59. package/frontend-vue/app/chat/composables/useSettings.ts +67 -0
  60. package/frontend-vue/app/chat/constants/attachments.ts +16 -0
  61. package/frontend-vue/app/chat/constants/connection-banner.ts +7 -0
  62. package/frontend-vue/app/chat/constants/conversation-drawer.ts +13 -0
  63. package/frontend-vue/app/chat/constants/conversation.ts +75 -0
  64. package/frontend-vue/app/chat/constants/permissions.ts +50 -0
  65. package/frontend-vue/app/chat/constants/protocol.ts +48 -0
  66. package/frontend-vue/app/chat/constants/run-status.ts +50 -0
  67. package/frontend-vue/app/chat/constants/settings.ts +60 -0
  68. package/frontend-vue/app/chat/types/conversation.ts +87 -0
  69. package/frontend-vue/app/chat/types/permission.ts +7 -0
  70. package/frontend-vue/app/chat/types/question.ts +17 -0
  71. package/frontend-vue/app/chat/types/settings.ts +27 -0
  72. package/frontend-vue/app/chat/utils/attachments.ts +62 -0
  73. package/frontend-vue/app/chat/utils/format.ts +14 -0
  74. package/frontend-vue/app/chat/utils/ids.ts +34 -0
  75. package/frontend-vue/app/chat/utils/markdown.ts +188 -0
  76. package/frontend-vue/app/chat/utils/run-status.ts +90 -0
  77. package/frontend-vue/app/chat/utils/todos.ts +64 -0
  78. package/frontend-vue/app/chat/utils/tool-summary.ts +53 -0
  79. package/frontend-vue/app/components/ActivityView.vue +34 -34
  80. package/frontend-vue/app/components/ChatPanel.vue +276 -0
  81. package/frontend-vue/app/components/SettingsView.vue +127 -130
  82. package/frontend-vue/app/components/SkillsView.vue +55 -53
  83. package/frontend-vue/app/plugins/ai.client.ts +145 -129
  84. package/frontend-vue/app/runtime/assistant-session.ts +21 -0
  85. package/frontend-vue/app/runtime/backoff.ts +11 -14
  86. package/frontend-vue/app/runtime/channel-client.ts +130 -141
  87. package/frontend-vue/app/runtime/chat-transport.ts +25 -55
  88. package/frontend-vue/app/runtime/constants.ts +70 -60
  89. package/frontend-vue/app/runtime/current-page.ts +49 -15
  90. package/frontend-vue/app/runtime/event-stream.ts +35 -35
  91. package/frontend-vue/app/runtime/frame-router.ts +30 -0
  92. package/frontend-vue/app/runtime/header-action.ts +18 -18
  93. package/frontend-vue/app/runtime/host-commands.ts +57 -56
  94. package/frontend-vue/app/runtime/listeners.ts +31 -0
  95. package/frontend-vue/app/runtime/navigation-complete.ts +7 -7
  96. package/frontend-vue/app/runtime/overlay-prefs.ts +36 -36
  97. package/frontend-vue/app/runtime/panel-state.ts +88 -0
  98. package/frontend-vue/app/runtime/session-gate.ts +8 -8
  99. package/frontend-vue/app/runtime/shortcuts.ts +12 -12
  100. package/frontend-vue/app/runtime/sidecar-status.ts +61 -61
  101. package/frontend-vue/app/runtime/typed-message.ts +11 -0
  102. package/frontend-vue/dms.frontend.ts +12 -12
  103. package/frontend-vue/eslint.config.mjs +13 -13
  104. package/frontend-vue/package.json +11 -4
  105. package/frontend-vue/pnpm-lock.yaml +298 -96
  106. package/frontend-vue/tests/backoff.test.ts +26 -30
  107. package/frontend-vue/tests/channel-client.test.ts +187 -188
  108. package/frontend-vue/tests/chat/markdown.test.ts +271 -0
  109. package/frontend-vue/tests/chat/useChatChannel.test.ts +124 -0
  110. package/frontend-vue/tests/chat/useConversation.test.ts +283 -0
  111. package/frontend-vue/tests/chat-panel.test.ts +354 -0
  112. package/frontend-vue/tests/chat-transport.test.ts +84 -57
  113. package/frontend-vue/tests/host-commands.test.ts +126 -87
  114. package/frontend-vue/tests/navigation.test.ts +65 -34
  115. package/frontend-vue/tests/overlay-prefs.test.ts +49 -49
  116. package/frontend-vue/tests/panel-state.test.ts +58 -0
  117. package/frontend-vue/tests/session-gate.test.ts +33 -33
  118. package/frontend-vue/tests/sidecar-guest.test.ts +46 -46
  119. package/frontend-vue/tests/sidecar-status.test.ts +29 -29
  120. package/frontend-vue/tsconfig.chat.json +16 -0
  121. package/frontend-vue/vitest.config.ts +6 -4
  122. package/package.json +5 -5
  123. package/sidecar/dist/agent/effective-mode.d.ts +2 -2
  124. package/sidecar/dist/agent/effective-mode.js +1 -1
  125. package/sidecar/dist/agent/effective-mode.js.map +1 -1
  126. package/sidecar/dist/agent/host-context.js +7 -9
  127. package/sidecar/dist/agent/host-context.js.map +1 -1
  128. package/sidecar/dist/agent/permission-bus.d.ts +1 -1
  129. package/sidecar/dist/agent/permission-bus.js +2 -2
  130. package/sidecar/dist/agent/permission-bus.js.map +1 -1
  131. package/sidecar/dist/agent/provider.d.ts +2 -2
  132. package/sidecar/dist/agent/question-bus.d.ts +1 -1
  133. package/sidecar/dist/agent/question-bus.js +2 -2
  134. package/sidecar/dist/agent/question-bus.js.map +1 -1
  135. package/sidecar/dist/agent/runner.d.ts +2 -2
  136. package/sidecar/dist/agent/runner.js +24 -8
  137. package/sidecar/dist/agent/runner.js.map +1 -1
  138. package/sidecar/dist/agent/session.d.ts +2 -2
  139. package/sidecar/dist/agent/session.js +49 -9
  140. package/sidecar/dist/agent/session.js.map +1 -1
  141. package/sidecar/dist/agent/switching-runner.js +10 -5
  142. package/sidecar/dist/agent/switching-runner.js.map +1 -1
  143. package/sidecar/dist/agent/turn-end-reasons.d.ts +2 -0
  144. package/sidecar/dist/agent/turn-end-reasons.js +6 -1
  145. package/sidecar/dist/agent/turn-end-reasons.js.map +1 -1
  146. package/sidecar/dist/constants/agent.d.ts +4 -1
  147. package/sidecar/dist/constants/agent.js +4 -1
  148. package/sidecar/dist/constants/agent.js.map +1 -1
  149. package/sidecar/dist/constants/cli.d.ts +0 -1
  150. package/sidecar/dist/constants/cli.js +0 -1
  151. package/sidecar/dist/constants/cli.js.map +1 -1
  152. package/sidecar/dist/constants/codex.d.ts +5 -2
  153. package/sidecar/dist/constants/codex.js +5 -2
  154. package/sidecar/dist/constants/codex.js.map +1 -1
  155. package/sidecar/dist/constants/http.d.ts +0 -9
  156. package/sidecar/dist/constants/http.js +0 -19
  157. package/sidecar/dist/constants/http.js.map +1 -1
  158. package/sidecar/dist/constants/mcp.d.ts +1 -1
  159. package/sidecar/dist/constants/mcp.js +1 -1
  160. package/sidecar/dist/constants/mcp.js.map +1 -1
  161. package/sidecar/dist/constants/paths.d.ts +0 -1
  162. package/sidecar/dist/constants/paths.js +0 -1
  163. package/sidecar/dist/constants/paths.js.map +1 -1
  164. package/sidecar/dist/constants/ws.d.ts +3 -4
  165. package/sidecar/dist/constants/ws.js +3 -4
  166. package/sidecar/dist/constants/ws.js.map +1 -1
  167. package/sidecar/dist/index.d.ts +0 -1
  168. package/sidecar/dist/index.js +6 -10
  169. package/sidecar/dist/index.js.map +1 -1
  170. package/sidecar/dist/mcp/tools/find-pages-using.js +5 -10
  171. package/sidecar/dist/mcp/tools/find-pages-using.js.map +1 -1
  172. package/sidecar/dist/mcp/types.d.ts +1 -1
  173. package/sidecar/dist/pages/page-filepath.d.ts +4 -0
  174. package/sidecar/dist/pages/page-filepath.js +28 -0
  175. package/sidecar/dist/pages/page-filepath.js.map +1 -0
  176. package/sidecar/dist/prompts/agent.d.ts +1 -1
  177. package/sidecar/dist/prompts/agent.js +1 -1
  178. package/sidecar/dist/prompts/agent.js.map +1 -1
  179. package/sidecar/dist/protocol/events.js +2 -2
  180. package/sidecar/dist/protocol/events.js.map +1 -1
  181. package/sidecar/dist/protocol/messages.d.ts +4 -15
  182. package/sidecar/dist/protocol/messages.js +4 -11
  183. package/sidecar/dist/protocol/messages.js.map +1 -1
  184. package/sidecar/dist/providers/claude/config.d.ts +2 -2
  185. package/sidecar/dist/providers/claude/config.js +2 -2
  186. package/sidecar/dist/providers/claude/config.js.map +1 -1
  187. package/sidecar/dist/providers/claude/provider.js +1 -1
  188. package/sidecar/dist/providers/claude/provider.js.map +1 -1
  189. package/sidecar/dist/providers/codex/config.d.ts +3 -2
  190. package/sidecar/dist/providers/codex/config.js +3 -3
  191. package/sidecar/dist/providers/codex/config.js.map +1 -1
  192. package/sidecar/dist/providers/codex/process.js +107 -74
  193. package/sidecar/dist/providers/codex/process.js.map +1 -1
  194. package/sidecar/dist/providers/codex/provider.js +68 -31
  195. package/sidecar/dist/providers/codex/provider.js.map +1 -1
  196. package/sidecar/dist/providers/codex/skills.d.ts +1 -0
  197. package/sidecar/dist/providers/codex/skills.js +4 -1
  198. package/sidecar/dist/providers/codex/skills.js.map +1 -1
  199. package/sidecar/dist/providers/codex/stop.d.ts +4 -0
  200. package/sidecar/dist/providers/codex/stop.js +71 -0
  201. package/sidecar/dist/providers/codex/stop.js.map +1 -0
  202. package/sidecar/dist/server/{iframe-socket-registry.d.ts → chat-socket-registry.d.ts} +3 -2
  203. package/sidecar/dist/server/{iframe-socket-registry.js → chat-socket-registry.js} +4 -3
  204. package/sidecar/dist/server/chat-socket-registry.js.map +1 -0
  205. package/sidecar/dist/server/client-auth.js +2 -14
  206. package/sidecar/dist/server/client-auth.js.map +1 -1
  207. package/sidecar/dist/server/host-command-router.d.ts +5 -0
  208. package/sidecar/dist/server/host-command-router.js +4 -0
  209. package/sidecar/dist/server/host-command-router.js.map +1 -0
  210. package/sidecar/dist/server/host-socket-registry.d.ts +1 -1
  211. package/sidecar/dist/server/host-socket-registry.js +16 -13
  212. package/sidecar/dist/server/host-socket-registry.js.map +1 -1
  213. package/sidecar/dist/server/http.d.ts +0 -1
  214. package/sidecar/dist/server/http.js +1 -44
  215. package/sidecar/dist/server/http.js.map +1 -1
  216. package/sidecar/dist/server/routing.d.ts +5 -6
  217. package/sidecar/dist/server/routing.js +18 -28
  218. package/sidecar/dist/server/routing.js.map +1 -1
  219. package/sidecar/dist/server/ws.d.ts +2 -2
  220. package/sidecar/dist/server/ws.js +41 -39
  221. package/sidecar/dist/server/ws.js.map +1 -1
  222. package/sidecar/dist/state/host-state.d.ts +10 -2
  223. package/sidecar/dist/state/host-state.js +13 -3
  224. package/sidecar/dist/state/host-state.js.map +1 -1
  225. package/sidecar/dist/state/settings-store.js +2 -2
  226. package/sidecar/dist/state/settings-store.js.map +1 -1
  227. package/sidecar/dist/state/settings-types.d.ts +3 -3
  228. package/sidecar/dist/state/settings-types.js +1 -1
  229. package/sidecar/dist/state/settings-types.js.map +1 -1
  230. package/sidecar/package.json +3 -5
  231. package/dist/chatbox/passthrough.d.ts +0 -3
  232. package/dist/chatbox/passthrough.js +0 -53
  233. package/dist/chatbox/passthrough.js.map +0 -1
  234. package/dist/constants/chatbox.d.ts +0 -10
  235. package/dist/constants/chatbox.js +0 -35
  236. package/dist/constants/chatbox.js.map +0 -1
  237. package/dist/routes/chatbox.d.ts +0 -7
  238. package/dist/routes/chatbox.js +0 -47
  239. package/dist/routes/chatbox.js.map +0 -1
  240. package/frontend-vue/app/runtime/overlay.ts +0 -400
  241. package/frontend-vue/app/runtime/theme-bridge.ts +0 -189
  242. package/sidecar/chatbox/dist/assets/index-C8u7mkHn.css +0 -1
  243. package/sidecar/chatbox/dist/assets/index-tdZvY7ee.js +0 -52
  244. package/sidecar/chatbox/dist/index.html +0 -13
  245. 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 'vue'
2
+ import { computed, onMounted, ref } from "vue";
3
3
 
4
- type Mode = 'normal' | 'acceptEdits' | 'plan' | 'auto'
5
- type Thinking = 'off' | 'low' | 'medium' | 'high'
6
- type GenerationMode = 'safe' | 'vibe'
7
- type ProviderName = 'claude' | 'codex'
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: 'claude',
28
- mode: 'normal',
29
- thinking: 'medium',
30
- generationMode: 'safe',
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: 'normal', label: 'Normal', hint: 'Ask before each tool action' },
40
+ { value: "normal", label: "Normal", hint: "Ask before each tool action" },
41
41
  {
42
- value: 'acceptEdits',
43
- label: 'Accept edits',
44
- hint: 'Auto-accept file edits, ask for the rest',
42
+ value: "acceptEdits",
43
+ label: "Accept edits",
44
+ hint: "Auto-accept file edits, ask for the rest",
45
45
  },
46
- { value: 'plan', label: 'Plan', hint: 'Plan only — propose without changes' },
47
- { value: 'auto', label: 'Auto', hint: 'Auto-approve every tool action' },
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
- 'Safe mode: raw edits and shell commands stay blocked, and Auto still asks before other actions.'
53
+ "Safe mode: raw edits and shell commands stay blocked, and Auto still asks before other actions.";
54
54
 
55
- const PROVIDER_OPTIONS: Array<{
56
- value: ProviderName
57
- label: string
58
- model: string
59
- }> = [
60
- { value: 'claude', label: 'Anthropic (Claude)', model: 'Claude Opus 4.x' },
61
- { value: 'codex', label: 'OpenAI (Codex)', model: 'GPT-5.x (Codex default)' },
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: 'Thinking budget handed to the model.',
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: 'off', label: 'Off' },
74
- { value: 'low', label: 'Low' },
75
- { value: 'medium', label: 'Medium' },
76
- { value: 'high', label: 'High' },
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>('/ai/settings')
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>('/ai/settings', {
96
- method: 'PUT',
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: (typeof PROVIDER_OPTIONS)[number]): string {
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
- ;(event.target as HTMLSelectElement).value = settings.value.provider
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).value as Thinking
146
- void persist()
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 === 'safe' && settings.value.builderAvailable
156
- ? 'safe'
157
- : 'vibe',
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 === 'safe' && !settings.value.builderAvailable) return
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
- 'w-full rounded-md border border-default bg-elevated px-3 py-2 text-sm'
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="rounded-lg border border-error bg-error/10 p-4 text-sm text-error"
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: Model (left) · Default behavior (right) -->
178
+ <!-- Row 1: Provider (left) · Default behavior (right) -->
183
179
  <div class="grid gap-5 lg:grid-cols-2">
184
- <section class="rounded-xl border border-default bg-elevated/30">
185
- <header class="border-b border-default px-5 py-4">
186
- <h2 class="text-sm font-semibold text-highlighted">Model</h2>
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 text-toned">Provider</label>
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 text-error">
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 text-dimmed">
210
- Switching provider ends the live context of open conversations;
211
- their transcripts are kept.
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="rounded-xl border border-default bg-elevated/30">
224
- <header class="border-b border-default px-5 py-4">
225
- <h2 class="text-sm font-semibold text-highlighted">Default behavior</h2>
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 text-toned">
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 text-dimmed">
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 text-dimmed">
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 text-toned">
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 text-dimmed">
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 border-default"
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 text-toned">
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 text-dimmed">
289
- Adds the skills from your machine
290
- (<code>~/.claude/skills</code>) on top of the ones bundled by
291
- modules. Machine-local, so not shared with other environments.
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="rounded-xl border border-default bg-elevated/30">
303
- <header class="border-b border-default px-5 py-4">
304
- <h2 class="text-sm font-semibold text-highlighted">Generation mode</h2>
305
- <p class="mt-0.5 text-xs text-dimmed">Default mode applied to new prompts</p>
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
- ? 'cursor-pointer hover:border-primary/60'
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 text-dimmed">
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
- : 'cursor-pointer border-default hover:border-primary/60'
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 text-dimmed">
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 'vue'
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 = 'local'
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[] }>('/ai/skills')
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 ?? '', ...s.tags]
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
- 'flex flex-col gap-2 rounded-xl border border-default bg-elevated/30 p-4 text-left transition-colors hover:border-primary'
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="rounded-lg border border-error bg-error/10 p-4 text-sm text-error"
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="rounded-xl border border-default bg-elevated/30 p-4">
87
- <p class="text-xs font-medium text-toned">Total skills</p>
88
- <p class="mt-1 text-2xl font-semibold text-highlighted">
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 border-default bg-elevated px-3 py-2 text-sm"
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="rounded-lg border border-default bg-elevated/30 p-6 text-center text-sm text-dimmed"
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 text-primary"
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 text-highlighted">
127
+ <p class="text-highlighted truncate text-sm font-semibold">
128
128
  {{ skill.name }}
129
129
  </p>
130
- <p class="truncate text-xs text-dimmed">
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 text-toned">
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 border-default bg-default p-6 shadow-xl"
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 text-primary"
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 text-highlighted">
176
+ <h2 class="text-highlighted text-lg font-semibold">
177
177
  {{ selected.name }}
178
178
  </h2>
179
- <p class="text-xs text-dimmed">{{ selected.id }}</p>
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 text-toned">
214
+ <p class="text-toned mb-4 text-sm leading-relaxed">
215
215
  {{ selected.description }}
216
216
  </p>
217
217
 
218
- <h3 class="mb-2 text-xs font-semibold uppercase tracking-wide text-dimmed">
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 border-default bg-elevated/40 p-4 text-xs leading-relaxed text-toned"
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>