@xmanrui/dsh-im 3.1.1 → 4.0.0
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.en.md +16 -1
- package/README.md +16 -1
- package/lib/client.js +1653 -333
- package/lib/index.js +235 -226
- package/package.json +5 -1
- package/plugin-src/client/channels/dingtalk/api.js +3 -0
- package/plugin-src/client/channels/dingtalk/index.js +18 -5
- package/plugin-src/client/channels/feishu/api.js +3 -0
- package/plugin-src/client/channels/feishu/index.js +18 -5
- package/plugin-src/client/channels/qq/api.js +3 -0
- package/plugin-src/client/channels/qq/index.js +13 -0
- package/plugin-src/client/channels/shared/token-api.js +3 -0
- package/plugin-src/client/channels/shared/token-channel.js +13 -1
- package/plugin-src/client/channels/wecom/api.js +3 -0
- package/plugin-src/client/channels/wecom/index.js +13 -0
- package/plugin-src/client/channels/weixin/api.js +3 -0
- package/plugin-src/client/channels/weixin/index.js +19 -5
- package/plugin-src/client/channels/whatsapp/api.js +3 -0
- package/plugin-src/client/channels/whatsapp/index.js +13 -0
- package/plugin-src/client/context-enhancement.js +275 -0
- package/plugin-src/client/i18n.js +54 -3
- package/plugin-src/client/styles.js +78 -0
- package/plugin-src/client/update-panel.js +108 -7
- package/plugin-src/host/channels/dingtalk/index.mjs +1 -1
- package/plugin-src/host/channels/dingtalk/production.mjs +1 -0
- package/plugin-src/host/channels/dingtalk/rpc.mjs +11 -0
- package/plugin-src/host/channels/discord/index.mjs +1 -1
- package/plugin-src/host/channels/feishu/index.mjs +1 -1
- package/plugin-src/host/channels/feishu/production.mjs +3 -0
- package/plugin-src/host/channels/feishu/rpc.mjs +13 -0
- package/plugin-src/host/channels/qq/index.mjs +1 -1
- package/plugin-src/host/channels/qq/production.mjs +1 -0
- package/plugin-src/host/channels/qq/rpc.mjs +11 -0
- package/plugin-src/host/channels/shared/context-enhancement-rpc.mjs +17 -0
- package/plugin-src/host/channels/shared/production.mjs +1 -0
- package/plugin-src/host/channels/shared/rpc.mjs +9 -0
- package/plugin-src/host/channels/shared/workspace-rpc.mjs +1 -0
- package/plugin-src/host/channels/slack/index.mjs +1 -1
- package/plugin-src/host/channels/slack/production.mjs +1 -0
- package/plugin-src/host/channels/slack/rpc.mjs +10 -0
- package/plugin-src/host/channels/telegram/index.mjs +1 -1
- package/plugin-src/host/channels/wecom/index.mjs +1 -1
- package/plugin-src/host/channels/wecom/production.mjs +1 -0
- package/plugin-src/host/channels/wecom/rpc.mjs +11 -0
- package/plugin-src/host/channels/weixin/index.mjs +1 -1
- package/plugin-src/host/channels/weixin/production.mjs +1 -0
- package/plugin-src/host/channels/weixin/rpc.mjs +11 -0
- package/plugin-src/host/channels/whatsapp/index.mjs +1 -1
- package/plugin-src/host/channels/whatsapp/production.mjs +1 -0
- package/plugin-src/host/channels/whatsapp/rpc.mjs +11 -0
- package/plugin-src/host/harness-connection.mjs +9 -4
- package/plugin-src/host/index.mjs +43 -29
- package/plugin-src/host/modern-harness-api.mjs +577 -0
- package/plugin-src/host/update-runtime.mjs +3 -2
- package/plugin-src/host/update-service.mjs +2 -0
- package/scripts/verify-package.mjs +15 -2
- package/src/channels/dingtalk/dingtalk-api.mjs +39 -16
- package/src/channels/dingtalk/dingtalk-bridge.mjs +52 -23
- package/src/channels/dingtalk/dingtalk-runtime.mjs +20 -1
- package/src/channels/discord/discord-runtime.mjs +18 -4
- package/src/channels/feishu/bridge.mjs +18 -3
- package/src/channels/feishu/feishu-runtime.mjs +4 -0
- package/src/channels/qq/qq-bridge.mjs +20 -4
- package/src/channels/qq/qq-runtime.mjs +4 -0
- package/src/channels/shared/bot-workspace-store.mjs +103 -6
- package/src/channels/shared/context-enhancement.mjs +135 -0
- package/src/channels/shared/harness-client.mjs +18 -0
- package/src/channels/shared/text-harness-bridge.mjs +19 -4
- package/src/channels/slack/slack-runtime.mjs +4 -0
- package/src/channels/telegram/telegram-runtime.mjs +24 -2
- package/src/channels/wecom/wecom-bridge.mjs +18 -3
- package/src/channels/wecom/wecom-runtime.mjs +4 -0
- package/src/channels/weixin/weixin-bridge.mjs +19 -4
- package/src/channels/weixin/weixin-runtime.mjs +4 -0
- package/src/channels/whatsapp/whatsapp-runtime.mjs +5 -0
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import QRCode from 'qrcode';
|
|
2
|
+
import { SET_CONTEXT_ENHANCEMENT_ENDPOINT, validContextEnhancementPayload } from '../shared/context-enhancement-rpc.mjs';
|
|
2
3
|
import { resolveRpcAuthority } from '../../rpc-authority.mjs';
|
|
3
4
|
import { publicWorkspaceError, SET_WORKSPACE_ENDPOINT, validWorkspacePayload } from '../shared/workspace-rpc.mjs';
|
|
4
5
|
import { SET_AGENT_PRESET_ENDPOINT, validAgentPresetPayload } from '../shared/agent-preset-rpc.mjs';
|
|
@@ -18,6 +19,7 @@ export const DINGTALK_ENDPOINTS = Object.freeze({
|
|
|
18
19
|
deleteBot: 'bot.delete',
|
|
19
20
|
setWorkspace: SET_WORKSPACE_ENDPOINT,
|
|
20
21
|
setAgentPreset: SET_AGENT_PRESET_ENDPOINT,
|
|
22
|
+
setContextEnhancement: SET_CONTEXT_ENHANCEMENT_ENDPOINT,
|
|
21
23
|
approveSender: 'bot.sender.approve',
|
|
22
24
|
revokeSender: 'bot.sender.revoke',
|
|
23
25
|
});
|
|
@@ -94,6 +96,10 @@ function payloadFailure(endpoint, payload) {
|
|
|
94
96
|
return validAgentPresetPayload(payload)
|
|
95
97
|
? null : '请选择 Agent Preset。';
|
|
96
98
|
}
|
|
99
|
+
if (endpoint === DINGTALK_ENDPOINTS.setContextEnhancement) {
|
|
100
|
+
return validContextEnhancementPayload(payload)
|
|
101
|
+
? null : '请提交有效的上下文增强设置。';
|
|
102
|
+
}
|
|
97
103
|
if (endpoint === DINGTALK_ENDPOINTS.approveSender) {
|
|
98
104
|
return exactKeys(payload, ['botId', 'requestId', 'confirm'])
|
|
99
105
|
&& validId(payload.botId)
|
|
@@ -251,6 +257,11 @@ export function createDingtalkRpcHandler(controller, { encodeQr = qrDataUrl } =
|
|
|
251
257
|
await controller.updateWorkspace(payload.botId, payload.workspace),
|
|
252
258
|
cachedEncode,
|
|
253
259
|
);
|
|
260
|
+
} else if (endpoint === DINGTALK_ENDPOINTS.setContextEnhancement) {
|
|
261
|
+
if (typeof controller.updateContextEnhancement !== 'function') throw new Error('Context enhancement update is unavailable');
|
|
262
|
+
value = await controller.updateContextEnhancement(
|
|
263
|
+
payload.botId, payload.config, (status) => publicStatus(status, cachedEncode),
|
|
264
|
+
);
|
|
254
265
|
} else if (endpoint === DINGTALK_ENDPOINTS.setAgentPreset) {
|
|
255
266
|
if (typeof controller.updateAgentPreset !== 'function') throw new Error('Agent preset update is unavailable');
|
|
256
267
|
value = await publicStatus(
|
|
@@ -2,7 +2,7 @@ import { createProductionController } from './production.mjs';
|
|
|
2
2
|
import { installDiscordRpc } from './rpc.mjs';
|
|
3
3
|
|
|
4
4
|
export const name = 'dsh-im-discord-host';
|
|
5
|
-
export const inject = ['connection', 'credentials', '
|
|
5
|
+
export const inject = ['connection', 'credentials', 'typertGateway'];
|
|
6
6
|
|
|
7
7
|
export async function apply(ctx, config = {}) {
|
|
8
8
|
if (config?.controller) {
|
|
@@ -3,7 +3,7 @@ import { createProductionController } from './production.mjs';
|
|
|
3
3
|
import { installFeishuRpc } from './rpc.mjs';
|
|
4
4
|
|
|
5
5
|
export const name = 'dsh-feishu-host';
|
|
6
|
-
export const inject = ['connection', 'credentials', '
|
|
6
|
+
export const inject = ['connection', 'credentials', 'typertGateway'];
|
|
7
7
|
|
|
8
8
|
function controllerFrom(ctx, config) {
|
|
9
9
|
if (config?.controller) return config.controller;
|
|
@@ -98,6 +98,8 @@ export async function createProductionController(ctx, config = {}, internals = {
|
|
|
98
98
|
workspaces,
|
|
99
99
|
method: 'removeBot',
|
|
100
100
|
botIdFromRemoved: (removed) => removed.id,
|
|
101
|
+
saveMethod: 'saveBot',
|
|
102
|
+
botIdFromSave: (bot) => bot?.id,
|
|
101
103
|
})
|
|
102
104
|
: configStore;
|
|
103
105
|
// State is lazy per bot. A corrupt legacy file can therefore fail only the
|
|
@@ -167,6 +169,7 @@ export async function createProductionController(ctx, config = {}, internals = {
|
|
|
167
169
|
ownerOpenIds: botConfig.ownerOpenIds ?? [botConfig.ownerOpenId],
|
|
168
170
|
harness: workspaceScope.harness,
|
|
169
171
|
state: workspaceScope.state,
|
|
172
|
+
contextEnhancement: { botId: id, getSettings: () => workspaces.contextEnhancementFor(id) },
|
|
170
173
|
replyTimeoutMs: config.replyTimeoutMs ?? 600_000,
|
|
171
174
|
...(wsAgent ? { wsAgent } : {}),
|
|
172
175
|
logger: {
|
|
@@ -8,6 +8,8 @@ import { publicMessageFailure } from '../../../../src/channels/shared/message-fa
|
|
|
8
8
|
import { resolveRpcAuthority } from '../../rpc-authority.mjs';
|
|
9
9
|
import { publicWorkspaceError, validWorkspacePayload } from '../shared/workspace-rpc.mjs';
|
|
10
10
|
import { validAgentPresetPayload } from '../shared/agent-preset-rpc.mjs';
|
|
11
|
+
import { validContextEnhancementPayload } from '../shared/context-enhancement-rpc.mjs';
|
|
12
|
+
import { normalizeContextEnhancementConfig } from '../../../../src/channels/shared/context-enhancement.mjs';
|
|
11
13
|
import {
|
|
12
14
|
isFeishuGroupResponseMode,
|
|
13
15
|
normalizeFeishuGroupResponseMode,
|
|
@@ -276,6 +278,7 @@ function publicBotEntry(entry) {
|
|
|
276
278
|
connected,
|
|
277
279
|
configured: source.configured === true,
|
|
278
280
|
agentPreset: normalizeAgentPresetId(source.agentPreset),
|
|
281
|
+
contextEnhancement: normalizeContextEnhancementConfig(source.contextEnhancement),
|
|
279
282
|
groupResponseMode: normalizeFeishuGroupResponseMode(source.groupResponseMode),
|
|
280
283
|
groupMessagePermissionGranted: source.groupMessagePermissionGranted === true,
|
|
281
284
|
bot: publicBot(source.bot),
|
|
@@ -415,6 +418,10 @@ function validPayload(endpoint, payload) {
|
|
|
415
418
|
return validAgentPresetPayload(payload)
|
|
416
419
|
? null : '请选择 Agent Preset。';
|
|
417
420
|
}
|
|
421
|
+
if (endpoint === FEISHU_ENDPOINTS.setContextEnhancement) {
|
|
422
|
+
return validContextEnhancementPayload(payload)
|
|
423
|
+
? null : '请提交有效的上下文增强设置。';
|
|
424
|
+
}
|
|
418
425
|
if (endpoint === FEISHU_ENDPOINTS.setGroupResponseMode) {
|
|
419
426
|
return hasOnlyKeys(payload, new Set(['botId', 'groupResponseMode']))
|
|
420
427
|
&& safeOpaqueId(payload.botId)
|
|
@@ -666,6 +673,12 @@ export function createFeishuRpcHandler(controller, { encodeQr = qrCodeDataUrl }
|
|
|
666
673
|
await controller.updateWorkspace(payload.botId, payload.workspace),
|
|
667
674
|
{ encodeQr: cachedEncodeQr },
|
|
668
675
|
);
|
|
676
|
+
} else if (endpoint === FEISHU_ENDPOINTS.setContextEnhancement) {
|
|
677
|
+
if (typeof controller.updateContextEnhancement !== 'function') throw new Error('Context enhancement update is unavailable');
|
|
678
|
+
value = await controller.updateContextEnhancement(
|
|
679
|
+
payload.botId, payload.config,
|
|
680
|
+
(status) => toPublicFeishuStatus(status, { encodeQr: cachedEncodeQr }),
|
|
681
|
+
);
|
|
669
682
|
} else if (endpoint === FEISHU_ENDPOINTS.setAgentPreset) {
|
|
670
683
|
if (typeof controller.updateAgentPreset !== 'function') throw new Error('Agent preset update is unavailable');
|
|
671
684
|
value = await toPublicFeishuStatus(
|
|
@@ -2,7 +2,7 @@ import { createProductionController } from './production.mjs';
|
|
|
2
2
|
import { installQqRpc } from './rpc.mjs';
|
|
3
3
|
|
|
4
4
|
export const name = 'dsh-im-qq-host';
|
|
5
|
-
export const inject = ['connection', 'credentials', '
|
|
5
|
+
export const inject = ['connection', 'credentials', 'typertGateway'];
|
|
6
6
|
|
|
7
7
|
export async function apply(ctx, config = {}) {
|
|
8
8
|
if (config?.controller) {
|
|
@@ -100,6 +100,7 @@ export async function createProductionController(ctx, config = {}, internals = {
|
|
|
100
100
|
appSecret,
|
|
101
101
|
harness: workspaceScope.harness,
|
|
102
102
|
state: workspaceScope.state,
|
|
103
|
+
contextEnhancement: { botId, getSettings: () => workspaces.contextEnhancementFor(botId) },
|
|
103
104
|
replyTimeoutMs: config.replyTimeoutMs ?? 600_000,
|
|
104
105
|
connectTimeoutMs: config.connectTimeoutMs ?? 20_000,
|
|
105
106
|
logger: {
|
|
@@ -3,6 +3,7 @@ import {
|
|
|
3
3
|
connectionTestTargetUnavailable,
|
|
4
4
|
publicConnectionTestResult,
|
|
5
5
|
} from '../../../../src/channels/shared/connection-test.mjs';
|
|
6
|
+
import { SET_CONTEXT_ENHANCEMENT_ENDPOINT, validContextEnhancementPayload } from '../shared/context-enhancement-rpc.mjs';
|
|
6
7
|
import { resolveRpcAuthority } from '../../rpc-authority.mjs';
|
|
7
8
|
import { publicWorkspaceError, SET_WORKSPACE_ENDPOINT, validWorkspacePayload } from '../shared/workspace-rpc.mjs';
|
|
8
9
|
import { SET_AGENT_PRESET_ENDPOINT, validAgentPresetPayload } from '../shared/agent-preset-rpc.mjs';
|
|
@@ -18,6 +19,7 @@ export const QQ_ENDPOINTS = Object.freeze({
|
|
|
18
19
|
deleteBot: 'bot.delete',
|
|
19
20
|
setWorkspace: SET_WORKSPACE_ENDPOINT,
|
|
20
21
|
setAgentPreset: SET_AGENT_PRESET_ENDPOINT,
|
|
22
|
+
setContextEnhancement: SET_CONTEXT_ENHANCEMENT_ENDPOINT,
|
|
21
23
|
});
|
|
22
24
|
export const QQ_RPC_ENDPOINTS = Object.freeze(Object.values(QQ_ENDPOINTS));
|
|
23
25
|
|
|
@@ -76,6 +78,10 @@ function payloadFailure(endpoint, payload) {
|
|
|
76
78
|
return validAgentPresetPayload(payload)
|
|
77
79
|
? null : '请选择 Agent Preset。';
|
|
78
80
|
}
|
|
81
|
+
if (endpoint === QQ_ENDPOINTS.setContextEnhancement) {
|
|
82
|
+
return validContextEnhancementPayload(payload)
|
|
83
|
+
? null : '请提交有效的上下文增强设置。';
|
|
84
|
+
}
|
|
79
85
|
return 'Unknown QQ endpoint.';
|
|
80
86
|
}
|
|
81
87
|
|
|
@@ -171,6 +177,11 @@ export function createQqRpcHandler(controller, { encodeQr = qrDataUrl } = {}) {
|
|
|
171
177
|
await controller.updateWorkspace(payload.botId, payload.workspace),
|
|
172
178
|
cachedEncode,
|
|
173
179
|
);
|
|
180
|
+
} else if (endpoint === QQ_ENDPOINTS.setContextEnhancement) {
|
|
181
|
+
if (typeof controller.updateContextEnhancement !== 'function') throw new Error('Context enhancement update is unavailable');
|
|
182
|
+
value = await controller.updateContextEnhancement(
|
|
183
|
+
payload.botId, payload.config, (status) => publicStatus(status, cachedEncode),
|
|
184
|
+
);
|
|
174
185
|
} else if (endpoint === QQ_ENDPOINTS.setAgentPreset) {
|
|
175
186
|
if (typeof controller.updateAgentPreset !== 'function') throw new Error('Agent preset update is unavailable');
|
|
176
187
|
value = await publicStatus(
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { validateContextEnhancementConfig } from '../../../../src/channels/shared/context-enhancement.mjs';
|
|
2
|
+
|
|
3
|
+
export const SET_CONTEXT_ENHANCEMENT_ENDPOINT = 'bot.context-enhancement.set';
|
|
4
|
+
|
|
5
|
+
export function validContextEnhancementPayload(payload) {
|
|
6
|
+
try {
|
|
7
|
+
if (!payload || typeof payload !== 'object' || Array.isArray(payload)
|
|
8
|
+
|| Reflect.ownKeys(payload).length !== 2
|
|
9
|
+
|| !Object.hasOwn(payload, 'botId') || !Object.hasOwn(payload, 'config')
|
|
10
|
+
|| typeof payload.botId !== 'string'
|
|
11
|
+
|| !/^[A-Za-z0-9_-]{1,128}$/.test(payload.botId)) return false;
|
|
12
|
+
validateContextEnhancementConfig(payload.config);
|
|
13
|
+
return true;
|
|
14
|
+
} catch {
|
|
15
|
+
return false;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -102,6 +102,7 @@ export async function createTokenProductionController(ctx, config, internals, de
|
|
|
102
102
|
token,
|
|
103
103
|
harness: workspaceScope.harness,
|
|
104
104
|
state: workspaceScope.state,
|
|
105
|
+
contextEnhancement: { botId, getSettings: () => workspaces.contextEnhancementFor(botId) },
|
|
105
106
|
replyTimeoutMs: config.replyTimeoutMs ?? 600_000,
|
|
106
107
|
connectTimeoutMs: config.connectTimeoutMs ?? 20_000,
|
|
107
108
|
logger: {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { SET_CONTEXT_ENHANCEMENT_ENDPOINT, validContextEnhancementPayload } from './context-enhancement-rpc.mjs';
|
|
1
2
|
import { resolveRpcAuthority } from '../../rpc-authority.mjs';
|
|
2
3
|
import { publicConnectionTestResult } from '../../../../src/channels/shared/connection-test.mjs';
|
|
3
4
|
import {
|
|
@@ -17,6 +18,7 @@ export const TOKEN_BOT_ENDPOINTS = Object.freeze({
|
|
|
17
18
|
deleteBot: 'bot.delete',
|
|
18
19
|
setWorkspace: SET_WORKSPACE_ENDPOINT,
|
|
19
20
|
setAgentPreset: SET_AGENT_PRESET_ENDPOINT,
|
|
21
|
+
setContextEnhancement: SET_CONTEXT_ENHANCEMENT_ENDPOINT,
|
|
20
22
|
});
|
|
21
23
|
|
|
22
24
|
const ENDPOINTS = Object.freeze(Object.values(TOKEN_BOT_ENDPOINTS));
|
|
@@ -71,6 +73,10 @@ function payloadFailure(endpoint, payload) {
|
|
|
71
73
|
return validAgentPresetPayload(payload)
|
|
72
74
|
? null : '请选择 Agent Preset。';
|
|
73
75
|
}
|
|
76
|
+
if (endpoint === TOKEN_BOT_ENDPOINTS.setContextEnhancement) {
|
|
77
|
+
return validContextEnhancementPayload(payload)
|
|
78
|
+
? null : '请提交有效的上下文增强设置。';
|
|
79
|
+
}
|
|
74
80
|
return 'Unknown bot endpoint.';
|
|
75
81
|
}
|
|
76
82
|
|
|
@@ -152,6 +158,9 @@ export function createTokenBotRpcHandler(controller, { channel }) {
|
|
|
152
158
|
} else if (endpoint === TOKEN_BOT_ENDPOINTS.setWorkspace) {
|
|
153
159
|
if (typeof controller.updateWorkspace !== 'function') throw new Error('Workspace update is unavailable');
|
|
154
160
|
value = await controller.updateWorkspace(payload.botId, payload.workspace);
|
|
161
|
+
} else if (endpoint === TOKEN_BOT_ENDPOINTS.setContextEnhancement) {
|
|
162
|
+
if (typeof controller.updateContextEnhancement !== 'function') throw new Error('Context enhancement update is unavailable');
|
|
163
|
+
value = await controller.updateContextEnhancement(payload.botId, payload.config);
|
|
155
164
|
} else if (endpoint === TOKEN_BOT_ENDPOINTS.setAgentPreset) {
|
|
156
165
|
if (typeof controller.updateAgentPreset !== 'function') throw new Error('Agent preset update is unavailable');
|
|
157
166
|
value = await controller.updateAgentPreset(payload.botId, payload.agentPreset);
|
|
@@ -22,6 +22,7 @@ export function publicWorkspaceError(error) {
|
|
|
22
22
|
'workspace-bot-not-found',
|
|
23
23
|
'agent-preset-invalid',
|
|
24
24
|
'agent-preset-unavailable',
|
|
25
|
+
'context-enhancement-invalid',
|
|
25
26
|
].includes(error?.code)) return null;
|
|
26
27
|
return { code: error.code, message: error.message };
|
|
27
28
|
}
|
|
@@ -2,7 +2,7 @@ import { createProductionController } from './production.mjs';
|
|
|
2
2
|
import { installSlackRpc } from './rpc.mjs';
|
|
3
3
|
|
|
4
4
|
export const name = 'dsh-im-slack-host';
|
|
5
|
-
export const inject = ['connection', 'credentials', '
|
|
5
|
+
export const inject = ['connection', 'credentials', 'typertGateway'];
|
|
6
6
|
|
|
7
7
|
export async function apply(ctx, config = {}) {
|
|
8
8
|
if (config?.controller) return installSlackRpc(ctx, config.controller, config.rpcAuthority);
|
|
@@ -89,6 +89,7 @@ export async function createProductionController(ctx, config = {}, internals = {
|
|
|
89
89
|
appToken,
|
|
90
90
|
harness: workspaceScope.harness,
|
|
91
91
|
state: workspaceScope.state,
|
|
92
|
+
contextEnhancement: { botId, getSettings: () => workspaces.contextEnhancementFor(botId) },
|
|
92
93
|
replyTimeoutMs: config.replyTimeoutMs ?? 600_000,
|
|
93
94
|
connectTimeoutMs: config.connectTimeoutMs ?? 20_000,
|
|
94
95
|
logger: {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { SET_CONTEXT_ENHANCEMENT_ENDPOINT, validContextEnhancementPayload } from '../shared/context-enhancement-rpc.mjs';
|
|
1
2
|
import { resolveRpcAuthority } from '../../rpc-authority.mjs';
|
|
2
3
|
import { publicConnectionTestResult } from '../../../../src/channels/shared/connection-test.mjs';
|
|
3
4
|
import {
|
|
@@ -18,6 +19,7 @@ export const SLACK_ENDPOINTS = Object.freeze({
|
|
|
18
19
|
deleteBot: 'bot.delete',
|
|
19
20
|
setWorkspace: SET_WORKSPACE_ENDPOINT,
|
|
20
21
|
setAgentPreset: SET_AGENT_PRESET_ENDPOINT,
|
|
22
|
+
setContextEnhancement: SET_CONTEXT_ENHANCEMENT_ENDPOINT,
|
|
21
23
|
});
|
|
22
24
|
export const SLACK_RPC_ENDPOINTS = Object.freeze(Object.values(SLACK_ENDPOINTS));
|
|
23
25
|
|
|
@@ -75,6 +77,10 @@ function payloadFailure(endpoint, payload) {
|
|
|
75
77
|
return validAgentPresetPayload(payload)
|
|
76
78
|
? null : '请选择 Agent Preset。';
|
|
77
79
|
}
|
|
80
|
+
if (endpoint === SLACK_ENDPOINTS.setContextEnhancement) {
|
|
81
|
+
return validContextEnhancementPayload(payload)
|
|
82
|
+
? null : '请提交有效的上下文增强设置。';
|
|
83
|
+
}
|
|
78
84
|
return 'Unknown Slack endpoint.';
|
|
79
85
|
}
|
|
80
86
|
|
|
@@ -154,6 +160,10 @@ export function createSlackRpcHandler(controller) {
|
|
|
154
160
|
if (typeof controller.updateWorkspace !== 'function') throw new Error('Workspace update is unavailable');
|
|
155
161
|
value = await controller.updateWorkspace(payload.botId, payload.workspace);
|
|
156
162
|
}
|
|
163
|
+
else if (endpoint === SLACK_ENDPOINTS.setContextEnhancement) {
|
|
164
|
+
if (typeof controller.updateContextEnhancement !== 'function') throw new Error('Context enhancement update is unavailable');
|
|
165
|
+
value = await controller.updateContextEnhancement(payload.botId, payload.config);
|
|
166
|
+
}
|
|
157
167
|
else if (endpoint === SLACK_ENDPOINTS.setAgentPreset) {
|
|
158
168
|
if (typeof controller.updateAgentPreset !== 'function') throw new Error('Agent preset update is unavailable');
|
|
159
169
|
value = await controller.updateAgentPreset(payload.botId, payload.agentPreset);
|
|
@@ -2,7 +2,7 @@ import { createProductionController } from './production.mjs';
|
|
|
2
2
|
import { installTelegramRpc } from './rpc.mjs';
|
|
3
3
|
|
|
4
4
|
export const name = 'dsh-im-telegram-host';
|
|
5
|
-
export const inject = ['connection', 'credentials', '
|
|
5
|
+
export const inject = ['connection', 'credentials', 'typertGateway'];
|
|
6
6
|
|
|
7
7
|
export async function apply(ctx, config = {}) {
|
|
8
8
|
if (config?.controller) {
|
|
@@ -2,7 +2,7 @@ import { createProductionController } from './production.mjs';
|
|
|
2
2
|
import { installWecomRpc } from './rpc.mjs';
|
|
3
3
|
|
|
4
4
|
export const name = 'dsh-im-wecom-host';
|
|
5
|
-
export const inject = ['connection', 'credentials', '
|
|
5
|
+
export const inject = ['connection', 'credentials', 'typertGateway'];
|
|
6
6
|
|
|
7
7
|
export async function apply(ctx, config = {}) {
|
|
8
8
|
if (config?.controller) {
|
|
@@ -103,6 +103,7 @@ export async function createProductionController(ctx, config = {}, internals = {
|
|
|
103
103
|
secret,
|
|
104
104
|
harness: workspaceScope.harness,
|
|
105
105
|
state: workspaceScope.state,
|
|
106
|
+
contextEnhancement: { botId, getSettings: () => workspaces.contextEnhancementFor(botId) },
|
|
106
107
|
replyTimeoutMs: config.replyTimeoutMs ?? 600_000,
|
|
107
108
|
connectTimeoutMs: config.connectTimeoutMs ?? 20_000,
|
|
108
109
|
maxReconnectAttempts: config.maxReconnectAttempts ?? 10,
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import QRCode from 'qrcode';
|
|
2
|
+
import { SET_CONTEXT_ENHANCEMENT_ENDPOINT, validContextEnhancementPayload } from '../shared/context-enhancement-rpc.mjs';
|
|
2
3
|
import { resolveRpcAuthority } from '../../rpc-authority.mjs';
|
|
3
4
|
import { publicWorkspaceError, SET_WORKSPACE_ENDPOINT, validWorkspacePayload } from '../shared/workspace-rpc.mjs';
|
|
4
5
|
import { SET_AGENT_PRESET_ENDPOINT, validAgentPresetPayload } from '../shared/agent-preset-rpc.mjs';
|
|
@@ -18,6 +19,7 @@ export const WECOM_ENDPOINTS = Object.freeze({
|
|
|
18
19
|
deleteBot: 'bot.delete',
|
|
19
20
|
setWorkspace: SET_WORKSPACE_ENDPOINT,
|
|
20
21
|
setAgentPreset: SET_AGENT_PRESET_ENDPOINT,
|
|
22
|
+
setContextEnhancement: SET_CONTEXT_ENHANCEMENT_ENDPOINT,
|
|
21
23
|
});
|
|
22
24
|
export const WECOM_RPC_ENDPOINTS = Object.freeze(Object.values(WECOM_ENDPOINTS));
|
|
23
25
|
|
|
@@ -76,6 +78,10 @@ function payloadFailure(endpoint, payload) {
|
|
|
76
78
|
return validAgentPresetPayload(payload)
|
|
77
79
|
? null : '请选择 Agent Preset。';
|
|
78
80
|
}
|
|
81
|
+
if (endpoint === WECOM_ENDPOINTS.setContextEnhancement) {
|
|
82
|
+
return validContextEnhancementPayload(payload)
|
|
83
|
+
? null : '请提交有效的上下文增强设置。';
|
|
84
|
+
}
|
|
79
85
|
return 'Unknown Enterprise WeChat endpoint.';
|
|
80
86
|
}
|
|
81
87
|
|
|
@@ -172,6 +178,11 @@ export function createWecomRpcHandler(controller, { encodeQr = qrDataUrl } = {})
|
|
|
172
178
|
await controller.updateWorkspace(payload.botId, payload.workspace),
|
|
173
179
|
cachedEncode,
|
|
174
180
|
);
|
|
181
|
+
} else if (endpoint === WECOM_ENDPOINTS.setContextEnhancement) {
|
|
182
|
+
if (typeof controller.updateContextEnhancement !== 'function') throw new Error('Context enhancement update is unavailable');
|
|
183
|
+
value = await controller.updateContextEnhancement(
|
|
184
|
+
payload.botId, payload.config, (status) => publicStatus(status, cachedEncode),
|
|
185
|
+
);
|
|
175
186
|
} else if (endpoint === WECOM_ENDPOINTS.setAgentPreset) {
|
|
176
187
|
if (typeof controller.updateAgentPreset !== 'function') throw new Error('Agent preset update is unavailable');
|
|
177
188
|
value = await publicStatus(
|
|
@@ -2,7 +2,7 @@ import { createProductionController } from './production.mjs';
|
|
|
2
2
|
import { installWeixinRpc } from './rpc.mjs';
|
|
3
3
|
|
|
4
4
|
export const name = 'dsh-weixin-host';
|
|
5
|
-
export const inject = ['connection', 'credentials', '
|
|
5
|
+
export const inject = ['connection', 'credentials', 'typertGateway'];
|
|
6
6
|
|
|
7
7
|
export async function apply(ctx, config = {}) {
|
|
8
8
|
if (config?.controller) {
|
|
@@ -107,6 +107,7 @@ export async function createProductionController(ctx, config = {}, internals = {
|
|
|
107
107
|
token,
|
|
108
108
|
harness: workspaceScope.harness,
|
|
109
109
|
state: workspaceScope.state,
|
|
110
|
+
contextEnhancement: { botId, getSettings: () => workspaces.contextEnhancementFor(botId) },
|
|
110
111
|
replyTimeoutMs: config.replyTimeoutMs ?? 600_000,
|
|
111
112
|
maxMessageChars: config.maxMessageChars ?? DEFAULT_WEIXIN_MAX_MESSAGE_CHARS,
|
|
112
113
|
logger: {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import QRCode from 'qrcode';
|
|
2
|
+
import { SET_CONTEXT_ENHANCEMENT_ENDPOINT, validContextEnhancementPayload } from '../shared/context-enhancement-rpc.mjs';
|
|
2
3
|
import { resolveRpcAuthority } from '../../rpc-authority.mjs';
|
|
3
4
|
import {
|
|
4
5
|
publicWorkspaceError,
|
|
@@ -25,6 +26,7 @@ export const WEIXIN_ENDPOINTS = Object.freeze({
|
|
|
25
26
|
deleteBot: 'bot.delete',
|
|
26
27
|
setWorkspace: SET_WORKSPACE_ENDPOINT,
|
|
27
28
|
setAgentPreset: SET_AGENT_PRESET_ENDPOINT,
|
|
29
|
+
setContextEnhancement: SET_CONTEXT_ENHANCEMENT_ENDPOINT,
|
|
28
30
|
});
|
|
29
31
|
export const WEIXIN_RPC_ENDPOINTS = Object.freeze(Object.values(WEIXIN_ENDPOINTS));
|
|
30
32
|
|
|
@@ -83,6 +85,10 @@ function payloadFailure(endpoint, payload) {
|
|
|
83
85
|
return validAgentPresetPayload(payload)
|
|
84
86
|
? null : '请选择 Agent Preset。';
|
|
85
87
|
}
|
|
88
|
+
if (endpoint === WEIXIN_ENDPOINTS.setContextEnhancement) {
|
|
89
|
+
return validContextEnhancementPayload(payload)
|
|
90
|
+
? null : '请提交有效的上下文增强设置。';
|
|
91
|
+
}
|
|
86
92
|
return 'Unknown Weixin endpoint.';
|
|
87
93
|
}
|
|
88
94
|
|
|
@@ -207,6 +213,11 @@ export function createWeixinRpcHandler(controller, { encodeQr = qrDataUrl } = {}
|
|
|
207
213
|
await controller.updateWorkspace(payload.botId, payload.workspace),
|
|
208
214
|
cachedEncode,
|
|
209
215
|
);
|
|
216
|
+
} else if (endpoint === WEIXIN_ENDPOINTS.setContextEnhancement) {
|
|
217
|
+
if (typeof controller.updateContextEnhancement !== 'function') throw new Error('Context enhancement update is unavailable');
|
|
218
|
+
value = await controller.updateContextEnhancement(
|
|
219
|
+
payload.botId, payload.config, (status) => publicStatus(status, cachedEncode),
|
|
220
|
+
);
|
|
210
221
|
} else if (endpoint === WEIXIN_ENDPOINTS.setAgentPreset) {
|
|
211
222
|
if (typeof controller.updateAgentPreset !== 'function') throw new Error('Agent preset update is unavailable');
|
|
212
223
|
value = await publicStatus(
|
|
@@ -2,7 +2,7 @@ import { createProductionController } from './production.mjs';
|
|
|
2
2
|
import { installWhatsappRpc } from './rpc.mjs';
|
|
3
3
|
|
|
4
4
|
export const name = 'dsh-im-whatsapp-host';
|
|
5
|
-
export const inject = ['connection', '
|
|
5
|
+
export const inject = ['connection', 'typertGateway'];
|
|
6
6
|
|
|
7
7
|
export async function apply(ctx, config = {}) {
|
|
8
8
|
if (config?.controller) {
|
|
@@ -106,6 +106,7 @@ export async function createProductionController(ctx, config = {}, internals = {
|
|
|
106
106
|
authDir,
|
|
107
107
|
harness: workspaceScope.harness,
|
|
108
108
|
state: workspaceScope.state,
|
|
109
|
+
contextEnhancement: { botId, getSettings: () => workspaces.contextEnhancementFor(botId) },
|
|
109
110
|
replyTimeoutMs: config.replyTimeoutMs ?? 600_000,
|
|
110
111
|
connectTimeoutMs: config.connectTimeoutMs ?? 30_000,
|
|
111
112
|
createSession,
|
|
@@ -2,6 +2,7 @@ import QRCode from 'qrcode';
|
|
|
2
2
|
|
|
3
3
|
import { publicConnectionTestResult } from '../../../../src/channels/shared/connection-test.mjs';
|
|
4
4
|
import { normalizeWhatsappAccessPolicy } from '../../../../src/channels/whatsapp/config-store.mjs';
|
|
5
|
+
import { SET_CONTEXT_ENHANCEMENT_ENDPOINT, validContextEnhancementPayload } from '../shared/context-enhancement-rpc.mjs';
|
|
5
6
|
import { resolveRpcAuthority } from '../../rpc-authority.mjs';
|
|
6
7
|
import { publicWorkspaceError, SET_WORKSPACE_ENDPOINT, validWorkspacePayload } from '../shared/workspace-rpc.mjs';
|
|
7
8
|
import { SET_AGENT_PRESET_ENDPOINT, validAgentPresetPayload } from '../shared/agent-preset-rpc.mjs';
|
|
@@ -17,6 +18,7 @@ export const WHATSAPP_ENDPOINTS = Object.freeze({
|
|
|
17
18
|
setAccessPolicy: 'bot.access-policy.set',
|
|
18
19
|
setWorkspace: SET_WORKSPACE_ENDPOINT,
|
|
19
20
|
setAgentPreset: SET_AGENT_PRESET_ENDPOINT,
|
|
21
|
+
setContextEnhancement: SET_CONTEXT_ENHANCEMENT_ENDPOINT,
|
|
20
22
|
});
|
|
21
23
|
export const WHATSAPP_RPC_ENDPOINTS = Object.freeze(Object.values(WHATSAPP_ENDPOINTS));
|
|
22
24
|
|
|
@@ -71,6 +73,10 @@ function payloadFailure(endpoint, payload) {
|
|
|
71
73
|
return validAgentPresetPayload(payload)
|
|
72
74
|
? null : '请选择 Agent Preset。';
|
|
73
75
|
}
|
|
76
|
+
if (endpoint === WHATSAPP_ENDPOINTS.setContextEnhancement) {
|
|
77
|
+
return validContextEnhancementPayload(payload)
|
|
78
|
+
? null : '请提交有效的上下文增强设置。';
|
|
79
|
+
}
|
|
74
80
|
return 'Unknown WhatsApp endpoint.';
|
|
75
81
|
}
|
|
76
82
|
|
|
@@ -173,6 +179,11 @@ export function createWhatsappRpcHandler(controller, { encodeQr = qrDataUrl } =
|
|
|
173
179
|
await controller.updateWorkspace(payload.botId, payload.workspace),
|
|
174
180
|
cachedEncode,
|
|
175
181
|
);
|
|
182
|
+
} else if (endpoint === WHATSAPP_ENDPOINTS.setContextEnhancement) {
|
|
183
|
+
if (typeof controller.updateContextEnhancement !== 'function') throw new Error('Context enhancement update is unavailable');
|
|
184
|
+
value = await controller.updateContextEnhancement(
|
|
185
|
+
payload.botId, payload.config, (status) => publicStatus(status, cachedEncode),
|
|
186
|
+
);
|
|
176
187
|
} else if (endpoint === WHATSAPP_ENDPOINTS.setAgentPreset) {
|
|
177
188
|
if (typeof controller.updateAgentPreset !== 'function') throw new Error('Agent preset update is unavailable');
|
|
178
189
|
value = await publicStatus(
|
|
@@ -1,13 +1,18 @@
|
|
|
1
|
+
import { modernHarnessApi } from './modern-harness-api.mjs';
|
|
2
|
+
|
|
3
|
+
function optionalService(ctx, name) {
|
|
4
|
+
if (ctx && Object.hasOwn(ctx, name)) return ctx[name];
|
|
5
|
+
return typeof ctx?.get === 'function' ? ctx.get(name) : undefined;
|
|
6
|
+
}
|
|
7
|
+
|
|
1
8
|
/** Connect to this Host directly unless an external Harness URL was configured. */
|
|
2
9
|
export function harnessConnection(ctx, config = {}) {
|
|
3
10
|
if (config.harnessBaseUrl !== undefined) {
|
|
4
11
|
return { baseUrl: new URL(config.harnessBaseUrl) };
|
|
5
12
|
}
|
|
6
|
-
|
|
7
|
-
throw new TypeError('dsh-im requires the Host apiProxy service; check that DSH has finished loading its Host services');
|
|
8
|
-
}
|
|
13
|
+
const apiProxy = optionalService(ctx, 'apiProxy') ?? modernHarnessApi(ctx);
|
|
9
14
|
return {
|
|
10
|
-
apiProxy
|
|
15
|
+
apiProxy,
|
|
11
16
|
// Cordis child contexts share one root; different Hosts must not share
|
|
12
17
|
// ownership of pending questions and approvals.
|
|
13
18
|
interactionScope: ctx.root ?? ctx,
|
|
@@ -16,7 +16,6 @@ export const name = 'dsh-im-host';
|
|
|
16
16
|
export const inject = [
|
|
17
17
|
'connection',
|
|
18
18
|
'credentials',
|
|
19
|
-
'apiProxy',
|
|
20
19
|
'typertGateway',
|
|
21
20
|
];
|
|
22
21
|
|
|
@@ -55,38 +54,53 @@ export function createImHostPlugin(internals = {}) {
|
|
|
55
54
|
name,
|
|
56
55
|
inject,
|
|
57
56
|
async apply(ctx, config = {}) {
|
|
58
|
-
|
|
57
|
+
const activate = async (readyCtx) => {
|
|
58
|
+
await activateChannels(readyCtx, config);
|
|
59
|
+
};
|
|
59
60
|
if (typeof ctx?.inject === 'function') {
|
|
60
|
-
ctx
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
const logger = typeof ctx?.logger === 'function'
|
|
67
|
-
? ctx.logger(name)
|
|
68
|
-
: (ctx?.logger ?? console);
|
|
69
|
-
if (ctx?.connection?.rpc) {
|
|
70
|
-
try {
|
|
71
|
-
startUpdate(ctx);
|
|
72
|
-
} catch (error) {
|
|
73
|
-
logger.error?.('[dsh-im] failed to activate update management; continuing with channels', error);
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
const failures = [];
|
|
77
|
-
for (const [channel, start] of channels) {
|
|
78
|
-
try {
|
|
79
|
-
await start(ctx, channelConfig(config, channel));
|
|
80
|
-
} catch (error) {
|
|
81
|
-
failures.push(error);
|
|
82
|
-
logger.error?.(`[dsh-im] failed to activate ${channel}; continuing with the remaining channels`, error);
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
if (failures.length === channels.length) {
|
|
86
|
-
throw new AggregateError(failures, 'dsh-im failed to activate every channel');
|
|
61
|
+
const modern = typeof ctx?.typertGateway?.stream === 'function';
|
|
62
|
+
await ctx.inject(
|
|
63
|
+
modern ? ['sessionController', 'workspaceController'] : ['apiProxy'],
|
|
64
|
+
activate,
|
|
65
|
+
);
|
|
66
|
+
return;
|
|
87
67
|
}
|
|
68
|
+
await activate(ctx);
|
|
88
69
|
},
|
|
89
70
|
});
|
|
71
|
+
|
|
72
|
+
async function activateChannels(ctx, config) {
|
|
73
|
+
setImHostLanguage(config.language ?? process.env.DSH_IM_LANGUAGE);
|
|
74
|
+
if (typeof ctx?.inject === 'function') {
|
|
75
|
+
ctx.inject(['tools', 'systemPrompt'], (artifactCtx) => {
|
|
76
|
+
installOutboundArtifactTool(artifactCtx);
|
|
77
|
+
});
|
|
78
|
+
} else {
|
|
79
|
+
installOutboundArtifactTool(ctx);
|
|
80
|
+
}
|
|
81
|
+
const logger = typeof ctx?.logger === 'function'
|
|
82
|
+
? ctx.logger(name)
|
|
83
|
+
: (ctx?.logger ?? console);
|
|
84
|
+
if (ctx?.connection?.rpc) {
|
|
85
|
+
try {
|
|
86
|
+
startUpdate(ctx);
|
|
87
|
+
} catch (error) {
|
|
88
|
+
logger.error?.('[dsh-im] failed to activate update management; continuing with channels', error);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
const failures = [];
|
|
92
|
+
for (const [channel, start] of channels) {
|
|
93
|
+
try {
|
|
94
|
+
await start(ctx, channelConfig(config, channel));
|
|
95
|
+
} catch (error) {
|
|
96
|
+
failures.push(error);
|
|
97
|
+
logger.error?.(`[dsh-im] failed to activate ${channel}; continuing with the remaining channels`, error);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
if (failures.length === channels.length) {
|
|
101
|
+
throw new AggregateError(failures, 'dsh-im failed to activate every channel');
|
|
102
|
+
}
|
|
103
|
+
}
|
|
90
104
|
}
|
|
91
105
|
|
|
92
106
|
export async function apply(ctx, config = {}) {
|