@chrysb/alphaclaw 0.8.1 → 0.8.3-beta.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.
Files changed (219) hide show
  1. package/README.md +33 -24
  2. package/bin/alphaclaw.js +13 -2
  3. package/lib/public/css/chat.css +426 -0
  4. package/lib/public/css/explorer.css +101 -0
  5. package/lib/public/css/tailwind.generated.css +1 -0
  6. package/lib/public/css/tailwind.input.css +3 -0
  7. package/lib/public/css/theme.css +28 -0
  8. package/lib/public/css/vendor/xterm.css +218 -0
  9. package/lib/public/dist/app.bundle.js +10706 -0
  10. package/lib/public/dist/chunks/addon-fit-W4YZGRNV.js +1 -0
  11. package/lib/public/dist/chunks/chunk-72ZECFVW.js +1 -0
  12. package/lib/public/dist/chunks/xterm-KOX4YMOF.js +9 -0
  13. package/lib/public/js/app.js +38 -4
  14. package/lib/public/js/components/action-button.js +8 -8
  15. package/lib/public/js/components/add-channel-menu.js +2 -2
  16. package/lib/public/js/components/agent-send-modal.js +6 -6
  17. package/lib/public/js/components/agents-tab/agent-bindings-section/channel-item-trailing.js +7 -7
  18. package/lib/public/js/components/agents-tab/agent-bindings-section/index.js +3 -3
  19. package/lib/public/js/components/agents-tab/agent-bindings-section/use-agent-bindings.js +1 -1
  20. package/lib/public/js/components/agents-tab/agent-bindings-section/use-channel-items.js +4 -4
  21. package/lib/public/js/components/agents-tab/agent-detail-panel.js +5 -5
  22. package/lib/public/js/components/agents-tab/agent-identity-section.js +18 -18
  23. package/lib/public/js/components/agents-tab/agent-overview/index.js +2 -2
  24. package/lib/public/js/components/agents-tab/agent-overview/manage-card.js +2 -2
  25. package/lib/public/js/components/agents-tab/agent-overview/model-card.js +8 -8
  26. package/lib/public/js/components/agents-tab/agent-overview/tools-card.js +5 -5
  27. package/lib/public/js/components/agents-tab/agent-overview/use-model-card.js +1 -1
  28. package/lib/public/js/components/agents-tab/agent-overview/use-workspace-card.js +1 -1
  29. package/lib/public/js/components/agents-tab/agent-overview/workspace-card.js +4 -4
  30. package/lib/public/js/components/agents-tab/agent-pairing-section.js +4 -4
  31. package/lib/public/js/components/agents-tab/agent-tools/index.js +5 -5
  32. package/lib/public/js/components/agents-tab/agent-tools/use-agent-tools.js +1 -1
  33. package/lib/public/js/components/agents-tab/create-agent-modal.js +13 -13
  34. package/lib/public/js/components/agents-tab/create-channel-modal.js +34 -34
  35. package/lib/public/js/components/agents-tab/delete-agent-dialog.js +3 -3
  36. package/lib/public/js/components/agents-tab/edit-agent-modal.js +9 -9
  37. package/lib/public/js/components/agents-tab/index.js +3 -3
  38. package/lib/public/js/components/agents-tab/use-agents.js +1 -1
  39. package/lib/public/js/components/badge.js +6 -6
  40. package/lib/public/js/components/channel-account-status-badge.js +2 -2
  41. package/lib/public/js/components/channel-operations-panel.js +2 -2
  42. package/lib/public/js/components/channels.js +9 -9
  43. package/lib/public/js/components/confirm-dialog.js +5 -5
  44. package/lib/public/js/components/credentials-modal.js +22 -22
  45. package/lib/public/js/components/cron-tab/cron-calendar.js +6 -6
  46. package/lib/public/js/components/cron-tab/cron-insights-panel.js +10 -10
  47. package/lib/public/js/components/cron-tab/cron-job-detail.js +4 -4
  48. package/lib/public/js/components/cron-tab/cron-job-list.js +4 -4
  49. package/lib/public/js/components/cron-tab/cron-job-settings-card.js +15 -15
  50. package/lib/public/js/components/cron-tab/cron-job-trends-panel.js +5 -5
  51. package/lib/public/js/components/cron-tab/cron-job-usage.js +16 -16
  52. package/lib/public/js/components/cron-tab/cron-overview.js +10 -10
  53. package/lib/public/js/components/cron-tab/cron-prompt-editor.js +3 -3
  54. package/lib/public/js/components/cron-tab/cron-run-history-panel.js +39 -39
  55. package/lib/public/js/components/cron-tab/cron-runs-trend-card.js +4 -4
  56. package/lib/public/js/components/cron-tab/index.js +5 -5
  57. package/lib/public/js/components/cron-tab/use-cron-tab.js +1 -1
  58. package/lib/public/js/components/device-pairings.js +12 -12
  59. package/lib/public/js/components/doctor/findings-list.js +22 -22
  60. package/lib/public/js/components/doctor/fix-card-modal.js +2 -2
  61. package/lib/public/js/components/doctor/general-warning.js +5 -5
  62. package/lib/public/js/components/doctor/index.js +26 -26
  63. package/lib/public/js/components/doctor/summary-cards.js +5 -5
  64. package/lib/public/js/components/envars.js +16 -16
  65. package/lib/public/js/components/features.js +4 -4
  66. package/lib/public/js/components/file-tree.js +4 -4
  67. package/lib/public/js/components/file-viewer/diff-viewer.js +2 -2
  68. package/lib/public/js/components/file-viewer/editor-surface.js +2 -2
  69. package/lib/public/js/components/file-viewer/frontmatter-panel.js +2 -2
  70. package/lib/public/js/components/file-viewer/index.js +3 -3
  71. package/lib/public/js/components/file-viewer/markdown-split-view.js +2 -2
  72. package/lib/public/js/components/file-viewer/media-preview.js +2 -2
  73. package/lib/public/js/components/file-viewer/scroll-sync.js +1 -1
  74. package/lib/public/js/components/file-viewer/sqlite-viewer.js +2 -2
  75. package/lib/public/js/components/file-viewer/status-banners.js +2 -2
  76. package/lib/public/js/components/file-viewer/toolbar.js +2 -2
  77. package/lib/public/js/components/file-viewer/use-editor-line-number-sync.js +1 -1
  78. package/lib/public/js/components/file-viewer/use-editor-selection-restore.js +1 -1
  79. package/lib/public/js/components/file-viewer/use-file-diff.js +1 -1
  80. package/lib/public/js/components/file-viewer/use-file-loader.js +1 -1
  81. package/lib/public/js/components/file-viewer/use-file-viewer-draft-sync.js +1 -1
  82. package/lib/public/js/components/file-viewer/use-file-viewer-hotkeys.js +1 -1
  83. package/lib/public/js/components/file-viewer/use-file-viewer.js +2 -2
  84. package/lib/public/js/components/gateway.js +12 -12
  85. package/lib/public/js/components/general/index.js +7 -7
  86. package/lib/public/js/components/general/use-general-tab.js +1 -1
  87. package/lib/public/js/components/global-restart-banner.js +2 -2
  88. package/lib/public/js/components/google/account-row.js +7 -7
  89. package/lib/public/js/components/google/add-account-modal.js +8 -8
  90. package/lib/public/js/components/google/gmail-setup-wizard.js +24 -24
  91. package/lib/public/js/components/google/gmail-watch-toggle.js +5 -5
  92. package/lib/public/js/components/google/index.js +6 -6
  93. package/lib/public/js/components/google/use-gmail-watch.js +1 -1
  94. package/lib/public/js/components/google/use-google-accounts.js +1 -1
  95. package/lib/public/js/components/icons.js +2 -2
  96. package/lib/public/js/components/info-tooltip.js +3 -3
  97. package/lib/public/js/components/loading-spinner.js +2 -2
  98. package/lib/public/js/components/modal-shell.js +5 -5
  99. package/lib/public/js/components/models-tab/index.js +11 -11
  100. package/lib/public/js/components/models-tab/model-picker.js +9 -9
  101. package/lib/public/js/components/models-tab/provider-auth-card.js +12 -12
  102. package/lib/public/js/components/models-tab/use-models.js +1 -1
  103. package/lib/public/js/components/models.js +18 -18
  104. package/lib/public/js/components/nodes-tab/browser-attach/index.js +5 -5
  105. package/lib/public/js/components/nodes-tab/connected-nodes/index.js +34 -32
  106. package/lib/public/js/components/nodes-tab/connected-nodes/use-connected-nodes-card.js +18 -3
  107. package/lib/public/js/components/nodes-tab/exec-allowlist/index.js +10 -10
  108. package/lib/public/js/components/nodes-tab/exec-allowlist/use-exec-allowlist.js +1 -1
  109. package/lib/public/js/components/nodes-tab/exec-config/index.js +13 -13
  110. package/lib/public/js/components/nodes-tab/exec-config/use-exec-config.js +1 -1
  111. package/lib/public/js/components/nodes-tab/index.js +2 -2
  112. package/lib/public/js/components/nodes-tab/setup-wizard/index.js +14 -14
  113. package/lib/public/js/components/nodes-tab/setup-wizard/use-setup-wizard.js +1 -1
  114. package/lib/public/js/components/nodes-tab/use-nodes-tab.js +1 -1
  115. package/lib/public/js/components/onboarding/use-welcome-codex.js +1 -1
  116. package/lib/public/js/components/onboarding/use-welcome-pairing.js +1 -1
  117. package/lib/public/js/components/onboarding/use-welcome-storage.js +1 -1
  118. package/lib/public/js/components/onboarding/welcome-config.js +3 -3
  119. package/lib/public/js/components/onboarding/welcome-form-step.js +34 -34
  120. package/lib/public/js/components/onboarding/welcome-header.js +2 -2
  121. package/lib/public/js/components/onboarding/welcome-import-step.js +22 -22
  122. package/lib/public/js/components/onboarding/welcome-pairing-step.js +15 -15
  123. package/lib/public/js/components/onboarding/welcome-placeholder-review-step.js +7 -7
  124. package/lib/public/js/components/onboarding/welcome-pre-step.js +9 -9
  125. package/lib/public/js/components/onboarding/welcome-secret-review-step.js +15 -15
  126. package/lib/public/js/components/onboarding/welcome-setup-step.js +8 -8
  127. package/lib/public/js/components/overflow-menu.js +3 -3
  128. package/lib/public/js/components/page-header.js +2 -2
  129. package/lib/public/js/components/pairings.js +14 -14
  130. package/lib/public/js/components/pane-shell.js +2 -2
  131. package/lib/public/js/components/pill-tabs.js +4 -4
  132. package/lib/public/js/components/pop-actions.js +3 -3
  133. package/lib/public/js/components/providers.js +17 -17
  134. package/lib/public/js/components/routes/agents-route.js +2 -2
  135. package/lib/public/js/components/routes/browse-route.js +2 -2
  136. package/lib/public/js/components/routes/chat-route.js +1094 -0
  137. package/lib/public/js/components/routes/cron-route.js +2 -2
  138. package/lib/public/js/components/routes/doctor-route.js +2 -2
  139. package/lib/public/js/components/routes/envars-route.js +2 -2
  140. package/lib/public/js/components/routes/general-route.js +2 -2
  141. package/lib/public/js/components/routes/index.js +1 -0
  142. package/lib/public/js/components/routes/models-route.js +2 -2
  143. package/lib/public/js/components/routes/nodes-route.js +2 -2
  144. package/lib/public/js/components/routes/providers-route.js +2 -2
  145. package/lib/public/js/components/routes/route-redirect.js +2 -2
  146. package/lib/public/js/components/routes/telegram-route.js +2 -2
  147. package/lib/public/js/components/routes/usage-route.js +2 -2
  148. package/lib/public/js/components/routes/watchdog-route.js +2 -2
  149. package/lib/public/js/components/routes/webhooks-route.js +2 -2
  150. package/lib/public/js/components/scope-picker.js +9 -9
  151. package/lib/public/js/components/secret-input.js +5 -5
  152. package/lib/public/js/components/segmented-control.js +2 -2
  153. package/lib/public/js/components/session-select-field.js +7 -7
  154. package/lib/public/js/components/sidebar-git-panel.js +3 -3
  155. package/lib/public/js/components/sidebar.js +55 -3
  156. package/lib/public/js/components/summary-stat-card.js +3 -3
  157. package/lib/public/js/components/telegram-workspace/index.js +10 -10
  158. package/lib/public/js/components/telegram-workspace/manage.js +36 -36
  159. package/lib/public/js/components/telegram-workspace/onboarding.js +73 -73
  160. package/lib/public/js/components/toast.js +8 -8
  161. package/lib/public/js/components/toggle-switch.js +2 -2
  162. package/lib/public/js/components/tooltip.js +5 -5
  163. package/lib/public/js/components/update-action-button.js +2 -2
  164. package/lib/public/js/components/update-modal.js +9 -9
  165. package/lib/public/js/components/usage-tab/constants.js +2 -2
  166. package/lib/public/js/components/usage-tab/index.js +3 -3
  167. package/lib/public/js/components/usage-tab/overview-section.js +15 -15
  168. package/lib/public/js/components/usage-tab/sessions-section.js +19 -19
  169. package/lib/public/js/components/usage-tab/use-usage-tab.js +2 -2
  170. package/lib/public/js/components/watchdog-tab/console/index.js +22 -8
  171. package/lib/public/js/components/watchdog-tab/console/use-console.js +28 -2
  172. package/lib/public/js/components/watchdog-tab/helpers.js +35 -6
  173. package/lib/public/js/components/watchdog-tab/incidents/index.js +6 -6
  174. package/lib/public/js/components/watchdog-tab/incidents/use-incidents.js +1 -1
  175. package/lib/public/js/components/watchdog-tab/index.js +4 -2
  176. package/lib/public/js/components/watchdog-tab/resource-bar.js +5 -5
  177. package/lib/public/js/components/watchdog-tab/resources/index.js +14 -3
  178. package/lib/public/js/components/watchdog-tab/resources/use-resources.js +1 -1
  179. package/lib/public/js/components/watchdog-tab/settings/index.js +97 -30
  180. package/lib/public/js/components/watchdog-tab/settings/use-settings.js +1 -1
  181. package/lib/public/js/components/watchdog-tab/terminal/index.js +3 -3
  182. package/lib/public/js/components/watchdog-tab/terminal/use-terminal.js +41 -5
  183. package/lib/public/js/components/watchdog-tab/use-watchdog-tab.js +2 -0
  184. package/lib/public/js/components/webhooks/create-webhook-modal/index.js +17 -17
  185. package/lib/public/js/components/webhooks/helpers.js +3 -3
  186. package/lib/public/js/components/webhooks/index.js +4 -4
  187. package/lib/public/js/components/webhooks/request-history/index.js +14 -14
  188. package/lib/public/js/components/webhooks/request-history/use-request-history.js +1 -1
  189. package/lib/public/js/components/webhooks/webhook-detail/index.js +41 -41
  190. package/lib/public/js/components/webhooks/webhook-detail/use-webhook-detail.js +1 -1
  191. package/lib/public/js/components/webhooks/webhook-list/index.js +11 -11
  192. package/lib/public/js/components/webhooks/webhook-list/use-webhook-list.js +1 -1
  193. package/lib/public/js/components/welcome/index.js +3 -3
  194. package/lib/public/js/components/welcome/use-welcome.js +10 -10
  195. package/lib/public/js/hooks/use-app-shell-controller.js +1 -1
  196. package/lib/public/js/hooks/use-app-shell-ui.js +1 -1
  197. package/lib/public/js/hooks/use-browse-navigation.js +14 -3
  198. package/lib/public/js/hooks/use-cached-fetch.js +1 -1
  199. package/lib/public/js/hooks/use-destination-session-selection.js +1 -1
  200. package/lib/public/js/hooks/use-hash-location.js +1 -1
  201. package/lib/public/js/hooks/useAgentSessions.js +1 -1
  202. package/lib/public/js/hooks/usePolling.js +1 -1
  203. package/lib/public/js/lib/app-navigation.js +1 -0
  204. package/lib/public/js/lib/storage-keys.js +3 -0
  205. package/lib/public/js/tailwind-config.js +39 -0
  206. package/lib/public/login.html +3 -18
  207. package/lib/public/setup.html +3 -18
  208. package/lib/server/auth-profiles.js +1 -1
  209. package/lib/server/chat-ws.js +835 -0
  210. package/lib/server/init/register-server-routes.js +2 -0
  211. package/lib/server/onboarding/validation.js +15 -10
  212. package/lib/server/routes/nodes.js +10 -2
  213. package/lib/server/routes/pairings.js +5 -1
  214. package/lib/server/routes/system.js +5 -0
  215. package/lib/server/routes/watchdog.js +15 -0
  216. package/lib/server/watchdog-terminal-ws.js +14 -1
  217. package/lib/server/watchdog.js +137 -51
  218. package/lib/server.js +38 -0
  219. package/package.json +14 -3
