mirror of
https://github.com/hansjone/dsh-im-ops.git
synced 2026-10-09 01:53:21 +08:00
chore: release v4.0.1
This commit is contained in:
parent
8794a46e81
commit
92ec91b7bd
7 changed files with 102 additions and 10 deletions
10
CHANGELOG.md
10
CHANGELOG.md
|
|
@ -6,6 +6,13 @@ This file records the notable changes in each dsh-im release. Its format follows
|
|||
|
||||
## [Unreleased]
|
||||
|
||||
## [4.0.1] - 2026-08-30
|
||||
|
||||
### Fixed / 修复
|
||||
|
||||
- 新版 DSH 中,机器人卡片的工作区目录选择器现在使用 `uiWorkspace` 目录服务,不再调用已从 Workspace Controller 移除的 `workspaces.listDirectory` / `pickDirectory`;旧版 Host 仍保留原接口回退。
|
||||
On current DSH releases, the bot-card workspace picker now uses the `uiWorkspace` directory service instead of the removed Workspace Controller `workspaces.listDirectory` / `pickDirectory` methods, while retaining the legacy Host fallback.
|
||||
|
||||
## [4.0.0] - 2026-08-29
|
||||
|
||||
### Fixed / 修复
|
||||
|
|
@ -468,7 +475,8 @@ This file records the notable changes in each dsh-im release. Its format follows
|
|||
- 改进 npm 发布包结构,保留 CLI 入口并避免安装脚本拦截。
|
||||
Improved npm package contents to preserve the CLI entry point and avoid install-script blocking.
|
||||
|
||||
[Unreleased]: https://github.com/xmanrui/dsh-im/compare/v4.0.0...HEAD
|
||||
[Unreleased]: https://github.com/xmanrui/dsh-im/compare/v4.0.1...HEAD
|
||||
[4.0.1]: https://github.com/xmanrui/dsh-im/compare/v4.0.0...v4.0.1
|
||||
[4.0.0]: https://github.com/xmanrui/dsh-im/compare/v3.2.0...v4.0.0
|
||||
[3.2.0]: https://github.com/xmanrui/dsh-im/compare/v3.1.1...v3.2.0
|
||||
[3.1.1]: https://github.com/xmanrui/dsh-im/compare/v3.1.0...v3.1.1
|
||||
|
|
|
|||
|
|
@ -571,7 +571,7 @@ var React22 = __toESM(require("react"), 1);
|
|||
// package.json
|
||||
var package_default = {
|
||||
name: "@xmanrui/dsh-im",
|
||||
version: "4.0.0",
|
||||
version: "4.0.1",
|
||||
description: "\u628A\u4E5D\u79CD IM \u673A\u5668\u4EBA\u548C\u516C\u7F51 AI Office \u63A5\u5165\u672C\u673A DeepSeek Harness\u3002 Connect nine IM channels and a public AI Office to a local DeepSeek Harness.",
|
||||
keywords: [
|
||||
"deepseek-harness",
|
||||
|
|
@ -12487,6 +12487,14 @@ function UpdatePanel({ rpcCall, clientVersion, onStatus }) {
|
|||
var name = "im-settings";
|
||||
var inject = ["slots", "connection", "locale", "workspaces"];
|
||||
var IM_PLUGIN_VERSION = package_default.version;
|
||||
function callWorkspaceDirectoryApi(ctx, method, ...args) {
|
||||
const uiWorkspace = typeof ctx.get === "function" ? ctx.get("uiWorkspace") : void 0;
|
||||
const service = typeof uiWorkspace?.[method] === "function" ? uiWorkspace : ctx.workspaces;
|
||||
if (typeof service?.[method] !== "function") {
|
||||
throw new Error("\u65E0\u6CD5\u8BFB\u53D6\u76EE\u5F55\uFF0C\u8BF7\u91CD\u8BD5\u3002");
|
||||
}
|
||||
return service[method](...args);
|
||||
}
|
||||
var CHANNELS = Object.freeze([
|
||||
{ id: "weixin", label: "\u5FAE\u4FE1" },
|
||||
{ id: "feishu", label: "\u98DE\u4E66" },
|
||||
|
|
@ -12785,8 +12793,8 @@ function apply(ctx) {
|
|||
const officeRpcCall = (endpoint, payload, signal) => ctx.connection.rpc.call(OFFICE_RPC_CHANNEL, endpoint, payload, signal);
|
||||
const updateRpcCall = (endpoint, payload, signal) => ctx.connection.rpc.call(UPDATE_RPC_CHANNEL, endpoint, payload, signal);
|
||||
const workspaceDirectoryPicker = Object.freeze({
|
||||
listDirectory: (path, signal) => ctx.workspaces.listDirectory(path, signal),
|
||||
pickDirectory: () => ctx.workspaces.pickDirectory()
|
||||
listDirectory: (path, signal) => callWorkspaceDirectoryApi(ctx, "listDirectory", path, signal),
|
||||
pickDirectory: () => callWorkspaceDirectoryApi(ctx, "pickDirectory")
|
||||
});
|
||||
ctx.slots.inject("settings.section", () => ctx.slots.register({
|
||||
name: "settings.section",
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
4
package-lock.json
generated
4
package-lock.json
generated
|
|
@ -1,12 +1,12 @@
|
|||
{
|
||||
"name": "@xmanrui/dsh-im",
|
||||
"version": "4.0.0",
|
||||
"version": "4.0.1",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@xmanrui/dsh-im",
|
||||
"version": "4.0.0",
|
||||
"version": "4.0.1",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@tencent-connect/qqbot-connector": "1.2.0",
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@xmanrui/dsh-im",
|
||||
"version": "4.0.0",
|
||||
"version": "4.0.1",
|
||||
"description": "把九种 IM 机器人和公网 AI Office 接入本机 DeepSeek Harness。 Connect nine IM channels and a public AI Office to a local DeepSeek Harness.",
|
||||
"keywords": [
|
||||
"deepseek-harness",
|
||||
|
|
|
|||
|
|
@ -55,6 +55,16 @@ export const name = 'im-settings';
|
|||
export const inject = ['slots', 'connection', 'locale', 'workspaces'];
|
||||
export const IM_PLUGIN_VERSION = manifest.version;
|
||||
|
||||
function callWorkspaceDirectoryApi(ctx, method, ...args) {
|
||||
// Current DSH owns directory operations on uiWorkspace; legacy Hosts keep them on workspaces.
|
||||
const uiWorkspace = typeof ctx.get === 'function' ? ctx.get('uiWorkspace') : undefined;
|
||||
const service = typeof uiWorkspace?.[method] === 'function' ? uiWorkspace : ctx.workspaces;
|
||||
if (typeof service?.[method] !== 'function') {
|
||||
throw new Error('无法读取目录,请重试。');
|
||||
}
|
||||
return service[method](...args);
|
||||
}
|
||||
|
||||
const CHANNELS = Object.freeze([
|
||||
{ id: 'weixin', label: '微信' },
|
||||
{ id: 'feishu', label: '飞书' },
|
||||
|
|
@ -335,8 +345,9 @@ export function apply(ctx) {
|
|||
const updateRpcCall = (endpoint, payload, signal) =>
|
||||
ctx.connection.rpc.call(UPDATE_RPC_CHANNEL, endpoint, payload, signal);
|
||||
const workspaceDirectoryPicker = Object.freeze({
|
||||
listDirectory: (path, signal) => ctx.workspaces.listDirectory(path, signal),
|
||||
pickDirectory: () => ctx.workspaces.pickDirectory(),
|
||||
listDirectory: (path, signal) =>
|
||||
callWorkspaceDirectoryApi(ctx, 'listDirectory', path, signal),
|
||||
pickDirectory: () => callWorkspaceDirectoryApi(ctx, 'pickDirectory'),
|
||||
});
|
||||
|
||||
ctx.slots.inject('settings.section', () => ctx.slots.register({
|
||||
|
|
|
|||
|
|
@ -792,6 +792,71 @@ test('client registers one top-level bilingual IM settings section with a direct
|
|||
}
|
||||
});
|
||||
|
||||
test('client directory picker uses the current DSH uiWorkspace service', async () => {
|
||||
const registrations = [];
|
||||
const directoryCalls = [];
|
||||
let uiWorkspace;
|
||||
const ctx = {
|
||||
effect() {},
|
||||
get(name) {
|
||||
assert.equal(name, 'uiWorkspace');
|
||||
return uiWorkspace;
|
||||
},
|
||||
locale: {
|
||||
bind: () => (key) => key,
|
||||
register: () => () => {},
|
||||
},
|
||||
connection: { rpc: { call: async () => ({ ok: true, value: {} }) } },
|
||||
workspaces: {
|
||||
list: {
|
||||
getSnapshot: () => ({ items: [] }),
|
||||
subscribe: () => () => {},
|
||||
},
|
||||
},
|
||||
slots: {
|
||||
inject(name, install) {
|
||||
assert.equal(name, 'settings.section');
|
||||
install();
|
||||
},
|
||||
register(options, component) {
|
||||
registrations.push({ options, component });
|
||||
return () => {};
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
try {
|
||||
applyClient(ctx);
|
||||
uiWorkspace = {
|
||||
async listDirectory(path, signal) {
|
||||
directoryCalls.push({ operation: 'list', path, signal });
|
||||
return { path, entries: [] };
|
||||
},
|
||||
async pickDirectory() {
|
||||
directoryCalls.push({ operation: 'pick' });
|
||||
return '/workspace/current-host';
|
||||
},
|
||||
};
|
||||
|
||||
const injected = registrations[0].options.inject();
|
||||
const signal = new AbortController().signal;
|
||||
assert.deepEqual(
|
||||
await injected.workspaceDirectoryPicker.listDirectory('/workspace/current', signal),
|
||||
{ path: '/workspace/current', entries: [] },
|
||||
);
|
||||
assert.equal(
|
||||
await injected.workspaceDirectoryPicker.pickDirectory(),
|
||||
'/workspace/current-host',
|
||||
);
|
||||
assert.deepEqual(directoryCalls, [
|
||||
{ operation: 'list', path: '/workspace/current', signal },
|
||||
{ operation: 'pick' },
|
||||
]);
|
||||
} finally {
|
||||
setImTranslator(null);
|
||||
}
|
||||
});
|
||||
|
||||
test('all nine channel settings and connected cards render English copy', () => {
|
||||
const rpcCall = async () => ({ ok: true, value: {} });
|
||||
const noop = () => {};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue