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