@ycodium-ai/plugin-im 0.2.2974 → 0.2.2978
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/README.md +19 -13
- package/assets/ui.js +201 -0
- package/dist/index.js +855 -350
- package/locales/en.json +65 -5
- package/locales/zh-CN.json +65 -5
- package/package.json +17 -4
package/dist/index.js
CHANGED
|
@@ -126213,9 +126213,6 @@ var ATTACHED_THREAD_LIMIT = 200;
|
|
|
126213
126213
|
var attachedKey = (chatKey, threadId) => `${chatKey}
|
|
126214
126214
|
${threadId}`;
|
|
126215
126215
|
var hasAttached = (state, chatKey, threadId) => state.attached?.[attachedKey(chatKey, threadId)] !== void 0;
|
|
126216
|
-
var attachedOnChat = (state, chatKey, projectId) => Object.values(state.attached ?? {}).filter(
|
|
126217
|
-
(record2) => record2.chatKey === chatKey && record2.projectId === projectId
|
|
126218
|
-
);
|
|
126219
126216
|
var nonEmpty = (value2) => typeof value2 === "string" && value2 !== "" ? value2 : null;
|
|
126220
126217
|
var readAttached = (data) => {
|
|
126221
126218
|
const chatKey = nonEmpty(data["chatKey"]);
|
|
@@ -126655,6 +126652,49 @@ var readString = (row, key) => {
|
|
|
126655
126652
|
return typeof value2 === "string" ? value2.trim() : "";
|
|
126656
126653
|
};
|
|
126657
126654
|
|
|
126655
|
+
// src/settingsContract.ts
|
|
126656
|
+
var SETTINGS_VIEW_COMMAND = "settings.view";
|
|
126657
|
+
var SETTINGS_SAVE_BOT_COMMAND = "settings.saveBot";
|
|
126658
|
+
var SETTINGS_REMOVE_BOT_COMMAND = "settings.removeBot";
|
|
126659
|
+
var SETTINGS_SAVE_GENERAL_COMMAND = "settings.saveGeneral";
|
|
126660
|
+
var SETTINGS_SAVE_TARGET_COMMAND = "settings.saveTarget";
|
|
126661
|
+
var SETTINGS_REMOVE_TARGET_COMMAND = "settings.removeTarget";
|
|
126662
|
+
var LARK_SETUP_SESSION_COMMAND = "larkSetup.session";
|
|
126663
|
+
var BOT_ACTION_COMMANDS = {
|
|
126664
|
+
checkConnection: "im.settings.checkConnection",
|
|
126665
|
+
copyDiagnostics: "im.settings.copyDiagnostics",
|
|
126666
|
+
larkRepair: "im.settings.larkRepair"
|
|
126667
|
+
};
|
|
126668
|
+
var DEFAULT_PLATFORM = "lark";
|
|
126669
|
+
var REPLY_LANGUAGE_OPTIONS = [
|
|
126670
|
+
{ value: "zh-CN", labelKey: "settings.language.zhCN" },
|
|
126671
|
+
{ value: "en", labelKey: "settings.language.en" }
|
|
126672
|
+
];
|
|
126673
|
+
var DELIVERY_BOT_COLUMN = "botId";
|
|
126674
|
+
var platformOf = (row) => readString(row, "platform") || DEFAULT_PLATFORM;
|
|
126675
|
+
var foldFlowItem = (snapshot, item) => {
|
|
126676
|
+
switch (item.kind) {
|
|
126677
|
+
case "qr": {
|
|
126678
|
+
const { expired: _expired, ...rest } = snapshot;
|
|
126679
|
+
const qr = item.expiresAt === void 0 ? { payload: item.payload } : { payload: item.payload, expiresAt: item.expiresAt };
|
|
126680
|
+
return { ...rest, qr };
|
|
126681
|
+
}
|
|
126682
|
+
case "status": {
|
|
126683
|
+
const status = item.params === void 0 ? { statusKey: item.statusKey } : { statusKey: item.statusKey, params: item.params };
|
|
126684
|
+
if (item.expired !== true) return { ...snapshot, status };
|
|
126685
|
+
const { qr: _qr, ...rest } = snapshot;
|
|
126686
|
+
return { ...rest, status, expired: true };
|
|
126687
|
+
}
|
|
126688
|
+
case "steps":
|
|
126689
|
+
return { ...snapshot, steps: item.steps };
|
|
126690
|
+
case "done":
|
|
126691
|
+
case "failed": {
|
|
126692
|
+
const { status: _status, ...rest } = snapshot;
|
|
126693
|
+
return { ...rest, result: item };
|
|
126694
|
+
}
|
|
126695
|
+
}
|
|
126696
|
+
};
|
|
126697
|
+
|
|
126658
126698
|
// src/targetKind.ts
|
|
126659
126699
|
var TARGET_KIND_OPTIONS = [
|
|
126660
126700
|
{ value: "chat", labelKey: "settings.deliveryKind.chat" },
|
|
@@ -126674,26 +126714,37 @@ var DELIVERY_HTTP_TOKEN_FIELD = "deliveryHttpToken";
|
|
|
126674
126714
|
var DEFAULT_DELIVERY_HTTP_PORT = 3847;
|
|
126675
126715
|
var TARGET_ID_PATTERN = /^[A-Za-z0-9._:@-]{1,128}$/;
|
|
126676
126716
|
var isValidTargetId = (value2) => TARGET_ID_PATTERN.test(value2);
|
|
126717
|
+
var REQUIRED_TARGET_COLUMNS = [DELIVERY_BOT_COLUMN, "targetId", "platformChatId"];
|
|
126718
|
+
var targetIssues = (row) => {
|
|
126719
|
+
const issues = [];
|
|
126720
|
+
for (const column of REQUIRED_TARGET_COLUMNS) {
|
|
126721
|
+
if (readString(row, column) === "") issues.push({ column, code: "required" });
|
|
126722
|
+
}
|
|
126723
|
+
const targetId = readString(row, "targetId");
|
|
126724
|
+
if (targetId !== "" && !isValidTargetId(targetId)) {
|
|
126725
|
+
issues.push({ column: "targetId", code: "format" });
|
|
126726
|
+
}
|
|
126727
|
+
const kind = readString(row, "kind");
|
|
126728
|
+
if (kind !== "" && !isTargetKind(kind)) issues.push({ column: "kind", code: "format" });
|
|
126729
|
+
return issues;
|
|
126730
|
+
};
|
|
126677
126731
|
var readDeliveryTargets = (config2) => {
|
|
126678
126732
|
const table2 = config2[DELIVERY_TARGETS_FIELD];
|
|
126679
126733
|
if (typeof table2 !== "object" || table2 === null) return [];
|
|
126680
126734
|
return Object.entries(table2).flatMap(([rowId, row]) => {
|
|
126681
126735
|
if (typeof row !== "object" || row === null) return [];
|
|
126682
126736
|
const record2 = row;
|
|
126683
|
-
const botId = readString(record2, "botId");
|
|
126684
|
-
const targetId = readString(record2, "targetId");
|
|
126685
|
-
const platformChatId = readString(record2, "platformChatId");
|
|
126686
126737
|
const kind = readString(record2, "kind") || "chat";
|
|
126687
|
-
if (
|
|
126688
|
-
|
|
126738
|
+
if (targetIssues(record2).length > 0 || !isTargetKind(kind)) return [];
|
|
126739
|
+
const targetId = readString(record2, "targetId");
|
|
126689
126740
|
return [
|
|
126690
126741
|
{
|
|
126691
126742
|
rowId,
|
|
126692
|
-
botId,
|
|
126743
|
+
botId: readString(record2, DELIVERY_BOT_COLUMN),
|
|
126693
126744
|
targetId,
|
|
126694
126745
|
name: readString(record2, "name") || targetId,
|
|
126695
126746
|
kind,
|
|
126696
|
-
platformChatId
|
|
126747
|
+
platformChatId: readString(record2, "platformChatId")
|
|
126697
126748
|
}
|
|
126698
126749
|
];
|
|
126699
126750
|
});
|
|
@@ -126710,6 +126761,41 @@ var readDeliveryHttpToken = (config2) => {
|
|
|
126710
126761
|
const value2 = config2[DELIVERY_HTTP_TOKEN_FIELD];
|
|
126711
126762
|
return typeof value2 === "string" ? value2 : "";
|
|
126712
126763
|
};
|
|
126764
|
+
var deliveryTargetColumns = () => [
|
|
126765
|
+
{
|
|
126766
|
+
key: DELIVERY_BOT_COLUMN,
|
|
126767
|
+
kind: "text",
|
|
126768
|
+
labelKey: "column.deliveryBotId.label",
|
|
126769
|
+
descriptionKey: "column.deliveryBotId.description",
|
|
126770
|
+
placeholderKey: "column.deliveryBotId.placeholder"
|
|
126771
|
+
},
|
|
126772
|
+
{
|
|
126773
|
+
key: "targetId",
|
|
126774
|
+
kind: "text",
|
|
126775
|
+
labelKey: "column.deliveryTargetId.label",
|
|
126776
|
+
descriptionKey: "column.deliveryTargetId.description",
|
|
126777
|
+
placeholderKey: "column.deliveryTargetId.placeholder"
|
|
126778
|
+
},
|
|
126779
|
+
{
|
|
126780
|
+
key: "name",
|
|
126781
|
+
kind: "text",
|
|
126782
|
+
labelKey: "column.deliveryName.label",
|
|
126783
|
+
placeholderKey: "column.deliveryName.placeholder"
|
|
126784
|
+
},
|
|
126785
|
+
{
|
|
126786
|
+
key: "kind",
|
|
126787
|
+
kind: "select",
|
|
126788
|
+
labelKey: "column.deliveryKind.label",
|
|
126789
|
+
options: [...TARGET_KIND_OPTIONS]
|
|
126790
|
+
},
|
|
126791
|
+
{
|
|
126792
|
+
key: "platformChatId",
|
|
126793
|
+
kind: "text",
|
|
126794
|
+
labelKey: "column.deliveryPlatformChatId.label",
|
|
126795
|
+
descriptionKey: "column.deliveryPlatformChatId.description",
|
|
126796
|
+
placeholderKey: "column.deliveryPlatformChatId.placeholder"
|
|
126797
|
+
}
|
|
126798
|
+
];
|
|
126713
126799
|
var buildDeliverySettingsFields = () => [
|
|
126714
126800
|
{
|
|
126715
126801
|
key: DELIVERY_HTTP_ENABLED_FIELD,
|
|
@@ -126736,48 +126822,13 @@ var buildDeliverySettingsFields = () => [
|
|
|
126736
126822
|
kind: "table",
|
|
126737
126823
|
labelKey: "settings.deliveryTargets.label",
|
|
126738
126824
|
descriptionKey: "settings.deliveryTargets.description",
|
|
126739
|
-
columns: [
|
|
126740
|
-
{
|
|
126741
|
-
key: "botId",
|
|
126742
|
-
kind: "text",
|
|
126743
|
-
labelKey: "column.deliveryBotId.label",
|
|
126744
|
-
descriptionKey: "column.deliveryBotId.description",
|
|
126745
|
-
placeholderKey: "column.deliveryBotId.placeholder"
|
|
126746
|
-
},
|
|
126747
|
-
{
|
|
126748
|
-
key: "targetId",
|
|
126749
|
-
kind: "text",
|
|
126750
|
-
labelKey: "column.deliveryTargetId.label",
|
|
126751
|
-
descriptionKey: "column.deliveryTargetId.description",
|
|
126752
|
-
placeholderKey: "column.deliveryTargetId.placeholder"
|
|
126753
|
-
},
|
|
126754
|
-
{
|
|
126755
|
-
key: "name",
|
|
126756
|
-
kind: "text",
|
|
126757
|
-
labelKey: "column.deliveryName.label",
|
|
126758
|
-
placeholderKey: "column.deliveryName.placeholder"
|
|
126759
|
-
},
|
|
126760
|
-
{
|
|
126761
|
-
key: "kind",
|
|
126762
|
-
kind: "select",
|
|
126763
|
-
labelKey: "column.deliveryKind.label",
|
|
126764
|
-
options: [...TARGET_KIND_OPTIONS]
|
|
126765
|
-
},
|
|
126766
|
-
{
|
|
126767
|
-
key: "platformChatId",
|
|
126768
|
-
kind: "text",
|
|
126769
|
-
labelKey: "column.deliveryPlatformChatId.label",
|
|
126770
|
-
descriptionKey: "column.deliveryPlatformChatId.description",
|
|
126771
|
-
placeholderKey: "column.deliveryPlatformChatId.placeholder"
|
|
126772
|
-
}
|
|
126773
|
-
]
|
|
126825
|
+
columns: [...deliveryTargetColumns()]
|
|
126774
126826
|
}
|
|
126775
126827
|
];
|
|
126776
126828
|
|
|
126777
126829
|
// src/botConfig.ts
|
|
126778
126830
|
var BOTS_FIELD = "bots";
|
|
126779
126831
|
var REPLY_LANGUAGE_FIELD = "replyLanguage";
|
|
126780
|
-
var DEFAULT_PLATFORM = "lark";
|
|
126781
126832
|
var parseGroupMention = (value2) => value2 === "never" || value2 === "ambient" ? value2 : "always";
|
|
126782
126833
|
var INBOUND_RUNTIME_MODES = /* @__PURE__ */ new Set([
|
|
126783
126834
|
"approval-required",
|
|
@@ -126809,6 +126860,7 @@ var LARK_PANEL_MODES = new Set(
|
|
|
126809
126860
|
);
|
|
126810
126861
|
var DEFAULT_LARK_PANEL_MODE = "default";
|
|
126811
126862
|
var chatKeyOf = (binding) => `${binding.rowId}:${binding.chatId}`;
|
|
126863
|
+
var isChatKeyOfRow = (chatKey, rowId) => chatKey.startsWith(chatKeyOf({ rowId, chatId: "" }));
|
|
126812
126864
|
var parseQueueMode = (value2) => QUEUE_MODES.has(value2) ? value2 : DEFAULT_QUEUE_MODE;
|
|
126813
126865
|
var parseAccessMode = (value2) => ACCESS_MODES.has(value2) ? value2 : DEFAULT_ACCESS_MODE;
|
|
126814
126866
|
var parseLarkPanelMode = (value2) => LARK_PANEL_MODES.has(value2) ? value2 : DEFAULT_LARK_PANEL_MODE;
|
|
@@ -126817,36 +126869,7 @@ var parseOnOff = (value2, defaultOn) => {
|
|
|
126817
126869
|
if (value2 === "off") return false;
|
|
126818
126870
|
return defaultOn;
|
|
126819
126871
|
};
|
|
126820
|
-
var
|
|
126821
|
-
checkConnection: "im.settings.checkConnection",
|
|
126822
|
-
copyDiagnostics: "im.settings.copyDiagnostics",
|
|
126823
|
-
larkRepair: "im.settings.larkRepair"
|
|
126824
|
-
};
|
|
126825
|
-
var BOT_ROW_ACTIONS = [
|
|
126826
|
-
{
|
|
126827
|
-
id: "checkConnection",
|
|
126828
|
-
labelKey: "rowAction.checkConnection.label",
|
|
126829
|
-
descriptionKey: "rowAction.checkConnection.description",
|
|
126830
|
-
command: ROW_ACTION_COMMANDS.checkConnection,
|
|
126831
|
-
fills: []
|
|
126832
|
-
},
|
|
126833
|
-
{
|
|
126834
|
-
id: "copyDiagnostics",
|
|
126835
|
-
labelKey: "rowAction.copyDiagnostics.label",
|
|
126836
|
-
descriptionKey: "rowAction.copyDiagnostics.description",
|
|
126837
|
-
command: ROW_ACTION_COMMANDS.copyDiagnostics,
|
|
126838
|
-
fills: []
|
|
126839
|
-
},
|
|
126840
|
-
{
|
|
126841
|
-
id: "larkRepair",
|
|
126842
|
-
labelKey: "rowAction.larkRepair.label",
|
|
126843
|
-
descriptionKey: "rowAction.larkRepair.description",
|
|
126844
|
-
command: ROW_ACTION_COMMANDS.larkRepair,
|
|
126845
|
-
showWhen: { key: "platform", equals: ["lark"] },
|
|
126846
|
-
fills: []
|
|
126847
|
-
}
|
|
126848
|
-
];
|
|
126849
|
-
var buildSettingsCard = (adapters) => {
|
|
126872
|
+
var buildBotColumns = (adapters) => {
|
|
126850
126873
|
const platformColumn = {
|
|
126851
126874
|
key: "platform",
|
|
126852
126875
|
kind: "select",
|
|
@@ -126864,134 +126887,139 @@ var buildSettingsCard = (adapters) => {
|
|
|
126864
126887
|
showWhen: { key: platformColumn.key, equals: [adapter.platform] }
|
|
126865
126888
|
}))
|
|
126866
126889
|
);
|
|
126890
|
+
return [
|
|
126891
|
+
{
|
|
126892
|
+
key: "displayName",
|
|
126893
|
+
kind: "text",
|
|
126894
|
+
labelKey: "column.displayName.label",
|
|
126895
|
+
placeholderKey: "column.displayName.placeholder"
|
|
126896
|
+
},
|
|
126897
|
+
platformColumn,
|
|
126898
|
+
...credentialColumns,
|
|
126899
|
+
{
|
|
126900
|
+
key: "accessMode",
|
|
126901
|
+
kind: "select",
|
|
126902
|
+
labelKey: "column.accessMode.label",
|
|
126903
|
+
descriptionKey: "column.accessMode.description",
|
|
126904
|
+
options: [...ACCESS_MODE_OPTIONS]
|
|
126905
|
+
},
|
|
126906
|
+
{
|
|
126907
|
+
key: "allowedSenders",
|
|
126908
|
+
kind: "text",
|
|
126909
|
+
labelKey: "column.allowedSenders.label",
|
|
126910
|
+
descriptionKey: "column.allowedSenders.description",
|
|
126911
|
+
// 缺省/空串=allowlist(与 parseAccessMode 一致),仍显示白名单框。
|
|
126912
|
+
showWhen: { key: "accessMode", equals: ["allowlist", ""] }
|
|
126913
|
+
},
|
|
126914
|
+
{
|
|
126915
|
+
// 选项由宿主填,连三态一起——插件只声明「这个格子装的是代理」,宿主因此
|
|
126916
|
+
// 也就认得出这一行引用了哪个代理,删代理时拦得住(路线图 #64)。
|
|
126917
|
+
key: "proxy",
|
|
126918
|
+
kind: "proxy",
|
|
126919
|
+
labelKey: "column.proxy.label",
|
|
126920
|
+
descriptionKey: "column.proxy.description"
|
|
126921
|
+
},
|
|
126922
|
+
{
|
|
126923
|
+
key: "runtimeMode",
|
|
126924
|
+
kind: "select",
|
|
126925
|
+
labelKey: "column.runtimeMode.label",
|
|
126926
|
+
descriptionKey: "column.runtimeMode.description",
|
|
126927
|
+
options: [
|
|
126928
|
+
{ value: "approval-required", labelKey: "settings.runtimeMode.approvalRequired" },
|
|
126929
|
+
{ value: "auto-accept-edits", labelKey: "settings.runtimeMode.autoAcceptEdits" },
|
|
126930
|
+
{ value: "auto", labelKey: "settings.runtimeMode.auto" },
|
|
126931
|
+
{ value: "full-access", labelKey: "settings.runtimeMode.fullAccess" }
|
|
126932
|
+
]
|
|
126933
|
+
},
|
|
126934
|
+
{
|
|
126935
|
+
key: "groupMention",
|
|
126936
|
+
kind: "select",
|
|
126937
|
+
labelKey: "column.groupMention.label",
|
|
126938
|
+
descriptionKey: "column.groupMention.description",
|
|
126939
|
+
options: [
|
|
126940
|
+
{ value: "always", labelKey: "settings.groupMention.always" },
|
|
126941
|
+
{ value: "never", labelKey: "settings.groupMention.never" },
|
|
126942
|
+
{ value: "ambient", labelKey: "settings.groupMention.ambient" }
|
|
126943
|
+
]
|
|
126944
|
+
},
|
|
126945
|
+
{
|
|
126946
|
+
key: "queueMode",
|
|
126947
|
+
kind: "select",
|
|
126948
|
+
labelKey: "column.queueMode.label",
|
|
126949
|
+
descriptionKey: "column.queueMode.description",
|
|
126950
|
+
options: [...QUEUE_MODE_OPTIONS]
|
|
126951
|
+
},
|
|
126952
|
+
{
|
|
126953
|
+
key: "larkPanelMode",
|
|
126954
|
+
kind: "select",
|
|
126955
|
+
labelKey: "column.larkPanelMode.label",
|
|
126956
|
+
descriptionKey: "column.larkPanelMode.description",
|
|
126957
|
+
showWhen: { key: "platform", equals: ["lark"] },
|
|
126958
|
+
options: [...LARK_PANEL_MODE_OPTIONS]
|
|
126959
|
+
},
|
|
126960
|
+
{
|
|
126961
|
+
key: "wecomNumberedHints",
|
|
126962
|
+
kind: "select",
|
|
126963
|
+
labelKey: "column.wecomNumberedHints.label",
|
|
126964
|
+
descriptionKey: "column.wecomNumberedHints.description",
|
|
126965
|
+
showWhen: { key: "platform", equals: ["wecom"] },
|
|
126966
|
+
options: [
|
|
126967
|
+
{ value: "on", labelKey: "settings.onOff.on" },
|
|
126968
|
+
{ value: "off", labelKey: "settings.onOff.off" }
|
|
126969
|
+
]
|
|
126970
|
+
}
|
|
126971
|
+
];
|
|
126972
|
+
};
|
|
126973
|
+
var buildSettingsCard = (adapters) => {
|
|
126867
126974
|
return {
|
|
126868
126975
|
titleKey: "settings.title",
|
|
126869
126976
|
descriptionKey: "settings.description",
|
|
126977
|
+
presentation: "hidden",
|
|
126870
126978
|
fields: [
|
|
126871
126979
|
{
|
|
126872
126980
|
key: REPLY_LANGUAGE_FIELD,
|
|
126873
126981
|
kind: "select",
|
|
126874
126982
|
labelKey: "settings.language.label",
|
|
126875
126983
|
descriptionKey: "settings.language.description",
|
|
126876
|
-
options: [
|
|
126877
|
-
{ value: "zh-CN", labelKey: "settings.language.zhCN" },
|
|
126878
|
-
{ value: "en", labelKey: "settings.language.en" }
|
|
126879
|
-
]
|
|
126984
|
+
options: [...REPLY_LANGUAGE_OPTIONS]
|
|
126880
126985
|
},
|
|
126881
126986
|
{
|
|
126882
126987
|
key: BOTS_FIELD,
|
|
126883
126988
|
kind: "table",
|
|
126884
126989
|
labelKey: "settings.bots",
|
|
126885
|
-
columns: [
|
|
126886
|
-
{
|
|
126887
|
-
key: "displayName",
|
|
126888
|
-
kind: "text",
|
|
126889
|
-
labelKey: "column.displayName.label",
|
|
126890
|
-
placeholderKey: "column.displayName.placeholder"
|
|
126891
|
-
},
|
|
126892
|
-
platformColumn,
|
|
126893
|
-
...credentialColumns,
|
|
126894
|
-
{
|
|
126895
|
-
key: "accessMode",
|
|
126896
|
-
kind: "select",
|
|
126897
|
-
labelKey: "column.accessMode.label",
|
|
126898
|
-
descriptionKey: "column.accessMode.description",
|
|
126899
|
-
options: [...ACCESS_MODE_OPTIONS]
|
|
126900
|
-
},
|
|
126901
|
-
{
|
|
126902
|
-
key: "allowedSenders",
|
|
126903
|
-
kind: "text",
|
|
126904
|
-
labelKey: "column.allowedSenders.label",
|
|
126905
|
-
descriptionKey: "column.allowedSenders.description",
|
|
126906
|
-
// 缺省/空串=allowlist(与 parseAccessMode 一致),仍显示白名单框。
|
|
126907
|
-
showWhen: { key: "accessMode", equals: ["allowlist", ""] }
|
|
126908
|
-
},
|
|
126909
|
-
{
|
|
126910
|
-
// 选项由宿主填,连三态一起——插件只声明「这个格子装的是代理」,宿主因此
|
|
126911
|
-
// 也就认得出这一行引用了哪个代理,删代理时拦得住(路线图 #64)。
|
|
126912
|
-
key: "proxy",
|
|
126913
|
-
kind: "proxy",
|
|
126914
|
-
labelKey: "column.proxy.label",
|
|
126915
|
-
descriptionKey: "column.proxy.description"
|
|
126916
|
-
},
|
|
126917
|
-
{
|
|
126918
|
-
key: "runtimeMode",
|
|
126919
|
-
kind: "select",
|
|
126920
|
-
labelKey: "column.runtimeMode.label",
|
|
126921
|
-
descriptionKey: "column.runtimeMode.description",
|
|
126922
|
-
options: [
|
|
126923
|
-
{ value: "approval-required", labelKey: "settings.runtimeMode.approvalRequired" },
|
|
126924
|
-
{ value: "auto-accept-edits", labelKey: "settings.runtimeMode.autoAcceptEdits" },
|
|
126925
|
-
{ value: "auto", labelKey: "settings.runtimeMode.auto" },
|
|
126926
|
-
{ value: "full-access", labelKey: "settings.runtimeMode.fullAccess" }
|
|
126927
|
-
]
|
|
126928
|
-
},
|
|
126929
|
-
{
|
|
126930
|
-
key: "groupMention",
|
|
126931
|
-
kind: "select",
|
|
126932
|
-
labelKey: "column.groupMention.label",
|
|
126933
|
-
descriptionKey: "column.groupMention.description",
|
|
126934
|
-
options: [
|
|
126935
|
-
{ value: "always", labelKey: "settings.groupMention.always" },
|
|
126936
|
-
{ value: "never", labelKey: "settings.groupMention.never" },
|
|
126937
|
-
{ value: "ambient", labelKey: "settings.groupMention.ambient" }
|
|
126938
|
-
]
|
|
126939
|
-
},
|
|
126940
|
-
{
|
|
126941
|
-
key: "queueMode",
|
|
126942
|
-
kind: "select",
|
|
126943
|
-
labelKey: "column.queueMode.label",
|
|
126944
|
-
descriptionKey: "column.queueMode.description",
|
|
126945
|
-
options: [...QUEUE_MODE_OPTIONS]
|
|
126946
|
-
},
|
|
126947
|
-
{
|
|
126948
|
-
key: "larkPanelMode",
|
|
126949
|
-
kind: "select",
|
|
126950
|
-
labelKey: "column.larkPanelMode.label",
|
|
126951
|
-
descriptionKey: "column.larkPanelMode.description",
|
|
126952
|
-
showWhen: { key: "platform", equals: ["lark"] },
|
|
126953
|
-
options: [...LARK_PANEL_MODE_OPTIONS]
|
|
126954
|
-
},
|
|
126955
|
-
{
|
|
126956
|
-
key: "wecomNumberedHints",
|
|
126957
|
-
kind: "select",
|
|
126958
|
-
labelKey: "column.wecomNumberedHints.label",
|
|
126959
|
-
descriptionKey: "column.wecomNumberedHints.description",
|
|
126960
|
-
showWhen: { key: "platform", equals: ["wecom"] },
|
|
126961
|
-
options: [
|
|
126962
|
-
{ value: "on", labelKey: "settings.onOff.on" },
|
|
126963
|
-
{ value: "off", labelKey: "settings.onOff.off" }
|
|
126964
|
-
]
|
|
126965
|
-
}
|
|
126966
|
-
],
|
|
126967
|
-
rowActions: [...BOT_ROW_ACTIONS]
|
|
126990
|
+
columns: [...buildBotColumns(adapters)]
|
|
126968
126991
|
},
|
|
126969
126992
|
...buildDeliverySettingsFields()
|
|
126970
126993
|
]
|
|
126971
126994
|
};
|
|
126972
126995
|
};
|
|
126996
|
+
var readBotView = (rowId, row, adapter) => {
|
|
126997
|
+
const values = {};
|
|
126998
|
+
for (const key of Object.keys(row)) values[key] = readString(row, key);
|
|
126999
|
+
const proxyValue = readString(row, "proxy");
|
|
127000
|
+
return {
|
|
127001
|
+
rowId,
|
|
127002
|
+
displayName: readString(row, "displayName") || adapter.label,
|
|
127003
|
+
// 空串=跟机器默认(省略),`direct`=明确不加代理(null),其余就是那个 id。
|
|
127004
|
+
proxy: proxyValue === "" ? void 0 : proxyValue === PLUGIN_PROXY_DIRECT ? null : proxyValue,
|
|
127005
|
+
values,
|
|
127006
|
+
groupMention: parseGroupMention(readString(row, "groupMention"))
|
|
127007
|
+
};
|
|
127008
|
+
};
|
|
126973
127009
|
var readBot = (adapterFor, rowId, row) => {
|
|
126974
|
-
const platform =
|
|
127010
|
+
const platform = platformOf(row);
|
|
126975
127011
|
const adapter = adapterFor(platform);
|
|
126976
127012
|
if (adapter === void 0) return null;
|
|
126977
|
-
const values = {};
|
|
126978
|
-
for (const key of Object.keys(row)) values[key] = readString(row, key);
|
|
126979
127013
|
const requested = readString(row, "runtimeMode");
|
|
126980
|
-
const proxyValue = readString(row, "proxy");
|
|
126981
127014
|
const allowedSenders = new Set(
|
|
126982
127015
|
readString(row, "allowedSenders").split(",").map((entry) => entry.trim()).filter((entry) => entry !== "")
|
|
126983
127016
|
);
|
|
126984
127017
|
const bot = {
|
|
126985
|
-
rowId,
|
|
127018
|
+
...readBotView(rowId, row, adapter),
|
|
126986
127019
|
platform,
|
|
126987
|
-
displayName: readString(row, "displayName") || adapter.label,
|
|
126988
|
-
// 空串=跟机器默认(省略),`direct`=明确不加代理(null),其余就是那个 id。
|
|
126989
|
-
proxy: proxyValue === "" ? void 0 : proxyValue === PLUGIN_PROXY_DIRECT ? null : proxyValue,
|
|
126990
127020
|
accessMode: parseAccessMode(readString(row, "accessMode")),
|
|
126991
127021
|
allowedSenders,
|
|
126992
|
-
values,
|
|
126993
127022
|
runtimeMode: INBOUND_RUNTIME_MODES.has(requested) ? requested : DEFAULT_INBOUND_RUNTIME_MODE,
|
|
126994
|
-
groupMention: parseGroupMention(readString(row, "groupMention")),
|
|
126995
127023
|
queueMode: parseQueueMode(readString(row, "queueMode")),
|
|
126996
127024
|
larkPanelMode: parseLarkPanelMode(readString(row, "larkPanelMode")),
|
|
126997
127025
|
wecomNumberedHints: parseOnOff(readString(row, "wecomNumberedHints"), true)
|
|
@@ -127014,7 +127042,7 @@ var bindingOf = (bot, chatId, state) => ({
|
|
|
127014
127042
|
projectId: chatOf(state, chatKeyOf({ rowId: bot.rowId, chatId })).projectId ?? ""
|
|
127015
127043
|
});
|
|
127016
127044
|
var findBindingByChatKey = (bots, state, chatKey) => {
|
|
127017
|
-
const bot = bots.find((candidate) => chatKey
|
|
127045
|
+
const bot = bots.find((candidate) => isChatKeyOfRow(chatKey, candidate.rowId));
|
|
127018
127046
|
return bot === void 0 ? void 0 : bindingOf(bot, chatKey.slice(bot.rowId.length + 1), state);
|
|
127019
127047
|
};
|
|
127020
127048
|
var isAllowedSender = (bot, sender) => {
|
|
@@ -127123,13 +127151,15 @@ var makeApprovals = (core, anchors) => {
|
|
|
127123
127151
|
if (binding === void 0) return;
|
|
127124
127152
|
const adapter = adapterFor(binding.platform);
|
|
127125
127153
|
if (adapter === void 0) return;
|
|
127126
|
-
const pending = await host.
|
|
127154
|
+
const pending = await host.approvals.pending.list({ threadId });
|
|
127127
127155
|
const fresh = pending.filter(
|
|
127128
127156
|
(candidate) => core.state.approvals[candidate.requestId] === void 0
|
|
127129
127157
|
);
|
|
127130
127158
|
const offers = (adapter.answerByText === void 0 ? fresh : fresh.slice(0, 1)).map(
|
|
127131
127159
|
(approval) => {
|
|
127132
|
-
const offered = approval.options.filter(
|
|
127160
|
+
const offered = (approval.options ?? []).filter(
|
|
127161
|
+
(option) => option.decision !== "acceptAlways"
|
|
127162
|
+
);
|
|
127133
127163
|
const options = offered.length > 0 ? offered : [
|
|
127134
127164
|
{ decision: "accept", label: t("approval.allow") },
|
|
127135
127165
|
{ decision: "decline", label: t("approval.deny") }
|
|
@@ -127227,6 +127257,57 @@ var pickProject = (arg, listed, rows) => {
|
|
|
127227
127257
|
return prefixed.length === 1 ? prefixed[0]?.projectId ?? null : null;
|
|
127228
127258
|
};
|
|
127229
127259
|
|
|
127260
|
+
// src/sessionList.ts
|
|
127261
|
+
var SESSION_LIST_MAX = 20;
|
|
127262
|
+
var isSessionRunning = (status) => status === "running";
|
|
127263
|
+
var SESSION_ID_SHORT_LENGTH = 8;
|
|
127264
|
+
var ageLabel = (updatedAt, now, t) => {
|
|
127265
|
+
const at = Date.parse(updatedAt);
|
|
127266
|
+
if (Number.isNaN(at)) return "";
|
|
127267
|
+
const minutes = Math.floor(Math.max(0, now - at) / 6e4);
|
|
127268
|
+
if (minutes < 1) return t("sessions.age.justNow");
|
|
127269
|
+
if (minutes < 60) return t("sessions.age.minutes", { count: minutes });
|
|
127270
|
+
const hours = Math.floor(minutes / 60);
|
|
127271
|
+
if (hours < 24) return t("sessions.age.hours", { count: hours });
|
|
127272
|
+
return t("sessions.age.days", { count: Math.floor(hours / 24) });
|
|
127273
|
+
};
|
|
127274
|
+
var shortId = (threadId) => threadId.slice(0, SESSION_ID_SHORT_LENGTH);
|
|
127275
|
+
var sessionLine = (row, position, now, t) => {
|
|
127276
|
+
const title = row.title.replace(/\s+/g, " ").trim() || t("sessions.untitled");
|
|
127277
|
+
const age = ageLabel(row.updatedAt, now, t);
|
|
127278
|
+
const badges = [
|
|
127279
|
+
row.current ? t("sessions.badge.current") : null,
|
|
127280
|
+
row.running ? t("sessions.badge.running") : null,
|
|
127281
|
+
row.elsewhere ? t("sessions.badge.elsewhere") : null,
|
|
127282
|
+
row.origin === "web" ? t("sessions.badge.web") : null
|
|
127283
|
+
].filter((badge) => badge !== null);
|
|
127284
|
+
return [`${String(position)}. ${title}`, age, ...badges, shortId(row.threadId)].filter((part) => part !== "").join(" \xB7 ");
|
|
127285
|
+
};
|
|
127286
|
+
var formatSessions = (rows, now, t) => {
|
|
127287
|
+
if (rows.length === 0) return t("sessions.empty");
|
|
127288
|
+
const shown = rows.slice(0, SESSION_LIST_MAX);
|
|
127289
|
+
return [
|
|
127290
|
+
t("sessions.title", { count: rows.length }),
|
|
127291
|
+
...shown.map((row, index) => sessionLine(row, index + 1, now, t)),
|
|
127292
|
+
...rows.length > shown.length ? [t("sessions.more", { count: rows.length - shown.length })] : [],
|
|
127293
|
+
"",
|
|
127294
|
+
t("sessions.footer")
|
|
127295
|
+
].join("\n");
|
|
127296
|
+
};
|
|
127297
|
+
var listedThreadIds = (rows) => rows.slice(0, SESSION_LIST_MAX).map((row) => row.threadId);
|
|
127298
|
+
var looksLikeListNumber = (wanted) => /^[1-9]\d*$/u.test(wanted) && wanted.length <= String(SESSION_LIST_MAX).length;
|
|
127299
|
+
var pickSession = (arg, listed, rows) => {
|
|
127300
|
+
const wanted = arg.trim();
|
|
127301
|
+
if (wanted === "") return null;
|
|
127302
|
+
if (looksLikeListNumber(wanted)) {
|
|
127303
|
+
const ids = listed ?? listedThreadIds(rows);
|
|
127304
|
+
return ids[Number(wanted) - 1] ?? null;
|
|
127305
|
+
}
|
|
127306
|
+
const needle = wanted.toLowerCase();
|
|
127307
|
+
const matches = rows.filter((row) => row.threadId.toLowerCase().startsWith(needle));
|
|
127308
|
+
return matches.length === 1 ? matches[0]?.threadId ?? null : null;
|
|
127309
|
+
};
|
|
127310
|
+
|
|
127230
127311
|
// src/chatSetup.ts
|
|
127231
127312
|
var makeChatSetup = (core, deps) => {
|
|
127232
127313
|
const { host, t, adapterFor, commit, deliver, bindingOf: bindingOf2, hasPanel } = core;
|
|
@@ -127285,7 +127366,7 @@ var makeChatSetup = (core, deps) => {
|
|
|
127285
127366
|
const threadId = chatOf(core.state, chatKey).threadId;
|
|
127286
127367
|
if (threadId !== null) {
|
|
127287
127368
|
const thread = await host.projections.getThread(threadId).catch(() => null);
|
|
127288
|
-
if (thread?.session?.
|
|
127369
|
+
if (isSessionRunning(thread?.session?.status)) {
|
|
127289
127370
|
await deliver(binding, t("repo.busy"));
|
|
127290
127371
|
return;
|
|
127291
127372
|
}
|
|
@@ -127640,7 +127721,7 @@ var makeCommands = (core, deps) => {
|
|
|
127640
127721
|
return true;
|
|
127641
127722
|
}
|
|
127642
127723
|
const thread = await host.projections.getThread(threadId);
|
|
127643
|
-
const running = thread?.session?.
|
|
127724
|
+
const running = isSessionRunning(thread?.session?.status);
|
|
127644
127725
|
await deliver(
|
|
127645
127726
|
binding,
|
|
127646
127727
|
[
|
|
@@ -128443,6 +128524,10 @@ var makeBoundedMap = (limit) => {
|
|
|
128443
128524
|
const oldest = entries.keys().next().value;
|
|
128444
128525
|
if (oldest !== void 0) entries.delete(oldest);
|
|
128445
128526
|
}
|
|
128527
|
+
},
|
|
128528
|
+
/** 忘掉键满足条件的那些。 */
|
|
128529
|
+
forget: (matches) => {
|
|
128530
|
+
for (const key of [...entries.keys()]) if (matches(key)) entries.delete(key);
|
|
128446
128531
|
}
|
|
128447
128532
|
};
|
|
128448
128533
|
};
|
|
@@ -129569,6 +129654,44 @@ var SETUP_ITEM_SCHEMA = makeFlowItemSchema({
|
|
|
129569
129654
|
qrRequired: ["payload", "expiresAt"],
|
|
129570
129655
|
doneRequired: ["messageKey"]
|
|
129571
129656
|
});
|
|
129657
|
+
var TERMINAL_ITEM_BRANCHES = SETUP_ITEM_SCHEMA.oneOf.filter(
|
|
129658
|
+
(branch) => ["done", "failed"].includes(branch.properties.kind.const)
|
|
129659
|
+
);
|
|
129660
|
+
var SETUP_SNAPSHOT_SCHEMA = {
|
|
129661
|
+
type: "object",
|
|
129662
|
+
additionalProperties: false,
|
|
129663
|
+
properties: {
|
|
129664
|
+
qr: {
|
|
129665
|
+
type: "object",
|
|
129666
|
+
additionalProperties: false,
|
|
129667
|
+
required: ["payload", "expiresAt"],
|
|
129668
|
+
properties: { payload: { type: "string" }, expiresAt: { type: "string" } }
|
|
129669
|
+
},
|
|
129670
|
+
status: {
|
|
129671
|
+
type: "object",
|
|
129672
|
+
additionalProperties: false,
|
|
129673
|
+
required: ["statusKey"],
|
|
129674
|
+
properties: { statusKey: { type: "string" }, params: { type: "object" } }
|
|
129675
|
+
},
|
|
129676
|
+
expired: { const: true },
|
|
129677
|
+
steps: SETUP_ITEM_SCHEMA.properties.steps,
|
|
129678
|
+
result: { ...SETUP_ITEM_SCHEMA, oneOf: TERMINAL_ITEM_BRANCHES }
|
|
129679
|
+
}
|
|
129680
|
+
};
|
|
129681
|
+
|
|
129682
|
+
// src/settingsUpdater.ts
|
|
129683
|
+
var makeSettingsUpdater = (settings) => {
|
|
129684
|
+
let tail = Promise.resolve();
|
|
129685
|
+
return (change) => {
|
|
129686
|
+
const run = tail.then(async () => {
|
|
129687
|
+
const { result, write } = change(await settings.read());
|
|
129688
|
+
if (write !== void 0) await settings.write(write.config, write.options);
|
|
129689
|
+
return result;
|
|
129690
|
+
});
|
|
129691
|
+
tail = run.catch(() => void 0);
|
|
129692
|
+
return run;
|
|
129693
|
+
};
|
|
129694
|
+
};
|
|
129572
129695
|
|
|
129573
129696
|
// src/lark/setup/saveBot.ts
|
|
129574
129697
|
var OPEN_ID_PREFIX = "ou_";
|
|
@@ -130986,16 +131109,7 @@ var createSetupRunner = (deps) => {
|
|
|
130986
131109
|
};
|
|
130987
131110
|
|
|
130988
131111
|
// src/lark/setup/setupCommands.ts
|
|
130989
|
-
var SETUP_START_COMMAND = "larkSetup.start";
|
|
130990
131112
|
var SETUP_CHECKLIST_COMMAND = "larkSetup.checklist";
|
|
130991
|
-
var LARK_SETUP_CARD_ACTION = {
|
|
130992
|
-
id: "larkSetup",
|
|
130993
|
-
labelKey: "setup.action.label",
|
|
130994
|
-
descriptionKey: "setup.action.description",
|
|
130995
|
-
badgeKey: "setup.action.badge",
|
|
130996
|
-
warningKey: "setup.action.warning",
|
|
130997
|
-
command: SETUP_START_COMMAND
|
|
130998
|
-
};
|
|
130999
131113
|
var MANUAL_STEP_IDS = [
|
|
131000
131114
|
"createApp",
|
|
131001
131115
|
"enableBot",
|
|
@@ -131004,7 +131118,7 @@ var MANUAL_STEP_IDS = [
|
|
|
131004
131118
|
"publish",
|
|
131005
131119
|
"fillRow"
|
|
131006
131120
|
];
|
|
131007
|
-
var
|
|
131121
|
+
var SETUP_SESSION_PAYLOAD_SCHEMA = {
|
|
131008
131122
|
type: "object",
|
|
131009
131123
|
additionalProperties: false
|
|
131010
131124
|
};
|
|
@@ -131059,10 +131173,15 @@ var makeRealClock = () => ({
|
|
|
131059
131173
|
signal?.addEventListener("abort", onAbort, { once: true });
|
|
131060
131174
|
})
|
|
131061
131175
|
});
|
|
131062
|
-
var saveAndConclude = async (ctx, result) => {
|
|
131176
|
+
var saveAndConclude = async (ctx, updateSettings, result) => {
|
|
131063
131177
|
try {
|
|
131064
|
-
const saved =
|
|
131065
|
-
|
|
131178
|
+
const saved = await updateSettings((config2) => {
|
|
131179
|
+
const upserted = upsertLarkBot(config2, result);
|
|
131180
|
+
return {
|
|
131181
|
+
result: upserted,
|
|
131182
|
+
write: { config: upserted.config, options: { secrets: [upserted.secretPath] } }
|
|
131183
|
+
};
|
|
131184
|
+
});
|
|
131066
131185
|
ctx.log.info("lark setup saved the bot", {
|
|
131067
131186
|
appId: result.appId,
|
|
131068
131187
|
rowId: saved.rowId,
|
|
@@ -131096,6 +131215,7 @@ var saveAndConclude = async (ctx, result) => {
|
|
|
131096
131215
|
}
|
|
131097
131216
|
};
|
|
131098
131217
|
var registerLarkSetup = (ctx, options = {}) => {
|
|
131218
|
+
const updateSettings = options.updateSettings ?? makeSettingsUpdater(ctx.settings);
|
|
131099
131219
|
const runner = createSetupRunner({
|
|
131100
131220
|
fetch: ctx.http,
|
|
131101
131221
|
clock: options.clock ?? makeRealClock(),
|
|
@@ -131108,15 +131228,19 @@ var registerLarkSetup = (ctx, options = {}) => {
|
|
|
131108
131228
|
...options.sessionRetryWindowMs === void 0 ? {} : { sessionRetryWindowMs: options.sessionRetryWindowMs }
|
|
131109
131229
|
});
|
|
131110
131230
|
ctx.stream({
|
|
131111
|
-
name:
|
|
131231
|
+
name: LARK_SETUP_SESSION_COMMAND,
|
|
131112
131232
|
description: "Set up a Lark app through the developer console after one QR scan.",
|
|
131113
131233
|
scope: "operate",
|
|
131114
|
-
payloadSchema:
|
|
131115
|
-
itemSchema:
|
|
131116
|
-
//
|
|
131234
|
+
payloadSchema: SETUP_SESSION_PAYLOAD_SCHEMA,
|
|
131235
|
+
itemSchema: SETUP_SNAPSHOT_SCHEMA,
|
|
131236
|
+
// 每一条都是完整的快照,慢订阅方丢掉的只该是旧的。
|
|
131117
131237
|
buffer: { latest: 16 },
|
|
131118
131238
|
handle: async (_payload, emit, signal) => {
|
|
131119
|
-
|
|
131239
|
+
let snapshot = {};
|
|
131240
|
+
const send = (item) => {
|
|
131241
|
+
snapshot = foldFlowItem(snapshot, item);
|
|
131242
|
+
emit(snapshot);
|
|
131243
|
+
};
|
|
131120
131244
|
const result = await runner.run(
|
|
131121
131245
|
{},
|
|
131122
131246
|
// 先落到宿主约定的条目类型上:形状不对在编译期就报,而不是到客户端被整条丢掉。
|
|
@@ -131124,7 +131248,7 @@ var registerLarkSetup = (ctx, options = {}) => {
|
|
|
131124
131248
|
signal
|
|
131125
131249
|
);
|
|
131126
131250
|
if (result === void 0) return;
|
|
131127
|
-
send(await saveAndConclude(ctx, result));
|
|
131251
|
+
send(await saveAndConclude(ctx, updateSettings, result));
|
|
131128
131252
|
}
|
|
131129
131253
|
});
|
|
131130
131254
|
ctx.command({
|
|
@@ -137182,6 +137306,13 @@ var credentials = (binding) => ({
|
|
|
137182
137306
|
appId: binding.values["larkAppId"] ?? "",
|
|
137183
137307
|
appSecret: binding.values["larkAppSecret"] ?? ""
|
|
137184
137308
|
});
|
|
137309
|
+
var larkConfigIssues = (binding) => {
|
|
137310
|
+
const { appId, appSecret } = credentials(binding);
|
|
137311
|
+
const issues = [];
|
|
137312
|
+
if (appId === "") issues.push({ column: "larkAppId", code: "required" });
|
|
137313
|
+
if (appSecret === "") issues.push({ column: "larkAppSecret", code: "required" });
|
|
137314
|
+
return issues;
|
|
137315
|
+
};
|
|
137185
137316
|
var makeLarkAdapter = (deps) => {
|
|
137186
137317
|
const tenantToken = async (binding) => {
|
|
137187
137318
|
const { appId, appSecret } = credentials(binding);
|
|
@@ -137194,12 +137325,16 @@ var makeLarkAdapter = (deps) => {
|
|
|
137194
137325
|
};
|
|
137195
137326
|
const aliasPorts = /* @__PURE__ */ new Map();
|
|
137196
137327
|
const topicThreadIds = makeBoundedMap(TOPIC_THREAD_CACHE_LIMIT);
|
|
137328
|
+
const unreported = /* @__PURE__ */ new Map();
|
|
137197
137329
|
const learning = /* @__PURE__ */ new Map();
|
|
137198
137330
|
const learnTopic = (binding, target2, threadId) => {
|
|
137199
137331
|
const key = chatKeyOf(binding);
|
|
137200
137332
|
const report = (id) => {
|
|
137201
137333
|
topicThreadIds.set(key, id);
|
|
137202
|
-
|
|
137334
|
+
const alias = topicAliasOf(target2.chatId, id);
|
|
137335
|
+
const port = target2.port ?? aliasPorts.get(binding.rowId);
|
|
137336
|
+
if (port === void 0) unreported.set(key, { alias, chatId: binding.chatId });
|
|
137337
|
+
else port.noteChatAlias?.(alias, binding.chatId);
|
|
137203
137338
|
};
|
|
137204
137339
|
const known = threadId ?? topicThreadIds.get(key);
|
|
137205
137340
|
if (known !== void 0) {
|
|
@@ -137264,10 +137399,8 @@ var makeLarkAdapter = (deps) => {
|
|
|
137264
137399
|
const { chatId: groupId, rootMessageId } = splitTopicChatId(chatId);
|
|
137265
137400
|
return rootMessageId === void 0 ? void 0 : groupId;
|
|
137266
137401
|
},
|
|
137267
|
-
|
|
137268
|
-
|
|
137269
|
-
return appId !== "" && appSecret !== "";
|
|
137270
|
-
},
|
|
137402
|
+
validate: larkConfigIssues,
|
|
137403
|
+
isConfigured: (binding) => larkConfigIssues(binding).length === 0,
|
|
137271
137404
|
connect: (binding, handlers) => {
|
|
137272
137405
|
const { appId, appSecret } = credentials(binding);
|
|
137273
137406
|
const port = {
|
|
@@ -137275,6 +137408,11 @@ var makeLarkAdapter = (deps) => {
|
|
|
137275
137408
|
knowsChatAlias: handlers.knowsChatAlias
|
|
137276
137409
|
};
|
|
137277
137410
|
aliasPorts.set(binding.rowId, port);
|
|
137411
|
+
for (const [key, pending] of [...unreported]) {
|
|
137412
|
+
if (!isChatKeyOfRow(key, binding.rowId)) continue;
|
|
137413
|
+
port.noteChatAlias?.(pending.alias, pending.chatId);
|
|
137414
|
+
unreported.delete(key);
|
|
137415
|
+
}
|
|
137278
137416
|
let open = true;
|
|
137279
137417
|
const inbound = startLarkInbound({
|
|
137280
137418
|
appId,
|
|
@@ -137328,7 +137466,10 @@ var makeLarkAdapter = (deps) => {
|
|
|
137328
137466
|
return {
|
|
137329
137467
|
close: () => {
|
|
137330
137468
|
open = false;
|
|
137331
|
-
if (aliasPorts.get(binding.rowId) === port)
|
|
137469
|
+
if (aliasPorts.get(binding.rowId) === port) {
|
|
137470
|
+
aliasPorts.delete(binding.rowId);
|
|
137471
|
+
topicThreadIds.forget((key) => isChatKeyOfRow(key, binding.rowId));
|
|
137472
|
+
}
|
|
137332
137473
|
inbound.close();
|
|
137333
137474
|
}
|
|
137334
137475
|
};
|
|
@@ -137502,7 +137643,7 @@ var makeLarkAdapter = (deps) => {
|
|
|
137502
137643
|
var en_default = {
|
|
137503
137644
|
settings: {
|
|
137504
137645
|
title: "Chat",
|
|
137505
|
-
description: "Connect chat bots to Ycodium. One row per bot: create the bot on its platform, paste its credentials, and pick an access mode (allowlist / open). In allowlist mode, list the people allowed to use it. For Lark, Connect a Lark bot
|
|
137646
|
+
description: "Connect chat bots to Ycodium. One row per bot: create the bot on its platform, paste its credentials, and pick an access mode (allowlist / open). In allowlist mode, list the people allowed to use it. For Lark, Connect a Lark bot does all of that with one scan. Admitted people message the bot (or add it to a group), pick a project in the chat, and can start work.",
|
|
137506
137647
|
bots: "Bots",
|
|
137507
137648
|
language: {
|
|
137508
137649
|
label: "Reply language",
|
|
@@ -137609,8 +137750,8 @@ var en_default = {
|
|
|
137609
137750
|
description: "When the bot answers in a group (unset means only when it is mentioned); direct chats always count. WeCom only delivers messages that mention the bot, so this changes nothing there."
|
|
137610
137751
|
},
|
|
137611
137752
|
deliveryBotId: {
|
|
137612
|
-
label: "Bot
|
|
137613
|
-
description: "The
|
|
137753
|
+
label: "Bot",
|
|
137754
|
+
description: "The bot that sends the message. Callers pass the id in brackets as botId.",
|
|
137614
137755
|
placeholder: "bot row id"
|
|
137615
137756
|
},
|
|
137616
137757
|
deliveryTargetId: {
|
|
@@ -137945,7 +138086,7 @@ var en_default = {
|
|
|
137945
138086
|
setup: {
|
|
137946
138087
|
action: {
|
|
137947
138088
|
label: "Connect a Lark bot",
|
|
137948
|
-
description: "Scan once with the Lark app. Ycodium creates a bot app under your account, publishes it for you only, and adds the bot to the list
|
|
138089
|
+
description: "Scan once with the Lark app. Ycodium creates a bot app under your account, publishes it for you only, and adds the bot to the list with its credentials saved. Nothing to fill in.",
|
|
137949
138090
|
badge: "Beta",
|
|
137950
138091
|
warning: "This relies on Lark developer console interfaces that are not public, so it may stop working. If it does, set the app up by hand in the developer console."
|
|
137951
138092
|
},
|
|
@@ -137972,7 +138113,7 @@ var en_default = {
|
|
|
137972
138113
|
},
|
|
137973
138114
|
fillRow: {
|
|
137974
138115
|
title: "Add the bot",
|
|
137975
|
-
body: "
|
|
138116
|
+
body: "Under Chat in Settings, add a bot: choose Lark, paste the App ID and App secret, put your own Lark user id in Allowed people (message the bot and it tells you your id), then save."
|
|
137976
138117
|
}
|
|
137977
138118
|
},
|
|
137978
138119
|
status: {
|
|
@@ -138106,6 +138247,66 @@ var en_default = {
|
|
|
138106
138247
|
thread: "Go back to a normal session",
|
|
138107
138248
|
panel: "Open the command panel",
|
|
138108
138249
|
help: "Show all commands"
|
|
138250
|
+
},
|
|
138251
|
+
settingsSection: {
|
|
138252
|
+
empty: "No bots yet",
|
|
138253
|
+
unavailable: "This machine doesn't have the chat bridge right now.",
|
|
138254
|
+
loadFailed: "Couldn't load the chat-bridge settings.",
|
|
138255
|
+
retry: "Try again",
|
|
138256
|
+
general: "General",
|
|
138257
|
+
addBot: "Add a bot",
|
|
138258
|
+
save: "Save",
|
|
138259
|
+
revert: "Undo changes",
|
|
138260
|
+
saveFailed: "Couldn't save.",
|
|
138261
|
+
remove: "Delete",
|
|
138262
|
+
removeConfirm: "Delete this bot",
|
|
138263
|
+
cancel: "Cancel",
|
|
138264
|
+
removeHint: "Deleting this bot drops the bindings for every chat on it.",
|
|
138265
|
+
copy: "Copy",
|
|
138266
|
+
copied: "Copied.",
|
|
138267
|
+
copyFailed: "Couldn't copy that.",
|
|
138268
|
+
removeFailed: "Couldn't delete this bot.",
|
|
138269
|
+
status: {
|
|
138270
|
+
ready: "Ready",
|
|
138271
|
+
incomplete: "Incomplete"
|
|
138272
|
+
},
|
|
138273
|
+
secret: {
|
|
138274
|
+
saved: "Saved. Leave blank to keep it.",
|
|
138275
|
+
clear: "Clear saved value",
|
|
138276
|
+
clearUndo: "Undo clear"
|
|
138277
|
+
},
|
|
138278
|
+
issue: {
|
|
138279
|
+
required: "Fill this in.",
|
|
138280
|
+
format: "This format isn't right."
|
|
138281
|
+
},
|
|
138282
|
+
publicField: {
|
|
138283
|
+
callbackUrl: "Callback URL"
|
|
138284
|
+
},
|
|
138285
|
+
action: {
|
|
138286
|
+
running: "Working\u2026",
|
|
138287
|
+
done: "Done.",
|
|
138288
|
+
close: "Close",
|
|
138289
|
+
failedToRun: "Couldn't run this on the machine.",
|
|
138290
|
+
saveFirst: "Save or undo your changes first. These check the saved settings.",
|
|
138291
|
+
qrTitle: "QR code to scan with the Lark app"
|
|
138292
|
+
},
|
|
138293
|
+
step: {
|
|
138294
|
+
pending: "Waiting",
|
|
138295
|
+
running: "In progress",
|
|
138296
|
+
done: "Done",
|
|
138297
|
+
skipped: "Skipped",
|
|
138298
|
+
failed: "Failed"
|
|
138299
|
+
},
|
|
138300
|
+
select: {
|
|
138301
|
+
default: "Default"
|
|
138302
|
+
},
|
|
138303
|
+
target: {
|
|
138304
|
+
description: "Places a script or another tool can send a message to through a bot. The caller names the bot and the target id; the chat id on the platform stays here.",
|
|
138305
|
+
add: "Add a target",
|
|
138306
|
+
untitled: "New target",
|
|
138307
|
+
removeConfirm: "Delete this target",
|
|
138308
|
+
removeFailed: "Couldn't delete this target."
|
|
138309
|
+
}
|
|
138109
138310
|
}
|
|
138110
138311
|
};
|
|
138111
138312
|
|
|
@@ -138113,7 +138314,7 @@ var en_default = {
|
|
|
138113
138314
|
var zh_CN_default = {
|
|
138114
138315
|
settings: {
|
|
138115
138316
|
title: "\u804A\u5929",
|
|
138116
|
-
description: "\u628A\u804A\u5929\u673A\u5668\u4EBA\u63A5\u5230 Ycodium\u3002\u4E00\u884C\u4E00\u4E2A\u673A\u5668\u4EBA\uFF1A\u5148\u5728\u5BF9\u5E94\u5E73\u53F0\u5EFA\u597D\u673A\u5668\u4EBA\u3001\u628A\u51ED\u636E\u586B\u8FDB\u6765\uFF0C\u518D\u9009\u8BBF\u95EE\u6A21\u5F0F\uFF08\u4EC5\u767D\u540D\u5355\uFF0F\u5141\u8BB8\u6240\u6709\u4EBA\uFF09\u3002\u4EC5\u767D\u540D\u5355\u65F6\u628A\u5141\u8BB8\u4F7F\u7528\u5B83\u7684\u4EBA\u586B\u8FDB\u300C\u5141\u8BB8\u7684\u4EBA\u300D\u3002\u98DE\u4E66\u53EF\u4EE5\u7528\
|
|
138317
|
+
description: "\u628A\u804A\u5929\u673A\u5668\u4EBA\u63A5\u5230 Ycodium\u3002\u4E00\u884C\u4E00\u4E2A\u673A\u5668\u4EBA\uFF1A\u5148\u5728\u5BF9\u5E94\u5E73\u53F0\u5EFA\u597D\u673A\u5668\u4EBA\u3001\u628A\u51ED\u636E\u586B\u8FDB\u6765\uFF0C\u518D\u9009\u8BBF\u95EE\u6A21\u5F0F\uFF08\u4EC5\u767D\u540D\u5355\uFF0F\u5141\u8BB8\u6240\u6709\u4EBA\uFF09\u3002\u4EC5\u767D\u540D\u5355\u65F6\u628A\u5141\u8BB8\u4F7F\u7528\u5B83\u7684\u4EBA\u586B\u8FDB\u300C\u5141\u8BB8\u7684\u4EBA\u300D\u3002\u98DE\u4E66\u53EF\u4EE5\u7528\u300C\u8FDE\u63A5\u98DE\u4E66\u673A\u5668\u4EBA\u300D\uFF0C\u626B\u4E00\u6B21\u7801\u5168\u90E8\u914D\u597D\u3002\u83B7\u51C6\u7684\u4EBA\u79C1\u804A\u673A\u5668\u4EBA\uFF08\u6216\u628A\u5B83\u62C9\u8FDB\u7FA4\uFF09\u3001\u5728\u804A\u5929\u91CC\u9009\u597D\u9879\u76EE\uFF0C\u5C31\u80FD\u6D3E\u6D3B\u3002",
|
|
138117
138318
|
bots: "\u673A\u5668\u4EBA",
|
|
138118
138319
|
language: {
|
|
138119
138320
|
label: "\u56DE\u8BDD\u8BED\u8A00",
|
|
@@ -138220,8 +138421,8 @@ var zh_CN_default = {
|
|
|
138220
138421
|
description: "\u673A\u5668\u4EBA\u5728\u7FA4\u91CC\u4EC0\u4E48\u65F6\u5019\u56DE\u5E94\uFF08\u4E0D\u9009\u5C31\u662F\u88AB @ \u624D\u7406\uFF09\uFF1B\u5355\u804A\u6C38\u8FDC\u7406\u3002\u4F01\u4E1A\u5FAE\u4FE1\u53EA\u628A @ \u5230\u673A\u5668\u4EBA\u7684\u7FA4\u6D88\u606F\u63A8\u8FC7\u6765\uFF0C\u8FD9\u4E00\u9879\u5BF9\u5B83\u6CA1\u6709\u6548\u679C\u3002"
|
|
138221
138422
|
},
|
|
138222
138423
|
deliveryBotId: {
|
|
138223
|
-
label: "
|
|
138224
|
-
description: "\
|
|
138424
|
+
label: "\u673A\u5668\u4EBA",
|
|
138425
|
+
description: "\u53D1\u6D88\u606F\u7684\u90A3\u4E2A\u673A\u5668\u4EBA\u3002\u8C03\u7528\u65B9\u628A\u62EC\u53F7\u91CC\u7684 id \u5F53\u4F5C botId \u4F20\u3002",
|
|
138225
138426
|
placeholder: "\u673A\u5668\u4EBA\u884C id"
|
|
138226
138427
|
},
|
|
138227
138428
|
deliveryTargetId: {
|
|
@@ -138556,7 +138757,7 @@ var zh_CN_default = {
|
|
|
138556
138757
|
setup: {
|
|
138557
138758
|
action: {
|
|
138558
138759
|
label: "\u8FDE\u63A5\u98DE\u4E66\u673A\u5668\u4EBA",
|
|
138559
|
-
description: "\u7528\u98DE\u4E66 App \u626B\u4E00\u6B21\u7801\u3002Ycodium \u4F1A\u5728\u4F60\u7684\u8D26\u53F7\u4E0B\u5EFA\u597D\u673A\u5668\u4EBA\u5E94\u7528\uFF0C\u53D1\u5E03\u4E3A\u4EC5\u81EA\u5DF1\u53EF\u89C1\uFF0C\u5E76\u628A\u8FD9\u4E2A\u673A\u5668\u4EBA\u8FDE\u540C\u51ED\u636E\u76F4\u63A5\u5B58\u8FDB\
|
|
138760
|
+
description: "\u7528\u98DE\u4E66 App \u626B\u4E00\u6B21\u7801\u3002Ycodium \u4F1A\u5728\u4F60\u7684\u8D26\u53F7\u4E0B\u5EFA\u597D\u673A\u5668\u4EBA\u5E94\u7528\uFF0C\u53D1\u5E03\u4E3A\u4EC5\u81EA\u5DF1\u53EF\u89C1\uFF0C\u5E76\u628A\u8FD9\u4E2A\u673A\u5668\u4EBA\u8FDE\u540C\u51ED\u636E\u76F4\u63A5\u5B58\u8FDB\u673A\u5668\u4EBA\u5217\u8868\uFF0C\u4E0D\u7528\u624B\u586B\u3002",
|
|
138560
138761
|
badge: "\u6D4B\u8BD5\u7248",
|
|
138561
138762
|
warning: "\u8FD9\u4E2A\u529F\u80FD\u4F9D\u8D56\u98DE\u4E66\u5F00\u53D1\u8005\u540E\u53F0\u7684\u975E\u516C\u5F00\u63A5\u53E3\uFF0C\u53EF\u80FD\u4F1A\u5931\u6548\u3002\u5931\u6548\u65F6\u8BF7\u5230\u5F00\u53D1\u8005\u540E\u53F0\u624B\u52A8\u914D\u7F6E\u5E94\u7528\u3002"
|
|
138562
138763
|
},
|
|
@@ -138583,7 +138784,7 @@ var zh_CN_default = {
|
|
|
138583
138784
|
},
|
|
138584
138785
|
fillRow: {
|
|
138585
138786
|
title: "\u6DFB\u52A0\u673A\u5668\u4EBA",
|
|
138586
|
-
body: "\u5728\u804A\u5929\
|
|
138787
|
+
body: "\u5728\u8BBE\u7F6E\u7684\u300C\u804A\u5929\u300D\u5206\u533A\u91CC\u6DFB\u52A0\u4E00\u4E2A\u673A\u5668\u4EBA\uFF1A\u5E73\u53F0\u9009\u98DE\u4E66\uFF0C\u586B\u5165 App ID \u4E0E App Secret\uFF0C\u628A\u4F60\u81EA\u5DF1\u7684\u98DE\u4E66\u7528\u6237 id \u586B\u8FDB\u300C\u5141\u8BB8\u7684\u4EBA\u300D\uFF08\u7ED9\u673A\u5668\u4EBA\u53D1\u4E00\u6761\u6D88\u606F\uFF0C\u5B83\u4F1A\u544A\u8BC9\u4F60\uFF09\uFF0C\u7136\u540E\u4FDD\u5B58\u3002"
|
|
138587
138788
|
}
|
|
138588
138789
|
},
|
|
138589
138790
|
status: {
|
|
@@ -138717,6 +138918,66 @@ var zh_CN_default = {
|
|
|
138717
138918
|
thread: "\u5207\u56DE\u666E\u901A\u4F1A\u8BDD",
|
|
138718
138919
|
panel: "\u6253\u5F00\u547D\u4EE4\u9762\u677F",
|
|
138719
138920
|
help: "\u5217\u51FA\u5168\u90E8\u547D\u4EE4"
|
|
138921
|
+
},
|
|
138922
|
+
settingsSection: {
|
|
138923
|
+
empty: "\u8FD8\u6CA1\u6709\u673A\u5668\u4EBA",
|
|
138924
|
+
unavailable: "\u8FD9\u53F0\u673A\u5668\u73B0\u5728\u6CA1\u6709\u804A\u5929\u6865\u3002",
|
|
138925
|
+
loadFailed: "\u804A\u5929\u6865\u7684\u8BBE\u7F6E\u6CA1\u80FD\u8BFB\u51FA\u6765\u3002",
|
|
138926
|
+
retry: "\u518D\u8BD5\u4E00\u6B21",
|
|
138927
|
+
general: "\u901A\u7528\u8BBE\u7F6E",
|
|
138928
|
+
addBot: "\u6DFB\u52A0\u673A\u5668\u4EBA",
|
|
138929
|
+
save: "\u4FDD\u5B58",
|
|
138930
|
+
revert: "\u64A4\u9500\u6539\u52A8",
|
|
138931
|
+
saveFailed: "\u6CA1\u80FD\u5B58\u4E0A\u3002",
|
|
138932
|
+
remove: "\u5220\u9664",
|
|
138933
|
+
removeConfirm: "\u786E\u8BA4\u5220\u9664",
|
|
138934
|
+
cancel: "\u53D6\u6D88",
|
|
138935
|
+
removeHint: "\u5220\u6389\u8FD9\u4E2A\u673A\u5668\u4EBA\u540E\uFF0C\u5B83\u4E0B\u9762\u6240\u6709\u4F1A\u8BDD\u7684\u7ED1\u5B9A\u90FD\u4F1A\u4E00\u8D77\u4E22\u6389\u3002",
|
|
138936
|
+
copy: "\u590D\u5236",
|
|
138937
|
+
copied: "\u5DF2\u590D\u5236\u3002",
|
|
138938
|
+
copyFailed: "\u6CA1\u590D\u5236\u4E0A\u3002",
|
|
138939
|
+
removeFailed: "\u6CA1\u80FD\u5220\u6389\u8FD9\u4E2A\u673A\u5668\u4EBA\u3002",
|
|
138940
|
+
status: {
|
|
138941
|
+
ready: "\u53EF\u7528",
|
|
138942
|
+
incomplete: "\u8FD8\u6CA1\u586B\u5B8C"
|
|
138943
|
+
},
|
|
138944
|
+
secret: {
|
|
138945
|
+
saved: "\u5DF2\u7ECF\u5B58\u8FC7\uFF0C\u7559\u7A7A\u5C31\u4FDD\u6301\u539F\u503C\u3002",
|
|
138946
|
+
clear: "\u6E05\u9664\u5DF2\u5B58\u7684\u503C",
|
|
138947
|
+
clearUndo: "\u64A4\u9500\u6E05\u9664"
|
|
138948
|
+
},
|
|
138949
|
+
issue: {
|
|
138950
|
+
required: "\u8FD9\u4E00\u9879\u8981\u586B\u3002",
|
|
138951
|
+
format: "\u8FD9\u4E2A\u683C\u5F0F\u4E0D\u5BF9\u3002"
|
|
138952
|
+
},
|
|
138953
|
+
publicField: {
|
|
138954
|
+
callbackUrl: "\u56DE\u8C03\u5730\u5740"
|
|
138955
|
+
},
|
|
138956
|
+
action: {
|
|
138957
|
+
running: "\u6B63\u5728\u5904\u7406\u2026",
|
|
138958
|
+
done: "\u5B8C\u6210\u3002",
|
|
138959
|
+
close: "\u5173\u95ED",
|
|
138960
|
+
failedToRun: "\u6CA1\u80FD\u5728\u8FD9\u53F0\u673A\u5668\u4E0A\u8FD0\u884C\u3002",
|
|
138961
|
+
saveFirst: "\u5148\u4FDD\u5B58\u6216\u64A4\u9500\u6539\u52A8\u3002\u8FD9\u51E0\u9879\u68C0\u67E5\u7684\u662F\u5DF2\u4FDD\u5B58\u7684\u8BBE\u7F6E\u3002",
|
|
138962
|
+
qrTitle: "\u7528\u98DE\u4E66 App \u626B\u7684\u4E8C\u7EF4\u7801"
|
|
138963
|
+
},
|
|
138964
|
+
step: {
|
|
138965
|
+
pending: "\u7B49\u5F85\u4E2D",
|
|
138966
|
+
running: "\u8FDB\u884C\u4E2D",
|
|
138967
|
+
done: "\u5DF2\u5B8C\u6210",
|
|
138968
|
+
skipped: "\u5DF2\u8DF3\u8FC7",
|
|
138969
|
+
failed: "\u5931\u8D25"
|
|
138970
|
+
},
|
|
138971
|
+
select: {
|
|
138972
|
+
default: "\u9ED8\u8BA4"
|
|
138973
|
+
},
|
|
138974
|
+
target: {
|
|
138975
|
+
description: "\u811A\u672C\u6216\u522B\u7684\u5DE5\u5177\u53EF\u4EE5\u7ECF\u673A\u5668\u4EBA\u628A\u6D88\u606F\u53D1\u5230\u8FD9\u4E9B\u5730\u65B9\u3002\u8C03\u7528\u65B9\u53EA\u62A5\u673A\u5668\u4EBA\u548C\u76EE\u6807 id\uFF0C\u5E73\u53F0\u4E0A\u7684\u804A\u5929 id \u7559\u5728\u8FD9\u91CC\u3002",
|
|
138976
|
+
add: "\u6DFB\u52A0\u76EE\u6807",
|
|
138977
|
+
untitled: "\u65B0\u76EE\u6807",
|
|
138978
|
+
removeConfirm: "\u5220\u9664\u8FD9\u4E2A\u76EE\u6807",
|
|
138979
|
+
removeFailed: "\u8FD9\u4E2A\u76EE\u6807\u6CA1\u5220\u6389\u3002"
|
|
138980
|
+
}
|
|
138720
138981
|
}
|
|
138721
138982
|
};
|
|
138722
138983
|
|
|
@@ -139062,56 +139323,6 @@ var MINIMAL_HIDDEN = /* @__PURE__ */ new Set([
|
|
|
139062
139323
|
]);
|
|
139063
139324
|
var panelCommandsFor = (mode = "default") => mode === "minimal" ? PANEL_COMMANDS.filter((spec) => !MINIMAL_HIDDEN.has(spec.id)) : PANEL_COMMANDS;
|
|
139064
139325
|
|
|
139065
|
-
// src/sessionList.ts
|
|
139066
|
-
var SESSION_LIST_MAX = 20;
|
|
139067
|
-
var SESSION_ID_SHORT_LENGTH = 8;
|
|
139068
|
-
var ageLabel = (updatedAt, now, t) => {
|
|
139069
|
-
const at = Date.parse(updatedAt);
|
|
139070
|
-
if (Number.isNaN(at)) return "";
|
|
139071
|
-
const minutes = Math.floor(Math.max(0, now - at) / 6e4);
|
|
139072
|
-
if (minutes < 1) return t("sessions.age.justNow");
|
|
139073
|
-
if (minutes < 60) return t("sessions.age.minutes", { count: minutes });
|
|
139074
|
-
const hours = Math.floor(minutes / 60);
|
|
139075
|
-
if (hours < 24) return t("sessions.age.hours", { count: hours });
|
|
139076
|
-
return t("sessions.age.days", { count: Math.floor(hours / 24) });
|
|
139077
|
-
};
|
|
139078
|
-
var shortId = (threadId) => threadId.slice(0, SESSION_ID_SHORT_LENGTH);
|
|
139079
|
-
var sessionLine = (row, position, now, t) => {
|
|
139080
|
-
const title = row.title.replace(/\s+/g, " ").trim() || t("sessions.untitled");
|
|
139081
|
-
const age = ageLabel(row.updatedAt, now, t);
|
|
139082
|
-
const badges = [
|
|
139083
|
-
row.current ? t("sessions.badge.current") : null,
|
|
139084
|
-
row.running ? t("sessions.badge.running") : null,
|
|
139085
|
-
row.elsewhere ? t("sessions.badge.elsewhere") : null,
|
|
139086
|
-
row.origin === "web" ? t("sessions.badge.web") : null
|
|
139087
|
-
].filter((badge) => badge !== null);
|
|
139088
|
-
return [`${String(position)}. ${title}`, age, ...badges, shortId(row.threadId)].filter((part) => part !== "").join(" \xB7 ");
|
|
139089
|
-
};
|
|
139090
|
-
var formatSessions = (rows, now, t) => {
|
|
139091
|
-
if (rows.length === 0) return t("sessions.empty");
|
|
139092
|
-
const shown = rows.slice(0, SESSION_LIST_MAX);
|
|
139093
|
-
return [
|
|
139094
|
-
t("sessions.title", { count: rows.length }),
|
|
139095
|
-
...shown.map((row, index) => sessionLine(row, index + 1, now, t)),
|
|
139096
|
-
...rows.length > shown.length ? [t("sessions.more", { count: rows.length - shown.length })] : [],
|
|
139097
|
-
"",
|
|
139098
|
-
t("sessions.footer")
|
|
139099
|
-
].join("\n");
|
|
139100
|
-
};
|
|
139101
|
-
var listedThreadIds = (rows) => rows.slice(0, SESSION_LIST_MAX).map((row) => row.threadId);
|
|
139102
|
-
var looksLikeListNumber = (wanted) => /^[1-9]\d*$/u.test(wanted) && wanted.length <= String(SESSION_LIST_MAX).length;
|
|
139103
|
-
var pickSession = (arg, listed, rows) => {
|
|
139104
|
-
const wanted = arg.trim();
|
|
139105
|
-
if (wanted === "") return null;
|
|
139106
|
-
if (looksLikeListNumber(wanted)) {
|
|
139107
|
-
const ids = listed ?? listedThreadIds(rows);
|
|
139108
|
-
return ids[Number(wanted) - 1] ?? null;
|
|
139109
|
-
}
|
|
139110
|
-
const needle = wanted.toLowerCase();
|
|
139111
|
-
const matches = rows.filter((row) => row.threadId.toLowerCase().startsWith(needle));
|
|
139112
|
-
return matches.length === 1 ? matches[0]?.threadId ?? null : null;
|
|
139113
|
-
};
|
|
139114
|
-
|
|
139115
139326
|
// src/panelController.ts
|
|
139116
139327
|
var PANEL_PAGE_SIZE = 8;
|
|
139117
139328
|
var PANEL_CARD_LIMIT = 200;
|
|
@@ -140183,8 +140394,14 @@ var makeSendFileTool = (deps) => ({
|
|
|
140183
140394
|
});
|
|
140184
140395
|
|
|
140185
140396
|
// src/sessions.ts
|
|
140186
|
-
var SESSION_SCAN_LIMIT = 50;
|
|
140187
140397
|
var WEB_LIST_PAGE = 100;
|
|
140398
|
+
var shellOf = (thread) => ({
|
|
140399
|
+
threadId: thread.threadId,
|
|
140400
|
+
title: thread.title,
|
|
140401
|
+
updatedAt: thread.updatedAt,
|
|
140402
|
+
archivedAt: thread.archivedAt,
|
|
140403
|
+
sessionStatus: thread.session?.status ?? null
|
|
140404
|
+
});
|
|
140188
140405
|
var makeSessions = (core) => {
|
|
140189
140406
|
const { host, t, commit, bindChat, deliver } = core;
|
|
140190
140407
|
const listedByChat = /* @__PURE__ */ new Map();
|
|
@@ -140195,7 +140412,7 @@ var makeSessions = (core) => {
|
|
|
140195
140412
|
threadId: thread.threadId,
|
|
140196
140413
|
title: thread.title,
|
|
140197
140414
|
updatedAt: thread.updatedAt,
|
|
140198
|
-
running: thread.
|
|
140415
|
+
running: isSessionRunning(thread.sessionStatus),
|
|
140199
140416
|
current: chatOf(core.state, chatKey).threadId === thread.threadId,
|
|
140200
140417
|
elsewhere: Object.entries(core.state.chats).some(
|
|
140201
140418
|
([otherKey, record2]) => otherKey !== chatKey && record2.threadId === thread.threadId
|
|
@@ -140203,74 +140420,43 @@ var makeSessions = (core) => {
|
|
|
140203
140420
|
origin
|
|
140204
140421
|
};
|
|
140205
140422
|
};
|
|
140206
|
-
const
|
|
140207
|
-
|
|
140208
|
-
if (listThreads === void 0 || projectId === "") return [];
|
|
140423
|
+
const projectShells = async (projectId) => {
|
|
140424
|
+
if (projectId === "") return [];
|
|
140209
140425
|
const shells = [];
|
|
140210
|
-
let cursor =
|
|
140211
|
-
|
|
140212
|
-
const result = await
|
|
140426
|
+
let cursor = null;
|
|
140427
|
+
do {
|
|
140428
|
+
const result = await host.threads.list({
|
|
140429
|
+
projectId,
|
|
140213
140430
|
limit: WEB_LIST_PAGE,
|
|
140214
|
-
|
|
140215
|
-
|
|
140431
|
+
archived: "exclude",
|
|
140432
|
+
cursor
|
|
140216
140433
|
});
|
|
140217
|
-
for (const shell of result.
|
|
140218
|
-
if (shell.projectId !== projectId) continue;
|
|
140219
|
-
if (shell.archivedAt != null) continue;
|
|
140434
|
+
for (const shell of result.items) {
|
|
140220
140435
|
shells.push({
|
|
140221
140436
|
threadId: shell.threadId,
|
|
140222
140437
|
title: shell.title,
|
|
140223
140438
|
updatedAt: shell.updatedAt,
|
|
140224
140439
|
archivedAt: shell.archivedAt,
|
|
140225
|
-
|
|
140226
|
-
activeTurnId: shell.sessionStatus === "running" ? "running" : null
|
|
140227
|
-
}
|
|
140440
|
+
sessionStatus: shell.sessionStatus
|
|
140228
140441
|
});
|
|
140229
140442
|
}
|
|
140230
|
-
if (result.nextCursor === null) break;
|
|
140231
140443
|
cursor = result.nextCursor;
|
|
140232
|
-
}
|
|
140444
|
+
} while (cursor !== null);
|
|
140233
140445
|
return shells;
|
|
140234
140446
|
};
|
|
140447
|
+
const originOf = (threadId, projectId) => core.state.opened[threadId]?.projectId === projectId ? "plugin" : "web";
|
|
140235
140448
|
const sessionRowsFor = async (binding) => {
|
|
140236
140449
|
const chatKey = chatKeyOf(binding);
|
|
140237
|
-
|
|
140238
|
-
|
|
140239
|
-
|
|
140240
|
-
|
|
140241
|
-
|
|
140242
|
-
|
|
140243
|
-
|
|
140244
|
-
);
|
|
140245
|
-
|
|
140246
|
-
|
|
140247
|
-
for (const thread of ownedThreads) {
|
|
140248
|
-
if (thread === null) continue;
|
|
140249
|
-
const row = rowFromThread(thread, chatKey, "plugin");
|
|
140250
|
-
if (row === null) continue;
|
|
140251
|
-
rows.push(row);
|
|
140252
|
-
seen.add(row.threadId);
|
|
140253
|
-
}
|
|
140254
|
-
const shells = await webShellsForProject(binding.projectId);
|
|
140255
|
-
const listed = new Set(shells.map((shell) => shell.threadId));
|
|
140256
|
-
const attached = await Promise.all(
|
|
140257
|
-
attachedOnChat(core.state, chatKey, binding.projectId).filter(({ threadId }) => !listed.has(threadId)).map(({ threadId }) => host.projections.getThread(threadId))
|
|
140258
|
-
);
|
|
140259
|
-
for (const thread of attached) {
|
|
140260
|
-
if (thread === null || seen.has(thread.threadId) || openedIds.has(thread.threadId)) continue;
|
|
140261
|
-
const row = rowFromThread(thread, chatKey, "web");
|
|
140262
|
-
if (row === null) continue;
|
|
140263
|
-
rows.push(row);
|
|
140264
|
-
seen.add(row.threadId);
|
|
140265
|
-
}
|
|
140266
|
-
for (const shell of shells) {
|
|
140267
|
-
if (seen.has(shell.threadId) || openedIds.has(shell.threadId)) continue;
|
|
140268
|
-
const row = rowFromThread(shell, chatKey, "web");
|
|
140269
|
-
if (row === null) continue;
|
|
140270
|
-
rows.push(row);
|
|
140271
|
-
seen.add(row.threadId);
|
|
140272
|
-
}
|
|
140273
|
-
return rows.toSorted((left, right) => right.updatedAt.localeCompare(left.updatedAt));
|
|
140450
|
+
const shells = await projectShells(binding.projectId);
|
|
140451
|
+
return shells.flatMap((shell) => {
|
|
140452
|
+
const row = rowFromThread(shell, chatKey, originOf(shell.threadId, binding.projectId));
|
|
140453
|
+
return row === null ? [] : [row];
|
|
140454
|
+
});
|
|
140455
|
+
};
|
|
140456
|
+
const rowForThread = async (binding, chatKey, threadId) => {
|
|
140457
|
+
const thread = await host.projections.getThread(threadId);
|
|
140458
|
+
if (thread === null || thread.projectId !== binding.projectId) return null;
|
|
140459
|
+
return rowFromThread(shellOf(thread), chatKey, originOf(threadId, binding.projectId));
|
|
140274
140460
|
};
|
|
140275
140461
|
const showSessions = async (binding) => {
|
|
140276
140462
|
const rows = await sessionRowsFor(binding);
|
|
@@ -140316,24 +140502,27 @@ var makeSessions = (core) => {
|
|
|
140316
140502
|
await deliver(binding, t("resume.nothingPending"));
|
|
140317
140503
|
return;
|
|
140318
140504
|
}
|
|
140319
|
-
const
|
|
140320
|
-
let targetId;
|
|
140321
|
-
if (
|
|
140322
|
-
targetId =
|
|
140323
|
-
} else {
|
|
140324
|
-
targetId = pickSession(wanted, listedByChat.get(chatKey), rows);
|
|
140505
|
+
const listed = listedByChat.get(chatKey);
|
|
140506
|
+
let targetId = confirming ? pending ?? null : listed === void 0 ? null : pickSession(wanted, listed, []);
|
|
140507
|
+
if (targetId === null) {
|
|
140508
|
+
targetId = pickSession(wanted, listed, await sessionRowsFor(binding));
|
|
140325
140509
|
if (targetId === null) {
|
|
140326
140510
|
await deliver(binding, t("resume.notFound", { query: arg }));
|
|
140327
140511
|
return;
|
|
140328
140512
|
}
|
|
140329
140513
|
}
|
|
140330
|
-
const
|
|
140331
|
-
|
|
140514
|
+
const currentId = chatOf(core.state, chatKey).threadId;
|
|
140515
|
+
const [target2, other] = await Promise.all([
|
|
140516
|
+
rowForThread(binding, chatKey, targetId),
|
|
140517
|
+
currentId === null || currentId === targetId ? null : rowForThread(binding, chatKey, currentId)
|
|
140518
|
+
]);
|
|
140519
|
+
const currentBusy = (currentId === targetId ? target2 : other)?.running === true;
|
|
140520
|
+
if (target2 === null) {
|
|
140332
140521
|
if (confirming) pendingAttachByChat.delete(chatKey);
|
|
140333
140522
|
await deliver(binding, t("resume.gone"));
|
|
140334
140523
|
return;
|
|
140335
140524
|
}
|
|
140336
|
-
if (
|
|
140525
|
+
if (currentBusy) {
|
|
140337
140526
|
await deliver(binding, t("resume.busy"));
|
|
140338
140527
|
return;
|
|
140339
140528
|
}
|
|
@@ -140875,6 +141064,7 @@ var tokenOf = (binding) => (binding.values["telegramToken"] ?? "").trim();
|
|
|
140875
141064
|
var REACTION_WORKING = "\u{1F440}";
|
|
140876
141065
|
var REACTION_DONE = "\u{1F44D}";
|
|
140877
141066
|
var REACTION_FAILED = "\u{1F44E}";
|
|
141067
|
+
var telegramConfigIssues = (binding) => tokenOf(binding) === "" ? [{ column: "telegramToken", code: "required" }] : [];
|
|
140878
141068
|
var defaultSleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
140879
141069
|
var webhookHost = (url) => {
|
|
140880
141070
|
try {
|
|
@@ -140976,7 +141166,8 @@ var makeTelegramAdapter = (deps) => {
|
|
|
140976
141166
|
icon: "telegram",
|
|
140977
141167
|
label: "Telegram",
|
|
140978
141168
|
columns: COLUMNS2,
|
|
140979
|
-
|
|
141169
|
+
validate: telegramConfigIssues,
|
|
141170
|
+
isConfigured: (binding) => telegramConfigIssues(binding).length === 0,
|
|
140980
141171
|
connect: async (binding, handlers) => {
|
|
140981
141172
|
let stop = () => {
|
|
140982
141173
|
};
|
|
@@ -141493,10 +141684,9 @@ var makeWebSync = (core) => {
|
|
|
141493
141684
|
// src/settingsRowActions.ts
|
|
141494
141685
|
var ROW_PAYLOAD_SCHEMA = {
|
|
141495
141686
|
type: "object",
|
|
141496
|
-
required: ["rowId"
|
|
141687
|
+
required: ["rowId"],
|
|
141497
141688
|
properties: {
|
|
141498
|
-
rowId: { type: "string" }
|
|
141499
|
-
values: { type: "object" }
|
|
141689
|
+
rowId: { type: "string" }
|
|
141500
141690
|
},
|
|
141501
141691
|
additionalProperties: false
|
|
141502
141692
|
};
|
|
@@ -141584,19 +141774,19 @@ var registerSettingsRowActions = (ctx, adapters) => {
|
|
|
141584
141774
|
});
|
|
141585
141775
|
};
|
|
141586
141776
|
registerProbeAction({
|
|
141587
|
-
name:
|
|
141777
|
+
name: BOT_ACTION_COMMANDS.checkConnection,
|
|
141588
141778
|
summary: "Probe an IM bot's platform credentials without calling a model.",
|
|
141589
141779
|
keyPrefix: "rowAction.checkConnection",
|
|
141590
141780
|
copyable: false
|
|
141591
141781
|
});
|
|
141592
141782
|
registerProbeAction({
|
|
141593
|
-
name:
|
|
141783
|
+
name: BOT_ACTION_COMMANDS.copyDiagnostics,
|
|
141594
141784
|
summary: "Probe an IM bot and return a copy-paste diagnostic report.",
|
|
141595
141785
|
keyPrefix: "rowAction.copyDiagnostics",
|
|
141596
141786
|
copyable: true
|
|
141597
141787
|
});
|
|
141598
141788
|
ctx.stream({
|
|
141599
|
-
name:
|
|
141789
|
+
name: BOT_ACTION_COMMANDS.larkRepair,
|
|
141600
141790
|
description: "Guide Lark scope repair and verify the saved app can still mint a token.",
|
|
141601
141791
|
scope: "operate",
|
|
141602
141792
|
payloadSchema: ROW_PAYLOAD_SCHEMA,
|
|
@@ -141662,6 +141852,289 @@ var registerSettingsRowActions = (ctx, adapters) => {
|
|
|
141662
141852
|
});
|
|
141663
141853
|
};
|
|
141664
141854
|
|
|
141855
|
+
// src/settingsView.ts
|
|
141856
|
+
var isRecord2 = (value2) => typeof value2 === "object" && value2 !== null && !Array.isArray(value2);
|
|
141857
|
+
var hasStoredSecret = (row, key) => {
|
|
141858
|
+
const value2 = row[key];
|
|
141859
|
+
return typeof value2 === "string" && value2 !== "";
|
|
141860
|
+
};
|
|
141861
|
+
var nextRowId = (table2) => {
|
|
141862
|
+
for (let index = 1; ; index += 1) {
|
|
141863
|
+
const candidate = `row${index}`;
|
|
141864
|
+
if (!Object.hasOwn(table2, candidate)) return candidate;
|
|
141865
|
+
}
|
|
141866
|
+
};
|
|
141867
|
+
var columnError = (code2, column) => ({ ok: false, code: code2, column });
|
|
141868
|
+
var targetTable = () => ({
|
|
141869
|
+
field: DELIVERY_TARGETS_FIELD,
|
|
141870
|
+
columns: deliveryTargetColumns()
|
|
141871
|
+
});
|
|
141872
|
+
var targetViews = (config2) => {
|
|
141873
|
+
const table2 = config2[DELIVERY_TARGETS_FIELD];
|
|
141874
|
+
if (!isRecord2(table2)) return [];
|
|
141875
|
+
const columns = deliveryTargetColumns();
|
|
141876
|
+
return Object.entries(table2).flatMap(([rowId, raw]) => {
|
|
141877
|
+
if (!isRecord2(raw)) return [];
|
|
141878
|
+
const issues = targetIssues(raw);
|
|
141879
|
+
const values = Object.fromEntries(
|
|
141880
|
+
columns.map((column) => [column.key, readString(raw, column.key)])
|
|
141881
|
+
);
|
|
141882
|
+
return [{ rowId, configured: issues.length === 0, values, issues }];
|
|
141883
|
+
});
|
|
141884
|
+
};
|
|
141885
|
+
var buildSettingsView = (config2, adapters) => {
|
|
141886
|
+
const columns = buildBotColumns(adapters);
|
|
141887
|
+
const table2 = config2[BOTS_FIELD];
|
|
141888
|
+
const bots = [];
|
|
141889
|
+
if (isRecord2(table2)) {
|
|
141890
|
+
for (const [rowId, raw] of Object.entries(table2)) {
|
|
141891
|
+
if (!isRecord2(raw)) continue;
|
|
141892
|
+
const platform = platformOf(raw);
|
|
141893
|
+
const values = {};
|
|
141894
|
+
const secrets = {};
|
|
141895
|
+
for (const column of columns) {
|
|
141896
|
+
if (column.kind === "password") secrets[column.key] = hasStoredSecret(raw, column.key);
|
|
141897
|
+
else values[column.key] = readString(raw, column.key);
|
|
141898
|
+
}
|
|
141899
|
+
const adapter = adapters.find((candidate) => candidate.platform === platform);
|
|
141900
|
+
if (adapter === void 0) {
|
|
141901
|
+
bots.push({
|
|
141902
|
+
rowId,
|
|
141903
|
+
platform,
|
|
141904
|
+
configured: false,
|
|
141905
|
+
values,
|
|
141906
|
+
secrets,
|
|
141907
|
+
issues: [],
|
|
141908
|
+
publicFields: []
|
|
141909
|
+
});
|
|
141910
|
+
continue;
|
|
141911
|
+
}
|
|
141912
|
+
const bot = readBotView(rowId, raw, adapter);
|
|
141913
|
+
bots.push({
|
|
141914
|
+
rowId,
|
|
141915
|
+
platform,
|
|
141916
|
+
configured: adapter.isConfigured(bot),
|
|
141917
|
+
values,
|
|
141918
|
+
secrets,
|
|
141919
|
+
issues: adapter.validate?.(bot) ?? [],
|
|
141920
|
+
publicFields: adapter.publicFields?.(bot) ?? []
|
|
141921
|
+
});
|
|
141922
|
+
}
|
|
141923
|
+
}
|
|
141924
|
+
return {
|
|
141925
|
+
replyLanguage: parseReplyLanguage(config2[REPLY_LANGUAGE_FIELD]),
|
|
141926
|
+
bots,
|
|
141927
|
+
targets: targetViews(config2),
|
|
141928
|
+
delivery: {
|
|
141929
|
+
enabled: readDeliveryHttpEnabled(config2),
|
|
141930
|
+
port: readDeliveryHttpPort(config2),
|
|
141931
|
+
hasToken: readDeliveryHttpToken(config2) !== ""
|
|
141932
|
+
}
|
|
141933
|
+
};
|
|
141934
|
+
};
|
|
141935
|
+
var applyRowEdit = (config2, { field, columns }, edit) => {
|
|
141936
|
+
const plain = new Set(
|
|
141937
|
+
columns.filter((column) => column.kind !== "password").map((column) => column.key)
|
|
141938
|
+
);
|
|
141939
|
+
const secretColumns = new Set(
|
|
141940
|
+
columns.filter((column) => column.kind === "password").map((column) => column.key)
|
|
141941
|
+
);
|
|
141942
|
+
for (const key of Object.keys(edit.values)) {
|
|
141943
|
+
if (!plain.has(key)) return columnError("unknown-column", key);
|
|
141944
|
+
}
|
|
141945
|
+
const secrets = edit.secrets ?? {};
|
|
141946
|
+
for (const [key, value2] of Object.entries(secrets)) {
|
|
141947
|
+
if (!secretColumns.has(key)) return columnError("not-a-secret", key);
|
|
141948
|
+
if (value2 === "") return columnError("empty-secret", key);
|
|
141949
|
+
}
|
|
141950
|
+
const clearSecrets = edit.clearSecrets ?? [];
|
|
141951
|
+
for (const key of clearSecrets) {
|
|
141952
|
+
if (!secretColumns.has(key)) return columnError("not-a-secret", key);
|
|
141953
|
+
}
|
|
141954
|
+
const table2 = isRecord2(config2[field]) ? config2[field] : {};
|
|
141955
|
+
const requested = edit.rowId;
|
|
141956
|
+
const current = requested === void 0 ? {} : Object.hasOwn(table2, requested) ? table2[requested] : void 0;
|
|
141957
|
+
if (!isRecord2(current)) return { ok: false, code: "unknown-row" };
|
|
141958
|
+
const rowId = requested ?? nextRowId(table2);
|
|
141959
|
+
const nextRow = { ...current, ...edit.values };
|
|
141960
|
+
const clearing = clearSecrets.filter((key) => !Object.hasOwn(secrets, key));
|
|
141961
|
+
for (const key of clearing) delete nextRow[key];
|
|
141962
|
+
for (const [key, value2] of Object.entries(secrets)) nextRow[key] = value2;
|
|
141963
|
+
return {
|
|
141964
|
+
ok: true,
|
|
141965
|
+
rowId,
|
|
141966
|
+
config: { ...config2, [field]: { ...table2, [rowId]: nextRow } },
|
|
141967
|
+
secrets: Object.keys(secrets).map((key) => [field, rowId, key]),
|
|
141968
|
+
clearSecrets: clearing.map((key) => [field, rowId, key])
|
|
141969
|
+
};
|
|
141970
|
+
};
|
|
141971
|
+
var applyBotEdit = (config2, adapters, edit) => applyRowEdit(config2, { field: BOTS_FIELD, columns: buildBotColumns(adapters) }, edit);
|
|
141972
|
+
var applyTargetEdit = (config2, edit) => applyRowEdit(config2, targetTable(), edit);
|
|
141973
|
+
var removeRow = (config2, field, rowId) => {
|
|
141974
|
+
const table2 = config2[field];
|
|
141975
|
+
if (!isRecord2(table2) || !Object.hasOwn(table2, rowId)) return null;
|
|
141976
|
+
const nextTable = { ...table2 };
|
|
141977
|
+
delete nextTable[rowId];
|
|
141978
|
+
return { ...config2, [field]: nextTable };
|
|
141979
|
+
};
|
|
141980
|
+
var removeBotRow = (config2, rowId) => removeRow(config2, BOTS_FIELD, rowId);
|
|
141981
|
+
var removeTargetRow = (config2, rowId) => removeRow(config2, DELIVERY_TARGETS_FIELD, rowId);
|
|
141982
|
+
|
|
141983
|
+
// src/settingsCommands.ts
|
|
141984
|
+
var CLEAR_DELIVERY_HTTP_TOKEN = "clearDeliveryHttpToken";
|
|
141985
|
+
var EMPTY_PAYLOAD = {
|
|
141986
|
+
type: "object",
|
|
141987
|
+
additionalProperties: false
|
|
141988
|
+
};
|
|
141989
|
+
var SAVE_BOT_PAYLOAD = {
|
|
141990
|
+
type: "object",
|
|
141991
|
+
additionalProperties: false,
|
|
141992
|
+
required: ["values"],
|
|
141993
|
+
properties: {
|
|
141994
|
+
rowId: { type: "string" },
|
|
141995
|
+
values: { type: "object", additionalProperties: { type: "string" } },
|
|
141996
|
+
secrets: { type: "object", additionalProperties: { type: "string" } },
|
|
141997
|
+
clearSecrets: { type: "array", items: { type: "string" } }
|
|
141998
|
+
}
|
|
141999
|
+
};
|
|
142000
|
+
var SAVE_TARGET_PAYLOAD = {
|
|
142001
|
+
type: "object",
|
|
142002
|
+
additionalProperties: false,
|
|
142003
|
+
required: ["values"],
|
|
142004
|
+
properties: {
|
|
142005
|
+
rowId: { type: "string" },
|
|
142006
|
+
values: { type: "object", additionalProperties: { type: "string" } }
|
|
142007
|
+
}
|
|
142008
|
+
};
|
|
142009
|
+
var REMOVE_BOT_PAYLOAD = {
|
|
142010
|
+
type: "object",
|
|
142011
|
+
additionalProperties: false,
|
|
142012
|
+
required: ["rowId"],
|
|
142013
|
+
properties: {
|
|
142014
|
+
rowId: { type: "string" }
|
|
142015
|
+
}
|
|
142016
|
+
};
|
|
142017
|
+
var SAVE_GENERAL_PAYLOAD = {
|
|
142018
|
+
type: "object",
|
|
142019
|
+
additionalProperties: false,
|
|
142020
|
+
properties: {
|
|
142021
|
+
[REPLY_LANGUAGE_FIELD]: {
|
|
142022
|
+
type: "string",
|
|
142023
|
+
enum: REPLY_LANGUAGE_OPTIONS.map((option) => option.value)
|
|
142024
|
+
},
|
|
142025
|
+
[DELIVERY_HTTP_ENABLED_FIELD]: { type: "boolean" },
|
|
142026
|
+
[DELIVERY_HTTP_PORT_FIELD]: { type: "integer", minimum: 1, maximum: 65535 },
|
|
142027
|
+
[DELIVERY_HTTP_TOKEN_FIELD]: { type: "string", minLength: 1 },
|
|
142028
|
+
[CLEAR_DELIVERY_HTTP_TOKEN]: { type: "boolean" }
|
|
142029
|
+
}
|
|
142030
|
+
};
|
|
142031
|
+
var proxyChoice = (proxy) => proxy.displayName === void 0 ? { id: proxy.id, isDefault: proxy.isDefault } : { id: proxy.id, displayName: proxy.displayName, isDefault: proxy.isDefault };
|
|
142032
|
+
var botEditOf = (payload) => ({
|
|
142033
|
+
values: payload["values"],
|
|
142034
|
+
..."rowId" in payload ? { rowId: payload["rowId"] } : {},
|
|
142035
|
+
..."secrets" in payload ? { secrets: payload["secrets"] } : {},
|
|
142036
|
+
..."clearSecrets" in payload ? { clearSecrets: payload["clearSecrets"] } : {}
|
|
142037
|
+
});
|
|
142038
|
+
var generalWriteOptions = (payload, next) => {
|
|
142039
|
+
if (DELIVERY_HTTP_TOKEN_FIELD in payload) {
|
|
142040
|
+
next[DELIVERY_HTTP_TOKEN_FIELD] = payload[DELIVERY_HTTP_TOKEN_FIELD];
|
|
142041
|
+
return { secrets: [[DELIVERY_HTTP_TOKEN_FIELD]] };
|
|
142042
|
+
}
|
|
142043
|
+
if (payload[CLEAR_DELIVERY_HTTP_TOKEN] === true) {
|
|
142044
|
+
delete next[DELIVERY_HTTP_TOKEN_FIELD];
|
|
142045
|
+
return { clearSecrets: [[DELIVERY_HTTP_TOKEN_FIELD]] };
|
|
142046
|
+
}
|
|
142047
|
+
return void 0;
|
|
142048
|
+
};
|
|
142049
|
+
var viewAfterWrite = async (ctx, adapters) => buildSettingsView(await ctx.settings.read(), adapters);
|
|
142050
|
+
var registerSettingsCommands = (ctx, adapters, updateSettings) => {
|
|
142051
|
+
ctx.command({
|
|
142052
|
+
name: SETTINGS_VIEW_COMMAND,
|
|
142053
|
+
description: "Read the chat-bridge settings view, bot columns, and this machine's proxies.",
|
|
142054
|
+
scope: "read",
|
|
142055
|
+
payloadSchema: EMPTY_PAYLOAD,
|
|
142056
|
+
handle: async () => {
|
|
142057
|
+
const [config2, listed] = await Promise.all([ctx.settings.read(), ctx.proxies.list()]);
|
|
142058
|
+
return {
|
|
142059
|
+
view: buildSettingsView(config2, adapters),
|
|
142060
|
+
columns: buildBotColumns(adapters),
|
|
142061
|
+
targetColumns: deliveryTargetColumns(),
|
|
142062
|
+
proxies: listed.map(proxyChoice)
|
|
142063
|
+
};
|
|
142064
|
+
}
|
|
142065
|
+
});
|
|
142066
|
+
const saveRow = async (edit) => {
|
|
142067
|
+
const edited = await updateSettings((config2) => {
|
|
142068
|
+
const result = edit(config2);
|
|
142069
|
+
if (!result.ok) return { result };
|
|
142070
|
+
const { config: next, secrets, clearSecrets } = result;
|
|
142071
|
+
return { result, write: { config: next, options: { secrets, clearSecrets } } };
|
|
142072
|
+
});
|
|
142073
|
+
if (!edited.ok) return edited;
|
|
142074
|
+
return { ok: true, rowId: edited.rowId, view: await viewAfterWrite(ctx, adapters) };
|
|
142075
|
+
};
|
|
142076
|
+
const removeRow2 = async (remove) => {
|
|
142077
|
+
const removed = await updateSettings((config2) => {
|
|
142078
|
+
const next = remove(config2);
|
|
142079
|
+
return next === null ? { result: false } : { result: true, write: { config: next } };
|
|
142080
|
+
});
|
|
142081
|
+
if (!removed) return { ok: false, code: "unknown-row" };
|
|
142082
|
+
return { ok: true, view: await viewAfterWrite(ctx, adapters) };
|
|
142083
|
+
};
|
|
142084
|
+
ctx.command({
|
|
142085
|
+
name: SETTINGS_SAVE_BOT_COMMAND,
|
|
142086
|
+
description: "Create or update one bot row.",
|
|
142087
|
+
scope: "operate",
|
|
142088
|
+
payloadSchema: SAVE_BOT_PAYLOAD,
|
|
142089
|
+
handle: (payload) => saveRow((config2) => applyBotEdit(config2, adapters, botEditOf(payload)))
|
|
142090
|
+
});
|
|
142091
|
+
ctx.command({
|
|
142092
|
+
name: SETTINGS_REMOVE_BOT_COMMAND,
|
|
142093
|
+
description: "Remove one bot row.",
|
|
142094
|
+
scope: "operate",
|
|
142095
|
+
payloadSchema: REMOVE_BOT_PAYLOAD,
|
|
142096
|
+
handle: (payload) => removeRow2((config2) => removeBotRow(config2, payload["rowId"]))
|
|
142097
|
+
});
|
|
142098
|
+
ctx.command({
|
|
142099
|
+
name: SETTINGS_SAVE_TARGET_COMMAND,
|
|
142100
|
+
description: "Create or update one proactive delivery target.",
|
|
142101
|
+
scope: "operate",
|
|
142102
|
+
payloadSchema: SAVE_TARGET_PAYLOAD,
|
|
142103
|
+
handle: (payload) => saveRow((config2) => applyTargetEdit(config2, botEditOf(payload)))
|
|
142104
|
+
});
|
|
142105
|
+
ctx.command({
|
|
142106
|
+
name: SETTINGS_REMOVE_TARGET_COMMAND,
|
|
142107
|
+
description: "Remove one proactive delivery target.",
|
|
142108
|
+
scope: "operate",
|
|
142109
|
+
payloadSchema: REMOVE_BOT_PAYLOAD,
|
|
142110
|
+
handle: (payload) => removeRow2((config2) => removeTargetRow(config2, payload["rowId"]))
|
|
142111
|
+
});
|
|
142112
|
+
ctx.command({
|
|
142113
|
+
name: SETTINGS_SAVE_GENERAL_COMMAND,
|
|
142114
|
+
description: "Update reply language and proactive delivery HTTP settings.",
|
|
142115
|
+
scope: "operate",
|
|
142116
|
+
payloadSchema: SAVE_GENERAL_PAYLOAD,
|
|
142117
|
+
handle: async (payload) => {
|
|
142118
|
+
await updateSettings((config2) => {
|
|
142119
|
+
const next = { ...config2 };
|
|
142120
|
+
for (const field of [
|
|
142121
|
+
REPLY_LANGUAGE_FIELD,
|
|
142122
|
+
DELIVERY_HTTP_ENABLED_FIELD,
|
|
142123
|
+
DELIVERY_HTTP_PORT_FIELD
|
|
142124
|
+
]) {
|
|
142125
|
+
if (field in payload) next[field] = payload[field];
|
|
142126
|
+
}
|
|
142127
|
+
const options = generalWriteOptions(payload, next);
|
|
142128
|
+
return {
|
|
142129
|
+
result: void 0,
|
|
142130
|
+
write: options === void 0 ? { config: next } : { config: next, options }
|
|
142131
|
+
};
|
|
142132
|
+
});
|
|
142133
|
+
return { ok: true, view: await viewAfterWrite(ctx, adapters) };
|
|
142134
|
+
}
|
|
142135
|
+
});
|
|
142136
|
+
};
|
|
142137
|
+
|
|
141665
142138
|
// src/wechatApi.ts
|
|
141666
142139
|
var WECHAT_TEXT_MAX_CHARS = 1800;
|
|
141667
142140
|
|
|
@@ -141675,6 +142148,7 @@ var COLUMNS3 = [
|
|
|
141675
142148
|
}
|
|
141676
142149
|
];
|
|
141677
142150
|
var tokenOf2 = (bot) => bot.values["wechatBotToken"] ?? "";
|
|
142151
|
+
var wechatConfigIssues = (bot) => tokenOf2(bot) === "" ? [{ column: "wechatBotToken", code: "required" }] : [];
|
|
141678
142152
|
var makeWechatAdapter = (deps) => {
|
|
141679
142153
|
return {
|
|
141680
142154
|
platform: "wechat",
|
|
@@ -141682,7 +142156,8 @@ var makeWechatAdapter = (deps) => {
|
|
|
141682
142156
|
// 平台名与设置表的平台选项同一个键,免得默认机器人名与选项写成两种叫法。
|
|
141683
142157
|
label: deps.translate("platform.wechat"),
|
|
141684
142158
|
columns: COLUMNS3,
|
|
141685
|
-
|
|
142159
|
+
validate: wechatConfigIssues,
|
|
142160
|
+
isConfigured: (bot) => wechatConfigIssues(bot).length === 0,
|
|
141686
142161
|
connect: (bot, _handlers) => {
|
|
141687
142162
|
deps.log.warn("wechat iLink connect is stubbed pending security-review gate (YCO-236)", {
|
|
141688
142163
|
bot: bot.displayName,
|
|
@@ -142216,6 +142691,13 @@ var credentials2 = (binding) => ({
|
|
|
142216
142691
|
botSecret: binding.values["wecomBotSecret"] ?? "",
|
|
142217
142692
|
endpoint: normalizeWecomEndpoint(binding.values["wecomEndpoint"] || DEFAULT_WECOM_ENDPOINT)
|
|
142218
142693
|
});
|
|
142694
|
+
var wecomConfigIssues = (binding) => {
|
|
142695
|
+
const { botId, botSecret } = credentials2(binding);
|
|
142696
|
+
const issues = [];
|
|
142697
|
+
if (botId === "") issues.push({ column: "wecomBotId", code: "required" });
|
|
142698
|
+
if (botSecret === "") issues.push({ column: "wecomBotSecret", code: "required" });
|
|
142699
|
+
return issues;
|
|
142700
|
+
};
|
|
142219
142701
|
var makeWecomAdapter = (deps) => {
|
|
142220
142702
|
const clients = /* @__PURE__ */ new Map();
|
|
142221
142703
|
const t = deps.translate;
|
|
@@ -142260,10 +142742,8 @@ ${kept}`;
|
|
|
142260
142742
|
label: "WeCom",
|
|
142261
142743
|
columns: COLUMNS4,
|
|
142262
142744
|
unlistedValues: ["wecomEndpoint"],
|
|
142263
|
-
|
|
142264
|
-
|
|
142265
|
-
return botId !== "" && botSecret !== "";
|
|
142266
|
-
},
|
|
142745
|
+
validate: wecomConfigIssues,
|
|
142746
|
+
isConfigured: (binding) => wecomConfigIssues(binding).length === 0,
|
|
142267
142747
|
connect: (binding, handlers) => {
|
|
142268
142748
|
const { botId, botSecret, endpoint } = credentials2(binding);
|
|
142269
142749
|
let stopped = false;
|
|
@@ -142755,7 +143235,7 @@ var createWecomAppCrypto = (input) => {
|
|
|
142755
143235
|
var deriveCallbackPathSecret = (token, encodingAESKey) => NodeCrypto4.createHash("sha256").update(`${token.trim()}:${encodingAESKey.trim()}`).digest("hex").slice(0, 24);
|
|
142756
143236
|
|
|
142757
143237
|
// src/wecomAppParse.ts
|
|
142758
|
-
var
|
|
143238
|
+
var isRecord3 = (value2) => value2 !== null && typeof value2 === "object" && !Array.isArray(value2);
|
|
142759
143239
|
var isXmlFormat = (raw) => {
|
|
142760
143240
|
const trimmed = raw.trim();
|
|
142761
143241
|
return trimmed.startsWith("<") && trimmed.endsWith(">");
|
|
@@ -142801,7 +143281,7 @@ var parseWecomAppPlainMessage = (raw) => {
|
|
|
142801
143281
|
} catch {
|
|
142802
143282
|
return null;
|
|
142803
143283
|
}
|
|
142804
|
-
if (!
|
|
143284
|
+
if (!isRecord3(data)) return null;
|
|
142805
143285
|
const fromRaw = data["from"];
|
|
142806
143286
|
const textRaw = data["text"];
|
|
142807
143287
|
const imageRaw = data["image"];
|
|
@@ -142810,10 +143290,10 @@ var parseWecomAppPlainMessage = (raw) => {
|
|
|
142810
143290
|
msgtype: String(data["msgtype"] ?? data["MsgType"] ?? "").toLowerCase(),
|
|
142811
143291
|
createTime: data["createTime"] !== void 0 ? String(data["createTime"]) : data["CreateTime"] !== void 0 ? String(data["CreateTime"]) : void 0,
|
|
142812
143292
|
agentId: data["agentid"] !== void 0 ? String(data["agentid"]) : data["AgentID"] !== void 0 ? String(data["AgentID"]) : void 0,
|
|
142813
|
-
from:
|
|
143293
|
+
from: isRecord3(fromRaw) ? { userid: typeof fromRaw["userid"] === "string" ? fromRaw["userid"] : void 0 } : typeof data["FromUserName"] === "string" ? { userid: data["FromUserName"] } : void 0,
|
|
142814
143294
|
to: typeof data["to"] === "string" ? data["to"] : void 0,
|
|
142815
|
-
text:
|
|
142816
|
-
image:
|
|
143295
|
+
text: isRecord3(textRaw) ? { content: typeof textRaw["content"] === "string" ? textRaw["content"] : void 0 } : void 0,
|
|
143296
|
+
image: isRecord3(imageRaw) ? { url: typeof imageRaw["url"] === "string" ? imageRaw["url"] : void 0 } : void 0,
|
|
142817
143297
|
mediaId: typeof data["mediaid"] === "string" ? data["mediaid"] : void 0,
|
|
142818
143298
|
recognition: typeof data["recognition"] === "string" ? data["recognition"] : void 0,
|
|
142819
143299
|
event: String(data["event"] ?? data["eventtype"] ?? "").toLowerCase() || void 0,
|
|
@@ -143183,6 +143663,21 @@ var WECOM_APP_IMAGE_BYTES = 10 * 1024 * 1024;
|
|
|
143183
143663
|
var WECOM_APP_FILE_BYTES = 20 * 1024 * 1024;
|
|
143184
143664
|
var WECOM_APP_MIN_BYTES = 5;
|
|
143185
143665
|
var WECOM_APP_IMAGE_TYPES = /* @__PURE__ */ new Set(["image/jpeg", "image/png"]);
|
|
143666
|
+
var joinCallbackUrl = (baseOrOrigin, path) => `${baseOrOrigin}${path}`;
|
|
143667
|
+
var wecomAppPublicFields = (bot) => {
|
|
143668
|
+
const c = wecomAppCredentials(bot);
|
|
143669
|
+
if (c.callbackBaseUrl === "") return [];
|
|
143670
|
+
return [
|
|
143671
|
+
{
|
|
143672
|
+
key: "callbackUrl",
|
|
143673
|
+
value: joinCallbackUrl(
|
|
143674
|
+
c.callbackBaseUrl,
|
|
143675
|
+
callbackRoutePath(bot.rowId, c.token, c.encodingAESKey)
|
|
143676
|
+
),
|
|
143677
|
+
copyable: true
|
|
143678
|
+
}
|
|
143679
|
+
];
|
|
143680
|
+
};
|
|
143186
143681
|
var OUTBOUND_COLUMNS = /* @__PURE__ */ new Set([
|
|
143187
143682
|
"wecomAppCorpId",
|
|
143188
143683
|
"wecomAppAgentId",
|
|
@@ -143252,11 +143747,14 @@ var makeWecomAppAdapter = (deps) => {
|
|
|
143252
143747
|
icon: "wecom",
|
|
143253
143748
|
label: deps.translate("platform.wecom-app"),
|
|
143254
143749
|
columns: COLUMNS5,
|
|
143255
|
-
//
|
|
143256
|
-
// connect
|
|
143750
|
+
// 设置页标格子用完整的逐列结果。算不算配齐仍是原来那份,不能收成「一个问题都没有」:
|
|
143751
|
+
// 必填都填了、EncodingAESKey 格式对。别的列格式不对的行照样交给 connect 报出来(一条日志,
|
|
143752
|
+
// 不重试),也不挡设置页的「检查连接」去探出站凭据。
|
|
143753
|
+
validate: validateWecomAppBot,
|
|
143257
143754
|
isConfigured: (bot) => validateWecomAppBot(bot).every(
|
|
143258
143755
|
(issue) => issue.code !== "required" && issue.column !== "wecomAppEncodingAESKey"
|
|
143259
143756
|
),
|
|
143757
|
+
publicFields: wecomAppPublicFields,
|
|
143260
143758
|
/**
|
|
143261
143759
|
* 自建应用是回调式渠道:入站由企微推到我们的 listener,没有可探的长连接;能探的是出站
|
|
143262
143760
|
* 凭据——和真实发送同一条路,向 gettoken 换一次 access_token。
|
|
@@ -143320,7 +143818,10 @@ var makeWecomAppAdapter = (deps) => {
|
|
|
143320
143818
|
deps.log.info("wecom-app connected", {
|
|
143321
143819
|
bot: bot.displayName,
|
|
143322
143820
|
callbackPath: path,
|
|
143323
|
-
callbackUrl:
|
|
143821
|
+
callbackUrl: joinCallbackUrl(
|
|
143822
|
+
c.callbackBaseUrl !== "" ? c.callbackBaseUrl : server.origin,
|
|
143823
|
+
path
|
|
143824
|
+
),
|
|
143324
143825
|
listen: `${server.host}:${String(server.port)}`
|
|
143325
143826
|
});
|
|
143326
143827
|
return {
|
|
@@ -143364,7 +143865,7 @@ var makeWecomAppAdapter = (deps) => {
|
|
|
143364
143865
|
// src/index.ts
|
|
143365
143866
|
var imPlugin = definePlugin({
|
|
143366
143867
|
id: "im",
|
|
143367
|
-
apiVersion:
|
|
143868
|
+
apiVersion: 5,
|
|
143368
143869
|
activate: async (ctx) => {
|
|
143369
143870
|
const { t, setLanguage } = makeLiveTranslate(
|
|
143370
143871
|
parseReplyLanguage(ctx.config[REPLY_LANGUAGE_FIELD])
|
|
@@ -143421,13 +143922,17 @@ var imPlugin = definePlugin({
|
|
|
143421
143922
|
}
|
|
143422
143923
|
})
|
|
143423
143924
|
];
|
|
143424
|
-
ctx.settingsCard(
|
|
143425
|
-
|
|
143925
|
+
ctx.settingsCard(buildSettingsCard(adapters));
|
|
143926
|
+
const updateSettings = makeSettingsUpdater(ctx.settings);
|
|
143927
|
+
registerLarkSetup(ctx, { updateSettings });
|
|
143426
143928
|
registerSettingsRowActions(ctx, adapters);
|
|
143929
|
+
registerSettingsCommands(ctx, adapters, updateSettings);
|
|
143427
143930
|
const core = makeImCore({
|
|
143428
143931
|
host: {
|
|
143429
143932
|
log: ctx.log,
|
|
143430
143933
|
projections: ctx.projections,
|
|
143934
|
+
threads: ctx.threads,
|
|
143935
|
+
approvals: ctx.approvals,
|
|
143431
143936
|
commands: ctx.commands,
|
|
143432
143937
|
plugins: ctx.plugins,
|
|
143433
143938
|
attachments: ctx.attachments,
|