Merge branch 'codex/simp-session-dead-surface' into codex/simp-session-log-representation

# Conflicts:
#	docs/event-producer-consumer.md
This commit is contained in:
Tianyi Cui
2026-07-14 00:34:46 +08:00
112 changed files with 10839 additions and 129 deletions

View File

@@ -0,0 +1,470 @@
/**
* Build the single-file SDK runtime executables
* (docs/rfc/implemented/architecture/2026-07-10-single-file-executable-sdk-runtime-distribution.md).
*
* Every settled decision is hardcoded — the PoC judged @yao-pkg/pkg's
* standard mode unusable for this architecture (its ESM→CJS transform breaks
* every runtime `import()`), so the pipeline is fixed on `--sea` mode, plain
* ESM entry, plain-source assets, and a hoisted (symlink-free) staged tree.
*
* Pipeline — every step fails loud with the command it ran:
*
* 1. `pnpm run build` — all packages emit `lib/` (skippable via --skip-build).
* 2. `pnpm --filter dsh-jsonrpc-agent-pkg deploy` — materialize the
* closure-manifest package (python/sdk-runtime/package.json — the single
* source of truth for the exe's plugin set) into the staging dir
* (cleared first; pnpm refuses a non-empty deploy target). Flags, all
* verified against pnpm 11.7: `--legacy` because the workspace does not
* set `inject-workspace-packages=true`; `node-linker=hoisted` for a plain
* file tree with zero symlinks (the safe shape for pkg's VFS, and it
* physically guarantees a single cordis copy); `auto-install-peers=false`
* so transitive `^0.0.x` peers on unpublished packages never hit the
* registry; `link-workspace-packages=true` so the closure resolves to
* workspace/vendor sources.
* 3. Inject the pkg config into the staged package.json: `bin` = the ESM
* `node_modules/@deepseek-ai/dsh-jsonrpc-agent/lib/bin.js` (SEA mode
* hands it to Node's default ESM loader — no CJS shim), plus whole-tree
* asset globs. The cordis Loader resolves plugins
* through runtime dynamic `import()` of bare package names, so pkg's
* static analysis discovers none of them — the entire staged tree must be
* globbed in explicitly.
* 4. `pnpm dlx @yao-pkg/pkg@<pinned> <staging> --sea --targets <t> --output
* <out>/dsh-jsonrpc-agent-pkg-<platform>-<arch>` — once per target (SEA mode
* packs a single target per invocation), so each product gets its
* canonical name directly.
* 5. Sync into the Python runtime package
* (python/sdk-runtime/src/deepseek_harness_runtime/runtime/,
* created if missing): each product under its canonical filename (exe
* mode), plus the whole staged closure into runtime/node/ (node mode —
* `node runtime/node/node_modules/@deepseek-ai/dsh-jsonrpc-agent/lib/bin.js`
* runs it directly; the injected pkg
* fields are harmless to node). dist-exe/ keeps the originals for CI
* artifact upload.
*
* `pnpm exec tsx scripts/build-exe-for-python-sdk.ts` → host-platform exe into dist-exe/
* `pnpm exec tsx scripts/build-exe-for-python-sdk.ts --targets=node24-linux-x64,node24-linux-arm64,node24-macos-arm64`
* `pnpm exec tsx scripts/build-exe-for-python-sdk.ts --dry-run` → print the plan without executing
*/
import { spawn } from 'node:child_process'
import { existsSync, mkdirSync, statSync } from 'node:fs'
import { copyFile, readFile, rm, writeFile } from 'node:fs/promises'
import { basename, join, resolve, sep } from 'node:path'
import { parseArgs } from 'node:util'
const root = resolve(import.meta.dirname, '..')
/**
* The deploy root: the closure-manifest package (python/sdk-runtime) whose
* dependencies define the exe's contents; the runnable entry inside the
* closure is {@link ENTRY_BIN}.
*/
const DEPLOY_ROOT_PACKAGE = 'dsh-jsonrpc-agent-pkg'
/** The bin entry inside the deployed closure (the dsh-jsonrpc-agent app bin). */
const ENTRY_BIN = 'node_modules/@deepseek-ai/dsh-jsonrpc-agent/lib/bin.js'
/** Basename of every product; the canonical name appends `-<platform>-<arch>`. */
const OUTPUT_BASENAME = 'dsh-jsonrpc-agent-pkg'
/** Default exe Node major; SEA mode requires >= node22, the repo tracks node24. */
const DEFAULT_NODE_RANGE = 'node24'
/** Pinned pkg version (the one the PoC and acceptance ran on) for reproducible builds. */
const PKG_SPEC = '@yao-pkg/pkg@6.21.0'
/** Staging dir for the deployed closure — cleared on every run (gitignored). */
// (No external staging dir: the deploy target IS the Python runtime's
// node-mode carrier — see PYTHON_RUNTIME_DIR/PYTHON_NODE_SUBDIR.)
/** Product output dir (gitignored). */
const OUT_DIR = 'dist-exe'
/**
* Python runtime package dir the products are synced into. A parallel change
* owns the directory and its .gitignore; this script's only contract is the
* destination path, so a missing dir is created, never an error.
*/
const PYTHON_RUNTIME_DIR = 'python/sdk-runtime/src/deepseek_harness_runtime/runtime'
/** Subdir of {@link PYTHON_RUNTIME_DIR} carrying the staged closure for node-mode execution. */
const PYTHON_NODE_SUBDIR = 'node'
/** Deploy-root documentation is not runtime input and violates the generated-directory i18n exclusion if retained. */
const DEPLOY_ONLY_DOCS = ['README.md', 'README.zh.md', 'README.i18n.yaml']
/**
* Whole-tree asset globs. The cordis Loader dynamic-imports bare package names
* at runtime, invisible to pkg's static analysis, so every runtime file in the
* closure is listed; SEA mode ships them as plain source in the VFS. Every
* package.json must ride along — bare-name resolution dies without them (the
* json glob would already match, but the manifests are resolution-critical, so
* they get their own explicit entry).
*/
const ASSET_GLOBS = [
'package.json',
'node_modules/**/*.js',
'node_modules/**/*.cjs',
'node_modules/**/*.mjs',
'node_modules/**/package.json',
'node_modules/**/*.json',
'node_modules/**/*.node',
'node_modules/**/*.wasm',
]
const PLATFORMS = ['linux', 'macos'] as const
const ARCHES = ['x64', 'arm64'] as const
type Platform = (typeof PLATFORMS)[number]
type Arch = (typeof ARCHES)[number]
/** True when `value` is a supported pkg platform tag. */
function isPlatform(value: string): value is Platform {
return (PLATFORMS as readonly string[]).includes(value)
}
/** True when `value` is a supported pkg CPU tag. */
function isArch(value: string): value is Arch {
return (ARCHES as readonly string[]).includes(value)
}
/**
* One pkg target triple, e.g. `node24-linux-x64`, as an immutable value.
* Construction goes through {@link Target.parse} (a `--targets` entry) or
* {@link Target.host} (the default), which own all validation.
*/
class Target {
private constructor(
/** pkg Node range (`node<major>`); pins the official base binary pkg pulls. */
readonly nodeRange: string,
/**
* pkg platform tag. Windows is a documented non-goal
* (docs/rfc/implemented/architecture/2026-07-10-single-file-executable-sdk-runtime-distribution.md).
*/
readonly platform: Platform,
/** pkg CPU tag. */
readonly arch: Arch,
) {}
/** The pkg `--targets` spec string `<nodeRange>-<platform>-<arch>`. */
get spec(): string {
return `${this.nodeRange}-${this.platform}-${this.arch}`
}
/**
* Parse and validate one target spec; throws on any malformed component.
* @param spec - the raw triple, e.g. `node24-linux-x64`.
* @returns the parsed target.
*/
static parse(spec: string): Target {
const parts = spec.split('-')
const [nodeRange, platform, arch] = parts
if (parts.length !== 3 || nodeRange === undefined || platform === undefined || arch === undefined) {
throw new Error(`build-exe-for-python-sdk: target ${JSON.stringify(spec)} must be <nodeRange>-<platform>-<arch>, e.g. node24-linux-x64.`)
}
if (!/^node\d+$/.test(nodeRange)) {
throw new Error(`build-exe-for-python-sdk: target ${JSON.stringify(spec)}: node range must look like node24, got ${JSON.stringify(nodeRange)}.`)
}
if (!isPlatform(platform)) {
throw new Error(`build-exe-for-python-sdk: target ${JSON.stringify(spec)}: platform must be one of ${PLATFORMS.join(', ')} (Windows is a docs/rfc/implemented/architecture/2026-07-10-single-file-executable-sdk-runtime-distribution.md non-goal), got ${JSON.stringify(platform)}.`)
}
if (!isArch(arch)) {
throw new Error(`build-exe-for-python-sdk: target ${JSON.stringify(spec)}: arch must be one of ${ARCHES.join(', ')}, got ${JSON.stringify(arch)}.`)
}
return new Target(nodeRange, platform, arch)
}
/**
* The default target when --targets is omitted: the host platform on node24.
* @returns the host target; throws on an unsupported host platform or arch.
*/
static host(): Target {
const platform = process.platform === 'darwin' ? 'macos' : process.platform === 'linux' ? 'linux' : undefined
if (platform === undefined) {
throw new Error(`build-exe-for-python-sdk: unsupported host platform ${process.platform}; pass --targets explicitly.`)
}
const arch = process.arch === 'x64' || process.arch === 'arm64' ? process.arch : undefined
if (arch === undefined) {
throw new Error(`build-exe-for-python-sdk: unsupported host arch ${process.arch}; pass --targets explicitly.`)
}
return new Target(DEFAULT_NODE_RANGE, platform, arch)
}
}
/**
* Parsed CLI configuration. {@link BuildCli.parse} is the only constructor
* path — it owns flag parsing, target validation, and the --help / bad-flag
* process exits, so an instance always holds a valid plan.
*/
class BuildCli {
private constructor(
/** Build targets; defaults to the host platform only. */
readonly targets: readonly Target[],
/** Skip step 1 (`pnpm run build`); lib/ artifacts must already exist. */
readonly skipBuild: boolean,
/** Print every command and config patch instead of executing. */
readonly dryRun: boolean,
) {}
/**
* Parse argv into a validated configuration. Exits the process for --help
* (code 0, usage) and for unknown/malformed flags (code 1, usage on
* stderr); throws on invalid or colliding targets.
* @param argv - the raw arguments (`process.argv.slice(2)`).
* @returns the parsed, validated configuration.
*/
static parse(argv: string[]): BuildCli {
let values: ReturnType<typeof BuildCli.parseRaw>
try {
values = BuildCli.parseRaw(argv)
} catch (error) {
console.error(`build-exe-for-python-sdk: ${error instanceof Error ? error.message : String(error)}\n`)
console.error(BuildCli.usage())
process.exit(1)
}
if (values.help) {
console.log(BuildCli.usage())
process.exit(0)
}
const targets = values.targets === undefined
? [Target.host()]
: values.targets.split(',').map(part => part.trim()).filter(part => part !== '').map(spec => Target.parse(spec))
if (targets.length === 0) throw new Error('build-exe-for-python-sdk: --targets is empty.')
const seen = new Set<string>()
for (const target of targets) {
const key = `${target.platform}-${target.arch}`
if (seen.has(key)) {
throw new Error(`build-exe-for-python-sdk: duplicate platform-arch ${key} in --targets; canonical product names would collide.`)
}
seen.add(key)
}
return new BuildCli(targets, values['skip-build'], values['dry-run'])
}
/** The flag grammar in one place; parseArgs throws on any unknown flag. */
private static parseRaw(argv: string[]) {
return parseArgs({
args: argv,
options: {
'targets': { type: 'string' },
'skip-build': { type: 'boolean', default: false },
'dry-run': { type: 'boolean', default: false },
'help': { type: 'boolean', default: false },
},
}).values
}
/** The --help text; also printed under flag-parse errors. */
private static usage(): string {
return [
'Usage: pnpm exec tsx scripts/build-exe-for-python-sdk.ts [flags]',
'',
' --targets=<t1,t2,...> pkg targets, e.g. node24-linux-x64,node24-linux-arm64,node24-macos-arm64.',
' Default: the host platform only (on node24).',
' --skip-build skip `pnpm run build` (lib/ artifacts must already exist).',
' --dry-run print every command and config patch without executing.',
' --help print this help.',
'',
'Settled decisions are hardcoded (docs/rfc/implemented/architecture/2026-07-10-single-file-executable-sdk-runtime-distribution.md): pkg runs in --sea mode',
`(standard mode breaks runtime import()), pinned to ${PKG_SPEC}; the deploy tree is`,
`hoisted/symlink-free; the closure deploys straight into ${PYTHON_RUNTIME_DIR}/${PYTHON_NODE_SUBDIR} and products land in ${OUT_DIR}/.`,
].join('\n')
}
}
/** The pnpm executable name for the host OS. */
function pnpmBin(): string {
return process.platform === 'win32' ? 'pnpm.cmd' : 'pnpm'
}
/**
* Render a command line for logs and error messages, quoting arguments that
* contain spaces.
* @param command - the executable.
* @param args - its arguments.
* @returns the printable command line.
*/
function formatCommand(command: string, args: string[]): string {
return [command, ...args].map(part => (part.includes(' ') ? JSON.stringify(part) : part)).join(' ')
}
/**
* The four-step build pipeline over one parsed CLI. Steps are sequential
* async methods; every subprocess inherits stdio and fails loud with the
* exact command it ran. In --dry-run the command/filesystem layer prints
* what it would do instead of executing.
*/
class SingleExeBuild {
/**
* Absolute staging dir — the Python runtime's node-mode carrier: step 2
* deploys the closure DIRECTLY here (cleared first; it is a pure build
* product, the checked-in default `cordis.yml` lives one level up), step 4
* reads it as the pkg input, and node mode runs it in place.
*/
readonly staging = resolve(root, PYTHON_RUNTIME_DIR, PYTHON_NODE_SUBDIR)
/** Absolute product output dir. */
private readonly outDir = resolve(root, OUT_DIR)
constructor(private readonly cli: BuildCli) {}
/** Gate the manifest before spending time compiling or packaging it. */
async verifyClosure(): Promise<void> {
await this.run('runtime dependency closure', pnpmBin(), ['run', 'verify-runtime-closure'])
}
/** Step 1: `pnpm run build` — all packages emit `lib/` (skipped via --skip-build). */
async build(): Promise<void> {
if (this.cli.skipBuild) {
console.log('build-exe-for-python-sdk: skipping pnpm run build (--skip-build)')
return
}
await this.run('build', pnpmBin(), ['run', 'build'])
}
/** Step 2: clear the staging dir and deploy the bridge closure into it. */
async deployStaging(): Promise<void> {
if (this.staging === root || root.startsWith(this.staging + sep)) {
throw new Error(`build-exe-for-python-sdk: refusing to clear staging dir ${this.staging}: it contains the repo root.`)
}
if (this.cli.dryRun) console.log(`build-exe-for-python-sdk: [dry-run] rm -rf ${this.staging}`)
else await rm(this.staging, { recursive: true, force: true })
await this.run('deploy', pnpmBin(), [
'--filter',
DEPLOY_ROOT_PACKAGE,
'deploy',
'--legacy',
'--prod',
'--config.node-linker=hoisted',
'--config.auto-install-peers=false',
'--config.link-workspace-packages=true',
this.staging,
])
if (this.cli.dryRun) {
for (const name of DEPLOY_ONLY_DOCS) console.log(`build-exe-for-python-sdk: [dry-run] rm -f ${join(this.staging, name)}`)
} else {
await Promise.all(DEPLOY_ONLY_DOCS.map(name => rm(join(this.staging, name), { force: true })))
}
}
/** Step 3: patch the staged package.json with the bin entry + pkg asset globs. */
async injectPkgConfig(): Promise<void> {
const patch = { bin: ENTRY_BIN, pkg: { assets: ASSET_GLOBS } }
const manifestPath = join(this.staging, 'package.json')
if (this.cli.dryRun) {
console.log(`build-exe-for-python-sdk: [dry-run] patch ${manifestPath} with ${JSON.stringify(patch)}`)
return
}
if (!existsSync(manifestPath)) {
throw new Error(`build-exe-for-python-sdk: ${manifestPath} missing — pnpm deploy did not produce a staged package.`)
}
if (!existsSync(join(this.staging, ENTRY_BIN))) {
throw new Error(`build-exe-for-python-sdk: ${join(this.staging, ENTRY_BIN)} missing — run without --skip-build so lib/ artifacts exist.`)
}
const manifest = JSON.parse(await readFile(manifestPath, 'utf8')) as Record<string, unknown>
await writeFile(manifestPath, `${JSON.stringify({ ...manifest, ...patch }, null, 2)}\n`)
console.log(`build-exe-for-python-sdk: injected pkg config into ${manifestPath}`)
}
/**
* Step 4: run @yao-pkg/pkg over the staged tree for ONE target (SEA mode
* packs a single target per invocation) and return the product path.
* @param target - the pkg target triple to build.
* @returns the canonical product path `<out>/dsh-jsonrpc-agent-pkg-<platform>-<arch>`.
*/
async pack(target: Target): Promise<string> {
const product = join(this.outDir, `${OUTPUT_BASENAME}-${target.platform}-${target.arch}`)
if (!this.cli.dryRun) mkdirSync(this.outDir, { recursive: true })
await this.run(`pkg ${target.spec}`, pnpmBin(), [
'dlx',
PKG_SPEC,
this.staging,
'--sea',
'--targets',
target.spec,
'--output',
product,
])
if (!this.cli.dryRun && !existsSync(product)) {
throw new Error(`build-exe-for-python-sdk: product ${product} is missing after the pkg run; inspect ${this.outDir}.`)
}
return product
}
/**
* Print each product path (and size, when it exists on disk).
* @param products - the product paths returned by {@link pack}.
*/
printProducts(products: string[]): void {
console.log(this.cli.dryRun ? 'build-exe-for-python-sdk: [dry-run] would produce:' : 'build-exe-for-python-sdk: products:')
for (const product of products) {
if (this.cli.dryRun) {
console.log(` ${product}`)
continue
}
const megabytes = statSync(product).size / (1024 * 1024)
console.log(` ${product} (${megabytes.toFixed(1)} MB)`)
}
}
/**
* Step 5: copy every product into the Python runtime package under its
* canonical filename (exe mode). The node-mode carrier needs no sync — step
* 2 deployed the closure into it directly. dist-exe/ keeps the originals
* for CI artifact upload; the destination dir is created if missing.
* @param products - the product paths returned by {@link pack}.
*/
async syncToPythonRuntime(products: string[]): Promise<void> {
const destDir = resolve(root, PYTHON_RUNTIME_DIR)
if (this.cli.dryRun) {
for (const product of products) {
console.log(`build-exe-for-python-sdk: [dry-run] cp ${product} ${join(destDir, basename(product))}`)
}
return
}
mkdirSync(destDir, { recursive: true })
for (const product of products) {
const destination = join(destDir, basename(product))
await copyFile(product, destination)
console.log(`build-exe-for-python-sdk: synced ${destination}`)
}
}
/**
* Run one pipeline step as a subprocess with inherited stdio; reject —
* carrying the printable command — on spawn failure and non-zero exit
* alike. In --dry-run, print the command instead of executing.
* @param label - the step name used in logs and error messages.
* @param command - the executable.
* @param args - its arguments.
*/
private async run(label: string, command: string, args: string[]): Promise<void> {
const printable = formatCommand(command, args)
if (this.cli.dryRun) {
console.log(`build-exe-for-python-sdk: [dry-run] ${printable}`)
return
}
console.log(`build-exe-for-python-sdk: ${label}: ${printable}`)
await new Promise<void>((resolvePromise, reject) => {
const child = spawn(command, args, { cwd: root, stdio: 'inherit' })
child.once('error', (error) => {
reject(new Error(`build-exe-for-python-sdk: ${label} failed to spawn: ${error.message} (${printable})`))
})
child.once('exit', (code, signal) => {
if (code === 0) {
resolvePromise()
return
}
const cause = code === null ? `signal ${signal ?? 'unknown'}` : `exit code ${code}`
reject(new Error(`build-exe-for-python-sdk: ${label} failed (${cause}): ${printable}`))
})
})
}
}
/** Entry point: parse the CLI, then await each pipeline step in order. */
async function main(): Promise<void> {
const cli = BuildCli.parse(process.argv.slice(2))
const pipeline = new SingleExeBuild(cli)
console.log(`build-exe-for-python-sdk: targets: ${cli.targets.map(target => target.spec).join(', ')}`)
console.log(`build-exe-for-python-sdk: staging: ${pipeline.staging}`)
await pipeline.verifyClosure()
await pipeline.build()
await pipeline.deployStaging()
await pipeline.injectPkgConfig()
const products: string[] = []
for (const target of cli.targets) products.push(await pipeline.pack(target))
pipeline.printProducts(products)
await pipeline.syncToPythonRuntime(products)
}
await main()

