Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,9 @@ jobs:
run: pnpm exec playwright install --with-deps chromium
- working-directory: apps/web
run: pnpm test:integration
- name: Library import, search and task reference tests
working-directory: apps/web
run: node --test ../../packages/plugins/library/tests/*.test.mjs
- name: Enterprise desktop identity and collaboration tests
working-directory: apps/web
run: node --test ../../packages/providers/identity-enterprise/tests/*.test.mjs ../../packages/plugins/enterprise-collaboration/tests/*.test.mjs
Expand Down
6 changes: 6 additions & 0 deletions apps/web/pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

13 changes: 13 additions & 0 deletions apps/web/scripts/build-library.mjs
Original file line number Diff line number Diff line change
@@ -1,6 +1,19 @@
import { build } from 'esbuild';
import { writeFile } from 'node:fs/promises';
import { fileURLToPath } from 'node:url';
import { createRequire } from 'node:module';
const entry = new URL('../../../packages/plugins/library/', import.meta.url);
const result = await build({ entryPoints: [fileURLToPath(new URL('src/client.tsx', entry))], bundle: true, write: false, format: 'cjs', platform: 'browser', target: 'es2022', external: ['@deepseek-ai/dsh-client-ui-primitives', 'react', 'react/jsx-runtime'] });
await writeFile(new URL('dist/client.browser.js', entry), `window.__ModuleLoader__.load({id: "workdsh-plugin-library", factory: function(require) { const module = {exports:{}};\n${result.outputFiles[0].text}\nreturn module.exports; }});\n`);

// Reuse Office's public extraction module at build time. Library must not require
// an unpublished Office plugin at runtime or activate Office in a personal Profile.
const requireOffice = createRequire(new URL('package.json', entry));
await build({
entryPoints: [fileURLToPath(new URL('src/index.ts', entry))],
bundle: true, format: 'esm', platform: 'node', target: 'node22', packages: 'external',
plugins: [{ name: 'office-tabular-only', setup(builder) {
builder.onResolve({ filter: /^workdsh-plugin-office\/tabular$/ }, () => ({ path: requireOffice.resolve('workdsh-plugin-office/tabular') }));
} }],
outfile: fileURLToPath(new URL('dist/index.js', entry)),
});
2 changes: 2 additions & 0 deletions apps/web/scripts/build-office.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import { fileURLToPath } from "node:url";
const root = new URL("../../../packages/plugins/office/", import.meta.url);
const wordOnly = process.argv.includes("--word-only");
await mkdir(new URL("dist/", root), { recursive: true });
await build({ entryPoints: [fileURLToPath(new URL("src/tabular.js", root))], bundle: true, platform: "node", format: "esm", target: "node22", external: ["exceljs"], outfile: fileURLToPath(new URL("dist/tabular.js", root)) });
await writeFile(new URL("dist/tabular.d.ts", root), await readFile(new URL("src/tabular.d.ts", root)));
const font=await readFile(new URL("src/pdf/fonts/NotoSansSC.ttf",root));
const fontSource=JSON.parse(await readFile(new URL("src/pdf/fonts/source.json",root),"utf8"));
if(font.length!==fontSource.bytes||createHash("sha256").update(font).digest("hex")!==fontSource.sha256)throw Error("Bundled PDF font integrity mismatch");
Expand Down
2 changes: 1 addition & 1 deletion apps/web/scripts/pack-library-release.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ delete manifest.devDependencies; delete manifest.scripts;
manifest.workdshRelease = {
scope: 'local-library-alpha',
storage: '$DSH_HOME/library',
formats: ['md', 'markdown', 'txt', 'html', 'htm', 'pdf', 'docx', 'pptx'],
formats: ['md', 'markdown', 'txt', 'html', 'htm', 'pdf', 'docx', 'pptx', 'csv', 'xlsx'],
preservesOriginals: true,
};
await writeFile(join(stage, 'package.json'), `${JSON.stringify(manifest, null, 2)}\n`);
Expand Down
2 changes: 1 addition & 1 deletion apps/web/scripts/pack-office-release.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ const manifest = JSON.parse(await readFile(join(plugin, "package.json"), "utf8")
delete manifest.devDependencies;
delete manifest.scripts;
manifest.description = "Independent Harness plugin: browser Office working copies and native PPTX templates (alpha preview)";
manifest.workdshRelease = {scope: "office-browser-preview", wordOnly: false, formats: ["docx", "pptx", "xlsx", "pdf", "html"]};
manifest.workdshRelease = {scope: "office-browser-preview", wordOnly: false, formats: ["docx", "pptx", "xlsx", "csv", "pdf", "html"]};
await writeFile(join(stage, "package.json"), JSON.stringify(manifest, null, 2) + "\n");
for (const file of manifest.files) await cp(join(plugin, file), join(stage, file), {recursive: true});
execFileSync("corepack", ["pnpm", "pack", "--pack-destination", destination], {cwd: stage, stdio: "inherit"});
Expand Down
4 changes: 2 additions & 2 deletions packages/contracts/src/library.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { ActorContext, ResourceOwner } from './governance.js';

export type LibraryAssetKind = 'markdown' | 'text' | 'pdf' | 'docx' | 'pptx' | 'html';
export type LibraryAssetKind = 'markdown' | 'text' | 'pdf' | 'docx' | 'pptx' | 'html' | 'csv' | 'xlsx';
export type LibraryConversionStatus = 'ready' | 'pending' | 'failed';
export type LibraryAssetStatus = 'active' | 'disabled';

Expand Down Expand Up @@ -114,7 +114,7 @@ export interface LibraryDraft {

export interface LibraryOriginalPreviewInput {
readonly name: string;
readonly kind: Extract<LibraryAssetKind, 'docx' | 'pptx'>;
readonly kind: Extract<LibraryAssetKind, 'docx' | 'pptx' | 'csv' | 'xlsx'>;
readonly bytes: Uint8Array;
}

Expand Down
8 changes: 7 additions & 1 deletion packages/plugins/library/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@

## 验收与下一步

完成对应 PLAN 任务及 [验收矩阵](../../../apps/web/docs/ACCEPTANCE.md) 场景,记录真实测试证据后才更新为完成。当前 Host 与 Client 入口可加载,数据保存到 `$DSH_HOME/library`。支持 MD、TXT、HTML、PDF、DOCX、PPTX;所有格式保留原件并生成独立检索文本。HTML 在无 Host 权限、无网络访问的沙箱中按原始样式和内联交互展示;PDF 可直接预览;安装 Office 插件时,Word 使用 `docx-preview`、PowerPoint 使用 `pptx-react-viewer` 打开原件,未安装时回退为派生检索文本和原件下载。Library 与 Office 通过公开可选预览注册表协作,不互相导入运行时内部实现。
完成对应 PLAN 任务及 [验收矩阵](../../../apps/web/docs/ACCEPTANCE.md) 场景,记录真实测试证据后才更新为完成。当前 Host 与 Client 入口可加载,数据保存到 `$DSH_HOME/library`。支持 MD、TXT、HTML、PDF、DOCX、PPTX、CSV、XLSX;所有格式保留原件并生成独立检索文本。HTML 在无 Host 权限、无网络访问的沙箱中按原始样式和内联交互展示;PDF 可直接预览;安装 Office 插件时,Word 使用 `docx-preview`、PowerPoint 使用 `pptx-react-viewer` 打开原件,未安装时回退为派生检索文本和原件下载。Library 与 Office 通过公开可选预览注册表协作,不互相导入运行时内部实现。

发布包可通过 `corepack pnpm probe:library` 验证独立安装、两次冷启动、卸载保留 `$DSH_HOME/library`、重新安装和资料恢复。页面支持搜索、最近、本地产物、完整目录树、目录内新建与导入、移动、添加到当前任务、停用与重新启用;停用会立即阻断历史任务引用的正文读取。搜索结果显示目录、类型、来源、修订、转换状态和页/段/幻灯片位置。

Expand All @@ -36,3 +36,9 @@
### 可选 Host 成员服务选择

公开 registerLibraryConnection、registerLibraryTools、registerLibraryContextInjection 接受可选可信选择器,返回服务端 actor、LibraryService 和 verify。工具与上下文使用实际 Agent 选择,不从模型参数读取主体;操作前后核验,拒绝不匹配的会话上下文。默认 apply 不传选择器,保持个人行为。企业装配必须提供隔离存储和可撤权身份;这些入口本身不是文件执行沙箱。

## 表格资料

CSV/XLSX 可上传、按类型检索并引用到任务;原始文件按字节保留。Host 转换在构建时复用 Office 的公开 `workdsh-plugin-office/tabular` 入口的 CSV 解码/解析;表格提取模块随 Library 构建,运行时复用 ExcelJS,无需安装或激活 Office 插件即可导入和检索。CSV 支持 UTF-8、GB18030、UTF-16,以及逗号、分号和制表符;XLSX 提取工作表名称和单元格已有值,公式不重新计算,图表、图片和格式不进入检索文本。检索文本最多 1500 行/120 列/24000 单元格,XLSX 最多 20 个工作表;截取会显示警告,完整原件仍可下载。

原件预览通过公开可选注册表复用 Office:CSV 为只读表格,XLSX 使用现有隔离编辑器,导出为副本,不覆盖资料库修订。未启用 Office 预览时显示检索文本。个人与企业 Desktop、Web 复用相同导入和预览实现,实际资料授权保持不变。
6 changes: 4 additions & 2 deletions packages/plugins/library/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -76,12 +76,14 @@
"react": "19.2.4",
"workdsh-contracts": "workspace:*",
"workdsh-ui": "workspace:*",
"@deepseek-ai/dsh-client-ui-primitives": "0.2.0-rc.2"
"@deepseek-ai/dsh-client-ui-primitives": "0.2.0-rc.2",
"workdsh-plugin-office": "workspace:*"
},
"dependencies": {
"jszip": "3.10.1",
"pdfjs-dist": "5.4.624",
"zod": "4.4.3"
"zod": "4.4.3",
"exceljs": "4.4.0"
},
"dsh": {
"bundle": {
Expand Down
Loading
Loading