@ycodium-ai/plugin-im 0.2.2976 → 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 +842 -340
- 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) => {
|
|
@@ -127229,6 +127257,57 @@ var pickProject = (arg, listed, rows) => {
|
|
|
127229
127257
|
return prefixed.length === 1 ? prefixed[0]?.projectId ?? null : null;
|
|
127230
127258
|
};
|
|
127231
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
|
+
|
|
127232
127311
|
// src/chatSetup.ts
|
|
127233
127312
|
var makeChatSetup = (core, deps) => {
|
|
127234
127313
|
const { host, t, adapterFor, commit, deliver, bindingOf: bindingOf2, hasPanel } = core;
|
|
@@ -127287,7 +127366,7 @@ var makeChatSetup = (core, deps) => {
|
|
|
127287
127366
|
const threadId = chatOf(core.state, chatKey).threadId;
|
|
127288
127367
|
if (threadId !== null) {
|
|
127289
127368
|
const thread = await host.projections.getThread(threadId).catch(() => null);
|
|
127290
|
-
if (thread?.session?.
|
|
127369
|
+
if (isSessionRunning(thread?.session?.status)) {
|
|
127291
127370
|
await deliver(binding, t("repo.busy"));
|
|
127292
127371
|
return;
|
|
127293
127372
|
}
|
|
@@ -127642,7 +127721,7 @@ var makeCommands = (core, deps) => {
|
|
|
127642
127721
|
return true;
|
|
127643
127722
|
}
|
|
127644
127723
|
const thread = await host.projections.getThread(threadId);
|
|
127645
|
-
const running = thread?.session?.
|
|
127724
|
+
const running = isSessionRunning(thread?.session?.status);
|
|
127646
127725
|
await deliver(
|
|
127647
127726
|
binding,
|
|
127648
127727
|
[
|
|
@@ -128445,6 +128524,10 @@ var makeBoundedMap = (limit) => {
|
|
|
128445
128524
|
const oldest = entries.keys().next().value;
|
|
128446
128525
|
if (oldest !== void 0) entries.delete(oldest);
|
|
128447
128526
|
}
|
|
128527
|
+
},
|
|
128528
|
+
/** 忘掉键满足条件的那些。 */
|
|
128529
|
+
forget: (matches) => {
|
|
128530
|
+
for (const key of [...entries.keys()]) if (matches(key)) entries.delete(key);
|
|
128448
128531
|
}
|
|
128449
128532
|
};
|
|
128450
128533
|
};
|
|
@@ -129571,6 +129654,44 @@ var SETUP_ITEM_SCHEMA = makeFlowItemSchema({
|
|
|
129571
129654
|
qrRequired: ["payload", "expiresAt"],
|
|
129572
129655
|
doneRequired: ["messageKey"]
|
|
129573
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
|
+
};
|
|
129574
129695
|
|
|
129575
129696
|
// src/lark/setup/saveBot.ts
|
|
129576
129697
|
var OPEN_ID_PREFIX = "ou_";
|
|
@@ -130988,16 +131109,7 @@ var createSetupRunner = (deps) => {
|
|
|
130988
131109
|
};
|
|
130989
131110
|
|
|
130990
131111
|
// src/lark/setup/setupCommands.ts
|
|
130991
|
-
var SETUP_START_COMMAND = "larkSetup.start";
|
|
130992
131112
|
var SETUP_CHECKLIST_COMMAND = "larkSetup.checklist";
|
|
130993
|
-
var LARK_SETUP_CARD_ACTION = {
|
|
130994
|
-
id: "larkSetup",
|
|
130995
|
-
labelKey: "setup.action.label",
|
|
130996
|
-
descriptionKey: "setup.action.description",
|
|
130997
|
-
badgeKey: "setup.action.badge",
|
|
130998
|
-
warningKey: "setup.action.warning",
|
|
130999
|
-
command: SETUP_START_COMMAND
|
|
131000
|
-
};
|
|
131001
131113
|
var MANUAL_STEP_IDS = [
|
|
131002
131114
|
"createApp",
|
|
131003
131115
|
"enableBot",
|
|
@@ -131006,7 +131118,7 @@ var MANUAL_STEP_IDS = [
|
|
|
131006
131118
|
"publish",
|
|
131007
131119
|
"fillRow"
|
|
131008
131120
|
];
|
|
131009
|
-
var
|
|
131121
|
+
var SETUP_SESSION_PAYLOAD_SCHEMA = {
|
|
131010
131122
|
type: "object",
|
|
131011
131123
|
additionalProperties: false
|
|
131012
131124
|
};
|
|
@@ -131061,10 +131173,15 @@ var makeRealClock = () => ({
|
|
|
131061
131173
|
signal?.addEventListener("abort", onAbort, { once: true });
|
|
131062
131174
|
})
|
|
131063
131175
|
});
|
|
131064
|
-
var saveAndConclude = async (ctx, result) => {
|
|
131176
|
+
var saveAndConclude = async (ctx, updateSettings, result) => {
|
|
131065
131177
|
try {
|
|
131066
|
-
const saved =
|
|
131067
|
-
|
|
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
|
+
});
|
|
131068
131185
|
ctx.log.info("lark setup saved the bot", {
|
|
131069
131186
|
appId: result.appId,
|
|
131070
131187
|
rowId: saved.rowId,
|
|
@@ -131098,6 +131215,7 @@ var saveAndConclude = async (ctx, result) => {
|
|
|
131098
131215
|
}
|
|
131099
131216
|
};
|
|
131100
131217
|
var registerLarkSetup = (ctx, options = {}) => {
|
|
131218
|
+
const updateSettings = options.updateSettings ?? makeSettingsUpdater(ctx.settings);
|
|
131101
131219
|
const runner = createSetupRunner({
|
|
131102
131220
|
fetch: ctx.http,
|
|
131103
131221
|
clock: options.clock ?? makeRealClock(),
|
|
@@ -131110,15 +131228,19 @@ var registerLarkSetup = (ctx, options = {}) => {
|
|
|
131110
131228
|
...options.sessionRetryWindowMs === void 0 ? {} : { sessionRetryWindowMs: options.sessionRetryWindowMs }
|
|
131111
131229
|
});
|
|
131112
131230
|
ctx.stream({
|
|
131113
|
-
name:
|
|
131231
|
+
name: LARK_SETUP_SESSION_COMMAND,
|
|
131114
131232
|
description: "Set up a Lark app through the developer console after one QR scan.",
|
|
131115
131233
|
scope: "operate",
|
|
131116
|
-
payloadSchema:
|
|
131117
|
-
itemSchema:
|
|
131118
|
-
//
|
|
131234
|
+
payloadSchema: SETUP_SESSION_PAYLOAD_SCHEMA,
|
|
131235
|
+
itemSchema: SETUP_SNAPSHOT_SCHEMA,
|
|
131236
|
+
// 每一条都是完整的快照,慢订阅方丢掉的只该是旧的。
|
|
131119
131237
|
buffer: { latest: 16 },
|
|
131120
131238
|
handle: async (_payload, emit, signal) => {
|
|
131121
|
-
|
|
131239
|
+
let snapshot = {};
|
|
131240
|
+
const send = (item) => {
|
|
131241
|
+
snapshot = foldFlowItem(snapshot, item);
|
|
131242
|
+
emit(snapshot);
|
|
131243
|
+
};
|
|
131122
131244
|
const result = await runner.run(
|
|
131123
131245
|
{},
|
|
131124
131246
|
// 先落到宿主约定的条目类型上:形状不对在编译期就报,而不是到客户端被整条丢掉。
|
|
@@ -131126,7 +131248,7 @@ var registerLarkSetup = (ctx, options = {}) => {
|
|
|
131126
131248
|
signal
|
|
131127
131249
|
);
|
|
131128
131250
|
if (result === void 0) return;
|
|
131129
|
-
send(await saveAndConclude(ctx, result));
|
|
131251
|
+
send(await saveAndConclude(ctx, updateSettings, result));
|
|
131130
131252
|
}
|
|
131131
131253
|
});
|
|
131132
131254
|
ctx.command({
|
|
@@ -137184,6 +137306,13 @@ var credentials = (binding) => ({
|
|
|
137184
137306
|
appId: binding.values["larkAppId"] ?? "",
|
|
137185
137307
|
appSecret: binding.values["larkAppSecret"] ?? ""
|
|
137186
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
|
+
};
|
|
137187
137316
|
var makeLarkAdapter = (deps) => {
|
|
137188
137317
|
const tenantToken = async (binding) => {
|
|
137189
137318
|
const { appId, appSecret } = credentials(binding);
|
|
@@ -137196,12 +137325,16 @@ var makeLarkAdapter = (deps) => {
|
|
|
137196
137325
|
};
|
|
137197
137326
|
const aliasPorts = /* @__PURE__ */ new Map();
|
|
137198
137327
|
const topicThreadIds = makeBoundedMap(TOPIC_THREAD_CACHE_LIMIT);
|
|
137328
|
+
const unreported = /* @__PURE__ */ new Map();
|
|
137199
137329
|
const learning = /* @__PURE__ */ new Map();
|
|
137200
137330
|
const learnTopic = (binding, target2, threadId) => {
|
|
137201
137331
|
const key = chatKeyOf(binding);
|
|
137202
137332
|
const report = (id) => {
|
|
137203
137333
|
topicThreadIds.set(key, id);
|
|
137204
|
-
|
|
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);
|
|
137205
137338
|
};
|
|
137206
137339
|
const known = threadId ?? topicThreadIds.get(key);
|
|
137207
137340
|
if (known !== void 0) {
|
|
@@ -137266,10 +137399,8 @@ var makeLarkAdapter = (deps) => {
|
|
|
137266
137399
|
const { chatId: groupId, rootMessageId } = splitTopicChatId(chatId);
|
|
137267
137400
|
return rootMessageId === void 0 ? void 0 : groupId;
|
|
137268
137401
|
},
|
|
137269
|
-
|
|
137270
|
-
|
|
137271
|
-
return appId !== "" && appSecret !== "";
|
|
137272
|
-
},
|
|
137402
|
+
validate: larkConfigIssues,
|
|
137403
|
+
isConfigured: (binding) => larkConfigIssues(binding).length === 0,
|
|
137273
137404
|
connect: (binding, handlers) => {
|
|
137274
137405
|
const { appId, appSecret } = credentials(binding);
|
|
137275
137406
|
const port = {
|
|
@@ -137277,6 +137408,11 @@ var makeLarkAdapter = (deps) => {
|
|
|
137277
137408
|
knowsChatAlias: handlers.knowsChatAlias
|
|
137278
137409
|
};
|
|
137279
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
|
+
}
|
|
137280
137416
|
let open = true;
|
|
137281
137417
|
const inbound = startLarkInbound({
|
|
137282
137418
|
appId,
|
|
@@ -137330,7 +137466,10 @@ var makeLarkAdapter = (deps) => {
|
|
|
137330
137466
|
return {
|
|
137331
137467
|
close: () => {
|
|
137332
137468
|
open = false;
|
|
137333
|
-
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
|
+
}
|
|
137334
137473
|
inbound.close();
|
|
137335
137474
|
}
|
|
137336
137475
|
};
|
|
@@ -137504,7 +137643,7 @@ var makeLarkAdapter = (deps) => {
|
|
|
137504
137643
|
var en_default = {
|
|
137505
137644
|
settings: {
|
|
137506
137645
|
title: "Chat",
|
|
137507
|
-
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.",
|
|
137508
137647
|
bots: "Bots",
|
|
137509
137648
|
language: {
|
|
137510
137649
|
label: "Reply language",
|
|
@@ -137611,8 +137750,8 @@ var en_default = {
|
|
|
137611
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."
|
|
137612
137751
|
},
|
|
137613
137752
|
deliveryBotId: {
|
|
137614
|
-
label: "Bot
|
|
137615
|
-
description: "The
|
|
137753
|
+
label: "Bot",
|
|
137754
|
+
description: "The bot that sends the message. Callers pass the id in brackets as botId.",
|
|
137616
137755
|
placeholder: "bot row id"
|
|
137617
137756
|
},
|
|
137618
137757
|
deliveryTargetId: {
|
|
@@ -137947,7 +138086,7 @@ var en_default = {
|
|
|
137947
138086
|
setup: {
|
|
137948
138087
|
action: {
|
|
137949
138088
|
label: "Connect a Lark bot",
|
|
137950
|
-
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.",
|
|
137951
138090
|
badge: "Beta",
|
|
137952
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."
|
|
137953
138092
|
},
|
|
@@ -137974,7 +138113,7 @@ var en_default = {
|
|
|
137974
138113
|
},
|
|
137975
138114
|
fillRow: {
|
|
137976
138115
|
title: "Add the bot",
|
|
137977
|
-
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."
|
|
137978
138117
|
}
|
|
137979
138118
|
},
|
|
137980
138119
|
status: {
|
|
@@ -138108,6 +138247,66 @@ var en_default = {
|
|
|
138108
138247
|
thread: "Go back to a normal session",
|
|
138109
138248
|
panel: "Open the command panel",
|
|
138110
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
|
+
}
|
|
138111
138310
|
}
|
|
138112
138311
|
};
|
|
138113
138312
|
|
|
@@ -138115,7 +138314,7 @@ var en_default = {
|
|
|
138115
138314
|
var zh_CN_default = {
|
|
138116
138315
|
settings: {
|
|
138117
138316
|
title: "\u804A\u5929",
|
|
138118
|
-
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",
|
|
138119
138318
|
bots: "\u673A\u5668\u4EBA",
|
|
138120
138319
|
language: {
|
|
138121
138320
|
label: "\u56DE\u8BDD\u8BED\u8A00",
|
|
@@ -138222,8 +138421,8 @@ var zh_CN_default = {
|
|
|
138222
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"
|
|
138223
138422
|
},
|
|
138224
138423
|
deliveryBotId: {
|
|
138225
|
-
label: "
|
|
138226
|
-
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",
|
|
138227
138426
|
placeholder: "\u673A\u5668\u4EBA\u884C id"
|
|
138228
138427
|
},
|
|
138229
138428
|
deliveryTargetId: {
|
|
@@ -138558,7 +138757,7 @@ var zh_CN_default = {
|
|
|
138558
138757
|
setup: {
|
|
138559
138758
|
action: {
|
|
138560
138759
|
label: "\u8FDE\u63A5\u98DE\u4E66\u673A\u5668\u4EBA",
|
|
138561
|
-
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",
|
|
138562
138761
|
badge: "\u6D4B\u8BD5\u7248",
|
|
138563
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"
|
|
138564
138763
|
},
|
|
@@ -138585,7 +138784,7 @@ var zh_CN_default = {
|
|
|
138585
138784
|
},
|
|
138586
138785
|
fillRow: {
|
|
138587
138786
|
title: "\u6DFB\u52A0\u673A\u5668\u4EBA",
|
|
138588
|
-
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"
|
|
138589
138788
|
}
|
|
138590
138789
|
},
|
|
138591
138790
|
status: {
|
|
@@ -138719,6 +138918,66 @@ var zh_CN_default = {
|
|
|
138719
138918
|
thread: "\u5207\u56DE\u666E\u901A\u4F1A\u8BDD",
|
|
138720
138919
|
panel: "\u6253\u5F00\u547D\u4EE4\u9762\u677F",
|
|
138721
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
|
+
}
|
|
138722
138981
|
}
|
|
138723
138982
|
};
|
|
138724
138983
|
|
|
@@ -139064,56 +139323,6 @@ var MINIMAL_HIDDEN = /* @__PURE__ */ new Set([
|
|
|
139064
139323
|
]);
|
|
139065
139324
|
var panelCommandsFor = (mode = "default") => mode === "minimal" ? PANEL_COMMANDS.filter((spec) => !MINIMAL_HIDDEN.has(spec.id)) : PANEL_COMMANDS;
|
|
139066
139325
|
|
|
139067
|
-
// src/sessionList.ts
|
|
139068
|
-
var SESSION_LIST_MAX = 20;
|
|
139069
|
-
var SESSION_ID_SHORT_LENGTH = 8;
|
|
139070
|
-
var ageLabel = (updatedAt, now, t) => {
|
|
139071
|
-
const at = Date.parse(updatedAt);
|
|
139072
|
-
if (Number.isNaN(at)) return "";
|
|
139073
|
-
const minutes = Math.floor(Math.max(0, now - at) / 6e4);
|
|
139074
|
-
if (minutes < 1) return t("sessions.age.justNow");
|
|
139075
|
-
if (minutes < 60) return t("sessions.age.minutes", { count: minutes });
|
|
139076
|
-
const hours = Math.floor(minutes / 60);
|
|
139077
|
-
if (hours < 24) return t("sessions.age.hours", { count: hours });
|
|
139078
|
-
return t("sessions.age.days", { count: Math.floor(hours / 24) });
|
|
139079
|
-
};
|
|
139080
|
-
var shortId = (threadId) => threadId.slice(0, SESSION_ID_SHORT_LENGTH);
|
|
139081
|
-
var sessionLine = (row, position, now, t) => {
|
|
139082
|
-
const title = row.title.replace(/\s+/g, " ").trim() || t("sessions.untitled");
|
|
139083
|
-
const age = ageLabel(row.updatedAt, now, t);
|
|
139084
|
-
const badges = [
|
|
139085
|
-
row.current ? t("sessions.badge.current") : null,
|
|
139086
|
-
row.running ? t("sessions.badge.running") : null,
|
|
139087
|
-
row.elsewhere ? t("sessions.badge.elsewhere") : null,
|
|
139088
|
-
row.origin === "web" ? t("sessions.badge.web") : null
|
|
139089
|
-
].filter((badge) => badge !== null);
|
|
139090
|
-
return [`${String(position)}. ${title}`, age, ...badges, shortId(row.threadId)].filter((part) => part !== "").join(" \xB7 ");
|
|
139091
|
-
};
|
|
139092
|
-
var formatSessions = (rows, now, t) => {
|
|
139093
|
-
if (rows.length === 0) return t("sessions.empty");
|
|
139094
|
-
const shown = rows.slice(0, SESSION_LIST_MAX);
|
|
139095
|
-
return [
|
|
139096
|
-
t("sessions.title", { count: rows.length }),
|
|
139097
|
-
...shown.map((row, index) => sessionLine(row, index + 1, now, t)),
|
|
139098
|
-
...rows.length > shown.length ? [t("sessions.more", { count: rows.length - shown.length })] : [],
|
|
139099
|
-
"",
|
|
139100
|
-
t("sessions.footer")
|
|
139101
|
-
].join("\n");
|
|
139102
|
-
};
|
|
139103
|
-
var listedThreadIds = (rows) => rows.slice(0, SESSION_LIST_MAX).map((row) => row.threadId);
|
|
139104
|
-
var looksLikeListNumber = (wanted) => /^[1-9]\d*$/u.test(wanted) && wanted.length <= String(SESSION_LIST_MAX).length;
|
|
139105
|
-
var pickSession = (arg, listed, rows) => {
|
|
139106
|
-
const wanted = arg.trim();
|
|
139107
|
-
if (wanted === "") return null;
|
|
139108
|
-
if (looksLikeListNumber(wanted)) {
|
|
139109
|
-
const ids = listed ?? listedThreadIds(rows);
|
|
139110
|
-
return ids[Number(wanted) - 1] ?? null;
|
|
139111
|
-
}
|
|
139112
|
-
const needle = wanted.toLowerCase();
|
|
139113
|
-
const matches = rows.filter((row) => row.threadId.toLowerCase().startsWith(needle));
|
|
139114
|
-
return matches.length === 1 ? matches[0]?.threadId ?? null : null;
|
|
139115
|
-
};
|
|
139116
|
-
|
|
139117
139326
|
// src/panelController.ts
|
|
139118
139327
|
var PANEL_PAGE_SIZE = 8;
|
|
139119
139328
|
var PANEL_CARD_LIMIT = 200;
|
|
@@ -140185,8 +140394,14 @@ var makeSendFileTool = (deps) => ({
|
|
|
140185
140394
|
});
|
|
140186
140395
|
|
|
140187
140396
|
// src/sessions.ts
|
|
140188
|
-
var SESSION_SCAN_LIMIT = 50;
|
|
140189
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
|
+
});
|
|
140190
140405
|
var makeSessions = (core) => {
|
|
140191
140406
|
const { host, t, commit, bindChat, deliver } = core;
|
|
140192
140407
|
const listedByChat = /* @__PURE__ */ new Map();
|
|
@@ -140197,7 +140412,7 @@ var makeSessions = (core) => {
|
|
|
140197
140412
|
threadId: thread.threadId,
|
|
140198
140413
|
title: thread.title,
|
|
140199
140414
|
updatedAt: thread.updatedAt,
|
|
140200
|
-
running: thread.
|
|
140415
|
+
running: isSessionRunning(thread.sessionStatus),
|
|
140201
140416
|
current: chatOf(core.state, chatKey).threadId === thread.threadId,
|
|
140202
140417
|
elsewhere: Object.entries(core.state.chats).some(
|
|
140203
140418
|
([otherKey, record2]) => otherKey !== chatKey && record2.threadId === thread.threadId
|
|
@@ -140205,73 +140420,43 @@ var makeSessions = (core) => {
|
|
|
140205
140420
|
origin
|
|
140206
140421
|
};
|
|
140207
140422
|
};
|
|
140208
|
-
const
|
|
140423
|
+
const projectShells = async (projectId) => {
|
|
140209
140424
|
if (projectId === "") return [];
|
|
140210
140425
|
const shells = [];
|
|
140211
140426
|
let cursor = null;
|
|
140212
|
-
|
|
140427
|
+
do {
|
|
140213
140428
|
const result = await host.threads.list({
|
|
140429
|
+
projectId,
|
|
140214
140430
|
limit: WEB_LIST_PAGE,
|
|
140215
140431
|
archived: "exclude",
|
|
140216
140432
|
cursor
|
|
140217
140433
|
});
|
|
140218
140434
|
for (const shell of result.items) {
|
|
140219
|
-
if (shell.projectId !== projectId) continue;
|
|
140220
|
-
if (shell.archivedAt != null) continue;
|
|
140221
140435
|
shells.push({
|
|
140222
140436
|
threadId: shell.threadId,
|
|
140223
140437
|
title: shell.title,
|
|
140224
140438
|
updatedAt: shell.updatedAt,
|
|
140225
140439
|
archivedAt: shell.archivedAt,
|
|
140226
|
-
|
|
140227
|
-
activeTurnId: shell.sessionStatus === "running" ? "running" : null
|
|
140228
|
-
}
|
|
140440
|
+
sessionStatus: shell.sessionStatus
|
|
140229
140441
|
});
|
|
140230
140442
|
}
|
|
140231
|
-
if (result.nextCursor === null) break;
|
|
140232
140443
|
cursor = result.nextCursor;
|
|
140233
|
-
}
|
|
140444
|
+
} while (cursor !== null);
|
|
140234
140445
|
return shells;
|
|
140235
140446
|
};
|
|
140447
|
+
const originOf = (threadId, projectId) => core.state.opened[threadId]?.projectId === projectId ? "plugin" : "web";
|
|
140236
140448
|
const sessionRowsFor = async (binding) => {
|
|
140237
140449
|
const chatKey = chatKeyOf(binding);
|
|
140238
|
-
|
|
140239
|
-
|
|
140240
|
-
|
|
140241
|
-
|
|
140242
|
-
|
|
140243
|
-
|
|
140244
|
-
|
|
140245
|
-
);
|
|
140246
|
-
|
|
140247
|
-
|
|
140248
|
-
for (const thread of ownedThreads) {
|
|
140249
|
-
if (thread === null) continue;
|
|
140250
|
-
const row = rowFromThread(thread, chatKey, "plugin");
|
|
140251
|
-
if (row === null) continue;
|
|
140252
|
-
rows.push(row);
|
|
140253
|
-
seen.add(row.threadId);
|
|
140254
|
-
}
|
|
140255
|
-
const shells = await webShellsForProject(binding.projectId);
|
|
140256
|
-
const listed = new Set(shells.map((shell) => shell.threadId));
|
|
140257
|
-
const attached = await Promise.all(
|
|
140258
|
-
attachedOnChat(core.state, chatKey, binding.projectId).filter(({ threadId }) => !listed.has(threadId)).map(({ threadId }) => host.projections.getThread(threadId))
|
|
140259
|
-
);
|
|
140260
|
-
for (const thread of attached) {
|
|
140261
|
-
if (thread === null || seen.has(thread.threadId) || openedIds.has(thread.threadId)) continue;
|
|
140262
|
-
const row = rowFromThread(thread, chatKey, "web");
|
|
140263
|
-
if (row === null) continue;
|
|
140264
|
-
rows.push(row);
|
|
140265
|
-
seen.add(row.threadId);
|
|
140266
|
-
}
|
|
140267
|
-
for (const shell of shells) {
|
|
140268
|
-
if (seen.has(shell.threadId) || openedIds.has(shell.threadId)) continue;
|
|
140269
|
-
const row = rowFromThread(shell, chatKey, "web");
|
|
140270
|
-
if (row === null) continue;
|
|
140271
|
-
rows.push(row);
|
|
140272
|
-
seen.add(row.threadId);
|
|
140273
|
-
}
|
|
140274
|
-
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));
|
|
140275
140460
|
};
|
|
140276
140461
|
const showSessions = async (binding) => {
|
|
140277
140462
|
const rows = await sessionRowsFor(binding);
|
|
@@ -140317,24 +140502,27 @@ var makeSessions = (core) => {
|
|
|
140317
140502
|
await deliver(binding, t("resume.nothingPending"));
|
|
140318
140503
|
return;
|
|
140319
140504
|
}
|
|
140320
|
-
const
|
|
140321
|
-
let targetId;
|
|
140322
|
-
if (
|
|
140323
|
-
targetId =
|
|
140324
|
-
} else {
|
|
140325
|
-
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));
|
|
140326
140509
|
if (targetId === null) {
|
|
140327
140510
|
await deliver(binding, t("resume.notFound", { query: arg }));
|
|
140328
140511
|
return;
|
|
140329
140512
|
}
|
|
140330
140513
|
}
|
|
140331
|
-
const
|
|
140332
|
-
|
|
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) {
|
|
140333
140521
|
if (confirming) pendingAttachByChat.delete(chatKey);
|
|
140334
140522
|
await deliver(binding, t("resume.gone"));
|
|
140335
140523
|
return;
|
|
140336
140524
|
}
|
|
140337
|
-
if (
|
|
140525
|
+
if (currentBusy) {
|
|
140338
140526
|
await deliver(binding, t("resume.busy"));
|
|
140339
140527
|
return;
|
|
140340
140528
|
}
|
|
@@ -140876,6 +141064,7 @@ var tokenOf = (binding) => (binding.values["telegramToken"] ?? "").trim();
|
|
|
140876
141064
|
var REACTION_WORKING = "\u{1F440}";
|
|
140877
141065
|
var REACTION_DONE = "\u{1F44D}";
|
|
140878
141066
|
var REACTION_FAILED = "\u{1F44E}";
|
|
141067
|
+
var telegramConfigIssues = (binding) => tokenOf(binding) === "" ? [{ column: "telegramToken", code: "required" }] : [];
|
|
140879
141068
|
var defaultSleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
140880
141069
|
var webhookHost = (url) => {
|
|
140881
141070
|
try {
|
|
@@ -140977,7 +141166,8 @@ var makeTelegramAdapter = (deps) => {
|
|
|
140977
141166
|
icon: "telegram",
|
|
140978
141167
|
label: "Telegram",
|
|
140979
141168
|
columns: COLUMNS2,
|
|
140980
|
-
|
|
141169
|
+
validate: telegramConfigIssues,
|
|
141170
|
+
isConfigured: (binding) => telegramConfigIssues(binding).length === 0,
|
|
140981
141171
|
connect: async (binding, handlers) => {
|
|
140982
141172
|
let stop = () => {
|
|
140983
141173
|
};
|
|
@@ -141494,10 +141684,9 @@ var makeWebSync = (core) => {
|
|
|
141494
141684
|
// src/settingsRowActions.ts
|
|
141495
141685
|
var ROW_PAYLOAD_SCHEMA = {
|
|
141496
141686
|
type: "object",
|
|
141497
|
-
required: ["rowId"
|
|
141687
|
+
required: ["rowId"],
|
|
141498
141688
|
properties: {
|
|
141499
|
-
rowId: { type: "string" }
|
|
141500
|
-
values: { type: "object" }
|
|
141689
|
+
rowId: { type: "string" }
|
|
141501
141690
|
},
|
|
141502
141691
|
additionalProperties: false
|
|
141503
141692
|
};
|
|
@@ -141585,19 +141774,19 @@ var registerSettingsRowActions = (ctx, adapters) => {
|
|
|
141585
141774
|
});
|
|
141586
141775
|
};
|
|
141587
141776
|
registerProbeAction({
|
|
141588
|
-
name:
|
|
141777
|
+
name: BOT_ACTION_COMMANDS.checkConnection,
|
|
141589
141778
|
summary: "Probe an IM bot's platform credentials without calling a model.",
|
|
141590
141779
|
keyPrefix: "rowAction.checkConnection",
|
|
141591
141780
|
copyable: false
|
|
141592
141781
|
});
|
|
141593
141782
|
registerProbeAction({
|
|
141594
|
-
name:
|
|
141783
|
+
name: BOT_ACTION_COMMANDS.copyDiagnostics,
|
|
141595
141784
|
summary: "Probe an IM bot and return a copy-paste diagnostic report.",
|
|
141596
141785
|
keyPrefix: "rowAction.copyDiagnostics",
|
|
141597
141786
|
copyable: true
|
|
141598
141787
|
});
|
|
141599
141788
|
ctx.stream({
|
|
141600
|
-
name:
|
|
141789
|
+
name: BOT_ACTION_COMMANDS.larkRepair,
|
|
141601
141790
|
description: "Guide Lark scope repair and verify the saved app can still mint a token.",
|
|
141602
141791
|
scope: "operate",
|
|
141603
141792
|
payloadSchema: ROW_PAYLOAD_SCHEMA,
|
|
@@ -141663,6 +141852,289 @@ var registerSettingsRowActions = (ctx, adapters) => {
|
|
|
141663
141852
|
});
|
|
141664
141853
|
};
|
|
141665
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
|
+
|
|
141666
142138
|
// src/wechatApi.ts
|
|
141667
142139
|
var WECHAT_TEXT_MAX_CHARS = 1800;
|
|
141668
142140
|
|
|
@@ -141676,6 +142148,7 @@ var COLUMNS3 = [
|
|
|
141676
142148
|
}
|
|
141677
142149
|
];
|
|
141678
142150
|
var tokenOf2 = (bot) => bot.values["wechatBotToken"] ?? "";
|
|
142151
|
+
var wechatConfigIssues = (bot) => tokenOf2(bot) === "" ? [{ column: "wechatBotToken", code: "required" }] : [];
|
|
141679
142152
|
var makeWechatAdapter = (deps) => {
|
|
141680
142153
|
return {
|
|
141681
142154
|
platform: "wechat",
|
|
@@ -141683,7 +142156,8 @@ var makeWechatAdapter = (deps) => {
|
|
|
141683
142156
|
// 平台名与设置表的平台选项同一个键,免得默认机器人名与选项写成两种叫法。
|
|
141684
142157
|
label: deps.translate("platform.wechat"),
|
|
141685
142158
|
columns: COLUMNS3,
|
|
141686
|
-
|
|
142159
|
+
validate: wechatConfigIssues,
|
|
142160
|
+
isConfigured: (bot) => wechatConfigIssues(bot).length === 0,
|
|
141687
142161
|
connect: (bot, _handlers) => {
|
|
141688
142162
|
deps.log.warn("wechat iLink connect is stubbed pending security-review gate (YCO-236)", {
|
|
141689
142163
|
bot: bot.displayName,
|
|
@@ -142217,6 +142691,13 @@ var credentials2 = (binding) => ({
|
|
|
142217
142691
|
botSecret: binding.values["wecomBotSecret"] ?? "",
|
|
142218
142692
|
endpoint: normalizeWecomEndpoint(binding.values["wecomEndpoint"] || DEFAULT_WECOM_ENDPOINT)
|
|
142219
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
|
+
};
|
|
142220
142701
|
var makeWecomAdapter = (deps) => {
|
|
142221
142702
|
const clients = /* @__PURE__ */ new Map();
|
|
142222
142703
|
const t = deps.translate;
|
|
@@ -142261,10 +142742,8 @@ ${kept}`;
|
|
|
142261
142742
|
label: "WeCom",
|
|
142262
142743
|
columns: COLUMNS4,
|
|
142263
142744
|
unlistedValues: ["wecomEndpoint"],
|
|
142264
|
-
|
|
142265
|
-
|
|
142266
|
-
return botId !== "" && botSecret !== "";
|
|
142267
|
-
},
|
|
142745
|
+
validate: wecomConfigIssues,
|
|
142746
|
+
isConfigured: (binding) => wecomConfigIssues(binding).length === 0,
|
|
142268
142747
|
connect: (binding, handlers) => {
|
|
142269
142748
|
const { botId, botSecret, endpoint } = credentials2(binding);
|
|
142270
142749
|
let stopped = false;
|
|
@@ -142756,7 +143235,7 @@ var createWecomAppCrypto = (input) => {
|
|
|
142756
143235
|
var deriveCallbackPathSecret = (token, encodingAESKey) => NodeCrypto4.createHash("sha256").update(`${token.trim()}:${encodingAESKey.trim()}`).digest("hex").slice(0, 24);
|
|
142757
143236
|
|
|
142758
143237
|
// src/wecomAppParse.ts
|
|
142759
|
-
var
|
|
143238
|
+
var isRecord3 = (value2) => value2 !== null && typeof value2 === "object" && !Array.isArray(value2);
|
|
142760
143239
|
var isXmlFormat = (raw) => {
|
|
142761
143240
|
const trimmed = raw.trim();
|
|
142762
143241
|
return trimmed.startsWith("<") && trimmed.endsWith(">");
|
|
@@ -142802,7 +143281,7 @@ var parseWecomAppPlainMessage = (raw) => {
|
|
|
142802
143281
|
} catch {
|
|
142803
143282
|
return null;
|
|
142804
143283
|
}
|
|
142805
|
-
if (!
|
|
143284
|
+
if (!isRecord3(data)) return null;
|
|
142806
143285
|
const fromRaw = data["from"];
|
|
142807
143286
|
const textRaw = data["text"];
|
|
142808
143287
|
const imageRaw = data["image"];
|
|
@@ -142811,10 +143290,10 @@ var parseWecomAppPlainMessage = (raw) => {
|
|
|
142811
143290
|
msgtype: String(data["msgtype"] ?? data["MsgType"] ?? "").toLowerCase(),
|
|
142812
143291
|
createTime: data["createTime"] !== void 0 ? String(data["createTime"]) : data["CreateTime"] !== void 0 ? String(data["CreateTime"]) : void 0,
|
|
142813
143292
|
agentId: data["agentid"] !== void 0 ? String(data["agentid"]) : data["AgentID"] !== void 0 ? String(data["AgentID"]) : void 0,
|
|
142814
|
-
from:
|
|
143293
|
+
from: isRecord3(fromRaw) ? { userid: typeof fromRaw["userid"] === "string" ? fromRaw["userid"] : void 0 } : typeof data["FromUserName"] === "string" ? { userid: data["FromUserName"] } : void 0,
|
|
142815
143294
|
to: typeof data["to"] === "string" ? data["to"] : void 0,
|
|
142816
|
-
text:
|
|
142817
|
-
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,
|
|
142818
143297
|
mediaId: typeof data["mediaid"] === "string" ? data["mediaid"] : void 0,
|
|
142819
143298
|
recognition: typeof data["recognition"] === "string" ? data["recognition"] : void 0,
|
|
142820
143299
|
event: String(data["event"] ?? data["eventtype"] ?? "").toLowerCase() || void 0,
|
|
@@ -143184,6 +143663,21 @@ var WECOM_APP_IMAGE_BYTES = 10 * 1024 * 1024;
|
|
|
143184
143663
|
var WECOM_APP_FILE_BYTES = 20 * 1024 * 1024;
|
|
143185
143664
|
var WECOM_APP_MIN_BYTES = 5;
|
|
143186
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
|
+
};
|
|
143187
143681
|
var OUTBOUND_COLUMNS = /* @__PURE__ */ new Set([
|
|
143188
143682
|
"wecomAppCorpId",
|
|
143189
143683
|
"wecomAppAgentId",
|
|
@@ -143253,11 +143747,14 @@ var makeWecomAppAdapter = (deps) => {
|
|
|
143253
143747
|
icon: "wecom",
|
|
143254
143748
|
label: deps.translate("platform.wecom-app"),
|
|
143255
143749
|
columns: COLUMNS5,
|
|
143256
|
-
//
|
|
143257
|
-
// connect
|
|
143750
|
+
// 设置页标格子用完整的逐列结果。算不算配齐仍是原来那份,不能收成「一个问题都没有」:
|
|
143751
|
+
// 必填都填了、EncodingAESKey 格式对。别的列格式不对的行照样交给 connect 报出来(一条日志,
|
|
143752
|
+
// 不重试),也不挡设置页的「检查连接」去探出站凭据。
|
|
143753
|
+
validate: validateWecomAppBot,
|
|
143258
143754
|
isConfigured: (bot) => validateWecomAppBot(bot).every(
|
|
143259
143755
|
(issue) => issue.code !== "required" && issue.column !== "wecomAppEncodingAESKey"
|
|
143260
143756
|
),
|
|
143757
|
+
publicFields: wecomAppPublicFields,
|
|
143261
143758
|
/**
|
|
143262
143759
|
* 自建应用是回调式渠道:入站由企微推到我们的 listener,没有可探的长连接;能探的是出站
|
|
143263
143760
|
* 凭据——和真实发送同一条路,向 gettoken 换一次 access_token。
|
|
@@ -143321,7 +143818,10 @@ var makeWecomAppAdapter = (deps) => {
|
|
|
143321
143818
|
deps.log.info("wecom-app connected", {
|
|
143322
143819
|
bot: bot.displayName,
|
|
143323
143820
|
callbackPath: path,
|
|
143324
|
-
callbackUrl:
|
|
143821
|
+
callbackUrl: joinCallbackUrl(
|
|
143822
|
+
c.callbackBaseUrl !== "" ? c.callbackBaseUrl : server.origin,
|
|
143823
|
+
path
|
|
143824
|
+
),
|
|
143325
143825
|
listen: `${server.host}:${String(server.port)}`
|
|
143326
143826
|
});
|
|
143327
143827
|
return {
|
|
@@ -143422,9 +143922,11 @@ var imPlugin = definePlugin({
|
|
|
143422
143922
|
}
|
|
143423
143923
|
})
|
|
143424
143924
|
];
|
|
143425
|
-
ctx.settingsCard(
|
|
143426
|
-
|
|
143925
|
+
ctx.settingsCard(buildSettingsCard(adapters));
|
|
143926
|
+
const updateSettings = makeSettingsUpdater(ctx.settings);
|
|
143927
|
+
registerLarkSetup(ctx, { updateSettings });
|
|
143427
143928
|
registerSettingsRowActions(ctx, adapters);
|
|
143929
|
+
registerSettingsCommands(ctx, adapters, updateSettings);
|
|
143428
143930
|
const core = makeImCore({
|
|
143429
143931
|
host: {
|
|
143430
143932
|
log: ctx.log,
|