View File

@@ -0,0 +1,182 @@
#!/usr/bin/env python3
"""Stage and build one Python wheel at the repository version."""
from __future__ import annotations
import argparse
import email
import json
import os
import re
import shutil
import stat
import subprocess
import tempfile
import zipfile
from pathlib import Path
ROOT = Path(__file__).resolve().parents[1]
PLATFORMS = {
"linux-x64": ("manylinux_2_28_x86_64", "dsh-jsonrpc-agent-pkg-linux-x64"),
"linux-arm64": ("manylinux_2_28_aarch64", "dsh-jsonrpc-agent-pkg-linux-arm64"),
"macos-arm64": ("macosx_11_0_arm64", "dsh-jsonrpc-agent-pkg-macos-arm64"),
}
def main() -> None:
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("--package", choices=("sdk", "runtime"), required=True)
parser.add_argument(
"--tag",
help="optional python-vX.Y.Z release tag; it must match package.json",
)
parser.add_argument("--output-dir", type=Path, required=True)
parser.add_argument("--platform", choices=tuple(PLATFORMS))
parser.add_argument("--runtime-exe", type=Path)
args = parser.parse_args()
version = repository_version()
validate_release_tag(args.tag, version)
if args.package == "runtime" and (args.platform is None or args.runtime_exe is None):
parser.error("runtime builds require --platform and --runtime-exe")
if args.package == "sdk" and (args.platform is not None or args.runtime_exe is not None):
parser.error("SDK builds do not accept --platform or --runtime-exe")
output_dir = args.output_dir.resolve()
output_dir.mkdir(parents=True, exist_ok=True)
with tempfile.TemporaryDirectory(prefix="dsh-python-release-") as temporary:
staging = Path(temporary) / args.package
if args.package == "sdk":
stage_sdk(staging, version)
environment = None
expected = output_dir / f"deepseek_harness-{version}-py3-none-any.whl"
else:
platform_tag, executable_name = PLATFORMS[args.platform]
stage_runtime(staging, version, args.runtime_exe.resolve(), executable_name)
environment = {"DSH_RUNTIME_PLATFORM_TAG": platform_tag}
expected = output_dir / f"deepseek_harness_runtime_bin-{version}-py3-none-{platform_tag}.whl"
command = ["uv", "build", "--wheel", "--out-dir", str(output_dir), str(staging)]
subprocess.run(command, cwd=ROOT, env=None if environment is None else {**os.environ, **environment}, check=True)
if not expected.is_file():
raise RuntimeError(f"build did not produce expected wheel: {expected}")
verify_wheel(expected, args.package, version, None if args.platform is None else PLATFORMS[args.platform])
print(expected)
def repository_version(root: Path = ROOT) -> str:
package_json = root / "package.json"
try:
payload = json.loads(package_json.read_text())
except (OSError, json.JSONDecodeError) as error:
raise ValueError(f"could not read repository version from {package_json}") from error
version = payload.get("version") if isinstance(payload, dict) else None
if not isinstance(version, str) or re.fullmatch(r"\d+\.\d+\.\d+", version) is None:
raise ValueError(
f"{package_json} version must be stable X.Y.Z, got {version!r}"
)
return version
def validate_release_tag(tag: str | None, version: str) -> None:
if tag is None:
return
expected = f"python-v{version}"
if tag != expected:
raise ValueError(
f"release tag must match repository version: expected {expected!r}, got {tag!r}"
)
def copy_package(source: Path, destination: Path) -> None:
shutil.copytree(
source,
destination,
ignore=shutil.ignore_patterns(
".venv",
".pytest_cache",
"__pycache__",
"*.pyc",
"dist",
"node_modules",
"dsh-jsonrpc-agent-pkg-*",
),
)
def rewrite_version(pyproject: Path, version: str) -> None:
text, count = re.subn(
r'^version = "[^"]+"$',
f'version = "{version}"',
pyproject.read_text(),
count=1,
flags=re.MULTILINE,
)
if count != 1:
raise RuntimeError(f"could not rewrite version in {pyproject}")
pyproject.write_text(text)
def stage_sdk(destination: Path, version: str) -> None:
copy_package(ROOT / "python" / "sdk", destination)
pyproject = destination / "pyproject.toml"
rewrite_version(pyproject, version)
text, count = re.subn(
r'"deepseek-harness-runtime-bin==[^"]+"',
f'"deepseek-harness-runtime-bin=={version}"',
pyproject.read_text(),
count=1,
)
if count != 1:
raise RuntimeError("SDK must contain exactly one runtime dependency pin")
pyproject.write_text(text)
def stage_runtime(destination: Path, version: str, executable: Path, executable_name: str) -> None:
if not executable.is_file():
raise FileNotFoundError(f"runtime executable does not exist: {executable}")
if executable.stat().st_mode & stat.S_IXUSR == 0:
raise PermissionError(f"runtime executable is not executable: {executable}")
copy_package(ROOT / "python" / "sdk-runtime", destination)
rewrite_version(destination / "pyproject.toml", version)
runtime_dir = destination / "src" / "deepseek_harness_runtime" / "runtime"
runtime_dir.mkdir(parents=True, exist_ok=True)
destination_executable = runtime_dir / executable_name
shutil.copyfile(executable, destination_executable)
destination_executable.chmod(executable.stat().st_mode & 0o777)
def verify_wheel(
wheel: Path,
package: str,
version: str,
platform: tuple[str, str] | None,
) -> None:
expected_tag = "py3-none-any" if platform is None else f"py3-none-{platform[0]}"
with zipfile.ZipFile(wheel) as archive:
wheel_metadata_path = next(name for name in archive.namelist() if name.endswith(".dist-info/WHEEL"))
metadata_path = next(name for name in archive.namelist() if name.endswith(".dist-info/METADATA"))
wheel_metadata = email.message_from_bytes(archive.read(wheel_metadata_path))
metadata = email.message_from_bytes(archive.read(metadata_path))
if wheel_metadata.get_all("Tag") != [expected_tag]:
raise RuntimeError(f"{wheel} has wrong WHEEL tags: {wheel_metadata.get_all('Tag')}")
if metadata.get("Version") != version:
raise RuntimeError(f"{wheel} has version {metadata.get('Version')}, expected {version}")
executables = [name for name in archive.namelist() if "/runtime/dsh-jsonrpc-agent-pkg-" in name]
if package == "runtime":
assert platform is not None
if len(executables) != 1 or not executables[0].endswith(f"/runtime/{platform[1]}"):
raise RuntimeError(f"{wheel} must contain exactly {platform[1]}, found {executables}")
mode = archive.getinfo(executables[0]).external_attr >> 16
if mode & stat.S_IXUSR == 0:
raise RuntimeError(f"{wheel} runtime executable lost its executable bit")
elif executables:
raise RuntimeError(f"SDK wheel unexpectedly contains runtime executables: {executables}")
if package == "sdk":
requirements = metadata.get_all("Requires-Dist") or []
expected_requirement = f"deepseek-harness-runtime-bin=={version}"
if expected_requirement not in requirements:
raise RuntimeError(f"{wheel} does not pin {expected_requirement}; found {requirements}")
if __name__ == "__main__":
main()

