diff --git a/CHANGELOG.md b/CHANGELOG.md index f5890147..d8adfde2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,41 @@ All notable changes to this project are documented in this file. Format follows For narrative release notes written for operators and product owners, see [RELEASE_NOTES.md](RELEASE_NOTES.md). +## [1.3.0] - 2026-07-10 + +Bedrock Mantle expansion and an API-key endpoint repair. Mantle models gain declarative per-model `apiMode` (Chat Completions vs Responses API) and `region` fields on Strands' `bedrock_mantle_config`, unlocking Responses-only models like `openai.gpt-5.x`; the API-key `POST /chat/api-converse` endpoint — broken in cloud since the BFF/runtime migrations — is relocated onto app-api and now serves the full model catalog including Mantle. Plus Memory Spaces and Scheduled Runs follow-ups. No breaking changes; a platform (CDK) deploy is required for two app-api IAM grants. + +### 🚀 Added + +- Per-model Mantle API mode + region: admin model records gain `apiMode` (`chat` | `responses`) selecting `OpenAIModel` vs `OpenAIResponsesModel`, and an optional `region` override driving both the Mantle endpoint host and SigV4 token region — Responses-only models (e.g. `openai.gpt-5.x`) now work, and a model can pin inference to its host region independent of where the app runs (#620) +- API-key `/chat/api-converse` now serves the full model catalog: `provider="mantle"` models route through a shared `build_mantle_model` builder (`apis/shared/models/mantle.py`, also used by the agent factory), whose Strands `.stream()` yields the same Converse-shaped events as the Bedrock path so SSE translation and cost accounting are shared (#621) +- The agent can read and keep a Memory Space's `MEMORY.md` index in sync via the reserved `MEMORY.md` slug on `memory_read` / `memory_write` (viewer+ read, editor+ write; the slug is reserved and can't become an ordinary entry) (#614) +- The scheduled-run form targets Agents (the Agent Designer primitive) instead of Assistants; the manual tool picker hides when an Agent is selected (its tool bindings replace `enabled_tools` at invocation), and "Run now" honors the selected Agent (#615) + +### ⚠️ Changed + +- Scheduled Runs are no longer gated by the `scheduled-runs` RBAC capability — only the `SCHEDULED_RUNS_ENABLED` kill switch remains (404 when off). The surface stays low-key (no nav entry, reachable by direct URL); runs still execute with the caller's own RBAC-allowed tools (#617) +- Mantle inference plumbing moved onto Strands' `bedrock_mantle_config` (the SDK owns the base URL, model-family base path, and bearer-token minting); `mantleEndpointPath` is deprecated (accepted-but-ignored, no stored record breaks) and removed from the admin UI. Gemma 4 is temporarily un-curated pending upstream `google.gemma-` family-prefix routing (#620) + +### 🐛 Fixed + +- API-key `POST /chat/api-converse` was broken in cloud: app-api proxied it to inference-api, whose AgentCore Runtime data plane only serves `/invocations` + `/ping` (`UnknownOperationException`). The handler is now a self-contained app-api route (validate key → RBAC → Bedrock converse → cost accounting) with no inference-api hop (#621) +- Settings API-key code snippets now resolve a relative `appApiUrl` against the current origin, targeting `/api/chat/api-converse` — the bare-origin URL missed CloudFront's `/api/*` backend routing and returned a 403 (#621) +- Regular users no longer hit a 403 "Access Denied" toast on page load — the sidenav's background schedules probe tripped the beta-cohort RBAC gate through the global error interceptor; the vestigial probe is also removed (#617) +- Memory Space entries with namespaced slugs (e.g. `people/brian-bolt`) no longer 404 on view/edit/delete — the entry routes use a `{slug:path}` converter so the embedded slash survives routing (#614) + +### 🏗️ Infrastructure + +- app-api task role: the Bedrock invoke statement gains `bedrock:InvokeModelWithResponseStream` plus all-region foundation-model and account-level inference-profile ARNs, and the project-scoped Mantle statement gains `bedrock-mantle:CreateInference` — both required by the relocated api-converse handler (#621) + +### 📦 Dependencies + +- Backend: `strands-agents` 1.40.0 → 1.47.0 (and the `[bidi]` extra), added `aws-bedrock-token-generator` 1.1.0 (#619) + +### 📚 Docs + +- Release workflow consolidated into a single auto-invoked "cutting a release" steering doc + skill, replacing the separate versioning and release-notes guides (#618) + ## [1.2.0] - 2026-07-09 Agent Designer completion. Finishes the run-time binding trio (skills join model + tools), makes the chat input honor an active agent's governed bindings, adds a live side-by-side editor preview and model-parameter governance, brings full knowledge-base management into the Designer, and flips the `/agents` API on by default. The Agent Designer nav stays admin-gated Preview; no breaking changes and no migration. diff --git a/README.md b/README.md index 2e954768..ff4ffab3 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ **An open-source, production-ready Generative AI platform for institutions** *Built by Boise State University, designed for everyone.* -[![Release](https://img.shields.io/badge/Release-v1.2.0-6366f1?style=flat&logo=github&logoColor=white)](RELEASE_NOTES.md) +[![Release](https://img.shields.io/badge/Release-v1.3.0-6366f1?style=flat&logo=github&logoColor=white)](RELEASE_NOTES.md) [![Nightly](https://github.com/Boise-State-Development/agentcore-public-stack/actions/workflows/nightly.yml/badge.svg)](https://github.com/Boise-State-Development/agentcore-public-stack/actions/workflows/nightly.yml) ![Python](https://img.shields.io/badge/Python-3.13+-3776AB?style=flat&logo=python&logoColor=white) @@ -296,7 +296,7 @@ agentcore-public-stack/ See [RELEASE_NOTES.md](RELEASE_NOTES.md) for the full changelog, including new features, bug fixes, platform upgrades, and deployment notes for each release. -**Current release:** v1.2.0 +**Current release:** v1.3.0 --- diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 5835e530..a3acebd1 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,3 +1,84 @@ +# Release Notes — v1.3.0 + +**Release Date:** July 10, 2026 +**Previous Release:** v1.2.0 (July 9, 2026) + +--- + +> 🏗️ **This release requires a platform (CDK) deploy** — two IAM grants on the app-api task role back the relocated API-key endpoint. No new AWS resources beyond IAM, no data migration, no breaking changes. Operators with Mantle Responses-only models (e.g. `openai.gpt-5.x`) should set `apiMode=responses` on those model records after deploy — see the Deployment notes. + +--- + +## Highlights + +v1.3.0 expands **Bedrock Mantle** support and repairs the **API-key chat endpoint** in cloud. Mantle model records gain two declarative per-model fields — `apiMode` (Chat Completions vs the Responses API) and an optional `region` override — built on Strands 1.47's `bedrock_mantle_config`, which unlocks Responses-only models like `openai.gpt-5.x` and lets a model pin inference to its host region. The API-key `POST /chat/api-converse` endpoint, broken in cloud since the BFF and AgentCore-Runtime migrations, now lives on app-api as a self-contained route and serves the **full model catalog** — Bedrock *and* Mantle — through one shared model builder. Smaller follow-ups: the agent can now read and maintain a Memory Space's `MEMORY.md` index, scheduled runs target Agents (and no longer 403 for regular users), and namespaced Memory Space entry slugs resolve correctly. + +## Bedrock Mantle — Responses API and per-model regions + +Some Mantle-hosted models only serve OpenAI's Responses API and reject Chat Completions — no endpoint-path knob could ever satisfy them. Admins can now declare, per model, which API a model speaks and which region hosts it. + +### Backend + +- **Strands-owned Mantle plumbing (#620).** The admin `mantle` provider now rides Strands' `bedrock_mantle_config`: the SDK owns the base URL, the model-family base path, and bearer-token minting (via the new `aws-bedrock-token-generator` dependency), replacing the hand-rolled inference plumbing. Two declarative per-model fields cover what the library can't infer: + - `apiMode` (`chat` | `responses`) — selects `OpenAIModel` vs `OpenAIResponsesModel`. The Responses API uses different native param names, so `to_mantle_config` selects a Responses-specific param map (`max_output_tokens`, nested `reasoning.effort`) by mode. + - `region` — optional override driving both the Mantle endpoint host and the SigV4 region the bearer token is signed for, so a model can pin inference to its host region (e.g. `gpt-5.x` in `us-east-1`) independent of where the app runs. +- The runtime fields (`mantle_api_mode` / `mantle_region`) thread through `model_config`, the agent factory, `base_agent`, the paused-turn snapshot, `stream_coordinator`, and the chat service/routes, so bound agents and resumed turns honor them end to end (#620). +- **`mantleEndpointPath` is deprecated** — accepted-but-ignored in the schema so no stored record breaks, and removed from the admin UI and runtime. Gemma 4 (`google.gemma-4-31b`) is temporarily un-curated: it needs the `/openai/v1` base path but the SDK only routes `openai.gpt-5.*` there; it returns once the `google.gemma-` family prefix lands upstream (#620). +- **Dependency step (#619):** `strands-agents` 1.40.0 → 1.47.0 (with the `[bidi]` extra) plus `aws-bedrock-token-generator` 1.1.0, resolver-confirmed against `strands-agents-tools` 0.5.2. Full backend suite green on the new pin. + +### Test Coverage + +Backend suite green at 2,342 tests on the refactor; frontend typecheck + manage-models specs green. + +## API keys work in cloud again — `/chat/api-converse` on app-api, full catalog + +The programmatic API-key endpoint was broken in every deployed environment: app-api proxied `POST /chat/api-converse` to inference-api, but inference-api now runs inside an AgentCore Runtime whose data plane only serves `POST /invocations` and `GET /ping` — every other path returns `UnknownOperationException` before reaching the container. It worked locally only because `localhost:8001` bypasses the runtime gateway. + +### Backend + +- **Self-contained app-api route (#621).** The handler moves onto app-api (validate key → RBAC → Bedrock converse → cost accounting), reaching Bedrock directly via the task role — no inference-api hop, no `INFERENCE_API_URL` dependency. The proxy, the dead inference-api route, and its DTOs are deleted; verified with an un-mocked smoke returning 200 for stream and non-stream. +- **Mantle models now work over API keys (#621).** The handler was Bedrock-only — `provider="mantle"` models 400'd. Mantle model construction (class-pick + `bedrock_mantle_config` + param maps) is extracted to `apis/shared/models/mantle.py` as `build_mantle_model`, shared by the agent factory and the API-key handler (app-api can't import `agents/`). The handler resolves the requested model's provider from the catalog and branches: Bedrock → boto3 converse (unchanged); Mantle → the shared builder's bare Strands `.stream()`, which yields the same Converse-shaped events — so SSE translation and usage/cost accounting are one code path, and cost records now carry the real provider. Unknown ids fail safe to the Bedrock path. Verified with live dev smokes: chat-mode Mantle and Responses-API Mantle (`openai.gpt-5.4`) both 200 (stream + non-stream). + +### Frontend + +- **API-key snippets point at the right URL (#621).** After the BFF refactor, CloudFront only routes `/api/*` to the backend; the generated curl/Python/JS examples emitted the bare origin, producing a CloudFront 403. The settings page now resolves a relative/empty `appApiUrl` against the current origin (`/api/chat/api-converse`), leaving local dev's absolute `http://localhost:8000` untouched. + +### Infrastructure + +- **app-api IAM (#621):** the Bedrock invoke statement gains `bedrock:InvokeModelWithResponseStream` and broadens to all-region foundation models plus the account-level inference-profile ARN (the catalog uses `us.*` cross-region profiles), mirroring inference-api's grant; and the project-scoped Mantle statement (previously browse-only `Get*`/`List*`) gains `bedrock-mantle:CreateInference`. + +## ✨ Improved + +- **Scheduled runs target Agents (#615).** The schedule form's target selector lists Agents (the Designer primitive superseding Assistants — same record, `agentId == assistantId`, so the wire field is unchanged). Because an Agent's tool bindings *replace* the run's `enabled_tools` at invocation, the manual tool picker now hides when an Agent is selected — it previously offered tools that would be silently discarded — and "Run now" actually targets the selected Agent (it previously ignored it). +- **The agent can maintain a Memory Space's index (#614).** `MEMORY.md` — the human-readable index hydrated into the agent's context each session — was write-only from the agent's perspective, so it could silently drift from the entries the agent writes. The reserved `MEMORY.md` slug (case-insensitive) now routes `memory_read` → `read_index` (viewer+) and `memory_write` → `update_index` (editor+), with the same readwrite-binding gate as entry writes. The slug is reserved; it can't become an ordinary entry. + +## ⚠️ Changed + +- **Scheduled Runs are un-gated from RBAC (#617).** The `scheduled-runs` capability check is dropped from the `/schedules` and `/runs/*` gates — only the `SCHEDULED_RUNS_ENABLED` kill switch remains (404 when off). This widens who can *reach* the surface, not what any caller can do: runs still execute with the caller's own RBAC-allowed tools. The feature stays deliberately low-key — no nav entry, reachable by direct URL. `apis/shared/rbac/capabilities.py` remains in place so re-gating is a two-line revert. + +## 🐛 Bug fixes + +- **Regular users saw a 403 "Access Denied" toast on page load (#617).** The sidenav ran a background `loadSchedules()` probe on every load; the beta-cohort RBAC gate 403'd it and the global error interceptor popped the toast before the service's graceful catch ran. Fixed by the un-gating above plus removing the vestigial probe (the template never rendered a schedules link). +- **Namespaced Memory Space entries 404'd (#614).** Entry slugs are namespaced with a slash (e.g. `people/brian-bolt`), but the entry routes declared a plain `{slug}` param whose converter stops at `/` — and Uvicorn percent-decodes `%2F` before routing, so view/edit/delete never matched. The GET/PUT/DELETE routes now use the `{slug:path}` converter. + +## 📦 Dependencies + +| Component | Package | From | To | +|---|---|---|---| +| Backend | `strands-agents` (+ `[bidi]`) | 1.40.0 | 1.47.0 | +| Backend | `aws-bedrock-token-generator` | — | 1.1.0 (new) | + +## 🚀 Deployment notes + +Deploy order: **platform (CDK) → backend → frontend.** + +- **Platform deploy is required** for the two app-api IAM grants (#621). Without them, the relocated `/chat/api-converse` AccessDenies on streaming/inference-profile Bedrock models and on all Mantle models. +- **Mantle model records:** after deploy, set `apiMode=responses` on any Responses-only Mantle model (e.g. `openai.gpt-5.4`) in the admin model manager — records default to `chat`. `mantleEndpointPath` is now ignored; no cleanup needed. Optionally set `region` on models whose host region differs from the app's. +- **Scheduled Runs** become reachable (by direct URL) to all users where `SCHEDULED_RUNS_ENABLED` is on; set it to `false` to turn the surface off entirely. +- No data migration and no breaking API changes. + +--- + # Release Notes — v1.2.0 **Release Date:** July 9, 2026 diff --git a/VERSION b/VERSION index 26aaba0e..f0bb29e7 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.2.0 +1.3.0 diff --git a/backend/pyproject.toml b/backend/pyproject.toml index 3eb90808..c4f49c4b 100644 --- a/backend/pyproject.toml +++ b/backend/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "agentcore-stack" -version = "1.2.0" +version = "1.3.0" requires-python = ">=3.10" description = "Multi-agent conversational AI system with AWS Bedrock AgentCore" readme = "README.md" diff --git a/backend/uv.lock b/backend/uv.lock index 37fd8278..98e74f01 100644 --- a/backend/uv.lock +++ b/backend/uv.lock @@ -12,7 +12,7 @@ resolution-markers = [ [[package]] name = "agentcore-stack" -version = "1.2.0" +version = "1.3.0" source = { editable = "." } dependencies = [ { name = "aiofiles" }, diff --git a/frontend/ai.client/package-lock.json b/frontend/ai.client/package-lock.json index 27023665..6a60694e 100644 --- a/frontend/ai.client/package-lock.json +++ b/frontend/ai.client/package-lock.json @@ -1,12 +1,12 @@ { "name": "ai.client", - "version": "1.2.0", + "version": "1.3.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "ai.client", - "version": "1.2.0", + "version": "1.3.0", "dependencies": { "@angular/cdk": "21.2.14", "@angular/common": "21.2.17", diff --git a/frontend/ai.client/package.json b/frontend/ai.client/package.json index b0474417..cebfc050 100644 --- a/frontend/ai.client/package.json +++ b/frontend/ai.client/package.json @@ -1,6 +1,6 @@ { "name": "ai.client", - "version": "1.2.0", + "version": "1.3.0", "scripts": { "ng": "ng", "start": "ng serve", diff --git a/infrastructure/package-lock.json b/infrastructure/package-lock.json index 9cca548e..a8446ecc 100644 --- a/infrastructure/package-lock.json +++ b/infrastructure/package-lock.json @@ -1,12 +1,12 @@ { "name": "infrastructure", - "version": "1.2.0", + "version": "1.3.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "infrastructure", - "version": "1.2.0", + "version": "1.3.0", "dependencies": { "aws-cdk-lib": "2.260.0", "constructs": "10.6.0" diff --git a/infrastructure/package.json b/infrastructure/package.json index 6a1c6a29..bf9ddf05 100644 --- a/infrastructure/package.json +++ b/infrastructure/package.json @@ -1,6 +1,6 @@ { "name": "infrastructure", - "version": "1.2.0", + "version": "1.3.0", "bin": { "infrastructure": "bin/infrastructure.js" },