ci: add GitHub Actions workflows for CI + release-notes (POC stage)#10
Merged
Conversation
Two workflows: 1. .github/workflows/ci.yml — runs on push to main + every PR. - Python: uv sync, ruff check, pyright, pytest. ~3-5 min. - TypeScript wrapper: bun install, tsc build, vitest run. ~1-2 min. - Concurrency group cancels in-flight runs for the same ref on new pushes. 2. .github/workflows/release-notes.yml — runs on tag push (v* or wrapper-v*). - Auto-generates GitHub Release with changelog notes derived from PRs/commits. - Tag with '-' suffix is auto-flagged as prerelease (v0.3.0-rc1, etc.). - Gives consumers a stable pin target for git+install workflows. Publish-to-registry workflows (PyPI, npm) deliberately NOT added yet — POC stage prefers git+install paths from public GitHub so package names stay swappable without consumer-facing migration. Will add publish workflows once names stabilize. Co-Authored-By: Amplifier <amplifier@microsoft.com>
manojp99
added a commit
that referenced
this pull request
May 26, 2026
…m git+install (#11) * feat(packaging): add root package.json + commit wrapper dist for git+install Enables bun/npm consumers to install amplifier-agent-client-ts via native git URL syntax: bun add github:microsoft/amplifier-agent#main Pattern: a minimal shipping-only package.json at the repo root points (via 'main', 'types', 'exports') at wrappers/typescript/dist/. The wrappers/typescript/package.json remains the dev manifest with scripts, devDependencies, and tsconfig — unchanged. Trade-off: wrappers/typescript/dist/ is now committed to the repo (~108KB, 20 files). The CI workflow added in #10 already builds the wrapper on every push; a follow-up can add an auto-commit step so dist stays current without manual rebuild discipline. For now, the 'wrapper-v*' tag workflow gives consumers stable pinnable refs. Why this pattern (vs alternatives): - npm publish: requires registry account, name commitment, token for consumers in some flows. Deferred until POC graduates. - gitpkg.vercel.app subdir proxy: third-party service, currently disabled (HTTP 402 DEPLOYMENT_DISABLED). - Dist branch (separate refs): requires force-push CI; this is simpler. - Separate repo for wrapper: needs new repo + code-sync overhead. Consumer install path (in any project's package.json): "amplifier-agent-client-ts": "github:microsoft/amplifier-agent#main" bun/npm clones the repo, finds package.json at root, the 'files' field restricts to wrappers/typescript/dist/, the 'exports' field resolves the entry point. No tokens, no proxies, no registries. Co-Authored-By: Amplifier <amplifier@microsoft.com> * fix(packaging): use conditional exports with explicit types resolution Updates /package.json exports from string form: "exports": { ".": "./wrappers/typescript/dist/index.js" } to conditional form with explicit types resolution: "exports": { ".": { "types": "./wrappers/typescript/dist/index.d.ts", "import": "./wrappers/typescript/dist/index.js" } } Modern TypeScript (with moduleResolution: bundler/nodenext) follows the exports field and looks for a 'types' condition before falling back to the top-level 'types' field. The string-form exports left only 'import' resolvable, so consumer projects (e.g. NanoClaw's agent-runner) saw 'McpServerConfig' as 'any' or unresolved, surfacing as TS2339 errors like 'Property transport does not exist on type McpServerConfig'. Verified locally: NC's bun run typecheck went from 5 errors to 0 after this change. Order matters in conditional exports: 'types' MUST appear FIRST so TS checks it before module conditions. This follows the TypeScript handbook guidance for the exports field. Co-Authored-By: Amplifier <amplifier@microsoft.com> --------- Co-authored-by: Manoj Prabhakar Paidiparthy <mpaidiparthy@microsoft.com> Co-authored-by: Amplifier <amplifier@microsoft.com>
manojp99
pushed a commit
that referenced
this pull request
Jun 3, 2026
…th (#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.
manojp99
pushed a commit
that referenced
this pull request
Jun 3, 2026
…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.
manojp99
pushed a commit
that referenced
this pull request
Jun 3, 2026
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.
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.
Summary
Adds two GitHub Actions workflows for the POC stage of packaging. Scope is deliberately minimal — CI and release-notes only, no publish-to-registry workflows yet.
What's in this PR
.github/workflows/ci.ymlRuns on every push to
mainand every PR. Two parallel jobs:uv sync→ruff check src/ tests/→pyright src/→pytest tests/ -q. ~3–5 min.wrappers/typescript/, runsbun install→bun run build(tsc) →bun run test(vitest). ~1–2 min.Concurrency group cancels in-flight runs for the same ref when a new commit arrives. 15-min timeout on the Python job, 10-min on the wrapper job.
.github/workflows/release-notes.ymlTriggered on tag push matching
v*(engine releases) orwrapper-v*(TS wrapper releases). Usessoftprops/action-gh-releasewithgenerate_release_notes: trueto auto-create a GitHub Release with changelog notes derived from PRs/commits since the previous tag.Tags with a
-suffix (e.g.v0.3.0-rc1) are auto-flagged as prerelease. This gives consumers of the POC-stage git+install pattern a stable, pinnable reference point.What's deliberately NOT in this PR
Publish-to-registry workflows (PyPI for amplifier-agent, npm for amplifier-agent-client-ts) are not included.
Rationale: in the POC stage, we want package names to stay swappable without consumer-facing migration. The git+install path (
uv tool install "amplifier-agent @ git+https://github.com/microsoft/amplifier-agent@<ref>"for Python; gitpkg.vercel.app proxy or future npm publish for TS) gives full naming freedom and zero token friction for consumers.We'll add publish workflows in a follow-up PR once names stabilize.
Tag conventions established here
v0.3.0,v0.3.0-rc1, etc.wrapper-v0.3.0, etc.Separate tag namespaces let engine and wrapper version independently, which matches the design where the engine is at v0.2.0 (additive-only changes) while the wrapper is at v0.3.0 (CR-C breaking DisplayEvent shape change).
Verification
yq— both valid.pyproject.toml(uv run pytest,uv run ruff,uv run pyright) andwrappers/typescript/package.json(bun run build,bun run test).Test Plan
python-testsandts-wrapper-testsjobs complete successfully