在编辑器内直接编辑 Overleaf 项目并实时双向同步
30.8/100
综合分
1
GitHub 星标
—
npm 周下载
—/5
用户评分
数据截至 2026/10/28 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。
安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add chenqaq123/dsh-overleaf-workshop该包不可直接 npm 安装,改从 GitHub 源安装(明细见下方安装检查)
状态速览
判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态信任档位:需留意
是什么
dsh 原生插件 · tool
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
活跃:最近一次提交在 7 天前
档位由哪些信号合成
本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。
⚠︎ 实装验证未通过(runtime_smoke_failed · 2026/10/28) ——可能是验证环境差异,装前建议到 GitHub 仓库确认最近更新与 issue。
社区实装还没有人打卡 · 装过的第一个就是你
安全扫描自动 · 静态分析源码v2.7.0🔵 扫描:含敏感能力尚无人工评估展开查看扫描说明与证据 ↓
安全扫描自动 · 静态分析源码
v2.7.0静态扫描发现插件具备触达本地系统的能力:执行外部命令、读写/删除本地文件、读取剪贴板或密钥类环境变量(至少其一)。这是能力清单,不是危险判定——具体能力项与证据见下方,安装前请自行判断是否需要。
可执行外部命令读写/删除本地文件发起外部网络请求
查看扫描证据(共 109 处,展示前 75 条)
- 写入本地文件index.js:144
if (firstOpen) mkdirSync(dir, { recursive: true, mode: 0o755 }); - 删除本地文件index.js:163
rmSync(join(dir, '.overleaf', 'state.json'), { force: true }); - 读取本地文件scripts/profile.mjs:30
const cli = candidates.find(path => existsSync(path) - 读取本地文件scripts/profile.mjs:31
&& (lstatSync(path).isFile() || lstatSync(path).isSymbolicLink())); - 执行外部命令来自配置/变量scripts/profile.mjs:37
return spawnSync(command, args, { - 读取本地文件scripts/profile.mjs:47
return lstatSync(join(base, 'profiles', profile, 'node_modules', packageName)).isSymbolicLink(); - 写入本地文件scripts/profile.mjs:56
mkdirSync(destination, { recursive: true, mode: 0o755 }); - 执行外部命令来自配置/变量scripts/profile.mjs:58
const result = spawnSync(npm, ['pack', source, '--pack-destination', destination, '--json'], { - 读取本地文件scripts/profile.mjs:73
if (!existsSync(tarball)) throw new Error(`npm pack did not create ${tarball}`); - 读取本地文件scripts/profile.mjs:103
if (!existsSync(manifestPath)) { - 读取本地文件scripts/profile.mjs:108
const metadata = JSON.parse(readFileSync(join(source, 'package.json'), 'utf8')); - 读取本地文件lib/host-modules.js:50
if (!existsSync(scope)) continue; - 发起网络请求lib/api.js:160
const response = await this.fetch(url, { - 发起网络请求lib/api.js:183
const response = await this.request('GET', '/project'); - 发起网络请求lib/api.js:198
const script = await this.request('GET', '/socket.io/socket.io.js'); - 发起网络请求lib/api.js:211
const response = await this.request('POST', '/api/project', { body: {} }); - 发起网络请求lib/api.js:218
const response = await this.request('GET', '/user/projects'); - 发起网络请求lib/api.js:229
const response = await this.request('GET', `/project/${encodeURIComponent(projectId)}/download/zip`, - 读取本地文件lib/compile.js:20
for (const entry of readdirSync(dir, { withFileTypes: true })) { - 写入本地文件lib/compile.js:72
mkdirSync(outDir, { recursive: true }); - 写入本地文件lib/compile.js:74
writeFileSync(join(localDir, 'output.pdf'), data, { mode: 0o644 }); - 写入本地文件lib/compile.js:79
mkdirSync(outDir, { recursive: true }); - 写入本地文件lib/compile.js:80
writeFileSync(join(localDir, 'output.log'), data, { mode: 0o644 }); - 读取本地文件lib/secrets.js:40
text = readFileSync(this.file, 'utf8'); - 读取本地文件lib/secrets.js:60
if ((statSync(this.file).mode & 0o077) !== 0) { - 写入本地文件lib/secrets.js:61
chmodSync(this.file, 0o600); - 写入本地文件lib/secrets.js:105
mkdirSync(dirname(this.file), { recursive: true, mode: 0o700 }); - 写入本地文件lib/secrets.js:108
writeFileSync(temp, `${JSON.stringify(body, null, 2)}\n`, { mode: 0o600 }); - 写入本地文件lib/secrets.js:109
renameSync(temp, this.file); - 删除本地文件lib/secrets.js:110
} finally { rmSync(temp, { force: true }); } - 读取本地文件lib/sync.js:30
for (const entry of readdirSync(dir, { withFileTypes: true })) { - 读取本地文件lib/sync.js:42
try { return readFileSync(join(localDir, path.split('/').join(sep))); } catch { return undefined; } - 写入本地文件lib/sync.js:93
mkdirSync(dirname(localPath), { recursive: true, mode: 0o755 }); - 写入本地文件lib/sync.js:94
writeFileSync(localPath, data, { mode: 0o644 }); - 读取本地文件lib/sync.js:104
if (existsSync(localPath)) { - 删除本地文件lib/sync.js:110
rmSync(localPath, { force: true }); - 读取本地文件lib/store.js:29
return JSON.parse(readFileSync(file, 'utf8')); - 写入本地文件lib/store.js:37
mkdirSync(dirname(file), { recursive: true, mode: 0o700 }); - 写入本地文件lib/store.js:40
writeFileSync(temp, `${JSON.stringify(value, null, 2)}\n`, { mode }); - 写入本地文件lib/store.js:41
renameSync(temp, file); - 删除本地文件lib/store.js:42
} finally { rmSync(temp, { force: true }); } - 读取本地文件lib/store.js:112
return existsSync(statePath(localDir)); - 读取本地文件ui/host.js:155
hasPdf: existsSync(join(localDir, 'output.pdf')), - 读取本地文件ui/host.js:197
for (const entry of readdirSync(dir, { withFileTypes: true })) { - 读取本地文件ui/host.js:202
const info = statSync(join(dir, entry.name)); - 读取本地文件ui/host.js:216
const info = statSync(file); - 读取本地文件ui/host.js:218
const buffer = readFileSync(file); - 读取本地文件ui/host.js:236
try { info = statSync(file); } catch { continue; } - 写入本地文件ui/host.js:261
mkdirSync(dirname(file), { recursive: true }); - 写入本地文件ui/host.js:262
writeFileSync(file, combined.text, { mode: 0o644 }); - 读取本地文件lib/live.js:291
if (!existsSync(file)) continue; - 读取本地文件lib/live.js:294
if (model !== undefined && readFileSync(file, 'utf8') !== model.baseText) dirty.add(entity.path); - 读取本地文件lib/live.js:295
} else if (this.binaryHashes.get(entity.path) !== sha256(readFileSync(file))) { - 写入本地文件lib/live.js:338
if (path !== '') mkdirSync(this.fileOf(path), { recursive: true }); - 读取本地文件lib/live.js:341
if (entity.type === 'file' && existsSync(this.fileOf(entity.path))) { - 读取本地文件lib/live.js:342
this.binaryHashes.set(entity.path, sha256(readFileSync(this.fileOf(entity.path)))); - 读取本地文件lib/live.js:373
const localBefore = existsSync(localFile) ? readFileSync(localFile, 'utf8') : undefined; - 写入本地文件lib/live.js:824
mkdirSync(this.fileOf(rel), { recursive: true }); - 写入本地文件lib/live.js:881
mkdirSync(this.fileOf(path), { recursive: true }); - 删除本地文件递归lib/live.js:915
rmSync(this.fileOf(prefix), { recursive: true, force: true }); - 写入本地文件lib/live.js:946
mkdirSync(dirname(file), { recursive: true }); - 写入本地文件lib/live.js:947
writeFileSync(file, text, { mode: 0o644 }); - 写入本地文件lib/live.js:952
mkdirSync(dirname(file), { recursive: true }); - 删除本地文件递归lib/live.js:966
rmSync(source, { recursive: true, force: true }); - 删除本地文件递归lib/live.js:1015
rmSync(this.fileOf(entity.path), { recursive: true, force: true }); - 写入本地文件lib/workspace-files.js:35
mkdirSync(dirname(absolute), { recursive: true }); - 写入本地文件lib/workspace-files.js:37
writeFileSync(absolute, '', { flag: 'wx', mode: 0o644 }); - 读取本地文件lib/workspace-files.js:52
if (existsSync(absolute)) throw new Error('同名文件或文件夹已存在。'); - 写入本地文件lib/workspace-files.js:54
mkdirSync(absolute, { recursive: true }); - 发起网络请求lib/socket.js:64
async fetch(url, init = {}) { - 发起网络请求lib/socket.js:65
const response = await this.client.fetch(url, { - 发起网络请求lib/socket.js:90
const response = await this.fetch(`${this.base}/socket.io/1/${query}`); - 发起网络请求lib/socket.js:138
response = await this.fetch(`${this.base}/socket.io/1/xhr-polling/${this.sid}?projectId=${encodeURIComponent(this.projectId)}&t=${Date.now()}`); - 发起网络请求lib/socket.js:222
const response = await this.fetch(`${this.base}/socket.io/1/xhr-polling/${this.sid}?t=${Date.now()}`, { - 发起网络请求lib/socket.js:246
await this.client.fetch(`${this.base}/socket.io/1/xhr-polling/${sid}?t=${Date.now()}&disconnect=1`,
扫描于 2026/11/4(0 天前) · 范围 入口闭包 + 发布文件清单 · 来源 GitHub 仓库
静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。
给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个
基于DeepSeek Harness 的 Overleaf Workshop 插件:三栏工作区、实时同步
README
由 DeepSeek 最新模型翻译生成DeepSeek Harness · Overleaf Workshop
在 DeepSeek Harness 里直接编辑 Overleaf 项目,实时双向同步。
Overleaf 工作区:左侧是项目目录树,中间是 LaTeX 编辑器,右侧是对话栏
界面示意(示例项目):左侧 Overleaf 目录,中间带高亮与自动保存的编辑器,右侧直接和智能体对话。
功能
- 实时双向同步:本地编辑、智能体修改会自动推送到 Overleaf,网页端的协作修改也会同步回本地。支持文件新建、重命名、移动和删除,以及并发编辑时的三方合并。
- 三栏编辑界面:目录树、文件编辑器、智能体对话并排显示。内置 CodeMirror 编辑器,支持 LaTeX 语法高亮、搜索、自动保存和快捷键操作。
- 在线编译与 PDF 预览:在 Overleaf 服务器上编译当前打开的 .tex 文件,生成的 output.pdf 可以直接在内置预览中查看。
- 项目与会话管理:侧边栏独立显示 Overleaf 项目及同步状态,支持快速编译、新建会话、切换历史会话和结束同步。
- 按需同步:可以随时停止实时连接,保留全部本地文件;重新进入项目即可恢复同步。实时连接不可用时,也支持手动拉取和推送。
展开完整文档(README 剩余 1 节)
DeepSeek Harness · Overleaf Workshop 在 DeepSeek Harness 里直接编辑 Overleaf 项目,实时双向同步。 Overleaf 工作区:左侧是项目目录树,中间是 LaTeX 编辑器,右侧是对话栏 界面示意(示例项目):左侧 Overleaf 目录,中间带高亮与自动保存的编辑器,右侧直接和智能体对话。 功能 - 实时双向同步:本地编辑、智能体修改会自动推送到 Overleaf,网页端的协作修改也会同步回本地。支持文件新建、重命名、移动和删除,以及并发编辑时的三方合并。 - 三栏编辑界面:目录树、文件编辑器、智能体对话并排显示。内置 CodeMirror 编辑器,支持 LaTeX 语法高亮、搜索、自动保存和快捷键操作。 - 在线编译与 PDF 预览:在 Overleaf 服务器上编译当前打开的 .tex 文件,生成的 output.pdf 可以直接在内置预览中查看。 - 项目与会话管理:侧边栏独立显示 Overleaf 项目及同步状态,支持快速编译、新建会话、切换历史会话和结束同步。 - 按需同步:可以随时停止实时连接,保留全部本地文件;重新进入项目即可恢复同步。实时连接不可用时,也支持手动拉取和推送。 安装 推荐通过 GitHub 安装: dsh plugin --profile desktop add github:chenqaq123/dsh-overleaf-workshop macOS 桌面版如果找不到 dsh 命令,可以使用应用内自带的命令行: "/Applications/DeepSeek Harness.app/Contents/Resources/runtime/cli/bin/dsh" plugin --profile desktop add github:chenqaq123/dsh-overleaf-workshop 安装完成后重启 Harness,在「插件 → 已安装」中管理插件。 登录与使用 1. 在浏览器中登录 Overleaf。 2. 按 F12 打开开发者工具,在 Network 中找到任意请求,复制请求头里的 Cookie 值。 3. 打开 Harness 侧边栏的 Overleaf → 管理,粘贴 Cookie,点击「验证并登录」。 4. 选择项目,即可进入本地工作区。 Cookie 仅保存在本机 ~/.dsh/overleaf/secrets.json。 进入项目后,可以直接编辑文件,也可以让智能体完成任务,例如: 许可证 MIT 本项目未使用 Overleaf Workshop(AGPL-3.0)的代码,相关协议实现基于独立研究。
预览分享卡片长什么样 ↓
分享 · DeepSeek Harness Hub
chenqaq123/dsh-overleaf-workshop
在编辑器内直接编辑 Overleaf 项目并实时双向同步
相关插件 · 工具 / 效率
破甲管控台kingcharleslzy-ai/dsh-purge
dsh-purge Community · DeepSeek Harness 社区维护版:宿主兼容、状态诊断、提示词管理、更新与本机备份回滚。基于小杨 / YuJunZhiXue 的 dsh-purge。
★ 4,330已汉化DeepSeek 客户端
74.5
网文长卷lingfengQAQ/webnovel-writer
基于 Claude Code 的长篇网文辅助创作系统,解决 AI 写作中的「遗忘」和「幻觉」问题,支持 200…
★ 7,636已汉化DSH
72.2
多智能体协作HKUDS/AutoSwarm
AutoSwarm: Unify Your Agents. Unify Your Context (Codex · Claude Code · DeepSeek Harness · Muse · Grok · WorkBuddy· nanobot · and more)
★ 2,349已汉化DSH
71.6
Vox 拼贴视频生成Alisa0808/vox-director
🎬 Vox Director拼贴动效导演
★ 2,129已汉化DSH
71.4
Agent 演化引擎Q00/ouroboros
智能体 OS:智能体自己变聪明,我们只守住底线:面试准入、分阶段评估、带预算的进化循环。MCP 服务器,14 种运行时:Claude Code、Codex CLI、Gemini CLI、OpenCode、Copilot、Kiro 等。
★ 6,311已汉化DSH
71.4
智能体运行框架路由HarnessRouter/harnessrouter
智能体 harness 的统一接口。
★ 3,984已汉化DSH
71.3
这是你的仓库?认领条目