@chrysb/alphaclaw 0.8.8 → 0.8.10

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 (31) hide show
  1. package/bin/alphaclaw.js +43 -174
  2. package/lib/public/css/tailwind.generated.css +1 -1
  3. package/lib/public/dist/app.bundle.js +2089 -2109
  4. package/lib/public/js/app.js +0 -3
  5. package/lib/public/js/components/gateway.js +3 -6
  6. package/lib/public/js/components/general/index.js +0 -2
  7. package/lib/public/js/components/onboarding/welcome-form-step.js +4 -29
  8. package/lib/public/js/components/routes/general-route.js +0 -2
  9. package/lib/public/js/components/routes/watchdog-route.js +0 -2
  10. package/lib/public/js/components/sidebar.js +7 -20
  11. package/lib/public/js/components/update-modal.js +1 -2
  12. package/lib/public/js/components/watchdog-tab/index.js +0 -2
  13. package/lib/public/js/components/welcome/index.js +0 -1
  14. package/lib/public/js/components/welcome/use-welcome.js +2 -52
  15. package/lib/public/js/hooks/use-app-shell-controller.js +9 -37
  16. package/lib/public/js/lib/api.js +0 -36
  17. package/lib/server/alphaclaw-version.js +128 -37
  18. package/lib/server/gateway.js +14 -32
  19. package/lib/server/init/register-server-routes.js +1 -7
  20. package/lib/server/openclaw-version.js +136 -76
  21. package/lib/server/routes/pages.js +1 -9
  22. package/lib/server/routes/system.js +1 -6
  23. package/lib/server/usage-tracker-config.js +3 -27
  24. package/package.json +1 -2
  25. package/lib/public/js/components/update-modal-helpers.js +0 -12
  26. package/lib/release/managed-release.js +0 -180
  27. package/lib/server/alphaclaw-runtime.js +0 -294
  28. package/lib/server/openclaw-runtime.js +0 -428
  29. package/lib/server/package-fingerprint.js +0 -274
  30. package/lib/server/pending-alphaclaw-update.js +0 -85
  31. package/lib/server/pending-openclaw-update.js +0 -86
