把一份需求拆成矢量、位图、动效与影片工程并调度交付
30.7/100
综合分
1
GitHub 星标
—
npm 周下载
—/5
用户评分
数据截至 2026/10/19 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。
安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add full-aigc-plugins/artcraft-plugin该包不可直接 npm 安装,改从 GitHub 源安装(明细见下方安装检查)
状态速览
判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态信任档位:已验证
是什么
dsh 原生插件 · vision
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
活跃:最近一次提交在 16 天前
档位由哪些信号合成
本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。
社区实装还没有人打卡 · 装过的第一个就是你
安全扫描自动 · 静态分析源码v2.7.0🔵 扫描:含敏感能力尚无人工评估展开查看扫描说明与证据 ↓
安全扫描自动 · 静态分析源码
v2.7.0静态扫描发现插件具备触达本地系统的能力:执行外部命令、读写/删除本地文件、读取剪贴板或密钥类环境变量(至少其一)。这是能力清单,不是危险判定——具体能力项与证据见下方,安装前请自行判断是否需要。
可执行外部命令读写/删除本地文件发起外部网络请求
查看扫描证据(共 121 处,展示前 75 条)
- 读取本地文件dsh/lib/index.js:139
if (!existsSync(SKILLS_DIR)) return [] - 读取本地文件dsh/lib/index.js:143
entries = await readdir(SKILLS_DIR, { withFileTypes: true }) - 读取本地文件dsh/lib/index.js:151
if (!existsSync(file)) continue - 读取本地文件dsh/lib/index.js:153
const parsed = parseSkill(await readFile(file, 'utf8')) - 读取本地文件dsh/lib/index.js:179
if (!existsSync(COMMANDS_DIR)) return [] - 读取本地文件dsh/lib/index.js:183
entries = await readdir(COMMANDS_DIR, { withFileTypes: true }) - 写入本地文件dsh/lib/index.js:271
mkdir(DATA_DIR, { recursive: true }).catch(() => {}) - 读取本地文件src/adapters/collected_output.ts:13
const bytes=(await stat(join(root,location))).size; - 读取本地文件src/adapters/collected_output.ts:18
const bytes=await readFile(join(root,'manifest.json')); - 读取本地文件src/adapters/font_output.ts:20
const bytes=(await stat(join(root,location))).size; - 读取本地文件src/adapters/font_output.ts:24
const content=await readFile(join(root,location)); - 读取本地文件src/adapters/public_skill.ts:74
const bytes=await readFile(join(source.root,'manifest.json')); - 读取本地文件src/adapters/public_skill.ts:83
await verifyArtifact({...source.artifact,location,sha256:digest,version:digest,bytes:(await stat(join(source.root,location))).size,mediaType:'applicat - 读取本地文件src/adapters/public_skill.ts:121
if(await readFile(locked.python).then(hash)!==locked.pythonSha256)throw new Error('launcher_identity_mismatch'); - 读取本地文件src/adapters/public_skill.ts:123
if(!isAbsolute(file.path) || await readFile(file.path).then(hash)!==file.sha256)throw new Error('launcher_file_identity_mismatch'); - 写入本地文件src/adapters/public_skill.ts:126
await mkdir(root,{recursive:true}); - 写入本地文件src/adapters/public_skill.ts:127
await writeFile(planFile,JSON.stringify(plan),'utf8'); - 写入本地文件src/adapters/public_skill.ts:129
await writeFile(strictRunner,strictMcpRunner,'utf8'); - 读取本地文件src/adapters/public_skill.ts:135
args.push(asset.kind==='lut'?'--lut-asset':asset.input.artifact.mediaType===imageSequenceMime?(segmented?'--segmented-sequence-asset':'--sequence-asse - 读取本地文件src/adapters/public_skill.ts:140
protocolVersion:'craft-artifact/v1',assetId,version:sha256,sha256,bytes:(await stat(join(delivery,location))).size,mediaType,producerTaskId:taskId,sou - 读取本地文件src/adapters/video_factory.ts:27
pluginRoot=await realpath(pluginRoot); - 读取本地文件src/adapters/video_factory.ts:28
const manifest=JSON.parse(await readFile(join(pluginRoot,'plugin.json'),'utf8')); - 读取本地文件src/adapters/video_factory.ts:29
const pkg=JSON.parse(await readFile(join(pluginRoot,'package.json'),'utf8')); - 读取本地文件src/adapters/video_factory.ts:32
const add=async(path:string)=>{if(!(await lstat(path)).isFile())throw new Error('video_factory_source_invalid');files.push({path,sha256:hash(await rea - 读取本地文件src/adapters/video_factory.ts:32
const add=async(path:string)=>{if(!(await lstat(path)).isFile())throw new Error('video_factory_source_invalid');files.push({path,sha256:hash(await rea - 读取本地文件src/adapters/video_factory.ts:33
const walk=async(path:string)=>{for(const entry of await readdir(path,{withFileTypes:true})){const child=join(path,entry.name);if(entry.isSymbolicLink - 写入本地文件src/adapters/video_factory.ts:56
const root=join(locked.outputRoot,hash(taskId));await mkdir(root,{recursive:true}); - 写入本地文件src/adapters/video_factory.ts:60
await writeFile(planFile,JSON.stringify(plan)); - 写入本地文件src/adapters/video_factory.ts:62
await writeFile(job,JSON.stringify(value)); - 读取本地文件src/adapters/video_factory_driver.ts:8
const job=JSON.parse(readFileSync(process.argv[2],'utf8')); - 读取本地文件src/adapters/video_factory_driver.ts:9
if(hash(readFileSync(job.input.path))!==job.input.sha256)throw new Error('video_factory_input_changed'); - 执行外部命令来自配置/变量src/adapters/video_factory_driver.ts:11
const invoke=(args:string[])=>JSON.parse(execFileSync(job.nodeExecutable,[job.entry,...args],{encoding:'utf8',env,maxBuffer:16*1024*1024,timeout:30000 - 读取本地文件src/adapters/video_factory_driver.ts:15
if(hash(readFileSync(job.input.path))!==job.input.sha256)throw new Error('video_factory_input_changed'); - 读取本地文件src/adapters/video_factory_driver.ts:16
writeFileSync(job.output,JSON.stringify({schema:'craft-video-evaluation/v1',input:job.input,planSha256:hash(readFileSync(job.planFile)),result})+'\n', - 写入本地文件src/adapters/video_factory_driver.ts:16
writeFileSync(job.output,JSON.stringify({schema:'craft-video-evaluation/v1',input:job.input,planSha256:hash(readFileSync(job.planFile)),result})+'\n', - 读取本地文件src/artifacts/project_package.ts:14
const base=await realpath(root),path=join(base,location),actual=await realpath(path),delta=relative(base,actual); - 读取本地文件src/artifacts/project_package.ts:15
if(!delta || delta.startsWith('../') || isAbsolute(delta) || !(await lstat(path)).isFile())throw new Error('package_location_invalid'); - 读取本地文件src/artifacts/project_package.ts:19
const before=await lstat(path),digest=createHash('sha256');let bytes=0; - 读取本地文件src/artifacts/project_package.ts:21
for await(const chunk of createReadStream(path)){bytes+=(chunk as Buffer).length;digest.update(chunk);} - 读取本地文件src/artifacts/project_package.ts:22
const after=await lstat(path); - 读取本地文件src/artifacts/project_package.ts:40
const text=await readFile(await filePath(root,'project.json')); - 写入本地文件src/artifacts/project_package.ts:94
await mkdir(dirname(destination),{recursive:true}); - 写入本地文件src/artifacts/project_package.ts:101
await mkdir(dirname(join(stage,location)),{recursive:true});await writeFile(join(stage,location),buffer,{flag:'wx',mode:0o600}); - 写入本地文件src/artifacts/project_package.ts:101
await mkdir(dirname(join(stage,location)),{recursive:true});await writeFile(join(stage,location),buffer,{flag:'wx',mode:0o600}); - 写入本地文件src/artifacts/project_package.ts:107
await mkdir(dirname(join(stage,target)),{recursive:true}); - 写入本地文件src/artifacts/project_package.ts:108
await copyFile(path,join(stage,target),constants.COPYFILE_EXCL); - 写入本地文件src/artifacts/project_package.ts:151
const text=json(manifest),digest=hash(text);await writeFile(join(stage,'project.json'),text,{flag:'wx',mode:0o600}); - 删除本地文件递归src/artifacts/project_package.ts:161
await rm(stage,{recursive:true,force:true}); - 删除本地文件src/artifacts/project_package.ts:162
if(reservedInode!==undefined){try{if((await lstat(destination)).ino===reservedInode)await rmdir(destination);}catch{}} - 读取本地文件src/cli.ts:16
const version=JSON.parse(readFileSync(new URL('../package.json',import.meta.url),'utf8')).version; - 读取本地文件src/cli.ts:40
await access(flags.database); - 读取本地文件src/cli.ts:53
const registry=JSON.parse(await readFile(flags.registry,'utf8')); - 读取本地文件src/cli.ts:60
const plan=JSON.parse(await readFile(flags.plan,'utf8')); - 写入本地文件src/cli.ts:73
await mkdir(dirname(flags.database),{recursive:true}); - 读取本地文件src/planning/film_duration.ts:24
const manifestBytes=await readFile(join(root,'manifest.json')); - 读取本地文件src/planning/film_duration.ts:34
const bytes=await readFile(join(root,location)); - 读取本地文件src/planning/native_brief_output.ts:17
const manifestBytes=await readFile(join(root,'manifest.json')); - 读取本地文件src/planning/native_brief_output.ts:27
const bytes=await readFile(join(root,'native.json')); - 读取本地文件src/planning/native_brief_output.ts:52
const image=await readFile(join(root,output.location)); - 读取本地文件src/planning/photo_variant_output.ts:27
const manifestBytes=await readFile(join(root,'manifest.json')); - 读取本地文件src/planning/photo_variant_output.ts:36
const bytes=await readFile(join(root,name));if(digest(bytes)!==expected)throw new Error('photo_variant_evidence_stale');return JSON.parse(bytes.toStri - 发起网络请求src/planning/workflow_engine.ts:55
validateTask(this.request(plan,node,'preflight','preflight',[])); - 发起网络请求src/planning/workflow_engine.ts:164
const request=this.request(plan,node,taskId,'wf-node:'+planHash({key,id,fingerprint}),inputs); - 读取本地文件src/protocol/contracts.ts:15
const taskSchema: Schema = JSON.parse(readFileSync(new URL('../../schemas/craft-task-v1.json', import.meta.url), 'utf8')); - 读取本地文件src/protocol/contracts.ts:16
const artifactSchema: Schema = JSON.parse(readFileSync(new URL('../../schemas/craft-artifact-v1.json', import.meta.url), 'utf8')); - 读取本地文件src/protocol/contracts.ts:81
const schema=JSON.parse(readFileSync(new URL('../../schemas/craft-exchange-loss-v1.json',import.meta.url),'utf8')); - 读取本地文件src/protocol/contracts.ts:115
const base = await realpath(root); - 读取本地文件src/protocol/contracts.ts:116
const target = await realpath(resolve(base, location)); - 读取本地文件src/protocol/contracts.ts:138
const target=await allowedPath(root,native.location),before=await stat(target); - 读取本地文件src/protocol/image_sequence.ts:41
if((await lstat(current)).isSymbolicLink())invalid('symlink'); - 读取本地文件src/protocol/image_sequence.ts:42
for(const part of location.split('/')){current=join(current,part);if((await lstat(current)).isSymbolicLink())invalid('symlink');} - 读取本地文件src/protocol/image_sequence.ts:43
const before=await lstat(target);if(!before.isFile()||before.size>4*1024*1024)invalid('descriptor_limit'); - 读取本地文件src/protocol/image_sequence.ts:44
const content=await readFile(target);if(content.length!==before.size||sha(content)!==expectedSha)invalid('descriptor_changed'); - 读取本地文件src/protocol/image_sequence.ts:65
if(!isDeepStrictEqual((await readdir(directory)).sort(),expected.sort()))invalid('file_set'); - 读取本地文件src/protocol/image_sequence.ts:67
const path=join(directory,frame.location),beforeFrame=await lstat(path);
扫描于 2026/11/3(0 天前) · 范围 入口闭包 + 全包扫描 · 来源 GitHub 仓库
静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。
给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个
从一份简报出发,统筹 VectorCraft、PhotoCraft、EffectCraft 和 FilmCraft 项目。
README
由 DeepSeek 最新模型翻译生成ArtCraft
插件市场导航
本插件所属分类:AIGC 内容创作。
| 分类 | 插件市场入口 | 用途 |
| 全栈开发 | Full Stack Plugins | 架构与 UI 设计、代码理解、质量检查、代码审查、流程治理与服务器运维 |
| AIGC 内容创作 | Full AIGC Plugins | 图像、视频、音频、音乐、3D 与多模态内容创作 |
把一份需求变成相互协同的 VectorCraft、PhotoCraft、EffectCraft 与 FilmCraft 工程,并保留冻结计划、持久账本与哈希绑定的交付证据。
项目定位
ArtCraft 是四个 -craft 创作工具的编排层:把混合需求(品牌图形、海报、动态片头、带字幕短片)拆成依赖图,安装该图所需的固定运行时与领域技能,以“每个工程一个写入者”的方式执行,并完整保留原生工程、素材摘要与回执。
它不是新编辑器。矢量文档归 VectorCraft,位图工程归 PhotoCraft,合成归 EffectCraft,时间线归 FilmCraft;ArtCraft 负责路由、调度、修订范围、打包与审阅证据。剪映有独立插件,不在本插件范围内。
展开完整文档(README 剩余 1 节)
ArtCraft
插件市场导航
本插件所属分类:AIGC 内容创作。
| 分类 | 插件市场入口 | 用途 |
| 全栈开发 | Full Stack Plugins | 架构与 UI 设计、代码理解、质量检查、代码审查、流程治理与服务器运维 |
| AIGC 内容创作 | Full AIGC Plugins | 图像、视频、音频、音乐、3D 与多模态内容创作 |
把一份需求变成相互协同的 VectorCraft、PhotoCraft、EffectCraft 与 FilmCraft 工程,并保留冻结计划、持久账本与哈希绑定的交付证据。
项目定位
ArtCraft 是四个 -craft 创作工具的编排层:把混合需求(品牌图形、海报、动态片头、带字幕短片)拆成依赖图,安装该图所需的固定运行时与领域技能,以“每个工程一个写入者”的方式执行,并完整保留原生工程、素材摘要与回执。
它不是新编辑器。矢量文档归 VectorCraft,位图工程归 PhotoCraft,合成归 EffectCraft,时间线归 FilmCraft;ArtCraft 负责路由、调度、修订范围、打包与审阅证据。剪映有独立插件,不在本插件范围内。
| 11 个技能 | 4 个原生领域 | 1 条执行通道 | macOS arm64 |
| 路由与生命周期 | 矢量、位图、动效、影片 | artcraft-harness 脚本 | 唯一已验证平台 |
状态与版本
0.1.0-dev.142+codex.20261018 · 开发预览 · project-status.json → marketplaceEligible: false、supportedPluginHosts: []。
安装
前置条件
- macOS arm64。这是唯一具备首用证据的平台,其他平台不作承诺。
- PATH 上有 Python 3.11 或更新版本。固定 Node 运行时由 bootstrap 脚本自行安装,不需要全局 Node。
- 不需要 sudo,不修改 PATH:安装落在用户数据目录(默认 ~/.local/share/craft-runtimes,可用 --runtime-home 或 CRAFT_RUNTIME_HOME 指定)。
- 首次使用需要网络,或通过 --node-archive、--bundle-dir、--native-archive-dir 提供固定的离线制品。
开发安装
codex plugin marketplace add full-aigc-plugins/artcraft-plugin
codex plugin add artcraft@full-aigc-plugins-artcraft
project-status.json 仍记录 marketplaceEligible: false,且 supportedPluginHosts 为空,因此请把它当作 0.1.0-dev. 候选的开发安装;本包没有面向生产的市场条目。
仓库带有 Codex(.codex-plugin/)、Claude Code(.claude-plugin/)、ZCode(.zcode-plugin/)与 Kimi(kimi.plugin.json)清单,但本候选尚未通过宿主发现验收。
快速开始
把 HARNESS_DIR 指向宿主实际加载的技能目录,然后安装固定运行时。系统解释器和 PATH 都不会被修改。
: "${HARNESS_DIR:?请设为已加载 artcraft-harness 的 SKILL.md 所在目录}"
python3 -I -B "$HARNESS_DIR/scripts/bootstrap.py" --runtime-only
bootstrap 返回包含 nodeExecutable 与 entryPoint 的 JSON;此时 skills 为空,因为还没有安装领域运行时。接着运行内置的四领域示例,再核对账本与重新打开的原生工程:
python3 "$HARNESS_DIR/scripts/workflow.py" \
"$SKILL_DIR/examples/brand-campaign.json" \
--output /absolute/path/brand-project \
--authorization brand-project-authorized \
--asset voice=/absolute/path/voice.wav
flowchart LR
A[需求与素材] --> B[artcraft-use 拆解路由]
B --> C[固定运行时与领域技能]
C --> D[冻结计划、SQLite 账本、DAG]
D --> E[矢量 / 位图 / 动效 / 影片工程]
E --> F[交付包与审阅证据]
示例需要真实的 voice WAV。没有音频时,应修改计划并去掉 audioRequired,而不是为了通过交付检查而生成假配音。
可完成的工作
| 工作流 | 内置路径 | 可验证输出 |
| 混合品牌项目 | artcraft-use → harness workflow | 四个原生工程、收集素材、预览与交付账本 |
| 替换 Logo 或素材 | artcraft-cli-revise | 受影响节点重建、无关节点复用、旧交付保留 |
| 恢复中断的任务 | artcraft-cli-recover | 采用原执行、不重放写入、保留停止证据 |
| 打包并迁移 | artcraft-cli-deliver | 移动后、删除原件后仍可核验的交付包 |
| 审阅混合交付 | artcraft-cli-review | 绑定当前插件与素材版本的具名观察记录 |
| 查询原生能力 | artcraft-cli → 领域命令组件 | 带已安装版本真实参数的命令目录 |
技能
| 技能 | 作用 |
| artcraft-use | 默认入口:拆解需求、选择工具、依赖交接与交付核验 |
| artcraft-cli | 查询公开 CLI 能力,执行明确命令与诊断 |
| artcraft-cli-setup | 首次安装、摘要校验、版本检查与缺失运行时排障 |
| artcraft-cli-plan | 规划品牌、海报、片头与宣传片的工具、DAG 与交付约束 |
| artcraft-cli-execute | 执行已有计划,核对输入版本与并发写入 |
| artcraft-cli-assets | 登记素材摘要、来源与子工程依赖 |
| artcraft-cli-revise | 替换 Logo 或资产,修改原生子工程并更新下游节点 |
| artcraft-cli-recover | 检查任务状态、取消原任务、调度器退出后恢复 |
| artcraft-cli-deliver | 收集原生工程、素材、计划与证据,迁移后核验 |
| artcraft-cli-review | 检查技术证据与视觉、文案、音频一致性 |
| artcraft-harness | 唯一的执行实现:bootstrap、workflow、审阅、修订、打包 |
配置
| 变量 / 参数 | 用途 |
| HARNESS_DIR | 已加载 artcraft-harness 技能的绝对目录;所有脚本从 $HARNESS_DIR/scripts/ 执行 |
| SKILL_DIR | 已加载领域 SKILL.md 所在目录;仅用于该技能的 examples/ 与 references/ |
| CRAFT_RUNTIME_HOME / --runtime-home | 隔离的运行时安装根目录 |
| --authorization | 既有任务授权范围的引用,不是凭据 |
| --output | 绝对输出目录;必须是新目录,已归属的目录不会被覆盖 |
本包自身不声明 MCP server(没有 mcp.json)。全部流程通过 harness 脚本与固定的原生 CLI 执行。
架构与安全
- 技能源码位于独立的 artcraft-skills 仓库,以锁定快照形式进入插件;skills.lock.json 固定源码提交与每个技能的 SHA-256。
- 受信配置固定解释器、脚本与原生可执行文件路径。计划载荷无法指定 shell、解释器或可执行文件。
- Python 以隔离模式运行且不写字节码缓存。每个工程目录只有一个写入者;计划修订被冻结,输入在使用前重新核对。
- 未知结果一律不重放:中断的原生写入保留租约,必须先完成核对。
- 证据是带哈希的单次运行 JSON;docs/README.md 是架构文档索引,行为规范见 OpenSpec。
故障排查
| 现象 | 处理方式 |
| 返回 unsupported_platform | 仅接受 macOS arm64;不要安装其他平台制品 |
| 下载或摘要不匹配 | 固定制品缺失或被改动;恢复网络,或提供已核验的离线制品 |
| 返回 runtime_upgrade_busy | 先在旧运行时上完成或可信停止任务,再迁移;不要删除租约 |
| 缺少 voice 素材 | 修改计划并去掉 audioRequired;不要合成配音 |
| 保存结果未知 | 读取 failure.json、暂存工程与停止证据;不要重跑同一写入 |
| 需要 Image Factory 或剪映 | 两者都未接入;剪映请使用其独立插件 |
升级
codex plugin marketplace upgrade full-aigc-plugins-artcraft
codex plugin add artcraft@full-aigc-plugins-artcraft
运行时身份与技能身份相互独立:复用某个版本会重新核验其文件,损坏的版本会明确失败,而不是被静默替换或升级。
贡献与支持
改动前先读 AGENTS.md:行为变更必须先走 OpenSpec,且没有真实交付证据不得勾选任务。文档与规范校验:
python3 scripts/validate_docs.py
openspec validate establish-v1-plugin --strict --no-interactive
这两条只校验文档与规范。缺陷请提交到 <https://github.com/full-aigc-plugins/artcraft-plugin/issues>。
许可证
本仓库原创内容采用 Apache-2.0。随包安装的 Node 运行时与四个上游创作 CLI 各自保留其许可证。受限的上游 ArtCraft/Services 代码与品牌素材未被复制;按版本绑定的历史见 RELEASE-HISTORY.md。预览分享卡片长什么样 ↓
分享 · DeepSeek Harness Hub
full-aigc-plugins/artcraft-plugin
把一份需求拆成矢量、位图、动效与影片工程并调度交付
相关插件 · 视觉能力
智能体工作台Devin-AXIS/iPolloWork
企业级、本地优先的智能体工作台,面向个人和智能体团队——一个工作区,容纳多个智能体引擎;一套统一体系,管理插件和技能;支…
★ 7,359已汉化DSH
72
开源设计工作台nexu-io/open-design
OpenDesign:首个协作式 AI 设计智能体工作区
★ 105,514已汉化DSH
71.8
多智能体编码工作区spacering-net/codeg
多智能体协作的 AI 编程工作区:汇总 Claude Code、Codex、OpenCode、Pi、Grok Build 等来源的会话。支持桌面应用、自托管服务器或 Docker。
★ 4,289已汉化DSH
71.6
GPT 图像提示词库freestylefly/awesome-gpt-image-2
Prompt as Code | GPT Image 2 / 2.5 提示词与案例库,530+ 个案例、20+…
★ 34,534已汉化DSH
71.5
架构图生成器tt-a1i/archify
把你想理解、规划或分享的事,变成可以互动的可视化作品。
★ 92,675已汉化DSH
71.2
AI 用量桌面小部件Javis603/token-monitor
EN | 简 | 繁 | KO | JA | PT
★ 3,522已汉化DSH
71
这是你的仓库?认领条目