Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 17 additions & 2 deletions .github/release-please-config.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
{
"$schema": "https://raw.githubusercontent.com/googleapis/release-please/main/schemas/config.json",
"bump-minor-pre-major": true,
"bump-patch-for-minor-pre-major": true,
"bump-patch-for-minor-pre-major": false,
"include-component-in-tag": false,
"include-v-in-tag": true,
"tag-separator": "-",
"packages": {
".": {
Expand All @@ -11,7 +12,21 @@
"changelog-path": "CHANGELOG.md",
"draft": false,
"prerelease": false,
"changelog-sections": [
"extra-files": [
"packages/api/src/lib/version.ts",
"packages/mcp/src/index.ts",
{
"type": "json",
"path": "packages/mcp/package.json",
"jsonpath": "$.version"
},
{
"type": "json",
"path": "packages/dashboard/package.json",
"jsonpath": "$.version"
}
],
"changelog-sections": [
{ "type": "feat", "section": "✨ Features" },
{ "type": "fix", "section": "🐛 Bug Fixes" },
{ "type": "perf", "section": "⚡ Performance" },
Expand Down
7 changes: 4 additions & 3 deletions .github/workflows/release-please.yml
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
name: Release Please

# release-please watches conventional commits landing on main and maintains a
# standing "chore(release): vX.Y.Z" PR plus the tracked CHANGELOG.md. Merging
# that PR tags the version and publishes a GitHub Release, which we then hand to
# release.yml (build artifacts + LLM-generated release notes).
# standing "chore(main): release X.Y.Z" PR plus CHANGELOG.md / version.txt.
# In 0.x, `feat` bumps MINOR and `fix` bumps PATCH. Merging that PR (human
# only — never auto-merge) tags vX.Y.Z and publishes a GitHub Release, which
# we then hand to release.yml (build artifacts + LLM-generated release notes).

on:
push:
Expand Down
4 changes: 3 additions & 1 deletion docs/api-reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -2139,9 +2139,11 @@ No authentication required.
**Response:** `200 OK`

```json
{ "name": "agentstate", "version": "0.1.0", "status": "ok" }
{ "name": "agentstate", "version": "0.1.4", "status": "ok" }
```

`version` is the product semver from [release-please](https://github.com/googleapis/release-please). In 0.x, `feat` commits bump the minor (0.1 → 0.2); `fix` bumps the patch. Tags (`vX.Y.Z`) are created when the standing `chore(main): release X.Y.Z` PR is merged.

## Remote MCP Server

```
Expand Down
2 changes: 1 addition & 1 deletion docs/knowledge/core-memory.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,4 @@ Durable notes for recurring maintenance. Keep this file small and update it inst
- **✅ RESOLVED 2026-06-15 — dashboard-management routes are now Clerk-authenticated (PR #132, merged).** `/api/v1/projects*` and `/api/v1/organizations*` were previously completely unauthenticated (anyone could list all projects, read tenants' data, mint/delete keys — confirmed live). Fixed with `clerkDashboardAuth` (fail-closed `@clerk/backend` `verifyToken`); `org_id` comes from the verified Clerk session.
- **✅ FIXED 2026-06-18 — removed the `/api/v/*` route scar + restored broken retention setting.** The `/api/v2/`→`/api/v1/` collapse had sed-mangled the dashboard-management mounts to `/api/v/projects*` and `/api/v/organizations*` (no version digit). The dashboard's `_retention-settings.tsx` still called `PATCH /v2/projects/:id` → `/api/v2/projects/:id` → **404** (silently broken retention in prod), while the only `PATCH /:id` handler sat orphaned at `/api/v/projects`. Converged everything on `/api/v1`: ported the retention `PATCH /:id` into `routes/projects.ts` (reusing `services/v2-projects.updateProject`), deleted the duplicate `routes/v2/projects/` router + its `/api/v/*` mounts/auth, repointed the dashboard to `/v1/projects/:id`, and added an authed regression test. NOTE: `services/v2-projects.ts` is now used only for `updateProject` — its other exports are dead; consider inlining/renaming in a follow-up. `CLERK_SECRET_KEY` is set on the Worker (`wrangler secret put`, persists across deploys — no GitHub Actions secret needed). **Verified live: unauthenticated → 401 across all dashboard-management routes; public routes (`/api`, `/llms.txt`) still 200; agent API-key routes intact.** The dashboard uses the matching live Clerk instance (`pk_live_Y2xlcmsuYWdlbnRzdGF0ZS5hcHAk`). NOTE: the `sk_live` secret was once pasted in chat during setup — rotate it in Clerk if that transcript exposure is a concern.
- **✅ DONE 2026-06-20 — finished the v2→v1 dead-code collapse (branch `claude/system-architecture-refactor-326foo`).** Removed everything the abandoned "API v2" effort left stranded (net −3.6k LOC, 17 files deleted, behavior unchanged, 327 tests green): the unmounted `routes/v2/{conversations,keys,analytics}` trees + the orphaned semantic-search plumbing (`services/embeddings.ts`, `SemanticSearch*`/`ContextRetrieval*` types in `packages/shared`, the AI provider's unused `generateEmbedding`); the duplicate `services/v2-projects.ts` (its one live function `updateProject` inlined into `services/projects.ts`, closing the prior follow-up note); the stale `*.skip.ts` suites; the fully-orphaned `services/analytics.ts` (the live dashboard analytics route computes inline — it never used that service); and orphaned helpers (`getCachedCount`, `parseIncludeParam`, `mapConversationToResponse`, `lib/deprecation.ts`). Flattened `routes/v2/` → `routes/` (states/leases/claims/capability-tokens/organizations are all `/api/v1/*`) and deleted its fiction README. Renamed `services/v2-conversations.ts` → `services/mcp-conversations.ts` (its only consumer is the MCP server). NOTE: two conversation services remain by design — `services/conversations.ts` (REST: fires the `conversation.created` webhook, composite-cursor pagination) vs `services/mcp-conversations.ts` (leaner, no webhook); merging would change MCP behavior, so it was left alone. NOTE: the `VECTORIZE_INDEX` binding (types.ts/wrangler.jsonc/deploy script) is now dead config but was left untouched — removing it is a deploy-infra change that can't be live-tested here.
- **Release Please fails with `Bad credentials`** on every main push: `release-please.yml` uses `secrets.DUYETBOT_GITHUB_TOKEN` which is unset/expired. Needs the user to set that GitHub secret. Not fixable without the token.
- Release Please uses `secrets.GITHUB_TOKEN` (the old `DUYETBOT_GITHUB_TOKEN` was expired). It maintains a standing `chore(main): release X.Y.Z` PR (`#242` lineage). **Never auto-merge that PR** — a human merge tags `vX.Y.Z` and publishes the GitHub Release. In 0.x, `bump-patch-for-minor-pre-major` is **false**, so `feat` bumps minor and `fix` bumps patch. Advertised version lives in `packages/api/src/lib/version.ts` (and `version.txt`); extra-files rewrite it on the release PR. `/api` and MCP `serverInfo` read that constant — do not hardcode `0.1.0`.
4 changes: 2 additions & 2 deletions packages/api/src/content/openapi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ export const OPENAPI_SPEC = `{
"openapi": "3.1.0",
"info": {
"title": "AgentState API",
"version": "0.1.0",
"version": "0.1.4",
"description": "Conversation history database-as-a-service for AI agents. Store, retrieve, and manage AI agent conversations via a simple REST API.",
"contact": {
"url": "https://github.com/duyet/agentstate"
Expand Down Expand Up @@ -396,7 +396,7 @@ export const OPENAPI_SPEC = `{
"required": ["name", "version", "status"],
"properties": {
"name": {"type": "string", "example": "agentstate"},
"version": {"type": "string", "example": "0.1.0"},
"version": {"type": "string", "example": "0.1.4"},
"status": {"type": "string", "example": "ok"}
}
}
Expand Down
11 changes: 9 additions & 2 deletions packages/api/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { OPENAPI_SPEC } from "./content/openapi";
import { AGENTS_MD, LLMS_TXT } from "./content/static";
import { resolveAllowedOrigin } from "./lib/cors";
import { errorResponse } from "./lib/helpers";
import { VERSION } from "./lib/version";
import { clerkDashboardAuth } from "./middleware/clerk-dashboard-auth";
import { dbMiddleware } from "./middleware/db";
import { requestIdMiddleware } from "./middleware/request-id";
Expand Down Expand Up @@ -91,7 +92,7 @@ app.get("/api", (c) => {
// stores this on a HIT (no Authorization header); SWR serves stale instantly
// while revalidating. See docs/knowledge/workers-cache.md.
c.header("Cache-Control", "public, max-age=60, stale-while-revalidate=300");
return c.json({ name: "agentstate", version: "0.1.0", status: "ok" });
return c.json({ name: "agentstate", version: VERSION, status: "ok" });
});

// ---------------------------------------------------------------------------
Expand All @@ -105,7 +106,13 @@ const STATIC_CACHE_CONTROL = "public, max-age=300, stale-while-revalidate=3600";

// The OpenAPI spec is static — parse it once at module load (Worker startup)
// instead of on every request, so cache misses/bypasses pay no re-parse cost.
const PARSED_OPENAPI_SPEC = JSON.parse(OPENAPI_SPEC);
const PARSED_OPENAPI_SPEC = (() => {
const spec = JSON.parse(OPENAPI_SPEC) as {
info: { version: string };
};
spec.info.version = VERSION;
return spec;
})();

app.get("/llms.txt", (c) => {
c.header("Cache-Control", STATIC_CACHE_CONTROL);
Expand Down
5 changes: 5 additions & 0 deletions packages/api/src/lib/version.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
/**
* Product semver. release-please rewrites this on each release PR.
* Do not bump by hand — merge the standing `chore(main): release X.Y.Z` PR.
*/
export const VERSION = "0.1.4"; // x-release-please-version
3 changes: 2 additions & 1 deletion packages/api/src/routes/mcp/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Hono } from "hono";
import { scopeSatisfies } from "../../lib/scopes";
import { VERSION } from "../../lib/version";
import { mcpAuth } from "../../middleware/mcp-auth";
import { rateLimitMiddleware } from "../../middleware/rate-limit";
import type { Bindings, Variables } from "../../types";
Expand All @@ -21,7 +22,7 @@ const PROTOCOL_VERSION = "2025-06-18";
// requested version only if it is one of these; otherwise we answer with our
// latest supported version, per the MCP spec.
const SUPPORTED_PROTOCOL_VERSIONS = new Set(["2025-06-18", "2025-03-26"]);
const SERVER_INFO = { name: "agentstate", version: "0.1.0" };
const SERVER_INFO = { name: "agentstate", version: VERSION };

// Origins allowed to call the MCP endpoint cross-site. Mirrors the global CORS
// allowlist in index.ts; same-origin requests (no Origin header) always pass.
Expand Down
3 changes: 2 additions & 1 deletion packages/api/test/health.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { SELF } from "cloudflare:test";
import { beforeAll, describe, expect, it } from "vitest";
import { VERSION } from "../src/lib/version";
import { applyMigrations, seedProject } from "./setup";

describe("GET /api", () => {
Expand All @@ -14,7 +15,7 @@ describe("GET /api", () => {

const body = await response.json<{ name: string; version: string; status: string }>();
expect(body.name).toBe("agentstate");
expect(body.version).toBe("0.1.0");
expect(body.version).toBe(VERSION);
expect(body.status).toBe("ok");
});
});
3 changes: 2 additions & 1 deletion packages/api/test/mcp.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { env, SELF } from "cloudflare:test";
import { beforeEach, describe, expect, it } from "vitest";
import { VERSION } from "../src/lib/version";
import { applyMigrations, authHeaders, seedProject, TEST_API_KEY } from "./setup";

// ---------------------------------------------------------------------------
Expand Down Expand Up @@ -56,7 +57,7 @@ describe("remote MCP server", () => {
params: { protocolVersion: "2025-06-18" },
});
expect(status).toBe(200);
expect(json.result.serverInfo).toEqual({ name: "agentstate", version: "0.1.0" });
expect(json.result.serverInfo).toEqual({ name: "agentstate", version: VERSION });
expect(json.result.protocolVersion).toBe("2025-06-18");
expect(json.result.capabilities).toHaveProperty("tools");
});
Expand Down
2 changes: 1 addition & 1 deletion packages/mcp/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@agentstate/mcp",
"version": "0.1.0",
"version": "0.1.4",
"description": "MCP server for AgentState — expose conversation history, state, leases, claims, and capability tokens as MCP tools",
"type": "module",
"bin": {
Expand Down
2 changes: 1 addition & 1 deletion packages/mcp/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ const claimEvidenceSchema = z.discriminatedUnion("kind", [
// ---------------------------------------------------------------------------

const server = new McpServer(
{ name: "agentstate", version: "0.1.0" },
{ name: "agentstate", version: "0.1.4" }, // x-release-please-version
{ capabilities: { tools: {} } },
);

Expand Down
1 change: 1 addition & 0 deletions version.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
0.1.4