Merge remote-tracking branch 'origin/master' into worktree/provider-routed-llm-adapters
# Conflicts: # docs/config-catalog.md # docs/cordis-catalog/events.md # docs/cordis-catalog/services.md # docs/core-data-structures/core.md # docs/event-producer-consumer.md # docs/persistence-catalog.md # examples/acp-agent/tests/snapshots/advanced-toolchain/session.1.jsonl # examples/acp-agent/tests/snapshots/advanced-toolchain/session.2.jsonl # examples/acp-agent/tests/snapshots/advanced-toolchain/session.jsonl # examples/acp-agent/tests/snapshots/both-mode-turn/session.jsonl # examples/acp-agent/tests/snapshots/hook-cc-pretool-ask/session.jsonl # examples/acp-agent/tests/snapshots/skill-load/session.jsonl # examples/acp-agent/tests/snapshots/text-turn/session.jsonl # examples/sandbox-acp-agent/cordis.yml # examples/sandbox-acp-agent/tests/snapshots/escalation-approved/session.jsonl # examples/sandbox-acp-agent/tests/snapshots/escalation-rejected/session.jsonl # examples/sandbox-acp-agent/tests/snapshots/mode-switching/session.jsonl # packages/compact/compact-basic/README.md # packages/compact/compact-basic/src/index.ts # packages/compact/compact-basic/tests/compact-basic.spec.ts # packages/core/agent-loop/README.md # packages/core/agent-loop/src/loop.ts # packages/core/agent-loop/tests/properties.spec.ts # packages/core/session/README.md # packages/core/session/src/types.ts # packages/core/session/tests/derived-cache.spec.ts # packages/llm/llm-deepseek/src/index.ts # packages/llm/llm-pi-ai/README.md # packages/llm/llm-pi-ai/src/adapter.ts # packages/llm/llm-pi-ai/src/convert.ts # packages/llm/llm-pi-ai/tests/adapter.spec.ts # packages/llm/llm/README.md # packages/llm/llm/src/call-config.ts # packages/llm/llm/src/index.ts # packages/ui/acp-agent/src/index.ts # packages/ui/acp/tests/harness.ts # packages/ui/jsonrpc/README.md # packages/ui/jsonrpc/src/server.ts # packages/ui/stdio-agent/README.md # packages/ui/stdio-agent/src/index.ts # python/sdk/README.i18n.yaml
This commit is contained in:
@@ -118,9 +118,6 @@ describe('Session', () => {
|
||||
const before = structuredClone(session.events)
|
||||
|
||||
// A misbehaving consumer tries to mutate the messages it was handed.
|
||||
// Derived messages are frozen shared projections (cloned once off the
|
||||
// log, then deep-frozen): every mutation attempt THROWS in strict mode —
|
||||
// isolation by unrepresentability, not by per-call cloning.
|
||||
const messages = session.deriveMessages()
|
||||
const userBlock = messages[0]!.content[0]!
|
||||
expect(() => { if (userBlock.type === 'text') userBlock.text = 'HACKED' }).toThrow(TypeError)
|
||||
@@ -169,11 +166,8 @@ describe('Session', () => {
|
||||
it('rejects a surface-eligible append with no surfaceOp marker (runtime guard for the union-widening loophole)', () => {
|
||||
const session = new Session(SessionId('s5b'))
|
||||
session.append('turn/start', { turn: 1, trigger: { kind: 'message', source: { kind: 'user' } } })
|
||||
// The typed overload makes surfaceOp mandatory only when the type argument is
|
||||
// a SPECIFIC SurfaceEventType literal. A caller iterating raw events widens it
|
||||
// to the SessionEventType union, where the conditional rest collapses to
|
||||
// optional — the exact shape `for (const e of log) append(e.type, e.data)`
|
||||
// produces. Reproduce that here and assert the runtime guard rejects it.
|
||||
// A widened SessionEventType bypasses the overload's conditional requirement,
|
||||
// so the runtime guard must still reject the missing surface marker.
|
||||
const widenedType = 'user/message' as SessionEventType
|
||||
expect(() => session.append(widenedType, { content: [{ type: 'text', text: 'hi' }], source: { kind: 'user' } }))
|
||||
.toThrow(/surface-eligible and requires a surfaceOp marker/)
|
||||
@@ -700,10 +694,8 @@ describe('SessionStore', () => {
|
||||
})
|
||||
|
||||
it('enter() rejects a stale prepared session whose id is already live (no overwrite)', async () => {
|
||||
// prepare()/enter() are public cross-package primitives that a caller may
|
||||
// separate with arbitrary work. A stale prepared session must NOT overwrite
|
||||
// a live store entry of the same id — its detach disposer would later delete
|
||||
// the REAL session, breaking the store-uniqueness invariant.
|
||||
// A stale prepared object must not replace the live same-id entry; its later
|
||||
// detach would otherwise remove the wrong session.
|
||||
const ctx = new Context()
|
||||
await ctx.plugin(SessionStore)
|
||||
const stale = ctx.sessions.prepare(SessionId('racy'))
|
||||
|
||||
Reference in New Issue
Block a user