Skip to content

feat(packaging): root package.json + committed dist for native bun/npm git+install#11

Merged
manojp99 merged 2 commits into
mainfrom
feat/root-package-json-git-install
May 26, 2026
Merged

feat(packaging): root package.json + committed dist for native bun/npm git+install#11
manojp99 merged 2 commits into
mainfrom
feat/root-package-json-git-install

Conversation

@manojp99
Copy link
Copy Markdown
Collaborator

Summary

Adds a root package.json and commits wrappers/typescript/dist/ so consumers can install the TypeScript wrapper via native bun/npm git URL syntax — no proxy, no registry, no tokens.

"amplifier-agent-client-ts": "github:microsoft/amplifier-agent#main"

That's it. bun/npm clones the repo, finds package.json at the root, the files field restricts the install to wrappers/typescript/dist/, and the exports field resolves the entry point.

Why this pattern

The TypeScript wrapper lives at wrappers/typescript/ — a subdirectory of this repo. npm and bun don't natively support subdirectory paths in git URLs, so consumers can't directly install from github:microsoft/amplifier-agent without help. Prior approaches:

Approach Status
npm publish to PyPI/npm registry Deferred — requires name commitment + token setup for some flows; want to keep names swappable during POC
gitpkg.vercel.app subdir proxy Dead — service returns HTTP 402 DEPLOYMENT_DISABLED; we hit this directly
Separate repo microsoft/amplifier-agent-client-ts Requires new repo + code-sync overhead between repos
Dist branch (force-pushed flat branch) Requires CI workflow + initial branch creation
Root package.json + commit dist/ (this PR) Simplest; uses standard bun/npm semantics

A root package.json that references the built wrapper via relative paths works natively because bun/npm find the manifest at the repo root, and the files field limits what ends up in node_modules/.

What's in this PR

1. /package.json (NEW, root)

A minimal shipping-only manifest:

{
  "name": "amplifier-agent-client-ts",
  "version": "0.3.0",
  "type": "module",
  "exports": { ".": "./wrappers/typescript/dist/index.js" },
  "types": "./wrappers/typescript/dist/index.d.ts",
  "files": ["wrappers/typescript/dist"],
  "engines": { "node": ">=20" },
  "license": "MIT",
  "repository": { "type": "git", "url": "...", "directory": "wrappers/typescript" }
}

No dependencies, no devDependencies, no scripts. The actual dev manifest stays at wrappers/typescript/package.json (unchanged) — that's where build/test/lint commands live.

2. wrappers/typescript/dist/ (NEW, 20 files, ~108KB)

Built TypeScript output, freshly regenerated from current source (Mode A only — no stale Mode B display.{js,d.ts}, jsonrpc.*, l14.* leftovers).

3. .gitignore (MODIFIED)

Added !wrappers/typescript/dist/ to negate the repo-wide dist/ rule (which exists for Python uv build output).

4. wrappers/typescript/.gitignore (MODIFIED)

Removed local dist/ rule (now handled by root .gitignore's negation).

Trade-off: committing built artifacts

This breaks the convention "don't commit build output." For git+install patterns this is the well-understood compromise — without committed dist/, consumers would need a prepare script that builds on install, requiring TypeScript + bun on their side and adding ~5 sec per install. Committing dist/ instead trades ~108KB of repo size for instant, build-free consumer installs.

The existing ci.yml workflow already builds the wrapper on every push. A follow-up PR can add an auto-commit step that commits the freshly-built dist/ so it stays current without manual rebuild discipline. For now, the workflow verifies the wrapper builds correctly; engineers updating wrappers/typescript/src/ need to run bun run build and include the dist/ changes in their PR.

Verification

  • Local install: uv tool install "amplifier-agent @ git+https://github.com/microsoft/amplifier-agent@main" (Python side) confirmed working in the prior local probe. The TS side will be testable once this PR's branch is reachable via github:microsoft/amplifier-agent#feat/root-package-json-git-install.
  • files field semantics: bun add and npm install from git honor the files field — only wrappers/typescript/dist/ ends up in consumer's node_modules/amplifier-agent-client-ts/, not the entire 200MB+ amplifier-agent repo. Consumer import paths resolve via exports field to ./wrappers/typescript/dist/index.js.

Test plan

  • CI passes (ci.yml: pytest, ruff, pyright, bun test) — the new root package.json shouldn't affect any of these
  • Verify in a fresh consumer project: bun add github:microsoft/amplifier-agent#feat/root-package-json-git-install (or after merge: #main)
  • Verify import { spawnAgent } from 'amplifier-agent-client-ts' resolves to the simplified Mode A DisplayEvent shape
  • Verify node_modules/amplifier-agent-client-ts/ contains only wrappers/typescript/dist/ + package.json (no Python sources, no docs)

Follow-up work

  • Add a CI step that auto-rebuilds + commits wrappers/typescript/dist/ on changes to wrappers/typescript/src/. Eliminates the "remember to rebuild" requirement.
  • Decide eventual registry destination (PyPI for engine, npm for wrapper) once package names stabilize. The root package.json pattern is forward-compatible — npm publish against this same root would work.

Manoj Prabhakar Paidiparthy and others added 2 commits May 25, 2026 21:32
…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>
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>
@manojp99 manojp99 merged commit 64a1d30 into main May 26, 2026
1 of 3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant