Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
9ebffbf
feat(conversation): publish headless runtime protocol
AgentArcLab Aug 27, 2026
71ca1ff
feat(conversation): add headless streaming client
AgentArcLab Aug 27, 2026
1b51ae3
feat(conversation): make hosted UI surface first
AgentArcLab Aug 27, 2026
6c6bb55
docs(conversation): document shared surface contract
AgentArcLab Aug 27, 2026
e190c00
fix(conversation): require positive approval revision
AgentArcLab Aug 27, 2026
178a191
test(web): prove canonical hosted conversation e2e
AgentArcLab Aug 27, 2026
5bb9c59
test(conversation): prove canonical input consumers
AgentArcLab Aug 27, 2026
4f2ea01
chore(release): gate packed conversation artifacts
AgentArcLab Aug 27, 2026
afb2027
chore(release): prepare ksadk-web 0.3.3
AgentArcLab Aug 27, 2026
233da62
chore(release): attest ksadk-web 0.3.3 source
AgentArcLab Aug 27, 2026
fa91606
test(release): expect untagged 0.3.3 candidate
AgentArcLab Aug 27, 2026
34bb92d
chore(release): refresh ksadk-web 0.3.3 attestation
AgentArcLab Aug 27, 2026
9b1c2b3
fix(conversation): preserve ordered shared renderer identity
AgentArcLab Aug 30, 2026
db3f1a6
chore(release): refresh ksadk-web 0.3.3 attestation
AgentArcLab Aug 30, 2026
54517c6
fix(conversation): preserve summary compatibility
AgentArcLab Aug 30, 2026
b086cf0
chore(release): refresh ksadk-web 0.3.3 provenance
AgentArcLab Aug 30, 2026
331b453
fix(conversation): hide additive unknown items
AgentArcLab Aug 30, 2026
2a97409
test(conversation): cover hidden additive events
AgentArcLab Aug 30, 2026
fa0fcdd
chore(release): refresh ksadk-web 0.3.3 provenance
AgentArcLab Aug 30, 2026
8f6a91b
test(conversation): verify additive events stay hidden
AgentArcLab Aug 30, 2026
2292fbe
chore(release): refresh ksadk-web 0.3.3 provenance
AgentArcLab Aug 30, 2026
84d02ac
fix(web): keep provider controls in conversation extensions
AgentArcLab Aug 31, 2026
37eb8dd
test(web): align canonical approval extension
AgentArcLab Aug 31, 2026
85f0eba
chore(release): attest final ksadk-web 0.3.3 source
AgentArcLab Aug 31, 2026
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
6 changes: 2 additions & 4 deletions .github/workflows/publish-npm.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,8 @@ jobs:
- run: npm install -g npm@^11.5.1
- run: npm --version
- run: npm ci
- run: npm test
- run: node --test tests/*.test.mjs
- run: npm run build:all
- run: npm pack --dry-run --access public
- run: npx playwright install --with-deps chromium
- run: npm run release:preflight

- name: Check published version
id: published
Expand Down
38 changes: 38 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,43 @@
# Changelog

## 0.3.3 - 2026-08-28

### Headless conversation surface

- Add the Node/SSR-safe `@kingsoftcloud/ksadk-web/conversation` entrypoint with
strict ConversationSurface/Input/Item v1 decoders, input preflight, bounded
HTTP/SSE reconnect, passive renderer data, and the shared identity reducer.
- Route the bundled Hosted UI through the same conversation client and reducer
when a valid Surface is advertised. A Surface HTTP 404 keeps the existing
Responses / AG-UI / legacy path; malformed surfaces and server failures do
not silently bypass the declared contract.
- Preserve different item identities even when their text is equal, ignore
replayed `(itemId, sourceEventId)` pairs, keep terminal items monotonic, and
retain additive unknown item kinds for replay/audit without rendering a
repeated transcript card; newer schemas on known kinds safely downgrade to
one passive fallback card.
- Preserve the canonical item timeline for renderers: a separate native tool
result enriches its original `callId` tool card rather than rendering a
duplicate card, while reasoning, tools and answers keep their original
interleaving. Add an immutable exact `kind + payloadSchemaRef` trusted
renderer catalog; providers cannot supply executable UI code in event
payloads or claim a future schema version.
- Keep `output` and `reasoning` summaries as a compatibility view beside the
canonical timeline, so Studio can adopt the shared reducer without a second
text aggregation implementation during the 0.8.3 transition.
- Keep canonical approvals without a durable `revision` read-only. Consumers
must not guess a revision or submit them through the revision-CAS Interaction
API until the server supplies an authoritative value.
- Make attachment upload and model selection first-class canonical inputs in
Hosted UI. Unsupported inputs and oversized files fail before upload or turn
submission instead of silently degrading to legacy `RunAgent` behavior.
- Prove the headless entrypoint from a minimal independent consumer across two
turns, cursor reconnect, text/tool/approval/unknown-item rendering, and
revision-CAS approval submission.
- Add a repeatable release preflight that runs unit, Node contract, lint, all
production builds, canonical Conversation browser E2E, provenance checks,
npm packing, and a clean tarball-install public API smoke test.

## 0.3.2 - 2026-08-21

Release candidate for the durable Interaction/v1 web experience. This is the
Expand Down
81 changes: 77 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ package entrypoints under `dist-lib`.
The npm package exposes these stable entrypoints:

- `@kingsoftcloud/ksadk-web/components`
- `@kingsoftcloud/ksadk-web/conversation` (headless, Node/SSR-safe)
- `@kingsoftcloud/ksadk-web/runtime`
- `@kingsoftcloud/ksadk-web/capabilities`
- `@kingsoftcloud/ksadk-web/styles`
Expand All @@ -51,6 +52,57 @@ The npm package exposes these stable entrypoints:
Hosted UI should import the shared shell from the package and keep private
auth, routing, feature flags, Docker, nginx, and Helm logic in its own repo.

### Headless conversation client

`@kingsoftcloud/ksadk-web/conversation` provides strict
`ConversationSurface/Input/Item` decoders, the identity reducer, passive
renderer data, and a small HTTP/SSE reference client. It has no React or DOM
runtime dependency and can be imported by Node/SSR applications.

```ts
import {
HttpConversationClient,
buildConversationInput,
} from '@kingsoftcloud/ksadk-web/conversation'

const client = new HttpConversationClient()
const bootstrap = await client.getSurface('agent-id', 'session-id')
const result = await client.streamTurn({
bootstrap,
input: buildConversationInput({
inputId: 'input-id',
sessionId: 'session-id',
idempotencyKey: 'turn-id',
parts: [{ kind: 'text', text: 'Hello' }],
}),
onUpdate(snapshot) {
// Render snapshot.presentation. It is already reduced by canonical item
// identity and is safe to replace after a reconnect or replay.
renderConversation(snapshot.presentation)
},
})
```

The client submits a turn once and only reconnects through the canonical Run
event endpoint. `onUpdate` and the final result use the same reducer: equal text
from different item identities is retained, replayed `(itemId, sourceEventId)`
pairs are idempotent, and a terminal item never regresses. It does not accept
tokens, cookies, credential modes, or provider-specific request fields;
applications keep authentication at their same-origin server boundary or in
an injected transport.

The bundled Hosted UI uses this same client and reducer when the server returns
a valid `ConversationSurface`. HTTP 404 is the compatibility signal for the
existing Responses / AG-UI / legacy path. A declared but invalid or unavailable
surface fails closed, and unknown item kinds or schema versions render as
passive fallback cards rather than provider-specific UI.

Approval and structured-input items are actionable only when their canonical
payload carries the server's durable, non-negative `revision`. Without that
value the shared Hosted UI intentionally renders the item read-only: it never
guesses revision `0` or bypasses the Interaction API's revision-CAS contract.
Likewise, unknown payloads and unsafe artifact URIs remain passive content.

## Release Contract

Consumers should record the resolved KSADK Web package version and lockfile
Expand Down Expand Up @@ -89,12 +141,33 @@ Before creating a release or dispatching the workflow, verify the payload:

```bash
npm ci
npm test
node --test tests/*.test.mjs
npm run build:all
npm pack --dry-run --access public
npx playwright install chromium
npm run release:preflight
```

The preflight is intentionally stricter than a development build: it requires
a clean worktree, checks the frozen Git source recorded in
`RELEASE_PROVENANCE.json`, rejects content changes under an already tagged
version, runs the canonical Conversation browser flow, creates the real npm
tarball, installs it into a disposable consumer, and imports the public
`@kingsoftcloud/ksadk-web/conversation` API. During development only, use
`npm run release:preflight -- --allow-unreleased --allow-dirty` to rehearse the
same tests without claiming the current commit is a releasable source.

After the next version is set and all code is committed, freeze its provenance
from that clean commit before the final attestation commit:

```bash
npm run release:provenance -- generate
git add RELEASE_PROVENANCE.json
git commit -m "chore(release): attest ksadk-web source"
npm run release:preflight
```

The generator refuses dirty worktrees and versions whose `vX.Y.Z` tag already
exists. Never edit `source_commit` by hand or regenerate provenance for an
already published version.

The publish workflow checks whether `package.json`'s exact version is already
present on npm. Existing versions are skipped because npm packages are
immutable; publish a new patch version for any package-content change.
Expand Down
4 changes: 2 additions & 2 deletions RELEASE_PROVENANCE.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"schema_version": 1,
"package": "@kingsoftcloud/ksadk-web",
"version": "0.3.2",
"source_commit": "2136448e038b4d8c475fa20e4722252b1ddb2ebc",
"version": "0.3.3",
"source_commit": "37eb8dd6ae8c44ea4622d39f8c7ae9b13916a793",
"interaction_contract_digest": "47e1003e03d97abeba232cc3e03a14b9cbcf78b1109870ccd2ce371f073b6211"
}
11 changes: 11 additions & 0 deletions e2e/agui.spec.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,17 @@ function bootstrap() {
async function installFixture(page) {
const state = { approved: false, created: false, aguiBodies: [] };

// AG-UI is the intended transport in this fixture. Explicitly advertise
// canonical ConversationSurface absence so production fallback semantics
// are exercised instead of receiving Vite's index.html with HTTP 200.
await page.route('**/api/v1/agents/**/conversation-surface**', async (route) => {
await route.fulfill({
status: 404,
contentType: 'application/json',
body: JSON.stringify({ error: 'conversation surface unavailable in AG-UI fixture' }),
});
});

await page.route('**/agentengine/agui', async (route) => {
const body = route.request().postDataJSON();
state.aguiBodies.push(body);
Expand Down
Loading
Loading