Merge remote-tracking branch 'origin/master' into codex/agent-session-jsonl-location
# Conflicts: # docs/config-catalog.md # docs/cordis-catalog/services.md # docs/core-data-structures/bash.md # docs/module-graph.md # docs/rfc/INDEX.md # docs/rfc/implemented/architecture/2026-06-30-bash-stdin-env-trusted-plugin-surface.md # docs/rfc/implemented/feature/2026-06-30-hook-bridges.md # examples/acp-agent/tests/snapshots/advanced-toolchain/session.1.jsonl # examples/acp-agent/tests/snapshots/advanced-toolchain/session.2.jsonl # examples/acp-agent/tests/snapshots/advanced-toolchain/session.jsonl # examples/acp-agent/tests/snapshots/advanced-toolchain/system-prompt.golden.md # examples/acp-agent/tests/snapshots/both-mode-turn/session.jsonl # examples/acp-agent/tests/snapshots/both-mode-turn/system-prompt.golden.md # examples/acp-agent/tests/snapshots/code-mode-turn/system-prompt.golden.md # examples/acp-agent/tests/snapshots/skill-load/session.jsonl # examples/acp-agent/tests/snapshots/text-turn/session.jsonl # examples/sandbox-acp-agent/tests/snapshots/mode-switching/session.jsonl # packages/bash/bash-local/README.md # packages/bash/bash-local/src/run.ts # packages/bash/bash-local/tests/run.spec.ts # packages/bash/bash/README.md # packages/bash/tool-bash/README.md # packages/bash/tool-bash/src/index.ts # packages/bash/tool-bash/tests/tools.spec.ts # packages/cordis/tool-cordis/src/api-catalog.ts # packages/core/agent-core/src/index.ts # packages/session-persistence/session-persistence-jsonl/src/index.ts # packages/session-persistence/session-persistence-sqlite/src/index.ts # packages/session-persistence/session-persistence/README.md # packages/session-persistence/session-persistence/src/index.ts # packages/ui/acp-agent/README.md # packages/ui/stdio-agent/README.md
This commit is contained in:
@@ -2,5 +2,5 @@
|
||||
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
||||
# after editing either side, bring the other along and re-record with:
|
||||
# pnpm run verify-translation-pairing --write
|
||||
README.md: 35ed645ce0e4d5e4c88c8aae2fe33d94aea79b3e
|
||||
README.zh.md: 214c5cd1900e52f9fe479247f9940a97bb22766b
|
||||
README.md: a04a0f99c95337b4d9e073e97075654190929520
|
||||
README.zh.md: 04e58c5a399565994df721d018ee0fc8a1d86578
|
||||
+1
-1
@@ -22,7 +22,7 @@ pnpm exec tsx scripts/build-exe-for-python-sdk.ts --skip-build # lib/ artifac
|
||||
pnpm exec tsx scripts/build-exe-for-python-sdk.ts --targets=node24-linux-x64,node24-linux-arm64,node24-macos-arm64
|
||||
```
|
||||
|
||||
Products land in `dist-exe/` and are synced into this package at `sdk-runtime/src/deepseek_harness_runtime/runtime/dsh-jsonrpc-agent-pkg-<platform>-<arch>` (platform: `linux`/`macos`; arch: `x64`/`arm64`) — after a local build the SDK finds the executable with no further setup. The `build-exe-for-python-sdk` CI workflow (manual dispatch, or the `build-exe` PR label) exercises the same binaries but retains only the four release wheels. Which plugins the exe bundles and how the carriers are organized: [sdk-runtime README](sdk-runtime/README.md); the build also refreshes the dev-only node carrier (see "against the Node source" below).
|
||||
Products land in `dist-exe/` and are synced into this package at `sdk-runtime/src/deepseek_harness_runtime/runtime/dsh-jsonrpc-agent-pkg-<platform>-<arch>` (platform: `linux`/`macos`; arch: `x64`/`arm64`) — after a local build the SDK finds the executable with no further setup. The `build-exe-for-python-sdk` CI workflow (manual dispatch, or the `build-exe` PR label) exercises the same binaries. A full three-target run retains four release wheels; a subset dispatch retains the SDK wheel and selected platform wheels. Which plugins the exe bundles and how the carriers are organized: [sdk-runtime README](sdk-runtime/README.md); the build also refreshes the dev-only node carrier (see "against the Node source" below).
|
||||
|
||||
## Validating the SDK against the executable
|
||||
|
||||
|
||||
+1
-1
@@ -22,7 +22,7 @@ pnpm exec tsx scripts/build-exe-for-python-sdk.ts --skip-build # lib/ artifac
|
||||
pnpm exec tsx scripts/build-exe-for-python-sdk.ts --targets=node24-linux-x64,node24-linux-arm64,node24-macos-arm64
|
||||
```
|
||||
|
||||
产物落入 `dist-exe/`,并同步进本包的 `sdk-runtime/src/deepseek_harness_runtime/runtime/dsh-jsonrpc-agent-pkg-<platform>-<arch>`(platform:`linux`/`macos`;arch:`x64`/`arm64`),本地构建完成后 SDK 不需要额外设置就能找到可执行文件。`build-exe-for-python-sdk` CI 工作流(手动触发,或给 PR 打 `build-exe` 标签)会测试同样的二进制,但只保留 4 个发布用 wheel 包。exe 内置哪些插件、载体如何组织,见 [sdk-runtime README](sdk-runtime/README.md);构建还会顺带刷新仅供开发使用的 `node` 载体(见下文「对着 Node 源码运行」)。
|
||||
产物落入 `dist-exe/`,并同步进本包的 `sdk-runtime/src/deepseek_harness_runtime/runtime/dsh-jsonrpc-agent-pkg-<platform>-<arch>`(platform:`linux`/`macos`;arch:`x64`/`arm64`),本地构建完成后 SDK 不需要额外设置就能找到可执行文件。`build-exe-for-python-sdk` CI 工作流(手动触发,或给 PR 打 `build-exe` 标签)会测试同样的二进制。完整构建三个目标时保留 4 个发布用 wheel 包;手动选择部分目标时保留 SDK wheel 与所选平台的 wheel。exe 内置哪些插件、载体如何组织,见 [sdk-runtime README](sdk-runtime/README.md);构建还会顺带刷新仅供开发使用的 `node` 载体(见下文「对着 Node 源码运行」)。
|
||||
|
||||
## 用可执行文件验证 SDK
|
||||
|
||||
|
||||
@@ -2,5 +2,5 @@
|
||||
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
||||
# after editing either side, bring the other along and re-record with:
|
||||
# pnpm run verify-translation-pairing --write
|
||||
README.md: 4beac57526761bb150e90b60f0030ed311c4034d
|
||||
README.zh.md: c0cc0eef6a9b569105408d2f2e6321795493036a
|
||||
README.md: a28ae59971e1997f8129c04518307eabece0b6de
|
||||
README.zh.md: 10dbb6b14f488072382eb01da7621c9bbb0dbcec
|
||||
@@ -13,7 +13,7 @@ Two carriers coexist under `src/deepseek_harness_runtime/runtime/`, both injecte
|
||||
|
||||
Both carriers hold the same content, defined once: the [package.json](package.json) at this package's root is the deploy root of the single-exe pipeline — a pure dependency manifest (no code of its own) whose dependency closure IS both the plugin set compiled into the exe and the tree materialized into `runtime/node/`. Adding a plugin to the distribution means adding one dependency line there and rebuilding.
|
||||
|
||||
Missing carriers raise `FileNotFoundError` naming the acquisition routes: build via `scripts/build-exe-for-python-sdk.ts` in a deepseek-harness checkout, or install the matching platform runtime wheel produced by the `build-exe-for-python-sdk` CI workflow. The workflow retains wheels rather than standalone executable archives. Acquisition strategy is deliberately separate from the lookup interface, so an on-demand download can replace it later without touching callers.
|
||||
A missing exe raises `FileNotFoundError` naming both acquisition routes: build via `scripts/build-exe-for-python-sdk.ts` in a deepseek-harness checkout, or install the matching platform runtime wheel produced by the `build-exe-for-python-sdk` CI workflow. A missing dev-only node carrier names its sole route, the build script. The workflow retains wheels rather than standalone executable archives. Acquisition strategy is deliberately separate from the lookup interface, so an on-demand download can replace it later without touching callers.
|
||||
|
||||
Each wheel contains exactly one executable. The fixed tags are `py3-none-manylinux_2_28_x86_64`, `py3-none-manylinux_2_28_aarch64`, and `py3-none-macosx_11_0_arm64`; the build hook rejects `py3-none-any`, absent or multiple executables, and unsupported platform tags. The repository root `package.json` supplies the shared version for this package and the SDK, and a `python-vX.Y.Z` release tag must match it.
|
||||
|
||||
@@ -26,4 +26,4 @@ Each wheel contains exactly one executable. The fixed tags are `py3-none-manylin
|
||||
|
||||
## Zero-config design
|
||||
|
||||
The runtime binary always demands an explicit config (`$DSH_CORDIS_CONFIG`, or a config path as an argv positional argument) and exits loudly without one — that hard semantic is part of the runtime's design and this package does not soften it. The bin (`dsh-jsonrpc-agent`) boots only the plugins the config lists; the serving surface (the stdio JSON-RPC server) is itself one of its entries (`@deepseek-ai/dsh-jsonrpc`), and without it the booted agent has no channel to the outside. This package checks in `runtime/cordis.yml` (the JSON-RPC serving entry, agent core, preloaded DeepSeek adapter, JSONL session persistence, local bash, each parameterized by the `DSH_*` env vars the SDK sets); when the caller uses no explicit config channel, the `deepseek_harness` client injects that file's path via `DSH_CORDIS_CONFIG` (injection conditions: [sdk README](../sdk/README.md)). Zero-config is thus an explicit, visible parameter pass in the wrapper, not a hidden fallback in the runtime.
|
||||
The runtime binary always demands an explicit config (`$DSH_CORDIS_CONFIG`, or a config path as an argv positional argument) and exits loudly without one — that hard semantic is part of the runtime's design and this package does not soften it. The bin (`dsh-jsonrpc-agent`) boots only the plugins the config lists; the serving surface (the stdio JSON-RPC server) is itself one of its entries (`@deepseek-ai/dsh-jsonrpc`), and without it the booted agent has no channel to the outside. This package checks in `runtime/cordis.yml` with the JSON-RPC serving entry, agent core, a preloaded DeepSeek adapter, JSONL persistence, and local bash. The adapter reads `DEEPSEEK_API_KEY` and `DEEPSEEK_BASE_URL`, while persistence and bash use `DSH_SESSION_ROOT` and `DSH_CWD` with manual-run fallbacks. When the caller uses no explicit config channel, the `deepseek_harness` client injects that file's path via `DSH_CORDIS_CONFIG` (injection conditions: [sdk README](../sdk/README.md)). Zero-config is thus an explicit, visible parameter pass in the wrapper, not a hidden fallback in the runtime.
|
||||
@@ -13,7 +13,7 @@ Python SDK 的运行时载体包(分发名 `deepseek-harness-runtime-bin`,
|
||||
|
||||
两种载体承载相同的内容,且只定义一次:本包根目录的 [package.json](package.json) 是 single-exe 流水线的部署根目录——一份零代码的纯依赖 manifest,其依赖闭包既是编译进 exe 的插件集,也是物化到 `runtime/node/` 的文件树。往分发物里加插件,就是在那里加一行依赖再重新构建。
|
||||
|
||||
载体缺失时抛出 `FileNotFoundError` 并写明获取途径:在 deepseek-harness 检出中经 `scripts/build-exe-for-python-sdk.ts` 构建,或安装 `build-exe-for-python-sdk` CI 工作流生成的对应平台运行时 wheel 包。该工作流只保留 wheel 包,不保留独立 exe 归档。获取策略与查找接口刻意分离,之后可以换成按需下载而不改动任何调用方。
|
||||
exe 缺失时抛出 `FileNotFoundError`,并写明两种获取途径:在 deepseek-harness 检出中经 `scripts/build-exe-for-python-sdk.ts` 构建,或安装 `build-exe-for-python-sdk` CI 工作流生成的对应平台运行时 wheel 包。仅限开发的 `node` 载体缺失时只提示构建脚本这一条途径。该工作流只保留 wheel 包,不保留独立 exe 归档。获取策略与查找接口刻意分离,之后可以换成按需下载而不改动任何调用方。
|
||||
|
||||
每个 wheel 包只包含一个可执行文件。固定标签为 `py3-none-manylinux_2_28_x86_64`、`py3-none-manylinux_2_28_aarch64` 与 `py3-none-macosx_11_0_arm64`;构建钩子会拒绝 `py3-none-any`、可执行文件缺失或重复以及不支持的平台标签。仓库根目录的 `package.json` 为本包和 SDK 提供共同版本,`python-vX.Y.Z` 发布标签必须与其匹配。
|
||||
|
||||
@@ -26,4 +26,4 @@ Python SDK 的运行时载体包(分发名 `deepseek-harness-runtime-bin`,
|
||||
|
||||
## 零配置设计
|
||||
|
||||
运行时二进制始终要求显式配置(`$DSH_CORDIS_CONFIG`,或作为 argv 位置参数的配置路径),缺了就报错退出——这一硬语义是运行时设计的一部分,本包不软化它。`bin`(`dsh-jsonrpc-agent`)只启动配置里列出的插件;对外服务接口(stdio JSON-RPC 服务器)也是其中一个条目(`@deepseek-ai/dsh-jsonrpc`),缺了它,启动出的 agent 就没有对外通道。本包检入 `runtime/cordis.yml`(JSON-RPC 服务条目、`agent-core`、预载的 DeepSeek 适配器、JSONL 会话持久化、本地 bash,各项由 SDK 设置的 `DSH_*` 环境变量参数化);调用方未使用任何显式配置通道时,`deepseek_harness` 客户端把该文件路径注入 `DSH_CORDIS_CONFIG`(注入条件见 [sdk README](../sdk/README.md))。因此,零配置是包装层中一次显式、可见的参数传递,而不是运行时中的隐藏回退。
|
||||
运行时二进制始终要求显式配置(`$DSH_CORDIS_CONFIG`,或作为 argv 位置参数的配置路径),缺了就报错退出——这一硬语义是运行时设计的一部分,本包不软化它。`bin`(`dsh-jsonrpc-agent`)只启动配置里列出的插件;对外服务接口(stdio JSON-RPC 服务器)也是其中一个条目(`@deepseek-ai/dsh-jsonrpc`),缺了它,启动出的 agent 就没有对外通道。本包检入的 `runtime/cordis.yml` 包含 JSON-RPC 服务条目、`agent-core`、预载的 DeepSeek 适配器、JSONL 持久化与本地 bash。DeepSeek 适配器读取 `DEEPSEEK_API_KEY` 与 `DEEPSEEK_BASE_URL`,持久化与 bash 则使用 `DSH_SESSION_ROOT` 和 `DSH_CWD`,并为手动运行提供回退值。调用方未使用任何显式配置通道时,`deepseek_harness` 客户端把该文件路径注入 `DSH_CORDIS_CONFIG`(注入条件见 [sdk README](../sdk/README.md))。因此,零配置是包装层中一次显式、可见的参数传递,而不是运行时中的隐藏回退。
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "dsh-jsonrpc-agent-pkg",
|
||||
"description": "Deploy root of the single-exe pipeline and the single source of truth unifying 'which plugins the exe bundles' and 'what the Python runtime distributes': the dependency list below IS the exe closure. Pure manifest — no code; a deploy materializes only this package.json plus node_modules.",
|
||||
"description": "Dependency-only deploy root defining the executable and Python runtime closure; pnpm deploy materializes this manifest and node_modules.",
|
||||
"version": "0.0.1",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
@@ -33,6 +33,7 @@
|
||||
"@deepseek-ai/dsh-llm": "workspace:^",
|
||||
"@deepseek-ai/dsh-llm-deepseek": "workspace:^",
|
||||
"@deepseek-ai/dsh-llm-pi-ai": "workspace:^",
|
||||
"@deepseek-ai/dsh-permission": "workspace:^",
|
||||
"@deepseek-ai/dsh-repeat-tool-guard": "workspace:^",
|
||||
"@deepseek-ai/dsh-sandbox": "workspace:^",
|
||||
"@deepseek-ai/dsh-scope": "workspace:^",
|
||||
|
||||
@@ -10,9 +10,8 @@ readme = "README.md"
|
||||
requires-python = ">=3.10"
|
||||
license = { text = "BSD-3-Clause" }
|
||||
|
||||
# Distributions carry the platform executables (build-injected, VCS-ignored —
|
||||
# hence `artifacts`) and the checked-in runtime/cordis.yml; the dev-only node
|
||||
# closure under runtime/node/ is explicitly excluded from wheel and sdist.
|
||||
# Include the injected executable and default config; exclude the dev-only node
|
||||
# closure from wheels and sdists.
|
||||
[tool.hatch.build]
|
||||
artifacts = ["src/deepseek_harness_runtime/runtime/dsh-jsonrpc-agent-*"]
|
||||
exclude = ["src/deepseek_harness_runtime/runtime/node"]
|
||||
|
||||
@@ -1,30 +1,17 @@
|
||||
# Default runtime configuration for the bundled dsh-jsonrpc-agent. The runtime
|
||||
# binary has NO built-in fallback — it always requires an explicit config via
|
||||
# `$DSH_CORDIS_CONFIG` (wins) or an argv positional path. The Python client SDK
|
||||
# injects THIS file's path via `$DSH_CORDIS_CONFIG` when the caller supplies
|
||||
# no config and the launch resolves to the bundled runtime; that explicit
|
||||
# injection is what restores the zero-config experience. The runtime bin only
|
||||
# boots this config; the serving surface (the stdio JSON-RPC server) comes
|
||||
# from the @deepseek-ai/dsh-jsonrpc entry below.
|
||||
#
|
||||
# $DSH_SESSION_ROOT and $DSH_CWD are set by the SDK per launch; the `!!js`
|
||||
# fallbacks keep this file usable when the runtime is driven manually.
|
||||
# Bundled default config. The runtime still requires an explicit
|
||||
# $DSH_CORDIS_CONFIG or argv path; the SDK injects this path for bundled
|
||||
# zero-config launches. SDK-set session-root and cwd variables have manual-run fallbacks.
|
||||
|
||||
# The serving surface: HarnessSdkServer + line-delimited JSON-RPC transport on
|
||||
# stdio. Without this entry the runtime boots an agent nobody can talk to.
|
||||
# Stdio JSON-RPC serving surface; without it the agent has no SDK client.
|
||||
- id: jsonrpc
|
||||
name: '@deepseek-ai/dsh-jsonrpc'
|
||||
|
||||
# The agent spine bundle: session store, system prompt, tool registry, agent
|
||||
# registry, and the agent loop. No pre-created agents — the SDK server creates
|
||||
# one per session/prompt sessionId.
|
||||
# Agent spine; the SDK server creates agents per sessionId.
|
||||
- id: agent-core
|
||||
name: '@deepseek-ai/dsh-agent-core'
|
||||
|
||||
# The DeepSeek adapter, preloaded for the stock models. The adapter fails loud
|
||||
# at load without an API key, so keyless boots must still export a dummy
|
||||
# DEEPSEEK_API_KEY (initialize/shutdown never call the model). baseURL falls
|
||||
# back to the public endpoint when unset.
|
||||
# Stock DeepSeek adapters. Loading requires an API key; initialize and shutdown
|
||||
# may use a dummy key because they do not call the model.
|
||||
- id: llm-deepseek
|
||||
name: '@deepseek-ai/dsh-llm-deepseek'
|
||||
config:
|
||||
@@ -34,16 +21,13 @@
|
||||
- deepseek-v4-flash
|
||||
- deepseek-v4-pro
|
||||
|
||||
# JSONL session persistence. $DSH_SESSION_ROOT (set by the SDK whenever
|
||||
# `session_root` is configured) wins; otherwise ./.sessions relative to the
|
||||
# runtime process cwd.
|
||||
# JSONL persistence; $DSH_SESSION_ROOT wins over ./.sessions in the process cwd.
|
||||
- id: sessions
|
||||
name: '@deepseek-ai/dsh-session-persistence-jsonl'
|
||||
config:
|
||||
root: !!js process.env.DSH_SESSION_ROOT ?? './.sessions'
|
||||
|
||||
# Local bash executor behind the spine's `bash` tool. $DSH_CWD (always set by
|
||||
# the SDK) wins; otherwise the runtime process cwd.
|
||||
# Local bash executor; $DSH_CWD wins over the process cwd.
|
||||
- id: bash
|
||||
name: '@deepseek-ai/dsh-bash-local'
|
||||
config:
|
||||
|
||||
@@ -2,5 +2,5 @@
|
||||
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
||||
# after editing either side, bring the other along and re-record with:
|
||||
# pnpm run verify-translation-pairing --write
|
||||
README.md: 60540376c5fd85b0852e204bc8bad3f01c849de5
|
||||
README.zh.md: 241c06057889f1aa4add6fc54024fba92bd19429
|
||||
README.md: 441b335b9e850c221fbd6a657c7de539ceca070d
|
||||
README.zh.md: 65134c0e856b933c793510c2ed528e97f940f47d
|
||||
@@ -35,6 +35,6 @@ with DeepSeekHarness(
|
||||
`assistant/message` event in the turn. Use `TurnResult.events` for the complete
|
||||
event stream, including intermediate assistant messages and tool activity.
|
||||
|
||||
The same behavior can be selected for the runtime subprocess with `DSH_CORDIS_CONFIG`. The injection lives in `HarnessClient.start()`, so the low-level client's default launch gets it too: when the launch resolves to the bundled runtime and neither `cordis` nor a non-empty `DSH_CORDIS_CONFIG` is set (the runtime treats an empty value as absent, and so does the injection check), the bundled default configuration is used; an explicit `runtime_bin` or `launch_args_override` disables the injection entirely. See the [sdk-runtime README](../sdk-runtime/README.md) for the runtime carriers (production exe vs dev-only node closure) and how to obtain them.
|
||||
The same behavior can be selected for the runtime subprocess with `DSH_CORDIS_CONFIG`. The injection lives in `HarnessClient.start()`, so the low-level client's default launch gets it too: when the launch resolves to the bundled runtime and neither `cordis` nor a non-empty `DSH_CORDIS_CONFIG` is set (the runtime treats an empty value as absent, and so does the injection check), the bundled default configuration is used; an explicit `runtime_bin`, `bridge_bin`, or `launch_args_override` disables the injection entirely. See the [sdk-runtime README](../sdk-runtime/README.md) for the runtime carriers (production exe vs dev-only node closure) and how to obtain them.
|
||||
|
||||
`cwd` and `runtime_cwd` are resolved to absolute paths before subprocess launch, environment injection, and the wire handshake. The public API exposes only applied options: deployment persona and persistence belong in `cordis.yml`, while `session_root` remains the high-level convenience that sets `DSH_SESSION_ROOT`.
|
||||
@@ -29,6 +29,6 @@ with DeepSeekHarness(
|
||||
|
||||
`TurnResult.final_response` 是本轮次最后一个 `assistant/message` 事件的文本内容。完整的事件流(包括中间的助手消息与工具活动)用 `TurnResult.events` 获取。
|
||||
|
||||
同样的行为也可以通过 `DSH_CORDIS_CONFIG` 为运行时子进程选定。注入逻辑位于 `HarnessClient.start()`,因此底层客户端的默认启动也具有此行为:当启动解析到内置运行时,且 `cordis` 与非空的 `DSH_CORDIS_CONFIG` 均未设置时(运行时把空值视为缺省,注入检查与之一致),使用内置的默认配置;显式给出 `runtime_bin` 或 `launch_args_override` 则完全禁用注入。运行时载体(生产用 exe 与仅限开发的 `node` 闭包)及其获取方式见 [sdk-runtime README](../sdk-runtime/README.md)。
|
||||
同样的行为也可以通过 `DSH_CORDIS_CONFIG` 为运行时子进程选定。注入逻辑位于 `HarnessClient.start()`,因此底层客户端的默认启动也具有此行为:当启动解析到内置运行时,且 `cordis` 与非空的 `DSH_CORDIS_CONFIG` 均未设置时(运行时把空值视为缺省,注入检查与之一致),使用内置的默认配置;显式给出 `runtime_bin`、`bridge_bin` 或 `launch_args_override` 则完全禁用注入。运行时载体(生产用 exe 与仅限开发的 `node` 闭包)及其获取方式见 [sdk-runtime README](../sdk-runtime/README.md)。
|
||||
|
||||
`cwd` 与 `runtime_cwd` 会在启动子进程、注入环境变量和协议握手前解析为绝对路径。公开 API 只暴露真正生效的选项:部署的角色设定与持久化配置归 `cordis.yml` 管理,而 `session_root` 继续作为设置 `DSH_SESSION_ROOT` 的高层便捷选项。
|
||||
@@ -24,8 +24,7 @@ testpaths = ["tests"]
|
||||
[tool.hatch.build.targets.wheel]
|
||||
packages = ["src/deepseek_harness"]
|
||||
|
||||
# Editable: the runtime package's executables are injected into its source
|
||||
# tree AFTER install (by scripts/build-exe-for-python-sdk.ts or a manual copy); an
|
||||
# editable install sees them immediately instead of freezing a wheel snapshot.
|
||||
# Editable installs see runtime executables injected after installation instead
|
||||
# of freezing a wheel snapshot.
|
||||
[tool.uv.sources]
|
||||
deepseek-harness-runtime-bin = { path = "../sdk-runtime", editable = true }
|
||||
@@ -416,16 +416,10 @@ class HarnessClient:
|
||||
return resolve_bundled_launch_args()
|
||||
|
||||
def _inject_bundled_default_config(self, env: dict[str, str]) -> None:
|
||||
"""Restore the zero-config experience over the config-mandatory bundled runtime.
|
||||
"""Inject the default config for a bundled launch with no non-empty config.
|
||||
|
||||
The bundled runtime (single-file exe or the dev-only node closure)
|
||||
always demands an explicit config. When the launch resolves to the
|
||||
bundled runtime (no ``runtime_bin`` / ``bridge_bin`` /
|
||||
``launch_args_override``) and the merged subprocess environment has no
|
||||
non-empty ``DSH_CORDIS_CONFIG`` — the runtime bin treats an empty
|
||||
value as absent, so this does too — inject the runtime package's
|
||||
checked-in default cordis.yml. With an explicit runtime or config
|
||||
channel the client stays out of the way.
|
||||
Both bundled carriers require an explicit config. Explicit runtime,
|
||||
launch-argument, and config channels remain untouched.
|
||||
"""
|
||||
uses_bundled_runtime = (
|
||||
self.config.launch_args_override is None
|
||||
@@ -434,9 +428,7 @@ class HarnessClient:
|
||||
)
|
||||
if not uses_bundled_runtime or env.get("DSH_CORDIS_CONFIG"):
|
||||
return
|
||||
# Cannot fail: _default_launch_args() already imported the runtime
|
||||
# package on this (bundled) path, raising the actionable install
|
||||
# error when it is absent.
|
||||
# _default_launch_args already imported the package or raised its install error.
|
||||
from deepseek_harness_runtime import bundled_default_config_path
|
||||
|
||||
env["DSH_CORDIS_CONFIG"] = str(bundled_default_config_path())
|
||||
|
||||
@@ -1,12 +1,7 @@
|
||||
"""Manual keyless smoke: drive the repo-source jsonrpc-agent bin (node + tsx).
|
||||
"""Drive the repo-source JSON-RPC bin through the SDK and a keyless mock SSE server.
|
||||
|
||||
Runs the SDK against `packages/ui/jsonrpc-agent/src/bin.ts` executed from the
|
||||
repo checkout (requires `pnpm install`; no build, no API key — the model
|
||||
endpoint is a local mock SSE server). The bin only boots the supplied
|
||||
cordis.yml — the stdio JSON-RPC server itself comes from the config's
|
||||
`@deepseek-ai/dsh-jsonrpc` entry — so the runtime package's default cordis.yml
|
||||
is passed explicitly. Not collected by pytest; run it directly:
|
||||
`python tests/manual_sdk_agent_smoke.py`.
|
||||
Requires ``pnpm install`` but no build. This manual test is not collected by
|
||||
pytest; run ``python tests/manual_sdk_agent_smoke.py``.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
@@ -1,12 +1,7 @@
|
||||
"""Smoke tests against the bundled dsh-jsonrpc-agent artifacts.
|
||||
"""Keyless boot tests for the production exe and development node carrier.
|
||||
|
||||
These boot the runtime the way an installed SDK does, once per bundled
|
||||
carrier: the platform single-file exe (production) and the dev-only node
|
||||
closure under ``runtime/node`` driven by system ``node``. Each carrier skips
|
||||
independently when its artifact is absent on this machine — build or fetch it
|
||||
per the FileNotFoundError guidance quoted in the skip reason. Keyless: the
|
||||
dummy DEEPSEEK_API_KEY only satisfies the adapter's load-time check;
|
||||
initialize/shutdown never call a model.
|
||||
Each carrier skips independently when absent. The dummy API key only satisfies
|
||||
adapter loading; initialize and shutdown do not call a model.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
@@ -21,8 +16,7 @@ from deepseek_harness_runtime import resolve_bundled_launch_args
|
||||
|
||||
_MODES = ("exe", "node")
|
||||
|
||||
# The serving surface is itself a plugin: without the dsh-jsonrpc entry the
|
||||
# runtime boots an agent nobody can talk to and exits 0 on stdin EOF.
|
||||
# The config must include the JSON-RPC serving plugin.
|
||||
_CORDIS_YML = """\
|
||||
- id: jsonrpc
|
||||
name: '@deepseek-ai/dsh-jsonrpc'
|
||||
@@ -57,9 +51,7 @@ def _client(tmp_path: Path, launch_args: tuple[str, ...]) -> HarnessClient:
|
||||
"DSH_CORDIS_CONFIG": "./cordis.yml",
|
||||
"DSH_SESSION_ROOT": str(tmp_path / "sessions"),
|
||||
"DSH_CWD": str(tmp_path),
|
||||
# initialize() lazily mounts the llm-deepseek adapter for the
|
||||
# requested model; a dummy key keeps the keyless boot green
|
||||
# (initialize/shutdown never call the model).
|
||||
# The lazily mounted adapter requires a key even without a model call.
|
||||
"DEEPSEEK_API_KEY": "sk-dummy-for-boot",
|
||||
"DEEPSEEK_BASE_URL": "http://127.0.0.1:9",
|
||||
},
|
||||
@@ -119,7 +111,4 @@ def test_zero_config_run_injects_bundled_default_cordis_config(
|
||||
request_timeout_seconds=120,
|
||||
)
|
||||
with harness:
|
||||
# __enter__ boots the runtime, which exits with a usage error unless
|
||||
# HarnessClient.start() injected the bundled default config over the
|
||||
# unset/empty DSH_CORDIS_CONFIG; __exit__ shuts it down.
|
||||
pass
|
||||
@@ -682,11 +682,9 @@ with open(os.environ["SEEN"], "w") as seen:
|
||||
def _install_fake_bundled_runtime(
|
||||
tmp_path: Path, monkeypatch: pytest.MonkeyPatch
|
||||
) -> Path:
|
||||
"""Fake the deepseek-harness-runtime-bin package on sys.path.
|
||||
"""Install a fake runtime package that records config and serves lifecycle calls.
|
||||
|
||||
A stub exe that dumps DSH_CORDIS_CONFIG to $ENV_DUMP before serving
|
||||
initialize/shutdown, plus a module exposing the resolution surface the
|
||||
client consumes. Returns the fake bundled default config path.
|
||||
Returns the fake bundled default config path.
|
||||
"""
|
||||
runtime = tmp_path / "dsh-jsonrpc-agent"
|
||||
runtime.write_text(
|
||||
|
||||
@@ -1,9 +1,4 @@
|
||||
"""Keyless tests for the deepseek_harness_runtime resolution API.
|
||||
|
||||
These never launch a runtime, so they run everywhere regardless of which
|
||||
bundled artifacts are present; the launch-and-boot coverage lives in
|
||||
``test_bundled_runtime.py``.
|
||||
"""
|
||||
"""Keyless runtime-resolution tests; launch coverage lives in test_bundled_runtime.py."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
|
||||
Reference in New Issue
Block a user