/** * The `subagentchat` resource address must stay byte-compatible with the host's * own codec: `@deepseek-ai/dsh-client-ui-subagent` parses what we emit, so a * different query order or an unescaped child id would silently open the wrong * page (or none). */ import { describe, expect, it } from 'vitest' import { SUBAGENT_CHAT_ADDRESS, SUBAGENT_CHAT_KIND, subagentChatAddress, } from '../src/client/native/subagent-chat.ts' describe('subagentChatAddress', () => { it("emits the canonical form with parent and mode", () => { expect(subagentChatAddress({ parentSessionId: 'parent-1', childSessionId: 'child-2', mode: 'one-shot', })).toBe('dsh-resource://subagentchat/session/child-2?parent=parent-1&mode=one-shot') }) it('keeps a continuable mode verbatim', () => { expect(subagentChatAddress({ parentSessionId: 'p', childSessionId: 'c', mode: 'continuable', })).toContain('mode=continuable') }) it('percent-encodes a child id so the address stays one path segment', () => { const address = subagentChatAddress({ parentSessionId: 'p', childSessionId: 'child/with:odd chars', mode: 'one-shot', }) expect(address).toContain('/child%2Fwith%3Aodd%20chars?') }) it('never leaks the parent into the path (it is a routing query only)', () => { const address = subagentChatAddress({ parentSessionId: 'p secret', childSessionId: 'c', mode: 'one-shot', }) expect(address.split('?')[0]).toBe(`${SUBAGENT_CHAT_ADDRESS}c`) }) it('names the page kind the native Sidebar roots these pages under', () => { expect(SUBAGENT_CHAT_KIND).toBe('subagentchat') }) it('omits an unknown mode so the host treats it as "unknown" and skips the check', () => { // The degraded synthesized catalog guesses mode from `running`; a wrong // guess used to 401 the open (the controller compares address.mode against // the child's durable descriptor). An unrecognized mode must be dropped, // which the controller reads as `mode: "unknown"` and does not compare. const address = subagentChatAddress({ parentSessionId: 'p', childSessionId: 'c', mode: 'unknown' as never, }) expect(address).toBe('dsh-resource://subagentchat/session/c?parent=p') expect(address).not.toContain('mode=') }) it('still emits the mode when it is one of the two durable values', () => { expect(subagentChatAddress({ parentSessionId: 'p', childSessionId: 'c', mode: 'one-shot' })) .toContain('mode=one-shot') expect(subagentChatAddress({ parentSessionId: 'p', childSessionId: 'c', mode: 'continuable' })) .toContain('mode=continuable') }) })