@chrysb/alphaclaw 0.8.1 → 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 (209) 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 +5 -5
  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 +18 -3
  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 +1 -1
  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/routes/nodes.js +10 -2
  204. package/lib/server/routes/pairings.js +5 -1
  205. package/lib/server/routes/system.js +5 -0
  206. package/lib/server/routes/watchdog.js +15 -0
  207. package/lib/server/watchdog.js +137 -51
  208. package/lib/server.js +2 -0
  209. package/package.json +14 -3
@@ -1,7 +1,8 @@
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 { formatBytes } from "../helpers.js";
4
4
  import { ResourceBar } from "../resource-bar.js";
5
+ import { Tooltip } from "../../tooltip.js";
5
6
 
6
7
  const html = htm.bind(h);
7
8
 
@@ -11,6 +12,16 @@ export const WatchdogResourcesCard = ({
11
12
  onSetMemoryExpanded = () => {},
12
13
  }) => {
13
14
  if (!resources) return null;
15
+ const diskLabel = resources.disk?.path
16
+ ? html`
17
+ <${Tooltip}
18
+ text=${resources.disk.path}
19
+ widthClass="w-auto max-w-80 whitespace-normal break-all"
20
+ >
21
+ <span class="inline-block cursor-help">Disk</span>
22
+ </${Tooltip}>
23
+ `
24
+ : "Disk";
14
25
  const memorySegments = (() => {
15
26
  const processes = resources.processes;
16
27
  const totalBytes = resources.memory?.totalBytes;
@@ -67,7 +78,7 @@ export const WatchdogResourcesCard = ({
67
78
  onToggle=${() => onSetMemoryExpanded(true)}
68
79
  />
69
80
  <${ResourceBar}
70
- label=${`Disk${resources.disk?.path ? ` (${resources.disk.path})` : ""}`}
81
+ label=${diskLabel}
71
82
  percent=${resources.disk?.percent}
72
83
  detail=${`${formatBytes(resources.disk?.usedBytes)} / ${formatBytes(resources.disk?.totalBytes)}`}
73
84
  />
@@ -1,4 +1,4 @@
1
- import { useState } from "https://esm.sh/preact/hooks";
1
+ import { useState } from "preact/hooks";
2
2
  import { usePolling } from "../../../hooks/usePolling.js";
3
3
  import { fetchWatchdogResources } from "../../../lib/api.js";
4
4
 
@@ -1,7 +1,9 @@
1
- import { h } from "https://esm.sh/preact";
2
- import htm from "https://esm.sh/htm";
1
+ import { h } from "preact";
2
+ import { useState } from "preact/hooks";
3
+ import htm from "htm";
3
4
  import { InfoTooltip } from "../../info-tooltip.js";
4
5
  import { ToggleSwitch } from "../../toggle-switch.js";
6
+ import { showToast } from "../../toast.js";
5
7
 
6
8
  const html = htm.bind(h);
7
9
 
@@ -10,35 +12,100 @@ export const WatchdogSettingsCard = ({
10
12
  savingSettings = false,
11
13
  onToggleAutoRepair = () => {},
12
14
  onToggleNotifications = () => {},
13
- }) => html`
14
- <div class="bg-surface border border-border rounded-xl p-4">
15
- <div class="flex items-center justify-between gap-3">
16
- <div class="inline-flex items-center gap-2 text-xs text-gray-400">
17
- <span>Auto-repair</span>
18
- <${InfoTooltip}
19
- text="Automatically runs OpenClaw doctor repair when watchdog detects gateway health failures or crash loops."
15
+ }) => {
16
+ const [testing, setTesting] = useState(false);
17
+ const [testResult, setTestResult] = useState(null);
18
+
19
+ const handleTestNotification = async () => {
20
+ setTesting(true);
21
+ setTestResult(null);
22
+ try {
23
+ const res = await fetch("/api/watchdog/test-notification", { method: "POST" });
24
+ const data = await res.json();
25
+ if (!data?.ok) {
26
+ setTestResult(data);
27
+ return;
28
+ }
29
+
30
+ const channels = data.result?.channels || data.result || {};
31
+ const parts = [];
32
+ for (const channel of ["telegram", "discord", "slack"]) {
33
+ const ch = channels[channel];
34
+ if (!ch || ch.skipped) continue;
35
+ if (ch.sent > 0) parts.push(`${channel}: ${ch.sent} sent`);
36
+ if (ch.failed > 0) parts.push(`${channel}: ${ch.failed} failed`);
37
+ }
38
+
39
+ if (parts.length === 0) {
40
+ showToast("No channels configured", "warning");
41
+ return;
42
+ }
43
+
44
+ const hasFailures = parts.some((part) => part.includes("failed"));
45
+ showToast(
46
+ hasFailures ? parts.join(", ") : `Test notification sent: ${parts.join(", ")}`,
47
+ hasFailures ? "warning" : "success",
48
+ );
49
+ } catch (err) {
50
+ setTestResult({ ok: false, error: err.message });
51
+ } finally {
52
+ setTesting(false);
53
+ }
54
+ };
55
+
56
+ const formatResult = (result) => {
57
+ if (!result) return null;
58
+ return html`<span class="text-status-error-muted text-xs">
59
+ ${result.error || "Failed"}
60
+ </span>`;
61
+ };
62
+
63
+ return html`
64
+ <div class="bg-surface border border-border rounded-xl p-4">
65
+ <div class="flex items-center justify-between gap-3">
66
+ <div class="inline-flex items-center gap-2 text-xs text-fg-muted">
67
+ <span>Auto-repair</span>
68
+ <${InfoTooltip}
69
+ text="Automatically runs OpenClaw doctor repair when watchdog detects gateway health failures or crash loops."
70
+ />
71
+ </div>
72
+ <${ToggleSwitch}
73
+ checked=${!!settings.autoRepair}
74
+ disabled=${savingSettings}
75
+ onChange=${onToggleAutoRepair}
76
+ label=""
20
77
  />
21
78
  </div>
22
- <${ToggleSwitch}
23
- checked=${!!settings.autoRepair}
24
- disabled=${savingSettings}
25
- onChange=${onToggleAutoRepair}
26
- label=""
27
- />
28
- </div>
29
- <div class="flex items-center justify-between gap-3 mt-3">
30
- <div class="inline-flex items-center gap-2 text-xs text-gray-400">
31
- <span>Notifications</span>
32
- <${InfoTooltip}
33
- text="Sends channel notices for watchdog alerts and auto-repair outcomes."
34
- />
79
+ <div class="flex items-center justify-between gap-3 mt-3">
80
+ <div class="inline-flex items-center gap-2 text-xs text-fg-muted">
81
+ <span>Notifications</span>
82
+ <${InfoTooltip}
83
+ text="Sends channel notices for watchdog alerts and auto-repair outcomes."
84
+ />
85
+ </div>
86
+ <div class="flex items-center gap-2">
87
+ <button
88
+ class=${`text-xs px-2 py-1 rounded-lg ac-btn-ghost disabled:opacity-50 disabled:cursor-not-allowed ${
89
+ settings.notificationsEnabled ? "" : "invisible pointer-events-none"
90
+ }`}
91
+ onClick=${handleTestNotification}
92
+ disabled=${testing || savingSettings || !settings.notificationsEnabled}
93
+ aria-hidden=${!settings.notificationsEnabled}
94
+ tabIndex=${settings.notificationsEnabled ? 0 : -1}
95
+ >
96
+ ${testing ? "Sending..." : "Test"}
97
+ </button>
98
+ <${ToggleSwitch}
99
+ checked=${!!settings.notificationsEnabled}
100
+ disabled=${savingSettings}
101
+ onChange=${onToggleNotifications}
102
+ label=""
103
+ />
104
+ </div>
35
105
  </div>
36
- <${ToggleSwitch}
37
- checked=${!!settings.notificationsEnabled}
38
- disabled=${savingSettings}
39
- onChange=${onToggleNotifications}
40
- label=""
41
- />
106
+ ${testResult
107
+ ? html`<div class="mt-2">${formatResult(testResult)}</div>`
108
+ : null}
42
109
  </div>
43
- </div>
44
- `;
110
+ `;
111
+ };
@@ -1,4 +1,4 @@
1
- import { useEffect, useState } from "https://esm.sh/preact/hooks";
1
+ import { useEffect, useState } from "preact/hooks";
2
2
  import {
3
3
  fetchWatchdogSettings,
4
4
  triggerWatchdogRepair,
@@ -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
 
@@ -11,7 +11,7 @@ export const WatchdogTerminal = ({
11
11
  }) => html`
12
12
  <div
13
13
  ref=${panelRef}
14
- class="watchdog-logs-panel bg-black/40 border border-border rounded-lg p-3 overflow-hidden"
14
+ class="watchdog-logs-panel bg-field border border-border rounded-lg p-3 overflow-hidden"
15
15
  style=${{ height: `${panelHeightPx}px` }}
16
16
  onClick=${() => terminalInstanceRef?.current?.focus()}
17
17
  >
@@ -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 { closeWatchdogTerminalSession } from "../../../lib/api.js";
3
3
  import { showToast } from "../../toast.js";
4
4
  import {
@@ -8,6 +8,33 @@ import {
8
8
  loadXtermModules,
9
9
  } from "../helpers.js";
10
10
 
11
+ const waitForTerminalHost = ({
12
+ hostRef = null,
13
+ panelRef = null,
14
+ maxFrames = 8,
15
+ } = {}) =>
16
+ new Promise((resolve, reject) => {
17
+ let framesRemaining = Math.max(1, Number(maxFrames) || 1);
18
+
19
+ const check = () => {
20
+ if (hostRef?.current && panelRef?.current) {
21
+ resolve({
22
+ hostElement: hostRef.current,
23
+ panelElement: panelRef.current,
24
+ });
25
+ return;
26
+ }
27
+ framesRemaining -= 1;
28
+ if (framesRemaining <= 0) {
29
+ reject(new Error("Terminal host not ready"));
30
+ return;
31
+ }
32
+ window.requestAnimationFrame(check);
33
+ };
34
+
35
+ check();
36
+ });
37
+
11
38
  export const useWatchdogTerminal = ({
12
39
  active = false,
13
40
  panelRef = null,
@@ -37,9 +64,14 @@ export const useWatchdogTerminal = ({
37
64
  try {
38
65
  setConnectingTerminal(true);
39
66
  ensureXtermStylesheet();
40
- const [{ Terminal }, { FitAddon }] = await loadXtermModules();
67
+ const { Terminal, FitAddon } = await loadXtermModules();
41
68
  if (cancelled) return;
42
- if (!terminalInstanceRef.current && hostRef?.current) {
69
+ const { hostElement } = await waitForTerminalHost({
70
+ hostRef,
71
+ panelRef,
72
+ });
73
+ if (cancelled) return;
74
+ if (!terminalInstanceRef.current) {
43
75
  const terminal = new Terminal({
44
76
  cursorBlink: true,
45
77
  fontFamily:
@@ -56,7 +88,7 @@ export const useWatchdogTerminal = ({
56
88
  });
57
89
  const fitAddon = new FitAddon();
58
90
  terminal.loadAddon(fitAddon);
59
- terminal.open(hostRef.current);
91
+ terminal.open(hostElement);
60
92
  fitAddon.fit();
61
93
  terminal.attachCustomKeyEventHandler((event) => {
62
94
  if (event.type !== "keydown") return true;
@@ -161,12 +193,16 @@ export const useWatchdogTerminal = ({
161
193
  setTerminalStatusText("Connection error");
162
194
  showToast("Watchdog terminal connection failed", "error");
163
195
  };
164
- } catch {
196
+ } catch (error) {
165
197
  if (cancelled) return;
166
198
  setConnectingTerminal(false);
167
199
  setTerminalUiSettling(false);
168
200
  setTerminalConnected(false);
169
201
  setTerminalStatusText("Terminal failed to load");
202
+ console.error(
203
+ `[watchdog-terminal] initialization failed: ${error?.message || "unknown error"}`,
204
+ error,
205
+ );
170
206
  showToast("Could not initialize terminal", "error");
171
207
  }
172
208
  };
@@ -36,6 +36,7 @@ export const useWatchdogTab = ({
36
36
  isRepairInProgress: settings.isRepairInProgress,
37
37
  logs: consoleState.logs,
38
38
  loadingLogs: consoleState.loadingLogs,
39
+ copyingAll: consoleState.copyingAll,
39
40
  stickToBottom: consoleState.stickToBottom,
40
41
  setStickToBottom: consoleState.setStickToBottom,
41
42
  activeConsoleTab: consoleState.activeConsoleTab,
@@ -51,5 +52,6 @@ export const useWatchdogTab = ({
51
52
  terminalPanelRef: consoleState.terminalPanelRef,
52
53
  terminalHostRef: consoleState.terminalHostRef,
53
54
  terminalInstanceRef: consoleState.terminalInstanceRef,
55
+ onCopyAll: consoleState.onCopyAll,
54
56
  };
55
57
  };
@@ -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 {
4
4
  kNoDestinationSessionValue,
5
5
  useDestinationSessionSelection,
@@ -61,18 +61,18 @@ export const CreateWebhookModal = ({
61
61
  class="h-8 w-8 inline-flex items-center justify-center rounded-lg ac-btn-secondary"
62
62
  aria-label="Close modal"
63
63
  >
64
- <${CloseIcon} className="w-3.5 h-3.5 text-gray-300" />
64
+ <${CloseIcon} className="w-3.5 h-3.5 text-body" />
65
65
  </button>
66
66
  `}
67
67
  />
68
68
  <div class="space-y-2">
69
- <p class="text-xs text-gray-500">Endpoint mode</p>
69
+ <p class="text-xs text-fg-muted">Endpoint mode</p>
70
70
  <div class="flex items-center gap-2">
71
71
  <button
72
72
  class="text-xs px-2 py-1 rounded border transition-colors ${mode ===
73
73
  "webhook"
74
- ? "border-cyan-400 text-cyan-200 bg-cyan-400/10"
75
- : "border-border text-gray-400 hover:text-gray-200"}"
74
+ ? "border-cyan-400 text-status-info bg-cyan-400/10"
75
+ : "border-border text-fg-muted hover:text-body"}"
76
76
  onclick=${() => onModeChange("webhook")}
77
77
  >
78
78
  Webhook
@@ -80,8 +80,8 @@ export const CreateWebhookModal = ({
80
80
  <button
81
81
  class="text-xs px-2 py-1 rounded border transition-colors ${mode ===
82
82
  "oauth"
83
- ? "border-cyan-400 text-cyan-200 bg-cyan-400/10"
84
- : "border-border text-gray-400 hover:text-gray-200"}"
83
+ ? "border-cyan-400 text-status-info bg-cyan-400/10"
84
+ : "border-border text-fg-muted hover:text-body"}"
85
85
  onclick=${() => onModeChange("oauth")}
86
86
  >
87
87
  OAuth Callback
@@ -89,7 +89,7 @@ export const CreateWebhookModal = ({
89
89
  </div>
90
90
  </div>
91
91
  <div class="space-y-2">
92
- <p class="text-xs text-gray-500">Name</p>
92
+ <p class="text-xs text-fg-muted">Name</p>
93
93
  <input
94
94
  type="text"
95
95
  value=${name}
@@ -101,7 +101,7 @@ export const CreateWebhookModal = ({
101
101
  }
102
102
  if (e.key === "Escape") onClose();
103
103
  }}
104
- class="w-full bg-black/30 border border-border rounded-lg px-3 py-1.5 text-sm text-gray-200 outline-none focus:border-gray-500 font-mono"
104
+ class="w-full bg-field border border-border rounded-lg px-3 py-1.5 text-sm text-body outline-none focus:border-fg-muted font-mono"
105
105
  />
106
106
  </div>
107
107
  <${SessionSelectField}
@@ -122,20 +122,20 @@ export const CreateWebhookModal = ({
122
122
  <table class="w-full text-xs">
123
123
  <tbody>
124
124
  <tr class="border-b border-border">
125
- <td class="w-24 px-3 py-2 text-gray-500">Path</td>
126
- <td class="px-3 py-2 text-gray-300 font-mono">
125
+ <td class="w-24 px-3 py-2 text-fg-muted">Path</td>
126
+ <td class="px-3 py-2 text-body font-mono">
127
127
  <code>${previewPath}</code>
128
128
  </td>
129
129
  </tr>
130
130
  <tr class="border-b border-border">
131
- <td class="w-24 px-3 py-2 text-gray-500">URL</td>
132
- <td class="px-3 py-2 text-gray-300 font-mono break-all">
131
+ <td class="w-24 px-3 py-2 text-fg-muted">URL</td>
132
+ <td class="px-3 py-2 text-body font-mono break-all">
133
133
  <code>${previewUrl}</code>
134
134
  </td>
135
135
  </tr>
136
136
  <tr>
137
- <td class="w-24 px-3 py-2 text-gray-500">Transform</td>
138
- <td class="px-3 py-2 text-gray-300 font-mono">
137
+ <td class="w-24 px-3 py-2 text-fg-muted">Transform</td>
138
+ <td class="px-3 py-2 text-body font-mono">
139
139
  <code>hooks/transforms/${previewName}/${previewName}-transform.mjs</code>
140
140
  </td>
141
141
  </tr>
@@ -145,7 +145,7 @@ export const CreateWebhookModal = ({
145
145
  ${mode === "oauth"
146
146
  ? html`
147
147
  <div class="space-y-1">
148
- <p class="text-xs text-gray-500">
148
+ <p class="text-xs text-fg-muted">
149
149
  For OAuth providers that can't send auth headers. AlphaClaw
150
150
  injects webhook auth before forwarding to /hooks/{name}.
151
151
  </p>
@@ -32,18 +32,18 @@ export const getRequestStatusTone = (status) => {
32
32
  if (status === "success") {
33
33
  return {
34
34
  dotClass: "bg-green-500/90",
35
- textClass: "text-green-500/90",
35
+ textClass: "text-status-success-muted/90",
36
36
  };
37
37
  }
38
38
  if (status === "error") {
39
39
  return {
40
40
  dotClass: "bg-red-500/90",
41
- textClass: "text-red-500/90",
41
+ textClass: "text-status-error-muted",
42
42
  };
43
43
  }
44
44
  return {
45
45
  dotClass: "bg-gray-500/70",
46
- textClass: "text-gray-400",
46
+ textClass: "text-fg-muted",
47
47
  };
48
48
  };
49
49
 
@@ -1,6 +1,6 @@
1
- import { h } from "https://esm.sh/preact";
2
- import { useCallback, useMemo, useState } from "https://esm.sh/preact/hooks";
3
- import htm from "https://esm.sh/htm";
1
+ import { h } from "preact";
2
+ import { useCallback, useMemo, useState } from "preact/hooks";
3
+ import htm from "htm";
4
4
  import { createWebhook } from "../../lib/api.js";
5
5
  import { ActionButton } from "../action-button.js";
6
6
  import { PageHeader } from "../page-header.js";
@@ -79,7 +79,7 @@ export const Webhooks = ({
79
79
  leading=${selectedHookName
80
80
  ? html`
81
81
  <button
82
- class="flex items-center gap-1.5 text-sm text-gray-500 hover:text-gray-300 transition-colors"
82
+ class="flex items-center gap-1.5 text-sm text-fg-muted hover:text-body transition-colors"
83
83
  onclick=${onBackToList}
84
84
  >
85
85
  <svg
@@ -1,6 +1,6 @@
1
- import { h } from "https://esm.sh/preact";
2
- import { useMemo } from "https://esm.sh/preact/hooks";
3
- import htm from "https://esm.sh/htm";
1
+ import { h } from "preact";
2
+ import { useMemo } from "preact/hooks";
3
+ import htm from "htm";
4
4
  import { sendAgentMessage } from "../../../lib/api.js";
5
5
  import { ActionButton } from "../../action-button.js";
6
6
  import { AgentSendModal } from "../../agent-send-modal.js";
@@ -63,8 +63,8 @@ export const RequestHistory = ({
63
63
  (filter) => html`
64
64
  <button
65
65
  class="text-xs px-2 py-1 rounded border ${statusFilter === filter
66
- ? "border-cyan-400 text-cyan-200 bg-cyan-400/10"
67
- : "border-border text-gray-400 hover:text-gray-200"}"
66
+ ? "border-cyan-400 text-status-info bg-cyan-400/10"
67
+ : "border-border text-fg-muted hover:text-body"}"
68
68
  onclick=${() => actions.handleSetStatusFilter(filter)}
69
69
  >
70
70
  ${filter}
@@ -75,7 +75,7 @@ export const RequestHistory = ({
75
75
  </div>
76
76
 
77
77
  ${requests.length === 0
78
- ? html`<p class="text-sm text-gray-500">No requests logged yet.</p>`
78
+ ? html`<p class="text-sm text-fg-muted">No requests logged yet.</p>`
79
79
  : html`
80
80
  <div class="ac-history-list">
81
81
  ${requests.map((item) => {
@@ -93,12 +93,12 @@ export const RequestHistory = ({
93
93
  <span class="ac-history-toggle shrink-0" aria-hidden="true"
94
94
  >▸</span
95
95
  >
96
- <span class="truncate text-xs text-gray-300">
96
+ <span class="truncate text-xs text-body">
97
97
  ${formatLastReceived(item.createdAt)}
98
98
  </span>
99
99
  </span>
100
100
  <span class="inline-flex items-center gap-2 shrink-0">
101
- <span class="text-xs text-gray-500"
101
+ <span class="text-xs text-fg-muted"
102
102
  >${formatBytes(item.payloadSize)}</span
103
103
  >
104
104
  <span class=${`text-xs font-medium ${statusTone.textClass}`}
@@ -118,9 +118,9 @@ export const RequestHistory = ({
118
118
  ? html`
119
119
  <div class="ac-history-body space-y-3">
120
120
  <div>
121
- <p class="text-[11px] text-gray-500 mb-1">Headers</p>
121
+ <p class="text-[11px] text-fg-muted mb-1">Headers</p>
122
122
  <pre
123
- class="text-xs bg-black/30 border border-border rounded p-2 overflow-auto"
123
+ class="text-xs bg-field border border-border rounded p-2 overflow-auto"
124
124
  >
125
125
  ${jsonPretty(item.headers)}</pre
126
126
  >
@@ -138,11 +138,11 @@ ${jsonPretty(item.headers)}</pre
138
138
  </div>
139
139
  </div>
140
140
  <div>
141
- <p class="text-[11px] text-gray-500 mb-1">
141
+ <p class="text-[11px] text-fg-muted mb-1">
142
142
  Payload ${item.payloadTruncated ? "(truncated)" : ""}
143
143
  </p>
144
144
  <pre
145
- class="text-xs bg-black/30 border border-border rounded p-2 overflow-auto"
145
+ class="text-xs bg-field border border-border rounded p-2 overflow-auto"
146
146
  >
147
147
  ${jsonPretty(item.payload)}</pre
148
148
  >
@@ -173,11 +173,11 @@ ${jsonPretty(item.payload)}</pre
173
173
  </div>
174
174
  </div>
175
175
  <div>
176
- <p class="text-[11px] text-gray-500 mb-1">
176
+ <p class="text-[11px] text-fg-muted mb-1">
177
177
  Gateway response (${item.gatewayStatus || "n/a"})
178
178
  </p>
179
179
  <pre
180
- class="text-xs bg-black/30 border border-border rounded p-2 overflow-auto"
180
+ class="text-xs bg-field border border-border rounded p-2 overflow-auto"
181
181
  >
182
182
  ${jsonPretty(item.gatewayBody)}</pre
183
183
  >
@@ -1,4 +1,4 @@
1
- import { useCallback, useEffect, useMemo, useState } from "https://esm.sh/preact/hooks";
1
+ import { useCallback, useEffect, useMemo, useState } from "preact/hooks";
2
2
  import {
3
3
  fetchWebhookRequest,
4
4
  fetchWebhookRequests,