feat: update openclaw workspace integration

This commit is contained in:
2026-03-27 22:27:16 +08:00
parent 5c08c1865c
commit 4aa69650e8
26 changed files with 2103 additions and 310 deletions

View File

@@ -7,10 +7,16 @@ export const useOpenClawStore = create(
// Raw data
openclawStatus: null,
openclawSessions: [],
openclawSessionsDefaults: null,
openclawSessionDetail: null,
openclawSessionHistory: [],
openclawCronJobs: [],
openclawApprovals: [],
openclawResolvedSessionKey: null,
openclawChatMessagesBySession: {},
openclawChatDraftBySession: {},
openclawChatSendingBySession: {},
openclawSessionSubscriptions: {},
// Loading states
isStatusLoading: false,
@@ -18,6 +24,7 @@ export const useOpenClawStore = create(
isSessionDetailLoading: false,
isCronLoading: false,
isApprovalsLoading: false,
isChatSending: false,
// Error states
statusError: null,
@@ -25,6 +32,7 @@ export const useOpenClawStore = create(
sessionDetailError: null,
cronError: null,
approvalsError: null,
chatError: null,
// Agents state
agents: [],
@@ -119,11 +127,129 @@ export const useOpenClawStore = create(
// Setters
setOpenclawStatus: (data) => set({ openclawStatus: data, statusError: null }),
setOpenclawSessions: (data) => set({ openclawSessions: data?.sessions || [], sessionsError: null }),
setOpenclawSessionDetail: (data) => set({ openclawSessionDetail: data?.session || null, sessionDetailError: null }),
setOpenclawSessionHistory: (data) => set({ openclawSessionHistory: data?.history || [], sessionDetailError: null }),
setOpenclawSessions: (data) => set({
openclawSessions: data?.sessions || [],
openclawSessionsDefaults: data?.defaults || null,
sessionsError: null,
}),
appendOpenclawSession: (session) => set((state) => {
const key = session?.key || session?.sessionKey;
if (!key) {
return {};
}
const existing = state.openclawSessions || [];
const deduped = existing.filter((item) => (item?.key || item?.sessionKey) !== key);
return { openclawSessions: [session, ...deduped] };
}),
removeOpenclawSession: (sessionKey) => set((state) => ({
openclawSessions: (state.openclawSessions || []).filter(
(item) => (item?.key || item?.sessionKey) !== sessionKey
),
selectedSessionKey:
state.selectedSessionKey === sessionKey ? null : state.selectedSessionKey,
})),
setOpenclawSessionDetail: (data) => set({ openclawSessionDetail: data?.session || null, sessionDetailError: data?.error || null }),
setOpenclawSessionHistory: (data) => set({ openclawSessionHistory: data?.history || [], sessionDetailError: data?.error || null }),
setOpenclawCronJobs: (data) => set({ openclawCronJobs: data?.cron || [], cronError: null }),
setOpenclawApprovals: (data) => set({ openclawApprovals: data?.approvals || [], approvalsError: null }),
setOpenclawResolvedSessionKey: (key) => set({ openclawResolvedSessionKey: key || null }),
setOpenclawChatDraft: (sessionKey, value) => set((state) => ({
openclawChatDraftBySession: { ...state.openclawChatDraftBySession, [sessionKey]: value },
})),
appendOpenclawChatMessage: (sessionKey, message) => set((state) => {
const current = state.openclawChatMessagesBySession[sessionKey] || [];
const sameMessageIndex = current.findIndex((item) => {
const sameId = Boolean(message?.id && item?.id && message.id === item.id);
const sameMessageId = Boolean(
message?.messageId &&
item?.messageId &&
message.messageId === item.messageId
);
const sameSeq = Boolean(
message?.seq !== undefined &&
message?.seq !== null &&
item?.seq !== undefined &&
item?.seq !== null &&
message.seq === item.seq &&
message?.role === item?.role
);
const incomingText = String(message?.text || '').trim();
const existingText = String(item?.text || '').trim();
const incomingTs = Date.parse(message?.timestamp || '');
const existingTs = Date.parse(item?.timestamp || '');
const nearInTime =
Number.isFinite(incomingTs) &&
Number.isFinite(existingTs) &&
Math.abs(incomingTs - existingTs) < 1500;
const sameAssistantText =
message?.role === 'assistant' &&
item?.role === 'assistant' &&
incomingText &&
existingText &&
(
incomingText === existingText ||
incomingText.startsWith(existingText) ||
existingText.startsWith(incomingText)
) &&
nearInTime;
return sameId || sameMessageId || sameSeq || sameAssistantText;
});
if (sameMessageIndex >= 0) {
const next = [...current];
next[sameMessageIndex] = { ...next[sameMessageIndex], ...message };
return {
openclawChatMessagesBySession: {
...state.openclawChatMessagesBySession,
[sessionKey]: next,
},
};
}
return {
openclawChatMessagesBySession: {
...state.openclawChatMessagesBySession,
[sessionKey]: [...current, message],
},
};
}),
replaceOpenclawChatHistory: (sessionKey, messages) => set((state) => {
const incoming = Array.isArray(messages) ? messages : [];
const existing = state.openclawChatMessagesBySession[sessionKey] || [];
const merged = [];
const seen = new Set();
const signatureFor = (message) => {
if (!message) return "";
if (message.id) return `id:${message.id}`;
if (message.messageId) return `mid:${message.messageId}`;
if (message.seq !== undefined && message.seq !== null) return `seq:${message.seq}`;
return `txt:${message.role || ""}:${String(message.text || "").trim()}`;
};
for (const message of [...incoming, ...existing]) {
const signature = signatureFor(message);
if (!signature || seen.has(signature)) {
continue;
}
seen.add(signature);
merged.push(message);
}
return {
openclawChatMessagesBySession: {
...state.openclawChatMessagesBySession,
[sessionKey]: merged,
},
};
}),
setOpenclawChatSendingForSession: (sessionKey, value) => set((state) => ({
openclawChatSendingBySession: { ...state.openclawChatSendingBySession, [sessionKey]: Boolean(value) },
isChatSending: Boolean(value),
})),
setOpenclawSessionSubscribed: (sessionKey, value) => set((state) => ({
openclawSessionSubscriptions: { ...state.openclawSessionSubscriptions, [sessionKey]: Boolean(value) },
})),
setSelectedSessionKey: (key) => set({ selectedSessionKey: key }),
@@ -138,6 +264,7 @@ export const useOpenClawStore = create(
setSessionDetailError: (e) => set({ sessionDetailError: e }),
setCronError: (e) => set({ cronError: e }),
setApprovalsError: (e) => set({ approvalsError: e }),
setChatError: (e) => set({ chatError: e }),
setAgents: (agents) => set({ agents }),
setAgentsLoading: (loading) => set({ agentsLoading: loading }),