@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
@@ -1,4 +1,4 @@
1
- import { useCallback } from "https://esm.sh/preact/hooks";
1
+ import { useCallback } from "preact/hooks";
2
2
  import { usePolling } from "../../../hooks/usePolling.js";
3
3
  import { fetchWebhooks } from "../../../lib/api.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 { kWelcomeGroups } from "../onboarding/welcome-config.js";
4
4
  import { WelcomePreStep } from "../onboarding/welcome-pre-step.js";
5
5
  import { WelcomeImportStep } from "../onboarding/welcome-import-step.js";
@@ -114,7 +114,7 @@ export const Welcome = ({ onComplete, acVersion }) => {
114
114
  </div>
115
115
  ${acVersion
116
116
  ? html`
117
- <div class="text-center text-xs text-gray-500 font-mono mt-8">
117
+ <div class="text-center text-xs text-fg-muted font-mono mt-8">
118
118
  v${acVersion}
119
119
  </div>
120
120
  `
@@ -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
  runOnboard,
4
4
  verifyGithubOnboardingRepo,
@@ -8,8 +8,10 @@ import {
8
8
  } from "../../lib/api.js";
9
9
  import {
10
10
  getModelProvider,
11
+ getAuthProviderFromModelProvider,
11
12
  getFeaturedModels,
12
13
  getVisibleAiFieldKeys,
14
+ kProviderAuthFields,
13
15
  } from "../../lib/model-config.js";
14
16
  import {
15
17
  kWelcomeGroups,
@@ -162,16 +164,14 @@ export const useWelcome = ({ onComplete }) => {
162
164
  const canToggleFullCatalog =
163
165
  featuredModels.length > 0 && models.length > featuredModels.length;
164
166
  const visibleAiFieldKeys = getVisibleAiFieldKeys(selectedProvider);
167
+ const selectedAuthProvider = getAuthProviderFromModelProvider(selectedProvider);
168
+ const selectedProviderAuthFields = kProviderAuthFields[selectedAuthProvider] || [];
165
169
  const hasAi =
166
- selectedProvider === "anthropic"
167
- ? !!(vals.ANTHROPIC_API_KEY || vals.ANTHROPIC_TOKEN)
168
- : selectedProvider === "openai"
169
- ? !!vals.OPENAI_API_KEY
170
- : selectedProvider === "google"
171
- ? !!vals.GEMINI_API_KEY
172
- : selectedProvider === "openai-codex"
173
- ? !!codexStatus.connected
174
- : false;
170
+ selectedProvider === "openai-codex"
171
+ ? !!codexStatus.connected
172
+ : selectedProviderAuthFields.some(
173
+ (field) => !!String(vals[field.key] || "").trim(),
174
+ );
175
175
 
176
176
  const allValid = kWelcomeGroups.every((group) => group.validate(vals, { hasAi }));
177
177
  const isPreStep = step === -1;
@@ -1,4 +1,4 @@
1
- import { useState, useEffect, useCallback } from "https://esm.sh/preact/hooks";
1
+ import { useState, useEffect, useCallback } from "preact/hooks";
2
2
  import {
3
3
  fetchStatus,
4
4
  fetchOnboardStatus,
@@ -18,6 +18,7 @@ import { usePolling } from "./usePolling.js";
18
18
  import { showToast } from "../components/toast.js";
19
19
 
20
20
  export const useAppShellController = ({ location = "" } = {}) => {
21
+ const kInitialStatusPollDelayMs = 5000;
21
22
  const [onboarded, setOnboarded] = useState(null);
22
23
  const [authEnabled, setAuthEnabled] = useState(false);
23
24
  const [acVersion, setAcVersion] = useState(null);
@@ -29,6 +30,7 @@ export const useAppShellController = ({ location = "" } = {}) => {
29
30
  const [restartingGateway, setRestartingGateway] = useState(false);
30
31
  const [gatewayRestartSignal, setGatewayRestartSignal] = useState(0);
31
32
  const [statusPollCadenceMs, setStatusPollCadenceMs] = useState(15000);
33
+ const [statusPollingGraceElapsed, setStatusPollingGraceElapsed] = useState(false);
32
34
  const [openclawUpdateInProgress, setOpenclawUpdateInProgress] = useState(false);
33
35
  const [statusStreamConnected, setStatusStreamConnected] = useState(false);
34
36
  const [statusStreamStatus, setStatusStreamStatus] = useState(null);
@@ -36,15 +38,18 @@ export const useAppShellController = ({ location = "" } = {}) => {
36
38
  const [statusStreamDoctor, setStatusStreamDoctor] = useState(null);
37
39
 
38
40
  const sharedStatusPoll = usePolling(fetchStatus, statusPollCadenceMs, {
39
- enabled: onboarded === true && !statusStreamConnected,
41
+ enabled:
42
+ onboarded === true && !statusStreamConnected && statusPollingGraceElapsed,
40
43
  cacheKey: "/api/status",
41
44
  });
42
45
  const sharedWatchdogPoll = usePolling(fetchWatchdogStatus, statusPollCadenceMs, {
43
- enabled: onboarded === true && !statusStreamConnected,
46
+ enabled:
47
+ onboarded === true && !statusStreamConnected && statusPollingGraceElapsed,
44
48
  cacheKey: "/api/watchdog/status",
45
49
  });
46
50
  const sharedDoctorPoll = usePolling(fetchDoctorStatus, statusPollCadenceMs, {
47
- enabled: onboarded === true && !statusStreamConnected,
51
+ enabled:
52
+ onboarded === true && !statusStreamConnected && statusPollingGraceElapsed,
48
53
  cacheKey: "/api/doctor/status",
49
54
  });
50
55
  const sharedStatus = statusStreamStatus || sharedStatusPoll.data || null;
@@ -69,6 +74,19 @@ export const useAppShellController = ({ location = "" } = {}) => {
69
74
  .catch(() => {});
70
75
  }, []);
71
76
 
77
+ useEffect(() => {
78
+ if (onboarded !== true) {
79
+ setStatusPollingGraceElapsed(false);
80
+ return () => {};
81
+ }
82
+ const timerId = setTimeout(() => {
83
+ setStatusPollingGraceElapsed(true);
84
+ }, kInitialStatusPollDelayMs);
85
+ return () => {
86
+ clearTimeout(timerId);
87
+ };
88
+ }, [onboarded]);
89
+
72
90
  useEffect(() => {
73
91
  if (onboarded !== true) return;
74
92
  let disposed = false;
@@ -1,4 +1,4 @@
1
- import { useState, useEffect, useRef, useCallback } from "https://esm.sh/preact/hooks";
1
+ import { useState, useEffect, useRef, useCallback } from "preact/hooks";
2
2
  import { readUiSettings, writeUiSettings } from "../lib/ui-settings.js";
3
3
 
4
4
  const kDefaultSidebarWidthPx = 220;
@@ -1,4 +1,4 @@
1
- import { useState, useEffect, useRef, useCallback } from "https://esm.sh/preact/hooks";
1
+ import { useState, useEffect, useRef, useCallback } from "preact/hooks";
2
2
  import { readUiSettings, writeUiSettings } from "../lib/ui-settings.js";
3
3
  import { kDefaultUiTab, getSelectedNavId, kNavSections } from "../lib/app-navigation.js";
4
4
  import { buildBrowseRoute, normalizeBrowsePath, parseBrowseRoute } from "../lib/browse-route.js";
@@ -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 { cachedFetch, getCached } from "../lib/api-cache.js";
3
3
 
4
4
  export const useCachedFetch = (
@@ -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 { useAgentSessions } from "./useAgentSessions.js";
3
3
  import {
4
4
  getDestinationFromSession,
@@ -1,4 +1,4 @@
1
- import { useState, useEffect, useCallback } from "https://esm.sh/preact/hooks";
1
+ import { useState, useEffect, useCallback } from "preact/hooks";
2
2
  import { kDefaultUiTab } from "../lib/app-navigation.js";
3
3
 
4
4
  const getHashPath = () => {
@@ -1,4 +1,4 @@
1
- import { useState, useEffect, useMemo, useCallback } from "https://esm.sh/preact/hooks";
1
+ import { useState, useEffect, useMemo, useCallback } from "preact/hooks";
2
2
  import { fetchAgentSessions } from "../lib/api.js";
3
3
  import {
4
4
  kAgentSessionsCacheKey,
@@ -1,4 +1,4 @@
1
- import { useState, useEffect, useCallback, useRef } from "https://esm.sh/preact/hooks";
1
+ import { useState, useEffect, useCallback, useRef } from "preact/hooks";
2
2
  import { getCached, setCached } from "../lib/api-cache.js";
3
3
 
4
4
  export const usePolling = (
@@ -0,0 +1,39 @@
1
+ // Shared Tailwind config — remaps color palette to CSS variables
2
+ // so themes can override colors without touching component files.
3
+ tailwind.config = {
4
+ theme: {
5
+ extend: {
6
+ colors: {
7
+ surface: "var(--bg-sidebar)",
8
+ border: "var(--border)",
9
+ body: "var(--text)",
10
+ bright: "var(--text-bright)",
11
+ "fg-muted": "var(--text-muted)",
12
+ "fg-dim": "var(--text-dim)",
13
+ field: "var(--field-bg-contrast)",
14
+ overlay: "var(--overlay)",
15
+ status: {
16
+ error: "var(--status-error)",
17
+ "error-muted": "var(--status-error-muted)",
18
+ "error-bg": "var(--status-error-bg)",
19
+ "error-border": "var(--status-error-border)",
20
+ warning: "var(--status-warning)",
21
+ "warning-muted": "var(--status-warning-muted)",
22
+ "warning-bg": "var(--status-warning-bg)",
23
+ "warning-border": "var(--status-warning-border)",
24
+ success: "var(--status-success)",
25
+ "success-muted": "var(--status-success-muted)",
26
+ "success-bg": "var(--status-success-bg)",
27
+ "success-border": "var(--status-success-border)",
28
+ info: "var(--status-info)",
29
+ "info-muted": "var(--status-info-muted)",
30
+ "info-bg": "var(--status-info-bg)",
31
+ "info-border": "var(--status-info-border)",
32
+ },
33
+ },
34
+ fontFamily: {
35
+ mono: ["'JetBrains Mono'", "monospace"],
36
+ },
37
+ },
38
+ },
39
+ };
@@ -10,22 +10,7 @@
10
10
  />
11
11
  <link rel="icon" type="image/svg+xml" href="./img/logo.svg" />
12
12
  <link rel="stylesheet" href="./css/theme.css" />
13
- <script src="https://cdn.tailwindcss.com"></script>
14
- <script>
15
- tailwind.config = {
16
- theme: {
17
- extend: {
18
- colors: {
19
- surface: "var(--bg-sidebar)",
20
- border: "var(--border)",
21
- },
22
- fontFamily: {
23
- mono: ["'JetBrains Mono'", "monospace"],
24
- },
25
- },
26
- },
27
- };
28
- </script>
13
+ <link rel="stylesheet" href="./css/tailwind.generated.css" />
29
14
  </head>
30
15
  <body class="min-h-screen flex items-center justify-center p-4">
31
16
  <div class="max-w-sm w-full relative z-10">
@@ -53,10 +38,10 @@
53
38
  type="password"
54
39
  placeholder="Password"
55
40
  autofocus
56
- class="w-full bg-black/30 border border-border rounded-lg px-3 py-2 text-sm outline-none focus:border-gray-500"
41
+ class="w-full bg-field border border-border rounded-lg px-3 py-2 text-sm outline-none focus:border-fg-muted"
57
42
  style="color: var(--text)"
58
43
  />
59
- <div id="error" class="text-red-400 text-xs hidden"></div>
44
+ <div id="error" class="text-status-error-muted text-xs hidden"></div>
60
45
  <button
61
46
  id="submit-btn"
62
47
  type="submit"
@@ -10,30 +10,14 @@
10
10
  />
11
11
  <link rel="icon" type="image/svg+xml" href="./img/logo.svg" />
12
12
  <link rel="stylesheet" href="./css/theme.css" />
13
+ <link rel="stylesheet" href="./css/tailwind.generated.css" />
13
14
  <link rel="stylesheet" href="./css/shell.css" />
14
15
  <link rel="stylesheet" href="./css/explorer.css" />
15
16
  <link rel="stylesheet" href="./css/agents.css" />
16
17
  <link rel="stylesheet" href="./css/cron.css" />
17
- <script src="https://cdn.tailwindcss.com"></script>
18
- <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
19
- <script>
20
- tailwind.config = {
21
- theme: {
22
- extend: {
23
- colors: {
24
- surface: "var(--bg-sidebar)",
25
- border: "var(--border)",
26
- },
27
- fontFamily: {
28
- mono: ["'JetBrains Mono'", "monospace"],
29
- },
30
- },
31
- },
32
- };
33
- </script>
34
18
  </head>
35
19
  <body>
36
20
  <div id="app"></div>
37
- <script type="module" src="./js/app.js"></script>
21
+ <script type="module" src="./dist/app.bundle.js"></script>
38
22
  </body>
39
23
  </html>
@@ -68,6 +68,7 @@ const registerServerRoutes = ({
68
68
  deleteOauthCallback,
69
69
  markOauthCallbackUsed,
70
70
  watchdog,
71
+ watchdogNotifier,
71
72
  getRecentEvents,
72
73
  readLogTail,
73
74
  watchdogTerminal,
@@ -212,6 +213,7 @@ const registerServerRoutes = ({
212
213
  app,
213
214
  requireAuth,
214
215
  watchdog,
216
+ watchdogNotifier,
215
217
  getRecentEvents,
216
218
  readLogTail,
217
219
  watchdogTerminal,
@@ -31,6 +31,38 @@ const parseGithubErrorMessage = async (response) => {
31
31
  return response.statusText || `HTTP ${response.status}`;
32
32
  };
33
33
 
34
+ // Files GitHub may auto-create when initializing a repo — a repo containing
35
+ // only these is treated as empty for onboarding purposes.
36
+ const kBoilerplateNames = new Set([
37
+ "readme",
38
+ "readme.md",
39
+ "readme.txt",
40
+ "readme.rst",
41
+ "license",
42
+ "license.md",
43
+ "license.txt",
44
+ ".gitignore",
45
+ ".gitattributes",
46
+ ]);
47
+
48
+ const repoContainsOnlyBoilerplate = async (repoUrl, ghHeaders) => {
49
+ try {
50
+ const res = await fetch(
51
+ `https://api.github.com/repos/${repoUrl}/contents/`,
52
+ { headers: ghHeaders },
53
+ );
54
+ if (!res.ok) return false;
55
+ const entries = await res.json();
56
+ if (!Array.isArray(entries)) return false;
57
+ if (entries.length === 0) return true;
58
+ return entries.every(
59
+ (e) => e.type === "file" && kBoilerplateNames.has(e.name.toLowerCase()),
60
+ );
61
+ } catch {
62
+ return false;
63
+ }
64
+ };
65
+
34
66
  const isClassicPat = (token) => String(token || "").startsWith("ghp_");
35
67
  const isFineGrainedPat = (token) =>
36
68
  String(token || "").startsWith("github_pat_");
@@ -98,6 +130,13 @@ const verifyGithubRepoForOnboarding = async ({
98
130
  return { ok: true, repoExists: true, repoIsEmpty: true };
99
131
  }
100
132
  if (commitsRes.ok) {
133
+ const onlyBoilerplate = await repoContainsOnlyBoilerplate(
134
+ repoUrl,
135
+ ghHeaders,
136
+ );
137
+ if (onlyBoilerplate) {
138
+ return { ok: true, repoExists: true, repoIsEmpty: true };
139
+ }
101
140
  if (isExisting) {
102
141
  return { ok: true, repoExists: true, repoIsEmpty: false };
103
142
  }
@@ -7,9 +7,11 @@ const kAllowedExecHosts = new Set(["gateway", "node"]);
7
7
  const kAllowedExecSecurity = new Set(["deny", "allowlist", "full"]);
8
8
  const kAllowedExecAsk = new Set(["off", "on-miss", "always"]);
9
9
  const kSafeNodeIdPattern = /^[\w\-:.]+$/;
10
- const kNodeBrowserInvokeTimeoutMs = 15000;
11
- const kNodeBrowserCliTimeoutMs = 18000;
10
+ const kNodeBrowserInvokeTimeoutMs = 30000;
11
+ const kNodeBrowserCliTimeoutMs = 35000;
12
12
  const kNodeRouteCliTimeoutMs = 12000;
13
+ const kNodesStatusCliTimeoutMs = 5000;
14
+ const kNodesPendingCliTimeoutMs = 5000;
13
15
 
14
16
  const quoteCliArg = (value) => quoteShellArg(value, { strategy: "single" });
15
17
 
@@ -172,7 +174,10 @@ const registerNodeRoutes = ({
172
174
  fsModule,
173
175
  }) => {
174
176
  app.get("/api/nodes", async (_req, res) => {
175
- const statusResult = await clawCmd("nodes status --json", { quiet: true });
177
+ const statusResult = await clawCmd("nodes status --json", {
178
+ quiet: true,
179
+ timeoutMs: kNodesStatusCliTimeoutMs,
180
+ });
176
181
  if (!statusResult.ok) {
177
182
  return res.status(500).json({
178
183
  ok: false,
@@ -180,7 +185,10 @@ const registerNodeRoutes = ({
180
185
  });
181
186
  }
182
187
  const status = parseNodesStatus(statusResult.stdout);
183
- const pendingResult = await clawCmd("nodes pending --json", { quiet: true });
188
+ const pendingResult = await clawCmd("nodes pending --json", {
189
+ quiet: true,
190
+ timeoutMs: kNodesPendingCliTimeoutMs,
191
+ });
184
192
  const pending = pendingResult.ok
185
193
  ? parseNodesPending(pendingResult.stdout)
186
194
  : status.pending;
@@ -7,6 +7,7 @@ const { quoteShellArg } = require("../utils/shell");
7
7
 
8
8
  const kAllowedPairingChannels = new Set(["telegram", "discord", "slack"]);
9
9
  const kSafePairingArgPattern = /^[\w\-:.]+$/;
10
+ const kDevicesListCliTimeoutMs = 5000;
10
11
  const quoteCliArg = (value) => quoteShellArg(value, { strategy: "single" });
11
12
 
12
13
  const resolvePairingStorePath = ({ openclawDir, channel }) =>
@@ -208,7 +209,10 @@ const registerPairingRoutes = ({ app, clawCmd, isOnboarded, fsModule = fs, openc
208
209
  cliAutoApproveComplete: devicePairingCache.cliAutoApproveComplete,
209
210
  });
210
211
  }
211
- const result = await clawCmd("devices list --json", { quiet: true });
212
+ const result = await clawCmd("devices list --json", {
213
+ quiet: true,
214
+ timeoutMs: kDevicesListCliTimeoutMs,
215
+ });
212
216
  if (!result.ok) {
213
217
  return res.json({ pending: [], cliAutoApproveComplete: hasCliAutoApproveMarker() });
214
218
  }
@@ -532,6 +532,10 @@ const registerSystemRoutes = ({
532
532
  const running = await isGatewayRunning();
533
533
  const repo = process.env.GITHUB_WORKSPACE_REPO || "";
534
534
  const openclawVersion = openclawVersionService.readOpenclawVersion();
535
+ const alphaclawVersion =
536
+ typeof alphaclawVersionService?.readAlphaclawVersion === "function"
537
+ ? alphaclawVersionService.readAlphaclawVersion()
538
+ : null;
535
539
  return {
536
540
  gateway: running
537
541
  ? "running"
@@ -542,6 +546,7 @@ const registerSystemRoutes = ({
542
546
  channels: getChannelStatus(),
543
547
  repo,
544
548
  openclawVersion,
549
+ alphaclawVersion,
545
550
  syncCron: getSystemCronStatus(),
546
551
  };
547
552
  };
@@ -4,6 +4,7 @@ const registerWatchdogRoutes = ({
4
4
  app,
5
5
  requireAuth,
6
6
  watchdog,
7
+ watchdogNotifier,
7
8
  getRecentEvents,
8
9
  readLogTail,
9
10
  watchdogTerminal,
@@ -76,6 +77,20 @@ const registerWatchdogRoutes = ({
76
77
  }
77
78
  });
78
79
 
80
+ app.post("/api/watchdog/test-notification", requireAuth, async (req, res) => {
81
+ try {
82
+ if (!watchdogNotifier?.notify) {
83
+ return res.status(503).json({ ok: false, error: "Notifier not available" });
84
+ }
85
+ const result = await watchdogNotifier.notify(
86
+ "*AlphaClaw test notification* — your watchdog alerts are working.",
87
+ );
88
+ res.json({ ok: true, result });
89
+ } catch (err) {
90
+ res.status(500).json({ ok: false, error: err.message });
91
+ }
92
+ });
93
+
79
94
  app.post("/api/watchdog/terminal/session", requireAuth, (req, res) => {
80
95
  try {
81
96
  const terminalSession = watchdogTerminal.createOrReuseSession();