把文字或图片里的几何题转成可拖动的 GeoGebra 文件
30/100
综合分
0
GitHub 星标
—
npm 周下载
—/5
用户评分
数据截至 2026/10/27 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。
安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add Jack7510/ggb-plugins-dsh该包不可直接 npm 安装,改从 GitHub 源安装(明细见下方安装检查)
状态速览
判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态信任档位:仅索引
是什么
dsh 原生插件 · other
装得上吗
本站尚未做安装检查
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
活跃:最近一次提交在 8 天前
档位由哪些信号合成
本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。
社区实装还没有人打卡 · 装过的第一个就是你
安全扫描自动 · 静态分析源码v2.7.0🔵 扫描:含敏感能力尚无人工评估展开查看扫描说明与证据 ↓
安全扫描自动 · 静态分析源码
v2.7.0静态扫描发现插件具备触达本地系统的能力:执行外部命令、读写/删除本地文件、读取剪贴板或密钥类环境变量(至少其一)。这是能力清单,不是危险判定——具体能力项与证据见下方,安装前请自行判断是否需要。
读写/删除本地文件发起外部网络请求
查看扫描证据(共 110 处,展示前 84 条)
- 读取本地文件index.js:22
const has = (root, entry) => existsSync(join(root, entry)); - 读取本地文件index.js:102
const description = parseSkill(readFileSync(skillPath, 'utf8'), skillPath).description; - 读取本地文件index.js:117
const raw = await readFile(skillPath, { encoding: 'utf8', signal: requestOptions?.signal }); - 读取本地文件dsh/installation.js:24
const read = file => JSON.parse(readFileSync(join(root, file), 'utf8')); - 读取本地文件dsh/installation.js:30
.update(readFileSync(workerSkill)).digest('hex'); - 读取本地文件dsh/installation.js:46
if (!statSync(join(root, path)).isFile()) { - 读取本地文件dsh/installation.js:69
const raw = readFileSync(installation.workerSkill, 'utf8'); - 读取本地文件dsh/installation.js:88
const runtime = JSON.parse(readFileSync( - 读取本地文件dsh/installation.js:98
if (!statSync(file).isFile() || statSync(file).size === 0) { - 读取本地文件dist/src/runtime-compatibility.js:68
const original = await readFile(path); - 读取本地文件dsh/executor.js:21
const json = async path => JSON.parse(await readFile(path, 'utf8')); - 读取本地文件dsh/executor.js:29
const info = await lstat(path); - 读取本地文件dsh/executor.js:33
const bytes = await readFile(path); - 读取本地文件dsh/executor.js:57
const info = await lstat(preview); - 读取本地文件dsh/executor.js:113
assert.equal(hash(await readFile(context.baseRef)), context.baseSha256); - 读取本地文件dsh/executor.js:124
assert.equal(hash(await readFile(context.baseRef)), context.baseSha256, - 读取本地文件dist/src/atomic-file.js:17
const previous = await lstat(path).catch(error => { - 写入本地文件dist/src/atomic-file.js:33
await rename(temporary, path); - 删除本地文件dist/src/atomic-file.js:51
await rm(temporary, { force: true }).catch(() => { }); - 写入本地文件dist/src/delivery.js:24
const save = (path, value) => writeFile(path, json(value)); - 读取本地文件dist/src/delivery.js:26
const info = await stat(path); - 读取本地文件dist/src/delivery.js:30
return JSON.parse(await readFile(path, 'utf8')); - 写入本地文件dist/src/delivery.js:92
await mkdir(request.outputDir, { recursive: true }); - 写入本地文件dist/src/delivery.js:97
await mkdir(context.temp); - 写入本地文件dist/src/delivery.js:98
await writeFile(join(context.run, 'request.json'), context.requestBytes); - 读取本地文件dist/src/delivery.js:119
const bytes = await readFile(join(context.temp, context.file)); - 写入本地文件dist/src/delivery.js:235
await mkdir(request.outputDir, { recursive: true }); - 写入本地文件dist/src/delivery.js:240
await mkdir(context.temp); - 读取本地文件dist/src/delivery.js:616
const bytes = await readFile(join(delivery, base.file)); - 读取本地文件dist/src/delivery.js:673
const bytes = await readFile(join(delivery, base.file)); - 读取本地文件dist/src/delivery.js:708
assert.equal(sha256(await readFile(join(delivery, 'request.json'))), manifest.requestSha256, 'Request checksum mismatch'); - 读取本地文件dist/src/server.js:26
const path = await realpath(resolve(runtime, pathname.slice('/runtime/'.length))); - 读取本地文件dist/src/server.js:60
let data = await readFile(asset.path); - 读取本地文件dist/src/server.js:90
const runtime = await realpath(runtimeDirectory); - 读取本地文件dist/src/doctor.js:41
const lock = JSON.parse(await readFile(join(root, 'runtime.lock.json'), 'utf8')); - 读取本地文件dist/src/doctor.js:42
const pkg = JSON.parse(await readFile(join(root, 'package.json'), 'utf8')); - 读取本地文件dist/src/browser.js:30
const lock = JSON.parse(await readFile(resolve(root, 'runtime.lock.json'), 'utf8')); - 读取本地文件dist/src/browser.js:31
const installed = JSON.parse(await readFile(resolve(root, '.runtime/runtime.json'), 'utf8')); - 发起网络请求dist/src/browser.js:69
await Promise.race([context.route('**/*', route => route.request().url().startsWith(service.url + '/') ? route.continue() : route.abort()), aborted]); - 读取本地文件dist/src/ggbfile.js:120
const info = await stat(path).catch(() => { - 读取本地文件dist/src/ggbfile.js:129
const bytes = await readFile(path); - 写入本地文件dist/src/naming.js:65
await mkdir(directory); - 读取本地文件source/dsh/executor.js:21
const json = async path => JSON.parse(await readFile(path, 'utf8')); - 读取本地文件source/dsh/executor.js:29
const info = await lstat(path); - 读取本地文件source/dsh/executor.js:33
const bytes = await readFile(path); - 读取本地文件source/dsh/executor.js:57
const info = await lstat(preview); - 读取本地文件source/dsh/executor.js:113
assert.equal(hash(await readFile(context.baseRef)), context.baseSha256); - 读取本地文件source/dsh/executor.js:124
assert.equal(hash(await readFile(context.baseRef)), context.baseSha256, - 读取本地文件source/dsh/index.js:22
const has = (root, entry) => existsSync(join(root, entry)); - 读取本地文件source/dsh/index.js:102
const description = parseSkill(readFileSync(skillPath, 'utf8'), skillPath).description; - 读取本地文件source/dsh/index.js:117
const raw = await readFile(skillPath, { encoding: 'utf8', signal: requestOptions?.signal }); - 读取本地文件source/dsh/installation.js:24
const read = file => JSON.parse(readFileSync(join(root, file), 'utf8')); - 读取本地文件source/dsh/installation.js:30
.update(readFileSync(workerSkill)).digest('hex'); - 读取本地文件source/dsh/installation.js:46
if (!statSync(join(root, path)).isFile()) { - 读取本地文件source/dsh/installation.js:69
const raw = readFileSync(installation.workerSkill, 'utf8'); - 读取本地文件source/dsh/installation.js:88
const runtime = JSON.parse(readFileSync( - 读取本地文件source/dsh/installation.js:98
if (!statSync(file).isFile() || statSync(file).size === 0) { - 读取本地文件source/src/atomic-file.ts:22
const previous = await lstat(path).catch(error => { - 写入本地文件source/src/atomic-file.ts:37
await rename(temporary, path); - 删除本地文件source/src/atomic-file.ts:48
await rm(temporary, {force: true}).catch(() => {}); - 读取本地文件source/src/browser.ts:89
const lock = JSON.parse(await readFile(resolve(root, 'runtime.lock.json'), 'utf8')) as { version: string; sha256: string }; - 读取本地文件source/src/browser.ts:90
const installed = JSON.parse(await readFile(resolve(root, '.runtime/runtime.json'), 'utf8')) as typeof lock; - 发起网络请求source/src/browser.ts:122
await Promise.race([context.route('**/*', route => route.request().url().startsWith(service.url + '/') ? route.continue() : route.abort()), aborted]); - 写入本地文件source/src/delivery.ts:32
const save = (path: string, value: unknown) => writeFile(path, json(value)); - 读取本地文件source/src/delivery.ts:34
const info = await stat(path); - 读取本地文件source/src/delivery.ts:37
return JSON.parse(await readFile(path, 'utf8')); - 写入本地文件source/src/delivery.ts:139
await mkdir(request.outputDir, { recursive: true }); - 写入本地文件source/src/delivery.ts:145
await mkdir(context.temp); - 写入本地文件source/src/delivery.ts:146
await writeFile(join(context.run, 'request.json'), context.requestBytes); - 读取本地文件source/src/delivery.ts:176
const bytes = await readFile(join(context.temp, context.file)); - 写入本地文件source/src/delivery.ts:318
await mkdir(request.outputDir, { recursive: true }); - 写入本地文件source/src/delivery.ts:324
await mkdir(context.temp); - 读取本地文件source/src/delivery.ts:768
const bytes = await readFile(join(delivery, base.file)); - 读取本地文件source/src/delivery.ts:841
const bytes = await readFile(join(delivery, base.file)); - 读取本地文件source/src/delivery.ts:882
assert.equal(sha256(await readFile(join(delivery, 'request.json'))), manifest.requestSha256, 'Request checksum mismatch'); - 读取本地文件source/src/doctor.ts:45
const lock = JSON.parse(await readFile(join(root, 'runtime.lock.json'), 'utf8')); - 读取本地文件source/src/doctor.ts:46
const pkg = JSON.parse(await readFile(join(root, 'package.json'), 'utf8')); - 读取本地文件source/src/ggbfile.ts:138
const info = await stat(path).catch(() => { - 读取本地文件source/src/ggbfile.ts:147
const bytes = await readFile(path); - 写入本地文件source/src/naming.ts:74
await mkdir(directory); - 读取本地文件source/src/runtime-compatibility.ts:82
const original = await readFile(path); - 读取本地文件source/src/server.ts:55
const path = await realpath( - 读取本地文件source/src/server.ts:95
let data: Buffer = await readFile(asset.path); - 读取本地文件source/src/server.ts:128
const runtime = await realpath(runtimeDirectory);
扫描于 2026/11/4(0 天前) · 范围 入口闭包 + 发布文件清单 · 来源 GitHub 仓库
静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。
给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个
README
由 DeepSeek 最新模型翻译生成ggb-plugins
把文字或图片中的二维数学题变成可交互的 GeoGebra 文件。宿主 Agent(Codex 或 DeepSeek Harness)理解题意并编写原生 Algebra/CAS 程序;本项目在本地执行、逐条件核验、导出 .ggb、重新加载,并交付文件、核验报告和截图。
支持中文和英文。Agent 根据你的偏好和上下文选择工作语言,保留题目原文,且只分析条件与构图方法,不替你给出题目答案。
演示
拖动 C 时圆周角保持为圆心角的一半
拖动 C 时,圆周角保持为圆心角的一半;构造、依赖和核验结果同步更新。
需要什么
| 依赖 | 用途 |
| Codex 或 DeepSeek Harness(DSH) | 理解题意并编写原生 GeoGebra 程序 |
| Node.js 22+ 与 pnpm 11 | 运行本地 CLI、准备依赖 |
| curl 与 unzip | 下载并解压固定版本的 GeoGebra 运行时 |
| Google Chrome 或 Microsoft Edge | 核验时以 headless 方式驱动 applet |
不需要额外模型密钥。安装需要网络;GeoGebra 与浏览器不随包再分发。构建发布包时另外使用 zip、tar 与 npm。
展开完整文档(README 剩余 1 节)
ggb-plugins 把文字或图片中的二维数学题变成可交互的 GeoGebra 文件。宿主 Agent(Codex 或 DeepSeek Harness)理解题意并编写原生 Algebra/CAS 程序;本项目在本地执行、逐条件核验、导出 .ggb、重新加载,并交付文件、核验报告和截图。 支持中文和英文。Agent 根据你的偏好和上下文选择工作语言,保留题目原文,且只分析条件与构图方法,不替你给出题目答案。 演示 拖动 C 时圆周角保持为圆心角的一半 拖动 C 时,圆周角保持为圆心角的一半;构造、依赖和核验结果同步更新。 需要什么 | 依赖 | 用途 | | Codex 或 DeepSeek Harness(DSH) | 理解题意并编写原生 GeoGebra 程序 | | Node.js 22+ 与 pnpm 11 | 运行本地 CLI、准备依赖 | | curl 与 unzip | 下载并解压固定版本的 GeoGebra 运行时 | | Google Chrome 或 Microsoft Edge | 核验时以 headless 方式驱动 applet | 不需要额外模型密钥。安装需要网络;GeoGebra 与浏览器不随包再分发。构建发布包时另外使用 zip、tar 与 npm。 安装 当前版本为 v0.8.5,提供 Codex ZIP 与 DSH npm 包。Codex 包尚未提交公共插件目录,但 Release ZIP 可直接安装;版本说明见 0.8.5 发布记录。 - Codex:安装与升级说明。 - DSH:独立 headless profile 安装说明。 DSH bundle 已发布到 npm: profile=desktop # DSH 插件中心或 Web 宿主改为 web dsh plugin --profile "$profile" add ggb-plugins-dsh@0.8.5 node ~/.dsh/profiles/$profile/node_modules/ggb-plugins-dsh/scripts/setup-plugin.mjs 桌面用户可以把这一句安装指令粘贴到 DSH 对话框,由 DSH 代为安装。 想在 DSH 中浏览并安装,启用 Experimental plugins → Custom plugin markets,然后在 Discover → Add index source 添加: https://cdn.jsdelivr.net/gh/Jack7510/ggb-plugins@main/docs/market/index.json 两个客户端各自安装,共用同一套执行与核验管线。两份说明都以运行依赖准备(setup-plugin,会报告实际使用的浏览器)和就绪检查(doctor)结束。 第一道题 启用插件后,在新的宿主会话中直接描述题目,图片可以随题附上。 用 GeoGebra 作三角形 ABC,取 AB 的中点 M,连接 CM,把中线标红。拖动 A 验证中点和中线联动,保存文件并打开交互预览。 构造、重载和全部自动核验都以 headless 运行,不打开中间窗口。失败或无法核验的必需条件会阻止交付,而不是被跳过;失败会保留诊断,便于下一轮修正。必要条件缺失或歧义时 Agent 先澄清;未指定坐标时它会说明自行选择的初始构型。Agent 可以自行决定什么、不能决定什么,见 Skill。 你会得到什么 成功运行写出一个交付目录: | 文件 | 用途 | | <题目>.ggb | 按题目命名的原生文件,可在 GeoGebra 中打开、查看并继续编辑 | | verification.json | 逐条件结果:构造、重载与交互样本 | | preview.png | 交付构型截图 | | request.json、manifest.json | 输入留档与交付清单 | 报告会说明实际执行了哪些检查、有限交互样本覆盖到哪里,不会声称构成一般性证明。 交付目录位于 <outputDir>/<题目>/delivery/;<题目> 同时是 GGB 文件名,同名题目自动追加 -2、-3,不覆盖旧文件。 交互预览 预览加载同一份交付的 GGB,支持适用的点拖动、参数变化与缩放,且不回写交付文件。预览进程在页面加载后自动退出,窗口继续可用;需要重新加载时再执行一次 preview;一次性宿主退出后进程可能被回收。自动复核加 --headless。 直接使用 CLI 宿主会替你调用这个 CLI,其他本地工具也可以直接驱动: node <installed-plugin>/dist/src/cli.js doctor node <installed-plugin>/dist/src/cli.js inspect --ggb /absolute/base.ggb node <installed-plugin>/dist/src/cli.js build --request /absolute/request.json node <installed-plugin>/dist/src/cli.js preview --delivery /absolute/delivery 已有 GGB 需要改颜色、线型、填充、可见性,或继续构造(增加对象、修改独立数值或坐标)时,在请求中声明 base;inspect 列出对象清单、当前值以及请求必须写入的摘要。删除、重命名和视图修改不支持。请求编写方式见 能力契约。 从源码运行 先满足上表依赖,然后: pnpm install --frozen-lockfile pnpm setup:runtime pnpm build pnpm demo pnpm demo 会把内置三角形示例构造到 output/。验证与维护命令、Agent 的工作规则以及发布流程都在 AGENTS.md,这里不重复。 仓库结构 - src/:CLI、执行、核验与交付管线。 - viewer/:承载 GeoGebra applet 的本地页面。 - skills/:两个宿主共用的 Skill。 - codex/、dsh/:各宿主的插件资产、安装说明与验收记录。 - examples/、tests/:可运行输入与回归用例。 - scripts/:依赖准备、两种打包与覆盖记录工具。 - docs/:需求与设计、重要修改记录与跨客户端验收记录;历史阶段结果见归档索引。 支持范围与边界 - 支持:二维几何、函数、方程、微积分、列表矩阵与统计,中英文均可。 - 不支持:三维构图、无法声明基线的外部 GGB 续题、一般数学证明。 - 原生命令可以接入,不等于全部命令与重载都已验收;边界见 命令覆盖记录。 - 数值采样与未决 CAS 结果是证据,不是证明。 项目采用 MIT 许可,源码位于 github.com/Jack7510/ggb-plugins。GeoGebra 的独立许可与归属见 第三方说明。
预览分享卡片长什么样 ↓
分享 · DeepSeek Harness Hub
Jack7510/ggb-plugins-dsh
把文字或图片里的几何题转成可拖动的 GeoGebra 文件
相关插件 · 其他
模型破甲清洗HunYiSage/dsh-purge
⚔️ DeepSeek Harness 网络安全红队工具dsh-purge
★ 16,993已汉化DeepSeek 客户端
73
女娲蒸馏alchaincyf/nuwa-skill
输入名人名字,提炼其思维模型与决策方式供你调用
★ 37,308已汉化DSH
72
逆向分析桥接Fanqi89/dsh-rea
REA(Reverse Engineer Anything)MCP 桥接,用来把 REA 逆向工具接入 DSH 插件
★ 51已汉化DSH
72
语音女友beiyege-01/dsh-voice-ai-girlfriend
语音 AI 女友Voice AI girlfriend for DeepSeek Harness:Whisper…
★ 888已汉化DSH
71.6
红队越狱测试套件Minglink/dsh-infinite-gen-5
DeepSeek v4.1 flash 逆向工具无限五代 求 Star 收藏 ⭐欢迎大家提交项目的改进
★ 3,759已汉化DSH
71.4
协同办公空间dream-num/univer-workspace
一个让人类与 AI Agent 共同创作、协作和审阅的开源 Office 工作空间。
★ 2,269已汉化DSH
70.8
这是你的仓库?认领条目