From fd10363f7f31e681b0dacb5b687068bfde613027 Mon Sep 17 00:00:00 2001 From: SaladDay <1203511142@qq.com> Date: Fri, 23 Oct 2026 19:06:39 +0000 Subject: [PATCH] Author Harness native pins in the declaration and move shared code to its owners --- apps/daemon/internal/agent/binpath/binpath.go | 51 ----------------- .../internal/agent/binpath/binpath_test.go | 36 ------------ .../internal/agent/claudesdk/installation.go | 5 +- .../internal/agent/codex/installation.go | 10 +++- apps/daemon/internal/agent/codex/recovery.go | 2 +- apps/daemon/internal/agent/codex/version.go | 20 ++++--- .../agent/mcode/discovery_workspace.go | 3 +- .../internal/agent/mcode/installation.go | 2 +- apps/daemon/internal/agent/mcode/version.go | 18 +++++- apps/daemon/internal/cli/native_harness.go | 7 ++- .../runtime_initialization_process.go | 4 +- .../runtime_initialization_test.go | 1 - contracts/agents-api/harness-catalog.md | 10 ++-- contracts/agents-api/harness-onboarding.md | 4 +- contracts/agents-api/zh/harness-catalog.md | 10 ++-- contracts/agents-api/zh/harness-onboarding.md | 6 +- docs/getting-started/self-hosted.md | 2 +- docs/maintainers.md | 4 +- docs/zh/getting-started/self-hosted.md | 4 +- docs/zh/maintainers.md | 6 +- .../harnessconfig/claudesdk/declaration.go | 5 +- internal/harnessconfig/codex/declaration.go | 5 +- internal/harnessconfig/harness.go | 7 +++ internal/harnessconfig/mcode/declaration.go | 5 +- scripts/build-core.sh | 2 +- scripts/build-native-installer.mjs | 3 +- scripts/ci_plan.py | 2 +- scripts/generate-harness-catalog.py | 56 +++++++++++++++++-- scripts/generate-harness-catalog.test.py | 2 +- scripts/harness-catalog/main.go | 5 +- scripts/native-pins.json | 5 ++ .../core/internal}/agentnetwork/policy.go | 0 .../internal}/agentnetwork/policy_test.go | 0 .../core/internal/api/hosted_environment.go | 2 +- .../core/internal/api/session_template.go | 2 +- .../internal/environmenttemplates/template.go | 2 +- 36 files changed, 155 insertions(+), 153 deletions(-) delete mode 100644 apps/daemon/internal/agent/binpath/binpath.go delete mode 100644 apps/daemon/internal/agent/binpath/binpath_test.go create mode 100644 scripts/native-pins.json rename {internal => services/core/internal}/agentnetwork/policy.go (100%) rename {internal => services/core/internal}/agentnetwork/policy_test.go (100%) diff --git a/apps/daemon/internal/agent/binpath/binpath.go b/apps/daemon/internal/agent/binpath/binpath.go deleted file mode 100644 index 792640034..000000000 --- a/apps/daemon/internal/agent/binpath/binpath.go +++ /dev/null @@ -1,51 +0,0 @@ -// Package binpath resolves which executable each agent adapter should -// probe and spawn. -// -// By default every engine is looked up by bare name on PATH ("codex", -// "codex", ...). That breaks in images where PATH is not under our -// control: e2b's base image, for instance, ships its own -// /usr/local/bin entries that can shadow the ones we install, and a -// bare-name lookup then resolves to the wrong (or no) binary. The -// symptom is the worst kind — `oac-daemon connect` reports -// "no supported agent CLI available" and the device never dials in, -// with no indication of which lookup failed. -// -// The env overrides below let an image or operator pin an absolute path -// instead. They are read in ONE place so the version probe -// (CheckCLIAvailable) and the run-time spawn (sessionConfig) can never -// disagree: a probe that succeeds against /custom/codex while the run -// spawns PATH's `codex` would advertise a capability the daemon cannot -// actually honour. -package binpath - -import ( - "os" - "strings" -) - -// Env var names for the per-engine executable overrides. Empty or unset -// means "look up the default name on PATH". -const ( - EnvCodex = "OAC_RUNTIME_CODEX_BIN" - EnvMCode = "OAC_RUNTIME_MCODE_BIN" -) - -// Default executable names, used when the matching env var is unset. -const ( - DefaultCodex = "codex" - DefaultMCode = "mcode" -) - -// resolve returns the trimmed env override when set, else fallback. -func resolve(envVar, fallback string) string { - if v := strings.TrimSpace(os.Getenv(envVar)); v != "" { - return v - } - return fallback -} - -// Codex returns the codex executable to probe and spawn. -func Codex() string { return resolve(EnvCodex, DefaultCodex) } - -// MCode returns the mcode executable to probe and spawn. -func MCode() string { return resolve(EnvMCode, DefaultMCode) } diff --git a/apps/daemon/internal/agent/binpath/binpath_test.go b/apps/daemon/internal/agent/binpath/binpath_test.go deleted file mode 100644 index be72eaef4..000000000 --- a/apps/daemon/internal/agent/binpath/binpath_test.go +++ /dev/null @@ -1,36 +0,0 @@ -package binpath - -import "testing" - -func TestResolvers(t *testing.T) { - tests := []struct { - name string - envVar string - fallback string - resolve func() string - override string - wantPinned string - }{ - {name: "codex", envVar: EnvCodex, fallback: DefaultCodex, resolve: Codex, override: " /opt/agents/codex ", wantPinned: "/opt/agents/codex"}, - {name: "mcode", envVar: EnvMCode, fallback: DefaultMCode, resolve: MCode, override: " /opt/agents/mcode ", wantPinned: "/opt/agents/mcode"}, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - t.Setenv(tt.envVar, "") - if got := tt.resolve(); got != tt.fallback { - t.Fatalf("unset override: got %q, want %q", got, tt.fallback) - } - - t.Setenv(tt.envVar, tt.override) - if got := tt.resolve(); got != tt.wantPinned { - t.Fatalf("explicit override: got %q, want %q", got, tt.wantPinned) - } - - t.Setenv(tt.envVar, " \t ") - if got := tt.resolve(); got != tt.fallback { - t.Fatalf("blank override: got %q, want %q", got, tt.fallback) - } - }) - } -} diff --git a/apps/daemon/internal/agent/claudesdk/installation.go b/apps/daemon/internal/agent/claudesdk/installation.go index 2bc814f6a..50e280368 100644 --- a/apps/daemon/internal/agent/claudesdk/installation.go +++ b/apps/daemon/internal/agent/claudesdk/installation.go @@ -4,18 +4,19 @@ import ( "context" "fmt" "github.com/MiniMax-AI/OpenAgentCore/apps/daemon/internal/agent" + declaration "github.com/MiniMax-AI/OpenAgentCore/internal/harnessconfig/claudesdk" "path/filepath" "runtime" ) func Installation() agent.Installation { - return agent.Installation{AgentKind: "claude_sdk", Version: "0.3.269", Supported: func() bool { return runtime.GOOS == "linux" || runtime.GOOS == "darwin" || runtime.GOOS == "windows" }, + return agent.Installation{AgentKind: "claude_sdk", Version: declaration.Declaration.Native.Version, Supported: func() bool { return runtime.GOOS == "linux" || runtime.GOOS == "darwin" || runtime.GOOS == "windows" }, Environment: func(dir, node string) map[string]string { return map[string]string{"OAC_RUNTIME_CLAUDE_SDK_ENTRYPOINT": filepath.Join(dir, "dist", "main.js"), "OAC_RUNTIME_CLAUDE_SDK_NODE": node} }, Check: func(ctx context.Context, dir, node string, env []string) error { got, err := CheckRuntime(ctx, Config{Node: node, Entrypoint: filepath.Join(dir, "dist", "main.js"), Env: env}) - if err != nil || got.SDK != "0.3.269" || !got.SupportsLocalRuntime() { + if err != nil || got.SDK != declaration.Declaration.Native.Version || !got.SupportsLocalRuntime() { return fmt.Errorf("Claude installation is incompatible; Windows requires Git Bash") } return nil diff --git a/apps/daemon/internal/agent/codex/installation.go b/apps/daemon/internal/agent/codex/installation.go index fe8e645b5..b9540a2d0 100644 --- a/apps/daemon/internal/agent/codex/installation.go +++ b/apps/daemon/internal/agent/codex/installation.go @@ -5,10 +5,14 @@ import ( "fmt" "github.com/MiniMax-AI/OpenAgentCore/apps/daemon/internal/agent" "github.com/MiniMax-AI/OpenAgentCore/apps/daemon/internal/agent/installroot" + declaration "github.com/MiniMax-AI/OpenAgentCore/internal/harnessconfig/codex" "path/filepath" "runtime" ) +// versionOutput is what the pinned native binary prints for --version. +var versionOutput = "codex-cli " + declaration.Declaration.Native.Version + func Installation() agent.Installation { binary := func(dir string) string { name := "codex" @@ -17,13 +21,13 @@ func Installation() agent.Installation { } return filepath.Join(dir, "bin", name) } - return agent.Installation{AgentKind: "codex", Version: "0.153.4", Supported: func() bool { return runtime.GOOS == "linux" || runtime.GOOS == "darwin" || runtime.GOOS == "windows" }, + return agent.Installation{AgentKind: "codex", Version: declaration.Declaration.Native.Version, Supported: func() bool { return runtime.GOOS == "linux" || runtime.GOOS == "darwin" || runtime.GOOS == "windows" }, Environment: func(dir, node string) map[string]string { - return map[string]string{"OAC_RUNTIME_CODEX_BIN": binary(dir)} + return map[string]string{binaryEnv: binary(dir)} }, Check: func(ctx context.Context, dir, node string, env []string) error { got, err := installroot.Probe(ctx, binary(dir), []string{"--version"}, env, dir) - if err != nil || got != "codex-cli 0.153.4" { + if err != nil || got != versionOutput { return fmt.Errorf("Codex installation is incompatible") } return nil diff --git a/apps/daemon/internal/agent/codex/recovery.go b/apps/daemon/internal/agent/codex/recovery.go index 1f787cf25..97d0df57e 100644 --- a/apps/daemon/internal/agent/codex/recovery.go +++ b/apps/daemon/internal/agent/codex/recovery.go @@ -9,7 +9,7 @@ import ( ) func SupportsNativeSessionRecovery(version string) bool { - return strings.TrimSpace(version) == "codex-cli 0.153.4" + return strings.TrimSpace(version) == versionOutput } func (s *Session) recoverRoot(plan SessionPlan) (string, error) { diff --git a/apps/daemon/internal/agent/codex/version.go b/apps/daemon/internal/agent/codex/version.go index 6a93cf979..90258ce9e 100644 --- a/apps/daemon/internal/agent/codex/version.go +++ b/apps/daemon/internal/agent/codex/version.go @@ -5,21 +5,27 @@ import ( "context" "errors" "fmt" + "os" "os/exec" "strings" - - "github.com/MiniMax-AI/OpenAgentCore/apps/daemon/internal/agent/binpath" ) // InstallURL points operators at the Codex install instructions when // the daemon can see the adapter but not the CLI binary. const InstallURL = "https://github.com/openai/codex" -// defaultBinary is the executable to probe and spawn: binpath.Codex() -// honours the OAC_RUNTIME_CODEX_BIN override so a bare-name PATH lookup can -// be bypassed in images where PATH is not under our control. A function -// rather than a const so the env is read at call time. -func defaultBinary() string { return binpath.Codex() } +// binaryEnv pins the codex executable in images where PATH is not under our +// control, so the version probe and the run-time spawn resolve the same binary. +const binaryEnv = "OAC_RUNTIME_CODEX_BIN" + +// defaultBinary is the executable to probe and spawn: the trimmed binaryEnv +// override, else "codex" on PATH. Read at call time. +func defaultBinary() string { + if v := strings.TrimSpace(os.Getenv(binaryEnv)); v != "" { + return v + } + return "codex" +} // ErrCLINotFound is returned by CheckCLIAvailable when the binary // cannot be located on PATH. Callers use errors.Is to distinguish an diff --git a/apps/daemon/internal/agent/mcode/discovery_workspace.go b/apps/daemon/internal/agent/mcode/discovery_workspace.go index d8f60f021..6be91c922 100644 --- a/apps/daemon/internal/agent/mcode/discovery_workspace.go +++ b/apps/daemon/internal/agent/mcode/discovery_workspace.go @@ -8,7 +8,6 @@ import ( "path/filepath" "github.com/MiniMax-AI/OpenAgentCore/apps/daemon/internal/agent" - "github.com/MiniMax-AI/OpenAgentCore/apps/daemon/internal/agent/binpath" "github.com/MiniMax-AI/OpenAgentCore/apps/daemon/internal/localworkspace" "github.com/MiniMax-AI/OpenAgentCore/internal/agentdaemon/proto" ) @@ -41,7 +40,7 @@ func discoverWorkspace(parent context.Context, options agent.DiscoveryOptions, r fail(err) return nil } - binary, err := exec.LookPath(binpath.MCode()) + binary, err := exec.LookPath(defaultBinary()) if err != nil { fail(err) return nil diff --git a/apps/daemon/internal/agent/mcode/installation.go b/apps/daemon/internal/agent/mcode/installation.go index ce35f0f42..9be60b062 100644 --- a/apps/daemon/internal/agent/mcode/installation.go +++ b/apps/daemon/internal/agent/mcode/installation.go @@ -12,7 +12,7 @@ import ( func Installation() agent.Installation { return agent.Installation{AgentKind: "mcode", Version: SupportedVersion, Supported: func() bool { return runtime.GOOS == "linux" || runtime.GOOS == "darwin" }, Environment: func(dir, node string) map[string]string { - return map[string]string{"OAC_RUNTIME_MCODE_BIN": filepath.Join(dir, "native", "cli.js"), "OAC_RUNTIME_MCODE_NODE": node, "OAC_RUNTIME_MCODE_COMPANION": dir} + return map[string]string{binaryEnv: filepath.Join(dir, "native", "cli.js"), "OAC_RUNTIME_MCODE_NODE": node, "OAC_RUNTIME_MCODE_COMPANION": dir} }, Check: func(ctx context.Context, dir, node string, env []string) error { got, err := installroot.Probe(ctx, node, []string{filepath.Join(dir, "native", "cli.js"), "--version"}, env, dir) diff --git a/apps/daemon/internal/agent/mcode/version.go b/apps/daemon/internal/agent/mcode/version.go index 95c476007..42bb13389 100644 --- a/apps/daemon/internal/agent/mcode/version.go +++ b/apps/daemon/internal/agent/mcode/version.go @@ -4,16 +4,28 @@ import ( "context" "errors" "fmt" + "os" + "strings" - "github.com/MiniMax-AI/OpenAgentCore/apps/daemon/internal/agent/binpath" "github.com/MiniMax-AI/OpenAgentCore/apps/daemon/internal/agent/versionprobe" + declaration "github.com/MiniMax-AI/OpenAgentCore/internal/harnessconfig/mcode" ) var ErrCLINotFound = errors.New("mcode CLI not found") -const SupportedVersion = "0.4.12" +var SupportedVersion = declaration.Declaration.Native.Version -func defaultBinary() string { return binpath.MCode() } +// binaryEnv pins the mcode executable in images where PATH is not under our +// control, so the version probe and the run-time spawn resolve the same binary. +const binaryEnv = "OAC_RUNTIME_MCODE_BIN" + +// defaultBinary is the trimmed binaryEnv override, else "mcode" on PATH. Read at call time. +func defaultBinary() string { + if v := strings.TrimSpace(os.Getenv(binaryEnv)); v != "" { + return v + } + return "mcode" +} func CheckCLIAvailable(ctx context.Context, binary string) (string, error) { version, err := versionprobe.Check(ctx, binary, versionprobe.Config{Name: "mcode", DefaultBinary: defaultBinary(), MissingError: ErrCLINotFound, TrimBinary: true}) diff --git a/apps/daemon/internal/cli/native_harness.go b/apps/daemon/internal/cli/native_harness.go index 34bc1f300..7b13ccda2 100644 --- a/apps/daemon/internal/cli/native_harness.go +++ b/apps/daemon/internal/cli/native_harness.go @@ -15,6 +15,9 @@ import ( "github.com/MiniMax-AI/OpenAgentCore/apps/daemon/internal/agent/codex" "github.com/MiniMax-AI/OpenAgentCore/apps/daemon/internal/agent/installroot" "github.com/MiniMax-AI/OpenAgentCore/apps/daemon/internal/agent/mcode" + claudedeclaration "github.com/MiniMax-AI/OpenAgentCore/internal/harnessconfig/claudesdk" + codexdeclaration "github.com/MiniMax-AI/OpenAgentCore/internal/harnessconfig/codex" + mcodedeclaration "github.com/MiniMax-AI/OpenAgentCore/internal/harnessconfig/mcode" ) func nativeExe(name string) string { @@ -69,7 +72,9 @@ func withNativeEnv(values map[string]string) []string { // Installation registration is local to Runtime; Core does not see native paths. var nativeHarnesses = map[string]agent.Installation{ - "codex": codex.Installation(), "claude": claudesdk.Installation(), "minimax": mcode.Installation(), + codexdeclaration.Declaration.Native.Component: codex.Installation(), + claudedeclaration.Declaration.Native.Component: claudesdk.Installation(), + mcodedeclaration.Declaration.Native.Component: mcode.Installation(), } var probeNativeInstallation = checkNativeInstallation diff --git a/apps/daemon/internal/localworkspace/runtime_initialization_process.go b/apps/daemon/internal/localworkspace/runtime_initialization_process.go index a8464ed97..f1ab774f1 100644 --- a/apps/daemon/internal/localworkspace/runtime_initialization_process.go +++ b/apps/daemon/internal/localworkspace/runtime_initialization_process.go @@ -25,9 +25,7 @@ func initializationBash() (string, error) { // Git Bash preserves setup's Bash syntax. Never substitute cmd.exe, PowerShell // or the Windows WSL launcher for a missing Bash implementation. candidates := []string{} - if explicit := os.Getenv("CLAUDE_CODE_GIT_BASH_PATH"); explicit != "" { - candidates = append(candidates, explicit) - } else if git, err := exec.LookPath("git.exe"); err == nil { + if git, err := exec.LookPath("git.exe"); err == nil { candidates = append(candidates, filepath.Join(filepath.Dir(git), "..", "bin", "bash.exe"), filepath.Join(filepath.Dir(git), "bash.exe")) } for _, candidate := range candidates { diff --git a/apps/daemon/internal/localworkspace/runtime_initialization_test.go b/apps/daemon/internal/localworkspace/runtime_initialization_test.go index 47896582a..4e4aeb2bf 100644 --- a/apps/daemon/internal/localworkspace/runtime_initialization_test.go +++ b/apps/daemon/internal/localworkspace/runtime_initialization_test.go @@ -257,7 +257,6 @@ func TestRuntimeInitializationSetupUsesBashAndPhysicalWorkspace(t *testing.T) { func TestRuntimeInitializationMissingDependenciesAndInvalidRequests(t *testing.T) { b := initializationFixture(t) t.Setenv("PATH", t.TempDir()) - t.Setenv("CLAUDE_CODE_GIT_BASH_PATH", "") if err := b.initializeRuntime(t.Context(), proto.RuntimeInitialization{Action: "configure"}); err != nil { t.Fatal(err) } diff --git a/contracts/agents-api/harness-catalog.md b/contracts/agents-api/harness-catalog.md index 200ad4e8e..a3bcc19db 100644 --- a/contracts/agents-api/harness-catalog.md +++ b/contracts/agents-api/harness-catalog.md @@ -7,10 +7,10 @@ title: "Built-in Harness registrations" Each Harness is the one `declaration.go` in its `internal/harnessconfig/` directory. Adding a directory with a `declaration.go` registers the Harness; `make generate-harness-catalog` regenerates the registrations and this page, and `make check-harness-catalog` checks them. -| Identifier | Display name | Declaration | -| --- | --- | --- | -| `claude_sdk` | Claude Code | [`claudesdk/declaration.go`](https://github.com/MiniMax-AI/OpenAgentCore/blob/main/internal/harnessconfig/claudesdk/declaration.go) | -| `codex` | Codex | [`codex/declaration.go`](https://github.com/MiniMax-AI/OpenAgentCore/blob/main/internal/harnessconfig/codex/declaration.go) | -| `mcode` | MiniMax Code | [`mcode/declaration.go`](https://github.com/MiniMax-AI/OpenAgentCore/blob/main/internal/harnessconfig/mcode/declaration.go) | +| Identifier | Display name | Native version | Declaration | +| --- | --- | --- | --- | +| `claude_sdk` | Claude Code | `0.3.269` | [`claudesdk/declaration.go`](https://github.com/MiniMax-AI/OpenAgentCore/blob/main/internal/harnessconfig/claudesdk/declaration.go) | +| `codex` | Codex | `0.153.4` | [`codex/declaration.go`](https://github.com/MiniMax-AI/OpenAgentCore/blob/main/internal/harnessconfig/codex/declaration.go) | +| `mcode` | MiniMax Code | `0.4.12` | [`mcode/declaration.go`](https://github.com/MiniMax-AI/OpenAgentCore/blob/main/internal/harnessconfig/mcode/declaration.go) | These registrations describe the build. Which Harnesses a deployment enables is the `OAC_HARNESSES` [process setting](../../docs/configuration.md#settings), [Harness capabilities](./harness-capabilities.md) lists what each Harness supports, and a connected Runtime reports its own availability. [Harness protocol](./harness-onboarding.md) describes the adapter and packaging steps. diff --git a/contracts/agents-api/harness-onboarding.md b/contracts/agents-api/harness-onboarding.md index 4890b0c77..cd29f9002 100644 --- a/contracts/agents-api/harness-onboarding.md +++ b/contracts/agents-api/harness-onboarding.md @@ -38,7 +38,7 @@ An Environment supplies execution resources. Managed E2B, Docker and microsandbo ## Steps -1. **Pin the native source.** Record the upstream package version and source revision and document the native entry point next to the adapter. +1. **Pin the native source.** Set the upstream package version in the declaration's `Native` field, which the adapter and `make check-harness-catalog` read for every other projection of the pin. Record the source revision and document the native entry point next to the adapter. 2. **Implement the adapter** in `apps/daemon/internal/agent/`, where `` is the kind without underscores: an `ExecutorFactory`, an `Executor` and a `Turn` ([required interfaces](#required-adapter-interfaces), [lifetimes](#executor-and-turn-lifetimes)). Reuse the shared process, credential, configuration and local workspace helpers. 3. **Write the declaration** in `internal/harnessconfig//declaration.go` and bind it to the adapter's discovery ([declare the Harness](#declare-the-harness), [register the adapter](#register-the-adapter)). Run `make generate-harness-catalog` to register both. 4. **Package native prerequisites.** Add a Runtime image under `services/core/deploy/` and, optionally, [native installer participation](#native-installer-participation). @@ -208,7 +208,7 @@ The declaration's ordered `protocols` list is the only source of accepted protoc ## Native installer participation -An adapter may supply `agent.Installation` from `installation.go` in its own package: registered kind, pinned version, supported platforms, activation environment and a bounded readiness probe. Register it in `cli/native_harness.go` and add its pinned component to the native distribution builder. This optional contract does not change Executor and Turn semantics. The Runtime owns checksums, copying, locks and additive installation; adapters own native layout and probes. Validate installation and execution on each advertised platform. Missing or incompatible native content fails; it never installs itself during a Turn. +An adapter may supply `agent.Installation` from `installation.go` in its own package: registered kind, pinned version (read from the declaration's `Native.Version`), supported platforms, activation environment and a bounded readiness probe. Register it in `cli/native_harness.go` and add its pinned component to the native distribution builder. This optional contract does not change Executor and Turn semantics. The Runtime owns checksums, copying, locks and additive installation; adapters own native layout and probes. Validate installation and execution on each advertised platform. Missing or incompatible native content fails; it never installs itself during a Turn. ## Native process ownership diff --git a/contracts/agents-api/zh/harness-catalog.md b/contracts/agents-api/zh/harness-catalog.md index 198b215fc..ba6e6fb37 100644 --- a/contracts/agents-api/zh/harness-catalog.md +++ b/contracts/agents-api/zh/harness-catalog.md @@ -7,10 +7,10 @@ title: "内置 Harness 注册" 每个 Harness 对应 `internal/harnessconfig/` 目录中唯一的 `declaration.go`。新增包含 `declaration.go` 的目录即注册该 Harness;`make generate-harness-catalog` 重新生成注册代码和本页,`make check-harness-catalog` 检查生成结果。 -| 标识符 | 显示名称 | 声明 | -| --- | --- | --- | -| `claude_sdk` | Claude Code | [`claudesdk/declaration.go`](https://github.com/MiniMax-AI/OpenAgentCore/blob/main/internal/harnessconfig/claudesdk/declaration.go) | -| `codex` | Codex | [`codex/declaration.go`](https://github.com/MiniMax-AI/OpenAgentCore/blob/main/internal/harnessconfig/codex/declaration.go) | -| `mcode` | MiniMax Code | [`mcode/declaration.go`](https://github.com/MiniMax-AI/OpenAgentCore/blob/main/internal/harnessconfig/mcode/declaration.go) | +| 标识符 | 显示名称 | 原生版本 | 声明 | +| --- | --- | --- | --- | +| `claude_sdk` | Claude Code | `0.3.269` | [`claudesdk/declaration.go`](https://github.com/MiniMax-AI/OpenAgentCore/blob/main/internal/harnessconfig/claudesdk/declaration.go) | +| `codex` | Codex | `0.153.4` | [`codex/declaration.go`](https://github.com/MiniMax-AI/OpenAgentCore/blob/main/internal/harnessconfig/codex/declaration.go) | +| `mcode` | MiniMax Code | `0.4.12` | [`mcode/declaration.go`](https://github.com/MiniMax-AI/OpenAgentCore/blob/main/internal/harnessconfig/mcode/declaration.go) | 这些注册描述当前构建。部署启用的 Harness 由 `OAC_HARNESSES` [进程设置](../../../docs/zh/configuration.md#settings)决定;[Harness 能力](./harness-capabilities.md)列出各 Harness 的支持范围,连接的 Runtime 报告自身可用性。[Harness protocol](./harness-onboarding.md)介绍适配器和打包步骤。 diff --git a/contracts/agents-api/zh/harness-onboarding.md b/contracts/agents-api/zh/harness-onboarding.md index 1e4799f52..bc6dda172 100644 --- a/contracts/agents-api/zh/harness-onboarding.md +++ b/contracts/agents-api/zh/harness-onboarding.md @@ -1,7 +1,7 @@ --- title: "Harness 协议" source: contracts/agents-api/harness-onboarding.md -source_hash: c5688b7362e0ede4a85200d3a66ee383bd71da23505429755adbc1888ce8dd60 +source_hash: bf3a297779def9925b30e6a77c3e5f28a1349964922242219bcf1fcaad9ef2af --- **Harness** 是一种运行模型和工具循环的原生代理引擎(Codex、Claude Code、MiniMax Code);**Harness 适配器**将 Runtime 的 Executor 和 Turn 契约转换到该引擎的 SDK 或协议。Harness 协议是 Runtime 与适配器之间的契约:适配器接口及其生命周期义务、声明、注册和验收。本文面向添加或维护 Harness 的开发者。 @@ -40,7 +40,7 @@ Environment 提供执行资源。受管 E2B、Docker 和 microsandbox 机器以 ## 步骤 {#steps} -1. **锁定原生来源。** 记录上游包版本和源修订版本,并在适配器旁记录原生入口点。 +1. **锁定原生来源。** 在声明的 `Native` 字段中设置上游包版本,适配器和 `make check-harness-catalog` 据此处理该版本的其他所有投影。记录源修订版本,并在适配器旁记录原生入口点。 2. **实现适配器**,位置为 `apps/daemon/internal/agent/`,其中 `` 是去掉下划线的 kind:实现 `ExecutorFactory`、`Executor` 和 `Turn`([required interfaces](#required-adapter-interfaces)、[lifetimes](#executor-and-turn-lifetimes))。复用共享的进程、凭据、配置和本地工作区辅助函数。 3. **编写声明**:在 `internal/harnessconfig//declaration.go` 中编写声明,并将其绑定到适配器的发现函数([declare the Harness](#declare-the-harness)、[register the adapter](#register-the-adapter))。运行 `make generate-harness-catalog` 完成两处注册。 4. **打包原生先决条件。** 在 `services/core/deploy/` 下添加 Runtime 镜像,并可选添加 [native installer participation](#native-installer-participation)。 @@ -210,7 +210,7 @@ Runtime 统一解析[状态目录](../../../docs/zh/configuration.md#runtime-res ## 原生安装程序参与 {#native-installer-participation} -适配器可以从自身包中的 `installation.go` 提供 `agent.Installation`:已注册 kind、锁定版本、受支持平台、激活环境和有界就绪探测。在 `cli/native_harness.go` 中注册它,并将其锁定组件添加到原生分发构建器。此可选契约不会改变 Executor 和 Turn 语义。Runtime 负责校验和、复制、锁和增量安装;适配器负责原生布局和探测。必须在每个宣称的平台上验证安装和执行。原生内容缺失或不兼容时必须失败;绝不会在 Turn 期间自行安装。 +适配器可以从自身包中的 `installation.go` 提供 `agent.Installation`:已注册 kind、锁定版本(取自声明的 `Native.Version`)、受支持平台、激活环境和有界就绪探测。在 `cli/native_harness.go` 中注册它,并将其锁定组件添加到原生分发构建器。此可选契约不会改变 Executor 和 Turn 语义。Runtime 负责校验和、复制、锁和增量安装;适配器负责原生布局和探测。必须在每个宣称的平台上验证安装和执行。原生内容缺失或不兼容时必须失败;绝不会在 Turn 期间自行安装。 ## 原生进程所有权 {#native-process-ownership} diff --git a/docs/getting-started/self-hosted.md b/docs/getting-started/self-hosted.md index 9462b1c8d..7cabd4222 100644 --- a/docs/getting-started/self-hosted.md +++ b/docs/getting-started/self-hosted.md @@ -19,7 +19,7 @@ The Session brings its own model provider; the installation default never applie | macOS arm64 | Supported | Supported | Supported | | Windows amd64 | Supported | Supported | Not supported | -The installer brings its own pinned Node.js and Harness versions (listed in [`scripts/build-native-installer.mjs`](https://github.com/MiniMax-AI/OpenAgentCore/blob/main/scripts/build-native-installer.mjs)) and leaves other installations of those tools untouched. On a platform without a matching installer, the command fails. +The installer brings its own pinned Node.js and Harness versions (Harnesses in the [Harness catalog](https://github.com/MiniMax-AI/OpenAgentCore/blob/main/contracts/agents-api/harness-catalog.md), Node.js in [`scripts/build-native-installer.mjs`](https://github.com/MiniMax-AI/OpenAgentCore/blob/main/scripts/build-native-installer.mjs)) and leaves other installations of those tools untouched. On a platform without a matching installer, the command fails. The download depends on the Harnesses you install. The installer (9 MiB) and Node.js (59 MiB) are always needed, plus 121 MiB for Codex, 99 MiB for Claude Code or 23 MiB for MiniMax Code, so a Session with one Harness downloads 90 to 189 MiB. Free space is needed on the disk that holds the Runtime home and the installation directory: diff --git a/docs/maintainers.md b/docs/maintainers.md index 3a9090c3b..4ba321ec6 100644 --- a/docs/maintainers.md +++ b/docs/maintainers.md @@ -46,7 +46,7 @@ A distribution carries the docs listed in `BUNDLED_DOCS` in `scripts/core-distri ### Native installers -Self-hosted machines install `oac-daemon` from per-platform native installers: Linux amd64, macOS arm64 and Windows amd64. Each is built on its own OS by the `native-check` workflow (`scripts/build-native-installer.mjs`, whose `pins` object fixes the Node.js and Harness versions) and verified on every selected native check. Manual packaging runs and release checks upload the platform's archives as `oac-native-installer--` for seven days; ordinary PR and main checks do not upload successful packages. For a local distribution, download the three artifacts from a `native-check` run on that exact commit (a manual run or the release run; pull-request runs build the merge commit and do not match), then assemble the catalog from that checkout, with all archives of the three artifacts in one input directory: +Self-hosted machines install `oac-daemon` from per-platform native installers: Linux amd64, macOS arm64 and Windows amd64. Each is built on its own OS by the `native-check` workflow (`scripts/build-native-installer.mjs`, whose `pins` object holds the Node.js version and the Harness versions generated from their declarations) and verified on every selected native check. Manual packaging runs and release checks upload the platform's archives as `oac-native-installer--` for seven days; ordinary PR and main checks do not upload successful packages. For a local distribution, download the three artifacts from a `native-check` run on that exact commit (a manual run or the release run; pull-request runs build the merge commit and do not match), then assemble the catalog from that checkout, with all archives of the three artifacts in one input directory: ```sh node scripts/build-native-catalog.mjs INPUT_DIR OUTPUT_DIR @@ -63,7 +63,7 @@ The catalog records the commit, the Runtime protocol version, each artifact's SH The three maintained Runtime images share the digest-pinned base `node:22.23.1-bookworm-slim` with `ca-certificates`, `bash`, `git`, `python3`, `python3-pip` and `ripgrep`, and a build-time adjustment to the pinned Debian login profile: an inherited, exported `PATH` is preserved, while an unset `PATH` receives Debian’s defaults. This keeps the Runtime’s initialized package and user paths available in login and non-login tools without another package-path setting. The combined image inherits the same profile. A changed upstream profile fails the build for review; custom shell startup files can still explicitly change `PATH`. -**Codex Runtime image.** Extract the official npm package `@openai/codex@0.153.4-linux-x64` under `~/.oac` (for example with `npm pack --ignore-scripts` and `tar -xzf`), then: +**Codex Runtime image.** Extract the official npm package `@openai/codex@-linux-x64` at the version in the [Harness catalog](https://github.com/MiniMax-AI/OpenAgentCore/blob/main/contracts/agents-api/harness-catalog.md) under `~/.oac` (for example with `npm pack --ignore-scripts` and `tar -xzf`), then: ```sh export CODEX_CLI_DIR=/absolute/path/to/package diff --git a/docs/zh/getting-started/self-hosted.md b/docs/zh/getting-started/self-hosted.md index 58c4faa25..b143ad952 100644 --- a/docs/zh/getting-started/self-hosted.md +++ b/docs/zh/getting-started/self-hosted.md @@ -1,7 +1,7 @@ --- title: "运行自托管 Session" source: docs/getting-started/self-hosted.md -source_hash: de2bf583004e0aabb735d434133780e26f96e9912dd7e11100327b2f83f403c4 +source_hash: b2f73a2c1f38ba263d2452a68e8dbf5f116167d23eb2036a6a6f768c70205a17 --- `self_hosted` Session 在应用拥有的机器上运行,例如工作站、虚拟机或容器,而不是 Core 管理的沙箱。本指南面向用 `oac-daemon` 连接此类机器并保持其运行的应用开发者。 @@ -21,7 +21,7 @@ Session 自带模型提供商;安装默认模型不适用([原因](../../../ | macOS arm64 | 支持 | 支持 | 支持 | | Windows amd64 | 支持 | 支持 | 不支持 | -安装程序自带固定版本的 Node.js 和 Harness(列于 [`scripts/build-native-installer.mjs`](https://github.com/MiniMax-AI/OpenAgentCore/blob/main/scripts/build-native-installer.mjs)),不修改这些工具的其他安装。在没有匹配安装程序的平台上,命令会失败。 +安装程序自带固定版本的 Node.js 和 Harness(Harness 版本见 [Harness 目录](https://github.com/MiniMax-AI/OpenAgentCore/blob/main/contracts/agents-api/harness-catalog.md),Node.js 见 [`scripts/build-native-installer.mjs`](https://github.com/MiniMax-AI/OpenAgentCore/blob/main/scripts/build-native-installer.mjs)),不修改这些工具的其他安装。在没有匹配安装程序的平台上,命令会失败。 下载量取决于你安装的 Harness。安装程序(9 MiB)和 Node.js(59 MiB)始终需要,再加上 Codex 的 121 MiB、Claude Code 的 99 MiB 或 MiniMax Code 的 23 MiB,因此安装一个 Harness 的 Session 下载 90 到 189 MiB。Runtime 主目录和安装目录所在磁盘需要有空闲空间: diff --git a/docs/zh/maintainers.md b/docs/zh/maintainers.md index 7fbf7b40d..0a542a927 100644 --- a/docs/zh/maintainers.md +++ b/docs/zh/maintainers.md @@ -1,7 +1,7 @@ --- title: "构建并发布 OpenAgentCore" source: docs/maintainers.md -source_hash: c0ce961c1457daffdada461892d2e75a44efa15efce814f535c60b98b0b7a6fc +source_hash: 4f856b71fa88a18950c6830dc906ef060ccf79f7514585606f0fdc9df94a89b5 --- 本指南面向负责构建和发布 OpenAgentCore 的维护者。要安装 Core 和 Web,请按 [安装 Core 和 Web](getting-started/install.md) 操作。安装程序代码遵循的规则见 [部署](https://github.com/MiniMax-AI/OpenAgentCore/blob/main/deploy/README.md) 和 [节点安装程序](https://github.com/MiniMax-AI/OpenAgentCore/blob/main/deploy/node/README.md);必需检查见 [CONTRIBUTING](https://github.com/MiniMax-AI/OpenAgentCore/blob/main/CONTRIBUTING.md#required-checks)。 @@ -48,7 +48,7 @@ ingress 镜像仅包含 `oac` 和四个节点元数据文件:`manifest.json` ### 原生安装程序 {#native-installers} -自托管机器通过各平台的原生安装程序安装 `oac-daemon`:Linux amd64、macOS arm64 和 Windows amd64。每个安装程序均由 `native-check` 工作流在各自的操作系统上构建(`scripts/build-native-installer.mjs`,其中的 `pins` 对象会固定 Node.js 和 Harness 版本),并在每次选中的原生检查中得到验证。手动打包运行和发布检查会将该平台的各个归档上传为 `oac-native-installer--` 并保留七天;普通 PR 和 main 检查即使成功也不会上传软件包。要构建本地分发包,请从该确切提交的一次 `native-check` 运行中下载这三个构件(可以是手动运行或发布运行;PR 运行构建的是合并提交,因此不匹配),然后使用该检出内容组装目录,输入目录中放入这三个构件的所有归档: +自托管机器通过各平台的原生安装程序安装 `oac-daemon`:Linux amd64、macOS arm64 和 Windows amd64。每个安装程序均由 `native-check` 工作流在各自的操作系统上构建(`scripts/build-native-installer.mjs`,其中的 `pins` 对象包含 Node.js 版本和由各 Harness 声明生成的 Harness 版本),并在每次选中的原生检查中得到验证。手动打包运行和发布检查会将该平台的各个归档上传为 `oac-native-installer--` 并保留七天;普通 PR 和 main 检查即使成功也不会上传软件包。要构建本地分发包,请从该确切提交的一次 `native-check` 运行中下载这三个构件(可以是手动运行或发布运行;PR 运行构建的是合并提交,因此不匹配),然后使用该检出内容组装目录,输入目录中放入这三个构件的所有归档: ```sh node scripts/build-native-catalog.mjs INPUT_DIR OUTPUT_DIR @@ -65,7 +65,7 @@ export OAC_NATIVE_INSTALLER_BUILD_DIR=OUTPUT_DIR 三个维护的 Runtime 镜像共用固定摘要的基础镜像 `node:22.23.1-bookworm-slim`(含 `ca-certificates`、`bash`、`git`、`python3`、`python3-pip` 和 `ripgrep`),以及一个构建期调整:固定 Debian 登录 profile 会保留继承且已导出的 `PATH`,未设置 `PATH` 时仍使用 Debian 默认值。这样,登录和非登录工具都能使用 Runtime 初始化的包路径与用户路径,无需另一份包路径设置。组合镜像继承同一 profile。上游 profile 结构变化会使构建失败以便审查;自定义 shell 启动文件仍可以显式更改 `PATH`。 -**Codex Runtime 镜像。** 在 `~/.oac` 下解压官方 npm 包 `@openai/codex@0.153.4-linux-x64`(例如使用 `npm pack --ignore-scripts` 和 `tar -xzf`),然后执行: +**Codex Runtime 镜像。** 在 `~/.oac` 下解压官方 npm 包 `@openai/codex@-linux-x64`,版本见 [Harness 目录](https://github.com/MiniMax-AI/OpenAgentCore/blob/main/contracts/agents-api/harness-catalog.md)(例如使用 `npm pack --ignore-scripts` 和 `tar -xzf`),然后执行: ```sh export CODEX_CLI_DIR=/absolute/path/to/package diff --git a/internal/harnessconfig/claudesdk/declaration.go b/internal/harnessconfig/claudesdk/declaration.go index dbbb5ba0c..049d58260 100644 --- a/internal/harnessconfig/claudesdk/declaration.go +++ b/internal/harnessconfig/claudesdk/declaration.go @@ -17,8 +17,9 @@ import ( // Declaration is the only authored description of the Claude Code Harness. The // Runtime may narrow Capabilities to the installed bundle, never widen them. var Declaration = harnessconfig.Declaration{ - Kind: "claude_sdk", - Label: "Claude Code", + Kind: "claude_sdk", + Label: "Claude Code", + Native: harnessconfig.NativePackage{Component: "claude", Version: "0.3.269"}, Configuration: harnessconfig.Configuration{ ValidateNativeConfig: validateNativeConfig, Providers: []harnessconfig.Provider{{Protocol: "anthropic"}}, diff --git a/internal/harnessconfig/codex/declaration.go b/internal/harnessconfig/codex/declaration.go index 93f96aca8..5f3d75c45 100644 --- a/internal/harnessconfig/codex/declaration.go +++ b/internal/harnessconfig/codex/declaration.go @@ -13,8 +13,9 @@ import ( // Declaration is the only authored description of the Codex Harness. The // Runtime may narrow Capabilities for the installed host, never widen them. var Declaration = harnessconfig.Declaration{ - Kind: "codex", - Label: "Codex", + Kind: "codex", + Label: "Codex", + Native: harnessconfig.NativePackage{Component: "codex", Version: "0.153.4"}, Configuration: harnessconfig.Configuration{ // context_window maps to model_context_window; Codex has no native // max_output_tokens setting. diff --git a/internal/harnessconfig/harness.go b/internal/harnessconfig/harness.go index e83562cdd..356020490 100644 --- a/internal/harnessconfig/harness.go +++ b/internal/harnessconfig/harness.go @@ -61,6 +61,10 @@ type Configuration struct { ValidateNativeConfig func(proto.HarnessConfig) bool } +// NativePackage names the native Harness package and its single supported version. +// Component is the name of its native installer component. +type NativePackage struct{ Component, Version string } + // Declaration is everything a Harness states about itself, authored once in // internal/harnessconfig//declaration.go. The Runtime adapter binds it // to native execution, and Core admission validates every Session against it: @@ -73,6 +77,9 @@ type Configuration struct { type Declaration struct { // Kind is the public identifier; Label is its display name. Kind, Label string + // Native is the pinned native package the Harness runs. Every projection of + // its name and version is generated from, or checked against, this value. + Native NativePackage // Configuration declares model providers and native parameter validation. Configuration // Capabilities is the maximum the adapter supports on a capable host and the diff --git a/internal/harnessconfig/mcode/declaration.go b/internal/harnessconfig/mcode/declaration.go index 4c0d873bb..e0f6330ac 100644 --- a/internal/harnessconfig/mcode/declaration.go +++ b/internal/harnessconfig/mcode/declaration.go @@ -17,8 +17,9 @@ const FunctionServerLabel = "functions" // Whitespace-only text is unsupported because the native runtime refuses such // prompts with "Local message content or attachments are required.". var Declaration = harnessconfig.Declaration{ - Kind: "mcode", - Label: "MiniMax Code", + Kind: "mcode", + Label: "MiniMax Code", + Native: harnessconfig.NativePackage{Component: "minimax", Version: "0.4.12"}, Configuration: harnessconfig.Configuration{Providers: []harnessconfig.Provider{ {Protocol: "anthropic"}, {Protocol: "responses"}, diff --git a/scripts/build-core.sh b/scripts/build-core.sh index 3feabc800..78e6a2326 100755 --- a/scripts/build-core.sh +++ b/scripts/build-core.sh @@ -27,7 +27,7 @@ tar -C "$repo_root" -cf - \ contracts/agents-api/v1 \ contracts/agents-api/openapi.go contracts/agents-api/openapi.yaml contracts/agents-api/core.openapi.yaml contracts/agents-api/runtime.openapi.yaml \ internal/agentdaemon/proto \ - internal/runtimefs internal/runtimebootstrap internal/agentnetwork internal/agentbundle internal/agentcapabilities internal/agentplugin internal/agentskill internal/harnessconfig internal/modelprovider internal/providerassets internal/obs/log services/core \ + internal/runtimefs internal/runtimebootstrap internal/agentbundle internal/agentcapabilities internal/agentplugin internal/agentskill internal/harnessconfig internal/modelprovider internal/providerassets internal/obs/log services/core \ | tar -C "$build_context" -xf - ( diff --git a/scripts/build-native-installer.mjs b/scripts/build-native-installer.mjs index 55c7f4e04..07c94d775 100644 --- a/scripts/build-native-installer.mjs +++ b/scripts/build-native-installer.mjs @@ -1,12 +1,13 @@ #!/usr/bin/env node // Package trusted, already-built native artifacts. This does not install on a host. import { createHash } from 'node:crypto'; +import { readFileSync } from 'node:fs'; import { execFileSync, spawnSync } from 'node:child_process'; import { chmod, copyFile, lstat, mkdir, mkdtemp, readFile, readdir, realpath, rename, rm, stat, writeFile } from 'node:fs/promises'; import { basename, dirname, isAbsolute, join, relative, sep } from 'node:path'; import { createRequire } from 'node:module'; -export const pins = { node: '22.22.0', codex: '0.153.4', claude: '0.3.269', minimax: '0.4.12' }; +export const pins = { node: '22.22.0', ...JSON.parse(readFileSync(new URL('./native-pins.json', import.meta.url), 'utf8')) }; const platforms = { linux: 'linux', darwin: 'darwin', win32: 'windows' }; const architectures = { x64: 'amd64', arm64: 'arm64' }; const inside = (root, path) => { diff --git a/scripts/ci_plan.py b/scripts/ci_plan.py index 6aee80a37..7d6836881 100644 --- a/scripts/ci_plan.py +++ b/scripts/ci_plan.py @@ -108,7 +108,7 @@ IMAGE_INPUTS = ("scripts/build-core", "scripts/build-e2b-provider", "deploy/distribution/", "services/core/tools/e2b-provider/", "services/core/deploy/e2b/") # Generated outputs retain freshness checks even when the file is documentation. -GENERATED_OUTPUTS = {"contracts/agents-api/harness-catalog.md", "contracts/agents-api/zh/harness-catalog.md", "packages/agents-client/src/harness-catalog.ts", +GENERATED_OUTPUTS = {"scripts/native-pins.json", "contracts/agents-api/harness-catalog.md", "contracts/agents-api/zh/harness-catalog.md", "packages/agents-client/src/harness-catalog.ts", "internal/harnessconfig/builtin/registry.go", "apps/daemon/internal/cli/harness_declarations.go"} diff --git a/scripts/generate-harness-catalog.py b/scripts/generate-harness-catalog.py index a9bc5b00f..fb7a9047b 100644 --- a/scripts/generate-harness-catalog.py +++ b/scripts/generate-harness-catalog.py @@ -86,7 +86,7 @@ def render_registrations(names): def render_docs(harnesses): tick = chr(96) rows = "\n".join( - f'| {tick}{h["kind"]}{tick} | {h["label"]} | [{tick}{h["package"]}/declaration.go{tick}]({SOURCE}internal/harnessconfig/{h["package"]}/declaration.go) |' + f'| {tick}{h["kind"]}{tick} | {h["label"]} | {tick}{h["version"]}{tick} | [{tick}{h["package"]}/declaration.go{tick}]({SOURCE}internal/harnessconfig/{h["package"]}/declaration.go) |' for h in harnesses) return { Path("contracts/agents-api/harness-catalog.md"): f"""--- @@ -98,8 +98,8 @@ def render_docs(harnesses): Each Harness is the one {tick}declaration.go{tick} in its {tick}internal/harnessconfig/{tick} directory. Adding a directory with a {tick}declaration.go{tick} registers the Harness; {tick}make generate-harness-catalog{tick} regenerates the registrations and this page, and {tick}make check-harness-catalog{tick} checks them. -| Identifier | Display name | Declaration | -| --- | --- | --- | +| Identifier | Display name | Native version | Declaration | +| --- | --- | --- | --- | {rows} These registrations describe the build. Which Harnesses a deployment enables is the {tick}OAC_HARNESSES{tick} [process setting](../../docs/configuration.md#settings), [Harness capabilities](./harness-capabilities.md) lists what each Harness supports, and a connected Runtime reports its own availability. [Harness protocol](./harness-onboarding.md) describes the adapter and packaging steps. @@ -113,8 +113,8 @@ def render_docs(harnesses): 每个 Harness 对应 {tick}internal/harnessconfig/{tick} 目录中唯一的 {tick}declaration.go{tick}。新增包含 {tick}declaration.go{tick} 的目录即注册该 Harness;{tick}make generate-harness-catalog{tick} 重新生成注册代码和本页,{tick}make check-harness-catalog{tick} 检查生成结果。 -| 标识符 | 显示名称 | 声明 | -| --- | --- | --- | +| 标识符 | 显示名称 | 原生版本 | 声明 | +| --- | --- | --- | --- | {rows} 这些注册描述当前构建。部署启用的 Harness 由 {tick}OAC_HARNESSES{tick} [进程设置](../../../docs/zh/configuration.md#settings)决定;[Harness 能力](./harness-capabilities.md)列出各 Harness 的支持范围,连接的 Runtime 报告自身可用性。[Harness protocol](./harness-onboarding.md)介绍适配器和打包步骤。 @@ -122,6 +122,48 @@ def render_docs(harnesses): } +# Projections of a native pin that other tools need in their own syntax. Each +# entry is checked against the declaration; a stale one names the file to edit. +# The installer pins file is generated, so it is not listed here. +NATIVE_PROJECTIONS = { + "codex": { + "scripts/build-codex-runtime.sh": ["@openai/codex@{v}-linux-x64", "== '{v}-linux-x64'"], + "scripts/prepare-release-runtimes.sh": ["@openai/codex@{v}-linux-x64"], + "scripts/native-harness-smoke.mjs": ["codex-cli {v}", "version: '{v}'"], + "services/core/deploy/codex/Dockerfile": ["Codex {v}", 'codex-cli {v}"'], + "deploy/distribution/Runtime.Dockerfile": ['codex-cli {v}"'], + ".github/workflows/native.yml": ["@openai/codex@{v}\n"], + "services/core/deploy/codex/README.md": ["`{v}`"], + }, + "claude": { + "scripts/native-harness-smoke.mjs": ["!== '{v}'", "info.sdk !== '{v}'"], + "packages/claude-sdk-adapter/package.json": ['"@anthropic-ai/claude-agent-sdk": "{v}"'], + }, + "minimax": { + "scripts/build-mcode-runtime.sh": ["= {v}\n"], + "scripts/build-mcode-harness.sh": ["= {v}\n"], + "packages/mcode-harness/source.json": ['"version": "{v}"'], + "services/core/deploy/mcode/README.md": ["`{v}`"], + }, +} + + +def render_pins(harnesses): + return json.dumps({h["component"]: h["version"] for h in harnesses}, indent=2) + "\n" + + +def stale_native_projections(harnesses, root=ROOT): + versions = {h["component"]: h["version"] for h in harnesses} + stale = [] + for component, files in NATIVE_PROJECTIONS.items(): + for relative, templates in files.items(): + text = (root / relative).read_text() + for template in templates: + if template.format(v=versions[component]) not in text: + stale.append(relative + " (" + component + " " + versions[component] + ")") + return stale + + def main(): parser = argparse.ArgumentParser(description=__doc__) parser.add_argument("--check", action="store_true") @@ -153,6 +195,10 @@ def projection(relative, content): raise SystemExit("Registered Harnesses differ from the declaration packages") for relative, content in render_docs(harnesses).items(): projection(relative, content) + projection(Path("scripts/native-pins.json"), render_pins(harnesses)) + native = stale_native_projections(harnesses) + if native: + raise SystemExit("Native pins differ from the declarations; edit these files to match:\n" + "\n".join(native)) projection(Path("packages/agents-client/src/harness-catalog.ts"), render_client(harnesses, declared["protocols"])) if stale: raise SystemExit("Stale Harness catalog projections; run make generate-harness-catalog:\n" + "\n".join(stale)) diff --git a/scripts/generate-harness-catalog.test.py b/scripts/generate-harness-catalog.test.py index 529a7f34a..0fa28eeae 100644 --- a/scripts/generate-harness-catalog.test.py +++ b/scripts/generate-harness-catalog.test.py @@ -22,7 +22,7 @@ def module(name, file): class HarnessCatalogTests(unittest.TestCase): def test_new_declaration_reaches_all_projections(self): - harnesses = [{"kind": "example", "label": "Example", "package": "example"}] + harnesses = [{"kind": "example", "label": "Example", "package": "example", "component": "example", "version": "1.0.0"}] generated = {**catalog.render_registrations(["example"]), **catalog.render_docs(harnesses)} generated["client"] = catalog.render_client(harnesses, ["responses"]) for content in generated.values(): diff --git a/scripts/harness-catalog/main.go b/scripts/harness-catalog/main.go index e217f3e72..14f31baa4 100644 --- a/scripts/harness-catalog/main.go +++ b/scripts/harness-catalog/main.go @@ -13,13 +13,16 @@ import ( type harness struct { Kind string `json:"kind"` Label string `json:"label"` + // Component and Version name the native installer component and its pin. + Component string `json:"component"` + Version string `json:"version"` } func declarations() []harness { var result []harness for _, kind := range builtin.Kinds() { declaration, _ := builtin.Registry().Lookup(kind) - result = append(result, harness{Kind: kind, Label: declaration.Label}) + result = append(result, harness{Kind: kind, Label: declaration.Label, Component: declaration.Native.Component, Version: declaration.Native.Version}) } return result } diff --git a/scripts/native-pins.json b/scripts/native-pins.json new file mode 100644 index 000000000..e57358257 --- /dev/null +++ b/scripts/native-pins.json @@ -0,0 +1,5 @@ +{ + "claude": "0.3.269", + "codex": "0.153.4", + "minimax": "0.4.12" +} diff --git a/internal/agentnetwork/policy.go b/services/core/internal/agentnetwork/policy.go similarity index 100% rename from internal/agentnetwork/policy.go rename to services/core/internal/agentnetwork/policy.go diff --git a/internal/agentnetwork/policy_test.go b/services/core/internal/agentnetwork/policy_test.go similarity index 100% rename from internal/agentnetwork/policy_test.go rename to services/core/internal/agentnetwork/policy_test.go diff --git a/services/core/internal/api/hosted_environment.go b/services/core/internal/api/hosted_environment.go index 4ed45216d..ded3037a5 100644 --- a/services/core/internal/api/hosted_environment.go +++ b/services/core/internal/api/hosted_environment.go @@ -6,7 +6,7 @@ import ( v1 "github.com/MiniMax-AI/OpenAgentCore/contracts/agents-api/v1" "github.com/MiniMax-AI/OpenAgentCore/internal/agentcapabilities" - "github.com/MiniMax-AI/OpenAgentCore/internal/agentnetwork" + "github.com/MiniMax-AI/OpenAgentCore/services/core/internal/agentnetwork" "github.com/MiniMax-AI/OpenAgentCore/services/core/internal/environmentconfig" "github.com/MiniMax-AI/OpenAgentCore/services/core/internal/sessions" ) diff --git a/services/core/internal/api/session_template.go b/services/core/internal/api/session_template.go index 54e505ef5..cfe2297be 100644 --- a/services/core/internal/api/session_template.go +++ b/services/core/internal/api/session_template.go @@ -7,7 +7,7 @@ import ( "slices" v1 "github.com/MiniMax-AI/OpenAgentCore/contracts/agents-api/v1" - "github.com/MiniMax-AI/OpenAgentCore/internal/agentnetwork" + "github.com/MiniMax-AI/OpenAgentCore/services/core/internal/agentnetwork" "github.com/MiniMax-AI/OpenAgentCore/services/core/internal/environmentconfig" "github.com/MiniMax-AI/OpenAgentCore/services/core/internal/environmenttemplates" "github.com/MiniMax-AI/OpenAgentCore/services/core/internal/sessions" diff --git a/services/core/internal/environmenttemplates/template.go b/services/core/internal/environmenttemplates/template.go index 7c6209ced..cd3305329 100644 --- a/services/core/internal/environmenttemplates/template.go +++ b/services/core/internal/environmenttemplates/template.go @@ -5,7 +5,7 @@ import ( "unicode/utf8" v1 "github.com/MiniMax-AI/OpenAgentCore/contracts/agents-api/v1" - "github.com/MiniMax-AI/OpenAgentCore/internal/agentnetwork" + "github.com/MiniMax-AI/OpenAgentCore/services/core/internal/agentnetwork" "github.com/MiniMax-AI/OpenAgentCore/internal/agentplugin" "github.com/MiniMax-AI/OpenAgentCore/services/core/internal/environmentconfig" )