@@ -1,5 +1,5 @@
1
- import { h } from "https://esm.sh/preact";
2
- import htm from "https://esm.sh/htm";
1
+ import { h } from "preact";
2
+ import htm from "htm";
3
3
  import { ActionButton } from "../../action-button.js";
4
4
  import { useExecAllowlist } from "./use-exec-allowlist.js";
5
5
 
@@ -13,7 +13,7 @@ export const NodeExecAllowlistCard = () => {
13
13
  <div class="flex items-center justify-between gap-2">
14
14
  <div class="space-y-1">
15
15
  <h3 class="font-semibold text-sm">Gateway Exec Allowlist</h3>
16
- <p class="text-xs text-gray-500">
16
+ <p class="text-xs text-fg-muted">
17
17
  Patterns here are used when <code>tools.exec.security</code> is set to
18
18
  <code>allowlist</code>.
19
19
  </p>
@@ -27,7 +27,7 @@ export const NodeExecAllowlistCard = () => {
27
27
  />
28
28
  </div>
29
29
 
30
- ${state.error ? html`<div class="text-xs text-red-400">${state.error}</div>` : null}
30
+ ${state.error ? html`<div class="text-xs text-status-error-muted">${state.error}</div>` : null}
31
31
 
32
32
  <div class="flex items-center gap-2">
33
33
  <input
@@ -35,7 +35,7 @@ export const NodeExecAllowlistCard = () => {
35
35
  value=${state.patternInput}
36
36
  oninput=${(event) => state.setPatternInput(event.target.value)}
37
37
  placeholder="/usr/bin/sw_vers"
38
- class="flex-1 min-w-0 bg-black/30 border border-border rounded-lg px-2.5 py-2 text-xs font-mono focus:border-gray-500 focus:outline-none"
38
+ class="flex-1 min-w-0 bg-field border border-border rounded-lg px-2.5 py-2 text-xs font-mono focus:border-fg-muted focus:outline-none"
39
39
  disabled=${state.loading || state.saving}
40
40
  />
41
41
  <${ActionButton}
@@ -49,25 +49,25 @@ export const NodeExecAllowlistCard = () => {
49
49
  />
50
50
  </div>
51
51
 
52
- <div class="text-[11px] text-gray-500">
52
+ <div class="text-[11px] text-fg-muted">
53
53
  Supports wildcard patterns like <code>*</code>, <code>**</code>, and
54
54
  exact executable paths.
55
55
  </div>
56
56
 
57
57
  ${state.loading
58
- ? html`<div class="text-xs text-gray-500">Loading allowlist...</div>`
58
+ ? html`<div class="text-xs text-fg-muted">Loading allowlist...</div>`
59
59
  : !state.allowlist.length
60
- ? html`<div class="text-xs text-gray-500">No allowlist patterns configured.</div>`
60
+ ? html`<div class="text-xs text-fg-muted">No allowlist patterns configured.</div>`
61
61
  : html`
62
62
  <div class="space-y-2">
63
63
  ${state.allowlist.map(
64
64
  (entry) => html`
65
65
  <div class="ac-surface-inset rounded-lg px-3 py-2 flex items-center justify-between gap-2">
66
66
  <div class="min-w-0">
67
- <div class="text-xs font-mono text-gray-200 truncate">
67
+ <div class="text-xs font-mono text-body truncate">
68
68
  ${entry?.pattern || ""}
69
69
  </div>
70
- <div class="text-[11px] text-gray-500 font-mono truncate">
70
+ <div class="text-[11px] text-fg-muted font-mono truncate">
71
71
  ${entry?.id || ""}
72
72
  </div>
73
73
  </div>
@@ -1,4 +1,4 @@
1
- import { useCallback, useEffect, useState } from "https://esm.sh/preact/hooks";
1
+ import { useCallback, useEffect, useState } from "preact/hooks";
2
2
  import {
3
3
  addNodeExecAllowlistPattern,
4
4
  fetchNodeExecApprovals,
@@ -1,5 +1,5 @@
1
- import { h } from "https://esm.sh/preact";
2
- import htm from "https://esm.sh/htm";
1
+ import { h } from "preact";
2
+ import htm from "htm";
3
3
  import { ActionButton } from "../../action-button.js";
4
4
  import { useExecConfig } from "./use-exec-config.js";
5
5
 
@@ -23,7 +23,7 @@ export const NodeExecConfigCard = ({
23
23
  <div class="flex items-center justify-between gap-2">
24
24
  <div class="space-y-1">
25
25
  <h3 class="font-semibold text-sm">Exec Routing</h3>
26
- <p class="text-xs text-gray-500">
26
+ <p class="text-xs text-fg-muted">
27
27
  Set where command execution runs and how strict approval policy should be.
28
28
  </p>
29
29
  </div>
@@ -36,16 +36,16 @@ export const NodeExecConfigCard = ({
36
36
  />
37
37
  </div>
38
38
 
39
- ${state.error ? html`<div class="text-xs text-red-400">${state.error}</div>` : null}
39
+ ${state.error ? html`<div class="text-xs text-status-error-muted">${state.error}</div>` : null}
40
40
 
41
41
  <div class="grid grid-cols-1 md:grid-cols-2 gap-3">
42
42
  <label class="space-y-1">
43
- <div class="text-xs text-gray-500">Host</div>
43
+ <div class="text-xs text-fg-muted">Host</div>
44
44
  <select
45
45
  value=${state.config.host}
46
46
  disabled=${state.loading || state.saving}
47
47
  oninput=${(event) => state.updateField("host", event.target.value)}
48
- class="w-full bg-black/30 border border-border rounded-lg px-2.5 py-2 text-xs font-mono focus:border-gray-500 focus:outline-none disabled:opacity-50 disabled:cursor-not-allowed"
48
+ class="w-full bg-field border border-border rounded-lg px-2.5 py-2 text-xs font-mono focus:border-fg-muted focus:outline-none disabled:opacity-50 disabled:cursor-not-allowed"
49
49
  >
50
50
  <option value="gateway">gateway</option>
51
51
  <option value="node">node</option>
@@ -53,12 +53,12 @@ export const NodeExecConfigCard = ({
53
53
  </label>
54
54
 
55
55
  <label class="space-y-1">
56
- <div class="text-xs text-gray-500">Security</div>
56
+ <div class="text-xs text-fg-muted">Security</div>
57
57
  <select
58
58
  value=${state.config.security}
59
59
  disabled=${state.loading || state.saving}
60
60
  oninput=${(event) => state.updateField("security", event.target.value)}
61
- class="w-full bg-black/30 border border-border rounded-lg px-2.5 py-2 text-xs font-mono focus:border-gray-500 focus:outline-none disabled:opacity-50 disabled:cursor-not-allowed"
61
+ class="w-full bg-field border border-border rounded-lg px-2.5 py-2 text-xs font-mono focus:border-fg-muted focus:outline-none disabled:opacity-50 disabled:cursor-not-allowed"
62
62
  >
63
63
  <option value="deny">deny</option>
64
64
  <option value="allowlist">allowlist</option>
@@ -67,12 +67,12 @@ export const NodeExecConfigCard = ({
67
67
  </label>
68
68
 
69
69
  <label class="space-y-1">
70
- <div class="text-xs text-gray-500">Ask</div>
70
+ <div class="text-xs text-fg-muted">Ask</div>
71
71
  <select
72
72
  value=${state.config.ask}
73
73
  disabled=${state.loading || state.saving}
74
74
  oninput=${(event) => state.updateField("ask", event.target.value)}
75
- class="w-full bg-black/30 border border-border rounded-lg px-2.5 py-2 text-xs font-mono focus:border-gray-500 focus:outline-none disabled:opacity-50 disabled:cursor-not-allowed"
75
+ class="w-full bg-field border border-border rounded-lg px-2.5 py-2 text-xs font-mono focus:border-fg-muted focus:outline-none disabled:opacity-50 disabled:cursor-not-allowed"
76
76
  >
77
77
  <option value="off">off</option>
78
78
  <option value="on-miss">on-miss</option>
@@ -81,12 +81,12 @@ export const NodeExecConfigCard = ({
81
81
  </label>
82
82
 
83
83
  <label class="space-y-1">
84
- <div class="text-xs text-gray-500">Node target</div>
84
+ <div class="text-xs text-fg-muted">Node target</div>
85
85
  <select
86
86
  value=${state.config.node}
87
87
  disabled=${state.loading || state.saving || state.config.host !== "node"}
88
88
  oninput=${(event) => state.updateField("node", event.target.value)}
89
- class="w-full bg-black/30 border border-border rounded-lg px-2.5 py-2 text-xs font-mono focus:border-gray-500 focus:outline-none disabled:opacity-50 disabled:cursor-not-allowed"
89
+ class="w-full bg-field border border-border rounded-lg px-2.5 py-2 text-xs font-mono focus:border-fg-muted focus:outline-none disabled:opacity-50 disabled:cursor-not-allowed"
90
90
  >
91
91
  <option value="">${availableNodeOptions.length ? "Select node..." : "No nodes available"}</option>
92
92
  ${availableNodeOptions.map(
@@ -98,7 +98,7 @@ export const NodeExecConfigCard = ({
98
98
  </label>
99
99
  </div>
100
100
 
101
- <div class="rounded-lg border border-yellow-500/40 bg-yellow-500/10 px-3 py-2 text-xs text-yellow-300">
101
+ <div class="rounded-lg border border-yellow-500/40 bg-yellow-500/10 px-3 py-2 text-xs text-status-warning">
102
102
  Save applies config immediately, but gateway restart may still be required by OpenClaw.
103
103
  </div>
104
104
 
@@ -1,4 +1,4 @@
1
- import { useCallback, useEffect, useState } from "https://esm.sh/preact/hooks";
1
+ import { useCallback, useEffect, useState } from "preact/hooks";
2
2
  import { fetchNodeExecConfig, saveNodeExecConfig } from "../../../lib/api.js";
3
3
  import { showToast } from "../../toast.js";
4
4
 
@@ -1,5 +1,5 @@
1
- import { h } from "https://esm.sh/preact";
2
- import htm from "https://esm.sh/htm";
1
+ import { h } from "preact";
2
+ import htm from "htm";
3
3
  import { PageHeader } from "../page-header.js";
4
4
  import { ActionButton } from "../action-button.js";
5
5
  import { useNodesTab } from "./use-nodes-tab.js";
@@ -1,5 +1,5 @@
1
- import { h } from "https://esm.sh/preact";
2
- import htm from "https://esm.sh/htm";
1
+ import { h } from "preact";
2
+ import htm from "htm";
3
3
  import { ModalShell } from "../../modal-shell.js";
4
4
  import { ActionButton } from "../../action-button.js";
5
5
  import { CloseIcon, FileCopyLineIcon } from "../../icons.js";
@@ -13,9 +13,9 @@ const html = htm.bind(h);
13
13
  const kWizardSteps = ["Install OpenClaw CLI", "Connect Node"];
14
14
 
15
15
  const renderCommandBlock = ({ command = "", onCopy = () => {} }) => html`
16
- <div class="rounded-lg border border-border bg-black/30 p-3">
16
+ <div class="rounded-lg border border-border bg-field p-3">
17
17
  <pre
18
- class="pt-1 pl-2 text-[11px] leading-5 whitespace-pre-wrap break-all font-mono text-gray-300"
18
+ class="pt-1 pl-2 text-[11px] leading-5 whitespace-pre-wrap break-all font-mono text-body"
19
19
  >
20
20
  ${command}</pre
21
21
  >
@@ -71,10 +71,10 @@ export const NodesSetupWizard = ({
71
71
  class="absolute top-6 right-6 h-8 w-8 inline-flex items-center justify-center rounded-lg ac-btn-secondary"
72
72
  aria-label="Close modal"
73
73
  >
74
- <${CloseIcon} className="w-3.5 h-3.5 text-gray-300" />
74
+ <${CloseIcon} className="w-3.5 h-3.5 text-body" />
75
75
  </button>
76
76
 
77
- <div class="text-xs text-gray-500">Node Setup Wizard</div>
77
+ <div class="text-xs text-fg-muted">Node Setup Wizard</div>
78
78
  <div class="flex items-center gap-1">
79
79
  ${kWizardSteps.map(
80
80
  (_label, idx) => html`
@@ -92,7 +92,7 @@ export const NodesSetupWizard = ({
92
92
  ${
93
93
  state.step === 0
94
94
  ? html`
95
- <div class="text-xs text-gray-500">
95
+ <div class="text-xs text-fg-muted">
96
96
  Install OpenClaw on the machine you want to connect as a node.
97
97
  </div>
98
98
  ${renderCommandBlock({
@@ -100,7 +100,7 @@ export const NodesSetupWizard = ({
100
100
  onCopy: () =>
101
101
  copyAndToast("npm install -g openclaw", "command"),
102
102
  })}
103
- <div class="text-xs text-gray-500">Requires Node.js 22+.</div>
103
+ <div class="text-xs text-fg-muted">Requires Node.js 22+.</div>
104
104
  `
105
105
  : null
106
106
  }
@@ -110,22 +110,22 @@ export const NodesSetupWizard = ({
110
110
  ? html`
111
111
  <div class="space-y-2">
112
112
  <label class="space-y-1 block">
113
- <div class="text-xs text-gray-500">Display name</div>
113
+ <div class="text-xs text-fg-muted">Display name</div>
114
114
  <input
115
115
  type="text"
116
116
  value=${state.displayName}
117
117
  oninput=${(event) =>
118
118
  state.setDisplayName(event.target.value)}
119
- class="w-full bg-black/30 border border-border rounded-lg px-2.5 py-2 text-xs font-mono focus:border-gray-500 focus:outline-none"
119
+ class="w-full bg-field border border-border rounded-lg px-2.5 py-2 text-xs font-mono focus:border-fg-muted focus:outline-none"
120
120
  />
121
121
  </label>
122
122
 
123
123
  <div>
124
- <div class="text-xs text-gray-500 mb-1">
124
+ <div class="text-xs text-fg-muted mb-1">
125
125
  Run this on the device you want to connect:
126
126
  </div>
127
127
  ${state.loadingConnectInfo
128
- ? html`<div class="text-xs text-gray-500">
128
+ ? html`<div class="text-xs text-fg-muted">
129
129
  Loading command...
130
130
  </div>`
131
131
  : renderCommandBlock({
@@ -148,7 +148,7 @@ export const NodesSetupWizard = ({
148
148
  !state.selectedPairedNode.connected
149
149
  ? html`
150
150
  <div
151
- class="rounded-lg border border-yellow-500/40 bg-yellow-500/10 px-3 py-2 text-xs text-yellow-200"
151
+ class="rounded-lg border border-yellow-500/40 bg-yellow-500/10 px-3 py-2 text-xs text-status-warning"
152
152
  >
153
153
  Node is paired but currently disconnected. Run the
154
154
  node command again on your device, then Finish will
@@ -157,7 +157,7 @@ export const NodesSetupWizard = ({
157
157
  `
158
158
  : html`
159
159
  <div
160
- class="rounded-lg border border-border bg-black/20 px-3 py-2 text-xs text-gray-400"
160
+ class="rounded-lg border border-border bg-field px-3 py-2 text-xs text-fg-muted"
161
161
  >
162
162
  Pairing request will show up here. Checks every 3s.
163
163
  </div>
@@ -4,7 +4,7 @@ import {
4
4
  useMemo,
5
5
  useRef,
6
6
  useState,
7
- } from "https://esm.sh/preact/hooks";
7
+ } from "preact/hooks";
8
8
  import {
9
9
  approveDevice,
10
10
  fetchDevicePairings,
@@ -1,4 +1,4 @@
1
- import { useCallback, useEffect, useState } from "https://esm.sh/preact/hooks";
1
+ import { useCallback, useEffect, useState } from "preact/hooks";
2
2
  import { fetchNodeConnectInfo } from "../../lib/api.js";
3
3
  import { useCachedFetch } from "../../hooks/use-cached-fetch.js";
4
4
  import { showToast } from "../toast.js";
@@ -1,4 +1,4 @@
1
- import { useEffect, useRef, useState } from "https://esm.sh/preact/hooks";
1
+ import { useEffect, useRef, useState } from "preact/hooks";
2
2
  import {
3
3
  disconnectCodex,
4
4
  exchangeCodexOAuth,
@@ -1,4 +1,4 @@
1
- import { useEffect, useState } from "https://esm.sh/preact/hooks";
1
+ import { useEffect, useState } from "preact/hooks";
2
2
  import { approvePairing, fetchPairings, fetchStatus, rejectPairing } from "../../lib/api.js";
3
3
  import { usePolling } from "../../hooks/usePolling.js";
4
4
  import { isChannelPaired } from "./pairing-utils.js";
@@ -1,4 +1,4 @@
1
- import { useEffect, useState } from "https://esm.sh/preact/hooks";
1
+ import { useEffect, useState } from "preact/hooks";
2
2
 
3
3
  import { kOnboardingStorageKey } from "../../lib/storage-keys.js";
4
4
  export { kOnboardingStorageKey };
@@ -1,5 +1,5 @@
1
- import { h } from "https://esm.sh/preact";
2
- import htm from "https://esm.sh/htm";
1
+ import { h } from "preact";
2
+ import htm from "htm";
3
3
  import { kAllAiAuthFields } from "../../lib/model-config.js";
4
4
 
5
5
  const html = htm.bind(h);
@@ -52,7 +52,7 @@ export const kWelcomeGroups = [
52
52
  class="hover:underline"
53
53
  style="color: var(--accent-link)"
54
54
  >classic PAT</a
55
- >${" "}with${" "}<code class="text-xs bg-black/30 px-1 rounded"
55
+ >${" "}with${" "}<code class="text-xs bg-field px-1 rounded"
56
56
  >repo</code
57
57
  >${" "}scope, or a${" "}<a
58
58
  href="https://github.com/settings/personal-access-tokens/new"
@@ -1,6 +1,6 @@
1
- import { h } from "https://esm.sh/preact";
2
- import { useEffect, useState } from "https://esm.sh/preact/hooks";
3
- import htm from "https://esm.sh/htm";
1
+ import { h } from "preact";
2
+ import { useEffect, useState } from "preact/hooks";
3
+ import htm from "htm";
4
4
  import { SecretInput } from "../secret-input.js";
5
5
  import { ActionButton } from "../action-button.js";
6
6
  import { Badge } from "../badge.js";
@@ -92,7 +92,7 @@ export const WelcomeFormStep = ({
92
92
 
93
93
  const renderStandardField = (field) => html`
94
94
  <div class="space-y-1" key=${field.key}>
95
- <label class="text-xs font-medium text-gray-400">${field.label}</label>
95
+ <label class="text-xs font-medium text-fg-muted">${field.label}</label>
96
96
  <${SecretInput}
97
97
  key=${field.key}
98
98
  value=${vals[field.key] || ""}
@@ -101,9 +101,9 @@ export const WelcomeFormStep = ({
101
101
  ? githubTokenPlaceholder
102
102
  : field.placeholder || ""}
103
103
  isSecret=${!field.isText}
104
- inputClass="flex-1 bg-black/30 border border-border rounded-lg px-3 py-2 text-sm text-gray-200 outline-none focus:border-gray-500 font-mono"
104
+ inputClass="flex-1 bg-field border border-border rounded-lg px-3 py-2 text-sm text-body outline-none focus:border-fg-muted font-mono"
105
105
  />
106
- <p class="text-xs text-gray-600">
106
+ <p class="text-xs text-fg-dim">
107
107
  ${activeGroup.id === "github" &&
108
108
  field.key === "GITHUB_WORKSPACE_REPO"
109
109
  ? githubFlow === kGithubFlowImport
@@ -117,25 +117,25 @@ export const WelcomeFormStep = ({
117
117
  ? githubFlow === kGithubFlowImport
118
118
  ? freshRepoMode === kGithubTargetRepoModeCreate
119
119
  ? html`Use a classic PAT with${" "}<code
120
- class="text-xs bg-black/30 px-1 rounded"
120
+ class="text-xs bg-field px-1 rounded"
121
121
  >repo</code
122
122
  >${" "}scope to create the target repo. Fine-grained
123
123
  works if the target already exists and can access both
124
124
  repos.`
125
125
  : html`Use a classic PAT with${" "}<code
126
- class="text-xs bg-black/30 px-1 rounded"
126
+ class="text-xs bg-field px-1 rounded"
127
127
  >repo</code
128
128
  >${" "}scope, or a fine-grained token with Contents +
129
129
  Metadata access to both the source repo and target
130
130
  repo`
131
131
  : freshRepoMode === kGithubTargetRepoModeExistingEmpty
132
132
  ? html`Use a classic PAT with${" "}<code
133
- class="text-xs bg-black/30 px-1 rounded"
133
+ class="text-xs bg-field px-1 rounded"
134
134
  >repo</code
135
135
  >${" "}scope, or a fine-grained token with Contents +
136
136
  Metadata access to this repo`
137
137
  : html`Use a classic PAT with${" "}<code
138
- class="text-xs bg-black/30 px-1 rounded"
138
+ class="text-xs bg-field px-1 rounded"
139
139
  >repo</code
140
140
  >${" "}scope to create a new private repository`
141
141
  : field.hint}
@@ -165,11 +165,11 @@ export const WelcomeFormStep = ({
165
165
  String(vals[fieldKey] || "").trim(),
166
166
  );
167
167
  return html`
168
- <div class="bg-black/20 border border-border rounded-lg overflow-hidden">
168
+ <div class="bg-field border border-border rounded-lg overflow-hidden">
169
169
  <button
170
170
  type="button"
171
171
  onclick=${() => toggleChannelSection(section.id)}
172
- class="w-full flex items-center justify-between gap-2 px-3 py-2 text-left hover:bg-white/5"
172
+ class="w-full flex items-center justify-between gap-2 px-3 py-2 text-left hover:bg-surface"
173
173
  >
174
174
  <span class="inline-flex items-center gap-2 min-w-0">
175
175
  ${channelMeta.iconSrc
@@ -180,7 +180,7 @@ export const WelcomeFormStep = ({
180
180
  aria-hidden="true"
181
181
  />`
182
182
  : null}
183
- <span class="text-sm text-gray-200">${section.title}</span>
183
+ <span class="text-sm text-body">${section.title}</span>
184
184
  ${hasValue
185
185
  ? html`<${Badge} tone="success">Configured</${Badge}>`
186
186
  : null}
@@ -206,17 +206,17 @@ export const WelcomeFormStep = ({
206
206
  return html`
207
207
  <div class="flex items-center justify-between">
208
208
  <div>
209
- <h2 class="text-sm font-medium text-gray-200">${activeGroup.title}</h2>
210
- <p class="text-xs text-gray-500">${activeGroup.description}</p>
209
+ <h2 class="text-sm font-medium text-body">${activeGroup.title}</h2>
210
+ <p class="text-xs text-fg-muted">${activeGroup.description}</p>
211
211
  </div>
212
212
  ${activeGroup.validate(vals, { hasAi })
213
213
  ? html`<span
214
- class="text-xs font-medium px-2 py-0.5 rounded-full bg-green-900/50 text-green-400"
214
+ class="text-xs font-medium px-2 py-0.5 rounded-full bg-status-success-bg text-status-success"
215
215
  >✓</span
216
216
  >`
217
217
  : activeGroup.id !== "tools"
218
218
  ? html`<span
219
- class="text-xs font-medium px-2 py-0.5 rounded-full bg-yellow-900/50 text-yellow-400"
219
+ class="text-xs font-medium px-2 py-0.5 rounded-full bg-status-warning-bg text-status-warning-muted"
220
220
  >Required</span
221
221
  >`
222
222
  : null}
@@ -225,11 +225,11 @@ export const WelcomeFormStep = ({
225
225
  ${activeGroup.id === "ai" &&
226
226
  html`
227
227
  <div class="space-y-1">
228
- <label class="text-xs font-medium text-gray-400">Model</label>
228
+ <label class="text-xs font-medium text-fg-muted">Model</label>
229
229
  <select
230
230
  value=${vals.MODEL_KEY || ""}
231
231
  onInput=${(e) => setValue("MODEL_KEY", e.target.value)}
232
- class="w-full bg-black/30 border border-border rounded-lg pl-3 pr-8 py-2 text-sm text-gray-200 outline-none focus:border-gray-500"
232
+ class="w-full bg-field border border-border rounded-lg pl-3 pr-8 py-2 text-sm text-body outline-none focus:border-fg-muted"
233
233
  >
234
234
  <option value="">Select a model</option>
235
235
  ${modelOptions.map(
@@ -238,7 +238,7 @@ export const WelcomeFormStep = ({
238
238
  `,
239
239
  )}
240
240
  </select>
241
- <p class="text-xs text-gray-600">
241
+ <p class="text-xs text-fg-dim">
242
242
  ${modelsLoading
243
243
  ? "Loading model catalog..."
244
244
  : modelsError
@@ -250,7 +250,7 @@ export const WelcomeFormStep = ({
250
250
  <button
251
251
  type="button"
252
252
  onclick=${() => setShowAllModels((prev) => !prev)}
253
- class="text-xs text-gray-500 hover:text-gray-300"
253
+ class="text-xs text-fg-muted hover:text-body"
254
254
  >
255
255
  ${showAllModels
256
256
  ? "Show recommended models"
@@ -262,11 +262,11 @@ export const WelcomeFormStep = ({
262
262
  ${activeGroup.id === "ai" &&
263
263
  selectedProvider === "openai-codex" &&
264
264
  html`
265
- <div class="bg-black/20 border border-border rounded-lg p-3 space-y-2">
265
+ <div class="bg-field border border-border rounded-lg p-3 space-y-2">
266
266
  <div class="flex items-center justify-between">
267
- <span class="text-xs text-gray-400">Codex OAuth</span>
267
+ <span class="text-xs text-fg-muted">Codex OAuth</span>
268
268
  ${codexLoading
269
- ? html`<span class="text-xs text-gray-500">Checking...</span>`
269
+ ? html`<span class="text-xs text-fg-muted">Checking...</span>`
270
270
  : codexStatus.connected
271
271
  ? html`<${Badge} tone="success">Connected</${Badge}>`
272
272
  : html`<${Badge} tone="warning">Not connected</${Badge}>`}
@@ -298,11 +298,11 @@ export const WelcomeFormStep = ({
298
298
  codexAuthStarted &&
299
299
  html`
300
300
  <div class="space-y-1 pt-1">
301
- <p class="text-xs text-gray-500">
301
+ <p class="text-xs text-fg-muted">
302
302
  ${codexAuthWaiting
303
303
  ? "Complete login in the popup, then paste the full redirect URL from the address bar (starts with "
304
304
  : "Paste the full redirect URL from the address bar (starts with "}
305
- <code class="text-xs bg-black/30 px-1 rounded"
305
+ <code class="text-xs bg-field px-1 rounded"
306
306
  >http://localhost:1455/auth/callback</code
307
307
  >) ${codexAuthWaiting ? " to finish setup." : " to finish setup."}
308
308
  </p>
@@ -311,7 +311,7 @@ export const WelcomeFormStep = ({
311
311
  value=${codexManualInput}
312
312
  onInput=${(e) => setCodexManualInput(e.target.value)}
313
313
  placeholder="http://localhost:1455/auth/callback?code=...&state=..."
314
- class="w-full bg-black/30 border border-border rounded-lg px-3 py-2 text-xs text-gray-200 outline-none focus:border-gray-500"
314
+ class="w-full bg-field border border-border rounded-lg px-3 py-2 text-xs text-body outline-none focus:border-fg-muted"
315
315
  />
316
316
  <${ActionButton}
317
317
  onClick=${completeCodexAuth}
@@ -370,7 +370,7 @@ export const WelcomeFormStep = ({
370
370
  ).map((field) => renderStandardField(field))}
371
371
  ${error
372
372
  ? html`<div
373
- class="bg-red-900/30 border border-red-800 rounded-xl p-3 text-red-300 text-sm"
373
+ class="bg-status-error-bg border border-status-error-border rounded-xl p-3 text-status-error text-sm"
374
374
  >
375
375
  ${error}
376
376
  </div>`
@@ -379,7 +379,7 @@ export const WelcomeFormStep = ({
379
379
  ? html`
380
380
  ${showOptionalOpenai
381
381
  ? html`<div class="space-y-1">
382
- <label class="text-xs font-medium text-gray-400"
382
+ <label class="text-xs font-medium text-fg-muted"
383
383
  >OpenAI API Key</label
384
384
  >
385
385
  <${SecretInput}
@@ -387,9 +387,9 @@ export const WelcomeFormStep = ({
387
387
  onInput=${(e) => setValue("OPENAI_API_KEY", e.target.value)}
388
388
  placeholder="sk-..."
389
389
  isSecret=${true}
390
- inputClass="flex-1 bg-black/30 border border-border rounded-lg px-3 py-2 text-sm text-gray-200 outline-none focus:border-gray-500 font-mono"
390
+ inputClass="flex-1 bg-field border border-border rounded-lg px-3 py-2 text-sm text-body outline-none focus:border-fg-muted font-mono"
391
391
  />
392
- <p class="text-xs text-gray-600">
392
+ <p class="text-xs text-fg-dim">
393
393
  Used for memory embeddings -${" "}
394
394
  <a
395
395
  href="https://platform.openai.com"
@@ -403,7 +403,7 @@ export const WelcomeFormStep = ({
403
403
  : null}
404
404
  ${showOptionalGemini
405
405
  ? html`<div class="space-y-1">
406
- <label class="text-xs font-medium text-gray-400"
406
+ <label class="text-xs font-medium text-fg-muted"
407
407
  >Gemini API Key</label
408
408
  >
409
409
  <${SecretInput}
@@ -411,9 +411,9 @@ export const WelcomeFormStep = ({
411
411
  onInput=${(e) => setValue("GEMINI_API_KEY", e.target.value)}
412
412
  placeholder="AI..."
413
413
  isSecret=${true}
414
- inputClass="flex-1 bg-black/30 border border-border rounded-lg px-3 py-2 text-sm text-gray-200 outline-none focus:border-gray-500 font-mono"
414
+ inputClass="flex-1 bg-field border border-border rounded-lg px-3 py-2 text-sm text-body outline-none focus:border-fg-muted font-mono"
415
415
  />
416
- <p class="text-xs text-gray-600">
416
+ <p class="text-xs text-fg-dim">
417
417
  Used for memory embeddings and Nano Banana -${" "}
418
418
  <a
419
419
  href="https://aistudio.google.com"
@@ -1,5 +1,5 @@
1
- import { h } from "https://esm.sh/preact";
2
- import htm from "https://esm.sh/htm";
1
+ import { h } from "preact";
2
+ import htm from "htm";
3
3
 
4
4
  const html = htm.bind(h);
5
5