viveworker 0.7.0-beta.2 → 0.7.0-beta.3

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.
@@ -101,3 +101,7 @@ APP_SERVER_NOTIFY_COMPLETIONS=0
101
101
  # hazBase wallet / x402 backend
102
102
  HAZBASE_API_URL=https://api.hazbase.com
103
103
  HAZBASE_DEVICE_LABEL=viveworker
104
+ # Require paired-device approval before `viveworker share pay` signs x402
105
+ # payments. Set to 0 only for trusted smoke tests / CI.
106
+ VIVEWORKER_PAYMENT_APPROVALS=1
107
+ VIVEWORKER_PAYMENT_APPROVAL_TIMEOUT_SEC=600
package/web/app.css CHANGED
@@ -1117,6 +1117,11 @@ code {
1117
1117
  background: linear-gradient(180deg, rgba(28, 40, 49, 0.98), rgba(20, 27, 34, 0.96));
1118
1118
  }
1119
1119
 
1120
+ .wallet-flow-banner--session-expired {
1121
+ border-color: rgba(255, 190, 92, 0.28);
1122
+ background: linear-gradient(180deg, rgba(49, 39, 28, 0.98), rgba(24, 28, 30, 0.96));
1123
+ }
1124
+
1120
1125
  .wallet-flow-banner__eyebrow {
1121
1126
  margin: 0;
1122
1127
  font-size: 0.72rem;
@@ -1232,6 +1237,30 @@ code {
1232
1237
  background: rgba(53, 26, 29, 0.96);
1233
1238
  }
1234
1239
 
1240
+ .settings-update-notice {
1241
+ margin-top: 0.85rem;
1242
+ border-color: rgba(121, 196, 255, 0.22);
1243
+ background: linear-gradient(180deg, rgba(28, 40, 49, 0.98), rgba(20, 27, 34, 0.96));
1244
+ }
1245
+
1246
+ .settings-update-notice__title {
1247
+ margin: 0;
1248
+ font-weight: 700;
1249
+ color: var(--text);
1250
+ }
1251
+
1252
+ .settings-update-notice__command {
1253
+ display: block;
1254
+ width: fit-content;
1255
+ max-width: 100%;
1256
+ margin-top: 0.35rem;
1257
+ padding: 0.32rem 0.5rem;
1258
+ border-radius: 10px;
1259
+ background: rgba(3, 10, 16, 0.38);
1260
+ color: rgba(233, 247, 255, 0.92);
1261
+ overflow-wrap: anywhere;
1262
+ }
1263
+
1235
1264
  /* Brand attribution at the very bottom of the wallet settings page.
1236
1265
  Sits below the advanced-actions panel as plain small text so it reads
1237
1266
  as a credit, not another card. The link inherits the muted color and
package/web/app.js CHANGED
@@ -106,6 +106,8 @@ const state = {
106
106
  defaultLocale: DEFAULT_LOCALE,
107
107
  supportedLocales: [...SUPPORTED_LOCALES],
108
108
  appVersion: "",
109
+ versionStatus: null,
110
+ versionStatusError: "",
109
111
  };
110
112
 
111
113
  let detailLoadSequence = 0;
@@ -225,6 +227,7 @@ async function boot() {
225
227
  ensureCurrentSelection();
226
228
  maybeAutoFocusClaudePending();
227
229
  await renderShell();
230
+ refreshVersionStatusForTechnicalPage();
228
231
 
229
232
  // Diff fetch runs as a background phase because `/api/inbox/diff`
230
233
  // spawns `git` subprocesses per tracked repo and can stall for several
@@ -586,6 +589,29 @@ async function fetchHazbaseStatus() {
586
589
  }
587
590
  }
588
591
 
592
+ async function fetchVersionStatus() {
593
+ try {
594
+ state.versionStatus = await apiGet("/api/version/status");
595
+ state.versionStatusError = "";
596
+ } catch (error) {
597
+ state.versionStatus = null;
598
+ state.versionStatusError = error.message || String(error);
599
+ }
600
+ }
601
+
602
+ function refreshVersionStatusForTechnicalPage() {
603
+ if (state.currentTab !== "settings" || state.settingsSubpage !== "advanced") {
604
+ return;
605
+ }
606
+ fetchVersionStatus()
607
+ .then(async () => {
608
+ if (state.currentTab === "settings" && state.settingsSubpage === "advanced" && !shouldDeferRenderForActiveInteraction()) {
609
+ await renderShell();
610
+ }
611
+ })
612
+ .catch(() => {});
613
+ }
614
+
589
615
  async function getClientPushState() {
590
616
  const registration = state.serviceWorkerRegistration || (await navigator.serviceWorker?.ready.catch(() => null));
591
617
  if (registration) {
@@ -827,6 +853,7 @@ function normalizeProviderClient(value) {
827
853
  if (normalized === "claude") return "claude";
828
854
  if (normalized === "moltbook") return "moltbook";
829
855
  if (normalized === "a2a") return "a2a";
856
+ if (normalized === "viveworker") return "viveworker";
830
857
  return "codex";
831
858
  }
832
859
 
@@ -835,6 +862,7 @@ function providerDisplayName(provider) {
835
862
  if (p === "claude") return L("common.claude");
836
863
  if (p === "moltbook") return "Moltbook";
837
864
  if (p === "a2a") return "A2A";
865
+ if (p === "viveworker") return L("common.appName");
838
866
  return L("common.codex");
839
867
  }
840
868
 
@@ -1234,6 +1262,7 @@ async function renderShell() {
1234
1262
  <div class="${shellClassName}">
1235
1263
  ${desktop ? renderDesktopHeader(detail) : renderMobileTopBar(detail)}
1236
1264
  ${renderTopBanner()}
1265
+ ${renderGlobalErrorBanner()}
1237
1266
  <main class="app-main">
1238
1267
  ${desktop ? renderDesktopWorkspace(detail) : renderMobileWorkspace(detail)}
1239
1268
  </main>
@@ -3490,7 +3519,9 @@ function renderSettingsRoot(context, { mobile }) {
3490
3519
  icon: "coin",
3491
3520
  title: L("settings.wallet.title"),
3492
3521
  subtitle: L("settings.wallet.subtitle"),
3493
- value: context.hazbase?.signedIn ? L("settings.hazbase.status.signedIn") : L("settings.hazbase.status.signedOut"),
3522
+ value: context.hazbase?.sessionInvalid
3523
+ ? L("settings.hazbase.status.sessionExpired")
3524
+ : context.hazbase?.signedIn ? L("settings.hazbase.status.signedIn") : L("settings.hazbase.status.signedOut"),
3494
3525
  }) : "",
3495
3526
  ].filter(Boolean)) : ""}
3496
3527
  ${renderSettingsGroup(L("settings.pairing.title"), deviceRows)}
@@ -3673,6 +3704,7 @@ function renderSettingsDevicePage(context) {
3673
3704
  }
3674
3705
 
3675
3706
  function renderSettingsAdvancedPage(context) {
3707
+ const versionNotice = renderVersionUpdateNotice();
3676
3708
  return `
3677
3709
  <div class="settings-page">
3678
3710
  ${context.diagnostics.map((message) => `<p class="inline-alert">${escapeHtml(message)}</p>`).join("")}
@@ -3691,10 +3723,28 @@ function renderSettingsAdvancedPage(context) {
3691
3723
  : "",
3692
3724
  renderSettingsInfoRow(L("settings.row.version"), state.appVersion || L("common.unavailable")),
3693
3725
  ].filter(Boolean), { listClassName: "settings-list settings-list--compact" })}
3726
+ ${versionNotice}
3694
3727
  </div>
3695
3728
  `;
3696
3729
  }
3697
3730
 
3731
+ function renderVersionUpdateNotice() {
3732
+ const status = state.versionStatus;
3733
+ if (!status?.updateAvailable || !status.latestVersion) {
3734
+ return "";
3735
+ }
3736
+ return `
3737
+ <section class="settings-copy-block settings-copy-block--compact settings-update-notice">
3738
+ <p class="settings-update-notice__title">${escapeHtml(L("settings.updateAvailable.title"))}</p>
3739
+ <p class="muted">${escapeHtml(L("settings.updateAvailable.copy", {
3740
+ current: status.currentVersion || state.appVersion || "",
3741
+ latest: status.latestVersion,
3742
+ }))}</p>
3743
+ <code class="settings-update-notice__command">npx viveworker update</code>
3744
+ </section>
3745
+ `;
3746
+ }
3747
+
3698
3748
  function renderSettingsNotificationActions({ push, canEnable, standalone }) {
3699
3749
  if (push.serverSubscribed) {
3700
3750
  return `
@@ -4523,8 +4573,16 @@ function renderSettingsWalletPage(context) {
4523
4573
  : "",
4524
4574
  renderHazbaseWalletStepList(flow),
4525
4575
  ].filter(Boolean);
4526
- const advancedActions = hazbase.signedIn
4527
- ? `<button class="secondary secondary--wide" type="button" data-hazbase-action="logout">${escapeHtml(L("settings.hazbase.action.signOut"))}</button>`
4576
+ const canRefreshSession = Boolean(hazbase.sessionInvalid);
4577
+ const advancedActions = canRefreshSession || hazbase.signedIn
4578
+ ? [
4579
+ canRefreshSession
4580
+ ? `<button class="secondary secondary--wide" type="button" data-hazbase-action="refresh-session">${escapeHtml(L("settings.hazbase.action.refreshSession"))}</button>`
4581
+ : "",
4582
+ hazbase.signedIn
4583
+ ? `<button class="secondary secondary--wide" type="button" data-hazbase-action="logout">${escapeHtml(L("settings.hazbase.action.signOut"))}</button>`
4584
+ : "",
4585
+ ].filter(Boolean).join("")
4528
4586
  : "";
4529
4587
  // Render the wallet flow without `renderSettingsGroup`'s `.settings-list`
4530
4588
  // wrapper. The banner (`.settings-copy-block`), notice/error blocks, and
@@ -4599,7 +4657,8 @@ function deriveHazbaseWalletFlow(hazbase) {
4599
4657
  const accounts = Array.isArray(hazbase.accounts) ? hazbase.accounts : [];
4600
4658
  const baseSepolia = accounts.find((entry) => Number(entry.chainId) === 84532) || null;
4601
4659
  const baseMainnet = accounts.find((entry) => Number(entry.chainId) === 8453) || null;
4602
- const signedIn = Boolean(hazbase.signedIn);
4660
+ const sessionInvalid = Boolean(hazbase.sessionInvalid);
4661
+ const signedIn = Boolean(hazbase.signedIn) && !sessionInvalid;
4603
4662
  const passkeyHost = hazbasePasskeyHostSupport();
4604
4663
  const hasPasskey = Boolean(hazbase.credentialId || hazbase.deviceBindingId);
4605
4664
  const hasBaseSepolia = Boolean(baseSepolia?.smartAccountAddress);
@@ -4619,17 +4678,20 @@ function deriveHazbaseWalletFlow(hazbase) {
4619
4678
  hasPasskey,
4620
4679
  baseSepolia,
4621
4680
  baseMainnet,
4681
+ sessionInvalid,
4622
4682
  coreReady,
4623
4683
  steps: [
4624
4684
  {
4625
4685
  number: 1,
4626
4686
  icon: "approval",
4627
- title: L("settings.wallet.step.signIn.title"),
4628
- copy: L("settings.wallet.step.signIn.copy"),
4687
+ title: sessionInvalid ? L("settings.wallet.step.refreshSession.title") : L("settings.wallet.step.signIn.title"),
4688
+ copy: sessionInvalid ? L("settings.wallet.step.refreshSession.copy") : L("settings.wallet.step.signIn.copy"),
4629
4689
  detail: signedIn
4630
4690
  ? hazbase.email || L("settings.hazbase.status.signedIn")
4631
4691
  : state.hazbaseOtpRequested
4632
4692
  ? L("settings.hazbase.status.otpAwaitingVerify")
4693
+ : sessionInvalid
4694
+ ? L("settings.hazbase.status.sessionExpired")
4633
4695
  : L("settings.hazbase.status.signedOut"),
4634
4696
  status: signedIn ? "complete" : "current",
4635
4697
  // Inline form: email input (always visible pre-sign-in) and the
@@ -4657,7 +4719,7 @@ function deriveHazbaseWalletFlow(hazbase) {
4657
4719
  actionButton("settings.hazbase.action.resendOtp", "request-otp"),
4658
4720
  ]
4659
4721
  : [
4660
- actionButton("settings.hazbase.action.requestOtp", "request-otp", { primary: true }),
4722
+ actionButton(sessionInvalid ? "settings.hazbase.action.refreshSession" : "settings.hazbase.action.requestOtp", "request-otp", { primary: true }),
4661
4723
  ],
4662
4724
  },
4663
4725
  {
@@ -4718,9 +4780,13 @@ function deriveHazbaseWalletFlow(hazbase) {
4718
4780
  }
4719
4781
 
4720
4782
  function renderHazbaseWalletBanner(flow) {
4721
- const title = flow.coreReady ? L("settings.wallet.ready.title") : L("settings.wallet.flow.banner.title");
4783
+ const title = flow.sessionInvalid
4784
+ ? L("settings.wallet.sessionExpired.title")
4785
+ : flow.coreReady ? L("settings.wallet.ready.title") : L("settings.wallet.flow.banner.title");
4722
4786
  const className = flow.coreReady
4723
4787
  ? "settings-copy-block settings-copy-block--stacked wallet-flow-banner wallet-flow-banner--ready"
4788
+ : flow.sessionInvalid
4789
+ ? "settings-copy-block settings-copy-block--stacked wallet-flow-banner wallet-flow-banner--session-expired"
4724
4790
  : "settings-copy-block settings-copy-block--stacked wallet-flow-banner";
4725
4791
  // Ready state: surface the smart-account address prominently so the user
4726
4792
  // can see at a glance which wallet agents will use as `--pay-to` when
@@ -4746,7 +4812,9 @@ function renderHazbaseWalletBanner(flow) {
4746
4812
  </button>
4747
4813
  `
4748
4814
  : `<p class="wallet-flow-banner__copy muted">${escapeHtml(
4749
- flow.coreReady ? L("settings.wallet.ready.copy") : L("settings.wallet.flow.copy"),
4815
+ flow.sessionInvalid
4816
+ ? L("settings.wallet.sessionExpired.copy")
4817
+ : flow.coreReady ? L("settings.wallet.ready.copy") : L("settings.wallet.flow.copy"),
4750
4818
  )}</p>`;
4751
4819
  return `
4752
4820
  <div class="${className}">
@@ -6305,6 +6373,20 @@ function renderTopBanner() {
6305
6373
  return "";
6306
6374
  }
6307
6375
 
6376
+ function renderGlobalErrorBanner() {
6377
+ if (!state.pushError) {
6378
+ return "";
6379
+ }
6380
+ return `
6381
+ <section class="install-banner install-banner--push">
6382
+ <div class="install-banner__copy">
6383
+ <strong>${escapeHtml(state.locale === "ja" ? "エラー" : "Error")}</strong>
6384
+ <p class="muted">${escapeHtml(state.pushError)}</p>
6385
+ </div>
6386
+ </section>
6387
+ `;
6388
+ }
6389
+
6308
6390
  function renderPushBanner() {
6309
6391
  if (!shouldShowPushBanner()) {
6310
6392
  return "";
@@ -6488,6 +6570,7 @@ function bindShellInteractions() {
6488
6570
  openSettingsSubpage(nextPage);
6489
6571
  }
6490
6572
  await renderShell();
6573
+ refreshVersionStatusForTechnicalPage();
6491
6574
  });
6492
6575
  }
6493
6576
 
@@ -6500,6 +6583,7 @@ function bindShellInteractions() {
6500
6583
  syncCurrentItemUrl(null);
6501
6584
  openSettingsSubpage("advanced");
6502
6585
  await renderShell();
6586
+ refreshVersionStatusForTechnicalPage();
6503
6587
  });
6504
6588
  }
6505
6589
 
@@ -6507,6 +6591,7 @@ function bindShellInteractions() {
6507
6591
  button.addEventListener("click", async () => {
6508
6592
  openSettingsSubpage(button.dataset.settingsSubpage || "");
6509
6593
  await renderShell();
6594
+ refreshVersionStatusForTechnicalPage();
6510
6595
  });
6511
6596
  }
6512
6597
 
@@ -6749,7 +6834,23 @@ function bindShellInteractions() {
6749
6834
  button.innerHTML = `<span class="action-spinner" aria-hidden="true"></span><span>${escapeHtml(L("reply.sendSending"))}</span>`;
6750
6835
 
6751
6836
  try {
6752
- await apiPost(actionUrl, body);
6837
+ let postBody = body;
6838
+ if (body?.hazbaseReauth === true) {
6839
+ if (!hazbasePasskeyHostSupport().eligible) {
6840
+ throw new Error(L("error.hazbasePasskeyLocalHostRequired"));
6841
+ }
6842
+ const { createPasskeyAssertionCredential } = await loadHazbasePasskeyModule();
6843
+ const challenge = await apiPost("/api/hazbase/passkey/assert/challenge", { purpose: "reauth" });
6844
+ const credential = await createPasskeyAssertionCredential(challenge);
6845
+ await apiPost("/api/hazbase/passkey/assert/complete", {
6846
+ challengeId: challenge.challengeId,
6847
+ credential,
6848
+ purpose: "reauth",
6849
+ });
6850
+ postBody = { ...body };
6851
+ delete postBody.hazbaseReauth;
6852
+ }
6853
+ await apiPost(actionUrl, postBody);
6753
6854
  if (keepDetailOpen && activeItem?.kind === "approval") {
6754
6855
  pinActionOutcomeDetail(
6755
6856
  activeItem,
@@ -6769,6 +6870,9 @@ function bindShellInteractions() {
6769
6870
  state.pendingActionUrls.delete(actionUrl);
6770
6871
  } catch (error) {
6771
6872
  state.pendingActionUrls.delete(actionUrl);
6873
+ if (error?.errorKey === "hazbase-session-expired") {
6874
+ await fetchHazbaseStatus();
6875
+ }
6772
6876
  // Restore buttons on failure so the user can retry
6773
6877
  for (const sibling of siblingButtons) {
6774
6878
  if (originalLabels.has(sibling)) {
@@ -6778,7 +6882,8 @@ function bindShellInteractions() {
6778
6882
  sibling.removeAttribute("aria-busy");
6779
6883
  }
6780
6884
  button.classList.remove("is-loading");
6781
- throw error;
6885
+ state.pushError = error.message || String(error);
6886
+ await renderShell();
6782
6887
  }
6783
6888
  });
6784
6889
  }
@@ -7209,6 +7314,11 @@ for (const button of document.querySelectorAll("[data-hazbase-action]")) {
7209
7314
  state.hazbaseLogoutConfirmOpen = false;
7210
7315
  await apiPost("/api/hazbase/logout", {});
7211
7316
  state.hazbaseNotice = L("settings.hazbase.notice.signedOut");
7317
+ } else if (action === "refresh-session") {
7318
+ await apiPost("/api/hazbase/session/refresh", {});
7319
+ state.hazbaseOtpRequested = false;
7320
+ state.hazbaseOtpCode = "";
7321
+ state.hazbaseNotice = L("settings.hazbase.notice.sessionRefreshStarted");
7212
7322
  } else if (action === "change-email") {
7213
7323
  // Flip the form back to pre-send mode. We keep the email so typo
7214
7324
  // recovery ("hoshin" → "hoshino") stays one edit away, but drop
@@ -7233,6 +7343,11 @@ for (const button of document.querySelectorAll("[data-hazbase-action]")) {
7233
7343
  }
7234
7344
  await fetchHazbaseStatus();
7235
7345
  } catch (error) {
7346
+ if (error?.errorKey === "hazbase-session-expired") {
7347
+ state.hazbaseOtpRequested = false;
7348
+ state.hazbaseOtpCode = "";
7349
+ await fetchHazbaseStatus();
7350
+ }
7236
7351
  state.hazbaseError = error.message || String(error);
7237
7352
  }
7238
7353
  await renderShell();
@@ -8697,6 +8812,7 @@ function localizeApiError(value) {
8697
8812
  "choice-input-already-handled": "error.choiceInputAlreadyHandled",
8698
8813
  "mkcert-root-ca-not-found": "error.mkcertRootCaNotFound",
8699
8814
  "hazbase-auth-required": "error.hazbaseAuthRequired",
8815
+ "hazbase-session-expired": "error.hazbaseSessionExpired",
8700
8816
  "hazbase-passkey-local-host-required": "error.hazbasePasskeyLocalHostRequired",
8701
8817
  "hazbase-wallet-account-missing": "error.hazbaseWalletAccountMissing",
8702
8818
  "unsupported-chain": "error.unsupportedChain",
package/web/i18n.js CHANGED
@@ -423,6 +423,8 @@ const translations = {
423
423
  "settings.row.currentDeviceSubscribed": "This device subscribed",
424
424
  "settings.row.lastSuccessfulDelivery": "Last successful delivery",
425
425
  "settings.row.version": "Version",
426
+ "settings.updateAvailable.title": "New version available",
427
+ "settings.updateAvailable.copy": "viveworker v{latest} is available. You are currently using v{current}.",
426
428
  "settings.row.currentLanguage": "Current language",
427
429
  "settings.row.languageSource": "Language source",
428
430
  "settings.row.defaultLanguage": "Setup default",
@@ -518,6 +520,8 @@ const translations = {
518
520
  "settings.wallet.flow.title": "Recommended order",
519
521
  "settings.wallet.flow.banner.title": "Let's set up your wallet",
520
522
  "settings.wallet.flow.copy": "You need to activate your wallet to exchange task rewards over A2A.",
523
+ "settings.wallet.sessionExpired.title": "Refresh your wallet session",
524
+ "settings.wallet.sessionExpired.copy": "Your wallet session expired. Sign in again with a one-time password; your passkey and Base Sepolia address stay linked.",
521
525
  "settings.wallet.ready.title": "Ready to use",
522
526
  "settings.wallet.ready.copy": "Your email sign-in, passkey, and Base Sepolia wallet are all set.",
523
527
  "settings.wallet.ready.payoutIntro": "Agents will use this address for payouts:",
@@ -531,6 +535,8 @@ const translations = {
531
535
  "settings.wallet.status.optional": "Optional",
532
536
  "settings.wallet.step.signIn.title": "Sign in with email",
533
537
  "settings.wallet.step.signIn.copy": "Send a one-time password to your email, then enter it here to sign in to your wallet.",
538
+ "settings.wallet.step.refreshSession.title": "Refresh session",
539
+ "settings.wallet.step.refreshSession.copy": "Send a new one-time password and sign in again before continuing wallet actions.",
534
540
  "settings.wallet.step.passkey.title": "Register a passkey",
535
541
  "settings.wallet.step.passkey.copy": "Register a passkey on this device. You will use it for wallet issuance and sensitive wallet actions.",
536
542
  "settings.wallet.step.baseSepolia.title": "Issue a Base Sepolia wallet",
@@ -542,6 +548,7 @@ const translations = {
542
548
  "settings.hazbase.title": "Wallet",
543
549
  "settings.hazbase.status.signedOut": "Signed out",
544
550
  "settings.hazbase.status.signedIn": "Signed in",
551
+ "settings.hazbase.status.sessionExpired": "Session expired",
545
552
  "settings.hazbase.status.otpAwaitingVerify": "Sent. Check your inbox, then enter the code below.",
546
553
  "settings.hazbase.passkey.ready": "Registered on this device",
547
554
  "settings.hazbase.passkey.missing": "Not registered yet",
@@ -552,6 +559,7 @@ const translations = {
552
559
  "settings.hazbase.field.otpLabel": "One-time password",
553
560
  "settings.hazbase.field.otpPlaceholder": "e.g. 123456",
554
561
  "settings.hazbase.action.requestOtp": "Send one-time password",
562
+ "settings.hazbase.action.refreshSession": "Refresh session",
555
563
  "settings.hazbase.action.resendOtp": "Resend",
556
564
  "settings.hazbase.action.verifyOtp": "Sign in",
557
565
  "settings.hazbase.action.changeEmail": "Change email",
@@ -567,6 +575,7 @@ const translations = {
567
575
  "settings.hazbase.notice.passkeyRegistered": "Passkey registered.",
568
576
  "settings.hazbase.notice.walletBootstrapped": "Wallet issued on chain {chainId}.",
569
577
  "settings.hazbase.notice.signedOut": "Signed out of wallet.",
578
+ "settings.hazbase.notice.sessionRefreshStarted": "Session refresh started. Send a one-time password to sign in again.",
570
579
  "settings.hazbase.prompt.email": "Wallet email address",
571
580
  "settings.hazbase.prompt.otp": "One-time password",
572
581
  "settings.row.hazbaseStatus": "Wallet",
@@ -639,6 +648,7 @@ const translations = {
639
648
  "error.choiceInputAlreadyHandled": "This choice request was already handled.",
640
649
  "error.mkcertRootCaNotFound": "The mkcert root CA file could not be found.",
641
650
  "error.hazbaseAuthRequired": "Sign in to your wallet first.",
651
+ "error.hazbaseSessionExpired": "Your wallet session expired. Open Wallet settings and sign in again.",
642
652
  "error.hazbaseEmailRequired": "Enter your email address first.",
643
653
  "error.hazbaseOtpRequired": "Enter the one-time password.",
644
654
  "error.hazbasePasskeyLocalHostRequired": "Open viveworker on its .local hostname to use hazBase passkeys.",
@@ -659,6 +669,7 @@ const translations = {
659
669
  "server.action.detail": "Detail",
660
670
  "server.action.select": "Choose",
661
671
  "server.action.approve": "Approve",
672
+ "server.action.payWithWallet": "Pay with wallet",
662
673
  "server.action.reject": "Reject",
663
674
  "server.action.implement": "Implement",
664
675
  "server.message.commandApprovalNeeded": "Command approval needed.",
@@ -1329,6 +1340,8 @@ const translations = {
1329
1340
  "settings.row.currentDeviceSubscribed": "この端末の購読状態",
1330
1341
  "settings.row.lastSuccessfulDelivery": "最後の通知成功時刻",
1331
1342
  "settings.row.version": "バージョン",
1343
+ "settings.updateAvailable.title": "新しいバージョンがあります",
1344
+ "settings.updateAvailable.copy": "viveworker v{latest} が利用できます。現在は v{current} です。",
1332
1345
  "settings.row.currentLanguage": "現在の言語",
1333
1346
  "settings.row.languageSource": "言語ソース",
1334
1347
  "settings.row.defaultLanguage": "setup 時の既定値",
@@ -1424,6 +1437,8 @@ const translations = {
1424
1437
  "settings.wallet.flow.title": "おすすめの順番",
1425
1438
  "settings.wallet.flow.banner.title": "まずは、セットアップしましょう",
1426
1439
  "settings.wallet.flow.copy": "A2A でタスクの報酬をやりとりするには、ウォレットを有効化する必要があります。",
1440
+ "settings.wallet.sessionExpired.title": "ウォレットセッションを更新しましょう",
1441
+ "settings.wallet.sessionExpired.copy": "ウォレットのセッションが切れています。ワンタイムパスワードで再サインインすれば、Passkey と Base Sepolia アドレスはそのまま使えます。",
1427
1442
  "settings.wallet.ready.title": "利用準備ができました",
1428
1443
  "settings.wallet.ready.copy": "メールサインイン、Passkey、Base Sepolia ウォレットの準備ができています。",
1429
1444
  "settings.wallet.ready.payoutIntro": "エージェントは下記アドレスを利用します:",
@@ -1437,6 +1452,8 @@ const translations = {
1437
1452
  "settings.wallet.status.optional": "任意",
1438
1453
  "settings.wallet.step.signIn.title": "メールでサインイン",
1439
1454
  "settings.wallet.step.signIn.copy": "メールにワンタイムパスワードを送り、届いた値を入力してウォレットにサインインします。",
1455
+ "settings.wallet.step.refreshSession.title": "セッションを更新",
1456
+ "settings.wallet.step.refreshSession.copy": "ウォレット操作を続ける前に、新しいワンタイムパスワードで再サインインします。",
1440
1457
  "settings.wallet.step.passkey.title": "Passkey を登録",
1441
1458
  "settings.wallet.step.passkey.copy": "この端末に Passkey を登録します。ウォレット発行や重要な操作で使います。",
1442
1459
  "settings.wallet.step.baseSepolia.title": "Base Sepolia ウォレットを発行",
@@ -1448,6 +1465,7 @@ const translations = {
1448
1465
  "settings.hazbase.title": "ウォレット",
1449
1466
  "settings.hazbase.status.signedOut": "未サインイン",
1450
1467
  "settings.hazbase.status.signedIn": "サインイン済み",
1468
+ "settings.hazbase.status.sessionExpired": "セッション切れ",
1451
1469
  "settings.hazbase.status.otpAwaitingVerify": "送信しました。メールを確認して、下のフィールドに入力してください。",
1452
1470
  "settings.hazbase.passkey.ready": "この端末で登録済み",
1453
1471
  "settings.hazbase.passkey.missing": "まだ登録されていません",
@@ -1458,6 +1476,7 @@ const translations = {
1458
1476
  "settings.hazbase.field.otpLabel": "ワンタイムパスワード",
1459
1477
  "settings.hazbase.field.otpPlaceholder": "例: 123456",
1460
1478
  "settings.hazbase.action.requestOtp": "ワンタイムパスワードを送信",
1479
+ "settings.hazbase.action.refreshSession": "セッションを更新",
1461
1480
  "settings.hazbase.action.resendOtp": "再送信",
1462
1481
  "settings.hazbase.action.verifyOtp": "サインイン",
1463
1482
  "settings.hazbase.action.changeEmail": "メールアドレスを変更",
@@ -1473,6 +1492,7 @@ const translations = {
1473
1492
  "settings.hazbase.notice.passkeyRegistered": "Passkeyを登録しました。",
1474
1493
  "settings.hazbase.notice.walletBootstrapped": "chain {chainId} にウォレットを発行しました。",
1475
1494
  "settings.hazbase.notice.signedOut": "ウォレットからログアウトしました。",
1495
+ "settings.hazbase.notice.sessionRefreshStarted": "セッション更新を開始しました。ワンタイムパスワードを送信して再サインインしてください。",
1476
1496
  "settings.hazbase.prompt.email": "ウォレットのメールアドレス",
1477
1497
  "settings.hazbase.prompt.otp": "ワンタイムパスワード",
1478
1498
  "settings.row.hazbaseStatus": "ウォレット",
@@ -1545,6 +1565,7 @@ const translations = {
1545
1565
  "error.choiceInputAlreadyHandled": "この選択入力はすでに処理済みです。",
1546
1566
  "error.mkcertRootCaNotFound": "mkcert の root CA ファイルが見つかりません。",
1547
1567
  "error.hazbaseAuthRequired": "先にウォレットへサインインしてください。",
1568
+ "error.hazbaseSessionExpired": "ウォレットのセッションが切れています。Wallet 設定を開いて再サインインしてください。",
1548
1569
  "error.hazbaseEmailRequired": "先にメールアドレスを入力してください。",
1549
1570
  "error.hazbaseOtpRequired": "ワンタイムパスワードを入力してください。",
1550
1571
  "error.hazbasePasskeyLocalHostRequired": ".local ホスト名で viveworker を開くと hazBase Passkey を使えます。",
@@ -1565,6 +1586,7 @@ const translations = {
1565
1586
  "server.action.detail": "詳細",
1566
1587
  "server.action.select": "選ぶ",
1567
1588
  "server.action.approve": "承認",
1589
+ "server.action.payWithWallet": "ウォレットで支払う",
1568
1590
  "server.action.reject": "拒否",
1569
1591
  "server.action.implement": "実装する",
1570
1592
  "server.message.commandApprovalNeeded": "コマンド実行の承認が必要です。",
package/web/sw.js CHANGED
@@ -1,4 +1,4 @@
1
- const CACHE_NAME = "viveworker-v47";
1
+ const CACHE_NAME = "viveworker-v56";
2
2
  const NOTIFICATION_INTENT_CACHE = "viveworker-notification-intent-v1";
3
3
  const NOTIFICATION_INTENT_PATH = "/__viveworker_notification_intent__";
4
4
  const APP_ASSETS = ["/app.css", "/app.js", "/i18n.js"];