View File

@@ -61,6 +61,9 @@ function readJson(path: string): PackageManifest {
return JSON.parse(readFileSync(path, 'utf8')) as PackageManifest
}
const rootManifest = readJson(join(root, 'package.json'))
const repositoryVersion = rootManifest.version
/** Repo-relative dirs holding a package.json, walked to the configured depth. */
function packageDirs(base: string, depth: number): string[] {
if (depth === 1) {
@@ -78,7 +81,7 @@ function packageDirs(base: string, depth: number): string[] {
function workspaceManifests(): WorkspaceManifest[] {
const manifests: WorkspaceManifest[] = [
{ dir: '.', manifest: readJson(join(root, 'package.json')) },
{ dir: '.', manifest: rootManifest },
]
for (const { dir: base, depth } of workspaceGlobs) {
@@ -107,7 +110,7 @@ const dshBinPackageFiles = [
const dshWorkerPackageFiles = [
'lib/index.js',
'lib/worker.js',
'lib/worker.cjs',
'lib/types/**/*.d.ts',
'lib/types/**/*.d.ts.map',
'src',
@@ -147,8 +150,8 @@ function checkWorkspace({ dir, manifest }: WorkspaceManifest): string[] {
if (peer && dev && peer !== dev) {
errors.push(`${label}: cordis peer (${peer}) and dev (${dev}) ranges must match`)
}
if (manifest.version !== '0.0.1') {
errors.push(`${label}: package.json must set "version": "0.0.1"`)
if (manifest.version !== repositoryVersion) {
errors.push(`${label}: package.json version must match root version ${repositoryVersion ?? '(missing)'}`)
}
if (manifest.type !== 'module') {
errors.push(`${label}: package.json must set "type": "module"`)
@@ -205,7 +208,16 @@ function checkHierarchyShape(): string[] {
return errors
}
const errors = [...workspaceManifests().flatMap(checkWorkspace), ...checkHierarchyShape()]
function checkRepositoryVersion(): string[] {
if (repositoryVersion && /^\d+\.\d+\.\d+$/.test(repositoryVersion)) return []
return ['package.json: version must be stable X.Y.Z']
}
const errors = [
...checkRepositoryVersion(),
...workspaceManifests().flatMap(checkWorkspace),
...checkHierarchyShape(),
]
if (errors.length > 0) {
console.error(errors.join('\n'))
process.exitCode = 1

View File

@@ -129,6 +129,7 @@ function gatesForMode(selected: Mode): Gate[] {
case 'ci-lint':
return [
lintGate(),
pnpmScript('duplication', 'duplication'),
]
case 'ci-coverage':
return [
@@ -151,7 +152,9 @@ function gatesForMode(selected: Mode): Gate[] {
]
case 'pre-push':
return [
pnpmScript('runtime-closure', 'verify-runtime-closure', { label: 'runtime closure' }),
pnpmScript('test', 'test'),
pnpmScript('duplication', 'duplication'),
pnpmScript('snapshot', 'test:snapshot'),
pnpmScript('build', 'build'),
...hygieneLeafGates({ artifactNeeds: ['build'] }),
@@ -163,9 +166,11 @@ function gatesForMode(selected: Mode): Gate[] {
function ciPrimaryGates(): Gate[] {
return [
pnpmScript('runtime-closure', 'verify-runtime-closure', { label: 'runtime closure' }),
pnpmScript('constraints', 'constraints'),
pnpmScript('typecheck', 'typecheck'),
lintGate(),
pnpmScript('duplication', 'duplication'),
coverageGate(),
pnpmScript('snapshot', 'test:snapshot'),
demoSmokeGate({ needs: ['lint'] }),
@@ -184,6 +189,7 @@ function ciPrimaryGates(): Gate[] {
function ciStaticGates(): Gate[] {
return [
pnpmScript('runtime-closure', 'verify-runtime-closure', { label: 'runtime closure' }),
pnpmScript('constraints', 'constraints'),
demoSmokeGate(),
...docSyncLeafGates(),
@@ -327,7 +333,7 @@ function builtBinSmokeGate(): Gate {
'packages/ui/stdio-agent/tests/built-bin.e2e.ts',
'packages/ui/acp-agent/tests/built-bin.e2e.ts',
// The worker-entry packages' built bundles: the only automated proof
// that lib/index.js resolves its sibling lib/worker.js under plain node
// that lib/index.js resolves its sibling lib/worker.cjs under plain node
// (the e2e lane runs unbuilt, so these files self-skip there).
'packages/workflow/workflow-workerthread/tests/built-worker.e2e.ts',
'packages/code-runtime/code-runtime-worker/tests/built-lib.e2e.ts',

View File

@@ -0,0 +1,794 @@
#!/usr/bin/env python3
"""Keyless full-turn and snapshot smoke for the Python SDK runtime."""
from __future__ import annotations
import argparse
import difflib
import json
import os
import queue
import subprocess
import tempfile
import threading
import time
from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer
from pathlib import Path
from typing import TYPE_CHECKING, Callable
if TYPE_CHECKING:
from deepseek_harness import TurnResult
EXPECTED_TEXT = "runtime smoke ok"
CODE_PROMPT = "Use run_code to compute the packaged worker smoke value."
CODE_WORKER_TEXT = "code worker smoke ok"
WORKFLOW_PROMPT = "Use workflow to compute the packaged worker smoke value without agents."
WORKFLOW_WORKER_TEXT = "workflow worker smoke ok"
SNAPSHOT_PROMPT = "Run the advanced packaged-runtime snapshot scenario."
SNAPSHOT_SESSION_ID = "advanced-executable"
SNAPSHOT_DIRECT_CHILD_PROMPT = "Reply with exactly DIRECT_CHILD_OK and nothing else."
SNAPSHOT_WORKFLOW_CHILD_PROMPT = "Reply with exactly WORKFLOW_CHILD_OK and nothing else."
SNAPSHOT_FINAL_TEXT = "ADVANCED_EXECUTABLE_OK"
SNAPSHOT_MOUNT_CODE = """\
return (ctx) => {
harness.registerTool(ctx, harness.defineTool({
name: 'snapshot_double',
description: 'Double a number for executable snapshot verification.',
parameters: { value: { type: 'number', required: true } },
async execute(args) {
return [{ type: 'text', text: String(args.value * 2) }]
}
}))
}
"""
SNAPSHOT_WORKFLOW_SCRIPT = (
"phase('Delegate')\n"
f"const reply = await agent('{SNAPSHOT_WORKFLOW_CHILD_PROMPT}', {{ label: 'workflow-child' }})\n"
"return { reply }"
)
SNAPSHOT_DIRECTORY = (
Path(__file__).resolve().parent / "snapshots" / "python-sdk-single-exe" / "advanced"
)
SNAPSHOT_FILENAMES = ("result.json", "session.jsonl", "session.1.jsonl", "session.2.jsonl")
CUSTOM_CORDIS = """\
- id: jsonrpc
name: '@deepseek-ai/dsh-jsonrpc'
- id: agent-core
name: '@deepseek-ai/dsh-agent-core'
config:
tools:
mode: both
- id: sessions
name: '@deepseek-ai/dsh-session-persistence-jsonl'
config:
root: !!js process.env.DSH_SESSION_ROOT
- id: bash
name: '@deepseek-ai/dsh-bash-local'
config:
cwd: !!js process.env.DSH_CWD
- id: code-runtime
name: '@deepseek-ai/dsh-code-runtime-worker'
- id: subagents
name: '@deepseek-ai/dsh-subagent'
- id: subagent-spawn
name: '@deepseek-ai/dsh-subagent-spawn'
config:
providerName: spawn
- id: subagent-tool
name: '@deepseek-ai/dsh-tool-subagent'
config:
provider: spawn
- id: workflow-engine
name: '@deepseek-ai/dsh-workflow-workerthread'
config:
provider: spawn
- id: workflow-tool
name: '@deepseek-ai/dsh-tool-workflow'
- id: cordis-tool
name: '@deepseek-ai/dsh-tool-cordis'
"""
class MockModelHandler(BaseHTTPRequestHandler):
"""Return deterministic text, worker, and orchestration completions."""
requests: list[dict[str, object]] = []
def do_POST(self) -> None:
content_length = int(self.headers.get("content-length", "0"))
body = json.loads(self.rfile.read(content_length))
self.requests.append(body)
self.send_response(200)
self.send_header("content-type", "text/event-stream")
self.end_headers()
chunks = completion_chunks(body)
for chunk in chunks:
self.wfile.write(f"data: {json.dumps(chunk)}\n\n".encode())
self.wfile.write(b"data: [DONE]\n\n")
self.wfile.flush()
def log_message(self, _format: str, *_args: object) -> None:
return
def completion_chunks(body: dict[str, object]) -> list[dict[str, object]]:
"""Choose the next deterministic model response from request history."""
messages = body.get("messages")
if not isinstance(messages, list) or not messages:
raise AssertionError(f"model request has no messages: {body}")
latest = messages[-1]
if not isinstance(latest, dict):
raise AssertionError(f"model request has an invalid latest message: {body}")
if latest.get("role") == "tool":
call_id, tool_name = latest_tool_call(messages)
tool_text = message_text(latest.get("content"))
advanced = advanced_tool_followup(body, call_id, tool_name, tool_text)
if advanced is not None:
return advanced
if "42" not in tool_text:
raise AssertionError(f"{tool_name} worker returned no expected value: {latest}")
if tool_name == "run_code":
return text_chunks(CODE_WORKER_TEXT)
if tool_name == "workflow":
return text_chunks(WORKFLOW_WORKER_TEXT)
raise AssertionError(f"unexpected tool follow-up: {tool_name}")
prompt = message_text(latest.get("content"))
if prompt == SNAPSHOT_DIRECT_CHILD_PROMPT:
return text_chunks("DIRECT_CHILD_OK")
if prompt == SNAPSHOT_WORKFLOW_CHILD_PROMPT:
return text_chunks("WORKFLOW_CHILD_OK")
if prompt == SNAPSHOT_PROMPT:
assert_advertised_tool(body, "cordis_mount")
return tool_call_chunks(
"advanced-mount",
"cordis_mount",
{"code": SNAPSHOT_MOUNT_CODE},
)
if prompt == CODE_PROMPT:
assert_advertised_tool(body, "run_code")
return tool_call_chunks("call-code-worker", "run_code", {"code": "return 6 * 7"})
if prompt == WORKFLOW_PROMPT:
assert_advertised_tool(body, "workflow")
return tool_call_chunks(
"call-workflow-worker",
"workflow",
{
"script": "return 6 * 7",
"meta": {
"name": "pkg-worker-smoke",
"description": "exercise the packaged workflow worker",
},
},
)
return text_chunks(EXPECTED_TEXT)
def advanced_tool_followup(
body: dict[str, object],
call_id: str,
tool_name: str,
tool_text: str,
) -> list[dict[str, object]] | None:
"""Advance the executable snapshot's deterministic parent tool chain."""
if not call_id.startswith("advanced-"):
return None
if call_id == "advanced-mount" and tool_name == "cordis_mount":
if "mounted dyn-1" not in tool_text:
raise AssertionError(f"cordis_mount returned no mount id: {tool_text}")
assert_advertised_tool(body, "run_code")
assert_advertised_tool(body, "snapshot_double")
return tool_call_chunks(
"advanced-code",
"run_code",
{"code": "return await tools.snapshot_double({ value: 21 })"},
)
if call_id == "advanced-code" and tool_name == "run_code":
if "42" not in tool_text:
raise AssertionError(f"run_code returned no dynamic-tool value: {tool_text}")
assert_advertised_tool(body, "subagent")
return tool_call_chunks(
"advanced-direct-child",
"subagent",
{
"description": "Check direct child",
"prompt": SNAPSHOT_DIRECT_CHILD_PROMPT,
},
)
if call_id == "advanced-direct-child" and tool_name == "subagent":
if "DIRECT_CHILD_OK" not in tool_text:
raise AssertionError(f"subagent returned no expected child value: {tool_text}")
assert_advertised_tool(body, "workflow")
return tool_call_chunks(
"advanced-workflow",
"workflow",
{
"script": SNAPSHOT_WORKFLOW_SCRIPT,
"meta": {
"name": "advanced-exe-snapshot",
"description": "exercise one packaged workflow child",
},
},
)
if call_id == "advanced-workflow" and tool_name == "workflow":
if "WORKFLOW_CHILD_OK" not in tool_text:
raise AssertionError(f"workflow returned no expected child value: {tool_text}")
assert_advertised_tool(body, "cordis_unmount")
return tool_call_chunks(
"advanced-unmount",
"cordis_unmount",
{"id": "dyn-1"},
)
if call_id == "advanced-unmount" and tool_name == "cordis_unmount":
if "unmounted dyn-1" not in tool_text:
raise AssertionError(f"cordis_unmount returned no disposal result: {tool_text}")
if "snapshot_double" in advertised_tool_names(body):
raise AssertionError("snapshot_double remained advertised after cordis_unmount")
return text_chunks(SNAPSHOT_FINAL_TEXT)
raise AssertionError(f"unexpected advanced tool follow-up: {call_id} {tool_name}: {tool_text}")
def text_chunks(text: str) -> list[dict[str, object]]:
"""Build a complete streaming text response."""
return [
{"choices": [{"delta": {"role": "assistant", "content": None, "reasoning_content": ""}}]},
{"choices": [{"delta": {"content": text}}]},
{
"choices": [{"delta": {"content": ""}, "finish_reason": "stop"}],
"usage": {"prompt_tokens": 3, "completion_tokens": 3},
},
]
def tool_call_chunks(call_id: str, name: str, arguments: dict[str, object]) -> list[dict[str, object]]:
"""Build a complete streaming function-call response."""
return [
{"choices": [{"delta": {"role": "assistant", "content": None, "reasoning_content": ""}}]},
{
"choices": [{
"delta": {
"tool_calls": [{
"index": 0,
"id": call_id,
"type": "function",
"function": {"name": name, "arguments": json.dumps(arguments)},
}],
},
}],
},
{
"choices": [{"delta": {"content": ""}, "finish_reason": "tool_calls"}],
"usage": {"prompt_tokens": 3, "completion_tokens": 3},
},
]
def latest_tool_call(messages: list[object]) -> tuple[str, str]:
"""Find the assistant call id and name paired with the latest tool result."""
for message in reversed(messages[:-1]):
if not isinstance(message, dict):
continue
calls = message.get("tool_calls")
if not isinstance(calls, list):
continue
for call in reversed(calls):
if not isinstance(call, dict):
continue
function = call.get("function")
call_id = call.get("id")
if (
isinstance(call_id, str)
and isinstance(function, dict)
and isinstance(function.get("name"), str)
):
return call_id, function["name"]
raise AssertionError(f"tool result has no preceding assistant tool call: {messages}")
def message_text(content: object) -> str:
"""Read OpenAI text content in either string or block-list form."""
if isinstance(content, str):
return content
if isinstance(content, list):
return "".join(
block.get("text", "")
for block in content
if isinstance(block, dict) and isinstance(block.get("text"), str)
)
return ""
def advertised_tool_names(body: dict[str, object]) -> set[str]:
"""Return the model-facing tool names advertised on one request."""
tools = body.get("tools")
if not isinstance(tools, list):
raise AssertionError(f"model request advertised no tools: {body}")
names: set[str] = set()
for tool in tools:
if not isinstance(tool, dict):
continue
function = tool.get("function")
if isinstance(function, dict) and isinstance(function.get("name"), str):
names.add(function["name"])
return names
def assert_advertised_tool(body: dict[str, object], expected: str) -> None:
"""Require the packaged deployment to expose the requested tool."""
names = advertised_tool_names(body)
if expected not in names:
raise AssertionError(f"model request did not advertise {expected}: {names}")
class MockModel:
def __enter__(self) -> "MockModel":
MockModelHandler.requests.clear()
self.server = ThreadingHTTPServer(("127.0.0.1", 0), MockModelHandler)
self.thread = threading.Thread(target=self.server.serve_forever, daemon=True)
self.thread.start()
host, port = self.server.server_address
self.url = f"http://{host}:{port}"
return self
def __exit__(self, _exc_type: object, _exc: object, _tb: object) -> None:
self.server.shutdown()
self.server.server_close()
self.thread.join(timeout=5)
def main() -> None:
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument(
"--scenario",
choices=("all", "sdk-default", "sdk-custom", "sdk-snapshot", "direct"),
default="all",
)
parser.add_argument("--exe", type=Path)
parser.add_argument("--update-snapshots", action="store_true")
args = parser.parse_args()
if args.scenario in {"all", "sdk-custom", "sdk-snapshot", "direct"} and args.exe is None:
parser.error("--exe is required for custom, snapshot, and direct scenarios")
if args.update_snapshots and args.scenario not in {"all", "sdk-snapshot"}:
parser.error("--update-snapshots requires --scenario sdk-snapshot or all")
if args.exe is not None and not args.exe.is_file():
parser.error(f"runtime executable does not exist: {args.exe}")
with MockModel() as model:
if args.scenario in {"all", "sdk-default"}:
smoke_sdk_default(model.url)
if args.scenario in {"all", "sdk-custom"}:
assert args.exe is not None
smoke_sdk_custom(model.url, args.exe.resolve())
if args.scenario in {"all", "sdk-snapshot"}:
assert args.exe is not None
smoke_sdk_snapshot(model.url, args.exe.resolve(), args.update_snapshots)
if args.scenario in {"all", "direct"}:
assert args.exe is not None
smoke_direct(model.url, args.exe.resolve())
if not MockModelHandler.requests:
raise AssertionError("mock model endpoint received no requests")
print(f"smoke-python-runtime: {args.scenario} passed")
def smoke_sdk_default(base_url: str) -> None:
from deepseek_harness import DeepSeekHarness
with tempfile.TemporaryDirectory(prefix="dsh-sdk-default-") as temporary:
root = Path(temporary).resolve()
sessions = root / "sessions"
with DeepSeekHarness(
model="smoke-model",
cwd=str(root),
session_root=str(sessions),
api_key="sk-keyless-smoke",
base_url=base_url,
request_timeout_seconds=60,
) as harness:
result = harness.run("reply with the smoke text", session_id="default-smoke")
assert result.status == "ok", result
assert result.final_response == EXPECTED_TEXT, result.final_response
assert_session_log(sessions, root, EXPECTED_TEXT)
def smoke_sdk_custom(base_url: str, executable: Path) -> None:
from deepseek_harness import DeepSeekHarness
with tempfile.TemporaryDirectory(prefix="dsh-sdk-custom-") as temporary:
root = Path(temporary).resolve()
sessions = root / "sessions"
cordis = root / "cordis.yml"
cordis.write_text(CUSTOM_CORDIS)
with DeepSeekHarness(
model="smoke-model",
cwd=str(root),
session_root=str(sessions),
cordis=str(cordis),
runtime_bin=str(executable),
api_key="sk-keyless-smoke",
base_url=base_url,
request_timeout_seconds=60,
) as harness:
text_result = harness.run("reply with the smoke text", session_id="custom-smoke")
code_result = harness.run(CODE_PROMPT, session_id="custom-smoke")
workflow_result = harness.run(WORKFLOW_PROMPT, session_id="custom-smoke")
assert text_result.status == "ok", text_result
assert text_result.final_response == EXPECTED_TEXT, text_result.final_response
assert code_result.status == "ok", code_result
assert code_result.final_response == CODE_WORKER_TEXT, code_result.final_response
assert workflow_result.status == "ok", workflow_result
assert workflow_result.final_response == WORKFLOW_WORKER_TEXT, workflow_result.final_response
assert_session_log(sessions, root, EXPECTED_TEXT, CODE_WORKER_TEXT, WORKFLOW_WORKER_TEXT)
def smoke_sdk_snapshot(base_url: str, executable: Path, update_snapshots: bool) -> None:
"""Drive and compare the advanced SDK/executable behavioral snapshot."""
from deepseek_harness import DeepSeekHarness
with tempfile.TemporaryDirectory(prefix="dsh-sdk-snapshot-") as temporary:
root = Path(temporary).resolve()
sessions = root / "sessions"
cordis = root / "cordis.yml"
cordis.write_text(CUSTOM_CORDIS)
with DeepSeekHarness(
model="smoke-model",
cwd=str(root),
session_root=str(sessions),
cordis=str(cordis),
runtime_bin=str(executable),
api_key="sk-keyless-smoke",
base_url=base_url,
request_timeout_seconds=60,
) as harness:
result = harness.run(SNAPSHOT_PROMPT, session_id=SNAPSHOT_SESSION_ID)
assert result.status == "ok", result
assert result.final_response == SNAPSHOT_FINAL_TEXT, result.final_response
methods = [notification.method for notification in result.notifications]
if methods.count("subagent.started") != 2 or methods.count("subagent.finished") != 2:
raise AssertionError(f"advanced snapshot emitted unexpected subagent lifecycle: {methods}")
if not any(event.get("type") == "tool/code-dispatch" for event in result.events):
raise AssertionError("advanced snapshot emitted no tool/code-dispatch event")
logs = read_session_logs(sessions)
child_ids = snapshot_child_ids(result)
expected_ids = {SNAPSHOT_SESSION_ID, *child_ids}
if set(logs) != expected_ids:
raise AssertionError(f"advanced snapshot expected parent plus two child logs: {sorted(logs)}")
if "DIRECT_CHILD_OK" not in render_jsonl(logs[child_ids[0]]):
raise AssertionError("first advanced child log has no direct-subagent result")
if "WORKFLOW_CHILD_OK" not in render_jsonl(logs[child_ids[1]]):
raise AssertionError("second advanced child log has no workflow-subagent result")
files = build_snapshot_files(result, logs, child_ids, root)
compare_snapshot_files(files, update_snapshots)
def smoke_direct(base_url: str, executable: Path) -> None:
with tempfile.TemporaryDirectory(prefix="dsh-direct-") as temporary:
root = Path(temporary).resolve()
sessions = root / "sessions"
cordis = root / "cordis.yml"
cordis.write_text(CUSTOM_CORDIS)
environment = {
**os.environ,
"DSH_CORDIS_CONFIG": str(cordis),
"DSH_SESSION_ROOT": str(sessions),
"DSH_CWD": str(root),
"DEEPSEEK_API_KEY": "sk-keyless-smoke",
"DEEPSEEK_BASE_URL": base_url,
}
peer = RuntimePeer([str(executable)], root, environment)
try:
peer.send({"jsonrpc": "2.0", "id": "initialize", "method": "initialize", "params": {"cwd": str(root), "model": "smoke-model"}})
peer.read_until(lambda message: message.get("id") == "initialize")
peer.send({
"jsonrpc": "2.0",
"id": "prompt",
"method": "session/prompt",
"params": {"sessionId": "direct-smoke", "contentBlocks": [{"type": "text", "text": "reply with the smoke text"}]},
})
messages = peer.read_until(lambda message: message.get("id") == "prompt")
if not any(message.get("method") == "session.finished" and message.get("params", {}).get("status") == "ok" for message in messages):
messages.extend(peer.read_until(lambda message: message.get("method") == "session.finished"))
event_text = json.dumps(messages)
if EXPECTED_TEXT not in event_text:
raise AssertionError(f"direct runtime emitted no final response: {messages}")
peer.send({"jsonrpc": "2.0", "id": "shutdown", "method": "shutdown"})
peer.read_until(lambda message: message.get("id") == "shutdown")
finally:
peer.close()
assert_session_log(sessions, root, EXPECTED_TEXT)
class RuntimePeer:
def __init__(self, argv: list[str], cwd: Path, environment: dict[str, str]) -> None:
self.process = subprocess.Popen(
argv,
cwd=cwd,
env=environment,
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
text=True,
encoding="utf-8",
bufsize=1,
)
self.stdout: queue.Queue[str | None] = queue.Queue()
self.stderr: list[str] = []
threading.Thread(target=self._read_stdout, daemon=True).start()
threading.Thread(target=self._read_stderr, daemon=True).start()
def send(self, message: dict[str, object]) -> None:
if self.process.stdin is None:
raise RuntimeError("runtime stdin is unavailable")
self.process.stdin.write(json.dumps(message) + "\n")
self.process.stdin.flush()
def read_until(self, predicate: Callable[[dict[str, object]], bool]) -> list[dict[str, object]]:
deadline = time.monotonic() + 60
messages: list[dict[str, object]] = []
while time.monotonic() < deadline:
try:
line = self.stdout.get(timeout=min(0.25, deadline - time.monotonic()))
except queue.Empty:
continue
if line is None:
raise RuntimeError(f"runtime exited before expected message; stderr: {''.join(self.stderr)}")
try:
message = json.loads(line)
except json.JSONDecodeError:
continue
messages.append(message)
if predicate(message):
return messages
raise TimeoutError(f"runtime timed out; messages={messages}; stderr={''.join(self.stderr)}")
def close(self) -> None:
if self.process.stdin is not None and not self.process.stdin.closed:
self.process.stdin.close()
try:
self.process.wait(timeout=10)
except subprocess.TimeoutExpired:
self.process.kill()
self.process.wait()
if self.process.returncode not in {0, -15}:
raise RuntimeError(f"runtime exited {self.process.returncode}; stderr: {''.join(self.stderr)}")
def _read_stdout(self) -> None:
assert self.process.stdout is not None
for line in self.process.stdout:
self.stdout.put(line)
self.stdout.put(None)
def _read_stderr(self) -> None:
assert self.process.stderr is not None
self.stderr.extend(self.process.stderr)
def assert_session_log(sessions: Path, cwd: Path, *expected_texts: str) -> None:
logs = list(sessions.rglob("*.jsonl"))
if len(logs) != 1:
raise AssertionError(f"expected one JSONL session log under {sessions}, found {logs}")
lines = logs[0].read_text().splitlines()
header = json.loads(lines[0])
if header.get("cwd") != str(cwd):
raise AssertionError(f"session header cwd is not absolute/canonical: {header}")
rendered = "\n".join(lines)
for expected in expected_texts:
if expected not in rendered:
raise AssertionError(f"session log has no {expected!r} response: {logs[0]}")
def read_session_logs(sessions: Path) -> dict[str, list[dict[str, object]]]:
"""Parse every persisted JSONL session into a map keyed by header id."""
logs: dict[str, list[dict[str, object]]] = {}
for path in sorted(sessions.rglob("*.jsonl")):
records = [
json.loads(line)
for line in path.read_text(encoding="utf-8").splitlines()
if line
]
if not records or records[0].get("type") != "session":
raise AssertionError(f"session log has no header: {path}")
session_id = records[0].get("id")
if not isinstance(session_id, str):
raise AssertionError(f"session log header has no string id: {path}")
if session_id in logs:
raise AssertionError(f"duplicate persisted session id: {session_id}")
logs[session_id] = records
return logs
def snapshot_child_ids(result: "TurnResult") -> list[str]:
"""Return the two child session ids in their SDK notification order."""
child_ids: list[str] = []
for notification in result.notifications:
if notification.method != "subagent.started":
continue
payload = notification.payload
if payload.get("parentSessionId") != SNAPSHOT_SESSION_ID:
continue
child_id = payload.get("childSessionId")
if isinstance(child_id, str) and child_id not in child_ids:
child_ids.append(child_id)
if len(child_ids) != 2:
raise AssertionError(f"advanced snapshot expected two child session ids: {child_ids}")
return child_ids
def build_snapshot_files(
result: "TurnResult",
logs: dict[str, list[dict[str, object]]],
child_ids: list[str],
cwd: Path,
) -> dict[str, str]:
"""Render the SDK result and three persisted logs into stable goldens."""
replacements = [(str(cwd), "{{cwd}}"), (SNAPSHOT_SESSION_ID, "{{parent}}")]
for index, child_id in enumerate(child_ids, start=1):
replacements.append((child_id, f"{{{{child-{index}}}}}"))
agent_id = snapshot_agent_id(result, child_id)
replacements.append((agent_id, f"{{{{agent-{index}}}}}"))
replacements.sort(key=lambda pair: len(pair[0]), reverse=True)
result_value = {
"session_id": result.session_id,
"status": result.status,
"final_response": result.final_response,
"events": result.events,
"notifications": [
{"method": notification.method, "payload": notification.payload}
for notification in result.notifications
],
"session_root": result.session_root,
}
normalized_result = normalize_snapshot_value(result_value, replacements)
files = {
"result.json": json.dumps(normalized_result, indent=2, ensure_ascii=False) + "\n",
"session.jsonl": render_jsonl(
[normalize_snapshot_value(record, replacements) for record in logs[SNAPSHOT_SESSION_ID]]
),
}
for index, child_id in enumerate(child_ids, start=1):
files[f"session.{index}.jsonl"] = render_jsonl(
[normalize_snapshot_value(record, replacements) for record in logs[child_id]]
)
if tuple(files) != SNAPSHOT_FILENAMES:
raise AssertionError(f"advanced snapshot file set drifted: {tuple(files)}")
return files
def snapshot_agent_id(result: "TurnResult", child_id: str) -> str:
"""Find the successful subagent id paired with one child session."""
for notification in result.notifications:
if notification.method != "subagent.finished":
continue
payload = notification.payload
if payload.get("childSessionId") != child_id:
continue
if payload.get("provider") != "spawn" or payload.get("status") != "ok":
raise AssertionError(f"advanced child did not finish successfully: {payload}")
agent_id = payload.get("agentId")
if isinstance(agent_id, str):
return agent_id
raise AssertionError(f"advanced snapshot has no finished agent for child {child_id}")
def normalize_snapshot_value(
value: object,
replacements: list[tuple[str, str]],
) -> object:
"""Scrub volatile values and bulky request headers without losing behavior."""
if isinstance(value, str):
normalized = value
for actual, token in replacements:
normalized = normalized.replace(actual, token)
return normalized
if isinstance(value, list):
return [normalize_snapshot_value(item, replacements) for item in value]
if not isinstance(value, dict):
return value
normalized = {
key: normalize_snapshot_value(item, replacements)
for key, item in value.items()
}
if normalized.get("type") == "session" and "createdAt" in normalized:
normalized["createdAt"] = 0
if "seq" in normalized and "time" in normalized:
normalized["time"] = 0
scrub_snapshot_header(normalized)
return normalized
def scrub_snapshot_header(value: dict[object, object]) -> None:
"""Tokenize request-header bulk while retaining delta tool names."""
data = value.get("data")
if not isinstance(data, dict):
return
if value.get("type") == "request/header":
header = data.get("header")
if not isinstance(header, dict):
return
if "system" in header:
header["system"] = "{{system}}"
tools = header.get("tools")
if isinstance(tools, list):
header["tools"] = [
tool.get("name") if isinstance(tool, dict) else "{{tools}}"
for tool in tools
]
if isinstance(header.get("messagePrefix"), list):
header["messagePrefix"] = ["{{messagePrefix}}" for _ in header["messagePrefix"]]
return
if value.get("type") != "request/header-delta":
return
system = data.get("system")
if isinstance(system, dict) and isinstance(system.get("insert"), list):
system["insert"] = ["{{system}}" for _ in system["insert"]]
tools = data.get("tools")
if isinstance(tools, dict):
for key in ("added", "changed"):
if isinstance(tools.get(key), list):
tools[key] = [scrub_snapshot_tool_schema(tool) for tool in tools[key]]
if isinstance(data.get("messagePrefix"), list):
data["messagePrefix"] = ["{{messagePrefix}}" for _ in data["messagePrefix"]]
def scrub_snapshot_tool_schema(value: object) -> object:
"""Keep a changed tool's name while tokenizing its schema bulk."""
if not isinstance(value, dict):
return value
return {
key: item if key == "name" else "{{tools}}"
for key, item in value.items()
}
def render_jsonl(records: list[object]) -> str:
"""Render parsed JSON values as compact, newline-terminated JSONL."""
return "".join(
json.dumps(record, ensure_ascii=False, separators=(",", ":")) + "\n"
for record in records
)
def compare_snapshot_files(files: dict[str, str], update: bool) -> None:
"""Write or exactly compare the advanced executable snapshot files."""
if update:
SNAPSHOT_DIRECTORY.mkdir(parents=True, exist_ok=True)
for name, content in files.items():
(SNAPSHOT_DIRECTORY / name).write_text(content, encoding="utf-8")
print(f"smoke-python-runtime: updated snapshots in {SNAPSHOT_DIRECTORY}")
existing = {
path.name
for path in SNAPSHOT_DIRECTORY.iterdir()
if path.is_file()
} if SNAPSHOT_DIRECTORY.is_dir() else set()
expected = set(SNAPSHOT_FILENAMES)
if existing != expected:
raise AssertionError(
"advanced snapshot files differ: "
f"missing={sorted(expected - existing)}, unexpected={sorted(existing - expected)}"
)
for name, actual in files.items():
expected_text = (SNAPSHOT_DIRECTORY / name).read_text(encoding="utf-8")
if actual == expected_text:
continue
diff = "".join(difflib.unified_diff(
expected_text.splitlines(keepends=True),
actual.splitlines(keepends=True),
fromfile=f"expected/{name}",
tofile=f"actual/{name}",
))
raise AssertionError(
f"advanced executable snapshot mismatch in {name}; "
"rerun with --update-snapshots after reviewing the behavior\n"
f"{diff}"
)
if __name__ == "__main__":
main()

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,13 @@
{"type":"session","version":0,"id":"{{child-1}}","createdAt":0,"cwd":"{{cwd}}","parentSession":"{{parent}}"}
{"type":"turn/start","seq":0,"time":0,"data":{"turn":1,"trigger":{"kind":"message","source":{"kind":"user"}}}}
{"type":"user/message","seq":1,"time":0,"data":{"content":[{"type":"text","text":"Reply with exactly DIRECT_CHILD_OK and nothing else."}],"source":{"kind":"user"}},"surfaceOp":"append"}
{"type":"step/start","seq":2,"time":0,"data":{"turn":1,"step":1}}
{"type":"request/header","seq":3,"time":0,"data":{"header":{"config":{"model":"smoke-model"},"system":"{{system}}","tools":["bash","bash_kill","bash_output","cordis_inspect","cordis_mount","cordis_unmount","run_code","skill","snapshot_double","subagent","workflow"]},"reason":"initial"}}
{"type":"assistant/chunk","seq":4,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"block-start","index":0,"blockType":"text"}}}
{"type":"assistant/chunk","seq":5,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"text-delta","index":0,"text":"DIRECT_CHILD_OK"}}}
{"type":"assistant/chunk","seq":6,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"block-end","index":0,"block":{"type":"text","text":"DIRECT_CHILD_OK"}}}}
{"type":"assistant/chunk","seq":7,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"usage","usage":{"inputTokens":3,"outputTokens":3}}}}
{"type":"assistant/chunk","seq":8,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"finish","reason":{"kind":"stop"}}}}
{"type":"assistant/message","seq":9,"time":0,"data":{"turn":1,"step":1,"content":[{"type":"text","text":"DIRECT_CHILD_OK"}],"usage":{"inputTokens":3,"outputTokens":3}},"sourceEventSeqs":[4,5,6,7,8],"surfaceOp":"append"}
{"type":"step/end","seq":10,"time":0,"data":{"turn":1,"step":1}}
{"type":"turn/end","seq":11,"time":0,"data":{"turn":1,"reason":{"kind":"completed"}}}

View File

@@ -0,0 +1,13 @@
{"type":"session","version":0,"id":"{{child-2}}","createdAt":0,"cwd":"{{cwd}}","parentSession":"{{parent}}"}
{"type":"turn/start","seq":0,"time":0,"data":{"turn":1,"trigger":{"kind":"message","source":{"kind":"user"}}}}
{"type":"user/message","seq":1,"time":0,"data":{"content":[{"type":"text","text":"Reply with exactly WORKFLOW_CHILD_OK and nothing else."}],"source":{"kind":"user"}},"surfaceOp":"append"}
{"type":"step/start","seq":2,"time":0,"data":{"turn":1,"step":1}}
{"type":"request/header","seq":3,"time":0,"data":{"header":{"config":{"model":"smoke-model"},"system":"{{system}}","tools":["bash","bash_kill","bash_output","cordis_inspect","cordis_mount","cordis_unmount","run_code","skill","snapshot_double","subagent","workflow"]},"reason":"initial"}}
{"type":"assistant/chunk","seq":4,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"block-start","index":0,"blockType":"text"}}}
{"type":"assistant/chunk","seq":5,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"text-delta","index":0,"text":"WORKFLOW_CHILD_OK"}}}
{"type":"assistant/chunk","seq":6,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"block-end","index":0,"block":{"type":"text","text":"WORKFLOW_CHILD_OK"}}}}
{"type":"assistant/chunk","seq":7,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"usage","usage":{"inputTokens":3,"outputTokens":3}}}}
{"type":"assistant/chunk","seq":8,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"finish","reason":{"kind":"stop"}}}}
{"type":"assistant/message","seq":9,"time":0,"data":{"turn":1,"step":1,"content":[{"type":"text","text":"WORKFLOW_CHILD_OK"}],"usage":{"inputTokens":3,"outputTokens":3}},"sourceEventSeqs":[4,5,6,7,8],"surfaceOp":"append"}
{"type":"step/end","seq":10,"time":0,"data":{"turn":1,"step":1}}
{"type":"turn/end","seq":11,"time":0,"data":{"turn":1,"reason":{"kind":"completed"}}}

View File

@@ -0,0 +1,66 @@
{"type":"session","version":0,"id":"{{parent}}","createdAt":0,"cwd":"{{cwd}}"}
{"type":"turn/start","seq":0,"time":0,"data":{"turn":1,"trigger":{"kind":"message","source":{"kind":"user"}}}}
{"type":"user/message","seq":1,"time":0,"data":{"content":[{"type":"text","text":"Run the advanced packaged-runtime snapshot scenario."}],"source":{"kind":"user"}},"surfaceOp":"append"}
{"type":"step/start","seq":2,"time":0,"data":{"turn":1,"step":1}}
{"type":"request/header","seq":3,"time":0,"data":{"header":{"config":{"model":"smoke-model"},"system":"{{system}}","tools":["bash","bash_kill","bash_output","cordis_inspect","cordis_mount","cordis_unmount","run_code","skill","subagent","workflow"]},"reason":"initial"}}
{"type":"assistant/chunk","seq":4,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}}}
{"type":"assistant/chunk","seq":5,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":0,"id":"advanced-mount","name":"cordis_mount","argumentsDelta":"{\"code\": \"return (ctx) => {\\n harness.registerTool(ctx, harness.defineTool({\\n name: 'snapshot_double',\\n description: 'Double a number for executable snapshot verification.',\\n parameters: { value: { type: 'number', required: true } },\\n async execute(args) {\\n return [{ type: 'text', text: String(args.value * 2) }]\\n }\\n }))\\n}\\n\"}"}}}
{"type":"assistant/chunk","seq":6,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"advanced-mount","name":"cordis_mount","arguments":"{\"code\": \"return (ctx) => {\\n harness.registerTool(ctx, harness.defineTool({\\n name: 'snapshot_double',\\n description: 'Double a number for executable snapshot verification.',\\n parameters: { value: { type: 'number', required: true } },\\n async execute(args) {\\n return [{ type: 'text', text: String(args.value * 2) }]\\n }\\n }))\\n}\\n\"}"}}}}
{"type":"assistant/chunk","seq":7,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"usage","usage":{"inputTokens":3,"outputTokens":3}}}}
{"type":"assistant/chunk","seq":8,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}}
{"type":"assistant/message","seq":9,"time":0,"data":{"turn":1,"step":1,"content":[{"type":"tool-call","id":"advanced-mount","name":"cordis_mount","arguments":"{\"code\": \"return (ctx) => {\\n harness.registerTool(ctx, harness.defineTool({\\n name: 'snapshot_double',\\n description: 'Double a number for executable snapshot verification.',\\n parameters: { value: { type: 'number', required: true } },\\n async execute(args) {\\n return [{ type: 'text', text: String(args.value * 2) }]\\n }\\n }))\\n}\\n\"}"}],"usage":{"inputTokens":3,"outputTokens":3}},"sourceEventSeqs":[4,5,6,7,8],"surfaceOp":"append"}
{"type":"tool/call","seq":10,"time":0,"data":{"turn":1,"step":1,"callId":"advanced-mount","name":"cordis_mount","arguments":"{\"code\": \"return (ctx) => {\\n harness.registerTool(ctx, harness.defineTool({\\n name: 'snapshot_double',\\n description: 'Double a number for executable snapshot verification.',\\n parameters: { value: { type: 'number', required: true } },\\n async execute(args) {\\n return [{ type: 'text', text: String(args.value * 2) }]\\n }\\n }))\\n}\\n\"}"}}
{"type":"tool/result","seq":11,"time":0,"data":{"turn":1,"step":1,"callId":"advanced-mount","content":[{"type":"text","text":"mounted dyn-1 (plugin \"<anonymous>\", state: active)"}],"isError":false},"sourceEventSeqs":[10],"surfaceOp":"append"}
{"type":"step/end","seq":12,"time":0,"data":{"turn":1,"step":1}}
{"type":"step/start","seq":13,"time":0,"data":{"turn":1,"step":2}}
{"type":"request/header","seq":14,"time":0,"data":{"header":{"config":{"model":"smoke-model"},"system":"{{system}}","tools":["bash","bash_kill","bash_output","cordis_inspect","cordis_mount","cordis_unmount","run_code","skill","snapshot_double","subagent","workflow"]},"reason":"fallback"}}
{"type":"assistant/chunk","seq":15,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}}}
{"type":"assistant/chunk","seq":16,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":0,"id":"advanced-code","name":"run_code","argumentsDelta":"{\"code\": \"return await tools.snapshot_double({ value: 21 })\"}"}}}
{"type":"assistant/chunk","seq":17,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"advanced-code","name":"run_code","arguments":"{\"code\": \"return await tools.snapshot_double({ value: 21 })\"}"}}}}
{"type":"assistant/chunk","seq":18,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"usage","usage":{"inputTokens":3,"outputTokens":3}}}}
{"type":"assistant/chunk","seq":19,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}}
{"type":"assistant/message","seq":20,"time":0,"data":{"turn":1,"step":2,"content":[{"type":"tool-call","id":"advanced-code","name":"run_code","arguments":"{\"code\": \"return await tools.snapshot_double({ value: 21 })\"}"}],"usage":{"inputTokens":3,"outputTokens":3}},"sourceEventSeqs":[15,16,17,18,19],"surfaceOp":"append"}
{"type":"tool/call","seq":21,"time":0,"data":{"turn":1,"step":2,"callId":"advanced-code","name":"run_code","arguments":"{\"code\": \"return await tools.snapshot_double({ value: 21 })\"}"}}
{"type":"tool/code-dispatch","seq":22,"time":0,"data":{"parentCallId":"advanced-code","subCallId":"advanced-code:code:1","name":"snapshot_double","arguments":{"value":21},"isError":false,"resultSummary":"42"}}
{"type":"tool/result","seq":23,"time":0,"data":{"turn":1,"step":2,"callId":"advanced-code","content":[{"type":"text","text":"42"}],"isError":false,"meta":{"logs":[],"dispatches":1}},"sourceEventSeqs":[21],"surfaceOp":"append"}
{"type":"step/end","seq":24,"time":0,"data":{"turn":1,"step":2}}
{"type":"step/start","seq":25,"time":0,"data":{"turn":1,"step":3}}
{"type":"assistant/chunk","seq":26,"time":0,"data":{"turn":1,"step":3,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}}}
{"type":"assistant/chunk","seq":27,"time":0,"data":{"turn":1,"step":3,"chunk":{"type":"tool-call-delta","index":0,"id":"advanced-direct-child","name":"subagent","argumentsDelta":"{\"description\": \"Check direct child\", \"prompt\": \"Reply with exactly DIRECT_CHILD_OK and nothing else.\"}"}}}
{"type":"assistant/chunk","seq":28,"time":0,"data":{"turn":1,"step":3,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"advanced-direct-child","name":"subagent","arguments":"{\"description\": \"Check direct child\", \"prompt\": \"Reply with exactly DIRECT_CHILD_OK and nothing else.\"}"}}}}
{"type":"assistant/chunk","seq":29,"time":0,"data":{"turn":1,"step":3,"chunk":{"type":"usage","usage":{"inputTokens":3,"outputTokens":3}}}}
{"type":"assistant/chunk","seq":30,"time":0,"data":{"turn":1,"step":3,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}}
{"type":"assistant/message","seq":31,"time":0,"data":{"turn":1,"step":3,"content":[{"type":"tool-call","id":"advanced-direct-child","name":"subagent","arguments":"{\"description\": \"Check direct child\", \"prompt\": \"Reply with exactly DIRECT_CHILD_OK and nothing else.\"}"}],"usage":{"inputTokens":3,"outputTokens":3}},"sourceEventSeqs":[26,27,28,29,30],"surfaceOp":"append"}
{"type":"tool/call","seq":32,"time":0,"data":{"turn":1,"step":3,"callId":"advanced-direct-child","name":"subagent","arguments":"{\"description\": \"Check direct child\", \"prompt\": \"Reply with exactly DIRECT_CHILD_OK and nothing else.\"}"}}
{"type":"tool/result","seq":33,"time":0,"data":{"turn":1,"step":3,"callId":"advanced-direct-child","content":[{"type":"text","text":"DIRECT_CHILD_OK"}],"isError":false},"sourceEventSeqs":[32],"surfaceOp":"append"}
{"type":"step/end","seq":34,"time":0,"data":{"turn":1,"step":3}}
{"type":"step/start","seq":35,"time":0,"data":{"turn":1,"step":4}}
{"type":"assistant/chunk","seq":36,"time":0,"data":{"turn":1,"step":4,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}}}
{"type":"assistant/chunk","seq":37,"time":0,"data":{"turn":1,"step":4,"chunk":{"type":"tool-call-delta","index":0,"id":"advanced-workflow","name":"workflow","argumentsDelta":"{\"script\": \"phase('Delegate')\\nconst reply = await agent('Reply with exactly WORKFLOW_CHILD_OK and nothing else.', { label: 'workflow-child' })\\nreturn { reply }\", \"meta\": {\"name\": \"advanced-exe-snapshot\", \"description\": \"exercise one packaged workflow child\"}}"}}}
{"type":"assistant/chunk","seq":38,"time":0,"data":{"turn":1,"step":4,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"advanced-workflow","name":"workflow","arguments":"{\"script\": \"phase('Delegate')\\nconst reply = await agent('Reply with exactly WORKFLOW_CHILD_OK and nothing else.', { label: 'workflow-child' })\\nreturn { reply }\", \"meta\": {\"name\": \"advanced-exe-snapshot\", \"description\": \"exercise one packaged workflow child\"}}"}}}}
{"type":"assistant/chunk","seq":39,"time":0,"data":{"turn":1,"step":4,"chunk":{"type":"usage","usage":{"inputTokens":3,"outputTokens":3}}}}
{"type":"assistant/chunk","seq":40,"time":0,"data":{"turn":1,"step":4,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}}
{"type":"assistant/message","seq":41,"time":0,"data":{"turn":1,"step":4,"content":[{"type":"tool-call","id":"advanced-workflow","name":"workflow","arguments":"{\"script\": \"phase('Delegate')\\nconst reply = await agent('Reply with exactly WORKFLOW_CHILD_OK and nothing else.', { label: 'workflow-child' })\\nreturn { reply }\", \"meta\": {\"name\": \"advanced-exe-snapshot\", \"description\": \"exercise one packaged workflow child\"}}"}],"usage":{"inputTokens":3,"outputTokens":3}},"sourceEventSeqs":[36,37,38,39,40],"surfaceOp":"append"}
{"type":"tool/call","seq":42,"time":0,"data":{"turn":1,"step":4,"callId":"advanced-workflow","name":"workflow","arguments":"{\"script\": \"phase('Delegate')\\nconst reply = await agent('Reply with exactly WORKFLOW_CHILD_OK and nothing else.', { label: 'workflow-child' })\\nreturn { reply }\", \"meta\": {\"name\": \"advanced-exe-snapshot\", \"description\": \"exercise one packaged workflow child\"}}"}}
{"type":"tool/result","seq":43,"time":0,"data":{"turn":1,"step":4,"callId":"advanced-workflow","content":[{"type":"text","text":"workflow \"advanced-exe-snapshot\" completed (1 agent).\nReturn value:\n{\n \"reply\": \"WORKFLOW_CHILD_OK\"\n}"}],"isError":false},"sourceEventSeqs":[42],"surfaceOp":"append"}
{"type":"step/end","seq":44,"time":0,"data":{"turn":1,"step":4}}
{"type":"step/start","seq":45,"time":0,"data":{"turn":1,"step":5}}
{"type":"assistant/chunk","seq":46,"time":0,"data":{"turn":1,"step":5,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}}}
{"type":"assistant/chunk","seq":47,"time":0,"data":{"turn":1,"step":5,"chunk":{"type":"tool-call-delta","index":0,"id":"advanced-unmount","name":"cordis_unmount","argumentsDelta":"{\"id\": \"dyn-1\"}"}}}
{"type":"assistant/chunk","seq":48,"time":0,"data":{"turn":1,"step":5,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"advanced-unmount","name":"cordis_unmount","arguments":"{\"id\": \"dyn-1\"}"}}}}
{"type":"assistant/chunk","seq":49,"time":0,"data":{"turn":1,"step":5,"chunk":{"type":"usage","usage":{"inputTokens":3,"outputTokens":3}}}}
{"type":"assistant/chunk","seq":50,"time":0,"data":{"turn":1,"step":5,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}}
{"type":"assistant/message","seq":51,"time":0,"data":{"turn":1,"step":5,"content":[{"type":"tool-call","id":"advanced-unmount","name":"cordis_unmount","arguments":"{\"id\": \"dyn-1\"}"}],"usage":{"inputTokens":3,"outputTokens":3}},"sourceEventSeqs":[46,47,48,49,50],"surfaceOp":"append"}
{"type":"tool/call","seq":52,"time":0,"data":{"turn":1,"step":5,"callId":"advanced-unmount","name":"cordis_unmount","arguments":"{\"id\": \"dyn-1\"}"}}
{"type":"tool/result","seq":53,"time":0,"data":{"turn":1,"step":5,"callId":"advanced-unmount","content":[{"type":"text","text":"unmounted dyn-1 (plugin \"<anonymous>\")"}],"isError":false},"sourceEventSeqs":[52],"surfaceOp":"append"}
{"type":"step/end","seq":54,"time":0,"data":{"turn":1,"step":5}}
{"type":"step/start","seq":55,"time":0,"data":{"turn":1,"step":6}}
{"type":"request/header-delta","seq":56,"time":0,"data":{"system":{"keepStart":62,"keepEnd":34,"insert":[]},"tools":{"added":[],"removed":["snapshot_double"],"changed":[]}}}
{"type":"assistant/chunk","seq":57,"time":0,"data":{"turn":1,"step":6,"chunk":{"type":"block-start","index":0,"blockType":"text"}}}
{"type":"assistant/chunk","seq":58,"time":0,"data":{"turn":1,"step":6,"chunk":{"type":"text-delta","index":0,"text":"ADVANCED_EXECUTABLE_OK"}}}
{"type":"assistant/chunk","seq":59,"time":0,"data":{"turn":1,"step":6,"chunk":{"type":"block-end","index":0,"block":{"type":"text","text":"ADVANCED_EXECUTABLE_OK"}}}}
{"type":"assistant/chunk","seq":60,"time":0,"data":{"turn":1,"step":6,"chunk":{"type":"usage","usage":{"inputTokens":3,"outputTokens":3}}}}
{"type":"assistant/chunk","seq":61,"time":0,"data":{"turn":1,"step":6,"chunk":{"type":"finish","reason":{"kind":"stop"}}}}
{"type":"assistant/message","seq":62,"time":0,"data":{"turn":1,"step":6,"content":[{"type":"text","text":"ADVANCED_EXECUTABLE_OK"}],"usage":{"inputTokens":3,"outputTokens":3}},"sourceEventSeqs":[57,58,59,60,61],"surfaceOp":"append"}
{"type":"step/end","seq":63,"time":0,"data":{"turn":1,"step":6}}
{"type":"turn/end","seq":64,"time":0,"data":{"turn":1,"reason":{"kind":"completed"}}}

View File

@@ -4,7 +4,11 @@
"docs/development.md",
"docs/i18n/README.md",
"docs/i18n/translation-rules.md",
"docs/rfc/implemented/process/2026-07-02-bilingual-docs-and-pairing-gate.md"
"docs/rfc/implemented/architecture/2026-07-10-single-file-executable-sdk-runtime-distribution.md",
"docs/rfc/implemented/process/2026-07-02-bilingual-docs-and-pairing-gate.md",
"python/README.md",
"python/sdk-runtime/README.md",
"python/sdk/README.md"
],
"excluded": [
"docs/AGENTS.md",
@@ -13,6 +17,7 @@
"docs/tool-catalog.md",
"docs/persistence-catalog.md",
"docs/cordis-catalog/",
"docs/i18n/terminology.md"
"docs/i18n/terminology.md",
"python/sdk-runtime/src/deepseek_harness_runtime/runtime/node/"
]
}

View File

@@ -0,0 +1,116 @@
/**
* Verify that the Python single-exe deploy manifest explicitly supplies every
* required workspace peer of every workspace package in its dependency graph.
*
* `pnpm deploy --config.auto-install-peers=false` cannot repair an incomplete
* runtime root. Keeping the peer at the root also prevents a successful build
* from producing an executable that fails only when Cordis loads the plugin.
*/
import { readFile, readdir } from 'node:fs/promises'
import { join, resolve } from 'node:path'
import { parseArgs } from 'node:util'
interface PackageManifest {
name?: string
dependencies?: Record<string, string>
optionalDependencies?: Record<string, string>
peerDependencies?: Record<string, string>
peerDependenciesMeta?: Record<string, { optional?: boolean }>
}
interface WorkspacePackage {
path: string
manifest: PackageManifest
}
const root = resolve(import.meta.dirname, '..')
const { values } = parseArgs({
args: process.argv.slice(2),
options: { manifest: { type: 'string' } },
})
const runtimeManifestPath = resolve(root, values.manifest ?? 'python/sdk-runtime/package.json')
const runtimeManifest = await loadManifest(runtimeManifestPath)
const runtimeName = runtimeManifest.name ?? 'python/sdk-runtime'
const workspace = await loadWorkspacePackages()
const runtimeDependencies = runtimeManifest.dependencies ?? {}
const parents = new Map<string, string | undefined>()
const queue: string[] = []
for (const dependency of Object.keys(runtimeDependencies).sort()) {
if (!workspace.has(dependency)) continue
parents.set(dependency, undefined)
queue.push(dependency)
}
const failures: string[] = []
for (let index = 0; index < queue.length; index += 1) {
const packageName = queue[index]
if (packageName === undefined) continue
const current = workspace.get(packageName)
if (current === undefined) continue
const peers = current.manifest.peerDependencies ?? {}
const peerMeta = current.manifest.peerDependenciesMeta ?? {}
for (const peer of Object.keys(peers).sort()) {
if (!workspace.has(peer) || peerMeta[peer]?.optional === true) continue
if (runtimeDependencies[peer]?.startsWith('workspace:') === true) continue
failures.push(`${formatChain(runtimeName, packageName, parents)} -> ${peer}`)
}
const dependencies = {
...current.manifest.dependencies,
...current.manifest.optionalDependencies,
}
for (const dependency of Object.keys(dependencies).sort()) {
if (!workspace.has(dependency) || parents.has(dependency)) continue
parents.set(dependency, packageName)
queue.push(dependency)
}
}
if (failures.length > 0) {
console.error('verify-runtime-closure: required workspace peers are missing from python/sdk-runtime dependencies:')
for (const failure of failures) console.error(` ${failure}`)
process.exit(1)
}
console.log(`verify-runtime-closure: ${queue.length} workspace packages form a closed runtime dependency graph.`)
async function loadWorkspacePackages(): Promise<Map<string, WorkspacePackage>> {
const paths: string[] = []
for (const group of await childDirectories(join(root, 'packages'))) {
for (const packageDir of await childDirectories(join(root, 'packages', group))) {
paths.push(join(root, 'packages', group, packageDir, 'package.json'))
}
}
for (const packageDir of await childDirectories(join(root, 'vendor'))) {
paths.push(join(root, 'vendor', packageDir, 'package.json'))
}
const result = new Map<string, WorkspacePackage>()
for (const path of paths) {
const manifest = await loadManifest(path)
if (manifest.name !== undefined) result.set(manifest.name, { path, manifest })
}
return result
}
async function childDirectories(path: string): Promise<string[]> {
const entries = await readdir(path, { withFileTypes: true })
return entries.filter(entry => entry.isDirectory()).map(entry => entry.name).sort()
}
async function loadManifest(path: string): Promise<PackageManifest> {
return JSON.parse(await readFile(path, 'utf8')) as PackageManifest
}
function formatChain(
runtimeName: string,
packageName: string,
parents: ReadonlyMap<string, string | undefined>,
): string {
const chain = [packageName]
let parent = parents.get(packageName)
while (parent !== undefined) {
chain.unshift(parent)
parent = parents.get(parent)
}
return [runtimeName, ...chain].join(' -> ')
}

View File

@@ -55,8 +55,8 @@ const root = resolve(import.meta.dirname, '..')
const listMode = process.argv.includes('--list')
const writeMode = process.argv.includes('--write')
/** Scope of the bilingual contract: the root README and the docs tree. */
const SCOPE_PATTERNS = ['README.md', 'README.zh.md', 'README.i18n.yaml', 'docs/**/*.md', 'docs/**/*.i18n.yaml']
/** Scope of the bilingual contract: the root README, the docs tree, and the Python SDK tree. */
const SCOPE_PATTERNS = ['README.md', 'README.zh.md', 'README.i18n.yaml', 'docs/**/*.md', 'docs/**/*.i18n.yaml', 'python/**/*.md', 'python/**/*.i18n.yaml']
/** The enforcement frontier and the never-paired set (docs/i18n/README.md § Scope). */
interface Manifest {