mirror of
https://github.com/openclaw/openclaw.git
synced 2026-03-12 07:20:45 +00:00
refactor(extensions): reuse shared helper primitives
This commit is contained in:
@@ -1,6 +1,9 @@
|
||||
import {
|
||||
applyAccountNameToChannelSection,
|
||||
buildBaseChannelStatusSummary,
|
||||
buildChannelConfigSchema,
|
||||
buildRuntimeAccountStatusSnapshot,
|
||||
clearAccountEntryFields,
|
||||
DEFAULT_ACCOUNT_ID,
|
||||
deleteAccountFromConfigSection,
|
||||
formatPairingApproveHint,
|
||||
@@ -288,17 +291,21 @@ export const nextcloudTalkPlugin: ChannelPlugin<ResolvedNextcloudTalkAccount> =
|
||||
lastStopAt: null,
|
||||
lastError: null,
|
||||
},
|
||||
buildChannelSummary: ({ snapshot }) => ({
|
||||
configured: snapshot.configured ?? false,
|
||||
secretSource: snapshot.secretSource ?? "none",
|
||||
running: snapshot.running ?? false,
|
||||
mode: "webhook",
|
||||
lastStartAt: snapshot.lastStartAt ?? null,
|
||||
lastStopAt: snapshot.lastStopAt ?? null,
|
||||
lastError: snapshot.lastError ?? null,
|
||||
}),
|
||||
buildChannelSummary: ({ snapshot }) => {
|
||||
const base = buildBaseChannelStatusSummary(snapshot);
|
||||
return {
|
||||
configured: base.configured,
|
||||
secretSource: snapshot.secretSource ?? "none",
|
||||
running: base.running,
|
||||
mode: "webhook",
|
||||
lastStartAt: base.lastStartAt,
|
||||
lastStopAt: base.lastStopAt,
|
||||
lastError: base.lastError,
|
||||
};
|
||||
},
|
||||
buildAccountSnapshot: ({ account, runtime }) => {
|
||||
const configured = Boolean(account.secret?.trim() && account.baseUrl?.trim());
|
||||
const runtimeSnapshot = buildRuntimeAccountStatusSnapshot({ runtime });
|
||||
return {
|
||||
accountId: account.accountId,
|
||||
name: account.name,
|
||||
@@ -306,10 +313,10 @@ export const nextcloudTalkPlugin: ChannelPlugin<ResolvedNextcloudTalkAccount> =
|
||||
configured,
|
||||
secretSource: account.secretSource,
|
||||
baseUrl: account.baseUrl ? "[set]" : "[missing]",
|
||||
running: runtime?.running ?? false,
|
||||
lastStartAt: runtime?.lastStartAt ?? null,
|
||||
lastStopAt: runtime?.lastStopAt ?? null,
|
||||
lastError: runtime?.lastError ?? null,
|
||||
running: runtimeSnapshot.running,
|
||||
lastStartAt: runtimeSnapshot.lastStartAt,
|
||||
lastStopAt: runtimeSnapshot.lastStopAt,
|
||||
lastError: runtimeSnapshot.lastError,
|
||||
mode: "webhook",
|
||||
lastInboundAt: runtime?.lastInboundAt ?? null,
|
||||
lastOutboundAt: runtime?.lastOutboundAt ?? null,
|
||||
@@ -353,36 +360,20 @@ export const nextcloudTalkPlugin: ChannelPlugin<ResolvedNextcloudTalkAccount> =
|
||||
cleared = true;
|
||||
changed = true;
|
||||
}
|
||||
const accounts =
|
||||
nextSection.accounts && typeof nextSection.accounts === "object"
|
||||
? { ...nextSection.accounts }
|
||||
: undefined;
|
||||
if (accounts && accountId in accounts) {
|
||||
const entry = accounts[accountId];
|
||||
if (entry && typeof entry === "object") {
|
||||
const nextEntry = { ...entry } as Record<string, unknown>;
|
||||
if ("botSecret" in nextEntry) {
|
||||
const secret = nextEntry.botSecret;
|
||||
if (typeof secret === "string" ? secret.trim() : secret) {
|
||||
cleared = true;
|
||||
}
|
||||
delete nextEntry.botSecret;
|
||||
changed = true;
|
||||
}
|
||||
if (Object.keys(nextEntry).length === 0) {
|
||||
delete accounts[accountId];
|
||||
changed = true;
|
||||
} else {
|
||||
accounts[accountId] = nextEntry as typeof entry;
|
||||
}
|
||||
const accountCleanup = clearAccountEntryFields({
|
||||
accounts: nextSection.accounts,
|
||||
accountId,
|
||||
fields: ["botSecret"],
|
||||
});
|
||||
if (accountCleanup.changed) {
|
||||
changed = true;
|
||||
if (accountCleanup.cleared) {
|
||||
cleared = true;
|
||||
}
|
||||
}
|
||||
if (accounts) {
|
||||
if (Object.keys(accounts).length === 0) {
|
||||
delete nextSection.accounts;
|
||||
changed = true;
|
||||
if (accountCleanup.nextAccounts) {
|
||||
nextSection.accounts = accountCleanup.nextAccounts;
|
||||
} else {
|
||||
nextSection.accounts = accounts;
|
||||
delete nextSection.accounts;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import {
|
||||
GROUP_POLICY_BLOCKED_LABEL,
|
||||
createScopedPairingAccess,
|
||||
createNormalizedOutboundDeliverer,
|
||||
createReplyPrefixOptions,
|
||||
dispatchInboundReplyWithBase,
|
||||
formatTextWithAttachmentLinks,
|
||||
logInboundDrop,
|
||||
readStoreAllowFromForDmPolicy,
|
||||
@@ -291,43 +290,30 @@ export async function handleNextcloudTalkInbound(params: {
|
||||
CommandAuthorized: commandAuthorized,
|
||||
});
|
||||
|
||||
await core.channel.session.recordInboundSession({
|
||||
await dispatchInboundReplyWithBase({
|
||||
cfg: config as OpenClawConfig,
|
||||
channel: CHANNEL_ID,
|
||||
accountId: account.accountId,
|
||||
route,
|
||||
storePath,
|
||||
sessionKey: ctxPayload.SessionKey ?? route.sessionKey,
|
||||
ctx: ctxPayload,
|
||||
ctxPayload,
|
||||
core,
|
||||
deliver: async (payload) => {
|
||||
await deliverNextcloudTalkReply({
|
||||
payload,
|
||||
roomToken,
|
||||
accountId: account.accountId,
|
||||
statusSink,
|
||||
});
|
||||
},
|
||||
onRecordError: (err) => {
|
||||
runtime.error?.(`nextcloud-talk: failed updating session meta: ${String(err)}`);
|
||||
},
|
||||
});
|
||||
|
||||
const { onModelSelected, ...prefixOptions } = createReplyPrefixOptions({
|
||||
cfg: config as OpenClawConfig,
|
||||
agentId: route.agentId,
|
||||
channel: CHANNEL_ID,
|
||||
accountId: account.accountId,
|
||||
});
|
||||
const deliverReply = createNormalizedOutboundDeliverer(async (payload) => {
|
||||
await deliverNextcloudTalkReply({
|
||||
payload,
|
||||
roomToken,
|
||||
accountId: account.accountId,
|
||||
statusSink,
|
||||
});
|
||||
});
|
||||
|
||||
await core.channel.reply.dispatchReplyWithBufferedBlockDispatcher({
|
||||
ctx: ctxPayload,
|
||||
cfg: config as OpenClawConfig,
|
||||
dispatcherOptions: {
|
||||
...prefixOptions,
|
||||
deliver: deliverReply,
|
||||
onError: (err, info) => {
|
||||
runtime.error?.(`nextcloud-talk ${info.kind} reply failed: ${String(err)}`);
|
||||
},
|
||||
onDispatchError: (err, info) => {
|
||||
runtime.error?.(`nextcloud-talk ${info.kind} reply failed: ${String(err)}`);
|
||||
},
|
||||
replyOptions: {
|
||||
skillFilter: roomConfig?.skills,
|
||||
onModelSelected,
|
||||
disableBlockStreaming:
|
||||
typeof account.config.blockStreaming === "boolean"
|
||||
? !account.config.blockStreaming
|
||||
|
||||
@@ -43,6 +43,45 @@ function setNextcloudTalkDmPolicy(cfg: CoreConfig, dmPolicy: DmPolicy): CoreConf
|
||||
} as CoreConfig;
|
||||
}
|
||||
|
||||
function setNextcloudTalkAccountConfig(
|
||||
cfg: CoreConfig,
|
||||
accountId: string,
|
||||
updates: Record<string, unknown>,
|
||||
): CoreConfig {
|
||||
if (accountId === DEFAULT_ACCOUNT_ID) {
|
||||
return {
|
||||
...cfg,
|
||||
channels: {
|
||||
...cfg.channels,
|
||||
"nextcloud-talk": {
|
||||
...cfg.channels?.["nextcloud-talk"],
|
||||
enabled: true,
|
||||
...updates,
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
...cfg,
|
||||
channels: {
|
||||
...cfg.channels,
|
||||
"nextcloud-talk": {
|
||||
...cfg.channels?.["nextcloud-talk"],
|
||||
enabled: true,
|
||||
accounts: {
|
||||
...cfg.channels?.["nextcloud-talk"]?.accounts,
|
||||
[accountId]: {
|
||||
...cfg.channels?.["nextcloud-talk"]?.accounts?.[accountId],
|
||||
enabled: cfg.channels?.["nextcloud-talk"]?.accounts?.[accountId]?.enabled ?? true,
|
||||
...updates,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
async function noteNextcloudTalkSecretHelp(prompter: WizardPrompter): Promise<void> {
|
||||
await prompter.note(
|
||||
[
|
||||
@@ -105,40 +144,10 @@ async function promptNextcloudTalkAllowFrom(params: {
|
||||
];
|
||||
const unique = mergeAllowFromEntries(undefined, merged);
|
||||
|
||||
if (accountId === DEFAULT_ACCOUNT_ID) {
|
||||
return {
|
||||
...cfg,
|
||||
channels: {
|
||||
...cfg.channels,
|
||||
"nextcloud-talk": {
|
||||
...cfg.channels?.["nextcloud-talk"],
|
||||
enabled: true,
|
||||
dmPolicy: "allowlist",
|
||||
allowFrom: unique,
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
...cfg,
|
||||
channels: {
|
||||
...cfg.channels,
|
||||
"nextcloud-talk": {
|
||||
...cfg.channels?.["nextcloud-talk"],
|
||||
enabled: true,
|
||||
accounts: {
|
||||
...cfg.channels?.["nextcloud-talk"]?.accounts,
|
||||
[accountId]: {
|
||||
...cfg.channels?.["nextcloud-talk"]?.accounts?.[accountId],
|
||||
enabled: cfg.channels?.["nextcloud-talk"]?.accounts?.[accountId]?.enabled ?? true,
|
||||
dmPolicy: "allowlist",
|
||||
allowFrom: unique,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
return setNextcloudTalkAccountConfig(cfg, accountId, {
|
||||
dmPolicy: "allowlist",
|
||||
allowFrom: unique,
|
||||
});
|
||||
}
|
||||
|
||||
async function promptNextcloudTalkAllowFromForAccount(params: {
|
||||
@@ -265,41 +274,10 @@ export const nextcloudTalkOnboardingAdapter: ChannelOnboardingAdapter = {
|
||||
}
|
||||
|
||||
if (secretResult.action === "use-env" || secret || baseUrl !== resolvedAccount.baseUrl) {
|
||||
if (accountId === DEFAULT_ACCOUNT_ID) {
|
||||
next = {
|
||||
...next,
|
||||
channels: {
|
||||
...next.channels,
|
||||
"nextcloud-talk": {
|
||||
...next.channels?.["nextcloud-talk"],
|
||||
enabled: true,
|
||||
baseUrl,
|
||||
...(secret ? { botSecret: secret } : {}),
|
||||
},
|
||||
},
|
||||
};
|
||||
} else {
|
||||
next = {
|
||||
...next,
|
||||
channels: {
|
||||
...next.channels,
|
||||
"nextcloud-talk": {
|
||||
...next.channels?.["nextcloud-talk"],
|
||||
enabled: true,
|
||||
accounts: {
|
||||
...next.channels?.["nextcloud-talk"]?.accounts,
|
||||
[accountId]: {
|
||||
...next.channels?.["nextcloud-talk"]?.accounts?.[accountId],
|
||||
enabled:
|
||||
next.channels?.["nextcloud-talk"]?.accounts?.[accountId]?.enabled ?? true,
|
||||
baseUrl,
|
||||
...(secret ? { botSecret: secret } : {}),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
next = setNextcloudTalkAccountConfig(next, accountId, {
|
||||
baseUrl,
|
||||
...(secret ? { botSecret: secret } : {}),
|
||||
});
|
||||
}
|
||||
|
||||
const existingApiUser = resolvedAccount.config.apiUser?.trim();
|
||||
@@ -333,41 +311,10 @@ export const nextcloudTalkOnboardingAdapter: ChannelOnboardingAdapter = {
|
||||
preferredEnvVar: "NEXTCLOUD_TALK_API_PASSWORD",
|
||||
});
|
||||
const apiPassword = apiPasswordResult.action === "set" ? apiPasswordResult.value : undefined;
|
||||
if (accountId === DEFAULT_ACCOUNT_ID) {
|
||||
next = {
|
||||
...next,
|
||||
channels: {
|
||||
...next.channels,
|
||||
"nextcloud-talk": {
|
||||
...next.channels?.["nextcloud-talk"],
|
||||
enabled: true,
|
||||
apiUser,
|
||||
...(apiPassword ? { apiPassword } : {}),
|
||||
},
|
||||
},
|
||||
};
|
||||
} else {
|
||||
next = {
|
||||
...next,
|
||||
channels: {
|
||||
...next.channels,
|
||||
"nextcloud-talk": {
|
||||
...next.channels?.["nextcloud-talk"],
|
||||
enabled: true,
|
||||
accounts: {
|
||||
...next.channels?.["nextcloud-talk"]?.accounts,
|
||||
[accountId]: {
|
||||
...next.channels?.["nextcloud-talk"]?.accounts?.[accountId],
|
||||
enabled:
|
||||
next.channels?.["nextcloud-talk"]?.accounts?.[accountId]?.enabled ?? true,
|
||||
apiUser,
|
||||
...(apiPassword ? { apiPassword } : {}),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
next = setNextcloudTalkAccountConfig(next, accountId, {
|
||||
apiUser,
|
||||
...(apiPassword ? { apiPassword } : {}),
|
||||
});
|
||||
}
|
||||
|
||||
if (forceAllowFrom) {
|
||||
|
||||
Reference in New Issue
Block a user