@@ -202,7 +202,6 @@ const App = () => {
202
202
  onPreviewBrowseFile=${browseActions.handleBrowsePreviewFile}
203
203
  acHasUpdate=${controllerState.acHasUpdate}
204
204
  acLatest=${controllerState.acLatest}
205
- acRestarting=${controllerState.acRestarting}
206
205
  acUpdating=${controllerState.acUpdating}
207
206
  onAcUpdate=${controllerActions.handleAcUpdate}
208
207
  agents=${agentsState.agents}
@@ -385,7 +384,6 @@ const App = () => {
385
384
  restartingGateway=${controllerState.restartingGateway}
386
385
  onRestartGateway=${controllerActions.handleGatewayRestart}
387
386
  restartSignal=${controllerState.gatewayRestartSignal}
388
- openclawRestarting=${controllerState.openclawRestarting}
389
387
  openclawUpdateInProgress=${controllerState.openclawUpdateInProgress}
390
388
  onOpenclawVersionActionComplete=${controllerActions.handleOpenclawVersionActionComplete}
391
389
  onOpenclawUpdate=${controllerActions.handleOpenclawUpdate}
@@ -421,7 +419,6 @@ const App = () => {
421
419
  restartingGateway=${controllerState.restartingGateway}
422
420
  onRestartGateway=${controllerActions.handleGatewayRestart}
423
421
  restartSignal=${controllerState.gatewayRestartSignal}
424
- openclawRestarting=${controllerState.openclawRestarting}
425
422
  openclawUpdateInProgress=${controllerState.openclawUpdateInProgress}
426
423
  onOpenclawVersionActionComplete=${controllerActions.handleOpenclawVersionActionComplete}
427
424
  onOpenclawUpdate=${controllerActions.handleOpenclawUpdate}
@@ -27,7 +27,6 @@ const VersionRow = ({
27
27
  fetchVersion,
28
28
  applyUpdate,
29
29
  updateInProgress = false,
30
- updateLoadingLabel = "Updating...",
31
30
  onActionComplete = () => {},
32
31
  }) => {
33
32
  const [checking, setChecking] = useState(false);
@@ -237,7 +236,7 @@ const VersionRow = ({
237
236
  ? updateIdleLabel
238
237
  : "Check updates"}
239
238
  loadingLabel=${isUpdateActionActive
240
- ? updateLoadingLabel
239
+ ? "Updating..."
241
240
  : "Checking..."}
242
241
  className="hidden md:inline-flex"
243
242
  />
@@ -251,7 +250,7 @@ const VersionRow = ({
251
250
  ? updateIdleLabel
252
251
  : "Check updates"}
253
252
  loadingLabel=${isUpdateActionActive
254
- ? updateLoadingLabel
253
+ ? "Updating..."
255
254
  : "Checking..."}
256
255
  />
257
256
  `}
@@ -273,7 +272,7 @@ const VersionRow = ({
273
272
  loading=${updateButtonLoading}
274
273
  warning=${isUpdateActionActive}
275
274
  idleLabel=${updateIdleLabel}
276
- loadingLabel=${updateLoadingLabel}
275
+ loadingLabel="Updating..."
277
276
  className="flex-1 h-9 px-3"
278
277
  />
279
278
  </div>
@@ -300,7 +299,6 @@ export const Gateway = ({
300
299
  onOpenWatchdog,
301
300
  onRepair,
302
301
  repairing = false,
303
- openclawRestarting = false,
304
302
  openclawUpdateInProgress = false,
305
303
  onOpenclawVersionActionComplete = () => {},
306
304
  onOpenclawUpdate = updateOpenclaw,
@@ -445,7 +443,6 @@ export const Gateway = ({
445
443
  fetchVersion=${fetchOpenclawVersion}
446
444
  applyUpdate=${onOpenclawUpdate}
447
445
  updateInProgress=${openclawUpdateInProgress}
448
- updateLoadingLabel=${openclawRestarting ? "Restarting..." : "Updating..."}
449
446
  onActionComplete=${onOpenclawVersionActionComplete}
450
447
  />
451
448
  </div>
@@ -28,7 +28,6 @@ export const GeneralTab = ({
28
28
  restartingGateway = false,
29
29
  onRestartGateway = () => {},
30
30
  restartSignal = 0,
31
- openclawRestarting = false,
32
31
  openclawUpdateInProgress = false,
33
32
  onOpenclawVersionActionComplete = () => {},
34
33
  onOpenclawUpdate = () => {},
@@ -55,7 +54,6 @@ export const GeneralTab = ({
55
54
  onOpenWatchdog=${() => onSwitchTab("watchdog")}
56
55
  onRepair=${actions.handleWatchdogRepair}
57
56
  repairing=${state.repairingWatchdog}
58
- openclawRestarting=${openclawRestarting}
59
57
  openclawUpdateInProgress=${openclawUpdateInProgress}
60
58
  onOpenclawVersionActionComplete=${onOpenclawVersionActionComplete}
61
59
  onOpenclawUpdate=${onOpenclawUpdate}
@@ -50,7 +50,6 @@ export const WelcomeFormStep = ({
50
50
  error,
51
51
  step,
52
52
  totalGroups,
53
- importApplied,
54
53
  goBack,
55
54
  goNext,
56
55
  loading,
@@ -89,28 +88,18 @@ export const WelcomeFormStep = ({
89
88
  });
90
89
  }, [activeGroup.id]);
91
90
 
92
- const renderStandardField = (field) => {
93
- const isLockedImportSourceField =
94
- activeGroup.id === "github" &&
95
- githubFlow === kGithubFlowImport &&
96
- importApplied &&
97
- field.key === "_GITHUB_SOURCE_REPO";
98
-
99
- return html`
91
+ const renderStandardField = (field) => html`
100
92
  <div class="space-y-1" key=${field.key}>
101
93
  <label class="text-xs font-medium text-fg-muted">${field.label}</label>
102
94
  <${SecretInput}
103
95
  key=${field.key}
104
96
  value=${vals[field.key] || ""}
105
97
  onInput=${(e) => setValue(field.key, e.target.value)}
106
- disabled=${isLockedImportSourceField}
107
98
  placeholder=${activeGroup.id === "github" && field.key === "GITHUB_TOKEN"
108
99
  ? githubTokenPlaceholder
109
100
  : field.placeholder || ""}
110
101
  isSecret=${!field.isText}
111
- inputClass=${`flex-1 bg-field border border-border rounded-lg px-3 py-2 text-sm text-body outline-none focus:border-fg-muted font-mono ${
112
- isLockedImportSourceField ? "opacity-60 cursor-not-allowed" : ""
113
- }`}
102
+ inputClass="flex-1 bg-field border border-border rounded-lg px-3 py-2 text-sm text-body outline-none focus:border-fg-muted font-mono"
114
103
  />
115
104
  <p class="text-xs text-fg-dim">
116
105
  ${activeGroup.id === "github" &&
@@ -121,9 +110,7 @@ export const WelcomeFormStep = ({
121
110
  ? "Enter the owner/repo of an existing empty repository"
122
111
  : "A new private repo will be created for you"
123
112
  : activeGroup.id === "github" && field.key === "_GITHUB_SOURCE_REPO"
124
- ? importApplied
125
- ? "This source repo is already imported locally. You can still change the target repo below."
126
- : "The repo to import from"
113
+ ? "The repo to import from"
127
114
  : activeGroup.id === "github" && field.key === "GITHUB_TOKEN"
128
115
  ? githubFlow === kGithubFlowImport
129
116
  ? freshRepoMode === kGithubTargetRepoModeCreate
@@ -152,8 +139,7 @@ export const WelcomeFormStep = ({
152
139
  : field.hint}
153
140
  </p>
154
141
  </div>
155
- `;
156
- };
142
+ `;
157
143
  const fieldLookup = new Map((activeGroup.fields || []).map((field) => [field.key, field]));
158
144
  const toggleChannelSection = (channelId) =>
159
145
  setExpandedChannels((current) => {
@@ -341,17 +327,6 @@ export const WelcomeFormStep = ({
341
327
  ${activeGroup.id === "github" &&
342
328
  html`
343
329
  <div class="space-y-3">
344
- ${githubFlow === kGithubFlowImport && importApplied
345
- ? html`
346
- <div
347
- class="bg-status-info-bg border border-status-info-border rounded-lg p-3 text-xs text-status-info"
348
- >
349
- The import source is already applied locally. You can still
350
- change the target repo before finishing setup, but we will not
351
- re-import the source repo a second time.
352
- </div>
353
- `
354
- : null}
355
330
  ${githubFlow === kGithubFlowFresh
356
331
  ? html`
357
332
  <div class="space-y-1">
@@ -16,7 +16,6 @@ export const GeneralRoute = ({
16
16
  restartingGateway = false,
17
17
  onRestartGateway = () => {},
18
18
  restartSignal = 0,
19
- openclawRestarting = false,
20
19
  openclawUpdateInProgress = false,
21
20
  onOpenclawVersionActionComplete = () => {},
22
21
  onOpenclawUpdate = () => {},
@@ -38,7 +37,6 @@ export const GeneralRoute = ({
38
37
  restartingGateway=${restartingGateway}
39
38
  onRestartGateway=${onRestartGateway}
40
39
  restartSignal=${restartSignal}
41
- openclawRestarting=${openclawRestarting}
42
40
  openclawUpdateInProgress=${openclawUpdateInProgress}
43
41
  onOpenclawVersionActionComplete=${onOpenclawVersionActionComplete}
44
42
  onOpenclawUpdate=${onOpenclawUpdate}
@@ -11,7 +11,6 @@ export const WatchdogRoute = ({
11
11
  restartingGateway = false,
12
12
  onRestartGateway = () => {},
13
13
  restartSignal = 0,
14
- openclawRestarting = false,
15
14
  openclawUpdateInProgress = false,
16
15
  onOpenclawVersionActionComplete = () => {},
17
16
  onOpenclawUpdate = () => {},
@@ -25,7 +24,6 @@ export const WatchdogRoute = ({
25
24
  restartingGateway=${restartingGateway}
26
25
  onRestartGateway=${onRestartGateway}
27
26
  restartSignal=${restartSignal}
28
- openclawRestarting=${openclawRestarting}
29
27
  openclawUpdateInProgress=${openclawUpdateInProgress}
30
28
  onOpenclawVersionActionComplete=${onOpenclawVersionActionComplete}
31
29
  onOpenclawUpdate=${onOpenclawUpdate}
@@ -1,5 +1,5 @@
1
1
  import { h } from "preact";
2
- import { useCallback, useEffect, useMemo, useRef, useState } from "preact/hooks";
2
+ import { useEffect, useMemo, useRef, useState } from "preact/hooks";
3
3
  import htm from "htm";
4
4
  import {
5
5
  AddLineIcon,
@@ -22,7 +22,6 @@ import { OverflowMenu, OverflowMenuItem } from "./overflow-menu.js";
22
22
  import { UpdateActionButton } from "./update-action-button.js";
23
23
  import { SidebarGitPanel } from "./sidebar-git-panel.js";
24
24
  import { UpdateModal } from "./update-modal.js";
25
- import { createUpdateModalSubmitHandler } from "./update-modal-helpers.js";
26
25
  import {
27
26
  readUiSettings,
28
27
  updateUiSettings,
@@ -111,7 +110,6 @@ export const AppSidebar = ({
111
110
  onPreviewBrowseFile = () => {},
112
111
  acHasUpdate = false,
113
112
  acLatest = "",
114
- acRestarting = false,
115
113
  acUpdating = false,
116
114
  onAcUpdate = () => {},
117
115
  agents = [],
@@ -184,19 +182,6 @@ export const AppSidebar = ({
184
182
  writeUiSettings(settings);
185
183
  }, [browseBottomPanelHeightPx]);
186
184
 
187
- const handleUpdateModalClose = useCallback(() => {
188
- if (acUpdating) return;
189
- setUpdateModalOpen(false);
190
- }, [acUpdating]);
191
-
192
- const handleUpdateModalSubmit = useCallback(
193
- createUpdateModalSubmitHandler({
194
- onClose: () => setUpdateModalOpen(false),
195
- onUpdate: onAcUpdate,
196
- }),
197
- [onAcUpdate],
198
- );
199
-
200
185
  const getClampedBrowseBottomPanelHeight = (value) => {
201
186
  const layoutElement = browseLayoutRef.current;
202
187
  if (!layoutElement) return value;
@@ -379,7 +364,7 @@ export const AppSidebar = ({
379
364
  loading=${acUpdating}
380
365
  warning=${true}
381
366
  idleLabel=${`Update to v${acLatest}`}
382
- loadingLabel=${acRestarting ? "Restarting..." : "Updating..."}
367
+ loadingLabel="Updating..."
383
368
  className="w-full justify-center"
384
369
  />
385
370
  `
@@ -504,11 +489,13 @@ export const AppSidebar = ({
504
489
  </div>
505
490
  <${UpdateModal}
506
491
  visible=${updateModalOpen}
507
- onClose=${handleUpdateModalClose}
492
+ onClose=${() => {
493
+ if (acUpdating) return;
494
+ setUpdateModalOpen(false);
495
+ }}
508
496
  version=${acLatest}
509
- onUpdate=${handleUpdateModalSubmit}
497
+ onUpdate=${onAcUpdate}
510
498
  updating=${acUpdating}
511
- updateLoadingLabel=${acRestarting ? "Restarting..." : "Updating..."}
512
499
  />
513
500
  </div>
514
501
  `;
@@ -40,7 +40,6 @@ export const UpdateModal = ({
40
40
  version = "",
41
41
  onUpdate = () => {},
42
42
  updating = false,
43
- updateLoadingLabel = "Updating...",
44
43
  }) => {
45
44
  const requestedTag = useMemo(() => getReleaseTagFromVersion(version), [version]);
46
45
  const [loadingNotes, setLoadingNotes] = useState(false);
@@ -164,7 +163,7 @@ export const UpdateModal = ({
164
163
  onClick=${onUpdate}
165
164
  tone="warning"
166
165
  idleLabel=${updateLabel}
167
- loadingLabel=${updateLoadingLabel}
166
+ loadingLabel="Updating..."
168
167
  loading=${updating}
169
168
  disabled=${loadingNotes}
170
169
  />
@@ -17,7 +17,6 @@ export const WatchdogTab = ({
17
17
  restartingGateway = false,
18
18
  onRestartGateway,
19
19
  restartSignal = 0,
20
- openclawRestarting = false,
21
20
  openclawUpdateInProgress = false,
22
21
  onOpenclawVersionActionComplete = () => {},
23
22
  onOpenclawUpdate,
@@ -38,7 +37,6 @@ export const WatchdogTab = ({
38
37
  watchdogStatus=${state.currentWatchdogStatus}
39
38
  onRepair=${state.onRepair}
40
39
  repairing=${state.isRepairInProgress}
41
- openclawRestarting=${openclawRestarting}
42
40
  openclawUpdateInProgress=${openclawUpdateInProgress}
43
41
  onOpenclawVersionActionComplete=${onOpenclawVersionActionComplete}
44
42
  onOpenclawUpdate=${onOpenclawUpdate}
@@ -102,7 +102,6 @@ export const Welcome = ({ onComplete, acVersion }) => {
102
102
  error=${state.formError}
103
103
  step=${state.step}
104
104
  totalGroups=${kWelcomeGroups.length}
105
- importApplied=${state.importApplied}
106
105
  goBack=${actions.goBack}
107
106
  goNext=${actions.goNext}
108
107
  loading=${state.loading}
@@ -23,7 +23,6 @@ import {
23
23
  kWelcomeGroups,
24
24
  getWelcomeGroupError,
25
25
  findFirstInvalidWelcomeGroup,
26
- normalizeGithubRepoInput,
27
26
  isValidGithubRepoInput,
28
27
  kGithubFlowFresh,
29
28
  kGithubFlowImport,
@@ -49,8 +48,6 @@ export const kImportStepId = "import";
49
48
  export const kSecretReviewStepId = "secret-review";
50
49
  export const kPlaceholderReviewStepId = "placeholder-review";
51
50
  const kImportSubstepKey = "_IMPORT_SUBSTEP";
52
- const kImportAppliedKey = "_IMPORT_APPLIED";
53
- const kImportedSourceRepoKey = "_IMPORTED_SOURCE_REPO";
54
51
  const kImportPlaceholderReviewKey = "_IMPORT_PLACEHOLDER_REVIEW";
55
52
  const kImportPlaceholderSkipConfirmedKey = "_IMPORT_PLACEHOLDER_SKIP_CONFIRMED";
56
53
 
@@ -84,30 +81,6 @@ const normalizePlaceholderReview = (review) => {
84
81
  };
85
82
  };
86
83
 
87
- const normalizeTrackedRepo = (repoInput) =>
88
- normalizeGithubRepoInput(repoInput).toLowerCase();
89
-
90
- export const getImportReuseState = ({
91
- githubFlow,
92
- importApplied,
93
- sourceRepo,
94
- importedSourceRepo,
95
- }) => {
96
- const sourceImportAlreadyApplied =
97
- githubFlow === kGithubFlowImport && !!importApplied;
98
- const normalizedSourceRepo = normalizeTrackedRepo(sourceRepo);
99
- const normalizedImportedSourceRepo = normalizeTrackedRepo(importedSourceRepo);
100
- const sourceRepoChangedAfterImport =
101
- sourceImportAlreadyApplied &&
102
- !!normalizedImportedSourceRepo &&
103
- normalizedSourceRepo !== normalizedImportedSourceRepo;
104
-
105
- return {
106
- sourceImportAlreadyApplied,
107
- sourceRepoChangedAfterImport,
108
- };
109
- };
110
-
111
84
  export const useWelcome = ({ onComplete }) => {
112
85
  const kSetupStepIndex = kWelcomeGroups.length;
113
86
  const kPairingStepIndex = kSetupStepIndex + 1;
@@ -230,7 +203,6 @@ export const useWelcome = ({ onComplete }) => {
230
203
  const placeholderReview = normalizePlaceholderReview(
231
204
  vals[kImportPlaceholderReviewKey],
232
205
  );
233
- const importApplied = !!vals[kImportAppliedKey];
234
206
  const featuredModels = getFeaturedModels(models);
235
207
  const baseModelOptions = showAllModels
236
208
  ? models
@@ -413,19 +385,6 @@ export const useWelcome = ({ onComplete }) => {
413
385
  ? kGithubTargetRepoModeCreate
414
386
  : normalizedVals._GITHUB_TARGET_REPO_MODE ||
415
387
  kGithubTargetRepoModeCreate;
416
- const { sourceImportAlreadyApplied, sourceRepoChangedAfterImport } =
417
- getImportReuseState({
418
- githubFlow,
419
- importApplied: normalizedVals[kImportAppliedKey],
420
- sourceRepo: normalizedVals._GITHUB_SOURCE_REPO,
421
- importedSourceRepo: normalizedVals[kImportedSourceRepoKey],
422
- });
423
- if (sourceRepoChangedAfterImport) {
424
- setFormError(
425
- "The source repo has already been imported into this setup. You can still change the target repo, but changing the source repo requires restarting onboarding.",
426
- );
427
- return;
428
- }
429
388
  const targetVerifyMode =
430
389
  targetRepoMode === kGithubTargetRepoModeExistingEmpty
431
390
  ? kRepoModeExisting
@@ -435,11 +394,9 @@ export const useWelcome = ({ onComplete }) => {
435
394
  ? normalizedVals._GITHUB_SOURCE_REPO
436
395
  : normalizedVals.GITHUB_WORKSPACE_REPO;
437
396
  setGithubStepLoading(true);
438
- if (!sourceImportAlreadyApplied) {
439
- clearPlaceholderReview();
440
- }
397
+ clearPlaceholderReview();
441
398
  try {
442
- if (githubFlow === kGithubFlowImport && !sourceImportAlreadyApplied) {
399
+ if (githubFlow === kGithubFlowImport) {
443
400
  const sourceResult = await verifyGithubOnboardingRepo(
444
401
  sourceRepo,
445
402
  normalizedVals.GITHUB_TOKEN,
@@ -561,16 +518,10 @@ export const useWelcome = ({ onComplete }) => {
561
518
  const nextPlaceholderReview = normalizePlaceholderReview(
562
519
  result.placeholderReview,
563
520
  );
564
- const importedSourceRepo =
565
- vals._GITHUB_FLOW === kGithubFlowImport
566
- ? normalizeGithubRepoInput(vals._GITHUB_SOURCE_REPO)
567
- : "";
568
521
  setVals((prev) => ({
569
522
  ...prev,
570
523
  ...approvedImportVals,
571
524
  ...(result.preFill || {}),
572
- [kImportAppliedKey]: true,
573
- [kImportedSourceRepoKey]: importedSourceRepo,
574
525
  [kImportPlaceholderReviewKey]: nextPlaceholderReview,
575
526
  [kImportPlaceholderSkipConfirmedKey]: false,
576
527
  }));
@@ -656,7 +607,6 @@ export const useWelcome = ({ onComplete }) => {
656
607
  importScanResult,
657
608
  importScanning,
658
609
  importError,
659
- importApplied,
660
610
  selectedProvider,
661
611
  modelOptions,
662
612
  canToggleFullCatalog,
@@ -5,7 +5,6 @@ import {
5
5
  fetchAuthStatus,
6
6
  fetchAlphaclawVersion,
7
7
  updateAlphaclaw,
8
- waitForAlphaclawRestart,
9
8
  fetchRestartStatus,
10
9
  dismissRestartStatus,
11
10
  restartGateway,
@@ -20,14 +19,12 @@ import { showToast } from "../components/toast.js";
20
19
 
21
20
  export const useAppShellController = ({ location = "" } = {}) => {
22
21
  const kInitialStatusPollDelayMs = 5000;
23
- const kOpenclawUpdateRestartTimeoutMs = 5 * 60 * 1000;
24
22
  const [onboarded, setOnboarded] = useState(null);
25
23
  const [authEnabled, setAuthEnabled] = useState(false);
26
24
  const [acVersion, setAcVersion] = useState(null);
27
25
  const [acLatest, setAcLatest] = useState(null);
28
26
  const [acHasUpdate, setAcHasUpdate] = useState(false);
29
27
  const [acUpdating, setAcUpdating] = useState(false);
30
- const [acRestarting, setAcRestarting] = useState(false);
31
28
  const [restartRequired, setRestartRequired] = useState(false);
32
29
  const [browseRestartRequired, setBrowseRestartRequired] = useState(false);
33
30
  const [restartingGateway, setRestartingGateway] = useState(false);
@@ -35,7 +32,6 @@ export const useAppShellController = ({ location = "" } = {}) => {
35
32
  const [statusPollCadenceMs, setStatusPollCadenceMs] = useState(15000);
36
33
  const [statusPollingGraceElapsed, setStatusPollingGraceElapsed] = useState(false);
37
34
  const [openclawUpdateInProgress, setOpenclawUpdateInProgress] = useState(false);
38
- const [openclawRestarting, setOpenclawRestarting] = useState(false);
39
35
  const [statusStreamConnected, setStatusStreamConnected] = useState(false);
40
36
  const [statusStreamStatus, setStatusStreamStatus] = useState(null);
41
37
  const [statusStreamWatchdog, setStatusStreamWatchdog] = useState(null);
@@ -245,28 +241,17 @@ export const useAppShellController = ({ location = "" } = {}) => {
245
241
  return { ok: false, error: "OpenClaw update already in progress" };
246
242
  }
247
243
  setOpenclawUpdateInProgress(true);
248
- setOpenclawRestarting(false);
249
244
  try {
250
245
  const data = await updateOpenclaw();
251
- if (data?.ok && data?.restarting) {
252
- setOpenclawRestarting(true);
253
- await waitForAlphaclawRestart({
254
- timeoutMs: kOpenclawUpdateRestartTimeoutMs,
255
- timeoutErrorMessage: "OpenClaw update is taking longer than expected",
256
- });
257
- window.location.reload();
258
- return { ...data, restartHandled: true };
259
- }
260
- setOpenclawUpdateInProgress(false);
261
- setOpenclawRestarting(false);
262
246
  return data;
263
- } catch (err) {
264
- const message = err.message || "Could not update OpenClaw";
247
+ } finally {
265
248
  setOpenclawUpdateInProgress(false);
266
- setOpenclawRestarting(false);
267
- return { ok: false, error: message };
249
+ refreshSharedStatuses();
250
+ setTimeout(refreshSharedStatuses, 1200);
251
+ setTimeout(refreshSharedStatuses, 3500);
252
+ setTimeout(refreshRestartStatus, 1200);
268
253
  }
269
- }, [openclawUpdateInProgress]);
254
+ }, [openclawUpdateInProgress, refreshRestartStatus, refreshSharedStatuses]);
270
255
 
271
256
  const handleOpenclawVersionActionComplete = useCallback(
272
257
  ({ type }) => {
@@ -278,31 +263,20 @@ export const useAppShellController = ({ location = "" } = {}) => {
278
263
  );
279
264
 
280
265
  const handleAcUpdate = useCallback(async () => {
281
- if (acUpdating) {
282
- return { ok: false, error: "AlphaClaw update already in progress" };
283
- }
266
+ if (acUpdating) return;
284
267
  setAcUpdating(true);
285
- setAcRestarting(false);
286
268
  try {
287
269
  const data = await updateAlphaclaw();
288
270
  if (data.ok) {
289
271
  showToast("AlphaClaw updated — restarting...", "success");
290
- setAcRestarting(true);
291
- await waitForAlphaclawRestart();
292
- window.location.reload();
293
- return data;
272
+ setTimeout(() => window.location.reload(), 5000);
294
273
  } else {
295
274
  showToast(data.error || "AlphaClaw update failed", "error");
296
275
  setAcUpdating(false);
297
- setAcRestarting(false);
298
- return data;
299
276
  }
300
277
  } catch (err) {
301
- const message = err.message || "Could not update AlphaClaw";
302
- showToast(message, "error");
278
+ showToast(err.message || "Could not update AlphaClaw", "error");
303
279
  setAcUpdating(false);
304
- setAcRestarting(false);
305
- return { ok: false, error: message };
306
280
  }
307
281
  }, [acUpdating]);
308
282
 
@@ -322,14 +296,12 @@ export const useAppShellController = ({ location = "" } = {}) => {
322
296
  state: {
323
297
  acHasUpdate,
324
298
  acLatest,
325
- acRestarting,
326
299
  acUpdating,
327
300
  acVersion,
328
301
  authEnabled,
329
302
  gatewayRestartSignal,
330
303
  isAnyRestartRequired,
331
304
  onboarded,
332
- openclawRestarting,
333
305
  openclawUpdateInProgress,
334
306
  restartingGateway,
335
307
  sharedDoctorStatus,
@@ -527,42 +527,6 @@ export async function updateAlphaclaw() {
527
527
  return res.json();
528
528
  }
529
529
 
530
- const delay = (ms) =>
531
- new Promise((resolve) => {
532
- setTimeout(resolve, Math.max(0, Number(ms) || 0));
533
- });
534
-
535
- export async function waitForAlphaclawRestart({
536
- initialDelayMs = 1500,
537
- intervalMs = 1000,
538
- timeoutMs = 60000,
539
- timeoutErrorMessage = "AlphaClaw restart is taking longer than expected",
540
- } = {}) {
541
- const deadline = Date.now() + Math.max(0, Number(timeoutMs) || 0);
542
- await delay(initialDelayMs);
543
-
544
- while (Date.now() <= deadline) {
545
- try {
546
- const headers = new Headers();
547
- const browserTimeZone = getBrowserTimeZone();
548
- if (browserTimeZone) {
549
- headers.set(kClientTimeZoneHeader, browserTimeZone);
550
- }
551
- const res = await fetch("/api/auth/status", {
552
- cache: "no-store",
553
- credentials: "same-origin",
554
- headers,
555
- });
556
- if (res.status < 500) {
557
- return { ok: true };
558
- }
559
- } catch {}
560
- await delay(intervalMs);
561
- }
562
-
563
- throw new Error(String(timeoutErrorMessage || "AlphaClaw restart is taking longer than expected"));
564
- }
565
-
566
530
  export async function fetchSyncCron() {
567
531
  const res = await authFetch("/api/sync-cron");
568
532
  const text = await res.text();