DSH HUB
HomePlugin StorePlugin PacksCommunityRankingsResourcesPublish Guide
Plugin source
Back to catalog

Cangjier /

Cangjier/xl

Verified

This plugin has no description yet.

★ 0 Stars0 Forks0 IssuesN/A Community rating0 Confirmed installs
View on GitHub
READMESource: main@c55965d0

xl

把 xl-md 编译器装进 DeepSeek Harness 的插件(bundle)。

它做两件事:

  1. 提供 xl CLI —— 新增一个名为 xl 的 dsh profile,dsh xl build / dsh xl check / dsh xl targets 与 xl-cli.md 的接口一致。
  2. 把非 ts 通道交给 DSH —— xl_* 七个模型工具让会话里的 agent 直接读需求、docs 与 *.xl.md,自己生成目标语言文件;xl 只提供标准化零件:产物计划、结构契约、语言上下文、增量 cache、校验、写盘与产物头。

纯 ESM、零依赖、零构建:装进任何 profile 都能直接被 Loader 加载。

docs/ 下是本实现自己的规范文档(语法 · CLI · 诊断码 · ts 产物映射 · 验收基准),加上设计说明。改行为就改文档,见 §7。


1. 两条通道

目标 通道 生成者 是否联网
ts 直出(direct) xl 内置打印器,离线、确定性、字节稳定 否
其它语言 计划(plan) DSH 会话里的 agent 由该会话的模型决定

与原设计的差别

xl-cli.md §3.4 的原设计是:xl 自己拼一段 prompt,再 spawn dsh --profile headless,从 --json 事件流的 final 里取回代码。

本插件把它换成了「xl 出零件,DSH 主动调用」:

原:  *.xl.md ──► xl 拼 prompt ──► dsh 子进程(一次性) ──► 代码
本:  *.xl.md ──► DSH agent(自己读文件) ──► xl_plan / xl_context / xl_cache
                                          └─► xl_verify / xl_emit ──► 代码

因此:

  • xl build -t csharp 只输出计划,不调用模型、不起子进程、不写文件;
  • prompt 组装、重试、超时这些原来属于 xl 的职责不再存在——agent 自己决定读什么、怎么改;
  • 产物头、指纹、历史版本 cache、结构回读校验仍然由 xl 统一负责,agent 调 xl_emit 一次就全部拿到。

-t ts 不受影响:仍然是内置打印器直出,字节与 xl-base-case.md 完全一致。


2. 安装

2.1 装进现有 profile(拿到模型工具)

在 Web 会话里用 plugin_manager,或者命令行:

dsh plugin --profile web add C:\Users\Admin\Documents\GitHub\xl

装完刷新页面,xl_plan 等七个工具即可用。这一步只注册 Host 插件与工具,不解析 profile 的命令行。

2.2 新建 xl profile(拿到 CLI)

dsh plugin --profile xl add C:\Users\Admin\Documents\GitHub\xl

dsh plugin 会初始化一个 base-backed profile 并选中本 bundle。之后:

dsh xl build . -t ts
dsh xl check .
dsh xl targets

xl 是一个 profile 名,所以 dsh xl … 就是 dsh --profile xl …。这是 dsh 唯一支持的应用入口写法:launcher 级子命令表是硬编码的(只有 plugin),profile 名是插件唯一能占用的「命令」。

应用行 xl/cli 只在 profile 名恰为 xl 时启用(bundle patch 里的 disabled: !!js "ctx.get('profileContext')?.name !== 'xl'")。原因是一个 profile 的命令行只能由一个应用插件解析:Web profile 已经用它解析 dsh web --port,headless profile 用它解析任务文本。

2.3 卸载

dsh plugin --profile web remove xl

3. 模型工具

七个工具,一个操作一个工具,不按选项拆分。

工具 作用 关键参数
xl_plan 列出每个源 × 目标会产出哪些文件、走哪条通道、cache 是否已满足 paths? targets? out? naming? flat? cwd?
xl_context 一个源 × 目标的标准化生成上下文:要写的确切路径(每个部件一条)、结构契约、语言覆盖段、每个部件的上一版指针,以及该目标语言的生成指南路径(存在时) file target out? naming? flat? cwd?
xl_cache 缓存状态:产物是否已匹配源指纹,以及每个部件最近归档的旧版本全文 file target out? cwd?
xl_verify 只校验不写盘:类型集合、成员名、参数个数 file target files cwd?
xl_emit 校验并写盘:产物头、指纹、prompt hash、归档旧版、更新 cache file target files model? force? verify? cwd?
xl_check 静态检查,返回规则码 paths? targets? ignore? strict? maxWarnings? cwd?
xl_build 跑一次构建:ts 直出写盘,其它目标只给计划 paths? targets? out? naming? flat? force? dryRun? cwd?

