chore(wrappers)!: drop env-allowlist, env-extra, allow-protocol-skew from wrappers (sync with engine)#31
Merged
Conversation
…om AssembleArgvInput + argv emission The engine removed the --env-allowlist, --env-extra, and --allow-protocol-skew argv flags in PR #27 (host config layer). The TypeScript wrapper was still emitting them when the corresponding AssembleArgvInput / SessionHandleParams / SpawnAgentParams fields were set, which made engine click reject the invocation with UsageError (exit 2) for any wrapper consumer that supplied them. This commit removes: - envAllowlist, envExtra, allowProtocolSkew from AssembleArgvInput and the three argv.push(...) blocks in assembleArgv() - envAllowlist, envExtra, allowProtocolSkew from SessionHandleParams and the threading through to assembleArgv() - allowProtocolSkew from SpawnAgentParams and the threading through to new SessionHandle(...) SpawnAgentParams.env = { allowlist, extra } is preserved unchanged - the wrapper still composes the subprocess environment via buildEnv(). Only the FORWARDING of those values as argv flags to the engine is removed. argv-builder tests are extended with @ts-expect-error compile-time guardrails and runtime negative assertions for all three flags, mirroring PR #29's removal pattern for --mcp-config-path. NC follow-up: the NC adapter (amplifier-module-provider-nc) may pass envAllowlist / envExtra / allowProtocolSkew to spawnAgent(); a follow-up adapter PR will catch it up. BREAKING CHANGE: SpawnAgentParams.allowProtocolSkew, SessionHandleParams.envAllowlist / envExtra / allowProtocolSkew, and the corresponding AssembleArgvInput fields are removed. Hosts that need the skew override now set host_config.allowProtocolSkew: true in the JSON config file. Hosts that need custom env composition either set $AMPLIFIER_AGENT_CONFIG in the subprocess env or pass --config <path> per turn. 🤖 Generated with [Amplifier](https://github.com/microsoft/amplifier) Co-Authored-By: Amplifier <240397093+microsoft-amplifier@users.noreply.github.com>
…w from spawn_agent + assemble_argv The engine removed the --env-allowlist, --env-extra, and --allow-protocol-skew argv flags in PR #27 (host config layer). The Python wrapper was still emitting them when the corresponding kwargs were set, which made engine click reject the invocation with UsageError (exit 2) for any wrapper consumer that supplied them. This commit removes: - env_allowlist, env_extra, allow_protocol_skew kwargs from assemble_argv and the three argv.extend(...) / argv.append(...) blocks - env_allowlist, env_extra, allow_protocol_skew fields from SessionHandleParams (and the unused `field` import that they required) plus the threading into assemble_argv - allow_protocol_skew kwarg from spawn_agent and the threading into SessionHandleParams spawn_agent(env={"allowlist": ..., "extra": ...}) is preserved unchanged - the wrapper still composes the subprocess environment via build_env(). Only the FORWARDING of those values as argv flags to the engine is removed. test_argv_builder is extended with three TypeError-rejected kwarg tests and three "flag not emitted" negative assertions, mirroring PR #29's removal pattern for --mcp-config-path. NC follow-up: the NC adapter (amplifier-module-provider-nc) may pass env_allowlist / env_extra / allow_protocol_skew to spawn_agent(); a follow-up adapter PR will catch it up. BREAKING CHANGE: spawn_agent.allow_protocol_skew, SessionHandleParams.env_allowlist / env_extra / allow_protocol_skew, and the corresponding assemble_argv kwargs are removed. Hosts that need the skew override now set host_config.allowProtocolSkew: true in the JSON config file. Hosts that need custom env composition either set $AMPLIFIER_AGENT_CONFIG in the subprocess env or pass --config <path> per turn. 🤖 Generated with [Amplifier](https://github.com/microsoft/amplifier) Co-Authored-By: Amplifier <240397093+microsoft-amplifier@users.noreply.github.com>
Regenerates wrappers/typescript/dist/ to reflect the source removals in 796f10d (drop envAllowlist, envExtra, allowProtocolSkew from AssembleArgvInput / SessionHandleParams / SpawnAgentParams + argv emission). Mirrors PR #29's pattern of committing the rebuilt dist alongside the source change so consumers using the published package see the API narrowing immediately. No additional source changes. 🤖 Generated with [Amplifier](https://github.com/microsoft/amplifier) Co-Authored-By: Amplifier <240397093+microsoft-amplifier@users.noreply.github.com>
manojp99
added a commit
that referenced
this pull request
Jun 3, 2026
…#27, #29, #31) (#32) * fix(conformance): rename runner refs to initialize-with-mcp-config-path (post-#24) PR #24 renamed the wire-shape fixture from ``initialize-with-mcpservers.yaml`` to ``initialize-with-mcp-config-path.yaml`` but left three hardcoded references to the old name behind: * wrappers/conformance/test/runner-ts.test.ts (TS conformance suite) * wrappers/conformance/tests/test_runner_py.py (Py conformance suite) * tests/test_phase_2_1_exit_gate.py (engine-side fixture-set guard) All three have been failing since PR #24. The conformance suites showed up as "1 pre-existing failure each" in PRs #27, #29, and #31, so wrapper/engine drift could land unseen during the entire window in which we did most of the v0.3.0 argv cleanup -- the exact class of bug the conformance suite is supposed to catch. This commit restores the baseline to green by pointing each reference at the surviving wire-protocol fixture name. No fixture data changes, no engine logic changes. Verification (this commit, host machine): * wrappers/conformance/ (TS): 5 passed (was 4 passed, 1 failed) * wrappers/conformance/ (Py): 5 passed (was 4 passed, 1 failed) * tests/test_phase_2_1_exit_gate.py: passes (was failing) Out of scope (separate cleanup, noted for the PR body): * tests/cli/test_mode_a_v2_envelope.py still has 3 pre-existing failures referencing the removed ``--mcp-servers`` flag. Not touched here per the conformance-restore PR scope. * chore(conformance): align version_skew remediation text with post-#27 host-config surface PR #27 dropped the --allow-protocol-skew argv flag and moved protocol-skew opt-in into the host config file (allowProtocolSkew: true, surfaced through --config). The engine's real protocol_version_mismatch remediation string was updated in lockstep (src/amplifier_agent_lib/engine.py:160-163). The version_skew wire-shape fixture's scripted server response still carried the old 'pass --allow-protocol-skew' remediation text, drifting it from current engine behavior even though no assertion in the fixture exercises the field directly. Update the scripted response to match the engine's current text so the fixture remains an honest exemplar of the wire-protocol surface post-#27/#29/#31. Companion to PR #31 fixture sweep. No engine logic changes, no assertions changed, no test outcome changes. * test(conformance): add baseline + protocol-skew-override wire-shape fixtures Extend the conformance suite with two wire-protocol fixtures that lock in the post-cleanup surface and the previously-uncovered override branch of the version-skew contract: * initialize-baseline.yaml -- canonical minimum init + turn/submit + result/final flow with only protocol-required params (no mcpConfigPath, no allowProtocolSkew, no hostCapabilities, no envAllowlist, no envExtra). Locks in the wire shape that survives PR #27 (host config + drop hostCapabilities), PR #29 (drop --mcp-config-path argv), and PR #31 (drop env-allowlist / env-extra / allow-protocol-skew from wrappers). Any future re-introduction of those legacy fields on the wire must be an intentional, reviewed addition rather than silent drift. * initialize-with-protocol-skew-override.yaml -- the 'permits the handshake' branch of design §8 D6, companion to version_skew.yaml which covers only the strict-refuse branch. Client sends allowProtocolSkew=true (now sourced from the host config file, not from a --allow-protocol-skew argv flag) and a mismatched protocolVersion; server returns a successful sessionState instead of protocol_version_mismatch. Both new fixtures are wired into the TS and Python conformance runners and acknowledged in the two fixture-set guard tests (tests/test_protocol_conformance_fixtures.py and tests/test_phase_2_1_exit_gate.py). Scope note: the conformance runners use scripted JSON-RPC wire replay (ScriptedTransport) -- they do NOT spawn the engine subprocess. Argv-level 'loud failure' invariants for the dropped flags (--host-capabilities, --env-allowlist, --env-extra, --allow-protocol-skew, --mcp-config-path) are already locked in by the engine-side click-CliRunner tests at tests/cli/test_drop_host_capabilities.py and tests/cli/test_drop_mcp_config_path_flag.py. Extending the conformance runner to also exercise argv-level invariants would require subprocess invocation and changes to the loader at src/amplifier_agent_lib/protocol/conformance/loader.py (engine-internal, off limits per the PR scope) and is intentionally left for a future PR. Verification (host machine): * wrappers/conformance/ (TS): 7 passed (was 5 after rename commit) * wrappers/conformance/ (Py): 7 passed (was 5 after rename commit) * tests/test_protocol_conformance_fixtures.py: 17 passed (was 16; the new fixtures load and validate) * tests/test_phase_2_1_exit_gate.py: passes (now acknowledges the new fixtures in the sorted-name guard) * Engine suite (uv run pytest -q --ignore=wrappers): 519 passed, 3 pre-existing failures in tests/cli/test_mode_a_v2_envelope.py (unchanged from PR #31's pre-existing baseline -- they reference the long-removed --mcp-servers flag and are tracked for a separate cleanup). * Wrappers/python: 48 passed; wrappers/typescript: 63 passed; manual smoke confirms --host-capabilities / --env-allowlist / --env-extra / --allow-protocol-skew / --mcp-config-path all reject with click UsageError ('no such option'). --------- Co-authored-by: Manoj Prabhakar Paidiparthy <mpaidiparthy@microsoft.com>
manojp99
pushed a commit
that referenced
this pull request
Jun 3, 2026
Engine version bump for the host-config-layer release window. Pairs with the wire PROTOCOL_VERSION bump (0.2.0 -> 0.3.0) and consolidates argv/wire surface removals shipped in PRs #27, #29, #30, #31. Verified: $ uv run amplifier-agent --version amplifier-agent, version 0.4.0 BREAKING CHANGE: Engine version 0.3.0 -> 0.4.0. Wire protocol 0.2.0 -> 0.3.0 shipped in the same release. Old wrappers fail handshake. See CHANGELOG.md for the full argv/wire/API removal list.
manojp99
pushed a commit
that referenced
this pull request
Jun 3, 2026
Python wrapper version bump to pair with the engine 0.4.0 release. Same major.minor as engine — the two move together. The wrapper's compiled PROTOCOL_VERSION (sourced from amplifier_agent_lib) follows the engine bump 0.2.0 -> 0.3.0 transitively. BREAKING CHANGE: SpawnAgentParams API removed envAllowlist, envExtra, allowProtocolSkew, host, and mcpConfigPath fields across PRs #27, #29, #31. Callers must migrate to host_config (JSON file passed via --config or $AMPLIFIER_AGENT_CONFIG) or env var injection (AMPLIFIER_MCP_CONFIG).
manojp99
pushed a commit
that referenced
this pull request
Jun 3, 2026
The TS wrapper jumps minor (0.4.0 -> 0.5.0) rather than tracking the
engine's major.minor (0.4.0) because of release-window history:
- 0.4.0 was already published to npm (verified: 'npm view
amplifier-agent-ts versions' lists 0.3.0, 0.3.1, 0.4.0)
- 0.4.0 was published by PR #17 (path-based MCP config delivery,
pre-#27/#29/#30/#31)
- Since the 0.4.0 publish, PRs #27, #29, #30, #31 have all landed,
removing breaking surface from the TS wrapper API:
* SpawnAgentParams.host / HostCapabilities type (#27)
* mcpConfigPath field + argv emission (#29)
* envAllowlist / envExtra / allowProtocolSkew fields (#31)
We cannot republish 0.4.0 with different code, and the accumulated changes
are breaking (not a patch). Bumping to 0.5.0 puts the next npm release on
a fresh, unpublished version. If you have context I'm missing about a
prior decision to keep TS major.minor tied to engine major.minor, override
with a follow-up bump.
BREAKING CHANGE: TS wrapper API removed SpawnAgentParams.host,
HostCapabilities type, InitializeHostParams type (#27); mcpConfigPath field
+ argv emission (#29); envAllowlist, envExtra, allowProtocolSkew fields
(#31). Callers must migrate to AMPLIFIER_MCP_CONFIG env var and a
host_config JSON file passed via --config.
manojp99
pushed a commit
that referenced
this pull request
Jun 3, 2026
, #32) Replace the [Unreleased] section with a full [0.4.0] - 2026-06-03 entry that consolidates the host-config-layer release window: PR #27 - Host config layer + drop hostCapabilities surface PR #29 - Drop --mcp-config-path argv (subsumed by host config + env var) PR #30 - host-config skills: block + tool-skills bundle composition PR #31 - Drop env-allowlist, env-extra, allow-protocol-skew from wrappers PR #32 - Restore conformance suite Highlights: - 4 argv flags + 1 env var removed (subsumed by host config layer) - hostCapabilities fully removed from envelope, initialize, and wrapper API - 5th host-config block 'skills:' (D11/D12/D13) - Wire protocol 0.2.0 -> 0.3.0 (BREAKING) - Engine 0.3.0 -> 0.4.0, Python wrapper 0.3.0 -> 0.4.0, TS wrapper 0.4.0 -> 0.5.0 Also documents the cross-repo follow-ups that downstream consumers (notably amplifier-module-provider-nc) must catch up on but are NOT part of this release.
manojp99
pushed a commit
that referenced
this pull request
Jun 3, 2026
Closes the last 4 Python CI failures on this release branch. (1) tests/cli/test_config_show.py::test_config_show_reports_default_when_env_absent Click's CliRunner.invoke(env=...) MERGES the env dict with os.environ instead of replacing it. GitHub Actions runners set XDG_CONFIG_HOME by default, which leaked into the test and made source='env:XDG_CONFIG_HOME' instead of the 'default' the test was asserting. Now uses monkeypatch.delenv() to explicitly remove XDG_CONFIG_HOME / XDG_CACHE_HOME / XDG_STATE_HOME before invoking. (2) tests/cli/test_mode_a_v2_envelope.py The three test_mcp_servers_* tests (inline_json_parsed, at_path_form, malformed_json_yields_argv_envelope) target the --mcp-servers argv flag. That flag was renamed to --mcp-config-path by PR #24 and then fully removed by PR #29. The tests have been failing as 'pre-existing baseline' through PRs #27, #29, #31, #32, and #33's earlier baselines. They test removed surface and should never have been kept. Replaced with an inline comment naming the removal context and pointing at the removal guardrail at tests/cli/test_drop_mcp_config_path_flag.py. Local: 532 passed, 3 skipped, 0 failed (full pytest tests/).
manojp99
added a commit
that referenced
this pull request
Jun 3, 2026
…ce restored (#33) * chore(protocol)!: bump wire PROTOCOL_VERSION 0.2.0 -> 0.3.0 Bump the wire protocol version to reflect accumulated backward-incompatible changes shipped under the 0.4.0 release window: - metadata.hostCapabilities removed from response envelope (#27) - InitializeParams.host removed (#27) - InitializeParams.mcpServers renamed to mcpConfigPath (#24) - skills field added (host config skills: block, #30) Old wrappers pinned to '0.2.0' should hard-fail handshake with a typed protocol_version_mismatch error and exit 2 — verified manually: $ uv run amplifier-agent run --protocol-version 0.2.0 --session-id sm 'hi' {... "code": "protocol_version_mismatch" ...} EXIT=2 $ uv run amplifier-agent run --protocol-version 0.3.0 --session-id sm 'hi' {... "reply": "..." ...} EXIT=0 Updated sites (audited via 'git grep "0.2.0" src/ tests/'): - src/amplifier_agent_lib/protocol/methods.py — PROTOCOL_VERSION constant - src/amplifier_agent_lib/protocol/spec.md — regenerated artifact - 9 conformance fixtures' protocolVersion: literals (setup + initialize params) - version_skew.yaml — serverVersion in expected error.data - 6 test files pinning protocolVersion in wrapper-side InitializeParams Left as historical references (per release-issue guidance): - loader.py docstring example (illustrative fixture shape) - test_protocol_conformance_fixtures.py's self-contained _VALID_FIXTURE (loader smoke test, not engine-compat) - serverInfo.version: "0.2.0" in fixture script result blocks (not asserted by conformance harness — engine emits __version__ at runtime; fixture scripts are descriptive, only the explicit assertions: block is verified) BREAKING CHANGE: Wire protocol 0.2.0 -> 0.3.0. Old wrappers pinned to 0.2.0 will hard-fail handshake with protocol_version_mismatch (exit 2). Reinstall both engine and wrapper, or set allowProtocolSkew: true in host config. * chore(engine)!: bump amplifier-agent version 0.3.0 -> 0.4.0 Engine version bump for the host-config-layer release window. Pairs with the wire PROTOCOL_VERSION bump (0.2.0 -> 0.3.0) and consolidates argv/wire surface removals shipped in PRs #27, #29, #30, #31. Verified: $ uv run amplifier-agent --version amplifier-agent, version 0.4.0 BREAKING CHANGE: Engine version 0.3.0 -> 0.4.0. Wire protocol 0.2.0 -> 0.3.0 shipped in the same release. Old wrappers fail handshake. See CHANGELOG.md for the full argv/wire/API removal list. * chore(wrapper-py)!: bump Python wrapper version 0.3.0 -> 0.4.0 Python wrapper version bump to pair with the engine 0.4.0 release. Same major.minor as engine — the two move together. The wrapper's compiled PROTOCOL_VERSION (sourced from amplifier_agent_lib) follows the engine bump 0.2.0 -> 0.3.0 transitively. BREAKING CHANGE: SpawnAgentParams API removed envAllowlist, envExtra, allowProtocolSkew, host, and mcpConfigPath fields across PRs #27, #29, #31. Callers must migrate to host_config (JSON file passed via --config or $AMPLIFIER_AGENT_CONFIG) or env var injection (AMPLIFIER_MCP_CONFIG). * chore(wrapper-ts)!: bump amplifier-agent-ts version 0.4.0 -> 0.5.0 The TS wrapper jumps minor (0.4.0 -> 0.5.0) rather than tracking the engine's major.minor (0.4.0) because of release-window history: - 0.4.0 was already published to npm (verified: 'npm view amplifier-agent-ts versions' lists 0.3.0, 0.3.1, 0.4.0) - 0.4.0 was published by PR #17 (path-based MCP config delivery, pre-#27/#29/#30/#31) - Since the 0.4.0 publish, PRs #27, #29, #30, #31 have all landed, removing breaking surface from the TS wrapper API: * SpawnAgentParams.host / HostCapabilities type (#27) * mcpConfigPath field + argv emission (#29) * envAllowlist / envExtra / allowProtocolSkew fields (#31) We cannot republish 0.4.0 with different code, and the accumulated changes are breaking (not a patch). Bumping to 0.5.0 puts the next npm release on a fresh, unpublished version. If you have context I'm missing about a prior decision to keep TS major.minor tied to engine major.minor, override with a follow-up bump. BREAKING CHANGE: TS wrapper API removed SpawnAgentParams.host, HostCapabilities type, InitializeHostParams type (#27); mcpConfigPath field + argv emission (#29); envAllowlist, envExtra, allowProtocolSkew fields (#31). Callers must migrate to AMPLIFIER_MCP_CONFIG env var and a host_config JSON file passed via --config. * docs(changelog): consolidate 0.4.0 release notes (PRs #27, #29, #30, #31, #32) Replace the [Unreleased] section with a full [0.4.0] - 2026-06-03 entry that consolidates the host-config-layer release window: PR #27 - Host config layer + drop hostCapabilities surface PR #29 - Drop --mcp-config-path argv (subsumed by host config + env var) PR #30 - host-config skills: block + tool-skills bundle composition PR #31 - Drop env-allowlist, env-extra, allow-protocol-skew from wrappers PR #32 - Restore conformance suite Highlights: - 4 argv flags + 1 env var removed (subsumed by host config layer) - hostCapabilities fully removed from envelope, initialize, and wrapper API - 5th host-config block 'skills:' (D11/D12/D13) - Wire protocol 0.2.0 -> 0.3.0 (BREAKING) - Engine 0.3.0 -> 0.4.0, Python wrapper 0.3.0 -> 0.4.0, TS wrapper 0.4.0 -> 0.5.0 Also documents the cross-repo follow-ups that downstream consumers (notably amplifier-module-provider-nc) must catch up on but are NOT part of this release. * fix(ci): commit uv.lock for deterministic dependency resolution The CI workflow uses astral-sh/setup-uv@v3 with enable-cache: true, which defaults to globbing **/uv.lock to compute the cache key. With uv.lock gitignored, every CI run failed at the install step with: No matches found for glob **/uv.lock Committing uv.lock fixes CI and aligns with Astral's recommended practice for reproducible builds. Catches reproducibility drift between contributors and CI/DTU. The lock is ~150KB. This was a pre-existing CI break on main (every recent CI run failing) that this version-bump release is unblocking as part of release-readiness. * fix(ci): install Node + pnpm for conformance parity tests tests/test_conformance_parity.py::test_ts_and_py_runners_agree[*] shells out to 'pnpm exec tsx runner_ts.ts' to cross-validate the TS runner against the Python runner. The Python CI job had no Node.js or pnpm installed, so all 10 parametrized cases failed with: FileNotFoundError: [Errno 2] No such file or directory: 'pnpm' Adds setup-node@v4, pnpm/action-setup@v3, and a pnpm-install step in wrappers/conformance/ before pytest runs. Pre-existing CI gap that this release branch is closing as part of release-readiness. * fix(ci): make XDG test hermetic + delete obsolete --mcp-servers tests Closes the last 4 Python CI failures on this release branch. (1) tests/cli/test_config_show.py::test_config_show_reports_default_when_env_absent Click's CliRunner.invoke(env=...) MERGES the env dict with os.environ instead of replacing it. GitHub Actions runners set XDG_CONFIG_HOME by default, which leaked into the test and made source='env:XDG_CONFIG_HOME' instead of the 'default' the test was asserting. Now uses monkeypatch.delenv() to explicitly remove XDG_CONFIG_HOME / XDG_CACHE_HOME / XDG_STATE_HOME before invoking. (2) tests/cli/test_mode_a_v2_envelope.py The three test_mcp_servers_* tests (inline_json_parsed, at_path_form, malformed_json_yields_argv_envelope) target the --mcp-servers argv flag. That flag was renamed to --mcp-config-path by PR #24 and then fully removed by PR #29. The tests have been failing as 'pre-existing baseline' through PRs #27, #29, #31, #32, and #33's earlier baselines. They test removed surface and should never have been kept. Replaced with an inline comment naming the removal context and pointing at the removal guardrail at tests/cli/test_drop_mcp_config_path_flag.py. Local: 532 passed, 3 skipped, 0 failed (full pytest tests/). --------- Co-authored-by: Manoj Prabhakar Paidiparthy <mpaidiparthy@microsoft.com>
manojp99
added a commit
that referenced
this pull request
Jun 3, 2026
…, approval, getEngineInfo, +5 more) (#36) * feat(wrapper-ts): re-export internal helpers from index.ts (#5) Adds named re-exports from the package entry point so consumers can import internal helpers without reaching into private deep paths: assembleArgv, AssembleArgvInput resolveMcpConfigPath, cleanupSpillFile, McpSpillResult buildEnv, resolveBinaryPath, probeEngineVersion, DEFAULT_ALLOWLIST, BLOCKED_ENV_KEYS, ResolveBinaryPathOptions, BuildEnvOptions Transport, TransportOptions, ExitInfo checkProtocolVersion, VersionCheckResult, VersionCheckOk, VersionCheckFail, CheckProtocolVersionOptions parseRunOutput, STDERR_TAIL_BYTES, SubprocessOutcome makeApprovalHandler, ApprovalAdapter, ApprovalRequest, ApprovalHandler Each export is annotated @public. Closes #5. * feat(wrapper-ts): wire checkProtocolVersion() into init path (#9) spawnAgent() now probes the engine's protocol version once during initialization (via amplifier-agent version --json) and runs checkProtocolVersion() against PROTOCOL_VERSION_REQUIRED_BY_WRAPPER BEFORE constructing a SessionHandle. Mismatch fails fast wrapper-side with AaaError(protocol_version_mismatch), saving a full subprocess roundtrip later. Adds two new SpawnAgentParams fields: - allowProtocolSkew?: boolean — bypass the check (mirrors engine's host_config.allowProtocolSkew) - _engineVersionProbe?: () => Promise<EngineVersionPayload> — test-only injection point for the probe Also bumps PROTOCOL_VERSION_REQUIRED_BY_WRAPPER from "0.2.0" to "0.3.0" to match the engine's current wire protocol (amplifier_agent_lib.protocol.methods.PROTOCOL_VERSION). The wrapper was shipping with a stale pin; the new check would have surfaced this at startup. Closes #9. * feat(wrapper-ts): add runChildProcess injection point (#3) Adds SpawnAgentParams.runChildProcess?: ChildProcessFactory — a public seam to substitute the subprocess factory used inside SessionHandle. When set, the wrapper invokes the factory in place of child_process.spawn, preserving the same options shape (detached, stdio, env, optional cwd). Useful for: - Sandboxing (e.g. wrapping the child in a container or namespace) - Test doubles (e.g. EventEmitter fakes that drive scripted outputs) - Harness wrapping (e.g. observing the subprocess from outside) ChildProcessFactory is exported as a @public type from index.ts. Closes #3. * feat(wrapper-ts)!: wire Transport NDJSON pipeline + dispatch to display.onEvent (#2, #4, #6) The engine emits one JSON object per line on the child subprocess's stderr stream for each wire-protocol notification (progress, result/delta, result/final, thinking/delta, thinking/final, tool/started, tool/completed, approval/request, approval/timeout, plus wire-level error). Before this change the wrapper buffered stderr as raw text and silently dropped every event — the existing Transport class implemented NDJSON parsing but was never wired anywhere (dead code). This change: - Adds parseNdjsonStream(stream, {onJson, onNonJson?}) — a standalone helper extracted from the parsing logic Transport already had. Resolves when the stream emits 'close'. Exported @public. - Wires parseNdjsonStream onto child.stderr inside SessionHandle.makeIterable(). JSON lines are parsed into 'notification' DisplayEvents and dispatched to params.display?.onEvent. Non-JSON lines (and JSON lines, for completeness) are still accumulated into stderrBuf so the stderrTail surface on parseRunOutput remains diagnostically useful. - Extends the DisplayEvent discriminated union with a new {type: 'notification', method: string, params: unknown} variant. **BREAKING**: existing exhaustive switch statements on event.type will no longer be exhaustive without a notification branch. - Threads SpawnAgentParams.display through to SessionHandle so the callback that was previously silently dropped is now actually fired (Issue #4). Closes #2, #4, #6. BREAKING CHANGE: display.onEvent callbacks are now actually invoked with wire-event notifications. Callers that registered onEvent expecting it to be a no-op may observe new event flow. The DisplayEvent union has a new 'notification' variant; exhaustive switch statements need a corresponding branch. * feat(wrapper-ts): surface --config flag via SpawnAgentParams.configPath (#1) Engine PR #27 / v0.4.0 added the --config <path> flag and the host_config layer (approval mode, MCP servers, provider defaults, allowProtocolSkew, etc.). The wrapper had no surface to forward this, so callers had to fall back to AMPLIFIER_AGENT_CONFIG in env.extra. This change: - Adds SpawnAgentParams.configPath?: string (public, @public TSDoc). - Adds AssembleArgvInput.configPath?: string. - assembleArgv emits --config <path> when configPath is set. - Threads configPath through SessionHandleParams to the per-submit argv assembly. Also drive-by adds approvalMode field to AssembleArgvInput (used by #10's commit). The argv-builder now reads input.approvalMode and emits -y / -n / nothing accordingly. Default remains -y for backward compat with callers that haven't opted into the approval API. Closes #1. * feat(wrapper-ts)!: wire approval API to engine -y/-n + approval.mode (#10) Previously, SpawnAgentParams.approval threw AaaError( approval_not_supported_in_v1) whenever set because it required the mid-turn onRequest callback that v1 doesn't support. This change extends SpawnAgentParams.approval to also accept the static-policy shape { mode: 'yes' | 'no' | 'prompt' }, which maps to engine argv: - 'yes' -> -y (auto-allow every tool call) - 'no' -> -n (auto-deny every tool call) - 'prompt' -> emit no flag; engine falls back to host_config.approval.mode or the bundle's TTY-based default. This is how a host hands policy resolution back to the engine. The legacy { onRequest, timeoutMs } form still throws approval_not_supported_in_v1 — the Mode A wire has no mid-turn channel. Mid-turn callbacks will return when WG-4 lands. Engine compatibility: { mode: 'prompt' } requires amplifier-agent >= 0.4.0 (PR #34 added host_config.approval.mode). Closes #10. BREAKING CHANGE: SpawnAgentParams.approval is now a union shape; callers passing { mode } no longer hit approval_not_supported_in_v1. Callers that defensively catch that error need to remove the try/catch when migrating to the mode shape. * feat(wrapper-ts): implement getEngineInfo() — engineVersion + bundleDigest (#7) Closes the Task-9 TODO: getEngineInfo() now returns the values captured during the engine version probe that spawnAgent() runs at init (Issue #9). Previously both fields were hardcoded empty strings. - engineVersion populated from `amplifier-agent version --json` payload's `version` field. - bundleDigest populated from the probe payload's optional `bundleDigest` field. The engine's current `version --json` output (from admin/version_info.py) only emits {version, protocolVersion} — bundleDigest will be empty string until a future engine release exposes it. Forward-compatible: when the engine adds it, the wrapper picks it up automatically with no further changes. DONE_WITH_CONCERNS for the bundleDigest follow-up: filed as an engine-side ask for a future PR. The wrapper does what it can with the data the engine surface exposes today; the contract is wired so the field will populate the moment the engine emits it. Closes #7. * chore(wrapper-ts): rebuild dist after hardening release changes Mirrors PR #29 / #31 pattern: dist/ is tracked so consumers installing from the git tarball get the compiled artifacts without a build step. Regenerated from npm run build after issues #1, #2, #3, #4, #5, #6, #7, #9, #10 landed. * chore(release): bump amplifier-agent-ts to 0.6.0 + CHANGELOG Wrapper hardening release closing 8 consumer-reported gaps at 0.5.0: #1 configPath surface #2 stderr NDJSON parsing #3 runChildProcess injection #4 display.onEvent dispatch #5 public re-exports #6 Transport dead code (root cause of #2/#4) #7 getEngineInfo() implementation #9 checkProtocolVersion() wired into init path #10 approval API mapped to engine -y/-n + approval.mode Issue #8 in the consumer report was a misread — InitializeParams. mcpConfigPath is intentionally retained in protocol-0.3.0. No type change needed; the schema is canonical and correct. This is a minor bump per 0.x convention even though some changes are BREAKING — the wrapper hasn't shipped a 1.0 yet, so breaking changes ride minor bumps. See CHANGELOG for the BREAKING list. Engine compatibility: requires amplifier-agent >= 0.4.0. Pinned protocol: 0.3.0. --------- Co-authored-by: Manoj Prabhakar Paidiparthy <mpaidiparthy@microsoft.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Catches both wrappers up to the engine surface PR #27 shipped. The engine dropped these three argv flags in #27 but the wrappers were never updated — they kept emitting them when consumer fields were set, causing callers that exercised those fields to fail at runtime with click
UsageError, exit 2.This PR is wrapper-only. Engine untouched.
The gap this fixes
After PR #27 merged on
main:--env-allowlist--env-extra--allow-protocol-skewWrapper consumers that set
envAllowlist/envExtra/allowProtocolSkewgot runtimeUsageErrorfailures. The wrapper API also still advertised these fields as valid — silently misleading. Surfaced when planning the post-#27 release version story.What's removed
TypeScript wrapper (BREAKING):
envAllowlist,envExtra,allowProtocolSkewfields fromAssembleArgvInput/SpawnAgentParams/SessionHandleParamsargv.push("--env-allowlist", ...)/--env-extra/--allow-protocol-skewblocks inargv-builder.tssession.ts/index.tsdist/regenerated (PR chore(cli)!: drop --mcp-config-path argv flag (subsumed by host config + env var) #29 pattern)Python wrapper (BREAKING):
env_allowlist,env_extra,allow_protocol_skewkwargs/fields fromspawn_agent/assemble_argv/SessionHandleParamsGuardrails added:
@ts-expect-errorcompile-time blocks asserting the fields are gone + runtimenot.toContainassertionspytest.raises(TypeError)kwarg-rejection tests + flag-not-emitted assertionsMigration
wrapper.spawnAgent({ envAllowlist: [...], envExtra: {...} })$AMPLIFIER_AGENT_CONFIGin subprocess env (or passes--config <path>per turn). Engine reads from host config — no per-call argv emission needed.wrapper.spawnAgent({ allowProtocolSkew: true })allowProtocolSkew: truein the host config JSON file ({ "allowProtocolSkew": true }). Engine reads it from the same place as the other config keys.Tests
initialize-with-mcpserversrunner test, unrelated)uv run pytest --ignore=wrappers)main)Engine suite verified unchanged — this PR only touches wrapper code.
Commits
Conventional Commits with
!for breaking changes;BREAKING CHANGE:footers document the migration paths.Cross-repo follow-up
amplifier-module-provider-nc's adapterspawnAgent()call may still passenvAllowlist/envExtra/allowProtocolSkew. Will break against post-this-PR wrappers. Same shape as Phase 1's hostCapabilities NC follow-up and PR #29's--mcp-config-pathNC follow-up.Migration for NC adapter: stop passing these three fields; if env injection is needed, compute it adapter-side and set
$AMPLIFIER_AGENT_CONFIG(or write a per-turn host config) before spawning the engine subprocess.Why strict (no wrapper tolerance)
Matches Phase 1 + PR #29 posture. The engine already rejects these flags loudly at runtime — keeping the wrapper fields would extend a lie about what works. Removing the fields surfaces the migration at compile time (TS) / signature-check time (Python) instead of silently at the first call site that exercises the dead path.
Supersedes / amends
docs/designs/2026-06-01-host-config-layer-revisit.mdD10 argv surface table — wrapper side of the table is now caught up.--env-allowlist/--env-extravia wrapper argv emission is fully gone end-to-end.