Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
168 commits
Select commit Hold shift + click to select a range
e77b532
fix(dashboard): extract concise-arrow and regex-heavy check blocks (#46)
samik-bind Jul 27, 2026
dea31ee
fix: re-apply conversation history fallback for imported traces (issu…
samikuikka Jul 27, 2026
a2e0453
feat(auth): require secret-bearing telemetry credentials (SPEC-149, i…
samikuikka Jul 27, 2026
cfab419
feat(otlp): bound public OTLP request work (SPEC-150, issue #50)
samikuikka Jul 28, 2026
d5b88d4
fix(executor): surface result_invalid failures instead of swallowing …
samikuikka Jul 28, 2026
353f052
feat(admission): shared telemetry admission control (SPEC-151, issue …
samikuikka Jul 28, 2026
923944c
fix(dashboard): render cost as USD, not raw micro-USD (#53)
samik-bind Jul 28, 2026
a217d6b
fix(cli): stop importing partial Langfuse traces silently (#55)
samik-bind Jul 28, 2026
24721a4
fix(auth): let attempt tokens read their own trace projection
samikuikka Jul 28, 2026
232f41e
feat(secrets): safe installation secret lifecycle (SPEC-152, issue #54)
samikuikka Jul 28, 2026
fbd712c
fix: unblock main CI (type error + langfuse flow_name clobber + stale…
samikuikka Jul 28, 2026
259acac
fix(test): set AUTH_SECRET for attempt-JWT round-trip test
samikuikka Jul 28, 2026
2a1b955
fix(api): count sessions whose runs have no session_id (#56)
samik-bind Jul 28, 2026
d435477
feat(pricing): surface unpriced models instead of silently costing 0 …
samikuikka Jul 28, 2026
4f487fb
feat(normalizer): map Langfuse SDK spans (langfuse.* attributes) (#61)
samik-bind Jul 28, 2026
88ec11a
fix(checks): keep check identity when the payload is shrunk to fit (#62)
samik-bind Jul 28, 2026
4d23910
fix(pricing): price gemini-2.5-flash-lite + strip router prefix (#57)
samikuikka Jul 28, 2026
e11ed31
feat(security): secure public application surface — core (SPEC-153, i…
samikuikka Jul 29, 2026
2ab570c
fix(security): wire public health route + setup status + singleton ba…
samikuikka Jul 29, 2026
a6af71e
feat(deploy): zero-cost Cloudflare Tunnel trial deployment (SPEC-154,…
samikuikka Jul 29, 2026
245bc14
feat(security): remove anonymous trace sharing (SPEC-155, issue #68)
samikuikka Jul 29, 2026
09a095b
feat(content): always store full trace content, remove content policy…
samikuikka Jul 29, 2026
104f8b7
feat(test): tunnel trial end-to-end validation harness (SPEC-157, iss…
samikuikka Jul 29, 2026
c8bb495
fix(test): working tunnel trial smoke + Caddy diagnostic deny fix (SP…
samikuikka Jul 29, 2026
8f91c7c
fix(security): complete tunnel trial validation PASS (SPEC-157, issue…
samikuikka Jul 29, 2026
9050d02
feat(runs): server-side pagination for batch runs page
samikuikka Jul 29, 2026
0746bc8
fix: mount dashboard auth in direct server profile
samikuikka Jul 30, 2026
cf608a2
fix: normalize snake_case API-key responses at dashboard boundary (#72)
samikuikka Jul 30, 2026
a9860f5
feat: project selector in Create API key dialog (#73)
samikuikka Jul 30, 2026
2a1a812
fix(backend): basedpyright error in runs level-summary loop
samikuikka Jul 30, 2026
e909290
test(backend): fix stale tests after pagination/security/bootstrap re…
samikuikka Jul 30, 2026
7a30044
fix(cli): caller execution set a trace env var nothing reads (#74)
samik-bind Jul 30, 2026
12495e3
fix(cli): caller execution trusted the server's guess at its own URL …
samik-bind Jul 30, 2026
ec5e2cf
fix(pricing): price current models claude-opus-5/-4-6 and gemini-3.x …
samikuikka Jul 30, 2026
66be6ab
feat(catalog): client-published task catalog vertical slice (SPEC-159)
samikuikka Jul 30, 2026
d15ae42
fix: add task_source back to ProjectDetail for dashboard compat (SPEC…
samikuikka Jul 30, 2026
fdc42f7
fix: --no-record forces local execution for published catalogs (SPEC-…
samikuikka Jul 30, 2026
1bf2fe8
docs: record source-owned task execution architecture
samikuikka Jul 30, 2026
ed49581
feat(catalog): remove old task-source/GitHub sync, complete SPEC-159 …
samikuikka Jul 31, 2026
b982355
feat(executor): Phase 1 — DB migration v16 for source-owned executor …
samikuikka Jul 31, 2026
ba01f09
feat(executor): Phase 2 — source-owned executor services (SPEC-161)
samikuikka Jul 31, 2026
c10da9e
feat(executor): Phase 3 — protocol v2 routes (SPEC-161)
samikuikka Jul 31, 2026
3502cc3
feat(executor): Phase 4-6 — apo connect CLI + bootstrap route (SPEC-161)
samikuikka Jul 31, 2026
1cabaab
fix(executor): add v2 to PUBLIC_PATHS + accept protocol v2 enrollment…
samikuikka Jul 31, 2026
9e8bfe9
feat: dashboard runs through Connected Executors (SPEC-162)
samikuikka Jul 31, 2026
94964d3
feat(scheduler): source-owned Occurrence delivery foundation (SPEC-163)
samikuikka Jul 31, 2026
23fdf8d
feat(scheduler): source-owned schedule routes, hooks, and pause (SPEC…
samikuikka Jul 31, 2026
ab36388
feat(schedules): source-owned schedule dashboard (SPEC-163)
samikuikka Jul 31, 2026
bdec685
fix(tests): make the full backend suite green (1575 passed, 0 failed)
samikuikka Jul 31, 2026
4a86374
docs: specify production connected executor runtime
samikuikka Jul 31, 2026
209a35a
feat(executor): production connected-executor runtime (SPEC-161)
samikuikka Jul 31, 2026
7a829c1
fix(executor): SPEC-164 conformance + shared claim service
samikuikka Jul 31, 2026
66dae02
test(executor): real apo connect command-through-protocol scene (SPEC…
samikuikka Jul 31, 2026
8c5a332
fix(catalog): TS digest matched Python only by accident (cross-langua…
samikuikka Jul 31, 2026
0f31009
docs: specify bundled execution retirement boundary
samikuikka Jul 31, 2026
1a46ea8
feat: retire bundled execution — retirement + narrowed API (SPEC-165)
samikuikka Aug 1, 2026
16bbf58
docs: document apo connect, task publish, and source-owned workflow
samikuikka Aug 1, 2026
43bb974
feat: remove persistent v1 executor + CLI batch/project-config (SPEC-…
samikuikka Aug 1, 2026
b115a9c
feat: remove SDK execution property + fix CLI types (SPEC-165)
samikuikka Aug 1, 2026
def96bc
fix: protocol-v2 compatibility + nullable revision migration (#83/#84)
samikuikka Aug 1, 2026
f47bade
fix: trace endpoint doubled — apo connect drops all SDK spans (#87)
samikuikka Aug 1, 2026
aeae209
fix: task-run default, double finalization, child loader (#85/#86/#88)
samikuikka Aug 1, 2026
0bf8a9a
fix: task run routing gate — bare command now reaches caller (#89)
samikuikka Aug 1, 2026
8ca91d9
fix: caller-execution parameter property crash + reachability check (…
samikuikka Aug 1, 2026
7fb1663
fix: caller path renders result + remove retired dispatch (#90/#91)
samikuikka Aug 1, 2026
8b1c82e
fix: caller result parity + call_count/primary_model accuracy (#92/#93)
samikuikka Aug 1, 2026
f5780c5
docs: remove stale repository sync and trace policy guidance
samikuikka Aug 1, 2026
0782003
chore: strip internal SPEC-XXX references from public codebase
samikuikka Aug 1, 2026
beab1c3
chore: remove remaining internal SPEC-XXX references from code and docs
samikuikka Aug 1, 2026
dce2d74
chore: untrack internal spec/plan docs, fix last SPEC ref
samikuikka Aug 1, 2026
6906e42
feat: remove retired executor service from Compose + source-owned top…
samikuikka Aug 1, 2026
e1c9782
chore: untrack internal spec/plan docs via jj (prior git rm --cached …
samikuikka Aug 1, 2026
6455617
test: align schema-version assertion with SPEC-167 v20 bump
samikuikka Aug 1, 2026
bd6c40d
fix: remove retired task cache from readiness
samikuikka Aug 1, 2026
5e36267
fix(dashboard): stop showing 'check source unavailable' warning for p…
samikuikka Aug 2, 2026
e0db2e0
fix(backend): purge_legacy_bundle_objects cannot call asyncio.run fro…
samikuikka Aug 2, 2026
ae56f53
docs: define versioned task source boundary
samikuikka Aug 2, 2026
8b20503
feat: Task Definition Revision foundation — CLI lib + DB + service + …
samikuikka Aug 2, 2026
3b3a2c7
feat: catalog v2 publish + caller definition pinning + Run detail sum…
samikuikka Aug 2, 2026
762a634
feat: dashboard CodeMirror from Run-bound Task Definition source (SPE…
samikuikka Aug 2, 2026
6d04cfe
feat: wire caller-execution task_definition + source-owned inventory …
samikuikka Aug 2, 2026
a6d6421
fix: wire task_definition through the caller route (SPEC-169)
samikuikka Aug 2, 2026
395ccf9
fix: register task definition schema migration
samikuikka Aug 2, 2026
d8c0a16
chore: remove dead has_user_simulator metadata
samikuikka Aug 2, 2026
9d6d520
fix: require eval source for recorded task runs
samikuikka Aug 2, 2026
c4f5f0b
fix: surface tool calls as a generation's output for tool-call rounds
samikuikka Aug 2, 2026
82af854
feat(dashboard): remove the Executors settings page
samikuikka Aug 2, 2026
5bc0f5a
fix: keep tool-call/result messages in a generation's input
samikuikka Aug 2, 2026
2467b4e
fix(trace): show each generation's own tool calls, not accumulated input
samikuikka Aug 2, 2026
e9e585f
fix(cost): price deepseek/glm/kimi + surface unpriced calls so totals…
samikuikka Aug 2, 2026
045a632
feat(trace): delta-render generation inputs; keep full prompt
samikuikka Aug 2, 2026
c19d672
test(backend): set AUTH_SECRET in executor-protocol-v2 finalization f…
samikuikka Aug 3, 2026
f222ee3
fix: name caller runs by their task, not "caller-task" (#95)
samik-bind Aug 3, 2026
976fbd1
fix: project deletion cascade order + task_definition_revisions (#96)
samikuikka Aug 3, 2026
53c236c
Compare view: resolve check source from the pinned Task Definition (#…
samik-bind Aug 3, 2026
aa94e03
fix: compare view uses Run-bound Task Definition source (#98)
samikuikka Aug 3, 2026
a6fa478
fix(deliverables): resolve legacy:<name> ids so bodies are fetchable …
samikuikka Aug 3, 2026
be5fbe7
fix(langfuse): derive span id from observation id alone so re-imports…
samikuikka Aug 3, 2026
9305b38
chore: delete dead bundled-executor client subsystem (#99)
samikuikka Aug 3, 2026
454a96f
feat(trace): combined-chat view for generation I/O
samikuikka Aug 3, 2026
edf79a5
fix(trace): stop tool-call argument boxes overflowing horizontally
samikuikka Aug 3, 2026
b5b353e
fix(trace): render tool-call arguments readably
samikuikka Aug 3, 2026
5bdd1a7
feat(example-service): default to deepseek-v4-flash-0731
samikuikka Aug 3, 2026
fdd632d
feat(example-service): align adapter model defaults with deepseek-v4-…
samikuikka Aug 3, 2026
d944928
feat(sdk): publish @apo/sdk to npm via OIDC trusted publishing
samikuikka Aug 3, 2026
7f75032
rename: @apo/sdk -> @apo-ai/sdk (npm apo scope is taken)
samikuikka Aug 3, 2026
eb34a5c
ui(trace): clean chat messages — no avatars, text-only role headers
samikuikka Aug 3, 2026
cafa968
chore(sdk): bump @apo-ai/sdk to 0.2.1
samikuikka Aug 3, 2026
201fe69
fix(sdk): resolve publish tarball from disk, not pnpm stdout
samikuikka Aug 3, 2026
50a99e2
ui(trace): normalize font sizes — two-scale system (text-xs + text-sm)
samikuikka Aug 3, 2026
14e15f3
fix(sdk): finish @apo/sdk -> @apo-ai/sdk rename in workflows + docs
samikuikka Aug 3, 2026
83680b7
ui(trace): compact tree nodes — icon-only, 37px rows, collapse-all
samikuikka Aug 3, 2026
7c2b424
feat(cli): publish @apo-ai/cli to npm via OIDC + fix loadTask error
samikuikka Aug 4, 2026
f4f9819
fix(trace): add visible collapse-tree button in nav header
samikuikka Aug 4, 2026
fbe8281
chore(cli): bump @apo-ai/cli to 0.1.1
samikuikka Aug 4, 2026
70eaa37
fix(cli): use test:unit in publish workflow + bump to 0.1.2
samikuikka Aug 4, 2026
4cbb77e
fix(cli): read version from package.json at runtime
samikuikka Aug 4, 2026
006abf4
fix(auth): invitation page scrollable on small screens
samikuikka Aug 4, 2026
f05d8f6
fix(trace): render Anthropic-style content blocks as chat (issue #107)
samikuikka Aug 4, 2026
0da6c88
fix(pricing): add gpt-5.6 terra/luna rates (issue #101, PR #101)
samikuikka Aug 4, 2026
5eb8362
fix(dashboard): stop sending fields the narrowed create API forbids (…
samik-bind Aug 4, 2026
8c4fe8d
fix(cli): move SDK import before /start so startup failures are pre-s…
samikuikka Aug 4, 2026
c1d861d
feat(dashboard): show token counts in runs table + compare page
samikuikka Aug 4, 2026
5f5d015
fix(cli): make connected execution work from the published package (#…
samik-bind Aug 4, 2026
f15c535
chore(cli): release 0.1.3
samikuikka Aug 4, 2026
d6ab450
docs(start): restructure for shared-server teams + fix stale CLI info
samikuikka Aug 4, 2026
67ebf96
fix(executor): preserve reported run configuration (#116)
samik-bind Aug 4, 2026
61301e0
ci: run dashboard vitest suite in CI (#115)
samikuikka Aug 4, 2026
65191ed
fix: simplify Tasks page selection action bar
samikuikka Aug 4, 2026
47de9db
fix: compact connected environment status indicator
samikuikka Aug 4, 2026
14d1f0e
fix: remove connected environment status from Tasks page
samikuikka Aug 4, 2026
a762fc1
feat: publish public docs at docs.test-apo.online (SPEC-171)
samikuikka Aug 4, 2026
a346c7d
fix: make cloudflared tunnel token optional for locally-managed mode
samikuikka Aug 4, 2026
a830295
fix: docs container starts under full hardening (cap_drop + read_only)
samikuikka Aug 4, 2026
6d60a17
fix: override no longer forces cloudflared into credentials-file mode
samikuikka Aug 4, 2026
ef60d03
fix: docs header bar spans full viewport width
samikuikka Aug 4, 2026
e57d087
fix: result submit persists deliverable rows instead of hot-row blob …
samikuikka Aug 4, 2026
a9b8211
feat: show cost and tokens on runs page
samikuikka Aug 5, 2026
f93ee36
fix(pricing): account for current models and cache writes (#122)
samikuikka Aug 5, 2026
82c4a3e
fix(deploy): keep direct Caddy docs host valid
samikuikka Aug 5, 2026
ba1378f
docs(adapter): require truthful effort reporting
samikuikka Aug 5, 2026
1034429
fix(cli): issue the caller heartbeat from a worker thread (#124)
samik-bind Aug 5, 2026
ad58547
chore(cli): release 0.1.4
samikuikka Aug 5, 2026
60ca8ec
fix: bare model names fall through to generic, zeroing cache-creation…
samikuikka Aug 5, 2026
fdbaf26
fix: show per-check source snippet for table-driven evals + CLI trans…
samikuikka Aug 5, 2026
e849ab9
feat(SPEC-172): wire file artifact persistence into source-owned paths
samikuikka Aug 5, 2026
a5d4c63
feat(SPEC-172): artifact upload authorization + finalization fence
samikuikka Aug 5, 2026
34d194c
feat(SPEC-172): replay detection before deliverable persistence (step 7)
samikuikka Aug 5, 2026
0c4c9f1
test(SPEC-172): full protocol-v2 upload-to-download integration scene…
samikuikka Aug 5, 2026
b3f4f76
feat(SPEC-172): Task Run row-lock fence (step 5) + ready artifacts re…
samikuikka Aug 5, 2026
0062580
fix(SPEC-172): adversarial review fixes
samikuikka Aug 5, 2026
104b113
fix: adversarial review round 2 — path leaks + SIGKILL dead code
samikuikka Aug 5, 2026
f33c417
feat: file artifact docs, CLI deliverables discovery, --output . shor…
samikuikka Aug 5, 2026
0482240
chore(sdk): release 0.2.2
samikuikka Aug 5, 2026
302b2fb
chore(cli): release 0.1.5
samikuikka Aug 5, 2026
61c8bef
fix: valid failure_kind for caller path (#127) + show passing asserti…
samikuikka Aug 6, 2026
2c9136b
fix: flag malformed JSON payloads instead of silently wrapping as tex…
samikuikka Aug 7, 2026
ebc5617
feat(docs): add Public Alpha badge to header and landing page
samikuikka Aug 7, 2026
6929623
docs: specify self-hosted first-run cleanup
samikuikka Aug 7, 2026
169637a
test: expect markers for all passing assertions
samikuikka Aug 7, 2026
18ee1cb
fix: count cached prompt tokens in per-call and run token totals (#131)
samik-bind Aug 7, 2026
1293c86
fix: persist trace projection normalizer version
samikuikka Aug 7, 2026
c2b0598
docs: correct self-hosted SQLite database path
samikuikka Aug 7, 2026
2061226
fix: refresh completed trace aggregates after projection
samikuikka Aug 7, 2026
51fc334
perf: speed up dashboard — DB index + parallel SSR calls
samikuikka Aug 7, 2026
6c345d8
perf: make span/tab/search selection shallow — no server round-trip p…
samik-bind Aug 7, 2026
32ef301
perf: cut heavy payloads from list/preview endpoints
samikuikka Aug 7, 2026
a86707f
perf: load the task-run transcript lazily instead of fetching the ful…
samik-bind Aug 7, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
2 changes: 1 addition & 1 deletion .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ APO_PUBLIC_URL=
# e.g. 262144 pages ~= 1 GiB. Writes fail once the cap is hit.
#APO_MAX_DB_PAGES=0

# --- Task Run Deliverables / Artifacts (SPEC-140) ---
# --- Task Run Deliverables / Artifacts ---
#
# Deliverable metadata stays in the database; large JSON bodies and file
# Artifacts go through an ArtifactStore. The default `local` backend writes
Expand Down
39 changes: 25 additions & 14 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,28 +20,39 @@ jobs:
node-version: 22
cache: pnpm
- run: pnpm install --frozen-lockfile
- name: Build @apo/sdk
- name: Build @apo-ai/sdk
# The SDK's exports map points external consumers at dist/. Internal dev
# routes back to src/ via the `development` condition, but the build must
# still succeed for any external/publish path. This catches build breakage
# on every PR — previously no CI step built the SDK, which is how the
# broken `build: tsc` script survived unnoticed.
run: pnpm --filter @apo/sdk build
- name: Verify SDK dist entry points
# Belt-and-suspenders: assert each declared exports target actually
# exists on disk after the build.
run: |
for f in index.js index.d.ts otel/index.js otel/index.d.ts \
agent-task/public.js agent-task/public.d.ts \
agent-task/integrations/ai-sdk.js agent-task/integrations/ai-sdk.d.ts \
agent-task/integrations/openai.js agent-task/integrations/openai.d.ts \
agent-task/integrations/anthropic.js agent-task/integrations/anthropic.d.ts; do
test -f "packages/sdk/dist/$f" || { echo "MISSING dist/$f"; exit 1; }
done
echo "All SDK dist entry points present."
run: pnpm --filter @apo-ai/sdk build
- name: Clean consumer package gate (SDK)
# The single source of truth for the publish boundary: pack the SDK
# exactly as a registry release would, install it into a clean
# directory, import/compile every entry point, and run publint.
run: pnpm --filter @apo-ai/sdk package:check
- name: Build @apo-ai/cli
run: pnpm --filter @apo-ai/cli build
- name: Test @apo-ai/cli
# No job ran the CLI's unit suite, so guards on resolution and entry
# behaviour could only fail on a user's machine. Same selection the
# publish workflow uses (excludes the long connect scene test).
run: pnpm --filter @apo-ai/cli test:unit
- name: Clean consumer package gate (CLI)
run: pnpm --filter @apo-ai/cli package:check
- run: pnpm lint
- run: pnpm typecheck
- name: Test dashboard
run: pnpm --filter dashboard test
- name: Build docs + publication gate
# Builds the Astro site, publishes versioned schemas, and verifies the
# publication invariants (no retired origin, every start.md link
# resolves, Copy Prompt uses the live origin, schema $ids map).
run: pnpm --filter docs build
- run: pnpm test:public-ingress
- name: Public docs deployment contract
run: pnpm test:public-docs

backend:
name: Typecheck + Test (Backend)
Expand Down
99 changes: 99 additions & 0 deletions .github/workflows/publish-cli.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
name: Publish CLI

# Releases the @apo-ai/cli npm package. Parallel to publish-sdk.yml but
# triggered by `cli-v*` tags and using the `npm-cli-release` environment.
# Authentication is OIDC trusted publishing only — no stored npm token.
# Requires a separate trusted-publisher registration on the npm side for
# @apo-ai/cli (per-package, not per-org).

on:
push:
tags:
- "cli-v*"

permissions:
contents: read
id-token: write

jobs:
publish:
name: Publish @apo-ai/cli
runs-on: ubuntu-latest
environment: npm-cli-release
defaults:
run:
working-directory: packages/cli
steps:
- uses: actions/checkout@v4

- name: Setup pnpm
uses: pnpm/action-setup@v4
with:
version: 11.3.0

- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: 24
cache: pnpm
registry-url: https://registry.npmjs.org/

- name: Install npm (trusted-publishing-aware)
run: npm install -g npm@latest

- name: Install dependencies
working-directory: .
run: pnpm install --frozen-lockfile

- name: Verify tag matches package version
run: |
set -euo pipefail
PKG_VERSION=$(node -p "require('./package.json').version")
TAG_VERSION="${GITHUB_REF#refs/tags/cli-v}"
echo "package version: $PKG_VERSION"
echo "tag version: $TAG_VERSION"
if [ "$PKG_VERSION" != "$TAG_VERSION" ]; then
echo "::error::Tag cli-v$TAG_VERSION does not match packages/cli/package.json version $PKG_VERSION"
exit 1
fi

- name: CLI tests
run: pnpm --filter @apo-ai/cli test:unit

- name: CLI typecheck
run: pnpm --filter @apo-ai/cli typecheck

- name: Clean consumer package gate
run: pnpm --filter @apo-ai/cli package:check

- name: Build release tarball
working-directory: .
run: |
set -euo pipefail
rm -rf release
mkdir -p release
pnpm --filter @apo-ai/cli pack --pack-destination ./release
TARBALL_PATH="$(realpath release/*.tgz)"
echo "TARBALL_PATH=$TARBALL_PATH" >> "$GITHUB_ENV"
echo "Packed $TARBALL_PATH"

- name: Publish to npm (OIDC, no token)
env:
TARBALL: ${{ env.TARBALL_PATH }}
run: |
set -euo pipefail
npm publish --access public --provenance "$TARBALL"

- name: Report publication
if: success()
working-directory: .
run: |
PKG_VERSION=$(node -p "require('./packages/cli/package.json').version")
{
echo "## @apo-ai/cli published"
echo ""
echo "- **Package**: [\`@apo-ai/cli@${PKG_VERSION}\`](https://www.npmjs.com/package/@apo-ai/cli/v/${PKG_VERSION})"
echo "- **Tag**: \`$GITHUB_REF_NAME\`"
echo "- **Tarball**: \`${TARBALL_PATH}\`"
echo "- **Auth**: GitHub OIDC trusted publishing (no npm token secret)"
} >> "$GITHUB_STEP_SUMMARY"
115 changes: 115 additions & 0 deletions .github/workflows/publish-sdk.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
name: Publish SDK

# Releases the @apo-ai/sdk npm package. Decoupled from the Docker release
# workflow (.github/workflows/release.yml, triggered by `v*` tags): SDK
# versions follow their own cadence under `sdk-v*` tags.
#
# Authentication is OIDC trusted publishing only — no long-lived npm
# credential is stored as a GitHub secret. The trusted publisher
# (repo `samikuikka/apo`, workflow `publish-sdk.yml`, environment
# `npm-sdk-release`) must be configured once on the npm side by a
# maintainer with publishing rights to the `apo` scope.

on:
push:
tags:
- "sdk-v*"

permissions:
contents: read
id-token: write

jobs:
publish:
name: Publish @apo-ai/sdk
runs-on: ubuntu-latest
environment: npm-sdk-release
defaults:
run:
working-directory: packages/sdk
steps:
- uses: actions/checkout@v4

- name: Setup pnpm
uses: pnpm/action-setup@v4
with:
version: 11.3.0

- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: 24
cache: pnpm
registry-url: https://registry.npmjs.org/

- name: Install npm (trusted-publishing-aware)
# npm >=11.5.1 understands the OIDC exchange used by trusted publishing.
run: npm install -g npm@latest

- name: Install dependencies
working-directory: .
run: pnpm install --frozen-lockfile

- name: Verify tag matches package version
# The Git tag must be exactly `sdk-v<packages/sdk/package.json version>`.
# Any mismatch is a hard stop — we never publish a tarball whose
# reported version disagrees with the immutable tag.
run: |
set -euo pipefail
PKG_VERSION=$(node -p "require('./package.json').version")
TAG_VERSION="${GITHUB_REF#refs/tags/sdk-v}"
echo "package version: $PKG_VERSION"
echo "tag version: $TAG_VERSION"
if [ "$PKG_VERSION" != "$TAG_VERSION" ]; then
echo "::error::Tag sdk-v$TAG_VERSION does not match packages/sdk/package.json version $PKG_VERSION"
exit 1
fi

- name: SDK tests
run: pnpm --filter @apo-ai/sdk test

- name: SDK typecheck
run: pnpm --filter @apo-ai/sdk typecheck

- name: Clean consumer package gate
run: pnpm --filter @apo-ai/sdk package:check

- name: Build release tarball
# `pnpm pack` is the only correct artifact source — it applies the
# publishConfig rewrite (strips `development` conditions, locks the
# six dist-only exports). We pack into a fresh dir to guarantee no
# stale local tarball is reused. Do NOT capture pnpm's stdout into
# $GITHUB_ENV — it carries ANSI color codes that the file command
# rejects. Resolve the tarball path from disk instead.
working-directory: .
run: |
set -euo pipefail
rm -rf release
mkdir -p release
pnpm --filter @apo-ai/sdk pack --pack-destination ./release
TARBALL_PATH="$(realpath release/*.tgz)"
echo "TARBALL_PATH=$TARBALL_PATH" >> "$GITHUB_ENV"
echo "Packed $TARBALL_PATH"

- name: Publish to npm (OIDC, no token)
# Trusted publishing exchanges the GitHub OIDC JWT for short-lived
# npm credentials. There is no NODE_AUTH_TOKEN and no NPM_TOKEN.
env:
TARBALL: ${{ env.TARBALL_PATH }}
run: |
set -euo pipefail
npm publish --access public --provenance "$TARBALL"

- name: Report publication
if: success()
working-directory: .
run: |
PKG_VERSION=$(node -p "require('./packages/sdk/package.json').version")
{
echo "## @apo-ai/sdk published"
echo ""
echo "- **Package**: [\`@apo-ai/sdk@${PKG_VERSION}\`](https://www.npmjs.com/package/@apo-ai/sdk/v/${PKG_VERSION})"
echo "- **Tag**: \`$GITHUB_REF_NAME\`"
echo "- **Tarball**: \`${TARBALL_PATH}\`"
echo "- **Auth**: GitHub OIDC trusted publishing (no \`NPM_TOKEN\` secret)"
} >> "$GITHUB_STEP_SUMMARY"
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ CLAUDE.md
/.codex/
/.opencode/
/.ncode/
/.zcode/
/.agent-state/
/.personal/
/wayfinder/
Expand Down
Loading
Loading