@chrysb/alphaclaw 0.1.3 → 0.1.4

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.
@@ -12,6 +12,8 @@ import {
12
12
  fetchOnboardStatus,
13
13
  fetchDashboardUrl,
14
14
  updateSyncCron,
15
+ fetchAlphaclawVersion,
16
+ updateAlphaclaw,
15
17
  } from "./lib/api.js";
16
18
  import { usePolling } from "./hooks/usePolling.js";
17
19
  import { Gateway } from "./components/gateway.js";
@@ -240,6 +242,11 @@ const GeneralTab = ({ onSwitchTab }) => {
240
242
  function App() {
241
243
  const [onboarded, setOnboarded] = useState(null);
242
244
  const [tab, setTab] = useState("general");
245
+ const [acVersion, setAcVersion] = useState(null);
246
+ const [acLatest, setAcLatest] = useState(null);
247
+ const [acHasUpdate, setAcHasUpdate] = useState(false);
248
+ const [acUpdating, setAcUpdating] = useState(false);
249
+ const [acDismissed, setAcDismissed] = useState(false);
243
250
 
244
251
  useEffect(() => {
245
252
  fetchOnboardStatus()
@@ -247,6 +254,40 @@ function App() {
247
254
  .catch(() => setOnboarded(false));
248
255
  }, []);
249
256
 
257
+ useEffect(() => {
258
+ if (!onboarded) return;
259
+ let active = true;
260
+ const check = async () => {
261
+ try {
262
+ const data = await fetchAlphaclawVersion(false);
263
+ if (!active) return;
264
+ setAcVersion(data.currentVersion || null);
265
+ setAcLatest(data.latestVersion || null);
266
+ setAcHasUpdate(!!data.hasUpdate);
267
+ } catch {}
268
+ };
269
+ check();
270
+ const id = setInterval(check, 5 * 60 * 1000);
271
+ return () => { active = false; clearInterval(id); };
272
+ }, [onboarded]);
273
+
274
+ const handleAcUpdate = async () => {
275
+ if (acUpdating) return;
276
+ setAcUpdating(true);
277
+ try {
278
+ const data = await updateAlphaclaw();
279
+ if (data.ok) {
280
+ showToast("AlphaClaw updated — restarting...", "success");
281
+ } else {
282
+ showToast(data.error || "AlphaClaw update failed", "error");
283
+ setAcUpdating(false);
284
+ }
285
+ } catch (err) {
286
+ showToast(err.message || "Could not update AlphaClaw", "error");
287
+ setAcUpdating(false);
288
+ }
289
+ };
290
+
250
291
  // Still loading onboard status
251
292
  if (onboarded === null) {
252
293
  return html`
@@ -288,11 +329,37 @@ function App() {
288
329
  <div class="flex items-center gap-3 pb-3">
289
330
  <div class="text-4xl">🦞</div>
290
331
  <div>
291
- <h1 class="text-2xl font-semibold">OpenClaw Setup</h1>
332
+ <h1 class="text-2xl font-semibold">OpenClaw Setup${acVersion ? html`${" "}<span class="text-base font-normal text-gray-600">v${acVersion}</span>` : ""}</h1>
292
333
  <p class="text-gray-500 text-sm">This should be easy, right?</p>
293
334
  </div>
294
335
  </div>
295
336
 
337
+ ${acHasUpdate && acLatest && !acDismissed && html`
338
+ <div class="mb-3 flex items-center justify-between gap-3 rounded-lg border border-yellow-500/30 bg-yellow-500/10 px-3 py-2">
339
+ <p class="text-sm text-yellow-400">
340
+ AlphaClaw <span class="font-medium">v${acLatest}</span> is available
341
+ </p>
342
+ <div class="flex items-center gap-2 shrink-0">
343
+ <button
344
+ onclick=${handleAcUpdate}
345
+ disabled=${acUpdating}
346
+ class="text-xs font-medium px-3 py-1 rounded-lg bg-yellow-500/20 text-yellow-300 hover:bg-yellow-500/30 transition-colors ${acUpdating ? "opacity-50 cursor-not-allowed" : ""}"
347
+ >
348
+ ${acUpdating ? "Updating..." : "Update now"}
349
+ </button>
350
+ <button
351
+ onclick=${() => setAcDismissed(true)}
352
+ class="text-yellow-500/60 hover:text-yellow-400 transition-colors"
353
+ title="Dismiss"
354
+ >
355
+ <svg class="w-4 h-4" viewBox="0 0 20 20" fill="currentColor">
356
+ <path d="M6.28 5.22a.75.75 0 00-1.06 1.06L8.94 10l-3.72 3.72a.75.75 0 101.06 1.06L10 11.06l3.72 3.72a.75.75 0 101.06-1.06L11.06 10l3.72-3.72a.75.75 0 00-1.06-1.06L10 8.94 6.28 5.22z"/>
357
+ </svg>
358
+ </button>
359
+ </div>
360
+ </div>
361
+ `}
362
+
296
363
  <div class="flex gap-1 border-b border-border">
297
364
  ${["general", "models", "envars"].map(
298
365
  (t) => html`
@@ -3,10 +3,8 @@ import { useEffect, useState } from "https://esm.sh/preact/hooks";
3
3
  import htm from "https://esm.sh/htm";
4
4
  import {
5
5
  fetchOpenclawVersion,
6
- fetchAlphaclawVersion,
7
6
  restartGateway,
8
7
  updateOpenclaw,
9
- updateAlphaclaw,
10
8
  } from "../lib/api.js";
11
9
  import { showToast } from "./toast.js";
12
10
  const html = htm.bind(h);
@@ -147,7 +145,7 @@ export function Gateway({ status, openclawVersion }) {
147
145
  Restart
148
146
  </button>
149
147
  </div>
150
- <div class="mt-3 pt-3 border-t border-border space-y-3">
148
+ <div class="mt-3 pt-3 border-t border-border">
151
149
  <${VersionRow}
152
150
  label="OpenClaw"
153
151
  currentVersion=${openclawVersion}
@@ -155,13 +153,6 @@ export function Gateway({ status, openclawVersion }) {
155
153
  applyUpdate=${updateOpenclaw}
156
154
  tagsUrl="https://github.com/openclaw/openclaw/tags"
157
155
  />
158
- <${VersionRow}
159
- label="AlphaClaw"
160
- currentVersion=${null}
161
- fetchVersion=${fetchAlphaclawVersion}
162
- applyUpdate=${updateAlphaclaw}
163
- tagsUrl="https://www.npmjs.com/package/@chrysb/alphaclaw"
164
- />
165
156
  </div>
166
157
  </div>`;
167
158
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@chrysb/alphaclaw",
3
- "version": "0.1.3",
3
+ "version": "0.1.4",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },