@xmanrui/dsh-im 3.2.0 → 4.0.1
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 +1 -1
- package/README.md +1 -1
- package/lib/client.js +11 -3
- package/lib/index.js +212 -212
- package/package.json +1 -1
- package/plugin-src/client/index.js +13 -2
- package/plugin-src/host/channels/dingtalk/index.mjs +1 -1
- 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/qq/index.mjs +1 -1
- package/plugin-src/host/channels/slack/index.mjs +1 -1
- 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/weixin/index.mjs +1 -1
- package/plugin-src/host/channels/whatsapp/index.mjs +1 -1
- 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/src/channels/shared/harness-client.mjs +18 -0
package/package.json
CHANGED
|
@@ -55,6 +55,16 @@ export const name = 'im-settings';
|
|
|
55
55
|
export const inject = ['slots', 'connection', 'locale', 'workspaces'];
|
|
56
56
|
export const IM_PLUGIN_VERSION = manifest.version;
|
|
57
57
|
|
|
58
|
+
function callWorkspaceDirectoryApi(ctx, method, ...args) {
|
|
59
|
+
// Current DSH owns directory operations on uiWorkspace; legacy Hosts keep them on workspaces.
|
|
60
|
+
const uiWorkspace = typeof ctx.get === 'function' ? ctx.get('uiWorkspace') : undefined;
|
|
61
|
+
const service = typeof uiWorkspace?.[method] === 'function' ? uiWorkspace : ctx.workspaces;
|
|
62
|
+
if (typeof service?.[method] !== 'function') {
|
|
63
|
+
throw new Error('无法读取目录,请重试。');
|
|
64
|
+
}
|
|
65
|
+
return service[method](...args);
|
|
66
|
+
}
|
|
67
|
+
|
|
58
68
|
const CHANNELS = Object.freeze([
|
|
59
69
|
{ id: 'weixin', label: '微信' },
|
|
60
70
|
{ id: 'feishu', label: '飞书' },
|
|
@@ -335,8 +345,9 @@ export function apply(ctx) {
|
|
|
335
345
|
const updateRpcCall = (endpoint, payload, signal) =>
|
|
336
346
|
ctx.connection.rpc.call(UPDATE_RPC_CHANNEL, endpoint, payload, signal);
|
|
337
347
|
const workspaceDirectoryPicker = Object.freeze({
|
|
338
|
-
listDirectory: (path, signal) =>
|
|
339
|
-
|
|
348
|
+
listDirectory: (path, signal) =>
|
|
349
|
+
callWorkspaceDirectoryApi(ctx, 'listDirectory', path, signal),
|
|
350
|
+
pickDirectory: () => callWorkspaceDirectoryApi(ctx, 'pickDirectory'),
|
|
340
351
|
});
|
|
341
352
|
|
|
342
353
|
ctx.slots.inject('settings.section', () => ctx.slots.register({
|
|
@@ -2,7 +2,7 @@ import { createProductionController } from './production.mjs';
|
|
|
2
2
|
import { installDingtalkRpc } from './rpc.mjs';
|
|
3
3
|
|
|
4
4
|
export const name = 'dsh-dingtalk-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 { 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;
|
|
@@ -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) {
|
|
@@ -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);
|
|
@@ -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) {
|
|
@@ -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) {
|
|
@@ -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) {
|
|
@@ -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 = {}) {
|