Skip to content

release: sdk/typescript v0.2.0 — 1:1 with CLI + native codedb#87

Open
justrach wants to merge 15 commits into
mainfrom
release/sdk-typescript-0.1.8
Open

release: sdk/typescript v0.2.0 — 1:1 with CLI + native codedb#87
justrach wants to merge 15 commits into
mainfrom
release/sdk-typescript-0.1.8

Conversation

@justrach
Copy link
Copy Markdown
Owner

Summary

  • Brings the npm @codegraff/sdk to feature parity with the Rust CLI's MCP support
  • Auto-equips installs with codedb so consumers get the same toolset CLI users have
  • Three layers wired together:
    • Rust: GraffApi::read_mcp_config + GraffApi::write_mcp_config napi methods exposing forge_api's existing MCP config surface
    • JS facade: Graff#readMcpConfig / Graff#writeMcpConfig convenience methods + an autoRegisterCodedb hook on Graff.init()
    • Postinstall: scripts/postinstall.cjs downloads codedb from github.com/justrach/codedb/releases/latest, sha256-verifies, drops in bin/codedb
  • Opt-out via CODEGRAFF_SKIP_POSTINSTALL=1 / CODEGRAFF_SKIP_AUTO_MCP=1

Verified end-to-end in Vercel sandbox

`npm install @codegraff/sdk@0.2.0` → postinstall fetched linux-x86_64 codedb (11.8 MB) → sha256 verified → `Graff.init()` auto-wrote MCP entry → agent then invoked `codedb.search` / `codedb.word` / `codedb.outline` natively, no manual configuration.

Test plan

  • Verified rust + napi binding compiles + new methods present on `.node`
  • Verified postinstall downloads correct platform binary + checksum matches
  • Verified `Graff.init()` auto-registers codedb (locally + in Vercel sandbox)
  • Verified agent has codedb tools available after install
  • Pending: codedb releases for linux-arm64 + windows-msvc (those triples fall back to standard tools today)

🤖 Generated with Claude Code

justrach and others added 14 commits May 10, 2026 00:52
Introduces sdk/typescript as a workspace member: Rust crate with
napi-rs bindings (lib.rs, wire.rs), TypeScript wrappers (lib.js,
lib.d.ts), example consumers (agent-demo, compare, benchmark, smoke),
and the per-triple npm subpackages so a future publish workflow can
ship the addon to npm without re-deriving the matrix.

The new sdk-typescript GitHub Actions workflow builds .node binaries
for darwin-{arm64,x64} + linux-{arm64,x64}-gnu + win32-x64-msvc on
every push touching sdk/typescript/, crates/, or Cargo.{toml,lock}.
Publishing is intentionally NOT wired up yet — that's a separate
release workflow gated on a tag.

Also: gitignore .worktrees/ and codedb.snapshot so the daemon's
session state and local worktree metadata stop showing up as
pending changes.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds the BYOK entrypoint third-party SDK consumers need:

  await graff.upsertCredential("openai", "sk-...");
  await graff.chat({ prompt: "...", model: "gpt-5.5" });

Routes through the same init_provider_auth + complete_provider_auth
flow `graff provider login` uses, so the credential persists in the
configured auth store and subsequent chats authenticate without
further setup. Optional extra_params support providers that need
URL parameters alongside the key (Vertex AI project + location, etc).

Also ships removeCredential() — mirrors `graff provider logout`.

Fixes a packaging miss: the previous commit's hand-written JS
wrappers (lib.js, lib.d.ts) were caught by the top-level *.js /
*.d.ts gitignore rules and never made it into git. Adds explicit
negating rules so they're tracked, while keeping the napi
auto-generated index.js / index.d.ts ignored.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…xTokens })

Folds the three sharp edges from the previous BYOK commit into a single
init call. Today's working setup goes from this:

  process.env.FORGE_SESSION__PROVIDER_ID = "openai";
  process.env.FORGE_SESSION__MODEL_ID = "gpt-4o-mini";
  process.env.FORGE_MAX_TOKENS = "8000";
  const g = await Graff.init(cwd);
  await g.upsertCredential("openai", key);

To this:

  const g = await Graff.init({
    cwd, provider: "openai", apiKey: key,
    model: "gpt-4o-mini", maxTokens: 8000,
  });

Implementation is JS-only — the new options translate to FORGE_* env
vars before the Rust init reads ForgeConfig, then upsertCredential is
called automatically when apiKey + provider are both supplied. No Rust
patch needed. The legacy `Graff.init(cwd)` string signature still works
(overload), so existing call sites are untouched.

When neither provider nor apiKey is supplied, the SDK falls back to
`~/.forge/forge.toml` exactly as before — graff CLI users see no
behavior change.

Verified end-to-end against api.openai.com with a real key:
- Graff.init({...BYOK...}) → 3ms
- chat({prompt: "PONG"}) → 1237ms, answer "PONG"

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Backport the pixo Linux coverage build fix and generated snapshot updates to release/0.1.53 without pulling main-only cleanup changes into the release branch.\n\nCo-Authored-By: blackfloofie-a codegraff agent <265516171+blackfloofie@users.noreply.github.com>
The orchestrator's End hook can re-arm the run loop by injecting a
follow-up message (orch.rs ~548-553), and PendingTodosHandler does
exactly that whenever there are still pending/in_progress todos. The
existing fingerprint dedupe is content-keyed, so any todo reword
changes the fingerprint and lets the reminder fire again. With a
vague meta-todo the agent can never check off, this loops until
max_requests_per_turn (default 100) cuts it off.

Four bounded fixes:

1. PendingTodosHandler tracks total reminders in context, not just
   the last fingerprint. After max_reminders injections the handler
   stops re-arming regardless of how the agent rewords its todos.

2. Orchestrator counts End-hook re-arms per run and force-yields
   with a new InterruptionReason::EndHookRearmLimitReached when the
   configured cap is exceeded. Defense-in-depth against any End
   hook (current or future), not just pending-todos.

3. DoomLoopDetector now strips volatile keys (offset, limit,
   line_start/end, max_results, context_lines, ...) from a known
   set of exploration tools (read, grep, fs_search, codedb_*) before
   computing tool-call signatures. Catches "re-read same file with
   shifting offsets" and "re-grep with different max_results" loops
   that previously slipped through because each call had a unique
   argument tuple.

4. Both caps are wired to a single forge_config knob,
   max_end_hook_rearms (default 3), so one number bounds the loop
   from both ends.

Tests:
- 5 new unit tests in hooks::pending_todos / hooks::doom_loop
- All 714 forge_app tests pass
- cargo test --workspace green

Generated with [Devin](https://cli.devin.ai/docs)

Co-Authored-By: blackfloofie-a codegraff agent <265516171+blackfloofie@users.noreply.github.com>
Triggered by sdk/typescript-vX.Y.Z tags. Builds native addons for all
four supported triples, assembles per-triple subpackages, then publishes
to npm with provenance via the GitHub OIDC token. Verifies the tag's
version matches package.json before building so a misnamed tag fails
fast instead of after the matrix completes.

Auth path is dual: Trusted Publisher (OIDC, no secret) is preferred,
NPM_TOKEN is the fallback if it is set as a repo secret. NPM_CONFIG_PROVENANCE
is enabled either way so the published artifacts carry a signed attestation
of which workflow + commit produced them.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Bump main package + 5 per-triple subpackages to 0.1.8 in lockstep.

0.1.7 shipped broken Linux binaries because zigbuild cross-compile
from macOS dropped aws-lc-sys versioned symbols. 0.1.8 ships the
same source rebuilt on ubuntu-latest in CI, where the native linker
resolves aws-lc symbols correctly.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Switch x86_64-apple-darwin CI matrix from macos-13 (Intel) to macos-latest
(Apple Silicon). macos-13 runners are over-subscribed on GitHub Actions
and routinely sit in queued for 40+ min; the 0.1.8 release stalled on
this twice. Apple Silicon cross-compiles to x86_64-apple-darwin via the
macOS SDK natively, no zig needed, no broken aws-lc symbols.

Bumps main + 5 per-triple subpackages 0.1.7 -> 0.1.9 in lockstep. 0.1.8
on npm will remain absent (CI never reached publish step before cancel).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Add 'repository' field to each per-triple subpackage's package.json
so npm provenance verification (sigstore) can match the publish to
the GitHub workflow's claimed source. 0.1.9 publish failed with E422
'package.json: "repository.url" is "", expected to match
https://github.com/justrach/codegraff from provenance'.

Bumps main + 5 subpackages 0.1.9 -> 0.1.10 in lockstep.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Run the x86_64-unknown-linux-gnu build inside a debian-bullseye container
(GLIBC 2.31) instead of on bare ubuntu-latest (GLIBC 2.39). The previous
.node required GLIBC 2.38 and failed to load on Vercel sandbox (2.34),
RHEL 9, Amazon Linux 2023, Debian 11, and Ubuntu 20/22.

Adds a separate build-linux job (GHA matrices cannot conditionally apply
container:) and makes publish depend on both build + build-linux.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Swap linux container from napi-rs/nodejs-rust:lts-debian to plain
node:20-bullseye. The napi-rs image presets a cross-compile toolchain
(CC=x86_64-unknown-linux-gnu-gcc with sysroot), which made aws-lc-sys
fail with '-fuse-ld=lld: unrecognized'. We want native compilation in
Debian Bullseye, not cross from a hosted sysroot. Install rustup +
protoc + build-essential inside the container explicitly.

Adds an objdump verification step that prints the .node's GLIBC
requirements so a regression to a newer GLIBC ABI is visible at build
time.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Linux container: install protoc from the official release tarball
instead of apt's protobuf-compiler 3.12. The apt package didn't ship
the google/protobuf/*.proto well-known files where prost-build looks
for them, so forge_repo's build script failed with
'google/protobuf/timestamp.proto: File not found'.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Brings the npm SDK to feature parity with the Rust CLI's MCP support
AND auto-equips it with codedb so 'npm install @codegraff/sdk' gives
consumers the same toolset CLI users get out of the box.

Three changes:

1. Expose forge_api's MCP config surface via napi:
   GraffApi::read_mcp_config(scope) -> JSON
   GraffApi::write_mcp_config(scope, json) -> ()
   Same code path as 'forge mcp add' / 'forge mcp set' — SDK and CLI
   share one config file, true 1:1 parity.

2. Add lib.js convenience methods on Graff:
   graff.readMcpConfig(scope?)
   graff.writeMcpConfig(scope, config)

3. Auto-install + auto-register codedb on Graff.init():
   - postinstall script downloads codedb-<platform> from the codedb
     GitHub release into bin/codedb at npm install time
   - Graff.init() detects the bundled binary and writes a User-scope
     MCP entry pointing at it (idempotent — only writes if missing or
     stale)
   - Forge then loads it on next chat call, so the agent has
     codedb's symbol-aware tools natively, no manual config required.

Opt-out: CODEGRAFF_SKIP_POSTINSTALL=1 disables download,
CODEGRAFF_SKIP_AUTO_MCP=1 disables registration.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
justrach

This comment was marked as outdated.

justrach

This comment was marked as outdated.

justrach

This comment was marked as outdated.

justrach

This comment was marked as outdated.

justrach

This comment was marked as outdated.

blackfloofie

This comment was marked as outdated.

blackfloofie

This comment was marked as outdated.

Copy link
Copy Markdown
Contributor

@blackfloofie blackfloofie left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 Swarm Code Review

Reviewed 5 files in parallel sandboxes, each running an independent Codegraff agent (@codegraff/sdk@0.2.0).

Findings: 1 (🛑 P0 0 · 🔴 P1 1 · 🟡 P2 0 · 💭 P3 0)

⚠️ 1 file(s) failed to complete: .github/workflows/sdk-typescript.yml

✅ Clean: .gitignore, Cargo.toml, crates/forge_app/src/app.rs

  • .gitignore — The .gitignore changes are syntactically correct and safe — no bugs, no broken invariants.

Model: deepseek-v4-pro · Tooling: Codegraff agent

# compiles to x86_64-apple-darwin via the macOS SDK natively.
os: macos-latest
# NOTE: x86_64-unknown-linux-gnu intentionally NOT in this matrix.
# bare ubuntu-latest produces a .node that requires GLIBC 2.38
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔴 P1 — No aarch64-unknown-linux-gnu build anywhere

The pre-flight comment block (lines 12-17) lists @codegraff/sdk-linux-arm64-gnu as a subpackage requiring Trusted Publisher configuration. However, the build matrix (line 92-107) only covers aarch64-apple-darwin, x86_64-apple-darwin, and x86_64-pc-windows-msvc, and the build-linux job (line 162) only builds x86_64-unknown-linux-gnu. There is no job or matrix entry for aarch64-unknown-linux-gnu. Running this workflow as-is will publish a release that either omits the linux-arm64 subpackage entirely (stranding arm64 Linux users) or publishes it without a native .node binary, depending on napi prepublish behavior. Add the target: either add aarch64-unknown-linux-gnu as a matrix entry (if it can cross-compile from ubuntu-latest) or add a separate build-linux-arm64 job equivalent to build-linux.

CI matrix doesn't currently build aarch64-unknown-linux-gnu, so the
subpackage @codegraff/sdk-linux-arm64-gnu has never been published to
npm. Listing it in optionalDependencies misleads tooling and confuses
arm64-linux users who get a silent skip + a 'cannot find module' at
runtime.

Drops the claim until the build matrix actually produces it. See follow-
up for properly adding aarch64-unknown-linux-gnu to the CI matrix.

Address P1 finding from PR #87 swarm review (4330389512).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@github-actions
Copy link
Copy Markdown

Action required: PR inactive for 5 days.
Status update or closure in 10 days.

@github-actions github-actions Bot added the state: inactive No current action needed/possible; issue fixed, out of scope, or superseded. label May 25, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

state: inactive No current action needed/possible; issue fixed, out of scope, or superseded.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants