mirror of
https://github.com/hansjone/dsh-im-ops.git
synced 2026-10-09 04:13:17 +08:00
Keep IM tool approvals in chat and add WhatsApp default model.
Claim in-flight IM turns before ownership flips active so approvals no longer stick only in DSH Web, auto-recover stale session models once, and let WhatsApp bots pick a shared default model for new sessions. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
2723e94541
commit
74c58bdcde
21 changed files with 1388 additions and 395 deletions
457
lib/client.js
457
lib/client.js
|
|
@ -566,7 +566,7 @@ __export(index_exports, {
|
|||
name: () => name
|
||||
});
|
||||
module.exports = __toCommonJS(index_exports);
|
||||
var React25 = __toESM(require("react"), 1);
|
||||
var React26 = __toESM(require("react"), 1);
|
||||
|
||||
// package.json
|
||||
var package_default = {
|
||||
|
|
@ -11122,6 +11122,177 @@ function installWeixinStyles() {
|
|||
return () => style.remove();
|
||||
}
|
||||
|
||||
// plugin-src/client/default-model.js
|
||||
var React19 = __toESM(require("react"), 1);
|
||||
|
||||
// src/channels/shared/default-model.mjs
|
||||
function normalizeDefaultModel(value) {
|
||||
if (value == null || value === "") return null;
|
||||
if (typeof value === "string") {
|
||||
const trimmed = value.trim();
|
||||
const slash = trimmed.indexOf("/");
|
||||
if (slash <= 0 || slash === trimmed.length - 1) return null;
|
||||
return {
|
||||
provider: trimmed.slice(0, slash),
|
||||
model: trimmed.slice(slash + 1)
|
||||
};
|
||||
}
|
||||
if (!value || typeof value !== "object" || Array.isArray(value)) return null;
|
||||
const provider = typeof value.provider === "string" ? value.provider.trim() : "";
|
||||
const model = typeof value.model === "string" ? value.model.trim() : "";
|
||||
if (!provider || !model) return null;
|
||||
const selection = { provider, model };
|
||||
if (value.reasoningEffort !== void 0) {
|
||||
if (typeof value.reasoningEffort !== "string" || !value.reasoningEffort.trim()) return null;
|
||||
selection.reasoningEffort = value.reasoningEffort.trim();
|
||||
}
|
||||
return selection;
|
||||
}
|
||||
function defaultModelKey(selection) {
|
||||
const normalized = normalizeDefaultModel(selection);
|
||||
return normalized ? `${normalized.provider}/${normalized.model}` : "";
|
||||
}
|
||||
function modelCatalogItems(catalog) {
|
||||
const items = [];
|
||||
const seen = /* @__PURE__ */ new Set();
|
||||
for (const group of Array.isArray(catalog?.groups) ? catalog.groups : []) {
|
||||
const provider = typeof group?.id === "string" ? group.id.trim() : "";
|
||||
if (!provider || !Array.isArray(group.models)) continue;
|
||||
for (const model of group.models) {
|
||||
const modelId = typeof model?.id === "string" ? model.id.trim() : "";
|
||||
if (!modelId) continue;
|
||||
const key = `${provider}/${modelId}`;
|
||||
if (seen.has(key)) continue;
|
||||
seen.add(key);
|
||||
const label = typeof model.name === "string" && model.name.trim() ? model.name.trim() : modelId;
|
||||
items.push({
|
||||
provider,
|
||||
model: modelId,
|
||||
key,
|
||||
label: label === modelId ? key : `${label}\uFF08${key}\uFF09`
|
||||
});
|
||||
}
|
||||
}
|
||||
return items;
|
||||
}
|
||||
function normalizeModelCatalog(value) {
|
||||
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
||||
return { groups: [], failures: [], items: [] };
|
||||
}
|
||||
const groups = Array.isArray(value.groups) ? value.groups : [];
|
||||
const failures = Array.isArray(value.failures) ? value.failures : [];
|
||||
return {
|
||||
groups,
|
||||
failures,
|
||||
items: modelCatalogItems({ groups, failures })
|
||||
};
|
||||
}
|
||||
|
||||
// plugin-src/client/default-model.js
|
||||
var SET_DEFAULT_MODEL_ENDPOINT = "bot.model.set";
|
||||
var EMPTY_MODEL_CATALOG = Object.freeze({
|
||||
groups: Object.freeze([]),
|
||||
failures: Object.freeze([]),
|
||||
items: Object.freeze([])
|
||||
});
|
||||
var ModelCatalogContext = React19.createContext(EMPTY_MODEL_CATALOG);
|
||||
function normalizeDefaultModelSelection(value) {
|
||||
return normalizeDefaultModel(value);
|
||||
}
|
||||
function normalizeHostModelCatalog(value) {
|
||||
return normalizeModelCatalog(value);
|
||||
}
|
||||
function DefaultModelEditor({ defaultModel = null, disabled = false, onSave }) {
|
||||
const catalog = React19.useContext(ModelCatalogContext) ?? EMPTY_MODEL_CATALOG;
|
||||
const helpId = React19.useId();
|
||||
const current = normalizeDefaultModel(defaultModel);
|
||||
const currentKey = defaultModelKey(current);
|
||||
const [saving, setSaving] = React19.useState(false);
|
||||
const [error, setError] = React19.useState(null);
|
||||
const items = [];
|
||||
const seen = /* @__PURE__ */ new Set();
|
||||
for (const item of Array.isArray(catalog.items) ? catalog.items : []) {
|
||||
if (!item?.key || seen.has(item.key)) continue;
|
||||
seen.add(item.key);
|
||||
items.push(item);
|
||||
}
|
||||
const currentUnavailable = Boolean(currentKey && !seen.has(currentKey));
|
||||
if (currentUnavailable && current) {
|
||||
items.push({
|
||||
key: currentKey,
|
||||
provider: current.provider,
|
||||
model: current.model,
|
||||
label: currentKey,
|
||||
unavailable: true
|
||||
});
|
||||
}
|
||||
const change = async (event) => {
|
||||
const nextKey = event.target.value;
|
||||
if (nextKey === currentKey || saving || disabled) return;
|
||||
setSaving(true);
|
||||
setError(null);
|
||||
try {
|
||||
await onSave?.(nextKey ? normalizeDefaultModel(nextKey) : null);
|
||||
} catch (cause) {
|
||||
setError(cause?.message ?? "\u9ED8\u8BA4\u6A21\u578B\u4FEE\u6539\u5931\u8D25\uFF0C\u8BF7\u91CD\u8BD5\u3002");
|
||||
} finally {
|
||||
setSaving(false);
|
||||
}
|
||||
};
|
||||
return h2(
|
||||
"div",
|
||||
{ className: "dim-preset" },
|
||||
h2(
|
||||
"div",
|
||||
{ className: "dim-presetHeader" },
|
||||
h2(
|
||||
"span",
|
||||
{ className: "dim-presetTitle" },
|
||||
h2("span", null, "\u9ED8\u8BA4\u6A21\u578B"),
|
||||
h2(
|
||||
"span",
|
||||
{ className: "dim-presetHelp" },
|
||||
h2("button", {
|
||||
type: "button",
|
||||
className: "dim-presetHelpButton",
|
||||
"aria-label": "\u67E5\u770B\u9ED8\u8BA4\u6A21\u578B\u8BF4\u660E",
|
||||
"aria-describedby": helpId
|
||||
}, h2("span", { "aria-hidden": "true" }, "?")),
|
||||
h2("span", {
|
||||
id: helpId,
|
||||
className: "dim-presetTooltip",
|
||||
role: "tooltip"
|
||||
}, "\u4E3A\u8BE5 WhatsApp \u673A\u5668\u4EBA\u7684\u65B0\u5EFA\u4F1A\u8BDD\u6307\u5B9A\u6A21\u578B\uFF0C\u907F\u514D\u6BCF\u4EBA\u5404\u81EA /model\u3002\u5DF2\u6709\u4F1A\u8BDD\u9700\u5148 /new \u518D\u53D1\u6D88\u606F\u624D\u4F1A\u751F\u6548\u3002")
|
||||
)
|
||||
),
|
||||
saving ? h2("span", { className: "dim-presetStatus" }, "\u4FDD\u5B58\u4E2D\u2026") : null
|
||||
),
|
||||
React19.createElement(
|
||||
"select",
|
||||
{
|
||||
className: "dim-presetSelect",
|
||||
value: currentKey,
|
||||
disabled: disabled || saving,
|
||||
"aria-label": "\u9ED8\u8BA4\u6A21\u578B",
|
||||
onChange: (event) => {
|
||||
void change(event);
|
||||
}
|
||||
},
|
||||
h2("option", { value: "" }, "\u8DDF\u968F Host \u9ED8\u8BA4"),
|
||||
...items.map((item) => h2(
|
||||
"option",
|
||||
{ key: item.key, value: item.key },
|
||||
item.unavailable ? [item.key, "\uFF08\u5DF2\u4E0D\u53EF\u7528\uFF09"] : item.label
|
||||
))
|
||||
),
|
||||
error || currentUnavailable ? h2(
|
||||
"p",
|
||||
{ className: "dim-presetError", role: error ? "alert" : "status" },
|
||||
error ?? "\u5F53\u524D\u9ED8\u8BA4\u6A21\u578B\u5DF2\u4E0D\u53EF\u7528\uFF0C\u8BF7\u9009\u62E9\u5176\u4ED6\u6A21\u578B\u6216\u8DDF\u968F Host \u9ED8\u8BA4\u3002"
|
||||
) : null
|
||||
);
|
||||
}
|
||||
|
||||
// src/channels/shared/access-grant.mjs
|
||||
var ACCESS_GRANT_VERSION = 1;
|
||||
var ACCESS_PENDING_TTL_MS = 7 * 24 * 60 * 60 * 1e3;
|
||||
|
|
@ -11359,6 +11530,7 @@ var WHATSAPP_ENDPOINTS = Object.freeze({
|
|||
setGroupSessionScope: "bot.group-session-scope.set",
|
||||
setWorkspace: "bot.workspace.set",
|
||||
setAgentPreset: SET_AGENT_PRESET_ENDPOINT,
|
||||
setDefaultModel: SET_DEFAULT_MODEL_ENDPOINT,
|
||||
setContextEnhancement: "bot.context-enhancement.set",
|
||||
resolveChannelPeer: "bot.session.channel-peer"
|
||||
});
|
||||
|
|
@ -11426,6 +11598,7 @@ function normalizeBot6(value) {
|
|||
state: connected ? "connected" : state,
|
||||
workspace: text5(value.workspace, "", 4096),
|
||||
agentPreset: normalizeAgentPresetId(value.agentPreset),
|
||||
defaultModel: normalizeDefaultModelSelection(value.defaultModel),
|
||||
contextEnhancement: normalizeContextEnhancementConfig(value.contextEnhancement),
|
||||
...Object.hasOwn(value, "accessPolicy") ? { accessPolicy: normalizeAccessPolicy(value.accessPolicy) } : {},
|
||||
...Object.hasOwn(value, "accessGrant") ? { accessGrant: normalizeAccessGrant(value.accessGrant) } : {},
|
||||
|
|
@ -11456,7 +11629,8 @@ function normalizeSnapshot8(value) {
|
|||
bots,
|
||||
totals: { configured: bots.length, connected: bots.filter((bot) => bot.connected).length },
|
||||
provisioning: source.provisioning ? normalizeProvisioning6(source.provisioning) : null,
|
||||
agentPresetCatalog: normalizeAgentPresetCatalog(source.agentPresetCatalog)
|
||||
agentPresetCatalog: normalizeAgentPresetCatalog(source.agentPresetCatalog),
|
||||
modelCatalog: normalizeHostModelCatalog(source.modelCatalog)
|
||||
};
|
||||
}
|
||||
function presentError9(error) {
|
||||
|
|
@ -11471,7 +11645,7 @@ function formatRemaining6(milliseconds) {
|
|||
}
|
||||
|
||||
// plugin-src/client/channels/whatsapp/index.js
|
||||
var React19 = __toESM(require("react"), 1);
|
||||
var React20 = __toESM(require("react"), 1);
|
||||
|
||||
// plugin-src/client/channels/whatsapp/styles.js
|
||||
var WHATSAPP_STYLE_ID = "xmanrui-dsh-im-whatsapp-settings";
|
||||
|
|
@ -11496,7 +11670,7 @@ function installWhatsappStyles() {
|
|||
|
||||
// plugin-src/client/channels/whatsapp/index.js
|
||||
var ACTIVE_STATES3 = /* @__PURE__ */ new Set(["pending", "connecting"]);
|
||||
var Button14 = React19.forwardRef(function Button15({ children, kind = "secondary", className = "", ...props }, ref) {
|
||||
var Button14 = React20.forwardRef(function Button15({ children, kind = "secondary", className = "", ...props }, ref) {
|
||||
return h2("button", {
|
||||
...props,
|
||||
ref,
|
||||
|
|
@ -11719,6 +11893,7 @@ function WhatsappAccountCard({
|
|||
onReconnect,
|
||||
onWorkspaceSave,
|
||||
onAgentPresetSave,
|
||||
onDefaultModelSave,
|
||||
onContextEnhancementSave,
|
||||
onRequestRemove,
|
||||
onConfirmRemove,
|
||||
|
|
@ -11783,6 +11958,11 @@ function WhatsappAccountCard({
|
|||
disabled: Boolean(busy),
|
||||
onSave: onAgentPresetSave
|
||||
}),
|
||||
h2(DefaultModelEditor, {
|
||||
defaultModel: account.defaultModel,
|
||||
disabled: Boolean(busy),
|
||||
onSave: onDefaultModelSave
|
||||
}),
|
||||
h2(ContextEnhancementEditor, {
|
||||
config: account.contextEnhancement,
|
||||
disabled: Boolean(busy),
|
||||
|
|
@ -11830,23 +12010,24 @@ function WhatsappAccountCard({
|
|||
);
|
||||
}
|
||||
function WhatsappSettingsTab({ rpcCall }) {
|
||||
const [model, setModel] = React19.useState({
|
||||
const [model, setModel] = React20.useState({
|
||||
phase: "loading",
|
||||
bots: [],
|
||||
totals: { configured: 0, connected: 0 },
|
||||
error: null,
|
||||
agentPresetCatalog: EMPTY_AGENT_PRESET_CATALOG
|
||||
agentPresetCatalog: EMPTY_AGENT_PRESET_CATALOG,
|
||||
modelCatalog: EMPTY_MODEL_CATALOG
|
||||
});
|
||||
const [provision, setProvision] = React19.useState(null);
|
||||
const [busy, setBusy] = React19.useState(false);
|
||||
const [busyByBot, setBusyByBot] = React19.useState({});
|
||||
const [testNoticeByBot, setTestNoticeByBot] = React19.useState({});
|
||||
const [removeTarget, setRemoveTarget] = React19.useState(null);
|
||||
const [now, setNow] = React19.useState(Date.now());
|
||||
const mounted = React19.useRef(true);
|
||||
const [provision, setProvision] = React20.useState(null);
|
||||
const [busy, setBusy] = React20.useState(false);
|
||||
const [busyByBot, setBusyByBot] = React20.useState({});
|
||||
const [testNoticeByBot, setTestNoticeByBot] = React20.useState({});
|
||||
const [removeTarget, setRemoveTarget] = React20.useState(null);
|
||||
const [now, setNow] = React20.useState(Date.now());
|
||||
const mounted = React20.useRef(true);
|
||||
const workspaceFence = useWorkspaceSnapshotFence();
|
||||
const addButtonRef = React19.useRef(null);
|
||||
React19.useEffect(() => {
|
||||
const addButtonRef = React20.useRef(null);
|
||||
React20.useEffect(() => {
|
||||
const disposeDingtalk = installDingtalkStyles();
|
||||
const disposeWhatsapp = installWhatsappStyles();
|
||||
mounted.current = true;
|
||||
|
|
@ -11856,11 +12037,11 @@ function WhatsappSettingsTab({ rpcCall }) {
|
|||
disposeDingtalk();
|
||||
};
|
||||
}, []);
|
||||
const invoke = React19.useCallback(async (endpoint, payload = {}, signal) => {
|
||||
const invoke = React20.useCallback(async (endpoint, payload = {}, signal) => {
|
||||
if (typeof rpcCall !== "function") throw new TypeError("WhatsApp \u8BBE\u7F6E\u9875\u7F3A\u5C11 RPC \u8FDE\u63A5");
|
||||
return unwrapRpcResult9(await rpcCall(endpoint, payload, signal));
|
||||
}, [rpcCall]);
|
||||
const loadStatus = React19.useCallback(async ({ signal, silent = false, restore = false } = {}) => {
|
||||
const loadStatus = React20.useCallback(async ({ signal, silent = false, restore = false } = {}) => {
|
||||
const workspaceVersion = workspaceFence.beginStatus();
|
||||
if (workspaceVersion === null) return void 0;
|
||||
if (!silent && mounted.current) setModel((current) => ({ ...current, phase: "loading", error: null }));
|
||||
|
|
@ -11872,7 +12053,8 @@ function WhatsappSettingsTab({ rpcCall }) {
|
|||
bots: snapshot.bots,
|
||||
totals: snapshot.totals,
|
||||
error: null,
|
||||
agentPresetCatalog: snapshot.agentPresetCatalog ?? EMPTY_AGENT_PRESET_CATALOG
|
||||
agentPresetCatalog: snapshot.agentPresetCatalog ?? EMPTY_AGENT_PRESET_CATALOG,
|
||||
modelCatalog: snapshot.modelCatalog ?? EMPTY_MODEL_CATALOG
|
||||
});
|
||||
if (restore && snapshot.provisioning) setProvision({
|
||||
...snapshot.provisioning,
|
||||
|
|
@ -11890,12 +12072,12 @@ function WhatsappSettingsTab({ rpcCall }) {
|
|||
return void 0;
|
||||
}
|
||||
}, [invoke, workspaceFence]);
|
||||
React19.useEffect(() => {
|
||||
React20.useEffect(() => {
|
||||
const controller = new AbortController();
|
||||
void loadStatus({ signal: controller.signal, restore: true });
|
||||
return () => controller.abort();
|
||||
}, [loadStatus]);
|
||||
React19.useEffect(() => {
|
||||
React20.useEffect(() => {
|
||||
if (model.phase !== "ready") return void 0;
|
||||
const controller = new AbortController();
|
||||
const timer = window.setInterval(
|
||||
|
|
@ -11907,12 +12089,12 @@ function WhatsappSettingsTab({ rpcCall }) {
|
|||
window.clearInterval(timer);
|
||||
};
|
||||
}, [loadStatus, model.phase]);
|
||||
React19.useEffect(() => {
|
||||
React20.useEffect(() => {
|
||||
if (!provision || !ACTIVE_STATES3.has(provision.status)) return void 0;
|
||||
const timer = window.setInterval(() => mounted.current && setNow(Date.now()), 1e3);
|
||||
return () => window.clearInterval(timer);
|
||||
}, [provision?.attemptId, provision?.status]);
|
||||
const startProvisioning = React19.useCallback(async (replace = false) => {
|
||||
const startProvisioning = React20.useCallback(async (replace = false) => {
|
||||
setBusy(true);
|
||||
try {
|
||||
if (replace && provision?.attemptId) {
|
||||
|
|
@ -11930,7 +12112,7 @@ function WhatsappSettingsTab({ rpcCall }) {
|
|||
if (mounted.current) setBusy(false);
|
||||
}
|
||||
}, [invoke, provision?.attemptId]);
|
||||
const closeProvision = React19.useCallback(async () => {
|
||||
const closeProvision = React20.useCallback(async () => {
|
||||
setBusy(true);
|
||||
try {
|
||||
if (provision?.attemptId && ACTIVE_STATES3.has(provision.status)) {
|
||||
|
|
@ -11941,7 +12123,7 @@ function WhatsappSettingsTab({ rpcCall }) {
|
|||
if (mounted.current) setBusy(false);
|
||||
}
|
||||
}, [invoke, provision?.attemptId, provision?.status]);
|
||||
React19.useEffect(() => {
|
||||
React20.useEffect(() => {
|
||||
const attemptId = provision?.attemptId;
|
||||
if (!attemptId || !ACTIVE_STATES3.has(provision.status)) return void 0;
|
||||
const controller = new AbortController();
|
||||
|
|
@ -11982,7 +12164,7 @@ function WhatsappSettingsTab({ rpcCall }) {
|
|||
if (timer) window.clearTimeout(timer);
|
||||
};
|
||||
}, [invoke, loadStatus, provision?.attemptId, provision?.status]);
|
||||
const botAction = React19.useCallback(async (account, operation, endpoint, payload) => {
|
||||
const botAction = React20.useCallback(async (account, operation, endpoint, payload) => {
|
||||
const snapshotVersion = workspaceFence.beginMutation();
|
||||
setBusyByBot((current) => ({ ...current, [account.botId]: operation }));
|
||||
if (operation === "reconnect") {
|
||||
|
|
@ -12001,7 +12183,8 @@ function WhatsappSettingsTab({ rpcCall }) {
|
|||
bots: snapshot.bots,
|
||||
totals: snapshot.totals,
|
||||
error: null,
|
||||
agentPresetCatalog: snapshot.agentPresetCatalog ?? EMPTY_AGENT_PRESET_CATALOG
|
||||
agentPresetCatalog: snapshot.agentPresetCatalog ?? EMPTY_AGENT_PRESET_CATALOG,
|
||||
modelCatalog: snapshot.modelCatalog ?? EMPTY_MODEL_CATALOG
|
||||
});
|
||||
if (operation === "reconnect") {
|
||||
setTestNoticeByBot((current) => ({
|
||||
|
|
@ -12059,6 +12242,12 @@ function WhatsappSettingsTab({ rpcCall }) {
|
|||
WHATSAPP_ENDPOINTS.setAgentPreset,
|
||||
{ botId: account.botId, agentPreset }
|
||||
),
|
||||
onDefaultModelSave: (defaultModel) => botAction(
|
||||
account,
|
||||
"model",
|
||||
WHATSAPP_ENDPOINTS.setDefaultModel,
|
||||
{ botId: account.botId, defaultModel }
|
||||
),
|
||||
onContextEnhancementSave: (config) => botAction(
|
||||
account,
|
||||
"context-enhancement",
|
||||
|
|
@ -12078,6 +12267,8 @@ function WhatsappSettingsTab({ rpcCall }) {
|
|||
) : null;
|
||||
return h2(AgentPresetCatalogContext.Provider, {
|
||||
value: model.agentPresetCatalog ?? EMPTY_AGENT_PRESET_CATALOG
|
||||
}, h2(ModelCatalogContext.Provider, {
|
||||
value: model.modelCatalog ?? EMPTY_MODEL_CATALOG
|
||||
}, h2(
|
||||
"section",
|
||||
{
|
||||
|
|
@ -12101,7 +12292,7 @@ function WhatsappSettingsTab({ rpcCall }) {
|
|||
h2(Button14, { onClick: () => void loadStatus() }, "\u91CD\u65B0\u8BFB\u53D6")
|
||||
)
|
||||
) : h2(
|
||||
React19.Fragment,
|
||||
React20.Fragment,
|
||||
null,
|
||||
provision?.status === "pending" ? h2(QrPanel5, {
|
||||
provision,
|
||||
|
|
@ -12117,11 +12308,11 @@ function WhatsappSettingsTab({ rpcCall }) {
|
|||
}) : model.bots.length === 0 ? h2(EmptyView6, { busy, onStart: () => void startProvisioning(false) }) : null,
|
||||
botList
|
||||
)
|
||||
));
|
||||
)));
|
||||
}
|
||||
|
||||
// plugin-src/client/channel-peer-label.js
|
||||
var React20 = __toESM(require("react"), 1);
|
||||
var React21 = __toESM(require("react"), 1);
|
||||
var CHANNEL_LABELS = Object.freeze({
|
||||
whatsapp: "WhatsApp",
|
||||
feishu: "\u98DE\u4E66",
|
||||
|
|
@ -12135,8 +12326,8 @@ var CHANNEL_LABELS = Object.freeze({
|
|||
office: "AI Office"
|
||||
});
|
||||
function ChannelPeerLabel({ sessionId, resolveChannelPeer }) {
|
||||
const [peer, setPeer] = React20.useState(null);
|
||||
React20.useEffect(() => {
|
||||
const [peer, setPeer] = React21.useState(null);
|
||||
React21.useEffect(() => {
|
||||
if (typeof resolveChannelPeer !== "function" || typeof sessionId !== "string" || !sessionId) {
|
||||
setPeer(null);
|
||||
return void 0;
|
||||
|
|
@ -12193,10 +12384,10 @@ async function resolveWhatsappChannelPeer(whatsappRpcCall, sessionId, signal) {
|
|||
}
|
||||
|
||||
// plugin-src/client/delivery-settings.js
|
||||
var React23 = __toESM(require("react"), 1);
|
||||
var React24 = __toESM(require("react"), 1);
|
||||
|
||||
// plugin-src/client/access-policy-settings.js
|
||||
var React21 = __toESM(require("react"), 1);
|
||||
var React22 = __toESM(require("react"), 1);
|
||||
var ACCESS_POLICY_ENDPOINT = "bot.access-policy.set";
|
||||
var GROUP_SESSION_SCOPE_ENDPOINT = "bot.group-session-scope.set";
|
||||
var ACCESS_CHANNEL_DEFINITIONS = Object.freeze({
|
||||
|
|
@ -12299,8 +12490,8 @@ function ScenePolicyEditor({
|
|||
unsupported = false,
|
||||
onChange
|
||||
}) {
|
||||
const ownerHelpId = React21.useId();
|
||||
const emptyAllowlistHelpId = React21.useId();
|
||||
const ownerHelpId = React22.useId();
|
||||
const emptyAllowlistHelpId = React22.useId();
|
||||
const allowlist = policy.mode === "allowlist";
|
||||
const collectionKey = allowlist ? "users" : "commandPermissionOverrides";
|
||||
const branchKey = allowlist ? "allowlist" : "open";
|
||||
|
|
@ -12352,7 +12543,7 @@ function ScenePolicyEditor({
|
|||
h2("strong", null, "\u5F53\u524D\u6E20\u9053\u4E0D\u652F\u6301\u7FA4\u804A"),
|
||||
h2("p", null, "\u6B64\u533A\u57DF\u65E0\u9700\u914D\u7F6E\uFF0C\u4FDD\u5B58\u79C1\u804A\u8BBE\u7F6E\u65F6\u4F1A\u4FDD\u7559\u73B0\u6709\u7FA4\u804A\u7B56\u7565\u3002")
|
||||
) : h2(
|
||||
React21.Fragment,
|
||||
React22.Fragment,
|
||||
null,
|
||||
h2(
|
||||
"div",
|
||||
|
|
@ -12494,18 +12685,18 @@ function AccessPolicySettingsPage({ channel: channel4, account, rpcCall, onSaved
|
|||
const initialPolicy = normalizeAccessPolicy(account?.accessPolicy);
|
||||
const initialKey = JSON.stringify(initialPolicy);
|
||||
const initialScope = normalizeGroupSessionScope(account?.groupSessionScope);
|
||||
const [draft, setDraft] = React21.useState(() => clonePolicy(
|
||||
const [draft, setDraft] = React22.useState(() => clonePolicy(
|
||||
initialPolicy ?? DEFAULT_ACCESS_POLICY
|
||||
));
|
||||
const [groupSessionScope, setGroupSessionScope] = React21.useState(initialScope);
|
||||
const [saving, setSaving] = React21.useState(false);
|
||||
const [feedback, setFeedback] = React21.useState(null);
|
||||
React21.useEffect(() => {
|
||||
const [groupSessionScope, setGroupSessionScope] = React22.useState(initialScope);
|
||||
const [saving, setSaving] = React22.useState(false);
|
||||
const [feedback, setFeedback] = React22.useState(null);
|
||||
React22.useEffect(() => {
|
||||
const next = normalizeAccessPolicy(account?.accessPolicy);
|
||||
setDraft(clonePolicy(next ?? DEFAULT_ACCESS_POLICY));
|
||||
setGroupSessionScope(normalizeGroupSessionScope(account?.groupSessionScope));
|
||||
}, [account?.botId, initialKey, account?.groupSessionScope]);
|
||||
React21.useEffect(() => {
|
||||
React22.useEffect(() => {
|
||||
setFeedback(null);
|
||||
}, [account?.botId]);
|
||||
if (!definition) {
|
||||
|
|
@ -12658,7 +12849,7 @@ function AccessPolicySettingsPage({ channel: channel4, account, rpcCall, onSaved
|
|||
}
|
||||
|
||||
// plugin-src/client/access-grant-settings.js
|
||||
var React22 = __toESM(require("react"), 1);
|
||||
var React23 = __toESM(require("react"), 1);
|
||||
var ACCESS_GRANT_ENDPOINT = "bot.access-grant.set";
|
||||
var ACCESS_PENDING_RESOLVE_ENDPOINT = "bot.access-pending.resolve";
|
||||
var ACCESS_GROUP_TITLES_REFRESH_ENDPOINT = "bot.access-group-titles.refresh";
|
||||
|
|
@ -12750,13 +12941,13 @@ function PhoneTypeahead({
|
|||
disabled,
|
||||
requirePhone = true
|
||||
}) {
|
||||
const [query, setQuery] = React22.useState(value || "");
|
||||
const [open, setOpen] = React22.useState(false);
|
||||
const blurTimer = React22.useRef(null);
|
||||
React22.useEffect(() => {
|
||||
const [query, setQuery] = React23.useState(value || "");
|
||||
const [open, setOpen] = React23.useState(false);
|
||||
const blurTimer = React23.useRef(null);
|
||||
React23.useEffect(() => {
|
||||
setQuery(value || "");
|
||||
}, [value]);
|
||||
React22.useEffect(() => () => {
|
||||
React23.useEffect(() => () => {
|
||||
if (blurTimer.current) window.clearTimeout(blurTimer.current);
|
||||
}, []);
|
||||
const q = query.trim().toLowerCase();
|
||||
|
|
@ -13064,21 +13255,21 @@ function AccessGrantSettingsPage({ channel: channel4, account, rpcCall, onSaved
|
|||
const initialGrant = normalizeAccessGrant(account?.accessGrant);
|
||||
const initialKey = JSON.stringify(initialGrant);
|
||||
const initialScope = normalizeGroupSessionScope(account?.groupSessionScope);
|
||||
const [draft, setDraft] = React22.useState(() => cloneGrant(initialGrant, ownerPhone));
|
||||
const [groupSessionScope, setGroupSessionScope] = React22.useState(initialScope);
|
||||
const [saving, setSaving] = React22.useState(false);
|
||||
const [feedback, setFeedback] = React22.useState(null);
|
||||
const [newGroupJid, setNewGroupJid] = React22.useState("");
|
||||
const [loadingGrant, setLoadingGrant] = React22.useState(!initialGrant);
|
||||
const contextCatalog = React22.useContext(AgentPresetCatalogContext);
|
||||
const [presetCatalog, setPresetCatalog] = React22.useState(() => normalizeAgentPresetCatalog(
|
||||
const [draft, setDraft] = React23.useState(() => cloneGrant(initialGrant, ownerPhone));
|
||||
const [groupSessionScope, setGroupSessionScope] = React23.useState(initialScope);
|
||||
const [saving, setSaving] = React23.useState(false);
|
||||
const [feedback, setFeedback] = React23.useState(null);
|
||||
const [newGroupJid, setNewGroupJid] = React23.useState("");
|
||||
const [loadingGrant, setLoadingGrant] = React23.useState(!initialGrant);
|
||||
const contextCatalog = React23.useContext(AgentPresetCatalogContext);
|
||||
const [presetCatalog, setPresetCatalog] = React23.useState(() => normalizeAgentPresetCatalog(
|
||||
account?.agentPresetCatalog ?? contextCatalog ?? EMPTY_AGENT_PRESET_CATALOG
|
||||
));
|
||||
React22.useEffect(() => {
|
||||
React23.useEffect(() => {
|
||||
setDraft(cloneGrant(normalizeAccessGrant(account?.accessGrant), ownerPhone));
|
||||
setGroupSessionScope(normalizeGroupSessionScope(account?.groupSessionScope));
|
||||
}, [account?.botId, initialKey, account?.groupSessionScope, ownerPhone]);
|
||||
React22.useEffect(() => {
|
||||
React23.useEffect(() => {
|
||||
if (typeof rpcCall !== "function" || !account?.botId) return void 0;
|
||||
let cancelled = false;
|
||||
setLoadingGrant(true);
|
||||
|
|
@ -13132,7 +13323,7 @@ function AccessGrantSettingsPage({ channel: channel4, account, rpcCall, onSaved
|
|||
};
|
||||
}, [account?.botId, rpcCall, ownerPhone]);
|
||||
const contacts = draft.contacts ?? [];
|
||||
const knownGroupJids = React22.useMemo(() => {
|
||||
const knownGroupJids = React23.useMemo(() => {
|
||||
const set = new Set(Object.keys(draft.groups ?? {}));
|
||||
for (const contact of contacts) {
|
||||
for (const jid of contact.groupJids ?? []) set.add(jid);
|
||||
|
|
@ -13142,7 +13333,7 @@ function AccessGrantSettingsPage({ channel: channel4, account, rpcCall, onSaved
|
|||
}
|
||||
return [...set].sort();
|
||||
}, [draft.groups, draft.pending, contacts]);
|
||||
const actionableContacts = React22.useMemo(
|
||||
const actionableContacts = React23.useMemo(
|
||||
() => contacts.filter((contact) => contactNeedsGrantAction(contact, draft, knownGroupJids)),
|
||||
[contacts, draft, knownGroupJids]
|
||||
);
|
||||
|
|
@ -13821,13 +14012,13 @@ function TargetForm({
|
|||
}) {
|
||||
const editing = mode === "edit";
|
||||
const initialKind = initialValue?.kind && definition.fields[initialValue.kind] ? initialValue.kind : definition.kinds[0].value;
|
||||
const [targetId, setTargetId] = React23.useState(initialValue?.targetId ?? "");
|
||||
const [name2, setName] = React23.useState(initialValue?.name ?? "");
|
||||
const [kind, setKind] = React23.useState(initialKind);
|
||||
const [route, setRoute] = React23.useState(initialValue?.route ?? {});
|
||||
const [error, setError] = React23.useState(null);
|
||||
const [testing, setTesting] = React23.useState(false);
|
||||
const [testState, setTestState] = React23.useState(null);
|
||||
const [targetId, setTargetId] = React24.useState(initialValue?.targetId ?? "");
|
||||
const [name2, setName] = React24.useState(initialValue?.name ?? "");
|
||||
const [kind, setKind] = React24.useState(initialKind);
|
||||
const [route, setRoute] = React24.useState(initialValue?.route ?? {});
|
||||
const [error, setError] = React24.useState(null);
|
||||
const [testing, setTesting] = React24.useState(false);
|
||||
const [testState, setTestState] = React24.useState(null);
|
||||
const currentTarget = () => {
|
||||
const normalizedRoute = Object.fromEntries(fieldsFor(definition, kind).map((field) => {
|
||||
const raw = String(route[field.key] ?? "").trim();
|
||||
|
|
@ -14042,7 +14233,7 @@ function TargetSuggestionPicker({
|
|||
}
|
||||
},
|
||||
// Platform display names must stay raw (bypass h() i18n phrase rewrite).
|
||||
React23.createElement(
|
||||
React24.createElement(
|
||||
"strong",
|
||||
null,
|
||||
suggestionDisplayName(suggestion) || suggestionFallbackName(definition, suggestion)
|
||||
|
|
@ -14051,7 +14242,7 @@ function TargetSuggestionPicker({
|
|||
localizeText(kindLabel(definition, suggestion.kind)),
|
||||
added ? localizeText("\u5DF2\u6DFB\u52A0") : null
|
||||
].filter(Boolean).join(" \xB7 ")),
|
||||
React23.createElement("code", null, fieldsFor(definition, suggestion.kind).map((field) => maskRouteValue(suggestion.route?.[field.key])).filter(Boolean).join(" \xB7 "))
|
||||
React24.createElement("code", null, fieldsFor(definition, suggestion.kind).map((field) => maskRouteValue(suggestion.route?.[field.key])).filter(Boolean).join(" \xB7 "))
|
||||
)
|
||||
);
|
||||
})
|
||||
|
|
@ -14065,10 +14256,10 @@ function TargetSuggestionPicker({
|
|||
);
|
||||
}
|
||||
function TargetRow({ definition, target, botId, connected, rpcCall, onChanged, onEdit }) {
|
||||
const [action, setAction] = React23.useState(null);
|
||||
const [testState, setTestState] = React23.useState(null);
|
||||
const [copyState, setCopyState] = React23.useState(null);
|
||||
const [confirmDelete, setConfirmDelete] = React23.useState(false);
|
||||
const [action, setAction] = React24.useState(null);
|
||||
const [testState, setTestState] = React24.useState(null);
|
||||
const [copyState, setCopyState] = React24.useState(null);
|
||||
const [confirmDelete, setConfirmDelete] = React24.useState(false);
|
||||
const testTarget = async () => {
|
||||
setAction("test");
|
||||
setTestState(null);
|
||||
|
|
@ -14110,7 +14301,7 @@ function TargetRow({ definition, target, botId, connected, rpcCall, onChanged, o
|
|||
h2(
|
||||
"div",
|
||||
{ className: "dim-targetTitle" },
|
||||
React23.createElement("strong", null, target.name || target.targetId),
|
||||
React24.createElement("strong", null, target.name || target.targetId),
|
||||
h2("span", null, kindLabel(definition, target.kind))
|
||||
),
|
||||
h2("code", null, `targetId: ${target.targetId}`)
|
||||
|
|
@ -14173,28 +14364,28 @@ function DeliveryTargetSettingsPage({
|
|||
onBack
|
||||
}) {
|
||||
const definition = CHANNEL_DEFINITIONS[channel4];
|
||||
const [activeTabId, setActiveTabId] = React23.useState(BOT_SETTINGS_TABS[0].id);
|
||||
const [phase, setPhase] = React23.useState("loading");
|
||||
const [targets, setTargets] = React23.useState([]);
|
||||
const [suggestionPhase, setSuggestionPhase] = React23.useState("idle");
|
||||
const [suggestions, setSuggestions] = React23.useState([]);
|
||||
const [suggestionError, setSuggestionError] = React23.useState(null);
|
||||
const [error, setError] = React23.useState(null);
|
||||
const [editor, setEditor] = React23.useState(null);
|
||||
const [saving, setSaving] = React23.useState(false);
|
||||
const [botCopyState, setBotCopyState] = React23.useState(null);
|
||||
const [accessPolicy, setAccessPolicy] = React23.useState(account.accessPolicy);
|
||||
const [accessGrant, setAccessGrant] = React23.useState(account.accessGrant);
|
||||
const mounted = React23.useRef(true);
|
||||
React23.useEffect(() => {
|
||||
const [activeTabId, setActiveTabId] = React24.useState(BOT_SETTINGS_TABS[0].id);
|
||||
const [phase, setPhase] = React24.useState("loading");
|
||||
const [targets, setTargets] = React24.useState([]);
|
||||
const [suggestionPhase, setSuggestionPhase] = React24.useState("idle");
|
||||
const [suggestions, setSuggestions] = React24.useState([]);
|
||||
const [suggestionError, setSuggestionError] = React24.useState(null);
|
||||
const [error, setError] = React24.useState(null);
|
||||
const [editor, setEditor] = React24.useState(null);
|
||||
const [saving, setSaving] = React24.useState(false);
|
||||
const [botCopyState, setBotCopyState] = React24.useState(null);
|
||||
const [accessPolicy, setAccessPolicy] = React24.useState(account.accessPolicy);
|
||||
const [accessGrant, setAccessGrant] = React24.useState(account.accessGrant);
|
||||
const mounted = React24.useRef(true);
|
||||
React24.useEffect(() => {
|
||||
setAccessPolicy(account.accessPolicy);
|
||||
setAccessGrant(account.accessGrant);
|
||||
}, [account.botId, account.accessPolicy, account.accessGrant]);
|
||||
const invoke = React23.useCallback(async (endpoint, payload = {}, signal) => {
|
||||
const invoke = React24.useCallback(async (endpoint, payload = {}, signal) => {
|
||||
if (typeof rpcCall !== "function") throw new Error("\u6295\u9012\u76EE\u6807\u8BBE\u7F6E\u6682\u4E0D\u53EF\u7528\u3002");
|
||||
return unwrapRpcResult12(await rpcCall(endpoint, payload, signal));
|
||||
}, [rpcCall]);
|
||||
const loadTargets = React23.useCallback(async ({ signal, silent = false } = {}) => {
|
||||
const loadTargets = React24.useCallback(async ({ signal, silent = false } = {}) => {
|
||||
if (!silent) setPhase("loading");
|
||||
setError(null);
|
||||
try {
|
||||
|
|
@ -14208,7 +14399,7 @@ function DeliveryTargetSettingsPage({
|
|||
setPhase("error");
|
||||
}
|
||||
}, [account.botId, invoke]);
|
||||
const loadSuggestions = React23.useCallback(async () => {
|
||||
const loadSuggestions = React24.useCallback(async () => {
|
||||
setSuggestionPhase("loading");
|
||||
setSuggestionError(null);
|
||||
try {
|
||||
|
|
@ -14222,7 +14413,7 @@ function DeliveryTargetSettingsPage({
|
|||
setSuggestionPhase("error");
|
||||
}
|
||||
}, [account.botId, definition, invoke]);
|
||||
React23.useEffect(() => {
|
||||
React24.useEffect(() => {
|
||||
mounted.current = true;
|
||||
const controller = new AbortController();
|
||||
void loadTargets({ signal: controller.signal });
|
||||
|
|
@ -14349,7 +14540,7 @@ function DeliveryTargetSettingsPage({
|
|||
rpcCall: accessRpcCall,
|
||||
onSaved: setAccessPolicy
|
||||
}) : h2(
|
||||
React23.Fragment,
|
||||
React24.Fragment,
|
||||
null,
|
||||
h2(
|
||||
"section",
|
||||
|
|
@ -15170,7 +15361,7 @@ function installImStyles() {
|
|||
}
|
||||
|
||||
// plugin-src/client/update-panel.js
|
||||
var React24 = __toESM(require("react"), 1);
|
||||
var React25 = __toESM(require("react"), 1);
|
||||
var import_react_dom3 = require("react-dom");
|
||||
var import_valid = __toESM(require_valid(), 1);
|
||||
var import_rcompare = __toESM(require_rcompare(), 1);
|
||||
|
|
@ -15260,11 +15451,11 @@ function manualUpdateCommand(snapshot) {
|
|||
return `dsh plugin --profile ${profileArgument} add -w dsh-im-ops@${version}`;
|
||||
}
|
||||
function ManualUpdateCommand({ command, disabled, sourceInstall, desktop }) {
|
||||
const [copyState, setCopyState] = React24.useState("idle");
|
||||
const commandRef = React24.useRef(null);
|
||||
const mounted = React24.useRef(false);
|
||||
const copying = React24.useRef(false);
|
||||
React24.useEffect(() => {
|
||||
const [copyState, setCopyState] = React25.useState("idle");
|
||||
const commandRef = React25.useRef(null);
|
||||
const mounted = React25.useRef(false);
|
||||
const copying = React25.useRef(false);
|
||||
React25.useEffect(() => {
|
||||
mounted.current = true;
|
||||
return () => {
|
||||
mounted.current = false;
|
||||
|
|
@ -15296,7 +15487,7 @@ function ManualUpdateCommand({ command, disabled, sourceInstall, desktop }) {
|
|||
{ className: "dim-updateManual", "aria-label": "\u624B\u5DE5\u66F4\u65B0" },
|
||||
h2("h4", { className: "dim-updateManualHeading" }, "\u624B\u5DE5\u66F4\u65B0"),
|
||||
command ? h2(
|
||||
React24.Fragment,
|
||||
React25.Fragment,
|
||||
null,
|
||||
h2("p", { className: "dim-updateManualHint" }, "\u81EA\u52A8\u66F4\u65B0\u5931\u8D25\u53EF\u4EE5\u4F7F\u7528\u547D\u4EE4\u66F4\u65B0\uFF1A"),
|
||||
h2(
|
||||
|
|
@ -15332,7 +15523,7 @@ function ManualUpdateCommand({ command, disabled, sourceInstall, desktop }) {
|
|||
"aria-hidden": "true",
|
||||
focusable: "false"
|
||||
}, copyState === "copied" ? h2("path", { d: "m4 10 4 4 8-8" }) : h2(
|
||||
React24.Fragment,
|
||||
React25.Fragment,
|
||||
null,
|
||||
h2("rect", { x: 7, y: 7, width: 10, height: 11, rx: 1.5 }),
|
||||
h2("path", { d: "M5 13H3.5A1.5 1.5 0 0 1 2 11.5v-8A1.5 1.5 0 0 1 3.5 2h8A1.5 1.5 0 0 1 13 3.5V5" })
|
||||
|
|
@ -15357,10 +15548,10 @@ function ManualUpdateCommand({ command, disabled, sourceInstall, desktop }) {
|
|||
);
|
||||
}
|
||||
function UpdateDialog({ children, onClose }) {
|
||||
const dialogRef = React24.useRef(null);
|
||||
const titleId = React24.useId();
|
||||
const descriptionId = React24.useId();
|
||||
React24.useEffect(() => {
|
||||
const dialogRef = React25.useRef(null);
|
||||
const titleId = React25.useId();
|
||||
const descriptionId = React25.useId();
|
||||
React25.useEffect(() => {
|
||||
const previous = globalThis.document?.activeElement;
|
||||
dialogRef.current?.focus?.();
|
||||
return () => {
|
||||
|
|
@ -15418,19 +15609,19 @@ function UpdateDialog({ children, onClose }) {
|
|||
return typeof document !== "undefined" && document.body ? (0, import_react_dom3.createPortal)(content, document.body) : content;
|
||||
}
|
||||
function UpdatePanel({ rpcCall, clientVersion, onStatus }) {
|
||||
const [snapshot, setSnapshot] = React24.useState(null);
|
||||
const [action, setAction] = React24.useState("status");
|
||||
const [error, setError] = React24.useState(null);
|
||||
const [open, setOpen] = React24.useState(false);
|
||||
const [uncertainInstall, setUncertainInstall] = React24.useState(false);
|
||||
const mounted = React24.useRef(false);
|
||||
const busy = React24.useRef(false);
|
||||
const readController = React24.useRef(null);
|
||||
const pollReadController = React24.useRef(null);
|
||||
const installRequest = React24.useRef(null);
|
||||
const onStatusRef = React24.useRef(onStatus);
|
||||
const [snapshot, setSnapshot] = React25.useState(null);
|
||||
const [action, setAction] = React25.useState("status");
|
||||
const [error, setError] = React25.useState(null);
|
||||
const [open, setOpen] = React25.useState(false);
|
||||
const [uncertainInstall, setUncertainInstall] = React25.useState(false);
|
||||
const mounted = React25.useRef(false);
|
||||
const busy = React25.useRef(false);
|
||||
const readController = React25.useRef(null);
|
||||
const pollReadController = React25.useRef(null);
|
||||
const installRequest = React25.useRef(null);
|
||||
const onStatusRef = React25.useRef(onStatus);
|
||||
onStatusRef.current = onStatus;
|
||||
const accept = React24.useCallback((next) => {
|
||||
const accept = React25.useCallback((next) => {
|
||||
setSnapshot(next);
|
||||
onStatusRef.current?.(next);
|
||||
}, []);
|
||||
|
|
@ -15439,7 +15630,7 @@ function UpdatePanel({ rpcCall, clientVersion, onStatus }) {
|
|||
setUncertainInstall(false);
|
||||
accept(next);
|
||||
};
|
||||
const invoke = React24.useCallback(async (endpoint, payload = {}, signal) => {
|
||||
const invoke = React25.useCallback(async (endpoint, payload = {}, signal) => {
|
||||
if (typeof rpcCall !== "function") {
|
||||
const unavailable = new Error("\u5F53\u524D Host \u4E0D\u652F\u6301\u66F4\u65B0\u63A5\u53E3\uFF0C\u8BF7\u5148\u624B\u52A8\u66F4\u65B0\u63D2\u4EF6\u5E76\u91CD\u542F\u3002");
|
||||
unavailable.code = "update-unavailable";
|
||||
|
|
@ -15447,7 +15638,7 @@ function UpdatePanel({ rpcCall, clientVersion, onStatus }) {
|
|||
}
|
||||
return unwrapSnapshot(await rpcCall(endpoint, payload, signal));
|
||||
}, [rpcCall]);
|
||||
React24.useEffect(() => {
|
||||
React25.useEffect(() => {
|
||||
mounted.current = true;
|
||||
busy.current = true;
|
||||
const controller = new AbortController();
|
||||
|
|
@ -15470,7 +15661,7 @@ function UpdatePanel({ rpcCall, clientVersion, onStatus }) {
|
|||
const activeJob = ACTIVE_STATES4.has(snapshot?.job?.state);
|
||||
const restartRequired = snapshot?.job?.state === "restart-required" || snapshot?.blockedReason === "pending-restart";
|
||||
const shouldPoll = activeJob || uncertainInstall;
|
||||
React24.useEffect(() => {
|
||||
React25.useEffect(() => {
|
||||
if (!shouldPoll) return void 0;
|
||||
let controller;
|
||||
const scheduler = createPollScheduler({
|
||||
|
|
@ -15568,7 +15759,7 @@ function UpdatePanel({ rpcCall, clientVersion, onStatus }) {
|
|||
const manualCommand = manualUpdateCommand(snapshot);
|
||||
const buttonLabel = action === "checking" ? "\u68C0\u67E5\u4E2D\u2026" : action === "starting" || activeJob ? "\u6B63\u5728\u66F4\u65B0\u2026" : restartRequired ? "\u5F85\u624B\u52A8\u91CD\u542F" : snapshot?.canInstall ? "\u66F4\u65B0\u81F3" : "\u68C0\u67E5\u66F4\u65B0";
|
||||
return h2(
|
||||
React24.Fragment,
|
||||
React25.Fragment,
|
||||
null,
|
||||
h2("button", {
|
||||
type: "button",
|
||||
|
|
@ -15593,13 +15784,13 @@ function UpdatePanel({ rpcCall, clientVersion, onStatus }) {
|
|||
h2("dt", null, "\u8FD0\u884C\u7248\u672C"),
|
||||
h2("dd", null, `v${snapshot?.runningVersion ?? clientVersion}`),
|
||||
snapshot?.installedVersion && snapshot.installedVersion !== snapshot.runningVersion ? h2(
|
||||
React24.Fragment,
|
||||
React25.Fragment,
|
||||
null,
|
||||
h2("dt", null, "\u5DF2\u5B89\u88C5\u7248\u672C"),
|
||||
h2("dd", null, `v${snapshot.installedVersion}`)
|
||||
) : null,
|
||||
targetVersion ? h2(
|
||||
React24.Fragment,
|
||||
React25.Fragment,
|
||||
null,
|
||||
h2("dt", null, "\u76EE\u6807\u7248\u672C"),
|
||||
h2("dd", null, `v${targetVersion}`)
|
||||
|
|
@ -15812,20 +16003,20 @@ function IMSettingsTab({
|
|||
browserLocation = globalThis.location,
|
||||
navigateToRecoveryUrl = replacePageLocation
|
||||
}) {
|
||||
const [selected, setSelected] = React25.useState("weixin");
|
||||
const [loopbackRecovery, setLoopbackRecovery] = React25.useState(null);
|
||||
const [runningVersion, setRunningVersion] = React25.useState(IM_PLUGIN_VERSION);
|
||||
const [deliverySettings, setDeliverySettings] = React25.useState(null);
|
||||
const githubTooltipId = React25.useId();
|
||||
const channelSelectId = React25.useId();
|
||||
const [selected, setSelected] = React26.useState("weixin");
|
||||
const [loopbackRecovery, setLoopbackRecovery] = React26.useState(null);
|
||||
const [runningVersion, setRunningVersion] = React26.useState(IM_PLUGIN_VERSION);
|
||||
const [deliverySettings, setDeliverySettings] = React26.useState(null);
|
||||
const githubTooltipId = React26.useId();
|
||||
const channelSelectId = React26.useId();
|
||||
const active = CHANNELS.find((channel4) => channel4.id === selected) ?? CHANNELS[0];
|
||||
const reportLoopbackRecovery = React25.useCallback((recovery) => {
|
||||
const reportLoopbackRecovery = React26.useCallback((recovery) => {
|
||||
setLoopbackRecovery((current) => current?.url === recovery.url ? current : recovery);
|
||||
}, []);
|
||||
const reportUpdateStatus = React25.useCallback((snapshot) => {
|
||||
const reportUpdateStatus = React26.useCallback((snapshot) => {
|
||||
setRunningVersion(snapshot.runningVersion);
|
||||
}, []);
|
||||
const rpcCalls = React25.useMemo(() => createLoopbackAwareRpcCalls({
|
||||
const rpcCalls = React26.useMemo(() => createLoopbackAwareRpcCalls({
|
||||
dingtalkRpcCall,
|
||||
discordRpcCall,
|
||||
feishuRpcCall,
|
||||
|
|
@ -15857,7 +16048,7 @@ function IMSettingsTab({
|
|||
weixinRpcCall,
|
||||
whatsappRpcCall
|
||||
]);
|
||||
const botSettingsContext = React25.useMemo(() => Object.freeze({
|
||||
const botSettingsContext = React26.useMemo(() => Object.freeze({
|
||||
openBotSettings: setDeliverySettings
|
||||
}), []);
|
||||
return h2(
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue