mirror of
https://github.com/hansjone/dsh-im-ops.git
synced 2026-10-20 07:33:20 +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]
|
## [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
|
## [4.0.0] - 2026-08-29
|
||||||
|
|
||||||
### Fixed / 修复
|
### Fixed / 修复
|
||||||
|
|
@ -468,7 +475,8 @@ This file records the notable changes in each dsh-im release. Its format follows
|
||||||
- 改进 npm 发布包结构,保留 CLI 入口并避免安装脚本拦截。
|
- 改进 npm 发布包结构,保留 CLI 入口并避免安装脚本拦截。
|
||||||
Improved npm package contents to preserve the CLI entry point and avoid install-script blocking.
|
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
|
[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.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
|
[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
|
// package.json
|
||||||
var package_default = {
|
var package_default = {
|
||||||
name: "@xmanrui/dsh-im",
|
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.",
|
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: [
|
keywords: [
|
||||||
"deepseek-harness",
|
"deepseek-harness",
|
||||||
|
|
@ -12487,6 +12487,14 @@ function UpdatePanel({ rpcCall, clientVersion, onStatus }) {
|
||||||
var name = "im-settings";
|
var name = "im-settings";
|
||||||
var inject = ["slots", "connection", "locale", "workspaces"];
|
var inject = ["slots", "connection", "locale", "workspaces"];
|
||||||
var IM_PLUGIN_VERSION = package_default.version;
|
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([
|
var CHANNELS = Object.freeze([
|
||||||
{ id: "weixin", label: "\u5FAE\u4FE1" },
|
{ id: "weixin", label: "\u5FAE\u4FE1" },
|
||||||
{ id: "feishu", label: "\u98DE\u4E66" },
|
{ 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 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 updateRpcCall = (endpoint, payload, signal) => ctx.connection.rpc.call(UPDATE_RPC_CHANNEL, endpoint, payload, signal);
|
||||||
const workspaceDirectoryPicker = Object.freeze({
|
const workspaceDirectoryPicker = Object.freeze({
|
||||||
listDirectory: (path, signal) => ctx.workspaces.listDirectory(path, signal),
|
listDirectory: (path, signal) => callWorkspaceDirectoryApi(ctx, "listDirectory", path, signal),
|
||||||
pickDirectory: () => ctx.workspaces.pickDirectory()
|
pickDirectory: () => callWorkspaceDirectoryApi(ctx, "pickDirectory")
|
||||||
});
|
});
|
||||||
ctx.slots.inject("settings.section", () => ctx.slots.register({
|
ctx.slots.inject("settings.section", () => ctx.slots.register({
|
||||||
name: "settings.section",
|
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",
|
"name": "@xmanrui/dsh-im",
|
||||||
"version": "4.0.0",
|
"version": "4.0.1",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "@xmanrui/dsh-im",
|
"name": "@xmanrui/dsh-im",
|
||||||
"version": "4.0.0",
|
"version": "4.0.1",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@tencent-connect/qqbot-connector": "1.2.0",
|
"@tencent-connect/qqbot-connector": "1.2.0",
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@xmanrui/dsh-im",
|
"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.",
|
"description": "把九种 IM 机器人和公网 AI Office 接入本机 DeepSeek Harness。 Connect nine IM channels and a public AI Office to a local DeepSeek Harness.",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"deepseek-harness",
|
"deepseek-harness",
|
||||||
|
|
|
||||||
|
|
@ -55,6 +55,16 @@ export const name = 'im-settings';
|
||||||
export const inject = ['slots', 'connection', 'locale', 'workspaces'];
|
export const inject = ['slots', 'connection', 'locale', 'workspaces'];
|
||||||
export const IM_PLUGIN_VERSION = manifest.version;
|
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([
|
const CHANNELS = Object.freeze([
|
||||||
{ id: 'weixin', label: '微信' },
|
{ id: 'weixin', label: '微信' },
|
||||||
{ id: 'feishu', label: '飞书' },
|
{ id: 'feishu', label: '飞书' },
|
||||||
|
|
@ -335,8 +345,9 @@ export function apply(ctx) {
|
||||||
const updateRpcCall = (endpoint, payload, signal) =>
|
const updateRpcCall = (endpoint, payload, signal) =>
|
||||||
ctx.connection.rpc.call(UPDATE_RPC_CHANNEL, endpoint, payload, signal);
|
ctx.connection.rpc.call(UPDATE_RPC_CHANNEL, endpoint, payload, signal);
|
||||||
const workspaceDirectoryPicker = Object.freeze({
|
const workspaceDirectoryPicker = Object.freeze({
|
||||||
listDirectory: (path, signal) => ctx.workspaces.listDirectory(path, signal),
|
listDirectory: (path, signal) =>
|
||||||
pickDirectory: () => ctx.workspaces.pickDirectory(),
|
callWorkspaceDirectoryApi(ctx, 'listDirectory', path, signal),
|
||||||
|
pickDirectory: () => callWorkspaceDirectoryApi(ctx, 'pickDirectory'),
|
||||||
});
|
});
|
||||||
|
|
||||||
ctx.slots.inject('settings.section', () => ctx.slots.register({
|
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', () => {
|
test('all nine channel settings and connected cards render English copy', () => {
|
||||||
const rpcCall = async () => ({ ok: true, value: {} });
|
const rpcCall = async () => ({ ok: true, value: {} });
|
||||||
const noop = () => {};
|
const noop = () => {};
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue