@nextclaw/ui 0.12.4 → 0.12.5
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/CHANGELOG.md +41 -0
- package/dist/assets/{ChannelsList-CobWeI2V.js → ChannelsList-C6-lh55g.js} +2 -2
- package/dist/assets/ChatPage-DOW0gPc2.js +45 -0
- package/dist/assets/DocBrowser-CGyeswYP.js +1 -0
- package/dist/assets/{DocBrowser-NSzgVKka.js → DocBrowser-QUZ3nfmH.js} +1 -1
- package/dist/assets/{DocBrowserContext-DpgVdRgk.js → DocBrowserContext-CpiIfhJO.js} +1 -1
- package/dist/assets/{LogoBadge-CHS4YNLw.js → LogoBadge-BUK13xK5.js} +1 -1
- package/dist/assets/MarketplacePage-BDVwhIYE.js +1 -0
- package/dist/assets/MarketplacePage-LnKKL3xK.js +49 -0
- package/dist/assets/McpMarketplacePage-BG4T_Pcx.js +40 -0
- package/dist/assets/ModelConfig-LtWuogIw.js +1 -0
- package/dist/assets/ProviderScopedModelInput-DGn6sFEN.js +1 -0
- package/dist/assets/ProvidersList-ma-_MlLo.js +1 -0
- package/dist/assets/{RemoteAccessPage-yfbrveNQ.js → RemoteAccessPage-ff15qO-c.js} +1 -1
- package/dist/assets/RuntimeConfig-TgPandXF.js +1 -0
- package/dist/assets/SearchConfig-C9iBt7pl.js +1 -0
- package/dist/assets/{SecretsConfig-CLFSSoTl.js → SecretsConfig-Bew4EF2A.js} +2 -2
- package/dist/assets/{SessionsConfig-vYrvc2Fk.js → SessionsConfig-2r2yAGZg.js} +2 -2
- package/dist/assets/{book-open-C7TAghTk.js → book-open-CJG8Yz3U.js} +1 -1
- package/dist/assets/{chat-session-display-5dVFkJyw.js → chat-session-display-DkAC5OMC.js} +1 -1
- package/dist/assets/{chunk-JZWAC4HX-DbL4EmiT.js → chunk-JZWAC4HX-D5b3Iyas.js} +1 -1
- package/dist/assets/{config-CMiW0yaK.js → config-zvnxSXSP.js} +1 -1
- package/dist/assets/{createLucideIcon-BRLFtf-8.js → createLucideIcon-_FMJqZw2.js} +1 -1
- package/dist/assets/{dist-DP-JKR4G.js → dist-B1fpOuON.js} +1 -1
- package/dist/assets/{dist-BFc_H-lY.js → dist-BCXX7FD-.js} +2 -2
- package/dist/assets/{external-link-BkJkiWbH.js → external-link-b7gAJWYY.js} +1 -1
- package/dist/assets/{hash-CbP6-6R9.js → hash-Bhy4TwfZ.js} +1 -1
- package/dist/assets/{i18n-C_2dKw6w.js → i18n-DJg9BPYk.js} +1 -1
- package/dist/assets/index-BoJbxdvZ.css +1 -0
- package/dist/assets/index-CtlT4E9Y.js +6 -0
- package/dist/assets/infiniteQueryBehavior-CTcVlD9s.js +1 -0
- package/dist/assets/loader-circle-B60I0hEk.js +1 -0
- package/dist/assets/{logos-N3dbS6-I.js → logos-GMeYU9vc.js} +1 -1
- package/dist/assets/{page-layout-DyuvlNrg.js → page-layout-C8UbWuMt.js} +1 -1
- package/dist/assets/plus-CR7RfK3H.js +1 -0
- package/dist/assets/{popover-BKKWGUaG.js → popover-8HSx9wQj.js} +1 -1
- package/dist/assets/react-BB4jko2M.js +1 -0
- package/dist/assets/{refresh-ccw-BGMdiNGq.js → refresh-ccw-CA4_C7Zg.js} +1 -1
- package/dist/assets/{save-Dh4GQzzX.js → save-BtvMy4lk.js} +1 -1
- package/dist/assets/search-C60UA27E.js +1 -0
- package/dist/assets/security-config-BkFDYZ6j.js +1 -0
- package/dist/assets/{select-BtIi5fnh.js → select-xp_Ac8ip.js} +1 -1
- package/dist/assets/skeleton-uxz_5h3A.js +1 -0
- package/dist/assets/{status-dot-C4O-2jZP.js → status-dot-Cn4Pp7DZ.js} +1 -1
- package/dist/assets/{switch-DPegGIa_.js → switch-BTi6UOij.js} +1 -1
- package/dist/assets/{tabs-custom-x5GZexrF.js → tabs-custom-BiiN8DME.js} +1 -1
- package/dist/assets/{trash-2-CU3LYIpQ.js → trash-2-BpsF0N-r.js} +1 -1
- package/dist/assets/use-infinite-scroll-loader-C8jBv11-.js +1 -0
- package/dist/assets/{useConfirmDialog-S5WsGOGf.js → useConfirmDialog-BJIwUZjH.js} +1 -1
- package/dist/assets/{useMutation-DSinpgEq.js → useMutation-BjBOKHj_.js} +1 -1
- package/dist/assets/x-BfTu-g7D.js +1 -0
- package/dist/index.html +19 -18
- package/package.json +4 -4
- package/src/account/components/account-panel.tsx +46 -4
- package/src/account/managers/account.manager.ts +19 -4
- package/src/api/remote.ts +9 -0
- package/src/api/remote.types.ts +5 -0
- package/src/components/chat/ChatConversationPanel.test.tsx +183 -141
- package/src/components/chat/adapters/chat-message-tool-agent-id.test.ts +11 -11
- package/src/components/chat/adapters/chat-message.adapter.test.ts +43 -6
- package/src/components/chat/adapters/chat-message.session-request-tool-card.ts +182 -44
- package/src/components/chat/adapters/chat-message.session-spawn-tool-card.test.ts +104 -0
- package/src/components/chat/chat-child-session-panel.tsx +103 -45
- package/src/components/chat/chat-page-runtime.test.ts +16 -19
- package/src/components/chat/chat-session-preference-sync.test.ts +13 -0
- package/src/components/chat/chat-session-preference-sync.ts +9 -7
- package/src/components/chat/hooks/use-chat-session-project.test.tsx +5 -5
- package/src/components/chat/hooks/use-chat-session-project.ts +0 -5
- package/src/components/chat/hooks/use-chat-session-update.test.tsx +75 -0
- package/src/components/chat/hooks/use-chat-session-update.ts +4 -2
- package/src/components/chat/managers/chat-session-list.manager.test.ts +45 -5
- package/src/components/chat/managers/chat-session-list.manager.ts +18 -4
- package/src/components/chat/ncp/NcpChatPage.tsx +32 -51
- package/src/components/chat/ncp/ncp-chat-input.manager.ts +3 -5
- package/src/components/chat/ncp/ncp-chat-page-data.ts +0 -1
- package/src/components/chat/ncp/ncp-chat.presenter.ts +1 -11
- package/src/components/chat/ncp/session-conversation/use-ncp-child-session-tabs-view.ts +20 -7
- package/src/components/chat/stores/chat-session-list.store.ts +3 -0
- package/src/components/chat/useChatSessionTypeState.test.tsx +0 -3
- package/src/components/chat/useChatSessionTypeState.ts +3 -5
- package/src/components/config/ChannelsList.test.tsx +68 -0
- package/src/components/config/ChannelsList.tsx +22 -4
- package/src/components/config/ProvidersList.tsx +17 -3
- package/src/components/config/providers-list.test.tsx +68 -0
- package/src/components/layout/Sidebar.tsx +13 -13
- package/src/components/layout/sidebar.layout.test.tsx +32 -1
- package/src/components/marketplace/MarketplacePage.tsx +30 -30
- package/src/components/marketplace/marketplace-page-parts.tsx +16 -24
- package/src/components/marketplace/mcp/McpMarketplacePage.tsx +28 -26
- package/src/hooks/marketplace-list-pages.ts +27 -0
- package/src/hooks/use-infinite-scroll-loader.ts +88 -0
- package/src/hooks/useMarketplace.ts +14 -3
- package/src/hooks/useMcpMarketplace.ts +14 -3
- package/src/lib/i18n.remote.ts +15 -0
- package/dist/assets/ChatPage-ZIdFFVAv.js +0 -43
- package/dist/assets/DocBrowser-D55C0iyl.js +0 -1
- package/dist/assets/MarketplacePage-BFYsRss_.js +0 -49
- package/dist/assets/MarketplacePage-DII-q-Y1.js +0 -1
- package/dist/assets/McpMarketplacePage-CPqsGJzz.js +0 -40
- package/dist/assets/ModelConfig-Bvuo_IpS.js +0 -1
- package/dist/assets/ProviderScopedModelInput-BfY8rGsf.js +0 -1
- package/dist/assets/ProvidersList-3tlaqwSS.js +0 -1
- package/dist/assets/RuntimeConfig-CAd5Kta3.js +0 -1
- package/dist/assets/SearchConfig-DFwgaAa7.js +0 -1
- package/dist/assets/index-ChUXhq0G.css +0 -1
- package/dist/assets/index-DAE8Srx-.js +0 -6
- package/dist/assets/label-D8yyejJS.js +0 -1
- package/dist/assets/loader-circle-B0sKKO29.js +0 -1
- package/dist/assets/marketplace-localization-CxSTG9wr.js +0 -1
- package/dist/assets/plus-CYXs3JtZ.js +0 -1
- package/dist/assets/react-8EIEQjMP.js +0 -1
- package/dist/assets/search-DOsLw-P9.js +0 -1
- package/dist/assets/security-config-CM_tQRXQ.js +0 -1
- package/dist/assets/skeleton-GbHLjPC0.js +0 -1
- package/dist/assets/x-Bnco_K8b.js +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
import{_ as e,i as t,m as n,p as r}from"./i18n-
|
|
1
|
+
import{_ as e,i as t,m as n,p as r}from"./i18n-DJg9BPYk.js";import{o as i}from"./dist-BCXX7FD-.js";import{at as a,it as o,nt as s,ot as c,rt as l,tt as u}from"./index-CtlT4E9Y.js";var d=e(n(),1),f=r(),p=({open:e,onOpenChange:n,title:r,description:d,confirmLabel:p=t(`confirm`),cancelLabel:m=t(`cancel`),variant:h=`default`,onConfirm:g,onCancel:_})=>(0,f.jsx)(u,{open:e,onOpenChange:n,children:(0,f.jsxs)(s,{className:`[&>:last-child]:hidden`,onCloseAutoFocus:e=>e.preventDefault(),children:[(0,f.jsxs)(a,{children:[(0,f.jsx)(c,{children:r}),d?(0,f.jsx)(l,{children:d}):null]}),(0,f.jsxs)(o,{className:`gap-2 sm:gap-0`,children:[(0,f.jsx)(i,{type:`button`,variant:`outline`,onClick:()=>{_(),n(!1)},children:m}),(0,f.jsx)(i,{type:`button`,variant:h===`destructive`?`destructive`:`default`,onClick:()=>{g(),n(!1)},children:p})]})]})}),m={open:!1,title:``,description:``,confirmLabel:t(`confirm`),cancelLabel:t(`cancel`),variant:`default`,resolve:null};function h(){let[e,n]=(0,d.useState)(m),r=(0,d.useCallback)(e=>new Promise(r=>{n({open:!0,title:e.title,description:e.description??``,confirmLabel:e.confirmLabel??t(`confirm`),cancelLabel:e.cancelLabel??t(`cancel`),variant:e.variant??`default`,resolve:e=>{r(e),n(e=>({...e,open:!1,resolve:null}))}})}),[]),i=(0,d.useCallback)(e=>{n(t=>(!e&&t.resolve&&t.resolve(!1),{...t,open:e,resolve:e?t.resolve:null}))},[]);return{confirm:r,ConfirmDialog:(0,d.useCallback)(()=>(0,f.jsx)(p,{open:e.open,onOpenChange:i,title:e.title,description:e.description||void 0,confirmLabel:e.confirmLabel,cancelLabel:e.cancelLabel,variant:e.variant,onConfirm:()=>e.resolve?.(!0),onCancel:()=>e.resolve?.(!1)}),[e,i])}}export{h as t};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{_ as e,m as t}from"./i18n-
|
|
1
|
+
import{_ as e,m as t}from"./i18n-DJg9BPYk.js";import{M as n,O as r,P as i,_ as a,d as o,j as s,p as c,w as l}from"./dist-BCXX7FD-.js";var u=class extends i{#e;#t=void 0;#n;#r;constructor(e,t){super(),this.#e=e,this.setOptions(t),this.bindMethods(),this.#i()}bindMethods(){this.mutate=this.mutate.bind(this),this.reset=this.reset.bind(this)}setOptions(e){let t=this.options;this.options=this.#e.defaultMutationOptions(e),s(this.options,t)||this.#e.getMutationCache().notify({type:`observerOptionsUpdated`,mutation:this.#n,observer:this}),t?.mutationKey&&this.options.mutationKey&&l(t.mutationKey)!==l(this.options.mutationKey)?this.reset():this.#n?.state.status===`pending`&&this.#n.setOptions(this.options)}onUnsubscribe(){this.hasListeners()||this.#n?.removeObserver(this)}onMutationUpdate(e){this.#i(),this.#a(e)}getCurrentResult(){return this.#t}reset(){this.#n?.removeObserver(this),this.#n=void 0,this.#i(),this.#a()}mutate(e,t){return this.#r=t,this.#n?.removeObserver(this),this.#n=this.#e.getMutationCache().build(this.#e,this.options),this.#n.addObserver(this),this.#n.execute(e)}#i(){let e=this.#n?.state??c();this.#t={...e,isPending:e.status===`pending`,isSuccess:e.status===`success`,isError:e.status===`error`,isIdle:e.status===`idle`,mutate:this.mutate,reset:this.reset}}#a(e){a.batch(()=>{if(this.#r&&this.hasListeners()){let t=this.#t.variables,n=this.#t.context,r={client:this.#e,meta:this.options.meta,mutationKey:this.options.mutationKey};if(e?.type===`success`){try{this.#r.onSuccess?.(e.data,t,n,r)}catch(e){Promise.reject(e)}try{this.#r.onSettled?.(e.data,null,t,n,r)}catch(e){Promise.reject(e)}}else if(e?.type===`error`){try{this.#r.onError?.(e.error,t,n,r)}catch(e){Promise.reject(e)}try{this.#r.onSettled?.(void 0,e.error,t,n,r)}catch(e){Promise.reject(e)}}}this.listeners.forEach(e=>{e(this.#t)})})}},d=e(t(),1);function f(e,t){let i=o(t),[s]=d.useState(()=>new u(i,e));d.useEffect(()=>{s.setOptions(e)},[s,e]);let c=d.useSyncExternalStore(d.useCallback(e=>s.subscribe(a.batchCalls(e)),[s]),()=>s.getCurrentResult(),()=>s.getCurrentResult()),l=d.useCallback((e,t)=>{s.mutate(e,t).catch(r)},[s]);if(c.error&&n(s.options.throwOnError,[c.error]))throw c.error;return{...c,mutate:l,mutateAsync:c.mutate}}export{f as t};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{t as e}from"./createLucideIcon-_FMJqZw2.js";var t=e(`X`,[[`path`,{d:`M18 6 6 18`,key:`1bl5f8`}],[`path`,{d:`m6 6 12 12`,key:`d8bk6v`}]]);export{t};
|
package/dist/index.html
CHANGED
|
@@ -6,24 +6,25 @@
|
|
|
6
6
|
<link rel="icon" type="image/svg+xml" href="/logo.svg" />
|
|
7
7
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
8
8
|
<title>NextClaw</title>
|
|
9
|
-
<script type="module" crossorigin src="/assets/index-
|
|
10
|
-
<link rel="modulepreload" crossorigin href="/assets/i18n-
|
|
11
|
-
<link rel="modulepreload" crossorigin href="/assets/chunk-JZWAC4HX-
|
|
12
|
-
<link rel="modulepreload" crossorigin href="/assets/dist-
|
|
13
|
-
<link rel="modulepreload" crossorigin href="/assets/createLucideIcon-
|
|
14
|
-
<link rel="modulepreload" crossorigin href="/assets/select-
|
|
15
|
-
<link rel="modulepreload" crossorigin href="/assets/dist-
|
|
16
|
-
<link rel="modulepreload" crossorigin href="/assets/
|
|
17
|
-
<link rel="modulepreload" crossorigin href="/assets/
|
|
18
|
-
<link rel="modulepreload" crossorigin href="/assets/
|
|
19
|
-
<link rel="modulepreload" crossorigin href="/assets/
|
|
20
|
-
<link rel="modulepreload" crossorigin href="/assets/
|
|
21
|
-
<link rel="modulepreload" crossorigin href="/assets/
|
|
22
|
-
<link rel="modulepreload" crossorigin href="/assets/
|
|
23
|
-
<link rel="modulepreload" crossorigin href="/assets/
|
|
24
|
-
<link rel="modulepreload" crossorigin href="/assets/
|
|
25
|
-
<link rel="modulepreload" crossorigin href="/assets/
|
|
26
|
-
<link rel="
|
|
9
|
+
<script type="module" crossorigin src="/assets/index-CtlT4E9Y.js"></script>
|
|
10
|
+
<link rel="modulepreload" crossorigin href="/assets/i18n-DJg9BPYk.js">
|
|
11
|
+
<link rel="modulepreload" crossorigin href="/assets/chunk-JZWAC4HX-D5b3Iyas.js">
|
|
12
|
+
<link rel="modulepreload" crossorigin href="/assets/dist-BCXX7FD-.js">
|
|
13
|
+
<link rel="modulepreload" crossorigin href="/assets/createLucideIcon-_FMJqZw2.js">
|
|
14
|
+
<link rel="modulepreload" crossorigin href="/assets/select-xp_Ac8ip.js">
|
|
15
|
+
<link rel="modulepreload" crossorigin href="/assets/dist-B1fpOuON.js">
|
|
16
|
+
<link rel="modulepreload" crossorigin href="/assets/infiniteQueryBehavior-CTcVlD9s.js">
|
|
17
|
+
<link rel="modulepreload" crossorigin href="/assets/react-BB4jko2M.js">
|
|
18
|
+
<link rel="modulepreload" crossorigin href="/assets/useMutation-BjBOKHj_.js">
|
|
19
|
+
<link rel="modulepreload" crossorigin href="/assets/book-open-CJG8Yz3U.js">
|
|
20
|
+
<link rel="modulepreload" crossorigin href="/assets/external-link-b7gAJWYY.js">
|
|
21
|
+
<link rel="modulepreload" crossorigin href="/assets/plus-CR7RfK3H.js">
|
|
22
|
+
<link rel="modulepreload" crossorigin href="/assets/search-C60UA27E.js">
|
|
23
|
+
<link rel="modulepreload" crossorigin href="/assets/x-BfTu-g7D.js">
|
|
24
|
+
<link rel="modulepreload" crossorigin href="/assets/DocBrowserContext-CpiIfhJO.js">
|
|
25
|
+
<link rel="modulepreload" crossorigin href="/assets/DocBrowser-QUZ3nfmH.js">
|
|
26
|
+
<link rel="modulepreload" crossorigin href="/assets/config-zvnxSXSP.js">
|
|
27
|
+
<link rel="stylesheet" crossorigin href="/assets/index-BoJbxdvZ.css">
|
|
27
28
|
</head>
|
|
28
29
|
|
|
29
30
|
<body>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nextclaw/ui",
|
|
3
|
-
"version": "0.12.
|
|
3
|
+
"version": "0.12.5",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -28,10 +28,10 @@
|
|
|
28
28
|
"tailwind-merge": "^2.5.4",
|
|
29
29
|
"zod": "^3.23.8",
|
|
30
30
|
"zustand": "^5.0.2",
|
|
31
|
-
"@nextclaw/agent-chat": "0.1.8",
|
|
32
|
-
"@nextclaw/ncp-react": "0.4.17",
|
|
33
31
|
"@nextclaw/ncp": "0.5.0",
|
|
34
|
-
"@nextclaw/
|
|
32
|
+
"@nextclaw/ncp-react": "0.4.18",
|
|
33
|
+
"@nextclaw/agent-chat": "0.1.9",
|
|
34
|
+
"@nextclaw/agent-chat-ui": "0.3.2",
|
|
35
35
|
"@nextclaw/ncp-http-agent-client": "0.3.12"
|
|
36
36
|
},
|
|
37
37
|
"devDependencies": {
|
|
@@ -1,17 +1,19 @@
|
|
|
1
1
|
import { Button } from '@/components/ui/button';
|
|
2
2
|
import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle } from '@/components/ui/dialog';
|
|
3
|
+
import { Input } from '@/components/ui/input';
|
|
4
|
+
import { Label } from '@/components/ui/label';
|
|
3
5
|
import { useRemoteStatus } from '@/hooks/useRemoteAccess';
|
|
4
6
|
import { formatDateTime, t } from '@/lib/i18n';
|
|
5
7
|
import { useAccountStore } from '@/account/stores/account.store';
|
|
6
8
|
import { useAppPresenter } from '@/presenter/app-presenter-context';
|
|
7
9
|
import { KeyRound, LogOut, SquareArrowOutUpRight } from 'lucide-react';
|
|
8
|
-
import { useEffect } from 'react';
|
|
10
|
+
import { useEffect, useState } from 'react';
|
|
9
11
|
|
|
10
|
-
function AccountValueRow(
|
|
12
|
+
function AccountValueRow({ label, value }: { label: string; value?: string | null }) {
|
|
11
13
|
return (
|
|
12
14
|
<div className="flex items-start justify-between gap-4 py-2 text-sm">
|
|
13
|
-
<span className="text-gray-500">{
|
|
14
|
-
<span className="text-right text-gray-900">{
|
|
15
|
+
<span className="text-gray-500">{label}</span>
|
|
16
|
+
<span className="text-right text-gray-900">{value?.trim() || '-'}</span>
|
|
15
17
|
</div>
|
|
16
18
|
);
|
|
17
19
|
}
|
|
@@ -25,11 +27,15 @@ export function AccountPanel() {
|
|
|
25
27
|
const authExpiresAt = useAccountStore((state) => state.authExpiresAt);
|
|
26
28
|
const authStatusMessage = useAccountStore((state) => state.authStatusMessage);
|
|
27
29
|
const status = remoteStatus.data;
|
|
30
|
+
const [usernameDraft, setUsernameDraft] = useState('');
|
|
31
|
+
const [savingUsername, setSavingUsername] = useState(false);
|
|
28
32
|
|
|
29
33
|
useEffect(() => {
|
|
30
34
|
presenter.accountManager.syncRemoteStatus(status);
|
|
31
35
|
}, [presenter, status]);
|
|
32
36
|
|
|
37
|
+
const canSubmitUsername = !savingUsername && usernameDraft.trim().length > 0 && !status?.account.username;
|
|
38
|
+
|
|
33
39
|
return (
|
|
34
40
|
<Dialog open={panelOpen} onOpenChange={(open) => (open ? presenter.accountManager.openAccountPanel() : presenter.accountManager.closeAccountPanel())}>
|
|
35
41
|
<DialogContent className="max-w-xl">
|
|
@@ -49,8 +55,44 @@ export function AccountPanel() {
|
|
|
49
55
|
</div>
|
|
50
56
|
<div className="rounded-2xl border border-gray-200 bg-gray-50 px-4 py-3">
|
|
51
57
|
<AccountValueRow label={t('remoteAccountEmail')} value={status.account.email} />
|
|
58
|
+
<AccountValueRow label={t('remoteAccountUsername')} value={status.account.username} />
|
|
52
59
|
<AccountValueRow label={t('remoteAccountRole')} value={status.account.role} />
|
|
53
60
|
</div>
|
|
61
|
+
{status.account.username ? (
|
|
62
|
+
<p className="text-xs text-gray-500">{t('remoteAccountUsernameLockedHelp')}</p>
|
|
63
|
+
) : (
|
|
64
|
+
<div className="rounded-2xl border border-amber-200 bg-amber-50 px-4 py-4">
|
|
65
|
+
<p className="text-sm font-medium text-amber-900">{t('remoteAccountUsernameRequiredTitle')}</p>
|
|
66
|
+
<p className="mt-1 text-sm text-amber-800">{t('remoteAccountUsernameRequiredDescription')}</p>
|
|
67
|
+
<div className="mt-4 space-y-2">
|
|
68
|
+
<Label htmlFor="account-panel-username">{t('remoteAccountUsername')}</Label>
|
|
69
|
+
<Input
|
|
70
|
+
id="account-panel-username"
|
|
71
|
+
value={usernameDraft}
|
|
72
|
+
onChange={(event) => setUsernameDraft(event.target.value)}
|
|
73
|
+
placeholder={t('remoteAccountUsernamePlaceholder')}
|
|
74
|
+
autoCapitalize="none"
|
|
75
|
+
autoCorrect="off"
|
|
76
|
+
spellCheck={false}
|
|
77
|
+
/>
|
|
78
|
+
</div>
|
|
79
|
+
<div className="mt-4 flex flex-wrap gap-3">
|
|
80
|
+
<Button
|
|
81
|
+
disabled={!canSubmitUsername}
|
|
82
|
+
onClick={async () => {
|
|
83
|
+
setSavingUsername(true);
|
|
84
|
+
try {
|
|
85
|
+
await presenter.accountManager.updateUsername(usernameDraft);
|
|
86
|
+
} finally {
|
|
87
|
+
setSavingUsername(false);
|
|
88
|
+
}
|
|
89
|
+
}}
|
|
90
|
+
>
|
|
91
|
+
{savingUsername ? t('remoteAccountUsernameSaving') : t('remoteAccountUsernameSave')}
|
|
92
|
+
</Button>
|
|
93
|
+
</div>
|
|
94
|
+
</div>
|
|
95
|
+
)}
|
|
54
96
|
<div className="flex flex-wrap gap-3">
|
|
55
97
|
<Button onClick={() => void presenter.accountManager.openNextClawWeb()}>
|
|
56
98
|
<SquareArrowOutUpRight className="mr-2 h-4 w-4" />
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { logoutRemote, pollRemoteBrowserAuth, startRemoteBrowserAuth } from '@/api/remote';
|
|
1
|
+
import { logoutRemote, pollRemoteBrowserAuth, startRemoteBrowserAuth, updateRemoteAccountProfile } from '@/api/remote';
|
|
2
2
|
import type { RemoteAccessView } from '@/api/remote.types';
|
|
3
3
|
import type { AccountPendingAction } from '@/account/stores/account.store';
|
|
4
4
|
import { useAccountStore } from '@/account/stores/account.store';
|
|
@@ -57,12 +57,14 @@ export class AccountManager {
|
|
|
57
57
|
pendingAction?: AccountPendingAction;
|
|
58
58
|
}) => {
|
|
59
59
|
try {
|
|
60
|
+
const apiBase = params?.apiBase;
|
|
61
|
+
const pendingAction = params?.pendingAction;
|
|
60
62
|
const status = params?.status ?? (await ensureRemoteStatus());
|
|
61
|
-
if (
|
|
62
|
-
useAccountStore.getState().setPendingAction(
|
|
63
|
+
if (pendingAction) {
|
|
64
|
+
useAccountStore.getState().setPendingAction(pendingAction);
|
|
63
65
|
}
|
|
64
66
|
const result = await startRemoteBrowserAuth({
|
|
65
|
-
apiBase: resolveRemotePlatformApiBase(status,
|
|
67
|
+
apiBase: resolveRemotePlatformApiBase(status, apiBase)
|
|
66
68
|
});
|
|
67
69
|
useAccountStore.getState().beginBrowserAuth({
|
|
68
70
|
sessionId: result.sessionId,
|
|
@@ -103,6 +105,19 @@ export class AccountManager {
|
|
|
103
105
|
}
|
|
104
106
|
};
|
|
105
107
|
|
|
108
|
+
updateUsername = async (username: string) => {
|
|
109
|
+
try {
|
|
110
|
+
await updateRemoteAccountProfile({
|
|
111
|
+
username: username.trim()
|
|
112
|
+
});
|
|
113
|
+
await refreshRemoteStatus();
|
|
114
|
+
toast.success(t('remoteAccountUsernameSetSuccess'));
|
|
115
|
+
} catch (error) {
|
|
116
|
+
const message = error instanceof Error ? error.message : t('remoteAccountUsernameSetFailed');
|
|
117
|
+
toast.error(`${t('remoteAccountUsernameSetFailed')}: ${message}`);
|
|
118
|
+
}
|
|
119
|
+
};
|
|
120
|
+
|
|
106
121
|
openNextClawWeb = async () => {
|
|
107
122
|
const status = await ensureRemoteStatus();
|
|
108
123
|
const webBase = resolveRemoteWebBase(status);
|
package/src/api/remote.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { api } from './client';
|
|
2
2
|
import type {
|
|
3
3
|
RemoteAccessView,
|
|
4
|
+
RemoteAccountProfileUpdateRequest,
|
|
4
5
|
RemoteBrowserAuthPollRequest,
|
|
5
6
|
RemoteBrowserAuthPollResult,
|
|
6
7
|
RemoteBrowserAuthStartRequest,
|
|
@@ -60,6 +61,14 @@ export async function logoutRemote(): Promise<RemoteAccessView> {
|
|
|
60
61
|
return response.data;
|
|
61
62
|
}
|
|
62
63
|
|
|
64
|
+
export async function updateRemoteAccountProfile(data: RemoteAccountProfileUpdateRequest): Promise<RemoteAccessView> {
|
|
65
|
+
const response = await api.put<RemoteAccessView>('/api/remote/account/profile', data);
|
|
66
|
+
if (!response.ok) {
|
|
67
|
+
throw new Error(response.error.message);
|
|
68
|
+
}
|
|
69
|
+
return response.data;
|
|
70
|
+
}
|
|
71
|
+
|
|
63
72
|
export async function updateRemoteSettings(data: RemoteSettingsUpdateRequest): Promise<RemoteAccessView> {
|
|
64
73
|
const response = await api.put<RemoteAccessView>('/api/remote/settings', data);
|
|
65
74
|
if (!response.ok) {
|
package/src/api/remote.types.ts
CHANGED
|
@@ -1,11 +1,16 @@
|
|
|
1
1
|
export type RemoteAccountView = {
|
|
2
2
|
loggedIn: boolean;
|
|
3
3
|
email?: string;
|
|
4
|
+
username?: string | null;
|
|
4
5
|
role?: string;
|
|
5
6
|
platformBase?: string | null;
|
|
6
7
|
apiBase?: string | null;
|
|
7
8
|
};
|
|
8
9
|
|
|
10
|
+
export type RemoteAccountProfileUpdateRequest = {
|
|
11
|
+
username: string;
|
|
12
|
+
};
|
|
13
|
+
|
|
9
14
|
export type RemoteRuntimeView = {
|
|
10
15
|
enabled: boolean;
|
|
11
16
|
mode: "service" | "foreground";
|