布局不是参数,而是目标的属性:ts 恒为 file(一个源一个产物),其余目标(含自定义目标)恒为 type(每个类型各一文件 + 一个模块文件);一个单元产出几个文件同样由目标的 parts 决定(cpp 是 .h + .cpp)。没有任何参数能改变它们,见 §4.4。

3.1 一次生成的标准流程

xl_plan      → 有哪些源、每个源要产出哪些文件、cache 是否 reusable
xl_context   → 这一份源 × 目标的契约:输出路径(每个部件一条)+ 结构摘要 + ## <lang> 段 + 每个部件的上一版指针 + 生成指南路径
(agent 自己读 *.xl.md、需求文档、依赖文件,以及 xl_context 报出的生成指南)
xl_cache     → 有上一版就取全文,在它之上改而不是重写
xl_emit      → 一次提交这一份源 × 目标的全部文件;xl 负责校验、头、指纹、归档、cache

生成指南:xl_context 会在 ## Next 里给出该目标语言的指南路径(本仓库 docs/xl-emit-<lang>.md),存在才给——插件里没有对应指南的目标(今天的非 cpp 目标)会明确回一句「没有指南」,agent 就只依据契约与目标工程惯例。指南是建议,不是契约:它不进 promptHash,改指南不会让任何产物失效(docs/design.md §4)。

xl_emit 的 files 必须逐一对应 xl_plan/xl_context 报出的路径:给出计划外的路径会被拒(E2001),漏掉计划内的路径会被拒(E4002),产物结构与 IR 不一致会被拒(E4002)且不写盘,agent 改完再调一次即可。

路径由 out / naming / flat 参与计算:xl_plan、xl_context、xl_verify、xl_emit 都接受这三个参数,调用时必须与规划时给的完全一致,否则算出来的路径与计划对不上。

3.2 产物头

非 ts 目标的每个部件各写一份产物头(C++ 的 .h 与 .cpp 各有一份),注释符按该部件的扩展名选:

// @generated by xl from pkg/demo.xl.md
// xl:sha256:<源指纹>  xl:target:csharp  xl:ver:0.1.0  xl:model:<模型>  xl:prompt:<上下文哈希>
// DO NOT EDIT — 修改请改 xl.md 并重新生成

xl:prompt 是 xl_context 报出的上下文哈希(结构摘要 + 语言覆盖段 + 依赖摘要 + layout + parts + naming)。它变了就说明生成依据变了,cache 因此失效。


4. xl CLI

4.1 命令

xl build [paths...] [options]    编译(ts 写盘;其它目标只给计划)
xl check [paths...] [options]    只做静态检查
xl targets [options]             列出已知目标
xl --help | -h                   帮助
xl --version | -v                版本

4.2 选项

选项 作用
-t, --target <lang> 目标语言,可重复;缺省取 xl.json 的 build.target,再取行配置的 defaultTargets(bundle patch 是 ['ts']),再缺省 ts
-o, --out <dir> 输出根目录;缺省取 xl.json 的 build.out,再缺省 dist;可给绝对路径
--flat 丢弃源文件相对目录层级
--stdout 产物正文写标准输出、不落盘
--naming <mode> idiomatic(缺省)| preserve
--force 忽略指纹与缓存,强制重新生成
--no-cache 本次不读写增量缓存,也不写历史版本归档
--clean 归档并删除本次计划的所有产物,然后强制重新生成
--dry-run 只打印计划,不写盘
--ignore <codes> 忽略指定诊断码,逗号分隔(产物层的 E2001 / E2002 / E2003 不可忽略)
--strict warning 视为 error(只对 xl check 生效)
--max-warnings <n> warning 数量上限(只对 xl check 生效)
--format <fmt> pretty(缺省)| compact | json
-q, --quiet / --verbose / --json / --color <when> 输出控制;前两者也接受 XL_LOG,颜色受 NO_COLOR / FORCE_COLOR 影响
--cwd <dir> 以指定目录为基准解析路径与配置

