@chrysb/alphaclaw 0.8.1-beta.8 → 0.8.2

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 (210) hide show
  1. package/README.md +32 -24
  2. package/bin/alphaclaw.js +13 -2
  3. package/lib/public/css/tailwind.generated.css +1 -0
  4. package/lib/public/css/tailwind.input.css +3 -0
  5. package/lib/public/css/theme.css +28 -0
  6. package/lib/public/css/vendor/xterm.css +218 -0
  7. package/lib/public/dist/app.bundle.js +10514 -0
  8. package/lib/public/dist/chunks/addon-fit-W4YZGRNV.js +1 -0
  9. package/lib/public/dist/chunks/chunk-72ZECFVW.js +1 -0
  10. package/lib/public/dist/chunks/xterm-KOX4YMOF.js +9 -0
  11. package/lib/public/js/app.js +4 -4
  12. package/lib/public/js/components/action-button.js +8 -8
  13. package/lib/public/js/components/add-channel-menu.js +2 -2
  14. package/lib/public/js/components/agent-send-modal.js +6 -6
  15. package/lib/public/js/components/agents-tab/agent-bindings-section/channel-item-trailing.js +7 -7
  16. package/lib/public/js/components/agents-tab/agent-bindings-section/index.js +3 -3
  17. package/lib/public/js/components/agents-tab/agent-bindings-section/use-agent-bindings.js +1 -1
  18. package/lib/public/js/components/agents-tab/agent-bindings-section/use-channel-items.js +4 -4
  19. package/lib/public/js/components/agents-tab/agent-detail-panel.js +5 -5
  20. package/lib/public/js/components/agents-tab/agent-identity-section.js +18 -18
  21. package/lib/public/js/components/agents-tab/agent-overview/index.js +2 -2
  22. package/lib/public/js/components/agents-tab/agent-overview/manage-card.js +2 -2
  23. package/lib/public/js/components/agents-tab/agent-overview/model-card.js +8 -8
  24. package/lib/public/js/components/agents-tab/agent-overview/tools-card.js +5 -5
  25. package/lib/public/js/components/agents-tab/agent-overview/use-model-card.js +1 -1
  26. package/lib/public/js/components/agents-tab/agent-overview/use-workspace-card.js +1 -1
  27. package/lib/public/js/components/agents-tab/agent-overview/workspace-card.js +4 -4
  28. package/lib/public/js/components/agents-tab/agent-pairing-section.js +4 -4
  29. package/lib/public/js/components/agents-tab/agent-tools/index.js +5 -5
  30. package/lib/public/js/components/agents-tab/agent-tools/use-agent-tools.js +1 -1
  31. package/lib/public/js/components/agents-tab/create-agent-modal.js +13 -13
  32. package/lib/public/js/components/agents-tab/create-channel-modal.js +34 -34
  33. package/lib/public/js/components/agents-tab/delete-agent-dialog.js +3 -3
  34. package/lib/public/js/components/agents-tab/edit-agent-modal.js +9 -9
  35. package/lib/public/js/components/agents-tab/index.js +3 -3
  36. package/lib/public/js/components/agents-tab/use-agents.js +1 -1
  37. package/lib/public/js/components/badge.js +6 -6
  38. package/lib/public/js/components/channel-account-status-badge.js +2 -2
  39. package/lib/public/js/components/channel-operations-panel.js +2 -2
  40. package/lib/public/js/components/channels.js +9 -9
  41. package/lib/public/js/components/confirm-dialog.js +5 -5
  42. package/lib/public/js/components/credentials-modal.js +22 -22
  43. package/lib/public/js/components/cron-tab/cron-calendar.js +6 -6
  44. package/lib/public/js/components/cron-tab/cron-insights-panel.js +10 -10
  45. package/lib/public/js/components/cron-tab/cron-job-detail.js +4 -4
  46. package/lib/public/js/components/cron-tab/cron-job-list.js +4 -4
  47. package/lib/public/js/components/cron-tab/cron-job-settings-card.js +15 -15
  48. package/lib/public/js/components/cron-tab/cron-job-trends-panel.js +5 -5
  49. package/lib/public/js/components/cron-tab/cron-job-usage.js +16 -16
  50. package/lib/public/js/components/cron-tab/cron-overview.js +10 -10
  51. package/lib/public/js/components/cron-tab/cron-prompt-editor.js +3 -3
  52. package/lib/public/js/components/cron-tab/cron-run-history-panel.js +39 -39
  53. package/lib/public/js/components/cron-tab/cron-runs-trend-card.js +4 -4
  54. package/lib/public/js/components/cron-tab/index.js +5 -5
  55. package/lib/public/js/components/cron-tab/use-cron-tab.js +1 -1
  56. package/lib/public/js/components/device-pairings.js +12 -12
  57. package/lib/public/js/components/doctor/findings-list.js +22 -22
  58. package/lib/public/js/components/doctor/fix-card-modal.js +2 -2
  59. package/lib/public/js/components/doctor/general-warning.js +5 -5
  60. package/lib/public/js/components/doctor/index.js +26 -26
  61. package/lib/public/js/components/doctor/summary-cards.js +5 -5
  62. package/lib/public/js/components/envars.js +16 -16
  63. package/lib/public/js/components/features.js +4 -4
  64. package/lib/public/js/components/file-tree.js +4 -4
  65. package/lib/public/js/components/file-viewer/diff-viewer.js +2 -2
  66. package/lib/public/js/components/file-viewer/editor-surface.js +2 -2
  67. package/lib/public/js/components/file-viewer/frontmatter-panel.js +2 -2
  68. package/lib/public/js/components/file-viewer/index.js +3 -3
  69. package/lib/public/js/components/file-viewer/markdown-split-view.js +2 -2
  70. package/lib/public/js/components/file-viewer/media-preview.js +2 -2
  71. package/lib/public/js/components/file-viewer/scroll-sync.js +1 -1
  72. package/lib/public/js/components/file-viewer/sqlite-viewer.js +2 -2
  73. package/lib/public/js/components/file-viewer/status-banners.js +2 -2
  74. package/lib/public/js/components/file-viewer/toolbar.js +2 -2
  75. package/lib/public/js/components/file-viewer/use-editor-line-number-sync.js +1 -1
  76. package/lib/public/js/components/file-viewer/use-editor-selection-restore.js +1 -1
  77. package/lib/public/js/components/file-viewer/use-file-diff.js +1 -1
  78. package/lib/public/js/components/file-viewer/use-file-loader.js +1 -1
  79. package/lib/public/js/components/file-viewer/use-file-viewer-draft-sync.js +1 -1
  80. package/lib/public/js/components/file-viewer/use-file-viewer-hotkeys.js +1 -1
  81. package/lib/public/js/components/file-viewer/use-file-viewer.js +2 -2
  82. package/lib/public/js/components/gateway.js +12 -12
  83. package/lib/public/js/components/general/index.js +7 -7
  84. package/lib/public/js/components/general/use-general-tab.js +1 -1
  85. package/lib/public/js/components/global-restart-banner.js +2 -2
  86. package/lib/public/js/components/google/account-row.js +7 -7
  87. package/lib/public/js/components/google/add-account-modal.js +8 -8
  88. package/lib/public/js/components/google/gmail-setup-wizard.js +24 -24
  89. package/lib/public/js/components/google/gmail-watch-toggle.js +5 -5
  90. package/lib/public/js/components/google/index.js +6 -6
  91. package/lib/public/js/components/google/use-gmail-watch.js +1 -1
  92. package/lib/public/js/components/google/use-google-accounts.js +1 -1
  93. package/lib/public/js/components/icons.js +2 -2
  94. package/lib/public/js/components/info-tooltip.js +3 -3
  95. package/lib/public/js/components/loading-spinner.js +2 -2
  96. package/lib/public/js/components/modal-shell.js +5 -5
  97. package/lib/public/js/components/models-tab/index.js +11 -11
  98. package/lib/public/js/components/models-tab/model-picker.js +9 -9
  99. package/lib/public/js/components/models-tab/provider-auth-card.js +12 -12
  100. package/lib/public/js/components/models-tab/use-models.js +1 -1
  101. package/lib/public/js/components/models.js +18 -18
  102. package/lib/public/js/components/nodes-tab/browser-attach/index.js +15 -25
  103. package/lib/public/js/components/nodes-tab/connected-nodes/index.js +32 -32
  104. package/lib/public/js/components/nodes-tab/connected-nodes/use-connected-nodes-card.js +57 -6
  105. package/lib/public/js/components/nodes-tab/exec-allowlist/index.js +10 -10
  106. package/lib/public/js/components/nodes-tab/exec-allowlist/use-exec-allowlist.js +1 -1
  107. package/lib/public/js/components/nodes-tab/exec-config/index.js +13 -13
  108. package/lib/public/js/components/nodes-tab/exec-config/use-exec-config.js +1 -1
  109. package/lib/public/js/components/nodes-tab/index.js +2 -2
  110. package/lib/public/js/components/nodes-tab/setup-wizard/index.js +14 -14
  111. package/lib/public/js/components/nodes-tab/setup-wizard/use-setup-wizard.js +1 -1
  112. package/lib/public/js/components/nodes-tab/use-nodes-tab.js +1 -1
  113. package/lib/public/js/components/onboarding/use-welcome-codex.js +1 -1
  114. package/lib/public/js/components/onboarding/use-welcome-pairing.js +1 -1
  115. package/lib/public/js/components/onboarding/use-welcome-storage.js +1 -1
  116. package/lib/public/js/components/onboarding/welcome-config.js +3 -3
  117. package/lib/public/js/components/onboarding/welcome-form-step.js +34 -34
  118. package/lib/public/js/components/onboarding/welcome-header.js +2 -2
  119. package/lib/public/js/components/onboarding/welcome-import-step.js +22 -22
  120. package/lib/public/js/components/onboarding/welcome-pairing-step.js +15 -15
  121. package/lib/public/js/components/onboarding/welcome-placeholder-review-step.js +7 -7
  122. package/lib/public/js/components/onboarding/welcome-pre-step.js +9 -9
  123. package/lib/public/js/components/onboarding/welcome-secret-review-step.js +15 -15
  124. package/lib/public/js/components/onboarding/welcome-setup-step.js +8 -8
  125. package/lib/public/js/components/overflow-menu.js +3 -3
  126. package/lib/public/js/components/page-header.js +2 -2
  127. package/lib/public/js/components/pairings.js +14 -14
  128. package/lib/public/js/components/pane-shell.js +2 -2
  129. package/lib/public/js/components/pill-tabs.js +4 -4
  130. package/lib/public/js/components/pop-actions.js +3 -3
  131. package/lib/public/js/components/providers.js +17 -17
  132. package/lib/public/js/components/routes/agents-route.js +2 -2
  133. package/lib/public/js/components/routes/browse-route.js +2 -2
  134. package/lib/public/js/components/routes/cron-route.js +2 -2
  135. package/lib/public/js/components/routes/doctor-route.js +2 -2
  136. package/lib/public/js/components/routes/envars-route.js +2 -2
  137. package/lib/public/js/components/routes/general-route.js +2 -2
  138. package/lib/public/js/components/routes/models-route.js +2 -2
  139. package/lib/public/js/components/routes/nodes-route.js +2 -2
  140. package/lib/public/js/components/routes/providers-route.js +2 -2
  141. package/lib/public/js/components/routes/route-redirect.js +2 -2
  142. package/lib/public/js/components/routes/telegram-route.js +2 -2
  143. package/lib/public/js/components/routes/usage-route.js +2 -2
  144. package/lib/public/js/components/routes/watchdog-route.js +2 -2
  145. package/lib/public/js/components/routes/webhooks-route.js +2 -2
  146. package/lib/public/js/components/scope-picker.js +9 -9
  147. package/lib/public/js/components/secret-input.js +5 -5
  148. package/lib/public/js/components/segmented-control.js +2 -2
  149. package/lib/public/js/components/session-select-field.js +7 -7
  150. package/lib/public/js/components/sidebar-git-panel.js +3 -3
  151. package/lib/public/js/components/sidebar.js +3 -3
  152. package/lib/public/js/components/summary-stat-card.js +3 -3
  153. package/lib/public/js/components/telegram-workspace/index.js +10 -10
  154. package/lib/public/js/components/telegram-workspace/manage.js +36 -36
  155. package/lib/public/js/components/telegram-workspace/onboarding.js +73 -73
  156. package/lib/public/js/components/toast.js +8 -8
  157. package/lib/public/js/components/toggle-switch.js +2 -2
  158. package/lib/public/js/components/tooltip.js +5 -5
  159. package/lib/public/js/components/update-action-button.js +2 -2
  160. package/lib/public/js/components/update-modal.js +9 -9
  161. package/lib/public/js/components/usage-tab/constants.js +2 -2
  162. package/lib/public/js/components/usage-tab/index.js +3 -3
  163. package/lib/public/js/components/usage-tab/overview-section.js +15 -15
  164. package/lib/public/js/components/usage-tab/sessions-section.js +19 -19
  165. package/lib/public/js/components/usage-tab/use-usage-tab.js +2 -2
  166. package/lib/public/js/components/watchdog-tab/console/index.js +22 -8
  167. package/lib/public/js/components/watchdog-tab/console/use-console.js +28 -2
  168. package/lib/public/js/components/watchdog-tab/helpers.js +35 -6
  169. package/lib/public/js/components/watchdog-tab/incidents/index.js +6 -6
  170. package/lib/public/js/components/watchdog-tab/incidents/use-incidents.js +1 -1
  171. package/lib/public/js/components/watchdog-tab/index.js +4 -2
  172. package/lib/public/js/components/watchdog-tab/resource-bar.js +5 -5
  173. package/lib/public/js/components/watchdog-tab/resources/index.js +14 -3
  174. package/lib/public/js/components/watchdog-tab/resources/use-resources.js +1 -1
  175. package/lib/public/js/components/watchdog-tab/settings/index.js +97 -30
  176. package/lib/public/js/components/watchdog-tab/settings/use-settings.js +1 -1
  177. package/lib/public/js/components/watchdog-tab/terminal/index.js +3 -3
  178. package/lib/public/js/components/watchdog-tab/terminal/use-terminal.js +41 -5
  179. package/lib/public/js/components/watchdog-tab/use-watchdog-tab.js +2 -0
  180. package/lib/public/js/components/webhooks/create-webhook-modal/index.js +17 -17
  181. package/lib/public/js/components/webhooks/helpers.js +3 -3
  182. package/lib/public/js/components/webhooks/index.js +4 -4
  183. package/lib/public/js/components/webhooks/request-history/index.js +14 -14
  184. package/lib/public/js/components/webhooks/request-history/use-request-history.js +1 -1
  185. package/lib/public/js/components/webhooks/webhook-detail/index.js +41 -41
  186. package/lib/public/js/components/webhooks/webhook-detail/use-webhook-detail.js +1 -1
  187. package/lib/public/js/components/webhooks/webhook-list/index.js +11 -11
  188. package/lib/public/js/components/webhooks/webhook-list/use-webhook-list.js +1 -1
  189. package/lib/public/js/components/welcome/index.js +3 -3
  190. package/lib/public/js/components/welcome/use-welcome.js +10 -10
  191. package/lib/public/js/hooks/use-app-shell-controller.js +22 -4
  192. package/lib/public/js/hooks/use-app-shell-ui.js +1 -1
  193. package/lib/public/js/hooks/use-browse-navigation.js +1 -1
  194. package/lib/public/js/hooks/use-cached-fetch.js +1 -1
  195. package/lib/public/js/hooks/use-destination-session-selection.js +1 -1
  196. package/lib/public/js/hooks/use-hash-location.js +1 -1
  197. package/lib/public/js/hooks/useAgentSessions.js +1 -1
  198. package/lib/public/js/hooks/usePolling.js +1 -1
  199. package/lib/public/js/tailwind-config.js +39 -0
  200. package/lib/public/login.html +3 -18
  201. package/lib/public/setup.html +2 -18
  202. package/lib/server/init/register-server-routes.js +2 -0
  203. package/lib/server/onboarding/github.js +39 -0
  204. package/lib/server/routes/nodes.js +12 -4
  205. package/lib/server/routes/pairings.js +5 -1
  206. package/lib/server/routes/system.js +5 -0
  207. package/lib/server/routes/watchdog.js +15 -0
  208. package/lib/server/watchdog.js +137 -51
  209. package/lib/server.js +2 -0
  210. package/package.json +14 -3
@@ -3,15 +3,16 @@ import {
3
3
  useEffect,
4
4
  useRef,
5
5
  useState,
6
- } from "https://esm.sh/preact/hooks";
6
+ } from "preact/hooks";
7
7
  import { copyTextToClipboard } from "../../../lib/clipboard.js";
8
8
  import { fetchNodeBrowserStatusForNode, removeNode } from "../../../lib/api.js";
9
9
  import { readUiSettings, updateUiSettings } from "../../../lib/ui-settings.js";
10
10
  import { showToast } from "../../toast.js";
11
11
 
12
- const kBrowserCheckTimeoutMs = 15000;
12
+ const kBrowserCheckTimeoutMs = 35000;
13
13
  const kBrowserPollIntervalMs = 10000;
14
14
  const kBrowserAttachStateByNodeKey = "nodesBrowserAttachStateByNode";
15
+ const kBrowserClosedPageErrorPattern = /selected page has been closed/i;
15
16
 
16
17
  const withTimeout = async (promise, timeoutMs = kBrowserCheckTimeoutMs) => {
17
18
  let timeoutId = null;
@@ -37,6 +38,16 @@ const isBrowserCapableNode = (node) => {
37
38
  return caps.includes("browser") || commands.includes("browser.proxy");
38
39
  };
39
40
 
41
+ const normalizeBrowserStatusError = (error) => {
42
+ const rawMessage = String(
43
+ error?.message || "Could not check node browser status",
44
+ ).trim();
45
+ if (kBrowserClosedPageErrorPattern.test(rawMessage)) {
46
+ return "Selected Chrome page was closed. Click Attach to reconnect.";
47
+ }
48
+ return rawMessage;
49
+ };
50
+
40
51
  const readBrowserAttachStateByNode = () => {
41
52
  const uiSettings = readUiSettings();
42
53
  const attachState = uiSettings?.[kBrowserAttachStateByNodeKey];
@@ -120,7 +131,12 @@ export const useConnectedNodesCard = ({
120
131
  [normalizedNodeId]: status,
121
132
  }));
122
133
  } catch (error) {
123
- const message = error.message || "Could not check node browser status";
134
+ const message = normalizeBrowserStatusError(error);
135
+ // Stop poll loops after failures so we do not keep retrying a stale browser session.
136
+ setBrowserStatusByNodeId((prev) => ({
137
+ ...prev,
138
+ [normalizedNodeId]: null,
139
+ }));
124
140
  setBrowserErrorByNodeId((prev) => ({
125
141
  ...prev,
126
142
  [normalizedNodeId]: message,
@@ -212,6 +228,32 @@ export const useConnectedNodesCard = ({
212
228
  removingNodeId,
213
229
  ]);
214
230
 
231
+ useEffect(() => {
232
+ if (checkingBrowserNodeId) return;
233
+ const pendingInitialNodeId = nodes
234
+ .map((node) => ({
235
+ nodeId: String(node?.nodeId || "").trim(),
236
+ connected: node?.connected === true,
237
+ browserCapable: isBrowserCapableNode(node),
238
+ }))
239
+ .find((entry) => {
240
+ if (!entry.nodeId || !entry.connected || !entry.browserCapable) return false;
241
+ if (browserAttachStateByNodeId?.[entry.nodeId] !== true) return false;
242
+ if (browserStatusByNodeId?.[entry.nodeId]) return false;
243
+ if (browserErrorByNodeId?.[entry.nodeId]) return false;
244
+ return true;
245
+ })?.nodeId;
246
+ if (!pendingInitialNodeId) return;
247
+ handleCheckNodeBrowser(pendingInitialNodeId, { silent: true });
248
+ }, [
249
+ browserAttachStateByNodeId,
250
+ browserErrorByNodeId,
251
+ browserStatusByNodeId,
252
+ checkingBrowserNodeId,
253
+ handleCheckNodeBrowser,
254
+ nodes,
255
+ ]);
256
+
215
257
  useEffect(() => {
216
258
  if (checkingBrowserNodeId) return;
217
259
  const pollableNodeIds = nodes
@@ -219,13 +261,17 @@ export const useConnectedNodesCard = ({
219
261
  nodeId: String(node?.nodeId || "").trim(),
220
262
  connected: node?.connected === true,
221
263
  browserCapable: isBrowserCapableNode(node),
264
+ browserRunning:
265
+ browserStatusByNodeId?.[String(node?.nodeId || "").trim()]?.running ===
266
+ true,
222
267
  }))
223
268
  .filter(
224
269
  (entry) =>
225
270
  entry.nodeId &&
226
271
  entry.connected &&
227
272
  entry.browserCapable &&
228
- browserAttachStateByNodeId?.[entry.nodeId] === true,
273
+ browserAttachStateByNodeId?.[entry.nodeId] === true &&
274
+ entry.browserRunning,
229
275
  )
230
276
  .map((entry) => entry.nodeId);
231
277
  if (!pollableNodeIds.length) return;
@@ -238,13 +284,18 @@ export const useConnectedNodesCard = ({
238
284
  const nextNodeId = pollableNodeIds[pollIndex];
239
285
  await handleCheckNodeBrowser(nextNodeId, { silent: true });
240
286
  };
241
- poll();
242
287
  const timer = setInterval(poll, kBrowserPollIntervalMs);
243
288
  return () => {
244
289
  active = false;
245
290
  clearInterval(timer);
246
291
  };
247
- }, [browserAttachStateByNodeId, checkingBrowserNodeId, handleCheckNodeBrowser, nodes]);
292
+ }, [
293
+ browserAttachStateByNodeId,
294
+ browserStatusByNodeId,
295
+ checkingBrowserNodeId,
296
+ handleCheckNodeBrowser,
297
+ nodes,
298
+ ]);
248
299
 
249
300
  return {
250
301
  browserStatusByNodeId,
@@ -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"