feat: release Dever 0.1.4 with enforceable project guidance

This commit is contained in:
Antigravity committed 2026-10-09 05:33:57 +00:00
1 parent 201bdee372
commit 89629c2197
86 files changed
+2798 -338

No files matched your search

+45 -11
View File
@@ -1,25 +1,59 @@
# External Worker SDKs
# Python、JavaScript 与 Go SDK
These are stdio Worker libraries for Python, JavaScript (Node), and Go. The compiler remains the sole owner of Port schemas. Each checked external Adapter exposes `ExternalWorkerContract::sdk_manifest()`, including the exact identity and recursive setting, input, output and declared-error types. The managed Python and JavaScript runners package this manifest and bind each Port operation to a same-named function exported by the Adapter entry; JavaScript accepts ESM named exports or CommonJS `module.exports` properties. Application code does not maintain a second registration table. Python uses `Worker.from_manifest(manifest, handlers)`, JavaScript uses `Worker.fromManifest(manifest, handlers)`, and Go uses `NewFromManifest(manifest)` followed by `RegisterHandlers(handlers)`. These paths decode inputs and validate results and declared business-error payloads from the same compiler-generated contract. The SDK checks the identity during `hello` and never adopts a schema supplied by the supervisor.
SDK 用于把现成的 Python、JavaScript 或 Go 能力接入 Dever。应用先声明 Port,再用外部 Adapter 对接;Dever 会管理 Worker 进程和通信。
The lower-level `Contract`/`Worker` registration API remains available for protocol fixtures. The setting decoder runs before `ready`; it receives only the `hello.setting` value. Handlers return JSON-compatible values or a declared `BusinessError`. Python handlers are async; JavaScript handlers receive an `AbortSignal`; Go handlers receive a `context.Context`. A cooperative cancellation receives one `dever.cancelled` protocol error and discards its handler result. If a handler ignores cancellation for one second, the Worker fails and admits no further calls. The supervisor owns the Worker process and its stdin lifetime; an in-process Go `Serve` caller must close or unblock its own `io.Reader` when returning.
开发应用先看 [三种语言的完整例子](../skills/references/external-lib.md)。那里包含同一 Port、三种 Adapter、处理函数和 fake 测试,不需要手写协议或维护另一份接口注册表。
The three `example` entries use the same fixture identity and contract to demonstrate the lower-level API. `fixture-schema-v1` and `test/external-sdk/typed_contract.json` are test data, not production Port hashes. Worker stdout is reserved for 4-byte big-endian length-prefixed UTF-8 JSON frames. Diagnostics go to stderr. The libraries use no external packages and do not read environment variables or `PATH`. A managed Worker entry reads only its explicitly packaged manifest path. Managed Python packs require fixed `-I -S -B` flags; the runner imports its packaged SDK before exposing Adapter source and dependencies on `sys.path`.
## 处理函数怎么写
Run the opt-in host SDK check with explicit absolute runtime paths, for example:
函数名与 Port 操作名对应。输入、输出和业务错误的类型由 Dever 编译器生成,SDK 负责验证。
| 语言 | 处理函数 | 加载生成的接口定义 |
| --- | --- | --- |
| Python | 异步函数 | `Worker.from_manifest(manifest, handlers)` |
| JavaScript | 函数接收 `AbortSignal`;支持 ESM 导出或 CommonJS 属性 | `Worker.fromManifest(manifest, handlers)` |
| Go | 函数接收 `context.Context` | `NewFromManifest(manifest)`,再 `RegisterHandlers(handlers)` |
处理函数返回能用 JSON 表达的值,业务失败返回已声明的 `BusinessError`。不要往 stdout 写日志;stdout 用于 Worker 通信,日志写 stderr。
取消请求会产生一次 `dever.cancelled` 错误,已取消调用的结果会被丢弃。如果处理函数一秒内不响应取消,Worker 失败并停止接收新调用。Dever 管理进程与 stdin;自行在 Go 进程内调用 `Serve` 时,调用方负责关闭或解除自己的 `io.Reader` 阻塞。
## SDK 维护与验证
维护 SDK 时,显式指定本机运行环境的绝对路径:
```text
/usr/bin/python3 -B test/external-sdk/check.py --python /usr/bin/python3 --node /absolute/path/to/node --go /absolute/path/to/go
```
Omitted runtime paths report `unavailable`; the script never discovers language runtimes through `PATH`. It builds the Go fixtures in a temporary offline cache. This check exercises both the lower-level and compiler-manifest-shaped typed paths on host interpreters. Managed runtime packaging and execution on a machine without host language runtimes require separate acceptance.
未指定的语言报告 `unavailable`,不会通过 PATH 猜测。Go 夹具在临时离线缓存中构建。这项检查验证本机 SDK 和类型协议;不能代替发行包或“机器未安装 Python/Node/Go”的运行验收。普通应用测试使用 Port fake,不启动真实 Worker。
Managed dependencies use `dever-lock-v6`. Python extras and selected wheel METADATA, npm nested instances/peers/optional/bundled dependencies, and authenticated Go module evidence are part of the exact lock. Original archives retain their fixed source locator and filename; build receipts retain the complete execution input lock, including npm's graph before optional build pruning. `dever lib install <project>` restores these exact inputs and artifacts without resolving new versions or modifying configuration/lock bytes. Missing built outputs are replayed through the same sandbox executor and must match the recorded output digest; non-reproducible outputs fail explicitly. Native Python wheels install into the packaged interpreter prefix and must satisfy its signed tags, extension ABI and loader closure.
编译器通过 `ExternalWorkerContract::sdk_manifest()` 生成唯一接口定义,包括身份、配置、输入、输出和业务错误。SDK 在 `hello` 时核对身份,不接受 supervisor 临时指定的 schema。配置在 `ready` 前解码,只读取 `hello.setting`。
Cross builds select the application platform explicitly: `dever lib update <project> --target linux-aarch64`, followed by `dever build <project> --target linux-aarch64 --output <new-file>`. Worker source and Port contracts stay unchanged. Locks, interpreters, native dependencies and sandbox assets must match that target. A Go runtime pack additionally declares `build.host` for its compiler/linker/analyzer; `build.goos/goarch` and standard-library object headers describe the output architecture. The tools run with a cleared environment and must have the correct target baked in. Missing target assets are errors, with no host runtime fallback. `run` and ordinary tests remain host operations.
本目录的三个 `example` 展示底层 `Contract`/`Worker` 注册 API,用于协议夹具。`fixture-schema-v1` 和 `test/external-sdk/typed_contract.json` 都是测试数据,不能复制成生产 Port hash。通信帧由 4 字节大端长度和 UTF-8 JSON 组成。
Only explicit Lib preparation may build Python sdists or run npm registry installation hooks. The shared build owner uses signed compiler/header/sysroot/frontend packs in a Linux sandbox with no network, immutable inputs and owned writable scratch space. Python PEP 517 build requirements have their own exact lock; each hook has a fresh process, and the parent retains the metadata snapshot used to validate the final wheel. npm uses its packaged lifecycle runner for `preinstall`, `install` and `postinstall`, including dependency bins and node-gyp. Missing tools do not fall back to host `PATH`.
SDK 不依赖第三方包,也不读取环境变量或 PATH。托管 Worker 只读取已打包的 manifest。Python 固定使用 `-I -S -B`,先加载打包的 SDK,再把 Adapter 与依赖加入 `sys.path`。
Build receipts bind sources, target runtimes, tools, frontend, dependency graph and final output hashes. Worker preparation replays those outputs offline without running installation hooks. Every npm `.node` output is classified by target/loader checks and an isolated Node load probe; only admitted addons enter the immutable Worker tree, including trees used by threads or child processes. Rejected platform/ABI variants remain in the locked archive. Runtime native dependencies must come from that tree or the signed OS library set, never the compiler sysroot. These rules do not change the Port protocol or require an application-side registration layer.
## 依赖与跨平台构建
A generated addon that fails admission fails the build; a pure JavaScript fallback is not evidence of successful native compilation. Build subprocesses have a five-minute deadline and separate 16 MiB stdout/stderr limits. Scratch usage is checked every 250 ms against 512 MiB and 65,536 entries, with owned-process cleanup on failure. This periodic check is not a kernel disk quota and may observe overshoot between checks. The final Worker installation remains limited to 256 MiB and 65,536 entries.
`dever lib install <project>` 按现有锁恢复依赖,不重新选版本、不修改配置或锁。`dever-lock-v6` 记录 Python extras/wheel METADATA、npm 嵌套依赖及 peers/optional/bundled 依赖、Go 模块校验证据。原始包保留来源与文件名,构建记录保留完整输入,包括 npm 剪除可选构建依赖前的依赖图。
丢失的构建结果由同一沙箱重建,必须与记录的摘要一致。Python 原生 wheel 安装到配套解释器中,必须满足签名声明的标签、扩展 ABI 和动态库依赖要求。
生成 ARM64 应用时,先运行 `dever lib update <project> --target linux-aarch64`,再运行 `dever build <project> --target linux-aarch64 --output <new-file>`。Port 和 Worker 源码无需改写;锁、解释器、原生依赖和沙箱资源必须匹配目标平台。缺少目标资源时失败,不借用宿主运行环境。`run/test` 仍在本机执行。
Go pack 的 `build.host` 描述编译器、链接器与分析器的运行平台;`build.goos/goarch` 和标准库对象头描述输出平台。工具在清空的环境中执行,目标必须预先正确配置。
## 第三方源码构建限制
只有显式准备 Lib 时才构建 Python sdist 或运行 npm 安装钩子。构建使用签名工具包和 Linux 沙箱,输入只读、网络关闭,写入仅限本次临时目录。缺少工具时不回退宿主 PATH。
Python PEP 517 的构建依赖单独锁定,每个 hook 使用新进程,最终 wheel 按保留的元数据核对。npm 的配套运行器处理 `preinstall/install/postinstall`、依赖 bin 和 node-gyp。
构建记录绑定源码、目标运行环境、工具、构建前端、依赖图和输出摘要。Worker 准备阶段离线恢复结果,不重跑安装钩子。npm `.node` 产物须通过目标检查、动态加载检查和独立 Node 加载探测,才能进入只读 Worker 目录;线程和子进程也受此限制。不匹配平台或 ABI 的其他变体保留在锁定原始包中,不加入运行目录。运行时原生依赖只能来自 Worker 目录或签名 OS 库,不能借用编译器 sysroot。
生成的原生 addon 验证失败,整个构建就失败;使用纯 JS 备用路径不能证明原生构建成功。当前限制:
- 构建进程最多 5 分钟,stdout/stderr 各最多 16 MiB。
- 每 250 毫秒检查临时目录,限制 512 MiB、65,536 个条目;这是定期检查,检查间隔内可能短暂超出。
- 最终 Worker 最多 256 MiB、65,536 个条目。失败时清理本次拥有的进程。