4.3 被接受但无效的选项

原设计里这些选项服务于「xl 自己 spawn harness」,本插件不再调用模型,因此它们只是为了让既有命令行不报错而被接受;--verbose 下会提示一次:

--harness --harness-profile --timeout --retries --keep-going --concurrency

另有几个选项在 xl build 上被接受但读取后不使用:--verify / --no-verify(只决定 xl_emit 的 verify 缺省);--keep-going 是冗余的(单个文件失败本来就不中断整轮构建),--concurrency 对 ts 直出也没有意义。XL_TIMEOUT / XL_CONCURRENCY / XL_HARNESS 不被读取。

4.4 输出布局

产物一律落在 <out>/<目标语言>/…,两种 layout 都保留源文件相对目录。源文件 pkg/demo.xl.md,xl build . -t ts -t csharp -t cpp -t python:

dist/
  ts/pkg/demo.ts                    # ts 恒为 file:一个源文件一个产物
  csharp/pkg/DemoModule.cs          # 其余目标恒为 type:模块级 # method / # const 合并到这里
  csharp/pkg/Point.cs               # 每个类型各成一文件
  cpp/pkg/demo_module.h             # cpp 一个单元两个部件:header …
  cpp/pkg/demo_module.cpp           #   … 与 source(该单元有函数体,所以被计划)
  cpp/pkg/point.h
  cpp/pkg/point.cpp
  python/pkg/demo_module.py         # type 布局的其它语言同样带语言目录
  python/pkg/point.py               # 文件名按 --naming 变换(idiomatic 下 Python / cpp 用 snake_case)
  • 布局是目标的属性,不是调用的属性:ts 恒为 file,csharp / java / python / go / rust / cpp 与自定义目标恒为 type。命令行与工具都没有 layout 参数(docs/xl-cli.md §3.5),xl.json 的 targets.<lang>.layout 根本不会被读取(§9)。
  • parts 同样是目标的属性:一个单元产出几个文件由目标的部件表决定,几乎所有语言只有一项,cpp 有两项 —— header(.h)与 source(.cpp)。带 requires: "bodies" 的部件只在单元确实有可执行内容(有函数体 / 代码块初始值 / # statement / 对应语言覆盖段的代码)时才计划:只有 inline 字段的类是 header-only,不会被要求交一个空的 .cpp(docs/xl-cli.md §3.5)。这个判定只依赖 IR 与目标名,所以同一份源的计划是确定的。
  • 语言目录是计划的产物路径的一部分:xl_plan / xl_context 报出的路径就是要写的确切路径(每个部件一条,带 part 标记),xl_emit 只接受这些路径、且一个都不能少。
  • --flat 丢弃源文件相对目录,但保留语言目录(dist/ts/demo.ts)。
  • 每个语言目录下另有自己的增量 cache:dist/ts/.xl/、dist/csharp/.xl/(§6)。
  • 未给 -o / build.out 时 <out> 是 dist;-o 可以是相对工作目录的路径,也可以是绝对路径(绝对路径会原样出现在计划里)。

4.5 退出码

码 含义
0 成功(允许 warning;--strict 下不允许)
1 源文件有 error、输出冲突、写盘失败
2 用法错误(未知选项 / 未知目标 / 无输入 / 路径不存在)
3 计划通道失败(本插件不返回;由 agent 侧的 xl_emit 以 E4002 表达)

--ignore 只对解析 / 检查层的码生效:E2001 / E2002 / E2003 写进 --ignore 也照常计数,写盘失败或输出冲突一律退出 1。


5. 配置

5.1 profile 行配置(cordis.patch.yml)

- id: xl
  name: 'xl'
  config:
    workspaceRoot: null      # 工具缺省的工作目录;null 用进程 cwd
    cacheDir: '.xl'          # 每个语言目录下的 cache 目录名(缺省即 dist/<lang>/.xl);xl.json 与 XL_CACHE_DIR 优先级更高
    defaultTargets: ['ts']   # 请求未给 targets 且 xl.json 也没有时的缺省
    verifyOnEmit: true       # xl_emit 未显式给 verify 时是否先校验

字段类型错误会在激活时抛错(Loader 无法替本包校验配置,因为校验需要 harness 依赖)。

5.2 xl.json

沿用 xl-cli.md §4 的查找顺序与字段:

{
  "build": { "target": ["ts"], "out": "dist", "naming": "idiomatic", "header": true, "cacheVersions": 5 },
  "check": { "ignore": ["W3102"], "strict": false, "maxWarnings": null },
  "targets": {
    "kotlin": { "ext": ".kt" },
    "objcpp": {
      "parts": [
        { "role": "header", "ext": ".h" },
        { "role": "source", "ext": ".mm", "requires": "bodies", "scope": "definition" }
      ]
    }
  }
}
  • 自定义目标给 ext(单部件,等价于 parts: [{ "role": "file", "ext": … }])或直接给 parts。parts 里 role 是部件名(缺省 part1、part2…,同一目标内唯一),ext 必填,requires: "bodies" 表示"该单元有可执行内容时才计划",scope: "definition" 表示"这个部件只定义部分成员"(见 docs/xl-cli.md §3.5)。声明不成部件表是用法错误(E0004,退出码 2)。

  • build.target(字符串或数组)是缺省目标,优先于行配置的 defaultTargets;build.out、build.naming、build.header、build.cacheVersions、build.cacheDir 都生效。

  • harness 段整体不再被读取(没有子进程通道);targets.<lang>.model 虽然被读进目标描述符,但无人消费——模型 id 由 agent 在 xl_emit 的 model 参数里给出;targets.<lang>.layout 则根本不读:自定义目标走计划通道,而计划通道恒为 type(§4.4)。

优先级一律是 CLI 参数 > 环境变量(XL_TARGET / XL_OUT / XL_CONFIG / XL_CACHE_DIR)> xl.json > 内置缺省,所有入口(CLI 与七个工具)适用同一套规则。


6. 增量 cache

两份存储,职责不同:

路径 内容
<out>/<目标语言>/.xl/cache.json 每个 源 × 目标 的源指纹、产物路径、产物内容哈希、model、prompt hash
<out>/<目标语言>/.xl/cache/<镜像源路径>.<扩展名>.<N> 最近 N 版产物(缺省 5,build.cacheVersions 为 false/0 时关闭)

归档家族以源 × 扩展名为单位:demo.h.1 与 demo.cpp.1 是两份互不干扰的历史,单部件语言仍然只有一个家族。所以"上一版"按部件给出:xl_context / xl_cache 的 previous 是数组({ part, ext, version, path, text }),C++ 给两条(header 一条、source 一条),csharp 这类给一条(part: "file")。

缺省 <out> 是 dist,所以 ts 的存储是 dist/ts/.xl/、csharp 的是 dist/csharp/.xl/:每个语言一份独立存储,互不读取。build.cacheDir / XL_CACHE_DIR 给的是该目录名(缺省 .xl)——相对值放在语言目录之下,绝对值原样使用(此时所有语言共享一份存储,仍然正确:cache.json 按 源 × 目标 分键,归档文件名带目标扩展名)。仅仅计划某个语言(xl_plan / xl_context,或 xl build -t <其它语言>)不会建出该目录:没有任何 源 × 目标 被记录时 cache 不落盘。

  • 复用判定:计划中的每个产物都存在、带 xl 头、xl:target 是本目标、xl:sha256 等于当前源指纹 → 跳过。--clean 直接判定为不可复用,于是整轮重新生成。
  • 归档:覆盖前把被覆盖的那一份存为下一序号;最新一版就是 xl_cache / xl_context 给出的「上一版」,用来在它之上改而不是重写。--no-cache 同时关闭 cache.json 与归档。
  • 手改检测(E2003):产物内容哈希与 cache 记录不一致,说明它在 xl 之外被改过,覆盖前给一次 warning。

7. 规范文档

docs/ 下的四份 xl-*.md 与 design.md 现在描述的就是本实现(见 docs/design.md §0):早先它们是与上游 xlanguage 仓库逐字同步的副本,靠 pnpm docs:sync 比对;该机制已取消——实现行为一变,文档就地更新,因此不再需要「文档 vs 本实现」的差异表。

仍然值得知道的偏差集中在两处:

  • docs/design.md §8「已知行为偏差与缺口」:面向维护者(几个选项在 xl build 上不生效、build.naming 不校验、interface 成员修饰符不报错、E4001 故意不产生等)。
  • 本文 §9「已知限制」:面向使用者。

docs/xl-base-case.md 是冻结的字节级验收基准:tests/fixtures/* 由它抽取(pnpm fixtures)。改动它必须重抽 fixture 并一起提交,其余四份文档则随手改。


8. 开发

pnpm test          # 等价于 node --test "tests/*.test.js"
pnpm check         # 入口文件语法检查
pnpm codes         # 诊断码 → 产生它的模块;有码没人产生就失败
pnpm fixtures      # 从 docs/xl-base-case.md 重抽验收 fixture

测试里最重要的一条是字节级一致性:tests/fixtures/demo.xl.md 与 demo.expected.ts 直接从 docs/xl-base-case.md 抽出来,打印器的输出必须逐字节等于期望产物。基准样例更新后重新抽取:

pnpm fixtures

docs/xl-*.md 描述的是本实现,改行为就改文档(§7);只有 docs/xl-base-case.md 是冻结的验收基准。

目录

index.js                  bundle 入口:xl 服务 + 模型工具
cli.js                    xl profile 的应用行入口
cordis.patch.yml          bundle patch:插入这两行
docs/                     规范文档(xl-*.md)+ design.md(本实现的事实来源)
src/core/                 纯核心(解析 / 检查 / ts 打印 / 计划 / cache / 校验)
  parse.js                *.xl.md → IR
  check.js                跨文件与跨目标规则、生成质量提示
  emit-ts.js              ts 直出打印器(确定性)
  plan.js                 输出路径与冲突
  cache.js                每个目标语言的 cache.json 与历史版本归档
  artifact.js             计划通道的三个操作:context / verify / emit
  build.js                扫描 → 解析 → 检查 → 计划 → 产出
src/plugin/               Host 插件与 CLI
  service.js              xl 服务(能力缝)
  tools.js                七个模型工具
  cli.js / args.js / console.js
tests/                    node:test
scripts/                  extract-fixtures.mjs / code-map.mjs

分层

src/core 里的 parse check emit-ts plan verify types header text diagnostics 全是纯函数,不碰文件系统,因此可以脱离进程与 CLI 单测;build artifact scan config cache source 是 I/O 层。src/plugin 只做三件事:把请求翻译成 core 调用、把结果渲染给模型或终端、把副作用留在 core 的 I/O 层。详见 docs/design.md。


9. 已知限制

  • 写盘绕过 ctx.fs 沙箱。 xl_emit 与 ts 直出直接用 node:fs 写文件,因此不受 profile 的文件沙箱与审批策略约束。这是为了让插件零依赖、可在任意 profile 装载;如果部署需要沙箱,应把 src/core/artifact.js 与 src/core/build.js 的写盘改成走 ctx.fs。
  • 没有子进程通道。 这是设计目标,不是缺口:非 ts 目标的生成者是会话里的 agent。
  • xl build 上的几个选项不产生作用。 --verify / --no-verify 只决定 xl_emit 的 verify 缺省;--keep-going 是冗余的(单文件失败本来就不中断整轮);--concurrency 对 ts 直出没有意义;--harness / --harness-profile / --timeout / --retries 属于旧设计,只为兼容而被接受。
  • 未实现的文档能力。 xl.json 的 build.layout / build.verify / build.specHint / build.source、targets.<lang>.namespace(只被读入描述符,无人消费)、targets.<lang>.layout(布局恒为目标的属性)、targets.<lang>.model(模型 id 由 xl_emit 的 model 参数给出)在本实现中不生效。XL_TIMEOUT / XL_CONCURRENCY / XL_HARNESS 不被读取。
  • E2003 依赖 cache。 --no-cache 时无法判断产物是否被手改,因此不会报告;xl_emit 也不做这项检查。
  • 归档家族是 源 × 扩展名,不是 源 × 产物路径。 xl_cache 给的"上一版"是该扩展名最新归档的那一份;layout=type 下一个源有多个同扩展名产物时(Point.cs、Box.cs…),它只保留其中一个的历史。cpp 因此每份 previous 对应一个部件扩展名,而不是每个类型各一份。
  • 类成员只支持 ### <lang>。 类级的 ## <lang> 会被当成成员标题而报 E1201(docs/xl-syntax.md §16)。

更完整的偏差清单(含位置与修法建议)见 docs/design.md §8。

—/ 5

No ratings yet

Verified DSH bundle

Commit c55965d0d077

Community comments

No comments yet. Be the first to write one.

DSH HUB

A community index for DSH plugins. Not an official GitHub or DeepSeek AI product.

CommunityResourcesAPIAbout